[cdo] 01/01: upstream 1.7.1
Alastair McKinstry
mckinstry at moszumanska.debian.org
Thu Jun 9 07:45:33 UTC 2016
This is an automated email from the git hooks/post-receive script.
mckinstry pushed a commit to tag upstream/1.7.1
in repository cdo.
commit f305ea549d0b9f6ba132dfc5ad3a19e83a7527e4
Author: Alastair McKinstry <mckinstry at debian.org>
Date: Wed Apr 27 10:05:16 2016 +0100
upstream 1.7.1
---
ChangeLog | 99 +-
Makefile.am | 2 +-
Makefile.in | 4 +-
NEWS | 20 +
OPERATORS | 91 +-
cdo.spec | 2 +-
config/default | 54 +-
configure | 112 +-
configure.ac | 22 +-
contrib/Makefile.in | 2 +
contrib/cdoCompletion.bash | 800 +-
contrib/cdoCompletion.tcsh | 800 +-
contrib/cdoCompletion.zsh | 800 +-
doc/cdo.pdf | Bin 1414096 -> 2652027 bytes
doc/cdo_eca.pdf | Bin 213128 -> 213128 bytes
doc/cdo_magics.pdf | Bin 0 -> 829844 bytes
doc/cdo_refcard.pdf | Bin 91167 -> 91624 bytes
libcdi/ChangeLog | 37 +
libcdi/app/cdi.c | 18 +-
libcdi/app/createtable.c | 1 -
libcdi/app/printinfo.h | 16 +-
libcdi/configure | 249 +-
libcdi/configure.ac | 25 +-
libcdi/doc/cdi_cman.pdf | Bin 332635 -> 333778 bytes
libcdi/doc/cdi_fman.pdf | Bin 360969 -> 362370 bytes
libcdi/interfaces/cdi.hpp | 2 +-
libcdi/src/Makefile.am | 17 +-
libcdi/src/Makefile.in | 85 +-
libcdi/src/basetime.c | 1 -
libcdi/src/binary.c | 22 +-
libcdi/src/calendar.h | 9 +-
libcdi/src/cdf_read.c | 720 +
libcdi/src/cdf_write.c | 1272 +
libcdi/src/cdi.h | 36 +-
libcdi/src/cdi.inc | 38 +-
libcdi/src/cdiFortran.c | 11 +
libcdi/src/cdi_error.c | 2 +-
libcdi/src/cdi_int.c | 13 +-
libcdi/src/cdi_int.h | 51 +-
libcdi/src/cdi_util.c | 48 +
libcdi/src/cdi_uuid.h | 42 +
libcdi/src/cdilib.c | 35864 ++++++++++++-----------
libcdi/src/cdipio.inc | 2 +-
libcdi/src/cgribex.h | 15 +-
libcdi/src/cgribexlib.c | 2918 +-
libcdi/src/config.h.in | 3 +-
libcdi/src/create_uuid.h | 23 -
libcdi/src/dmemory.h | 8 +
libcdi/src/error.c | 8 +-
libcdi/src/error.h | 10 +-
libcdi/src/gaussgrid.h | 10 +-
libcdi/src/grb_read.c | 239 +
libcdi/src/grb_write.c | 257 +
libcdi/src/gribapi_utilities.c | 62 +-
libcdi/src/gribapi_utilities.h | 3 +-
libcdi/src/grid.c | 2075 +-
libcdi/src/grid.h | 72 +-
libcdi/src/ieglib.c | 14 +-
libcdi/src/institution.c | 2 +-
libcdi/src/iterator.c | 161 +-
libcdi/src/iterator_fallback.c | 133 +-
libcdi/src/iterator_fallback.h | 5 +-
libcdi/src/iterator_grib.c | 87 +-
libcdi/src/iterator_grib.h | 5 +-
libcdi/src/mo_cdi.f90 | 205 +-
libcdi/src/namespace.h | 2 +-
libcdi/src/pio_client.c | 10 +
libcdi/src/pio_mpi_fw_at_reblock.c | 3 +-
libcdi/src/pio_server.c | 40 +-
libcdi/src/pio_util.c | 44 -
libcdi/src/pio_util.h | 11 +-
libcdi/src/stream.c | 728 +-
libcdi/src/stream_cdf.c | 3958 +--
libcdi/src/stream_cdf.h | 12 +-
libcdi/src/stream_cgribex.c | 107 +-
libcdi/src/stream_cgribex.h | 6 +-
libcdi/src/stream_ext.c | 56 +-
libcdi/src/stream_fcommon.c | 5 +-
libcdi/src/stream_grb.c | 635 +-
libcdi/src/stream_grb.h | 20 +-
libcdi/src/stream_gribapi.c | 233 +-
libcdi/src/stream_gribapi.h | 6 +-
libcdi/src/stream_ieg.c | 133 +-
libcdi/src/stream_read.c | 357 +
libcdi/src/stream_record.c | 143 +-
libcdi/src/stream_srv.c | 130 +-
libcdi/src/stream_write.c | 431 +
libcdi/src/subtype.c | 134 +-
libcdi/src/table.c | 4 +-
libcdi/src/table.h | 355 +-
libcdi/src/taxis.c | 113 +-
libcdi/src/timebase.h | 8 +
libcdi/src/util.c | 16 +-
libcdi/src/varscan.c | 57 +-
libcdi/src/varscan.h | 6 +-
libcdi/src/vlist.c | 66 +-
libcdi/src/vlist.h | 14 +-
libcdi/src/vlist_var.c | 17 +-
libcdi/src/zaxis.c | 36 +-
libcdi/tables/gen_tableheaderfile.in | 22 +-
libcdi/tests/cksum_read.c | 4 +
libcdi/tests/cksum_write.c | 6 +-
libcdi/tests/deco2d_model.c | 38 +-
libcdi/tests/pio_write.c | 18 +-
libcdi/tests/pio_write.h | 2 +-
libcdi/tests/simple_model.c | 42 +-
libcdi/tests/test_resource_copy.c | 7 +-
m4/acx_options.m4 | 6 +-
src/Adisit.c | 16 +-
src/Afterburner.c | 87 +-
src/Arith.c | 13 +-
src/Arithc.c | 9 +-
src/Arithdays.c | 9 +-
src/Arithlat.c | 2 +-
src/CDIread.c | 26 +-
src/CDItest.c | 2 +-
src/CDIwrite.c | 20 +-
src/CMOR.c | 692 +-
src/Cat.c | 47 +-
src/CdoMagicsMapper.c | 166 +-
src/CdoMagicsMapper.h | 4 -
src/Change.c | 2 +-
src/Change_e5slm.c | 2 +-
src/Cloudlayer.c | 2 +-
src/Collgrid.c | 52 +-
src/Command.c | 2 +-
src/Comp.c | 2 +-
src/Compc.c | 2 +-
src/Complextorect.c | 4 +-
src/Cond.c | 2 +-
src/Cond2.c | 2 +-
src/Condc.c | 2 +-
src/Consecstat.c | 14 +-
src/Copy.c | 56 +-
src/Deltime.c | 4 +-
src/Derivepar.c | 2 +-
src/Detrend.c | 10 +-
src/Diff.c | 2 +-
src/Distgrid.c | 2 +-
src/Duplicate.c | 4 +-
src/EOFs.c | 2 +-
src/Echam5ini.c | 12 +-
src/Enlarge.c | 2 +-
src/Enlargegrid.c | 2 +-
src/Ensstat.c | 2 +-
src/Ensstat3.c | 2 +-
src/Ensval.c | 2 +-
src/Eof3d.c | 2 +-
src/Eofcoeff.c | 9 +-
src/Eofcoeff3d.c | 12 +-
src/Exprf.c | 604 +-
src/FC.c | 2 +-
src/Filedes.c | 47 +-
src/Fillmiss.c | 6 +-
src/Filter.c | 2 +-
src/Fldrms.c | 11 +-
src/Fldstat.c | 13 +-
src/Fldstat2.c | 6 +-
src/Fourier.c | 4 +-
src/Gengrid.c | 2 +-
src/Gradsdes.c | 15 +-
src/Gridboxstat.c | 12 +-
src/Gridcell.c | 74 +-
src/Gridsearch.c | 2 +-
src/Harmonic.c | 2 +-
src/Hi.c | 14 +-
src/Histogram.c | 2 +-
src/Importamsr.c | 2 +-
src/Importbinary.c | 2 +-
src/Importcmsaf.c | 2 +-
src/Importobs.c | 2 +-
src/Info.c | 2 +-
src/Input.c | 2 +-
src/Intgrid.c | 2 +-
src/Intgridtraj.c | 2 +-
src/Intlevel.c | 2 +-
src/Intlevel3d.c | 2 +-
src/Intntime.c | 2 +-
src/Inttime.c | 2 +-
src/Intyear.c | 2 +-
src/Invert.c | 68 +-
src/Invertlev.c | 2 +-
src/Isosurface.c | 2 +-
src/Kvl.c | 2 +-
src/Log.c | 2 +-
src/Maggraph.c | 386 +-
src/Magplot.c | 910 +-
src/Magvector.c | 323 +-
src/Makefile.am | 12 +-
src/Makefile.in | 311 +-
src/Maskbox.c | 2 +-
src/Mastrfu.c | 2 +-
src/Math.c | 4 +-
src/Merge.c | 2 +-
src/Mergegrid.c | 2 +-
src/Mergetime.c | 17 +-
src/Merstat.c | 13 +-
src/Monarith.c | 20 +-
src/Mrotuv.c | 2 +-
src/Mrotuvb.c | 2 +-
src/Ninfo.c | 2 +-
src/Nmltest.c | 2 +-
src/Output.c | 2 +-
src/Outputgmt.c | 902 +-
src/Pack.c | 2 +-
src/{Vardup.c => Pardup.c} | 8 +-
src/Pinfo.c | 2 +-
src/Pressure.c | 2 +-
src/Regres.c | 18 +-
src/Remap.c | 4 +-
src/Remapeta.c | 9 +-
src/Replace.c | 2 +-
src/Replacevalues.c | 2 +-
src/Rhopot.c | 16 +-
src/Rotuv.c | 2 +-
src/Runstat.c | 8 +-
src/Seascount.c | 6 +-
src/Seasstat.c | 17 +-
src/Selbox.c | 2 +-
src/Select.c | 470 +-
src/Seloperator.c | 2 +-
src/Selrec.c | 6 +-
src/Seltime.c | 124 +-
src/Selvar.c | 35 +-
src/Set.c | 2 +-
src/Setbox.c | 2 +-
src/Setgatt.c | 2 +-
src/Setgrid.c | 2 +-
src/Sethalo.c | 2 +-
src/Setmiss.c | 2 +-
src/Setpartab.c | 66 +-
src/Setrcaname.c | 2 +-
src/Settime.c | 16 +-
src/Setzaxis.c | 2 +-
src/Showinfo.c | 2 +-
src/Sinfo.c | 9 +-
src/Smooth9.c | 2 +-
src/Sort.c | 2 +-
src/Sorttimestamp.c | 2 +-
src/Specinfo.c | 2 +-
src/Spectral.c | 2 +-
src/Spectrum.c | 2 +-
src/Split.c | 2 +-
src/Splitrec.c | 2 +-
src/Splitsel.c | 9 +-
src/Splittime.c | 2 +-
src/Splityear.c | 2 +-
src/StringUtilities.c | 85 +-
src/StringUtilities.h | 7 +-
src/Subtrend.c | 4 +-
src/Tee.c | 2 +-
src/Templates.c | 51 +-
src/Test.c | 2 +-
src/Tests.c | 2 +-
src/Timcount.c | 6 +-
src/Timedt.c | 121 +
src/Timselstat.c | 15 +-
src/Timsort.c | 2 +-
src/Timstat.c | 349 +-
src/Timstat2.c | 32 +-
src/Timstat3.c | 45 +-
src/Tinfo.c | 3 +-
src/Tocomplex.c | 4 +-
src/Transpose.c | 2 +-
src/Trend.c | 18 +-
src/Trms.c | 10 +-
src/Tstepcount.c | 2 +-
src/Vargen.c | 4 +-
src/Varrms.c | 2 +-
src/Verifygrid.c | 1188 +
src/Vertcum.c | 4 +-
src/Vertintap.c | 2 +-
src/Vertintml.c | 2 +-
src/Vertstat.c | 19 +-
src/Vertwind.c | 2 +-
src/Wct.c | 13 +-
src/Wind.c | 4 +-
src/Writegrid.c | 2 +-
src/Writerandom.c | 4 +-
src/XTimstat.c | 440 +-
src/YAR.c | 2 +-
src/Ydayarith.c | 131 +-
src/Ydaypctl.c | 65 +-
src/Ydaystat.c | 65 +-
src/Ydrunpctl.c | 17 +-
src/Ydrunstat.c | 9 +-
src/Yearmonstat.c | 10 +-
src/Yhourarith.c | 18 +-
src/Yhourstat.c | 18 +-
src/Ymonarith.c | 20 +-
src/Ymonpctl.c | 59 +-
src/Ymonstat.c | 18 +-
src/Yseaspctl.c | 9 +-
src/Yseasstat.c | 17 +-
src/Zonstat.c | 12 +-
src/after_sptrans.c | 6 +
{libcdi/src => src}/calendar.h | 9 +-
src/cdi_uuid.h | 42 +
src/cdo.c | 197 +-
src/cdo.h | 2 +-
src/cdo_getopt.c | 2 +-
src/cdo_getopt.h | 2 +-
src/cdo_history.c | 11 +-
src/cdo_int.h | 26 +-
src/cdo_pthread.c | 2 +-
src/cdo_vlist.c | 54 +-
src/commandline.c | 2 +-
src/compare.h | 2 +-
src/config.h.in | 15 +
src/dmemory.h | 17 +-
src/ecacore.c | 27 +-
src/error.h | 49 +
src/exception.c | 41 +-
src/expr.c | 1739 +-
src/expr.h | 183 +-
src/expr_fun.c | 76 +
src/{cdo.h => expr_fun.h} | 12 +-
src/expr_lex.c | 385 +-
src/expr_yacc.c | 527 +-
src/expr_yacc.h | 42 +-
src/features.c | 3 +
src/field.c | 260 +-
src/field.h | 90 +-
src/field2.c | 881 +-
src/fieldc.c | 10 +-
src/fieldmem.c | 32 +-
src/fieldmer.c | 8 +-
src/fieldzon.c | 8 +-
src/grid.c | 193 +-
src/grid.h | 4 -
src/grid_area.c | 62 +-
src/grid_search.c | 45 +-
src/grid_search.h | 2 +-
src/griddes.c | 10 +-
src/griddes_nc.c | 50 +-
src/gridreference.c | 2 +-
src/institution.c | 2 +-
src/juldate.c | 7 +-
src/kdtreelib/kdtree.h | 119 +-
src/kdtreelib/kdtree_cartesian.c | 72 +-
src/kdtreelib/kdtree_common.c | 65 +-
src/kdtreelib/kdtree_spherical.c | 70 +-
src/kvlist.c | 2 +-
src/kvlist.h | 2 +-
src/list.c | 2 +-
src/list.h | 2 +-
src/magics_template_parser.c | 84 +-
src/magics_template_parser.h | 13 +-
src/modules.c | 776 +-
src/modules.h | 3 +-
src/namelist.c | 2 +-
src/namelist.h | 2 +-
src/operator_help.h | 541 +-
src/pipe.c | 2 +-
src/pipe.h | 2 +-
src/printinfo.h | 24 +-
src/process.c | 7 +-
src/process.h | 2 +-
src/pstream.c | 73 +-
src/pstream.h | 6 +-
src/pstream_int.h | 2 +-
src/pstream_write.h | 2 +-
src/readline.c | 2 +-
src/remap.h | 3 +
src/remap_conserv.c | 623 +-
src/remap_conserv_scrip.c | 22 +-
src/remap_distwgt.c | 6 +-
src/remap_scrip_io.c | 160 +-
src/remaplib.c | 25 +
src/results_template_parser.c | 64 +-
src/results_template_parser.h | 9 +-
src/table.c | 2 +-
src/template_parser.c | 203 +-
src/template_parser.h | 18 +-
src/timebase.h | 18 +
src/timer.c | 2 +-
src/util.c | 42 +-
src/util.h | 5 +-
src/zaxis.c | 2 +-
test/{Copy_netcdf.test.in => Collgrid.test.in} | 24 +-
test/Copy_netcdf.test.in | 6 +-
test/Expr.test.in | 64 +
test/Makefile.am | 5 +-
test/Makefile.in | 21 +-
test/data/Makefile.am | 7 +-
test/data/Makefile.in | 9 +-
test/data/aexpr1_ref | Bin 0 -> 16800 bytes
test/data/aexpr2_ref | Bin 0 -> 16800 bytes
test/data/datac.nc | Bin 0 -> 7012 bytes
test/data/datag.nc | Bin 0 -> 704 bytes
test/data/datar.nc | Bin 0 -> 1156 bytes
test/data/datau.nc | Bin 0 -> 6884 bytes
test/data/expr1_ref | Bin 0 -> 6720 bytes
test/data/expr2_ref | Bin 0 -> 6720 bytes
test/data/grib_testfile01_sinfo_ref | 2 +-
test/data/grib_testfile02_sinfo_ref | 2 +-
test/data/netcdf_testfile01_sinfon_ref | 4 +-
test/data/netcdf_testfile02_sinfon_ref | 4 +-
test/data/thread1_ref | Bin 0 -> 312 bytes
test/threads.test.in | 55 +
400 files changed, 38438 insertions(+), 34667 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5f3e60d..239359e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,100 @@
+2016-02-25 Uwe Schulzweida
+
+ * using CDI library version 1.7.1
+ * Version 1.7.1 released
+
+2016-02-26 Uwe Schulzweida
+
+ * cat: skip time constant fields for nfile>1 (bug fix) [report: Ralf M�ller]
+ * copy: skip time constant fields for nfile>1 (bug fix)
+ * mergetime: skip time constant fields for nfile>1 (bug fix)
+ * select: skip time constant fields for nfile>1 (bug fix)
+ * select: search key timestep doesn't work with nfiles>1 (bug fix)
+
+2016-02-22 Uwe Schulzweida
+
+ * settaxis: set default increment to 1hour
+
+2016-02-08 Uwe Schulzweida
+
+ * expr: added support for function clon(), clat() and clev()
+
+2016-02-04 Uwe Schulzweida
+
+ * selmon: renamed to selmonth
+ * selseas: renamed to selseason
+
+2016-02-03 Uwe Schulzweida
+
+ * select: added search key season to select seasons
+ * selseas: added support for season ANN
+
+2016-01-13 Uwe Schulzweida
+
+ * Expr: added support for temporary variables (starting with underscore)
+
+2016-01-11 Uwe Schulzweida
+
+ * grfill: removed unused plot parameter: resolution
+
+2016-01-08 Uwe Schulzweida
+
+ * ydaypctl: check of verification date failed (bug fix)
+
+2016-01-07 Uwe Schulzweida
+
+ * setpartab: added support to combine setpartab operators (bug fix) [report: Karl-Hermann Wieners]
+
+2016-01-06 Uwe Schulzweida
+
+ * genbil: generate weight file also for num_links=0
+
+2016-01-05 Uwe Schulzweida
+
+ * Select: added search key steptype
+
+2016-01-04 Uwe Schulzweida
+
+ * select/delete: added full support for time constant fields (bug fix) [report: Ralf M�ller]
+ * delete: don't abort if variables are available (bug fix) [report: Renate Brokopf]
+
+2015-12-28 Uwe Schulzweida
+
+ * Exprf: init nmiss (bug fix)
+
+2015-12-15 Uwe Schulzweida
+
+ * after: added optional parameter to read VCT from file
+
+2015-12-14 Uwe Schulzweida
+
+ * grfill: changed contour_shade_technique from cell_shading to grid_shading
+
+2015-12-10 Uwe Schulzweida
+
+ * Select: added search key gridnum and gridname
+ * Select: added search key zaxisnum and zaxisname
+
+2015-11-26 Uwe Schulzweida
+
+ * Timstat: added frequency attribute for day, mon and year
+
+2015-11-25 Uwe Schulzweida
+
+ * selname: select also ps for variables on hybrid sigma pressure levels
+
+2015-11-18 Modali Kameswarrao
+
+ * Magplot: added support for projections and regions
+
+2015-11-16 Uwe Schulzweida
+
+ * seldate: stop reading if data date is greater than end date
+
+2015-11-16 Uwe Schulzweida
+
+ * timcor: set data range -1 to 1
+
2015-10-28 Uwe Schulzweida
* using CDI library version 1.7.0
@@ -526,7 +623,7 @@
2014-06-19 Uwe Schulzweida
- * Filter: disable zero-padding
+ * Filter (operator: highpass,lowpass,bandpass): disable zero-padding
* Detrend: added test
* added option --use_fftw: used in module filter
diff --git a/Makefile.am b/Makefile.am
index d55fc98..df6b08d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# Process this file with automake to produce Makefile.in
SUBDIRS = libcdi src contrib test/data test
#
-EXTRA_DIST=config/default OPERATORS doc/cdo.pdf doc/cdo_eca.pdf doc/cdo_refcard.pdf cdo.spec README
+EXTRA_DIST=config/default OPERATORS doc/cdo.pdf doc/cdo_eca.pdf doc/cdo_magics.pdf doc/cdo_refcard.pdf cdo.spec README
#
ACLOCAL_AMFLAGS = -I m4
#
diff --git a/Makefile.in b/Makefile.in
index d637110..a0347df 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -239,6 +239,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_CDI_LIB = @ENABLE_CDI_LIB@
ENABLE_CGRIBEX = @ENABLE_CGRIBEX@
+ENABLE_CXX = @ENABLE_CXX@
ENABLE_DATA = @ENABLE_DATA@
ENABLE_EXTRA = @ENABLE_EXTRA@
ENABLE_GRIB = @ENABLE_GRIB@
@@ -249,6 +250,7 @@ ENABLE_NC4 = @ENABLE_NC4@
ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
ENABLE_NETCDF = @ENABLE_NETCDF@
ENABLE_SERVICE = @ENABLE_SERVICE@
+ENABLE_THREADS = @ENABLE_THREADS@
EXEEXT = @EXEEXT@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
@@ -379,7 +381,7 @@ top_srcdir = @top_srcdir@
# Process this file with automake to produce Makefile.in
SUBDIRS = libcdi src contrib test/data test
#
-EXTRA_DIST = config/default OPERATORS doc/cdo.pdf doc/cdo_eca.pdf doc/cdo_refcard.pdf cdo.spec README
+EXTRA_DIST = config/default OPERATORS doc/cdo.pdf doc/cdo_eca.pdf doc/cdo_magics.pdf doc/cdo_refcard.pdf cdo.spec README
#
ACLOCAL_AMFLAGS = -I m4
#
diff --git a/NEWS b/NEWS
index d864dda..3bd9eb9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,26 @@
CDO NEWS
--------
+Version 1.7.1 (25 February 2016):
+
+ New features:
+ * select: added search key steptype, gridnum, gridname, zaxisnum, zaxisname
+ * expr, exprf, aexpr, aexprf: added support for function clon(x), clat(x), clev(x),
+ remove(x), ngp(x), nlev(x), size(x), missval(x), sellevel(x,k), sellevidx(x,k),
+ fldmin(x), fldmax(x), fldsum(x), fldmean(x), fldavg(x), fldstd(x), fldstd1(x), fldvar(x), fldvar1(x),
+ vertmin(x), vertmax(x), vertsum(x), vertmean(x), vertavg(x), vertstd(x), vertstd1(x), vertvar(x), vertvar1(x)
+ New operators:
+ * contour: Contour plot
+ * shaded: Shaded contour plot
+ * grfill: Shaded gridfill plot
+ * gmtxyz: Output GMT xyz format to create contour plots with the GMT module pscontour.
+ * gmtcells: Output GMT multiple segment format to create shaded gridfill plots with psxy.
+ Fixed bugs:
+ * cdo -t table_file does not read variable name from table file [Bug #6312]
+ * One day shift backwards when converting to relative time axis with -r [Bug #6496]
+ * ydaypctl: check of verification date failed (bug fix)
+ * cat, copy, mergetime, select: remove time constant input fields for nfile>1 [Bug #6552]
+
Version 1.7.0 (28 October 2015):
New features:
diff --git a/OPERATORS b/OPERATORS
index e6a283e..11a5dd5 100644
--- a/OPERATORS
+++ b/OPERATORS
@@ -84,9 +84,9 @@ Operator catalog:
Seltime seltime Select times
Seltime selhour Select hours
Seltime selday Select days
- Seltime selmon Select months
+ Seltime selmonth Select months
Seltime selyear Select years
- Seltime selseas Select seasons
+ Seltime selseason Select seasons
Seltime seldate Select dates
Seltime selsmon Select single month
Selbox sellonlatbox Select a longitude/latitude box
@@ -186,6 +186,7 @@ Operator catalog:
Math tan Tangent
Math asin Arc sine
Math acos Arc cosine
+ Math atan Arc tangent
Math reci Reciprocal value
Arithc addc Add a constant
Arithc subc Subtract a constant
@@ -233,9 +234,9 @@ Operator catalog:
Ensstat ensmean Ensemble mean
Ensstat ensavg Ensemble average
Ensstat ensstd Ensemble standard deviation
- Ensstat ensstd1 Ensemble standard deviation
+ Ensstat ensstd1 Ensemble standard deviation (n-1)
Ensstat ensvar Ensemble variance
- Ensstat ensvar1 Ensemble variance
+ Ensstat ensvar1 Ensemble variance (n-1)
Ensstat enspctl Ensemble percentiles
Ensstat2 ensrkhistspace Ranked Histogram averaged over time
Ensstat2 ensrkhisttime Ranked Histogram averaged over space
@@ -248,9 +249,9 @@ Operator catalog:
Fldstat fldmean Field mean
Fldstat fldavg Field average
Fldstat fldstd Field standard deviation
- Fldstat fldstd1 Field standard deviation
+ Fldstat fldstd1 Field standard deviation (n-1)
Fldstat fldvar Field variance
- Fldstat fldvar1 Field variance
+ Fldstat fldvar1 Field variance (n-1)
Fldstat fldpctl Field percentiles
Zonstat zonmin Zonal minimum
Zonstat zonmax Zonal maximum
@@ -258,9 +259,9 @@ Operator catalog:
Zonstat zonmean Zonal mean
Zonstat zonavg Zonal average
Zonstat zonstd Zonal standard deviation
- Zonstat zonstd1 Zonal standard deviation
+ Zonstat zonstd1 Zonal standard deviation (n-1)
Zonstat zonvar Zonal variance
- Zonstat zonvar1 Zonal variance
+ Zonstat zonvar1 Zonal variance (n-1)
Zonstat zonpctl Zonal percentiles
Merstat mermin Meridional minimum
Merstat mermax Meridional maximum
@@ -268,9 +269,9 @@ Operator catalog:
Merstat mermean Meridional mean
Merstat meravg Meridional average
Merstat merstd Meridional standard deviation
- Merstat merstd1 Meridional standard deviation
+ Merstat merstd1 Meridional standard deviation (n-1)
Merstat mervar Meridional variance
- Merstat mervar1 Meridional variance
+ Merstat mervar1 Meridional variance (n-1)
Merstat merpctl Meridional percentiles
Gridboxstat gridboxmin Gridbox minimum
Gridboxstat gridboxmax Gridbox maximum
@@ -278,27 +279,27 @@ Operator catalog:
Gridboxstat gridboxmean Gridbox mean
Gridboxstat gridboxavg Gridbox average
Gridboxstat gridboxstd Gridbox standard deviation
- Gridboxstat gridboxstd1 Gridbox standard deviation
+ Gridboxstat gridboxstd1 Gridbox standard deviation (n-1)
Gridboxstat gridboxvar Gridbox variance
- Gridboxstat gridboxvar1 Gridbox variance
+ Gridboxstat gridboxvar1 Gridbox variance (n-1)
Vertstat vertmin Vertical minimum
Vertstat vertmax Vertical maximum
Vertstat vertsum Vertical sum
Vertstat vertmean Vertical mean
Vertstat vertavg Vertical average
Vertstat vertstd Vertical standard deviation
- Vertstat vertstd1 Vertical standard deviation
+ Vertstat vertstd1 Vertical standard deviation (n-1)
Vertstat vertvar Vertical variance
- Vertstat vertvar1 Vertical variance
+ Vertstat vertvar1 Vertical variance (n-1)
Timselstat timselmin Time range minimum
Timselstat timselmax Time range maximum
Timselstat timselsum Time range sum
Timselstat timselmean Time range mean
Timselstat timselavg Time range average
Timselstat timselstd Time range standard deviation
- Timselstat timselstd1 Time range standard deviation
+ Timselstat timselstd1 Time range standard deviation (n-1)
Timselstat timselvar Time range variance
- Timselstat timselvar1 Time range variance
+ Timselstat timselvar1 Time range variance (n-1)
Timselpctl timselpctl Time range percentiles
Runstat runmin Running minimum
Runstat runmax Running maximum
@@ -306,9 +307,9 @@ Operator catalog:
Runstat runmean Running mean
Runstat runavg Running average
Runstat runstd Running standard deviation
- Runstat runstd1 Running standard deviation
+ Runstat runstd1 Running standard deviation (n-1)
Runstat runvar Running variance
- Runstat runvar1 Running variance
+ Runstat runvar1 Running variance (n-1)
Runpctl runpctl Running percentiles
Timstat timmin Time minimum
Timstat timmax Time maximum
@@ -316,9 +317,9 @@ Operator catalog:
Timstat timmean Time mean
Timstat timavg Time average
Timstat timstd Time standard deviation
- Timstat timstd1 Time standard deviation
+ Timstat timstd1 Time standard deviation (n-1)
Timstat timvar Time variance
- Timstat timvar1 Time variance
+ Timstat timvar1 Time variance (n-1)
Timpctl timpctl Time percentiles
Hourstat hourmin Hourly minimum
Hourstat hourmax Hourly maximum
@@ -326,9 +327,9 @@ Operator catalog:
Hourstat hourmean Hourly mean
Hourstat houravg Hourly average
Hourstat hourstd Hourly standard deviation
- Hourstat hourstd1 Hourly standard deviation
+ Hourstat hourstd1 Hourly standard deviation (n-1)
Hourstat hourvar Hourly variance
- Hourstat hourvar1 Hourly variance
+ Hourstat hourvar1 Hourly variance (n-1)
Hourpctl hourpctl Hourly percentiles
Daystat daymin Daily minimum
Daystat daymax Daily maximum
@@ -336,9 +337,9 @@ Operator catalog:
Daystat daymean Daily mean
Daystat dayavg Daily average
Daystat daystd Daily standard deviation
- Daystat daystd1 Daily standard deviation
+ Daystat daystd1 Daily standard deviation (n-1)
Daystat dayvar Daily variance
- Daystat dayvar1 Daily variance
+ Daystat dayvar1 Daily variance (n-1)
Daypctl daypctl Daily percentiles
Monstat monmin Monthly minimum
Monstat monmax Monthly maximum
@@ -346,9 +347,9 @@ Operator catalog:
Monstat monmean Monthly mean
Monstat monavg Monthly average
Monstat monstd Monthly standard deviation
- Monstat monstd1 Monthly standard deviation
+ Monstat monstd1 Monthly standard deviation (n-1)
Monstat monvar Monthly variance
- Monstat monvar1 Monthly variance
+ Monstat monvar1 Monthly variance (n-1)
Monpctl monpctl Monthly percentiles
Yearmonstat yearmonmean Yearly mean from monthly data
Yearstat yearmin Yearly minimum
@@ -357,9 +358,9 @@ Operator catalog:
Yearstat yearmean Yearly mean
Yearstat yearavg Yearly average
Yearstat yearstd Yearly standard deviation
- Yearstat yearstd1 Yearly standard deviation
+ Yearstat yearstd1 Yearly standard deviation (n-1)
Yearstat yearvar Yearly variance
- Yearstat yearvar1 Yearly variance
+ Yearstat yearvar1 Yearly variance (n-1)
Yearpctl yearpctl Yearly percentiles
Seasstat seasmin Seasonal minimum
Seasstat seasmax Seasonal maximum
@@ -367,9 +368,9 @@ Operator catalog:
Seasstat seasmean Seasonal mean
Seasstat seasavg Seasonal average
Seasstat seasstd Seasonal standard deviation
- Seasstat seasstd1 Seasonal standard deviation
+ Seasstat seasstd1 Seasonal standard deviation (n-1)
Seasstat seasvar Seasonal variance
- Seasstat seasvar1 Seasonal variance
+ Seasstat seasvar1 Seasonal variance (n-1)
Seaspctl seaspctl Seasonal percentiles
Yhourstat yhourmin Multi-year hourly minimum
Yhourstat yhourmax Multi-year hourly maximum
@@ -377,18 +378,18 @@ Operator catalog:
Yhourstat yhourmean Multi-year hourly mean
Yhourstat yhouravg Multi-year hourly average
Yhourstat yhourstd Multi-year hourly standard deviation
- Yhourstat yhourstd1 Multi-year hourly standard deviation
+ Yhourstat yhourstd1 Multi-year hourly standard deviation (n-1)
Yhourstat yhourvar Multi-year hourly variance
- Yhourstat yhourvar1 Multi-year hourly variance
+ Yhourstat yhourvar1 Multi-year hourly variance (n-1)
Ydaystat ydaymin Multi-year daily minimum
Ydaystat ydaymax Multi-year daily maximum
Ydaystat ydaysum Multi-year daily sum
Ydaystat ydaymean Multi-year daily mean
Ydaystat ydayavg Multi-year daily average
Ydaystat ydaystd Multi-year daily standard deviation
- Ydaystat ydaystd1 Multi-year daily standard deviation
+ Ydaystat ydaystd1 Multi-year daily standard deviation (n-1)
Ydaystat ydayvar Multi-year daily variance
- Ydaystat ydayvar1 Multi-year daily variance
+ Ydaystat ydayvar1 Multi-year daily variance (n-1)
Ydaypctl ydaypctl Multi-year daily percentiles
Ymonstat ymonmin Multi-year monthly minimum
Ymonstat ymonmax Multi-year monthly maximum
@@ -396,9 +397,9 @@ Operator catalog:
Ymonstat ymonmean Multi-year monthly mean
Ymonstat ymonavg Multi-year monthly average
Ymonstat ymonstd Multi-year monthly standard deviation
- Ymonstat ymonstd1 Multi-year monthly standard deviation
+ Ymonstat ymonstd1 Multi-year monthly standard deviation (n-1)
Ymonstat ymonvar Multi-year monthly variance
- Ymonstat ymonvar1 Multi-year monthly variance
+ Ymonstat ymonvar1 Multi-year monthly variance (n-1)
Ymonpctl ymonpctl Multi-year monthly percentiles
Yseasstat yseasmin Multi-year seasonal minimum
Yseasstat yseasmax Multi-year seasonal maximum
@@ -406,9 +407,9 @@ Operator catalog:
Yseasstat yseasmean Multi-year seasonal mean
Yseasstat yseasavg Multi-year seasonal average
Yseasstat yseasstd Multi-year seasonal standard deviation
- Yseasstat yseasstd1 Multi-year seasonal standard deviation
+ Yseasstat yseasstd1 Multi-year seasonal standard deviation (n-1)
Yseasstat yseasvar Multi-year seasonal variance
- Yseasstat yseasvar1 Multi-year seasonal variance
+ Yseasstat yseasvar1 Multi-year seasonal variance (n-1)
Yseaspctl yseaspctl Multi-year seasonal percentiles
Ydrunstat ydrunmin Multi-year daily running minimum
Ydrunstat ydrunmax Multi-year daily running maximum
@@ -416,9 +417,9 @@ Operator catalog:
Ydrunstat ydrunmean Multi-year daily running mean
Ydrunstat ydrunavg Multi-year daily running average
Ydrunstat ydrunstd Multi-year daily running standard deviation
- Ydrunstat ydrunstd1 Multi-year daily running standard deviation
+ Ydrunstat ydrunstd1 Multi-year daily running standard deviation (n-1)
Ydrunstat ydrunvar Multi-year daily running variance
- Ydrunstat ydrunvar1 Multi-year daily running variance
+ Ydrunstat ydrunvar1 Multi-year daily running variance (n-1)
Ydrunpctl ydrunpctl Multi-year daily running percentiles
-------------------------------------------------------------
Correlation and co.
@@ -500,6 +501,8 @@ Operator catalog:
Output outputsrv SERVICE ASCII output
Output outputext EXTRA ASCII output
Outputtab outputtab Table output
+ Outputgmt gmtxyz GMT xyz format
+ Outputgmt gmtcells GMT multiple segment format
-------------------------------------------------------------
Miscellaneous
-------------------------------------------------------------
@@ -538,6 +541,14 @@ Operator catalog:
Strgal strgal Strong gale days index per time period
Hurr hurr Hurricane days index per time period
-------------------------------------------------------------
+ Magics
+-------------------------------------------------------------
+ Magplot contour Contour plot
+ Magplot shaded Shaded contour plot
+ Magplot grfill Shaded gridfill plot
+ Magvector vector Vector arrows plot
+ Maggraph graph Line graph plot
+-------------------------------------------------------------
Climate indices
-------------------------------------------------------------
EcaCdd eca_cdd Consecutive dry days index per time period
diff --git a/cdo.spec b/cdo.spec
index 44e87cc..6f6566e 100644
--- a/cdo.spec
+++ b/cdo.spec
@@ -4,7 +4,7 @@
Name: cdo
#BuildRequires:
-Version: 1.7.0
+Version: 1.7.1
Release: 1
Summary: Climate Data Operators
License: GNU GENERAL PUBLIC LICENSE Version 2, June 1991
diff --git a/config/default b/config/default
index 7216c98..d2b1912 100755
--- a/config/default
+++ b/config/default
@@ -36,29 +36,31 @@ case "${HOSTNAME}" in
--with-hdf5=$HOME/local/hdf5-1.8.15-threadsafe \
--with-udunits2=/opt/local \
--with-curl=/opt/local \
+ --with-libxml2=/usr \
+ --with-magics=$HOME/local/Magics-2.25.3 \
--with-proj=/opt/local \
--with-szlib=$HOME/local"
- if test "$COMP" = icc ; then
- ${CONFPATH}configure \
+ if test "$COMP" = icpc ; then
+ ${CONFPATH}configure --enable-cxx \
$CDOLIBS \
- CC=icc CFLAGS="-g -Wall -Wwrite-strings -O2 -qopt-report=5 -march=native" CXX=icpc
- elif test "$COMP" = icpc ; then
+ CC=icc CXX=icpc CFLAGS="-g -Wall -O2 -qopt-report=5 -march=native"
+ elif test "$COMP" = icc ; then
${CONFPATH}configure \
$CDOLIBS \
- CC=icpc CFLAGS="-g -std=c++11 -Wall -O2 -qopt-report=5 -march=native"
+ CC=icc CFLAGS="-g -Wall -Wwrite-strings -O2 -qopt-report=5 -march=native"
elif test "$COMP" = clang++ ; then
- ${CONFPATH}configure \
+ ${CONFPATH}configure --enable-cxx \
$CDOLIBS \
- CC=clang++ CFLAGS="-g -Wall -O3"
+ CC=clang CXX=clang++ CFLAGS="-g -Wall -O3"
elif test "$COMP" = clang ; then
${CONFPATH}configure \
$CDOLIBS \
CC=clang CFLAGS="-g -Wall -Wwrite-strings -O3"
elif test "$COMP" = g++ ; then
- ${CONFPATH}configure \
+ ${CONFPATH}configure --enable-cxx \
$CDOLIBS \
- CC=g++ CFLAGS="-g -std=c++14 -Wall -W -Wfloat-equal -pedantic -O3 -march=native"
+ CC=gcc CXX=g++ CFLAGS="-g -Wall -W -Wfloat-equal -pedantic -O3 -march=native"
else
${CONFPATH}configure --prefix=$HOME/local \
--enable-maintainer-mode \
@@ -75,39 +77,41 @@ case "${HOSTNAME}" in
# --with-szlib=$HOME/local \
# --with-proj=/opt/local \
# --with-cmor=/Users/m214003/work/CMOR \
+# --with-magics=$HOME/local/magics-2.25.3 \
# --with-curl=/opt/local"
CDOLIBS="--enable-nearpt3 \
--with-fftw3 \
--with-grib_api=$HOME/local/gribapi-1.13.0 \
--with-netcdf=$HOME/local \
--with-hdf5=$HOME/local \
+ --with-libxml2=/opt/local \
--with-proj=/opt/local"
- if test "$COMP" = icc ; then
- ${CONFPATH}configure --prefix=$HOME/local \
+ if test "$COMP" = icpc ; then
+ ${CONFPATH}configure --enable-cxx --prefix=$HOME/local \
$CDOLIBS \
- CC=icc CFLAGS="-g -Wall -Wwrite-strings -O2 -qopt-report=5 -march=native" CXX=icpc
+ CC=icc CXX=icpc CFLAGS="-g -Wall -O2 -qopt-report=5 -march=native" CXX=icpc
elif test "$COMP" = icpc ; then
- ${CONFPATH}configure \
+ ${CONFPATH}configure \
$CDOLIBS \
- CC=icpc CFLAGS="-g -std=c++11 -Wall -O2 -qopt-report=5 -march=native"
+ CC=icc CFLAGS="-g -Wall -Wwrite-strings -O2 -qopt-report=5 -march=native"
elif test "$COMP" = clang++ ; then
- ${CONFPATH}configure \
+ ${CONFPATH}configure --enable-cxx \
$CDOLIBS \
- CC=clang++ CFLAGS="-g -Wall -O3"
+ CC=clang CXX=clang++ CFLAGS="-g -Wall -O3"
elif test "$COMP" = clang ; then
${CONFPATH}configure \
$CDOLIBS \
CC=clang CFLAGS="-g -Wall -Wwrite-strings -Ofast -march=native"
elif test "$COMP" = g++ ; then
- ${CONFPATH}configure \
+ ${CONFPATH}configure --enable-cxx \
$CDOLIBS \
- CC=g++ CFLAGS="-g -std=c++14 -Wall -W -Wfloat-equal -pedantic -O3"
+ CC=gcc CXX=g++ CFLAGS="-g -Wall -W -Wfloat-equal -pedantic -O3"
else
${CONFPATH}configure --prefix=$HOME/local \
--enable-maintainer-mode \
$CDOLIBS \
- CC=gcc CFLAGS="-g -std=c11 -pipe -Wall -Wwrite-strings -W -Wfloat-equal -pedantic -O3 -march=native -fstack-protector -Wa,-q"
+ CC=gcc CFLAGS="-g -std=c11 -pipe -Wall -Wpointer-arith -Wwrite-strings -W -Wfloat-equal -pedantic -O3 -march=native -fstack-protector -funsigned-char -Wa,-q"
# --with-libxml2=/usr \
# --with-magics=/Users/m214003/local/Magics-2.18.14nio \
fi
@@ -144,7 +148,12 @@ case "${HOSTNAME}" in
--with-udunits2=/sw/squeeze-x64/udunits-2.1.19 \
--with-proj=/sw/squeeze-x64/proj-4.7.0"
- if test "$COMP" = icc ; then
+ if test "$COMP" = icpc ; then
+ ${CONFPATH}configure --enable-cxx --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
+ --with-fftw3 \
+ $CDOLIBS \
+ CC=icc CXX=icpc CFLAGS="-g -Wall -O2 -qopt-report=5 -march=native"
+ elif test "$COMP" = icc ; then
${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
--with-fftw3 \
$CDOLIBS \
@@ -153,6 +162,10 @@ case "${HOSTNAME}" in
${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
$CDOLIBS \
CC=pgcc CFLAGS="-g -fast"
+ elif test "$COMP" = g++ ; then
+ ${CONFPATH}configure --enable-cxx \
+ $CDOLIBS \
+ CC=gcc CXX=g++ CFLAGS="-g -Wall -O3"
else
${CONFPATH}configure --prefix=$HOME/local --exec_prefix=$HOME/local/thunder \
--with-fftw3 \
@@ -168,6 +181,7 @@ case "${HOSTNAME}" in
--with-szlib=/sw/rhel6-x64/sys/szip-2.1-gcc48 \
--with-udunits2=/sw/rhel6-x64/util/udunits-2.2.17-gcc48 \
--with-proj=/sw/rhel6-x64/graphics/proj4-4.9.1-gcc48"
+# --with-cmor=/sw/rhel6-x64/cmor-2.9.2-shared-gcc48 \
if test "$COMP" = icc ; then
${CONFPATH}configure --prefix=$HOME/local \
diff --git a/configure b/configure
index cc5ef9b..116e78f 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for cdo 1.7.0.
+# Generated by GNU Autoconf 2.68 for cdo 1.7.1.
#
# Report bugs to <http://mpimet.mpg.de/cdo>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cdo'
PACKAGE_TARNAME='cdo'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='cdo 1.7.0'
+PACKAGE_VERSION='1.7.1'
+PACKAGE_STRING='cdo 1.7.1'
PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdo'
PACKAGE_URL=''
@@ -621,6 +621,7 @@ AM_CPPFLAGS
CLIBS
CLDFLAGS
FCFLAGS
+ENABLE_CXX
BUILD_AVX2_TESTS_FALSE
BUILD_AVX2_TESTS_TRUE
BUILD_AVX_TESTS_FALSE
@@ -671,6 +672,7 @@ ZLIB_LIBS
ZLIB_INCLUDE
THREADS_LIBS
THREADS_INCLUDE
+ENABLE_THREADS
PTHREAD_CFLAGS
PTHREAD_LIBS
PTHREAD_CC
@@ -839,6 +841,7 @@ with_magics
with_libxml2
enable_cdi_lib
enable_all_static
+enable_cxx
'
ac_precious_vars='build_alias
host_alias
@@ -1395,7 +1398,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures cdo 1.7.0 to adapt to many kinds of systems.
+\`configure' configures cdo 1.7.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1465,7 +1468,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of cdo 1.7.0:";;
+ short | recursive ) echo "Configuration of cdo 1.7.1:";;
esac
cat <<\_ACEOF
@@ -1499,6 +1502,7 @@ Optional Features:
[default=no]
--enable-all-static build a completely statically linked CDO binary
[default=no]
+ --enable-cxx Use CXX as default compiler [default=no]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1616,7 +1620,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-cdo configure 1.7.0
+cdo configure 1.7.1
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2209,7 +2213,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by cdo $as_me 1.7.0, which was
+It was created by cdo $as_me 1.7.1, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3158,7 +3162,7 @@ fi
# Define the identity of the package.
PACKAGE='cdo'
- VERSION='1.7.0'
+ VERSION='1.7.1'
cat >>confdefs.h <<_ACEOF
@@ -17521,6 +17525,18 @@ fi
done
+for ac_header in execinfo.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_execinfo_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EXECINFO_H 1
+_ACEOF
+
+fi
+
+done
+
# ----------------------------------------------------------------------
# Checks for the availability of functions
for ac_func in mallinfo
@@ -17534,6 +17550,17 @@ _ACEOF
fi
done
+for ac_func in backtrace
+do :
+ ac_fn_c_check_func "$LINENO" "backtrace" "ac_cv_func_backtrace"
+if test "x$ac_cv_func_backtrace" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_BACKTRACE 1
+_ACEOF
+
+fi
+done
+
# ----------------------------------------------------------------------
# Checks for the availability of ANSI-C99 functions
for ac_func in getrlimit
@@ -17688,6 +17715,39 @@ _ACEOF
fi
done
+for ac_func in feenableexcept
+do :
+ ac_fn_c_check_func "$LINENO" "feenableexcept" "ac_cv_func_feenableexcept"
+if test "x$ac_cv_func_feenableexcept" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_FEENABLEEXCEPT 1
+_ACEOF
+
+fi
+done
+
+#
+ac_fn_c_check_member "$LINENO" "fenv_t" "__control" "ac_cv_member_fenv_t___control" "#include <fenv.h>
+"
+if test "x$ac_cv_member_fenv_t___control" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FENV_T___CONTROL 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "fenv_t" "__mxcsr" "ac_cv_member_fenv_t___mxcsr" "#include <fenv.h>
+"
+if test "x$ac_cv_member_fenv_t___mxcsr" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FENV_T___MXCSR 1
+_ACEOF
+
+
+fi
+
# ----------------------------------------------------------------------
# Enable NEARPT3 support
# AC_MSG_CHECKING([for nearpt3 support])
@@ -17728,6 +17788,7 @@ CFLAGS="$CFLAGS ${OPENMP_CFLAGS}"
# ----------------------------------------------------------------------
# Checks for multithreaded compiling + linking
+ENABLE_THREADS=no
# Check whether --with-threads was given.
if test "${with_threads+set}" = set; then :
@@ -18175,6 +18236,7 @@ if test x"$ax_pthread_ok" = xyes; then
$as_echo "#define HAVE_LIBPTHREAD 1" >>confdefs.h
+ ENABLE_THREADS=yes
:
else
ax_pthread_ok=no
@@ -18252,6 +18314,7 @@ _ACEOF
fi
+ ENABLE_THREADS=yes
THREADS_LIBS=" -L$THREADS_ROOT/lib -lpthread"
THREADS_INCLUDE=" -I$THREADS_ROOT/include" ;; #(
*) :
@@ -18259,6 +18322,7 @@ fi
esac
+
# ----------------------------------------------------------------------
# Link application to ZLIB library, needed for netcdf
ZLIB_INCLUDE=''
@@ -21167,11 +21231,29 @@ else
fi
+# Check whether --enable-cxx was given.
+if test "${enable_cxx+set}" = set; then :
+ enableval=$enable_cxx; if test "x$enable_cxx" != 'xno'; then :
+ CC=$CXX
+ CXXFLAGS=$CFLAGS
+ enable_cxx=yes
+else
+ enable_cxx=no
+fi
+else
+ enable_cxx=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_cxx" >&5
+$as_echo "$enable_cxx" >&6; }
+ENABLE_CXX=$enable_cxx
+
# ----------------------------------------------------------------------
+
#AC_SUBST([INCLUDES])
@@ -21236,9 +21318,9 @@ ac_config_files="$ac_config_files test/Select.test test/Spectral.test test/Timst
ac_config_files="$ac_config_files test/Ymonstat.test test/Fldstat.test test/Fldpctl.test test/Ensstat.test test/Enspctl.test"
-ac_config_files="$ac_config_files test/Afterburner.test test/Detrend.test test/Arith.test test/Gradsdes.test"
+ac_config_files="$ac_config_files test/Afterburner.test test/Detrend.test test/Arith.test test/Expr.test"
-ac_config_files="$ac_config_files test/wildcard.test"
+ac_config_files="$ac_config_files test/Gradsdes.test test/Collgrid.test test/threads.test test/wildcard.test"
ac_config_files="$ac_config_files Makefile src/Makefile contrib/Makefile test/Makefile test/data/Makefile cdo.spec cdo.settings"
@@ -21816,7 +21898,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by cdo $as_me 1.7.0, which was
+This file was extended by cdo $as_me 1.7.1, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21882,7 +21964,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-cdo config.status 1.7.0
+cdo config.status 1.7.1
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
@@ -22409,7 +22491,10 @@ do
"test/Afterburner.test") CONFIG_FILES="$CONFIG_FILES test/Afterburner.test" ;;
"test/Detrend.test") CONFIG_FILES="$CONFIG_FILES test/Detrend.test" ;;
"test/Arith.test") CONFIG_FILES="$CONFIG_FILES test/Arith.test" ;;
+ "test/Expr.test") CONFIG_FILES="$CONFIG_FILES test/Expr.test" ;;
"test/Gradsdes.test") CONFIG_FILES="$CONFIG_FILES test/Gradsdes.test" ;;
+ "test/Collgrid.test") CONFIG_FILES="$CONFIG_FILES test/Collgrid.test" ;;
+ "test/threads.test") CONFIG_FILES="$CONFIG_FILES test/threads.test" ;;
"test/wildcard.test") CONFIG_FILES="$CONFIG_FILES test/wildcard.test" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
@@ -23923,7 +24008,10 @@ _LT_EOF
"test/Afterburner.test":F) chmod a+x "$ac_file" ;;
"test/Detrend.test":F) chmod a+x "$ac_file" ;;
"test/Arith.test":F) chmod a+x "$ac_file" ;;
+ "test/Expr.test":F) chmod a+x "$ac_file" ;;
"test/Gradsdes.test":F) chmod a+x "$ac_file" ;;
+ "test/Collgrid.test":F) chmod a+x "$ac_file" ;;
+ "test/threads.test":F) chmod a+x "$ac_file" ;;
"test/wildcard.test":F) chmod a+x "$ac_file" ;;
esac
diff --git a/configure.ac b/configure.ac
index 8d8b8d9..518d115 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
# autoconf 2.68
# libtool 2.4.2
-AC_INIT([cdo], [1.7.0], [http://mpimet.mpg.de/cdo])
+AC_INIT([cdo], [1.7.1], [http://mpimet.mpg.de/cdo])
AC_DEFINE_UNQUOTED(CDO, ["$PACKAGE_VERSION"], [CDO version])
@@ -67,9 +67,11 @@ AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(glob.h)
AC_CHECK_HEADERS(fnmatch.h)
AC_CHECK_HEADERS(wordexp.h)
+AC_CHECK_HEADERS(execinfo.h)
# ----------------------------------------------------------------------
# Checks for the availability of functions
AC_CHECK_FUNCS(mallinfo)
+AC_CHECK_FUNCS(backtrace)
# ----------------------------------------------------------------------
# Checks for the availability of ANSI-C99 functions
AC_CHECK_FUNCS(getrlimit)
@@ -115,6 +117,9 @@ AC_CHECK_LIB([m],[floor])
AC_CHECK_DECLS([isnan],,,[AC_INCLUDES_DEFAULT
@%:@include <math.h>])
AC_CHECK_FUNCS(sqrtl)
+AC_CHECK_FUNCS(feenableexcept)
+#
+AC_CHECK_MEMBERS([fenv_t.__control, fenv_t.__mxcsr],,,[[#include <fenv.h>]])
# ----------------------------------------------------------------------
# Enable NEARPT3 support
# AC_MSG_CHECKING([for nearpt3 support])
@@ -215,7 +220,18 @@ AC_MSG_RESULT([no])
AM_CONDITIONAL(BUILD_AVX2_TESTS, test x$ac_have_as_avx2 = xyes)
+AC_ARG_ENABLE([cxx],
+ [AS_HELP_STRING([--enable-cxx],[Use CXX as default compiler [default=no]])],
+ [AS_IF([test "x$enable_cxx" != 'xno'],
+ [CC=$CXX
+ CXXFLAGS=$CFLAGS
+ enable_cxx=yes],
+ [enable_cxx=no])],
+ [enable_cxx=no])
+AC_MSG_RESULT([$enable_cxx])
+AC_SUBST([ENABLE_CXX],[$enable_cxx])
# ----------------------------------------------------------------------
+AC_SUBST([CXXFLAGS])
AC_SUBST([CPPFLAGS])
AC_SUBST([FCFLAGS])
AC_SUBST([CLDFLAGS])
@@ -235,8 +251,8 @@ AC_CONFIG_FILES([test/File.test test/Read_grib.test test/Read_netcdf.test test/C
AC_CONFIG_FILES([test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test],[chmod a+x "$ac_file"])
AC_CONFIG_FILES([test/Select.test test/Spectral.test test/Timstat.test test/Vertint.test],[chmod a+x "$ac_file"])
AC_CONFIG_FILES([test/Ymonstat.test test/Fldstat.test test/Fldpctl.test test/Ensstat.test test/Enspctl.test],[chmod a+x "$ac_file"])
-AC_CONFIG_FILES([test/Afterburner.test test/Detrend.test test/Arith.test test/Gradsdes.test],[chmod a+x "$ac_file"])
-AC_CONFIG_FILES([test/wildcard.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Afterburner.test test/Detrend.test test/Arith.test test/Expr.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Gradsdes.test test/Collgrid.test test/threads.test test/wildcard.test],[chmod a+x "$ac_file"])
AC_CONFIG_FILES([Makefile src/Makefile contrib/Makefile test/Makefile test/data/Makefile cdo.spec cdo.settings])
AC_OUTPUT
diff --git a/contrib/Makefile.in b/contrib/Makefile.in
index bbc9966..e3ff687 100644
--- a/contrib/Makefile.in
+++ b/contrib/Makefile.in
@@ -150,6 +150,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_CDI_LIB = @ENABLE_CDI_LIB@
ENABLE_CGRIBEX = @ENABLE_CGRIBEX@
+ENABLE_CXX = @ENABLE_CXX@
ENABLE_DATA = @ENABLE_DATA@
ENABLE_EXTRA = @ENABLE_EXTRA@
ENABLE_GRIB = @ENABLE_GRIB@
@@ -160,6 +161,7 @@ ENABLE_NC4 = @ENABLE_NC4@
ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
ENABLE_NETCDF = @ENABLE_NETCDF@
ENABLE_SERVICE = @ENABLE_SERVICE@
+ENABLE_THREADS = @ENABLE_THREADS@
EXEEXT = @EXEEXT@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
diff --git a/contrib/cdoCompletion.bash b/contrib/cdoCompletion.bash
index 948aa02..517486b 100644
--- a/contrib/cdoCompletion.bash
+++ b/contrib/cdoCompletion.bash
@@ -4,6 +4,8 @@ complete -W "
-- \
-- \
-- \
+-- \
+-- \
-L \
-M \
-O \
@@ -25,795 +27,13 @@ complete -W "
-t \
-v \
-z \
-abs -abs \
-acos -acos \
-add -add \
-addc -addc \
-adipot -adipot \
-adisit -adisit \
-aexpr -aexpr \
-aexprf -aexprf \
-after -after \
-afterburner -afterburner \
-anomaly -anomaly \
-ap2pl -ap2pl \
-ap2pl_lp -ap2pl_lp \
-ap2plx -ap2plx \
-ap2plx_lp -ap2plx_lp \
-asin -asin \
-atan -atan \
-atan2 -atan2 \
-bandpass -bandpass \
-beta -beta \
-boxavg -boxavg \
-cat -cat \
-cdiread -cdiread \
-cdiwrite -cdiwrite \
-change_e5lsm -change_e5lsm \
-change_e5mask -change_e5mask \
-change_e5slm -change_e5slm \
-chcode -chcode \
-chisquare -chisquare \
-chlevel -chlevel \
-chlevelc -chlevelc \
-chlevelv -chlevelv \
-chltype -chltype \
-chname -chname \
-chparam -chparam \
-chtabnum -chtabnum \
-chunit -chunit \
-chvar -chvar \
-cloudlayer -cloudlayer \
-cmd -cmd \
-cmor -cmor \
-collgrid -collgrid \
-com -com \
-command -command \
-complextorect -complextorect \
-consecsum -consecsum \
-consects -consects \
-const -const \
-conv_cmor_table -conv_cmor_table \
-copy -copy \
-cos -cos \
-coshill -coshill \
-covar0 -covar0 \
-covar0r -covar0r \
-dayavg -dayavg \
-daycount -daycount \
-daylogs -daylogs \
-daymax -daymax \
-daymean -daymean \
-daymin -daymin \
-daypctl -daypctl \
-daystd -daystd \
-daystd1 -daystd1 \
-daysum -daysum \
-dayvar -dayvar \
-dayvar1 -dayvar1 \
-del29feb -del29feb \
-delcode -delcode \
-delday -delday \
-delete -delete \
-delname -delname \
-delparam -delparam \
-deltap -deltap \
-deltap_fl -deltap_fl \
-delvar -delvar \
-detrend -detrend \
-diff -diff \
-diffc -diffc \
-diffn -diffn \
-diffp -diffp \
-diffv -diffv \
-distgrid -distgrid \
-div -div \
-divc -divc \
-divcoslat -divcoslat \
-divdpm -divdpm \
-divdpy -divdpy \
-dumplogo -dumplogo \
-dumplogs -dumplogs \
-dumpmap -dumpmap \
-duplicate -duplicate \
-dv2ps -dv2ps \
-dv2uv -dv2uv \
-dv2uvl -dv2uvl \
-eca_cdd -eca_cdd \
-eca_cfd -eca_cfd \
-eca_csu -eca_csu \
-eca_cwd -eca_cwd \
-eca_cwdi -eca_cwdi \
-eca_cwfi -eca_cwfi \
-eca_etr -eca_etr \
-eca_fd -eca_fd \
-eca_gsl -eca_gsl \
-eca_hd -eca_hd \
-eca_hwdi -eca_hwdi \
-eca_hwfi -eca_hwfi \
-eca_id -eca_id \
-eca_pd -eca_pd \
-eca_r10mm -eca_r10mm \
-eca_r1mm -eca_r1mm \
-eca_r20mm -eca_r20mm \
-eca_r75p -eca_r75p \
-eca_r75ptot -eca_r75ptot \
-eca_r90p -eca_r90p \
-eca_r90ptot -eca_r90ptot \
-eca_r95p -eca_r95p \
-eca_r95ptot -eca_r95ptot \
-eca_r99p -eca_r99p \
-eca_r99ptot -eca_r99ptot \
-eca_rr1 -eca_rr1 \
-eca_rx1day -eca_rx1day \
-eca_rx5day -eca_rx5day \
-eca_sdii -eca_sdii \
-eca_su -eca_su \
-eca_tg10p -eca_tg10p \
-eca_tg90p -eca_tg90p \
-eca_tn10p -eca_tn10p \
-eca_tn90p -eca_tn90p \
-eca_tr -eca_tr \
-eca_tx10p -eca_tx10p \
-eca_tx90p -eca_tx90p \
-enlarge -enlarge \
-enlargegrid -enlargegrid \
-ensavg -ensavg \
-ensbrs -ensbrs \
-enscrps -enscrps \
-ensmax -ensmax \
-ensmean -ensmean \
-ensmin -ensmin \
-enspctl -enspctl \
-ensrkhist_space -ensrkhist_space \
-ensrkhist_time -ensrkhist_time \
-ensrkhistspace -ensrkhistspace \
-ensrkhisttime -ensrkhisttime \
-ensroc -ensroc \
-ensstd -ensstd \
-ensstd1 -ensstd1 \
-enssum -enssum \
-ensvar -ensvar \
-ensvar1 -ensvar1 \
-eof -eof \
-eof3d -eof3d \
-eof3dspatial -eof3dspatial \
-eof3dtime -eof3dtime \
-eofcoeff -eofcoeff \
-eofcoeff3d -eofcoeff3d \
-eofspatial -eofspatial \
-eoftime -eoftime \
-eq -eq \
-eqc -eqc \
-exp -exp \
-export_e5ml -export_e5ml \
-export_e5res -export_e5res \
-expr -expr \
-exprf -exprf \
-fc2gp -fc2gp \
-fc2sp -fc2sp \
-fdns -fdns \
-filedes -filedes \
-fillmiss -fillmiss \
-fillmiss2 -fillmiss2 \
-fisher -fisher \
-fldavg -fldavg \
-fldcor -fldcor \
-fldcovar -fldcovar \
-fldmax -fldmax \
-fldmean -fldmean \
-fldmin -fldmin \
-fldpctl -fldpctl \
-fldrms -fldrms \
-fldstd -fldstd \
-fldstd1 -fldstd1 \
-fldsum -fldsum \
-fldvar -fldvar \
-fldvar1 -fldvar1 \
+--operators ---operators \
+Use -Use \
+a -a \
+all -all \
for -for \
-fourier -fourier \
-fpressure -fpressure \
-gather -gather \
-ge -ge \
-gec -gec \
-genbic -genbic \
-genbil -genbil \
-gencon -gencon \
-gencon2 -gencon2 \
-gendis -gendis \
-gengrid -gengrid \
-genlaf -genlaf \
-genlevelbounds -genlevelbounds \
-gennn -gennn \
-genycon -genycon \
-geopotheight -geopotheight \
-ggstat -ggstat \
-ggstats -ggstats \
-gheight -gheight \
-globavg -globavg \
-gp2fc -gp2fc \
-gp2sp -gp2sp \
-gp2spl -gp2spl \
-gradsdes -gradsdes \
-gridarea -gridarea \
-gridboxavg -gridboxavg \
-gridboxmax -gridboxmax \
-gridboxmean -gridboxmean \
-gridboxmin -gridboxmin \
-gridboxstd -gridboxstd \
-gridboxstd1 -gridboxstd1 \
-gridboxsum -gridboxsum \
-gridboxvar -gridboxvar \
-gridboxvar1 -gridboxvar1 \
-griddes -griddes \
-griddes2 -griddes2 \
-griddx -griddx \
-griddy -griddy \
-gridmask -gridmask \
-gridverify -gridverify \
-gridweights -gridweights \
-gt -gt \
-gtc -gtc \
-harmonic -harmonic \
-highpass -highpass \
-histcount -histcount \
-histfreq -histfreq \
-histmean -histmean \
-histsum -histsum \
-houravg -houravg \
-hourcount -hourcount \
-hourmax -hourmax \
-hourmean -hourmean \
-hourmin -hourmin \
-hourpctl -hourpctl \
-hourstd -hourstd \
-hourstd1 -hourstd1 \
-hoursum -hoursum \
-hourvar -hourvar \
-hourvar1 -hourvar1 \
-hpressure -hpressure \
-hurr -hurr \
-ifnotthen -ifnotthen \
-ifnotthenc -ifnotthenc \
-ifthen -ifthen \
-ifthenc -ifthenc \
-ifthenelse -ifthenelse \
-import_amsr -import_amsr \
-import_binary -import_binary \
-import_cmsaf -import_cmsaf \
-import_e5ml -import_e5ml \
-import_e5res -import_e5res \
-import_grads -import_grads \
-import_obs -import_obs \
-imtocomplex -imtocomplex \
-info -info \
-infoc -infoc \
-infon -infon \
-infop -infop \
-infos -infos \
-infov -infov \
-input -input \
-inputext -inputext \
-inputsrv -inputsrv \
-int -int \
-interpolate -interpolate \
-intgrid -intgrid \
-intgridbil -intgridbil \
-intgridcon -intgridcon \
-intgridtraj -intgridtraj \
-intlevel -intlevel \
-intlevel3d -intlevel3d \
-intlevelx -intlevelx \
-intlevelx3d -intlevelx3d \
-intntime -intntime \
-intpoint -intpoint \
-inttime -inttime \
-intyear -intyear \
-invertlat -invertlat \
-invertlatdata -invertlatdata \
-invertlatdes -invertlatdes \
-invertlev -invertlev \
-invertlon -invertlon \
-invertlondata -invertlondata \
-invertlondes -invertlondes \
-isosurface -isosurface \
-le -le \
-lec -lec \
-lmavg -lmavg \
-lmean -lmean \
-lmmean -lmmean \
-lmstd -lmstd \
-ln -ln \
-log -log \
-log10 -log10 \
-lowpass -lowpass \
-lsmean -lsmean \
-lt -lt \
-ltc -ltc \
-map -map \
-mask -mask \
-maskindexbox -maskindexbox \
-masklonlatbox -masklonlatbox \
-maskregion -maskregion \
-mastrfu -mastrfu \
-max -max \
-meandiff2test -meandiff2test \
-meravg -meravg \
-merge -merge \
-mergegrid -mergegrid \
-mergetime -mergetime \
-mermax -mermax \
-mermean -mermean \
-mermin -mermin \
-merpctl -merpctl \
-merstd -merstd \
-merstd1 -merstd1 \
-mersum -mersum \
-mervar -mervar \
-mervar1 -mervar1 \
-min -min \
-ml2hl -ml2hl \
-ml2hl_lp -ml2hl_lp \
-ml2hlx -ml2hlx \
-ml2hlx_lp -ml2hlx_lp \
-ml2pl -ml2pl \
-ml2pl_lp -ml2pl_lp \
-ml2plx -ml2plx \
-ml2plx_lp -ml2plx_lp \
-mod -mod \
-monadd -monadd \
-monavg -monavg \
-moncount -moncount \
-mondiv -mondiv \
-monlogs -monlogs \
-monmax -monmax \
-monmean -monmean \
-monmin -monmin \
-monmul -monmul \
-monpctl -monpctl \
-monstd -monstd \
-monstd1 -monstd1 \
-monsub -monsub \
-monsum -monsum \
-monvar -monvar \
-monvar1 -monvar1 \
-mrotuv -mrotuv \
-mrotuvb -mrotuvb \
-mul -mul \
-mulc -mulc \
-mulcoslat -mulcoslat \
-muldoy -muldoy \
-muldpm -muldpm \
-muldpy -muldpy \
-ncode -ncode \
-ncode -ncode \
-ncopy -ncopy \
-ndate -ndate \
-ne -ne \
-nec -nec \
-nint -nint \
-nlevel -nlevel \
-nmltest -nmltest \
-nmon -nmon \
-normal -normal \
-npar -npar \
-ntime -ntime \
-nvar -nvar \
-nyear -nyear \
-output -output \
-outputarr -outputarr \
-outputbounds -outputbounds \
-outputboundscpt -outputboundscpt \
-outputcenter -outputcenter \
-outputcenter2 -outputcenter2 \
-outputcentercpt -outputcentercpt \
-outputext -outputext \
-outputf -outputf \
-outputfld -outputfld \
-outputint -outputint \
-outputkey -outputkey \
-outputsrv -outputsrv \
-outputtab -outputtab \
-outputtri -outputtri \
-outputts -outputts \
-outputvector -outputvector \
-outputvrml -outputvrml \
-outputxyz -outputxyz \
-pack -pack \
-pardes -pardes \
-pardup -pardup \
-parmul -parmul \
-partab -partab \
-partab2 -partab2 \
-pinfo -pinfo \
-pinfov -pinfov \
-pow -pow \
-pressure_fl -pressure_fl \
-pressure_hl -pressure_hl \
-random -random \
-read_cmor_table -read_cmor_table \
-read_e5ml -read_e5ml \
-reci -reci \
-regres -regres \
-remap -remap \
-remapbic -remapbic \
-remapbil -remapbil \
-remapcon -remapcon \
-remapcon1 -remapcon1 \
-remapcon2 -remapcon2 \
-remapdis -remapdis \
-remapdis1 -remapdis1 \
-remapeta -remapeta \
-remapeta_s -remapeta_s \
-remapeta_z -remapeta_z \
-remaplaf -remaplaf \
-remapnn -remapnn \
-remapsum -remapsum \
-remapycon -remapycon \
-replace -replace \
-retocomplex -retocomplex \
-rhopot -rhopot \
-rotuvb -rotuvb \
-runavg -runavg \
-runmax -runmax \
-runmean -runmean \
-runmin -runmin \
-runpctl -runpctl \
-runstd -runstd \
-runstd1 -runstd1 \
-runsum -runsum \
-runvar -runvar \
-runvar1 -runvar1 \
-scalllogo -scalllogo \
-scatter -scatter \
-sealevelpressure -sealevelpressure \
-seasavg -seasavg \
-seascount -seascount \
-seasmax -seasmax \
-seasmean -seasmean \
-seasmin -seasmin \
-seaspctl -seaspctl \
-seasstd -seasstd \
-seasstd1 -seasstd1 \
-seassum -seassum \
-seasvar -seasvar \
-seasvar1 -seasvar1 \
-seinfo -seinfo \
-seinfoc -seinfoc \
-seinfon -seinfon \
-seinfop -seinfop \
-selall -selall \
-selcode -selcode \
-seldate -seldate \
-selday -selday \
-select -select \
-selgrid -selgrid \
-selgridname -selgridname \
-selhour -selhour \
-selindexbox -selindexbox \
-sellevel -sellevel \
-sellevidx -sellevidx \
-sellonlatbox -sellonlatbox \
-selltype -selltype \
-selmon -selmon \
-selname -selname \
-seloperator -seloperator \
-selparam -selparam \
-selrec -selrec \
-selseas -selseas \
-selsmon -selsmon \
-selstdname -selstdname \
-seltabnum -seltabnum \
-seltime -seltime \
-seltimestep -seltimestep \
-selvar -selvar \
-selyear -selyear \
-selzaxis -selzaxis \
-selzaxisname -selzaxisname \
-setcalendar -setcalendar \
-setcindexbox -setcindexbox \
-setclonlatbox -setclonlatbox \
-setcode -setcode \
-setctomiss -setctomiss \
-setdate -setdate \
-setday -setday \
-setgatt -setgatt \
-setgatts -setgatts \
-setgrid -setgrid \
-setgridarea -setgridarea \
-setgridmask -setgridmask \
-setgridnumber -setgridnumber \
-setgridtype -setgridtype \
-setgriduri -setgriduri \
-sethalo -sethalo \
-setlevel -setlevel \
-setltype -setltype \
-setmisstoc -setmisstoc \
-setmisstodis -setmisstodis \
-setmisstonn -setmisstonn \
-setmissval -setmissval \
-setmon -setmon \
-setname -setname \
-setparam -setparam \
-setpartab -setpartab \
-setpartabc -setpartabc \
-setpartabn -setpartabn \
-setpartabp -setpartabp \
-setpartabv -setpartabv \
-setrcaname -setrcaname \
-setreftime -setreftime \
-setrtoc -setrtoc \
-setrtoc2 -setrtoc2 \
-setrtomiss -setrtomiss \
-settabnum -settabnum \
-settaxis -settaxis \
-settime -settime \
-settunits -settunits \
-setunit -setunit \
-setvals -setvals \
-setvar -setvar \
-setvrange -setvrange \
-setyear -setyear \
-setzaxis -setzaxis \
-shifttime -shifttime \
-showcode -showcode \
-showdate -showdate \
-showformat -showformat \
-showlevel -showlevel \
-showltype -showltype \
-showmon -showmon \
-showname -showname \
-showparam -showparam \
-showstdname -showstdname \
-showtime -showtime \
-showtimestamp -showtimestamp \
-showunit -showunit \
-showvar -showvar \
-showyear -showyear \
-sin -sin \
-sincos -sincos \
-sinfo -sinfo \
-sinfoc -sinfoc \
-sinfon -sinfon \
-sinfop -sinfop \
-sinfov -sinfov \
-smemlogo -smemlogo \
-smooth9 -smooth9 \
-snamelogo -snamelogo \
-sort -sort \
-sortcode -sortcode \
-sortlevel -sortlevel \
-sortname -sortname \
-sortparam -sortparam \
-sorttaxis -sorttaxis \
-sorttimestamp -sorttimestamp \
-sortvar -sortvar \
-sp2fc -sp2fc \
-sp2gp -sp2gp \
-sp2gpl -sp2gpl \
-sp2sp -sp2sp \
-spartab -spartab \
-spcut -spcut \
-specinfo -specinfo \
-spectrum -spectrum \
-sperclogo -sperclogo \
-splitcode -splitcode \
-splitday -splitday \
-splitgrid -splitgrid \
-splithour -splithour \
-splitlevel -splitlevel \
-splitmon -splitmon \
-splitname -splitname \
-splitparam -splitparam \
-splitrec -splitrec \
-splitseas -splitseas \
-splitsel -splitsel \
-splittabnum -splittabnum \
-splitvar -splitvar \
-splityear -splityear \
-splityearmon -splityearmon \
-splitzaxis -splitzaxis \
-sqr -sqr \
-sqrt -sqrt \
-ssopar -ssopar \
-stdatm -stdatm \
-stimelogo -stimelogo \
-strbre -strbre \
-strgal -strgal \
-strwin -strwin \
-studentt -studentt \
-sub -sub \
-subc -subc \
-subtrend -subtrend \
-szip -szip \
-tan -tan \
-tee -tee \
-temp -temp \
-template1 -template1 \
-template2 -template2 \
-test -test \
-test2 -test2 \
-testcellsearch -testcellsearch \
-testdata -testdata \
-testpointsearch -testpointsearch \
-thinout -thinout \
-timavg -timavg \
-timcor -timcor \
-timcount -timcount \
-timcovar -timcovar \
-timmax -timmax \
-timmean -timmean \
-timmin -timmin \
-timpctl -timpctl \
-timselavg -timselavg \
-timselmax -timselmax \
-timselmean -timselmean \
-timselmin -timselmin \
-timselpctl -timselpctl \
-timselstd -timselstd \
-timselstd1 -timselstd1 \
-timselsum -timselsum \
-timselvar -timselvar \
-timselvar1 -timselvar1 \
-timsort -timsort \
-timstd -timstd \
-timstd1 -timstd1 \
-timsum -timsum \
-timvar -timvar \
-timvar1 -timvar1 \
-tinfo -tinfo \
-topo -topo \
-tpnhalo -tpnhalo \
-transxy -transxy \
-trend -trend \
-trms -trms \
-tstepcount -tstepcount \
-unsetgridmask -unsetgridmask \
-uv2dv -uv2dv \
-uv2dvl -uv2dvl \
-vardes -vardes \
-vardup -vardup \
-varmul -varmul \
-varquot2test -varquot2test \
-varrms -varrms \
-vct -vct \
-vct2 -vct2 \
-vertavg -vertavg \
-vertcum -vertcum \
-vertcumhl -vertcumhl \
-vertint -vertint \
-vertmax -vertmax \
-vertmean -vertmean \
-vertmin -vertmin \
-vertstd -vertstd \
-vertstd1 -vertstd1 \
-vertsum -vertsum \
-vertvar -vertvar \
-vertvar1 -vertvar1 \
-vertwind -vertwind \
-vlist -vlist \
-wct -wct \
-write_e5ml -write_e5ml \
-writegrid -writegrid \
-writerandom -writerandom \
-xmonavg -xmonavg \
-xmonmax -xmonmax \
-xmonmean -xmonmean \
-xmonmin -xmonmin \
-xmonstd -xmonstd \
-xmonstd1 -xmonstd1 \
-xmonsum -xmonsum \
-xmonvar -xmonvar \
-xmonvar1 -xmonvar1 \
-xtimavg -xtimavg \
-xtimmax -xtimmax \
-xtimmean -xtimmean \
-xtimmin -xtimmin \
-xtimstd -xtimstd \
-xtimstd1 -xtimstd1 \
-xtimsum -xtimsum \
-xtimvar -xtimvar \
-xtimvar1 -xtimvar1 \
-xyearavg -xyearavg \
-xyearmax -xyearmax \
-xyearmean -xyearmean \
-xyearmin -xyearmin \
-xyearstd -xyearstd \
-xyearstd1 -xyearstd1 \
-xyearsum -xyearsum \
-xyearvar -xyearvar \
-xyearvar1 -xyearvar1 \
-yarbil -yarbil \
-yarcon -yarcon \
-yarnn -yarnn \
-ydayadd -ydayadd \
-ydayavg -ydayavg \
-ydaydiv -ydaydiv \
-ydaymax -ydaymax \
-ydaymean -ydaymean \
-ydaymin -ydaymin \
-ydaymul -ydaymul \
-ydaypctl -ydaypctl \
-ydaystd -ydaystd \
-ydaystd1 -ydaystd1 \
-ydaysub -ydaysub \
-ydaysum -ydaysum \
-ydayvar -ydayvar \
-ydayvar1 -ydayvar1 \
-ydrunavg -ydrunavg \
-ydrunmax -ydrunmax \
-ydrunmean -ydrunmean \
-ydrunmin -ydrunmin \
-ydrunpctl -ydrunpctl \
-ydrunstd -ydrunstd \
-ydrunstd1 -ydrunstd1 \
-ydrunsum -ydrunsum \
-ydrunvar -ydrunvar \
-ydrunvar1 -ydrunvar1 \
-yearavg -yearavg \
-yearcount -yearcount \
-yearmax -yearmax \
-yearmean -yearmean \
-yearmin -yearmin \
-yearmonavg -yearmonavg \
-yearmonmean -yearmonmean \
-yearpctl -yearpctl \
-yearstd -yearstd \
-yearstd1 -yearstd1 \
-yearsum -yearsum \
-yearvar -yearvar \
-yearvar1 -yearvar1 \
-yhouradd -yhouradd \
-yhouravg -yhouravg \
-yhourdiv -yhourdiv \
-yhourmax -yhourmax \
-yhourmean -yhourmean \
-yhourmin -yhourmin \
-yhourmul -yhourmul \
-yhourstd -yhourstd \
-yhourstd1 -yhourstd1 \
-yhoursub -yhoursub \
-yhoursum -yhoursum \
-yhourvar -yhourvar \
-yhourvar1 -yhourvar1 \
-ymonadd -ymonadd \
-ymonavg -ymonavg \
-ymondiv -ymondiv \
-ymonmax -ymonmax \
-ymonmean -ymonmean \
-ymonmin -ymonmin \
-ymonmul -ymonmul \
-ymonpctl -ymonpctl \
-ymonstd -ymonstd \
-ymonstd1 -ymonstd1 \
-ymonsub -ymonsub \
-ymonsum -ymonsum \
-ymonvar -ymonvar \
-ymonvar1 -ymonvar1 \
-yseasadd -yseasadd \
-yseasavg -yseasavg \
-yseasdiv -yseasdiv \
-yseasmax -yseasmax \
-yseasmean -yseasmean \
-yseasmin -yseasmin \
-yseasmul -yseasmul \
-yseaspctl -yseaspctl \
-yseasstd -yseasstd \
-yseasstd1 -yseasstd1 \
-yseassub -yseassub \
-yseassum -yseassum \
-yseasvar -yseasvar \
-yseasvar1 -yseasvar1 \
-zaxisdes -zaxisdes \
-zonavg -zonavg \
-zonmax -zonmax \
-zonmean -zonmean \
-zonmin -zonmin \
-zonpctl -zonpctl \
-zonrange -zonrange \
-zonstd -zonstd \
-zonstd1 -zonstd1 \
-zonsum -zonsum \
-zonvar -zonvar \
-zonvar1 -zonvar1 \
+list -list \
+of -of \
+operators. -operators. \
+option -option \
" -f cdo
diff --git a/contrib/cdoCompletion.tcsh b/contrib/cdoCompletion.tcsh
index 839531f..ab97758 100644
--- a/contrib/cdoCompletion.tcsh
+++ b/contrib/cdoCompletion.tcsh
@@ -4,6 +4,8 @@ set cdoCmpl = (\
- \
- \
- \
+- \
+- \
L \
M \
O \
@@ -25,795 +27,13 @@ s \
t \
v \
z \
-abs \
-acos \
-add \
-addc \
-adipot \
-adisit \
-aexpr \
-aexprf \
-after \
-afterburner \
-anomaly \
-ap2pl \
-ap2pl_lp \
-ap2plx \
-ap2plx_lp \
-asin \
-atan \
-atan2 \
-bandpass \
-beta \
-boxavg \
-cat \
-cdiread \
-cdiwrite \
-change_e5lsm \
-change_e5mask \
-change_e5slm \
-chcode \
-chisquare \
-chlevel \
-chlevelc \
-chlevelv \
-chltype \
-chname \
-chparam \
-chtabnum \
-chunit \
-chvar \
-cloudlayer \
-cmd \
-cmor \
-collgrid \
-com \
-command \
-complextorect \
-consecsum \
-consects \
-const \
-conv_cmor_table \
-copy \
-cos \
-coshill \
-covar0 \
-covar0r \
-dayavg \
-daycount \
-daylogs \
-daymax \
-daymean \
-daymin \
-daypctl \
-daystd \
-daystd1 \
-daysum \
-dayvar \
-dayvar1 \
-del29feb \
-delcode \
-delday \
-delete \
-delname \
-delparam \
-deltap \
-deltap_fl \
-delvar \
-detrend \
-diff \
-diffc \
-diffn \
-diffp \
-diffv \
-distgrid \
-div \
-divc \
-divcoslat \
-divdpm \
-divdpy \
-dumplogo \
-dumplogs \
-dumpmap \
-duplicate \
-dv2ps \
-dv2uv \
-dv2uvl \
-eca_cdd \
-eca_cfd \
-eca_csu \
-eca_cwd \
-eca_cwdi \
-eca_cwfi \
-eca_etr \
-eca_fd \
-eca_gsl \
-eca_hd \
-eca_hwdi \
-eca_hwfi \
-eca_id \
-eca_pd \
-eca_r10mm \
-eca_r1mm \
-eca_r20mm \
-eca_r75p \
-eca_r75ptot \
-eca_r90p \
-eca_r90ptot \
-eca_r95p \
-eca_r95ptot \
-eca_r99p \
-eca_r99ptot \
-eca_rr1 \
-eca_rx1day \
-eca_rx5day \
-eca_sdii \
-eca_su \
-eca_tg10p \
-eca_tg90p \
-eca_tn10p \
-eca_tn90p \
-eca_tr \
-eca_tx10p \
-eca_tx90p \
-enlarge \
-enlargegrid \
-ensavg \
-ensbrs \
-enscrps \
-ensmax \
-ensmean \
-ensmin \
-enspctl \
-ensrkhist_space \
-ensrkhist_time \
-ensrkhistspace \
-ensrkhisttime \
-ensroc \
-ensstd \
-ensstd1 \
-enssum \
-ensvar \
-ensvar1 \
-eof \
-eof3d \
-eof3dspatial \
-eof3dtime \
-eofcoeff \
-eofcoeff3d \
-eofspatial \
-eoftime \
-eq \
-eqc \
-exp \
-export_e5ml \
-export_e5res \
-expr \
-exprf \
-fc2gp \
-fc2sp \
-fdns \
-filedes \
-fillmiss \
-fillmiss2 \
-fisher \
-fldavg \
-fldcor \
-fldcovar \
-fldmax \
-fldmean \
-fldmin \
-fldpctl \
-fldrms \
-fldstd \
-fldstd1 \
-fldsum \
-fldvar \
-fldvar1 \
+--operators \
+Use \
+a \
+all \
for \
-fourier \
-fpressure \
-gather \
-ge \
-gec \
-genbic \
-genbil \
-gencon \
-gencon2 \
-gendis \
-gengrid \
-genlaf \
-genlevelbounds \
-gennn \
-genycon \
-geopotheight \
-ggstat \
-ggstats \
-gheight \
-globavg \
-gp2fc \
-gp2sp \
-gp2spl \
-gradsdes \
-gridarea \
-gridboxavg \
-gridboxmax \
-gridboxmean \
-gridboxmin \
-gridboxstd \
-gridboxstd1 \
-gridboxsum \
-gridboxvar \
-gridboxvar1 \
-griddes \
-griddes2 \
-griddx \
-griddy \
-gridmask \
-gridverify \
-gridweights \
-gt \
-gtc \
-harmonic \
-highpass \
-histcount \
-histfreq \
-histmean \
-histsum \
-houravg \
-hourcount \
-hourmax \
-hourmean \
-hourmin \
-hourpctl \
-hourstd \
-hourstd1 \
-hoursum \
-hourvar \
-hourvar1 \
-hpressure \
-hurr \
-ifnotthen \
-ifnotthenc \
-ifthen \
-ifthenc \
-ifthenelse \
-import_amsr \
-import_binary \
-import_cmsaf \
-import_e5ml \
-import_e5res \
-import_grads \
-import_obs \
-imtocomplex \
-info \
-infoc \
-infon \
-infop \
-infos \
-infov \
-input \
-inputext \
-inputsrv \
-int \
-interpolate \
-intgrid \
-intgridbil \
-intgridcon \
-intgridtraj \
-intlevel \
-intlevel3d \
-intlevelx \
-intlevelx3d \
-intntime \
-intpoint \
-inttime \
-intyear \
-invertlat \
-invertlatdata \
-invertlatdes \
-invertlev \
-invertlon \
-invertlondata \
-invertlondes \
-isosurface \
-le \
-lec \
-lmavg \
-lmean \
-lmmean \
-lmstd \
-ln \
-log \
-log10 \
-lowpass \
-lsmean \
-lt \
-ltc \
-map \
-mask \
-maskindexbox \
-masklonlatbox \
-maskregion \
-mastrfu \
-max \
-meandiff2test \
-meravg \
-merge \
-mergegrid \
-mergetime \
-mermax \
-mermean \
-mermin \
-merpctl \
-merstd \
-merstd1 \
-mersum \
-mervar \
-mervar1 \
-min \
-ml2hl \
-ml2hl_lp \
-ml2hlx \
-ml2hlx_lp \
-ml2pl \
-ml2pl_lp \
-ml2plx \
-ml2plx_lp \
-mod \
-monadd \
-monavg \
-moncount \
-mondiv \
-monlogs \
-monmax \
-monmean \
-monmin \
-monmul \
-monpctl \
-monstd \
-monstd1 \
-monsub \
-monsum \
-monvar \
-monvar1 \
-mrotuv \
-mrotuvb \
-mul \
-mulc \
-mulcoslat \
-muldoy \
-muldpm \
-muldpy \
-ncode \
-ncode \
-ncopy \
-ndate \
-ne \
-nec \
-nint \
-nlevel \
-nmltest \
-nmon \
-normal \
-npar \
-ntime \
-nvar \
-nyear \
-output \
-outputarr \
-outputbounds \
-outputboundscpt \
-outputcenter \
-outputcenter2 \
-outputcentercpt \
-outputext \
-outputf \
-outputfld \
-outputint \
-outputkey \
-outputsrv \
-outputtab \
-outputtri \
-outputts \
-outputvector \
-outputvrml \
-outputxyz \
-pack \
-pardes \
-pardup \
-parmul \
-partab \
-partab2 \
-pinfo \
-pinfov \
-pow \
-pressure_fl \
-pressure_hl \
-random \
-read_cmor_table \
-read_e5ml \
-reci \
-regres \
-remap \
-remapbic \
-remapbil \
-remapcon \
-remapcon1 \
-remapcon2 \
-remapdis \
-remapdis1 \
-remapeta \
-remapeta_s \
-remapeta_z \
-remaplaf \
-remapnn \
-remapsum \
-remapycon \
-replace \
-retocomplex \
-rhopot \
-rotuvb \
-runavg \
-runmax \
-runmean \
-runmin \
-runpctl \
-runstd \
-runstd1 \
-runsum \
-runvar \
-runvar1 \
-scalllogo \
-scatter \
-sealevelpressure \
-seasavg \
-seascount \
-seasmax \
-seasmean \
-seasmin \
-seaspctl \
-seasstd \
-seasstd1 \
-seassum \
-seasvar \
-seasvar1 \
-seinfo \
-seinfoc \
-seinfon \
-seinfop \
-selall \
-selcode \
-seldate \
-selday \
-select \
-selgrid \
-selgridname \
-selhour \
-selindexbox \
-sellevel \
-sellevidx \
-sellonlatbox \
-selltype \
-selmon \
-selname \
-seloperator \
-selparam \
-selrec \
-selseas \
-selsmon \
-selstdname \
-seltabnum \
-seltime \
-seltimestep \
-selvar \
-selyear \
-selzaxis \
-selzaxisname \
-setcalendar \
-setcindexbox \
-setclonlatbox \
-setcode \
-setctomiss \
-setdate \
-setday \
-setgatt \
-setgatts \
-setgrid \
-setgridarea \
-setgridmask \
-setgridnumber \
-setgridtype \
-setgriduri \
-sethalo \
-setlevel \
-setltype \
-setmisstoc \
-setmisstodis \
-setmisstonn \
-setmissval \
-setmon \
-setname \
-setparam \
-setpartab \
-setpartabc \
-setpartabn \
-setpartabp \
-setpartabv \
-setrcaname \
-setreftime \
-setrtoc \
-setrtoc2 \
-setrtomiss \
-settabnum \
-settaxis \
-settime \
-settunits \
-setunit \
-setvals \
-setvar \
-setvrange \
-setyear \
-setzaxis \
-shifttime \
-showcode \
-showdate \
-showformat \
-showlevel \
-showltype \
-showmon \
-showname \
-showparam \
-showstdname \
-showtime \
-showtimestamp \
-showunit \
-showvar \
-showyear \
-sin \
-sincos \
-sinfo \
-sinfoc \
-sinfon \
-sinfop \
-sinfov \
-smemlogo \
-smooth9 \
-snamelogo \
-sort \
-sortcode \
-sortlevel \
-sortname \
-sortparam \
-sorttaxis \
-sorttimestamp \
-sortvar \
-sp2fc \
-sp2gp \
-sp2gpl \
-sp2sp \
-spartab \
-spcut \
-specinfo \
-spectrum \
-sperclogo \
-splitcode \
-splitday \
-splitgrid \
-splithour \
-splitlevel \
-splitmon \
-splitname \
-splitparam \
-splitrec \
-splitseas \
-splitsel \
-splittabnum \
-splitvar \
-splityear \
-splityearmon \
-splitzaxis \
-sqr \
-sqrt \
-ssopar \
-stdatm \
-stimelogo \
-strbre \
-strgal \
-strwin \
-studentt \
-sub \
-subc \
-subtrend \
-szip \
-tan \
-tee \
-temp \
-template1 \
-template2 \
-test \
-test2 \
-testcellsearch \
-testdata \
-testpointsearch \
-thinout \
-timavg \
-timcor \
-timcount \
-timcovar \
-timmax \
-timmean \
-timmin \
-timpctl \
-timselavg \
-timselmax \
-timselmean \
-timselmin \
-timselpctl \
-timselstd \
-timselstd1 \
-timselsum \
-timselvar \
-timselvar1 \
-timsort \
-timstd \
-timstd1 \
-timsum \
-timvar \
-timvar1 \
-tinfo \
-topo \
-tpnhalo \
-transxy \
-trend \
-trms \
-tstepcount \
-unsetgridmask \
-uv2dv \
-uv2dvl \
-vardes \
-vardup \
-varmul \
-varquot2test \
-varrms \
-vct \
-vct2 \
-vertavg \
-vertcum \
-vertcumhl \
-vertint \
-vertmax \
-vertmean \
-vertmin \
-vertstd \
-vertstd1 \
-vertsum \
-vertvar \
-vertvar1 \
-vertwind \
-vlist \
-wct \
-write_e5ml \
-writegrid \
-writerandom \
-xmonavg \
-xmonmax \
-xmonmean \
-xmonmin \
-xmonstd \
-xmonstd1 \
-xmonsum \
-xmonvar \
-xmonvar1 \
-xtimavg \
-xtimmax \
-xtimmean \
-xtimmin \
-xtimstd \
-xtimstd1 \
-xtimsum \
-xtimvar \
-xtimvar1 \
-xyearavg \
-xyearmax \
-xyearmean \
-xyearmin \
-xyearstd \
-xyearstd1 \
-xyearsum \
-xyearvar \
-xyearvar1 \
-yarbil \
-yarcon \
-yarnn \
-ydayadd \
-ydayavg \
-ydaydiv \
-ydaymax \
-ydaymean \
-ydaymin \
-ydaymul \
-ydaypctl \
-ydaystd \
-ydaystd1 \
-ydaysub \
-ydaysum \
-ydayvar \
-ydayvar1 \
-ydrunavg \
-ydrunmax \
-ydrunmean \
-ydrunmin \
-ydrunpctl \
-ydrunstd \
-ydrunstd1 \
-ydrunsum \
-ydrunvar \
-ydrunvar1 \
-yearavg \
-yearcount \
-yearmax \
-yearmean \
-yearmin \
-yearmonavg \
-yearmonmean \
-yearpctl \
-yearstd \
-yearstd1 \
-yearsum \
-yearvar \
-yearvar1 \
-yhouradd \
-yhouravg \
-yhourdiv \
-yhourmax \
-yhourmean \
-yhourmin \
-yhourmul \
-yhourstd \
-yhourstd1 \
-yhoursub \
-yhoursum \
-yhourvar \
-yhourvar1 \
-ymonadd \
-ymonavg \
-ymondiv \
-ymonmax \
-ymonmean \
-ymonmin \
-ymonmul \
-ymonpctl \
-ymonstd \
-ymonstd1 \
-ymonsub \
-ymonsum \
-ymonvar \
-ymonvar1 \
-yseasadd \
-yseasavg \
-yseasdiv \
-yseasmax \
-yseasmean \
-yseasmin \
-yseasmul \
-yseaspctl \
-yseasstd \
-yseasstd1 \
-yseassub \
-yseassum \
-yseasvar \
-yseasvar1 \
-zaxisdes \
-zonavg \
-zonmax \
-zonmean \
-zonmin \
-zonpctl \
-zonrange \
-zonstd \
-zonstd1 \
-zonsum \
-zonvar \
-zonvar1 \
+list \
+of \
+operators. \
+option \
); complete cdo 'c/-/$cdoCmpl/' 'n/*/f/'
diff --git a/contrib/cdoCompletion.zsh b/contrib/cdoCompletion.zsh
index 7dc2836..af132a8 100644
--- a/contrib/cdoCompletion.zsh
+++ b/contrib/cdoCompletion.zsh
@@ -4,6 +4,8 @@ compctl -k "(
-- \
-- \
-- \
+-- \
+-- \
-L \
-M \
-O \
@@ -25,795 +27,13 @@ compctl -k "(
-t \
-v \
-z \
-abs -abs \
-acos -acos \
-add -add \
-addc -addc \
-adipot -adipot \
-adisit -adisit \
-aexpr -aexpr \
-aexprf -aexprf \
-after -after \
-afterburner -afterburner \
-anomaly -anomaly \
-ap2pl -ap2pl \
-ap2pl_lp -ap2pl_lp \
-ap2plx -ap2plx \
-ap2plx_lp -ap2plx_lp \
-asin -asin \
-atan -atan \
-atan2 -atan2 \
-bandpass -bandpass \
-beta -beta \
-boxavg -boxavg \
-cat -cat \
-cdiread -cdiread \
-cdiwrite -cdiwrite \
-change_e5lsm -change_e5lsm \
-change_e5mask -change_e5mask \
-change_e5slm -change_e5slm \
-chcode -chcode \
-chisquare -chisquare \
-chlevel -chlevel \
-chlevelc -chlevelc \
-chlevelv -chlevelv \
-chltype -chltype \
-chname -chname \
-chparam -chparam \
-chtabnum -chtabnum \
-chunit -chunit \
-chvar -chvar \
-cloudlayer -cloudlayer \
-cmd -cmd \
-cmor -cmor \
-collgrid -collgrid \
-com -com \
-command -command \
-complextorect -complextorect \
-consecsum -consecsum \
-consects -consects \
-const -const \
-conv_cmor_table -conv_cmor_table \
-copy -copy \
-cos -cos \
-coshill -coshill \
-covar0 -covar0 \
-covar0r -covar0r \
-dayavg -dayavg \
-daycount -daycount \
-daylogs -daylogs \
-daymax -daymax \
-daymean -daymean \
-daymin -daymin \
-daypctl -daypctl \
-daystd -daystd \
-daystd1 -daystd1 \
-daysum -daysum \
-dayvar -dayvar \
-dayvar1 -dayvar1 \
-del29feb -del29feb \
-delcode -delcode \
-delday -delday \
-delete -delete \
-delname -delname \
-delparam -delparam \
-deltap -deltap \
-deltap_fl -deltap_fl \
-delvar -delvar \
-detrend -detrend \
-diff -diff \
-diffc -diffc \
-diffn -diffn \
-diffp -diffp \
-diffv -diffv \
-distgrid -distgrid \
-div -div \
-divc -divc \
-divcoslat -divcoslat \
-divdpm -divdpm \
-divdpy -divdpy \
-dumplogo -dumplogo \
-dumplogs -dumplogs \
-dumpmap -dumpmap \
-duplicate -duplicate \
-dv2ps -dv2ps \
-dv2uv -dv2uv \
-dv2uvl -dv2uvl \
-eca_cdd -eca_cdd \
-eca_cfd -eca_cfd \
-eca_csu -eca_csu \
-eca_cwd -eca_cwd \
-eca_cwdi -eca_cwdi \
-eca_cwfi -eca_cwfi \
-eca_etr -eca_etr \
-eca_fd -eca_fd \
-eca_gsl -eca_gsl \
-eca_hd -eca_hd \
-eca_hwdi -eca_hwdi \
-eca_hwfi -eca_hwfi \
-eca_id -eca_id \
-eca_pd -eca_pd \
-eca_r10mm -eca_r10mm \
-eca_r1mm -eca_r1mm \
-eca_r20mm -eca_r20mm \
-eca_r75p -eca_r75p \
-eca_r75ptot -eca_r75ptot \
-eca_r90p -eca_r90p \
-eca_r90ptot -eca_r90ptot \
-eca_r95p -eca_r95p \
-eca_r95ptot -eca_r95ptot \
-eca_r99p -eca_r99p \
-eca_r99ptot -eca_r99ptot \
-eca_rr1 -eca_rr1 \
-eca_rx1day -eca_rx1day \
-eca_rx5day -eca_rx5day \
-eca_sdii -eca_sdii \
-eca_su -eca_su \
-eca_tg10p -eca_tg10p \
-eca_tg90p -eca_tg90p \
-eca_tn10p -eca_tn10p \
-eca_tn90p -eca_tn90p \
-eca_tr -eca_tr \
-eca_tx10p -eca_tx10p \
-eca_tx90p -eca_tx90p \
-enlarge -enlarge \
-enlargegrid -enlargegrid \
-ensavg -ensavg \
-ensbrs -ensbrs \
-enscrps -enscrps \
-ensmax -ensmax \
-ensmean -ensmean \
-ensmin -ensmin \
-enspctl -enspctl \
-ensrkhist_space -ensrkhist_space \
-ensrkhist_time -ensrkhist_time \
-ensrkhistspace -ensrkhistspace \
-ensrkhisttime -ensrkhisttime \
-ensroc -ensroc \
-ensstd -ensstd \
-ensstd1 -ensstd1 \
-enssum -enssum \
-ensvar -ensvar \
-ensvar1 -ensvar1 \
-eof -eof \
-eof3d -eof3d \
-eof3dspatial -eof3dspatial \
-eof3dtime -eof3dtime \
-eofcoeff -eofcoeff \
-eofcoeff3d -eofcoeff3d \
-eofspatial -eofspatial \
-eoftime -eoftime \
-eq -eq \
-eqc -eqc \
-exp -exp \
-export_e5ml -export_e5ml \
-export_e5res -export_e5res \
-expr -expr \
-exprf -exprf \
-fc2gp -fc2gp \
-fc2sp -fc2sp \
-fdns -fdns \
-filedes -filedes \
-fillmiss -fillmiss \
-fillmiss2 -fillmiss2 \
-fisher -fisher \
-fldavg -fldavg \
-fldcor -fldcor \
-fldcovar -fldcovar \
-fldmax -fldmax \
-fldmean -fldmean \
-fldmin -fldmin \
-fldpctl -fldpctl \
-fldrms -fldrms \
-fldstd -fldstd \
-fldstd1 -fldstd1 \
-fldsum -fldsum \
-fldvar -fldvar \
-fldvar1 -fldvar1 \
+--operators ---operators \
+Use -Use \
+a -a \
+all -all \
for -for \
-fourier -fourier \
-fpressure -fpressure \
-gather -gather \
-ge -ge \
-gec -gec \
-genbic -genbic \
-genbil -genbil \
-gencon -gencon \
-gencon2 -gencon2 \
-gendis -gendis \
-gengrid -gengrid \
-genlaf -genlaf \
-genlevelbounds -genlevelbounds \
-gennn -gennn \
-genycon -genycon \
-geopotheight -geopotheight \
-ggstat -ggstat \
-ggstats -ggstats \
-gheight -gheight \
-globavg -globavg \
-gp2fc -gp2fc \
-gp2sp -gp2sp \
-gp2spl -gp2spl \
-gradsdes -gradsdes \
-gridarea -gridarea \
-gridboxavg -gridboxavg \
-gridboxmax -gridboxmax \
-gridboxmean -gridboxmean \
-gridboxmin -gridboxmin \
-gridboxstd -gridboxstd \
-gridboxstd1 -gridboxstd1 \
-gridboxsum -gridboxsum \
-gridboxvar -gridboxvar \
-gridboxvar1 -gridboxvar1 \
-griddes -griddes \
-griddes2 -griddes2 \
-griddx -griddx \
-griddy -griddy \
-gridmask -gridmask \
-gridverify -gridverify \
-gridweights -gridweights \
-gt -gt \
-gtc -gtc \
-harmonic -harmonic \
-highpass -highpass \
-histcount -histcount \
-histfreq -histfreq \
-histmean -histmean \
-histsum -histsum \
-houravg -houravg \
-hourcount -hourcount \
-hourmax -hourmax \
-hourmean -hourmean \
-hourmin -hourmin \
-hourpctl -hourpctl \
-hourstd -hourstd \
-hourstd1 -hourstd1 \
-hoursum -hoursum \
-hourvar -hourvar \
-hourvar1 -hourvar1 \
-hpressure -hpressure \
-hurr -hurr \
-ifnotthen -ifnotthen \
-ifnotthenc -ifnotthenc \
-ifthen -ifthen \
-ifthenc -ifthenc \
-ifthenelse -ifthenelse \
-import_amsr -import_amsr \
-import_binary -import_binary \
-import_cmsaf -import_cmsaf \
-import_e5ml -import_e5ml \
-import_e5res -import_e5res \
-import_grads -import_grads \
-import_obs -import_obs \
-imtocomplex -imtocomplex \
-info -info \
-infoc -infoc \
-infon -infon \
-infop -infop \
-infos -infos \
-infov -infov \
-input -input \
-inputext -inputext \
-inputsrv -inputsrv \
-int -int \
-interpolate -interpolate \
-intgrid -intgrid \
-intgridbil -intgridbil \
-intgridcon -intgridcon \
-intgridtraj -intgridtraj \
-intlevel -intlevel \
-intlevel3d -intlevel3d \
-intlevelx -intlevelx \
-intlevelx3d -intlevelx3d \
-intntime -intntime \
-intpoint -intpoint \
-inttime -inttime \
-intyear -intyear \
-invertlat -invertlat \
-invertlatdata -invertlatdata \
-invertlatdes -invertlatdes \
-invertlev -invertlev \
-invertlon -invertlon \
-invertlondata -invertlondata \
-invertlondes -invertlondes \
-isosurface -isosurface \
-le -le \
-lec -lec \
-lmavg -lmavg \
-lmean -lmean \
-lmmean -lmmean \
-lmstd -lmstd \
-ln -ln \
-log -log \
-log10 -log10 \
-lowpass -lowpass \
-lsmean -lsmean \
-lt -lt \
-ltc -ltc \
-map -map \
-mask -mask \
-maskindexbox -maskindexbox \
-masklonlatbox -masklonlatbox \
-maskregion -maskregion \
-mastrfu -mastrfu \
-max -max \
-meandiff2test -meandiff2test \
-meravg -meravg \
-merge -merge \
-mergegrid -mergegrid \
-mergetime -mergetime \
-mermax -mermax \
-mermean -mermean \
-mermin -mermin \
-merpctl -merpctl \
-merstd -merstd \
-merstd1 -merstd1 \
-mersum -mersum \
-mervar -mervar \
-mervar1 -mervar1 \
-min -min \
-ml2hl -ml2hl \
-ml2hl_lp -ml2hl_lp \
-ml2hlx -ml2hlx \
-ml2hlx_lp -ml2hlx_lp \
-ml2pl -ml2pl \
-ml2pl_lp -ml2pl_lp \
-ml2plx -ml2plx \
-ml2plx_lp -ml2plx_lp \
-mod -mod \
-monadd -monadd \
-monavg -monavg \
-moncount -moncount \
-mondiv -mondiv \
-monlogs -monlogs \
-monmax -monmax \
-monmean -monmean \
-monmin -monmin \
-monmul -monmul \
-monpctl -monpctl \
-monstd -monstd \
-monstd1 -monstd1 \
-monsub -monsub \
-monsum -monsum \
-monvar -monvar \
-monvar1 -monvar1 \
-mrotuv -mrotuv \
-mrotuvb -mrotuvb \
-mul -mul \
-mulc -mulc \
-mulcoslat -mulcoslat \
-muldoy -muldoy \
-muldpm -muldpm \
-muldpy -muldpy \
-ncode -ncode \
-ncode -ncode \
-ncopy -ncopy \
-ndate -ndate \
-ne -ne \
-nec -nec \
-nint -nint \
-nlevel -nlevel \
-nmltest -nmltest \
-nmon -nmon \
-normal -normal \
-npar -npar \
-ntime -ntime \
-nvar -nvar \
-nyear -nyear \
-output -output \
-outputarr -outputarr \
-outputbounds -outputbounds \
-outputboundscpt -outputboundscpt \
-outputcenter -outputcenter \
-outputcenter2 -outputcenter2 \
-outputcentercpt -outputcentercpt \
-outputext -outputext \
-outputf -outputf \
-outputfld -outputfld \
-outputint -outputint \
-outputkey -outputkey \
-outputsrv -outputsrv \
-outputtab -outputtab \
-outputtri -outputtri \
-outputts -outputts \
-outputvector -outputvector \
-outputvrml -outputvrml \
-outputxyz -outputxyz \
-pack -pack \
-pardes -pardes \
-pardup -pardup \
-parmul -parmul \
-partab -partab \
-partab2 -partab2 \
-pinfo -pinfo \
-pinfov -pinfov \
-pow -pow \
-pressure_fl -pressure_fl \
-pressure_hl -pressure_hl \
-random -random \
-read_cmor_table -read_cmor_table \
-read_e5ml -read_e5ml \
-reci -reci \
-regres -regres \
-remap -remap \
-remapbic -remapbic \
-remapbil -remapbil \
-remapcon -remapcon \
-remapcon1 -remapcon1 \
-remapcon2 -remapcon2 \
-remapdis -remapdis \
-remapdis1 -remapdis1 \
-remapeta -remapeta \
-remapeta_s -remapeta_s \
-remapeta_z -remapeta_z \
-remaplaf -remaplaf \
-remapnn -remapnn \
-remapsum -remapsum \
-remapycon -remapycon \
-replace -replace \
-retocomplex -retocomplex \
-rhopot -rhopot \
-rotuvb -rotuvb \
-runavg -runavg \
-runmax -runmax \
-runmean -runmean \
-runmin -runmin \
-runpctl -runpctl \
-runstd -runstd \
-runstd1 -runstd1 \
-runsum -runsum \
-runvar -runvar \
-runvar1 -runvar1 \
-scalllogo -scalllogo \
-scatter -scatter \
-sealevelpressure -sealevelpressure \
-seasavg -seasavg \
-seascount -seascount \
-seasmax -seasmax \
-seasmean -seasmean \
-seasmin -seasmin \
-seaspctl -seaspctl \
-seasstd -seasstd \
-seasstd1 -seasstd1 \
-seassum -seassum \
-seasvar -seasvar \
-seasvar1 -seasvar1 \
-seinfo -seinfo \
-seinfoc -seinfoc \
-seinfon -seinfon \
-seinfop -seinfop \
-selall -selall \
-selcode -selcode \
-seldate -seldate \
-selday -selday \
-select -select \
-selgrid -selgrid \
-selgridname -selgridname \
-selhour -selhour \
-selindexbox -selindexbox \
-sellevel -sellevel \
-sellevidx -sellevidx \
-sellonlatbox -sellonlatbox \
-selltype -selltype \
-selmon -selmon \
-selname -selname \
-seloperator -seloperator \
-selparam -selparam \
-selrec -selrec \
-selseas -selseas \
-selsmon -selsmon \
-selstdname -selstdname \
-seltabnum -seltabnum \
-seltime -seltime \
-seltimestep -seltimestep \
-selvar -selvar \
-selyear -selyear \
-selzaxis -selzaxis \
-selzaxisname -selzaxisname \
-setcalendar -setcalendar \
-setcindexbox -setcindexbox \
-setclonlatbox -setclonlatbox \
-setcode -setcode \
-setctomiss -setctomiss \
-setdate -setdate \
-setday -setday \
-setgatt -setgatt \
-setgatts -setgatts \
-setgrid -setgrid \
-setgridarea -setgridarea \
-setgridmask -setgridmask \
-setgridnumber -setgridnumber \
-setgridtype -setgridtype \
-setgriduri -setgriduri \
-sethalo -sethalo \
-setlevel -setlevel \
-setltype -setltype \
-setmisstoc -setmisstoc \
-setmisstodis -setmisstodis \
-setmisstonn -setmisstonn \
-setmissval -setmissval \
-setmon -setmon \
-setname -setname \
-setparam -setparam \
-setpartab -setpartab \
-setpartabc -setpartabc \
-setpartabn -setpartabn \
-setpartabp -setpartabp \
-setpartabv -setpartabv \
-setrcaname -setrcaname \
-setreftime -setreftime \
-setrtoc -setrtoc \
-setrtoc2 -setrtoc2 \
-setrtomiss -setrtomiss \
-settabnum -settabnum \
-settaxis -settaxis \
-settime -settime \
-settunits -settunits \
-setunit -setunit \
-setvals -setvals \
-setvar -setvar \
-setvrange -setvrange \
-setyear -setyear \
-setzaxis -setzaxis \
-shifttime -shifttime \
-showcode -showcode \
-showdate -showdate \
-showformat -showformat \
-showlevel -showlevel \
-showltype -showltype \
-showmon -showmon \
-showname -showname \
-showparam -showparam \
-showstdname -showstdname \
-showtime -showtime \
-showtimestamp -showtimestamp \
-showunit -showunit \
-showvar -showvar \
-showyear -showyear \
-sin -sin \
-sincos -sincos \
-sinfo -sinfo \
-sinfoc -sinfoc \
-sinfon -sinfon \
-sinfop -sinfop \
-sinfov -sinfov \
-smemlogo -smemlogo \
-smooth9 -smooth9 \
-snamelogo -snamelogo \
-sort -sort \
-sortcode -sortcode \
-sortlevel -sortlevel \
-sortname -sortname \
-sortparam -sortparam \
-sorttaxis -sorttaxis \
-sorttimestamp -sorttimestamp \
-sortvar -sortvar \
-sp2fc -sp2fc \
-sp2gp -sp2gp \
-sp2gpl -sp2gpl \
-sp2sp -sp2sp \
-spartab -spartab \
-spcut -spcut \
-specinfo -specinfo \
-spectrum -spectrum \
-sperclogo -sperclogo \
-splitcode -splitcode \
-splitday -splitday \
-splitgrid -splitgrid \
-splithour -splithour \
-splitlevel -splitlevel \
-splitmon -splitmon \
-splitname -splitname \
-splitparam -splitparam \
-splitrec -splitrec \
-splitseas -splitseas \
-splitsel -splitsel \
-splittabnum -splittabnum \
-splitvar -splitvar \
-splityear -splityear \
-splityearmon -splityearmon \
-splitzaxis -splitzaxis \
-sqr -sqr \
-sqrt -sqrt \
-ssopar -ssopar \
-stdatm -stdatm \
-stimelogo -stimelogo \
-strbre -strbre \
-strgal -strgal \
-strwin -strwin \
-studentt -studentt \
-sub -sub \
-subc -subc \
-subtrend -subtrend \
-szip -szip \
-tan -tan \
-tee -tee \
-temp -temp \
-template1 -template1 \
-template2 -template2 \
-test -test \
-test2 -test2 \
-testcellsearch -testcellsearch \
-testdata -testdata \
-testpointsearch -testpointsearch \
-thinout -thinout \
-timavg -timavg \
-timcor -timcor \
-timcount -timcount \
-timcovar -timcovar \
-timmax -timmax \
-timmean -timmean \
-timmin -timmin \
-timpctl -timpctl \
-timselavg -timselavg \
-timselmax -timselmax \
-timselmean -timselmean \
-timselmin -timselmin \
-timselpctl -timselpctl \
-timselstd -timselstd \
-timselstd1 -timselstd1 \
-timselsum -timselsum \
-timselvar -timselvar \
-timselvar1 -timselvar1 \
-timsort -timsort \
-timstd -timstd \
-timstd1 -timstd1 \
-timsum -timsum \
-timvar -timvar \
-timvar1 -timvar1 \
-tinfo -tinfo \
-topo -topo \
-tpnhalo -tpnhalo \
-transxy -transxy \
-trend -trend \
-trms -trms \
-tstepcount -tstepcount \
-unsetgridmask -unsetgridmask \
-uv2dv -uv2dv \
-uv2dvl -uv2dvl \
-vardes -vardes \
-vardup -vardup \
-varmul -varmul \
-varquot2test -varquot2test \
-varrms -varrms \
-vct -vct \
-vct2 -vct2 \
-vertavg -vertavg \
-vertcum -vertcum \
-vertcumhl -vertcumhl \
-vertint -vertint \
-vertmax -vertmax \
-vertmean -vertmean \
-vertmin -vertmin \
-vertstd -vertstd \
-vertstd1 -vertstd1 \
-vertsum -vertsum \
-vertvar -vertvar \
-vertvar1 -vertvar1 \
-vertwind -vertwind \
-vlist -vlist \
-wct -wct \
-write_e5ml -write_e5ml \
-writegrid -writegrid \
-writerandom -writerandom \
-xmonavg -xmonavg \
-xmonmax -xmonmax \
-xmonmean -xmonmean \
-xmonmin -xmonmin \
-xmonstd -xmonstd \
-xmonstd1 -xmonstd1 \
-xmonsum -xmonsum \
-xmonvar -xmonvar \
-xmonvar1 -xmonvar1 \
-xtimavg -xtimavg \
-xtimmax -xtimmax \
-xtimmean -xtimmean \
-xtimmin -xtimmin \
-xtimstd -xtimstd \
-xtimstd1 -xtimstd1 \
-xtimsum -xtimsum \
-xtimvar -xtimvar \
-xtimvar1 -xtimvar1 \
-xyearavg -xyearavg \
-xyearmax -xyearmax \
-xyearmean -xyearmean \
-xyearmin -xyearmin \
-xyearstd -xyearstd \
-xyearstd1 -xyearstd1 \
-xyearsum -xyearsum \
-xyearvar -xyearvar \
-xyearvar1 -xyearvar1 \
-yarbil -yarbil \
-yarcon -yarcon \
-yarnn -yarnn \
-ydayadd -ydayadd \
-ydayavg -ydayavg \
-ydaydiv -ydaydiv \
-ydaymax -ydaymax \
-ydaymean -ydaymean \
-ydaymin -ydaymin \
-ydaymul -ydaymul \
-ydaypctl -ydaypctl \
-ydaystd -ydaystd \
-ydaystd1 -ydaystd1 \
-ydaysub -ydaysub \
-ydaysum -ydaysum \
-ydayvar -ydayvar \
-ydayvar1 -ydayvar1 \
-ydrunavg -ydrunavg \
-ydrunmax -ydrunmax \
-ydrunmean -ydrunmean \
-ydrunmin -ydrunmin \
-ydrunpctl -ydrunpctl \
-ydrunstd -ydrunstd \
-ydrunstd1 -ydrunstd1 \
-ydrunsum -ydrunsum \
-ydrunvar -ydrunvar \
-ydrunvar1 -ydrunvar1 \
-yearavg -yearavg \
-yearcount -yearcount \
-yearmax -yearmax \
-yearmean -yearmean \
-yearmin -yearmin \
-yearmonavg -yearmonavg \
-yearmonmean -yearmonmean \
-yearpctl -yearpctl \
-yearstd -yearstd \
-yearstd1 -yearstd1 \
-yearsum -yearsum \
-yearvar -yearvar \
-yearvar1 -yearvar1 \
-yhouradd -yhouradd \
-yhouravg -yhouravg \
-yhourdiv -yhourdiv \
-yhourmax -yhourmax \
-yhourmean -yhourmean \
-yhourmin -yhourmin \
-yhourmul -yhourmul \
-yhourstd -yhourstd \
-yhourstd1 -yhourstd1 \
-yhoursub -yhoursub \
-yhoursum -yhoursum \
-yhourvar -yhourvar \
-yhourvar1 -yhourvar1 \
-ymonadd -ymonadd \
-ymonavg -ymonavg \
-ymondiv -ymondiv \
-ymonmax -ymonmax \
-ymonmean -ymonmean \
-ymonmin -ymonmin \
-ymonmul -ymonmul \
-ymonpctl -ymonpctl \
-ymonstd -ymonstd \
-ymonstd1 -ymonstd1 \
-ymonsub -ymonsub \
-ymonsum -ymonsum \
-ymonvar -ymonvar \
-ymonvar1 -ymonvar1 \
-yseasadd -yseasadd \
-yseasavg -yseasavg \
-yseasdiv -yseasdiv \
-yseasmax -yseasmax \
-yseasmean -yseasmean \
-yseasmin -yseasmin \
-yseasmul -yseasmul \
-yseaspctl -yseaspctl \
-yseasstd -yseasstd \
-yseasstd1 -yseasstd1 \
-yseassub -yseassub \
-yseassum -yseassum \
-yseasvar -yseasvar \
-yseasvar1 -yseasvar1 \
-zaxisdes -zaxisdes \
-zonavg -zonavg \
-zonmax -zonmax \
-zonmean -zonmean \
-zonmin -zonmin \
-zonpctl -zonpctl \
-zonrange -zonrange \
-zonstd -zonstd \
-zonstd1 -zonstd1 \
-zonsum -zonsum \
-zonvar -zonvar \
-zonvar1 -zonvar1 \
+list -list \
+of -of \
+operators. -operators. \
+option -option \
)" -f cdo
diff --git a/doc/cdo.pdf b/doc/cdo.pdf
index 8310717..f8d2ff9 100644
Binary files a/doc/cdo.pdf and b/doc/cdo.pdf differ
diff --git a/doc/cdo_eca.pdf b/doc/cdo_eca.pdf
index 99ff09e..d4cc2d5 100644
Binary files a/doc/cdo_eca.pdf and b/doc/cdo_eca.pdf differ
diff --git a/doc/cdo_magics.pdf b/doc/cdo_magics.pdf
new file mode 100644
index 0000000..0a19605
Binary files /dev/null and b/doc/cdo_magics.pdf differ
diff --git a/doc/cdo_refcard.pdf b/doc/cdo_refcard.pdf
index acd98c9..2115cf3 100644
Binary files a/doc/cdo_refcard.pdf and b/doc/cdo_refcard.pdf differ
diff --git a/libcdi/ChangeLog b/libcdi/ChangeLog
index 01c8edf..bbc83d6 100644
--- a/libcdi/ChangeLog
+++ b/libcdi/ChangeLog
@@ -1,3 +1,40 @@
+2016-02-19 Uwe Schulzweida
+
+ * Version 1.7.1 released
+ * using CGRIBEX library version 1.7.4
+
+2016-02-05 Uwe Schulzweida
+
+ * timeval2vtime: set vtime=rtime if timevalue=0 [Bug: #6496]
+
+2015-12-23 Uwe Schulzweida
+
+ * ZAXIS_HEIGHT: added support for units cm, dm and km
+
+2015-12-19 Uwe Schulzweida
+
+ * gribapiDecode internal problem when processing 1x1 GRIB2 data with JPEG compression [Bug #6402]
+
+2015-12-10 Uwe Schulzweida
+
+ * gridGenYvals: bug fix [Bug #6373]
+
+2015-11-25 Uwe Schulzweida
+
+ * cdfDefXaxis/cdfDefXaxis: generate bounds for CDI_cmor_mode
+
+2015-11-23 Nathanael Huebbe
+
+ * replaced the vlist locked flag by two other flags
+
+2015-11-17 Uwe Schulzweida
+
+ * cdfCopyRecord: use MEMTYPE_FLOAT for DATATYPE_FLT32
+
+2015-11-04 Uwe Schulzweida
+
+ * tableRead: name is not interpreted correctly (bug introduced in 1.7.0 #3933)
+
2015-10-27 Uwe Schulzweida
* Version 1.7.0 released
diff --git a/libcdi/app/cdi.c b/libcdi/app/cdi.c
index eeee339..8b32c5a 100644
--- a/libcdi/app/cdi.c
+++ b/libcdi/app/cdi.c
@@ -12,6 +12,8 @@
#include <math.h>
#include <cdi.h>
+#include <cdi_uuid.h>
+
int vlistInqVarMissvalUsed(int vlistID, int varID);
#ifndef DBL_IS_NAN
#if defined (HAVE_DECL_ISNAN)
@@ -44,7 +46,13 @@ static const uint32_t HOST_ENDIANNESS_temp[1] = { UINT32_C(0x00030201) };
#include "printinfo.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
void cdiDefTableID(int tableID);
+#if defined (__cplusplus)
+}
+#endif
int getopt(int argc, char *const argv[], const char *optstring);
@@ -61,6 +69,8 @@ static int DefaultByteorder = CDI_UNDEFID;
static int comptype = COMPRESS_NONE; // Compression type
static int complevel = 0; // Compression level
+enum datamode {SP_MODE, DP_MODE};
+static int datamode = DP_MODE;
static
void version(void)
@@ -749,7 +759,7 @@ int main(int argc, char *argv[])
if (Progname == 0) Progname = argv[0];
else Progname++;
- while ( (c = getopt(argc, argv, "b:f:t:w:z:cdhlMmqRrsvVZ")) != EOF )
+ while ( (c = getopt(argc, argv, "b:f:t:w:z:cdhlMmqRrsvVxZ")) != EOF )
{
switch (c)
{
@@ -798,6 +808,9 @@ int main(int argc, char *argv[])
case 'w':
wTable = optarg;
break;
+ case 'x':
+ datamode = SP_MODE;
+ break;
case 'z':
defineCompress(optarg);
break;
@@ -925,8 +938,7 @@ int main(int argc, char *argv[])
nts = cdiInqTimeSize(streamID1);
*/
if (Debug)
- printf("nts = %d\n"
- "streamID1 = %d, streamID2 = %d\n",
+ printf("nts = %d streamID1 = %d, streamID2 = %d\n",
nts, streamID1, streamID2);
if ( Shortinfo )
diff --git a/libcdi/app/createtable.c b/libcdi/app/createtable.c
index 3a32019..29377bf 100644
--- a/libcdi/app/createtable.c
+++ b/libcdi/app/createtable.c
@@ -64,7 +64,6 @@ int main(int argc, char *argv[])
usage();
fprintf(stderr, "illegal option %s\n", cstring);
return EXIT_FAILURE;
- break;
}
}
diff --git a/libcdi/app/printinfo.h b/libcdi/app/printinfo.h
index c68c2ec..fe64df6 100644
--- a/libcdi/app/printinfo.h
+++ b/libcdi/app/printinfo.h
@@ -3,18 +3,6 @@
#define DATE_FORMAT "%5.4d-%2.2d-%2.2d"
#define TIME_FORMAT "%2.2d:%2.2d:%2.2d"
-void uuid2str(const unsigned char uuid[CDI_UUID_SIZE], char *uuidstr);
-
-static inline
-int cdiUUIDIsNull(const unsigned char uuid[CDI_UUID_SIZE])
-{
- int isNull = 1;
- for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
- isNull &= (uuid[i] == 0);
- return isNull;
-}
-
-
void datetime2str(int date, int time, char *datetimestr, int maxlen)
{
int year, month, day;
@@ -385,7 +373,7 @@ void printGridInfo(int vlistID)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
{
fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr);
@@ -502,7 +490,7 @@ void printZaxisInfo(int vlistID)
if ( !cdiUUIDIsNull(uuidOfVGrid) )
{
char uuidOfVGridStr[37];
- uuid2str(uuidOfVGrid, uuidOfVGridStr);
+ cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
{
fprintf(stdout, "%33s : ", "uuid");
diff --git a/libcdi/configure b/libcdi/configure
index b56dc78..ff3c62a 100755
--- a/libcdi/configure
+++ b/libcdi/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for cdi 1.7.0.
+# Generated by GNU Autoconf 2.68 for cdi 1.7.1.
#
# Report bugs to <http://mpimet.mpg.de/cdi>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cdi'
PACKAGE_TARNAME='cdi'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='cdi 1.7.0'
+PACKAGE_VERSION='1.7.1'
+PACKAGE_STRING='cdi 1.7.1'
PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdi'
PACKAGE_URL=''
@@ -1473,7 +1473,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures cdi 1.7.0 to adapt to many kinds of systems.
+\`configure' configures cdi 1.7.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1543,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of cdi 1.7.0:";;
+ short | recursive ) echo "Configuration of cdi 1.7.1:";;
esac
cat <<\_ACEOF
@@ -1752,7 +1752,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-cdi configure 1.7.0
+cdi configure 1.7.1
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2597,7 +2597,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by cdi $as_me 1.7.0, which was
+It was created by cdi $as_me 1.7.1, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -3549,7 +3549,7 @@ fi
# Define the identity of the package.
PACKAGE='cdi'
- VERSION='1.7.0'
+ VERSION='1.7.1'
cat >>confdefs.h <<_ACEOF
@@ -23418,7 +23418,7 @@ Usage: $0 [OPTIONS]
Report bugs to <bug-libtool at gnu.org>."
lt_cl_version="\
-cdi config.lt 1.7.0
+cdi config.lt 1.7.1
configured by $0, generated by GNU Autoconf 2.68.
Copyright (C) 2011 Free Software Foundation, Inc.
@@ -26087,18 +26087,143 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-#
-# Check for non-standard builtin
-ac_fn_c_check_decl "$LINENO" "__builtin_ctz" "ac_cv_have_decl___builtin_ctz" "$ac_includes_default"
-if test "x$ac_cv_have_decl___builtin_ctz" = xyes; then :
+# check for sysconf names
+ac_fn_c_check_decl "$LINENO" "_SC_LARGE_PAGESIZE" "ac_cv_have_decl__SC_LARGE_PAGESIZE" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl__SC_LARGE_PAGESIZE" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL___BUILTIN_CTZ $ac_have_decl
+#define HAVE_DECL__SC_LARGE_PAGESIZE $ac_have_decl
_ACEOF
+ac_fn_c_check_decl "$LINENO" "PAGESIZE" "ac_cv_have_decl_PAGESIZE" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl_PAGESIZE" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_PAGESIZE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "PAGE_SIZE" "ac_cv_have_decl_PAGE_SIZE" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl_PAGE_SIZE" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_PAGE_SIZE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_SC_PAGE_SIZE" "ac_cv_have_decl__SC_PAGE_SIZE" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl__SC_PAGE_SIZE" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__SC_PAGE_SIZE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_SC_PAGESIZE" "ac_cv_have_decl__SC_PAGESIZE" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl__SC_PAGESIZE" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__SC_PAGESIZE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_PC_REC_XFER_ALIGN" "ac_cv_have_decl__PC_REC_XFER_ALIGN" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl__PC_REC_XFER_ALIGN" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__PC_REC_XFER_ALIGN $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "POSIX_REC_XFER_ALIGN" "ac_cv_have_decl_POSIX_REC_XFER_ALIGN" "$ac_includes_default
+#include <limits.h>
+#include <unistd.h>
+"
+if test "x$ac_cv_have_decl_POSIX_REC_XFER_ALIGN" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_POSIX_REC_XFER_ALIGN $ac_have_decl
+_ACEOF
+
+#
+# Check for non-standard builtin
+for builtin in __builtin_ctz
+do :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __builtin_ctz is declared" >&5
+$as_echo_n "checking whether __builtin_ctz is declared... " >&6; }
+if ${acx_cv_have_decl___builtin_ctz+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+ unsigned lbz = __builtin_ctz(56U)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ acx_cv_have_decl___builtin_ctz=yes
+else
+ acx_cv_have_decl___builtin_ctz=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_have_decl___builtin_ctz" >&5
+$as_echo "$acx_cv_have_decl___builtin_ctz" >&6; }
+ if test "x$acx_cv_have_decl___builtin_ctz" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL___BUILTIN_CTZ 1
+_ACEOF
+
+ break
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL___BUILTIN_CTZ 0
+_ACEOF
+
+fi
+done
# Check compiler version
@@ -29440,98 +29565,6 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPI launch command unavailable" >&5
$as_echo "$as_me: WARNING: MPI launch command unavailable" >&2;}
fi
- ac_fn_c_check_decl "$LINENO" "_SC_LARGE_PAGESIZE" "ac_cv_have_decl__SC_LARGE_PAGESIZE" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl__SC_LARGE_PAGESIZE" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__SC_LARGE_PAGESIZE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "PAGESIZE" "ac_cv_have_decl_PAGESIZE" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl_PAGESIZE" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_PAGESIZE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "PAGE_SIZE" "ac_cv_have_decl_PAGE_SIZE" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl_PAGE_SIZE" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_PAGE_SIZE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "_SC_PAGE_SIZE" "ac_cv_have_decl__SC_PAGE_SIZE" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl__SC_PAGE_SIZE" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__SC_PAGE_SIZE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "_SC_PAGESIZE" "ac_cv_have_decl__SC_PAGESIZE" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl__SC_PAGESIZE" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__SC_PAGESIZE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "_PC_REC_XFER_ALIGN" "ac_cv_have_decl__PC_REC_XFER_ALIGN" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl__PC_REC_XFER_ALIGN" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL__PC_REC_XFER_ALIGN $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "POSIX_REC_XFER_ALIGN" "ac_cv_have_decl_POSIX_REC_XFER_ALIGN" "$ac_includes_default
-#include <limits.h>
-#include <unistd.h>
-"
-if test "x$ac_cv_have_decl_POSIX_REC_XFER_ALIGN" = xyes; then :
- ac_have_decl=1
-else
- ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_POSIX_REC_XFER_ALIGN $ac_have_decl
-_ACEOF
-
pkg_failed=no
@@ -31428,7 +31461,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by cdi $as_me 1.7.0, which was
+This file was extended by cdi $as_me 1.7.1, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -31494,7 +31527,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-cdi config.status 1.7.0
+cdi config.status 1.7.1
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/libcdi/configure.ac b/libcdi/configure.ac
index d95aa34..c6ed99b 100644
--- a/libcdi/configure.ac
+++ b/libcdi/configure.ac
@@ -4,7 +4,7 @@
# autoconf 2.68
# libtool 2.4.2
-AC_INIT([cdi], [1.7.0], [http://mpimet.mpg.de/cdi])
+AC_INIT([cdi], [1.7.1], [http://mpimet.mpg.de/cdi])
AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
@@ -85,9 +85,26 @@ AC_SUBST([UUID_C_LIB])
AC_CHECK_DECLS([isnan],,,[AC_INCLUDES_DEFAULT
@%:@include <math.h>])
+# check for sysconf names
+AC_CHECK_DECLS([_SC_LARGE_PAGESIZE, PAGESIZE, PAGE_SIZE, _SC_PAGE_SIZE, dnl
+_SC_PAGESIZE, _PC_REC_XFER_ALIGN, POSIX_REC_XFER_ALIGN],,,[AC_INCLUDES_DEFAULT
+@%:@include <limits.h>
+@%:@include <unistd.h>])
#
# Check for non-standard builtin
-AC_CHECK_DECLS([__builtin_ctz])
+AS_FOR([builtin_macro],[builtin],[__builtin_ctz],
+ [AS_VAR_PUSHDEF([builtin_cache],[acx_cv_have_decl_]builtin_macro)
+ AC_CACHE_CHECK([whether ]builtin_macro[ is declared],
+ [builtin_cache],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM(,[ unsigned lbz = builtin_macro][[(56U)]])],
+ [AS_VAR_SET([builtin_cache],[yes])],
+ [AS_VAR_SET([builtin_cache],[no])])])
+ AS_VAR_IF([builtin_cache],[yes],
+ [AC_DEFINE_UNQUOTED([HAVE_DECL_]AS_TR_CPP([builtin_macro]),[1])
+ break],
+ [AC_DEFINE_UNQUOTED([HAVE_DECL_]AS_TR_CPP([builtin_macro]),[0])])])
+AH_TEMPLATE([HAVE_DECL___BUILTIN_CTZ],
+ [Define to 1 if __builtin_ctz is available, 0 if not])
# Check compiler version
case "$CC" in
@@ -195,10 +212,6 @@ main(int argc, char **argv)
])
AS_IF([test "x$MPI_LAUNCH" = xtrue],
[AC_MSG_WARN([MPI launch command unavailable])])
- AC_CHECK_DECLS([_SC_LARGE_PAGESIZE, PAGESIZE, PAGE_SIZE, _SC_PAGE_SIZE, dnl
-_SC_PAGESIZE, _PC_REC_XFER_ALIGN, POSIX_REC_XFER_ALIGN],,,[AC_INCLUDES_DEFAULT
-@%:@include <limits.h>
-@%:@include <unistd.h>])
PKG_CHECK_MODULES([YAXT],[yaxt],
[AC_DEFINE([HAVE_YAXT],,[yaxt library is available])],
diff --git a/libcdi/doc/cdi_cman.pdf b/libcdi/doc/cdi_cman.pdf
index 20571a0..5334413 100644
Binary files a/libcdi/doc/cdi_cman.pdf and b/libcdi/doc/cdi_cman.pdf differ
diff --git a/libcdi/doc/cdi_fman.pdf b/libcdi/doc/cdi_fman.pdf
index 0e2f0af..2941678 100644
Binary files a/libcdi/doc/cdi_fman.pdf and b/libcdi/doc/cdi_fman.pdf differ
diff --git a/libcdi/interfaces/cdi.hpp b/libcdi/interfaces/cdi.hpp
index 96bdbb0..4c6fb88 100644
--- a/libcdi/interfaces/cdi.hpp
+++ b/libcdi/interfaces/cdi.hpp
@@ -14,7 +14,7 @@ class CdiGrid {
bool hasXValues, hasYValues, hasBounds;
std::vector<double> xvalues, yvalues, xbounds, ybounds;
-
+ // [xy]stdname cannot be set arbitrarily
std::string xname, xlongname, xstdname, xunits;
std::string yname, ylongname, ystdname, yunits;
std::string name;
diff --git a/libcdi/src/Makefile.am b/libcdi/src/Makefile.am
index b00051d..eb933b6 100644
--- a/libcdi/src/Makefile.am
+++ b/libcdi/src/Makefile.am
@@ -37,7 +37,7 @@ libcdi_la_SOURCES = \
cksum.h \
cdi_cksum.c \
cdi_cksum.h \
- create_uuid.h \
+ cdi_uuid.h \
dtypes.h \
error.c \
error.h \
@@ -55,8 +55,8 @@ libcdi_la_SOURCES = \
grid.h \
ieg.h \
ieglib.c \
- input_file.c \
- input_file.h \
+ input_file.c \
+ input_file.h \
institution.c \
institution.h \
model.c \
@@ -79,7 +79,6 @@ libcdi_la_SOURCES = \
stream_ext.h \
stream_grb.c \
stream_grb.h \
- stream_gribapi.c \
stream_gribapi.h \
stream_history.c \
stream_ieg.c \
@@ -92,6 +91,10 @@ libcdi_la_SOURCES = \
stream_srv.c \
stream_srv.h \
stream_var.c \
+ grb_write.c \
+ grb_read.c \
+ cdf_write.c \
+ cdf_read.c \
subtype.c \
subtype.h \
swap.h \
@@ -116,7 +119,9 @@ libcdi_la_SOURCES = \
zaxis.c \
zaxis.h \
stream.c \
- swap.c \
+ stream_write.c \
+ stream_read.c \
+ swap.c \
iterator.c \
iterator.h \
iterator_fallback.c \
@@ -131,7 +136,7 @@ libcdi_la_USE_FC_extra_sources = \
# these only contain code iff grib_api is available
libcdi_la_HAVE_LIBGRIB_API_extra_sources = \
- gribapi_utilities.c
+ gribapi_utilities.c stream_gribapi.c
if USE_FC
libcdi_la_SOURCES += \
diff --git a/libcdi/src/Makefile.in b/libcdi/src/Makefile.in
index 3d93ab7..ab7d81c 100644
--- a/libcdi/src/Makefile.in
+++ b/libcdi/src/Makefile.in
@@ -171,28 +171,29 @@ am__libcdi_la_SOURCES_DIST = basetime.c basetime.h binary.c binary.h \
calendar.c calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h \
cdi_error.c cdi_limits.h cdi_util.c cgribex.h cgribexlib.c \
datetime.h dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c \
- cdi_cksum.h create_uuid.h dtypes.h error.c error.h exse.h \
- extra.h extralib.c file.c file.h gaussgrid.c gaussgrid.h \
- gribapi.c gribapi.h gribapi_utilities.h grid.c grid.h ieg.h \
- ieglib.c input_file.c input_file.h institution.c institution.h \
- model.c model.h namespace.c namespace.h serialize.h \
- serialize.c referenceCounting.c referenceCounting.h \
- resource_handle.c resource_handle.h service.h servicelib.c \
- stream_cdf.c stream_cdf.h stream_cgribex.c stream_cgribex.h \
- stream_ext.c stream_ext.h stream_grb.c stream_grb.h \
- stream_gribapi.c stream_gribapi.h stream_history.c \
- stream_ieg.c stream_ieg.h stream_fcommon.c stream_fcommon.h \
- cdi_int.c cdi_int.h stream_record.c stream_srv.c stream_srv.h \
- stream_var.c subtype.c subtype.h swap.h table.c table.h \
- tablepar.h taxis.c taxis.h timebase.c timebase.h tsteps.c \
- util.c varscan.c varscan.h version.c vlist.c vlist.h \
+ cdi_cksum.h cdi_uuid.h dtypes.h error.c error.h exse.h extra.h \
+ extralib.c file.c file.h gaussgrid.c gaussgrid.h gribapi.c \
+ gribapi.h gribapi_utilities.h grid.c grid.h ieg.h ieglib.c \
+ input_file.c input_file.h institution.c institution.h model.c \
+ model.h namespace.c namespace.h serialize.h serialize.c \
+ referenceCounting.c referenceCounting.h resource_handle.c \
+ resource_handle.h service.h servicelib.c stream_cdf.c \
+ stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \
+ stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \
+ stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \
+ stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \
+ stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \
+ cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \
+ table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \
+ tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \
vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \
- zaxis.h stream.c swap.c iterator.c iterator.h \
- iterator_fallback.c iterator_fallback.h iterator_grib.c \
- iterator_grib.h cfortran.h cdiFortran.c gribapi_utilities.c
+ zaxis.h stream.c stream_write.c stream_read.c swap.c \
+ iterator.c iterator.h iterator_fallback.c iterator_fallback.h \
+ iterator_grib.c iterator_grib.h cfortran.h cdiFortran.c \
+ gribapi_utilities.c stream_gribapi.c
am__objects_1 = cdiFortran.lo
@USE_FC_TRUE at am__objects_2 = $(am__objects_1)
-am__objects_3 = gribapi_utilities.lo
+am__objects_3 = gribapi_utilities.lo stream_gribapi.lo
@HAVE_LIBGRIB_API_TRUE at am__objects_4 = $(am__objects_3)
am_libcdi_la_OBJECTS = basetime.lo binary.lo calendar.lo cdf.lo \
cdf_int.lo cdi_error.lo cdi_util.lo cgribexlib.lo dmemory.lo \
@@ -201,11 +202,12 @@ am_libcdi_la_OBJECTS = basetime.lo binary.lo calendar.lo cdf.lo \
institution.lo model.lo namespace.lo serialize.lo \
referenceCounting.lo resource_handle.lo servicelib.lo \
stream_cdf.lo stream_cgribex.lo stream_ext.lo stream_grb.lo \
- stream_gribapi.lo stream_history.lo stream_ieg.lo \
- stream_fcommon.lo cdi_int.lo stream_record.lo stream_srv.lo \
- stream_var.lo subtype.lo table.lo taxis.lo timebase.lo \
- tsteps.lo util.lo varscan.lo version.lo vlist.lo vlist_att.lo \
- vlist_var.lo zaxis.lo stream.lo swap.lo iterator.lo \
+ stream_history.lo stream_ieg.lo stream_fcommon.lo cdi_int.lo \
+ stream_record.lo stream_srv.lo stream_var.lo grb_write.lo \
+ grb_read.lo cdf_write.lo cdf_read.lo subtype.lo table.lo \
+ taxis.lo timebase.lo tsteps.lo util.lo varscan.lo version.lo \
+ vlist.lo vlist_att.lo vlist_var.lo zaxis.lo stream.lo \
+ stream_write.lo stream_read.lo swap.lo iterator.lo \
iterator_fallback.lo iterator_grib.lo $(am__objects_2) \
$(am__objects_4)
libcdi_la_OBJECTS = $(am_libcdi_la_OBJECTS)
@@ -516,22 +518,23 @@ libcdi_la_SOURCES = basetime.c basetime.h binary.c binary.h calendar.c \
calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h cdi_error.c \
cdi_limits.h cdi_util.c cgribex.h cgribexlib.c datetime.h \
dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c cdi_cksum.h \
- create_uuid.h dtypes.h error.c error.h exse.h extra.h \
- extralib.c file.c file.h gaussgrid.c gaussgrid.h gribapi.c \
- gribapi.h gribapi_utilities.h grid.c grid.h ieg.h ieglib.c \
- input_file.c input_file.h institution.c institution.h model.c \
- model.h namespace.c namespace.h serialize.h serialize.c \
+ cdi_uuid.h dtypes.h error.c error.h exse.h extra.h extralib.c \
+ file.c file.h gaussgrid.c gaussgrid.h gribapi.c gribapi.h \
+ gribapi_utilities.h grid.c grid.h ieg.h ieglib.c input_file.c \
+ input_file.h institution.c institution.h model.c model.h \
+ namespace.c namespace.h serialize.h serialize.c \
referenceCounting.c referenceCounting.h resource_handle.c \
resource_handle.h service.h servicelib.c stream_cdf.c \
stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \
- stream_ext.h stream_grb.c stream_grb.h stream_gribapi.c \
- stream_gribapi.h stream_history.c stream_ieg.c stream_ieg.h \
- stream_fcommon.c stream_fcommon.h cdi_int.c cdi_int.h \
- stream_record.c stream_srv.c stream_srv.h stream_var.c \
- subtype.c subtype.h swap.h table.c table.h tablepar.h taxis.c \
- taxis.h timebase.c timebase.h tsteps.c util.c varscan.c \
- varscan.h version.c vlist.c vlist.h vlist_att.c vlist_att.h \
- vlist_var.c vlist_var.h zaxis.c zaxis.h stream.c swap.c \
+ stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \
+ stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \
+ stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \
+ stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \
+ cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \
+ table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \
+ tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \
+ vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \
+ zaxis.h stream.c stream_write.c stream_read.c swap.c \
iterator.c iterator.h iterator_fallback.c iterator_fallback.h \
iterator_grib.c iterator_grib.h $(am__append_2) \
$(am__append_3)
@@ -544,7 +547,7 @@ libcdi_la_USE_FC_extra_sources = \
# these only contain code iff grib_api is available
libcdi_la_HAVE_LIBGRIB_API_extra_sources = \
- gribapi_utilities.c
+ gribapi_utilities.c stream_gribapi.c
libcdiresunpack_la_SOURCES = \
resource_unpack.c
@@ -693,6 +696,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/calendar.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdf.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdf_int.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdf_read.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdf_write.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdiFortran.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdi_cksum.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdi_error.Plo at am__quote@
@@ -706,6 +711,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/extralib.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/file.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gaussgrid.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/grb_read.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/grb_write.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gribapi.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gribapi_utilities.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/grid.Plo at am__quote@
@@ -752,9 +759,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_gribapi.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_history.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_ieg.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_read.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_record.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_srv.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_var.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stream_write.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/subtype.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/swap.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/table.Plo at am__quote@
diff --git a/libcdi/src/basetime.c b/libcdi/src/basetime.c
index 5d0efba..3d4d5e3 100644
--- a/libcdi/src/basetime.c
+++ b/libcdi/src/basetime.c
@@ -32,4 +32,3 @@ void basetimeInit(basetime_t *basetime)
* require-trailing-newline: t
* End:
*/
-
\ No newline at end of file
diff --git a/libcdi/src/binary.c b/libcdi/src/binary.c
index 9772272..dac4086 100644
--- a/libcdi/src/binary.c
+++ b/libcdi/src/binary.c
@@ -16,7 +16,7 @@ UINT32 get_UINT32(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
+ return ((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
case CDI_LITTLEENDIAN:
return ((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
default:
@@ -31,9 +31,9 @@ UINT32 get_SUINT32(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
+ return ((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
case CDI_LITTLEENDIAN:
- return((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
+ return ((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT32_C(0xFFFFFFFF);
@@ -46,11 +46,11 @@ UINT64 get_UINT64(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
- ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
+ return ((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
+ ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
case CDI_LITTLEENDIAN:
- return((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
- ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
+ return ((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
+ ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT64_C(0xFFFFFFFFFFFFFFFF);
@@ -63,11 +63,11 @@ UINT64 get_SUINT64(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
- ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
+ return ((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
+ ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
case CDI_LITTLEENDIAN:
- return((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
- ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
+ return ((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
+ ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT64_C(0xFFFFFFFFFFFFFFFF);
diff --git a/libcdi/src/calendar.h b/libcdi/src/calendar.h
index c5836e9..cd7ea77 100644
--- a/libcdi/src/calendar.h
+++ b/libcdi/src/calendar.h
@@ -1,15 +1,22 @@
#ifndef _CALENDAR_H
#define _CALENDAR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void encode_caldaysec(int calendar, int year, int month, int day, int hour, int minute, int second,
int *julday, int *secofday);
-void decode_caldaysec(int calendar, int julday, int secofday,
+void decode_caldaysec(int calendar, int julday, int secofday,
int *year, int *month, int *day, int *hour, int *minute, int *second);
int calendar_dpy(int calendar);
int days_per_year(int calendar, int year);
int days_per_month(int calendar, int year, int month);
+#if defined (__cplusplus)
+}
+#endif
#endif /* _CALENDAR_H */
/*
diff --git a/libcdi/src/cdf_read.c b/libcdi/src/cdf_read.c
new file mode 100644
index 0000000..5c872f7
--- /dev/null
+++ b/libcdi/src/cdf_read.c
@@ -0,0 +1,720 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBNETCDF
+
+#include <limits.h>
+#include <float.h>
+
+#include "dmemory.h"
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_cdf.h"
+#include "cdf.h"
+#include "cdf_int.h"
+#include "vlist.h"
+
+
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
+
+
+static
+void cdfReadGridTraj(stream_t *streamptr, int gridID)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int lonID = streamptr->xdimID[gridindex];
+ int latID = streamptr->ydimID[gridindex];
+
+ int tsID = streamptr->curTsID;
+ size_t index = (size_t)tsID;
+
+ double xlon, xlat;
+ cdf_get_var1_double(fileID, lonID, &index, &xlon);
+ cdf_get_var1_double(fileID, latID, &index, &xlat);
+
+ gridDefXvals(gridID, &xlon);
+ gridDefYvals(gridID, &xlat);
+}
+
+static
+void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
+{
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
+
+ if ( CDI_Debug ) Message("tsID = %d", tsID);
+
+ int xid = UNDEFID, yid = UNDEFID;
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfReadGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+
+ int ndims = 0;
+#define addDimension(startCoord, length) do \
+ { \
+ (*start)[ndims] = startCoord; \
+ (*count)[ndims] = length; \
+ ndims++; \
+ } while(0)
+ if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+ if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
+ if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
+ if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
+#undef addDimension
+
+ assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+ assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+
+ if ( CDI_Debug )
+ for (int idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+}
+
+//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
+//Returns the number of missing + out-of-range values encountered.
+static
+size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
+ {
+ const bool haveOffset = IS_NOT_EQUAL(offset, 0);
+ const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+ size_t missValCount = 0;
+
+ if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
+ if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
+
+ bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
+ assert(!haveRangeCheck || haveMissVal);
+
+ switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
+ | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ {
+ case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] * scaleFactor + offset;
+ }
+ break;
+ case 13: /* haveRangeCheck & haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] + offset;
+ }
+ break;
+ case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] * scaleFactor;
+ }
+ break;
+ case 9: /* haveRangeCheck & haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal : data[i];
+ }
+ break;
+ case 7: /* haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = data[i] * scaleFactor + offset;
+ break;
+ case 6: /* haveOffset & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = data[i] * scaleFactor + offset;
+ break;
+ case 5: /* haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] += offset;
+ break;
+ case 4: /* haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] += offset;
+ break;
+ case 3: /* haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] *= scaleFactor;
+ break;
+ case 2: /* haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] *= scaleFactor;
+ break;
+ case 1: /* haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
+ break;
+ }
+
+ return missValCount;
+}
+
+static
+size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
+ {
+ const bool haveOffset = IS_NOT_EQUAL(offset, 0);
+ const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+ size_t missValCount = 0;
+
+ if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
+ if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
+
+ bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
+ assert(!haveRangeCheck || haveMissVal);
+
+ switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
+ | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ {
+ case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] * scaleFactor + offset);
+ }
+ break;
+ case 13: /* haveRangeCheck & haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] + offset);
+ }
+ break;
+ case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] * scaleFactor);
+ }
+ break;
+ case 9: /* haveRangeCheck & haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal : data[i];
+ }
+ break;
+ case 7: /* haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] * scaleFactor + offset);
+ break;
+ case 6: /* haveOffset & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] * scaleFactor + offset);
+ break;
+ case 5: /* haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] + offset);
+ break;
+ case 4: /* haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] + offset);
+ break;
+ case 3: /* haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] * scaleFactor);
+ break;
+ case 2: /* haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] * scaleFactor);
+ break;
+ case 1: /* haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
+ break;
+ }
+
+ return missValCount;
+}
+
+static
+size_t min_size(size_t a, size_t b)
+{
+ return a < b ? a : b;
+}
+
+static
+void transpose2dArrayDP(size_t inWidth, size_t inHeight, double *data)
+{
+ const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+ // which should be a decent compromise on many architectures.
+#ifdef __cplusplus
+ double *out[inHeight];
+ double *temp[inWidth];
+ temp[0] = (double *) Malloc(inHeight*inWidth*sizeof(double));
+ memcpy(temp[0], data, inHeight*inWidth*sizeof(double));
+ for(int i = 0; i < inHeight; i++) out[i] = data + (inWidth*i);
+ for(int i = 1; i < inWidth; i++) temp[i] = temp[0] + (inHeight*i);
+#else
+ double (*out)[inHeight] = (double (*)[inHeight])data;
+ double (*temp)[inWidth] = (double (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
+ memcpy(temp, data, inHeight*sizeof(*temp));
+#endif
+
+ /*
+ for ( size_t y = 0; y < inHeight; ++y )
+ for ( size_t x = 0; x < inWidth; ++x )
+ out[x][y] = temp[y][x];
+ */
+
+ for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
+ {
+ for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
+ {
+ for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+ {
+ for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+ {
+ out[x][y] = temp[y][x];
+ }
+ }
+ }
+ }
+
+ Free(temp[0]);
+}
+
+static
+void transpose2dArraySP(size_t inWidth, size_t inHeight, float *data)
+{
+ const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+ // which should be a decent compromise on many architectures.
+#ifdef __cplusplus
+ float *out[inHeight];
+ float *temp[inWidth];
+ temp[0] = (float *) Malloc(inHeight*inWidth*sizeof(float));
+ memcpy(temp[0], data, inHeight*inWidth*sizeof(float));
+ for(int i = 0; i < inHeight; i++) out[i] = data + (inWidth*i);
+ for(int i = 1; i < inWidth; i++) temp[i] = temp[0] + (inHeight*i);
+#else
+ float (*out)[inHeight] = (float (*)[inHeight])data;
+ float (*temp)[inWidth] = (float (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
+ memcpy(temp, data, inHeight*sizeof(*temp));
+#endif
+
+ /*
+ for ( size_t y = 0; y < inHeight; ++y )
+ for ( size_t x = 0; x < inWidth; ++x )
+ out[x][y] = temp[y][x];
+ */
+
+ for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
+ {
+ for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
+ {
+ for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+ {
+ for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+ {
+ out[x][y] = temp[y][x];
+ }
+ }
+ }
+ }
+
+ Free(temp);
+}
+
+static
+void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
+{
+ int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
+ int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
+
+ (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
+ switch ( gridInqType(gridId) )
+ {
+ case GRID_TRAJECTORY:
+ cdfReadGridTraj(streamptr, gridId);
+ break;
+
+ case GRID_UNSTRUCTURED:
+ (*outDimIds)[0] = streamptr->xdimID[gridindex];
+ break;
+
+ default:
+ (*outDimIds)[0] = streamptr->xdimID[gridindex];
+ (*outDimIds)[1] = streamptr->ydimID[gridindex];
+ break;
+ }
+
+ int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
+ int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
+ (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
+}
+
+static
+int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
+{
+ if((*dimIds)[0] != UNDEFID) return 0;
+ if((*dimIds)[1] != UNDEFID) return 0;
+ int nvdims;
+ cdf_inq_varndims(fileId, ncvarid, &nvdims);
+ if(nvdims != 3) return 0;
+
+ int varDimIds[3];
+ cdf_inq_vardimid(fileId, ncvarid, varDimIds);
+ size_t size = 0;
+ if ( (*dimIds)[2] == varDimIds[2] )
+ {
+ cdf_inq_dimlen(fileId, varDimIds[1], &size);
+ if ( size == 1 ) return 1;
+ }
+ else if ( (*dimIds)[2] == varDimIds[1] )
+ {
+ cdf_inq_dimlen(fileId, varDimIds[2], &size);
+ if ( size == 1 ) return 2;
+ }
+ return 0;
+}
+
+static
+void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
+{
+ int tsID = streamptr->curTsID;
+ if ( CDI_Debug ) Message("tsID = %d", tsID);
+
+ int fileId = streamptr->fileID;
+ int vlistId = streamptr->vlistID;
+ int ncvarid = streamptr->vars[varId].ncvarid;
+
+ int gridId = vlistInqVarGrid(vlistId, varId);
+ int tsteptype = vlistInqVarTsteptype(vlistId, varId);
+ int gridsize = gridInqSize(gridId);
+
+ streamptr->numvals += gridsize;
+
+ int dimIds[3]; //this array joins the old variables xid, yid, and zid
+ cdfInqDimIds(streamptr, varId, &dimIds);
+
+ int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
+
+ int dimorder[3];
+ vlistInqVarDimorder(vlistId, varId, &dimorder);
+
+ *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
+
+ int ndims = 0;
+
+#define addDimension(startIndex, extent) do { \
+ (*start)[ndims] = startIndex; \
+ (*count)[ndims] = extent; \
+ ndims++; \
+ } while(0)
+
+ if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+ if ( skipdim == 1 ) addDimension(0, 1);
+
+ for ( int id = 0; id < 3; ++id )
+ {
+ size_t size;
+ int curDimId = dimIds[dimorder[id]-1];
+ if ( curDimId == UNDEFID ) continue;
+ switch ( dimorder[id] )
+ {
+ Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+ case 1:
+ case 2:
+ cdf_inq_dimlen(fileId, curDimId, &size);
+ addDimension(0, size);
+ break;
+
+ case 3:
+ addDimension((size_t)levelId, 1);
+ break;
+
+ default:
+ Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+ }
+ }
+
+ if ( skipdim == 2 ) addDimension(0, 1);
+
+ assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+ assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+
+#undef addDimension
+
+ if ( CDI_Debug )
+ for (int idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, (*start)[idim], (*count)[idim]);
+
+ int nvdims;
+ cdf_inq_varndims(fileId, ncvarid, &nvdims);
+
+ if ( nvdims != ndims )
+ Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
+}
+
+static
+void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ int ncvarid = streamptr->vars[varID].ncvarid;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+ size_t start[4];
+ size_t count[4];
+ cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+ cdf_get_vara_double(fileID, ncvarid, start, count, data);
+
+ size_t size = (size_t)gridInqSize(gridID)*(size_t)zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationDP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
+}
+
+static
+void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ int ncvarid = streamptr->vars[varID].ncvarid;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+ size_t start[4];
+ size_t count[4];
+ cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+ cdf_get_vara_float(fileID, ncvarid, start, count, data);
+
+ size_t size = (size_t)gridInqSize(gridID) * (size_t)zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationSP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
+}
+
+
+void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss)
+{
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarDP(streamptr, varID, (double*) data, nmiss);
+ else
+ cdfReadVarSP(streamptr, varID, (float*) data, nmiss);
+}
+
+static
+void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
+{
+ size_t start[4];
+ size_t count[4];
+
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ bool swapxy;
+ cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ int gridId = vlistInqVarGrid(vlistID, varID);
+ size_t gridsize = (size_t)gridInqSize(gridId);
+ size_t xsize = (size_t)gridInqXsize(gridId);
+ size_t ysize = (size_t)gridInqYsize(gridId);
+
+ if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+ {
+ float *data_fp = (float *) Malloc(gridsize*sizeof(*data_fp));
+ cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
+ for ( size_t i = 0; i < gridsize; i++ )
+ data[i] = (double) data_fp[i];
+ Free(data_fp);
+ }
+ else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < gridsize; i++ )
+ if ( data[i] < 0 ) data[i] += 256;
+ }
+ }
+ else
+ {
+ cdf_get_vara_double(fileID, ncvarid, start, count, data);
+ }
+
+ if ( swapxy ) transpose2dArrayDP(ysize, xsize, data);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationDP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
+}
+
+static
+void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
+{
+ size_t start[4];
+ size_t count[4];
+
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ bool swapxy;
+ cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ int gridId = vlistInqVarGrid(vlistID, varID);
+ size_t gridsize = (size_t)gridInqSize(gridId);
+ size_t xsize = (size_t)gridInqXsize(gridId);
+ size_t ysize = (size_t)gridInqYsize(gridId);
+
+ if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
+ {
+ double *data_dp = (double *) Malloc(gridsize*sizeof(*data_dp));
+ cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
+ for ( size_t i = 0; i < gridsize; i++ )
+ data[i] = (float) data_dp[i];
+ Free(data_dp);
+ }
+ else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < gridsize; i++ )
+ if ( data[i] < 0 ) data[i] += 256;
+ }
+ }
+ else
+ {
+ cdf_get_vara_float(fileID, ncvarid, start, count, data);
+ }
+
+ if ( swapxy ) transpose2dArraySP(ysize, xsize, data);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+ bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationSP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
+}
+
+
+void cdf_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss)
+{
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarSliceDP(streamptr, varID, levelID, (double*) data, nmiss);
+ else
+ cdfReadVarSliceSP(streamptr, varID, levelID, (float*) data, nmiss);
+}
+
+
+void cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
+
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ int levelID = streamptr->tsteps[tsID].records[recID].levelID;
+
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarSliceDP(streamptr, varID, levelID, (double*) data, nmiss);
+ else
+ cdfReadVarSliceSP(streamptr, varID, levelID, (float*) data, nmiss);
+}
+
+#endif
diff --git a/libcdi/src/cdf_write.c b/libcdi/src/cdf_write.c
new file mode 100644
index 0000000..942f0c7
--- /dev/null
+++ b/libcdi/src/cdf_write.c
@@ -0,0 +1,1272 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBNETCDF
+
+#include "dmemory.h"
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_cdf.h"
+#include "cdf.h"
+#include "cdf_int.h"
+#include "vlist.h"
+
+
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
+
+
+void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
+{
+#if defined (HAVE_NETCDF4)
+ int retval;
+ /* Set chunking, shuffle, and deflate. */
+ int shuffle = 1;
+ int deflate = 1;
+
+ if ( deflate_level < 1 || deflate_level > 9 ) deflate_level = 1;
+
+ if ((retval = nc_def_var_deflate(ncid, ncvarid, shuffle, deflate, deflate_level)))
+ {
+ Error("nc_def_var_deflate failed, status = %d", retval);
+ }
+#else
+
+ static int lwarn = TRUE;
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("Deflate compression failed, NetCDF4 not available!");
+ }
+#endif
+}
+
+static
+int cdfDefDatatype(int datatype, int filetype)
+{
+ int xtype = NC_FLOAT;
+
+ if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
+ Error("CDI/NetCDF library does not support complex numbers!");
+
+ if ( filetype == FILETYPE_NC4 )
+ {
+ if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
+ else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
+#if defined (HAVE_NETCDF4)
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_UBYTE;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
+#else
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
+#endif
+ else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
+ else xtype = NC_FLOAT;
+ }
+ else
+ {
+ if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
+ else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
+ else xtype = NC_FLOAT;
+ }
+
+ return xtype;
+}
+
+static
+void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
+{
+ if ( streamptr->vars[varID].defmiss == FALSE )
+ {
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+ int xtype = cdfDefDatatype(dtype, streamptr->filetype);
+
+ if ( xtype == NC_BYTE && missval > 127 && missval < 256 ) xtype = NC_INT;
+
+ cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
+ cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
+
+ if ( lcheck && streamptr->ncmode == 2 ) cdf_enddef(fileID);
+
+ streamptr->vars[varID].defmiss = TRUE;
+ }
+}
+
+static
+void cdfDefInstitut(stream_t *streamptr)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int instID = vlistInqInstitut(vlistID);
+
+ if ( instID != UNDEFID )
+ {
+ const char *longname = institutInqLongnamePtr(instID);
+ if ( longname )
+ {
+ size_t len = strlen(longname);
+ if ( len > 0 )
+ {
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ cdf_put_att_text(fileID, NC_GLOBAL, "institution", len, longname);
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ }
+ }
+ }
+}
+
+static
+void cdfDefSource(stream_t *streamptr)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int modelID = vlistInqModel(vlistID);
+
+ if ( modelID != UNDEFID )
+ {
+ const char *longname = modelInqNamePtr(modelID);
+ if ( longname )
+ {
+ size_t len = strlen(longname);
+ if ( len > 0 )
+ {
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ cdf_put_att_text(fileID, NC_GLOBAL, "source", len, longname);
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ }
+ }
+ }
+}
+
+static inline
+void *resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
+{
+ if (reqSize > *bufSize)
+ {
+ *buf = Realloc(*buf, reqSize);
+ *bufSize = reqSize;
+ }
+ return *buf;
+}
+
+static
+void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
+{
+ int atttype, attlen;
+ size_t len;
+ char attname[CDI_MAX_NAME+1];
+ void *attBuf = NULL;
+ size_t attBufSize = 0;
+
+ int natts;
+ vlistInqNatts(vlistID, varID, &natts);
+
+ for ( int iatt = 0; iatt < natts; iatt++ )
+ {
+ vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
+
+ if ( attlen == 0 ) continue;
+
+ if ( atttype == DATATYPE_TXT )
+ {
+ size_t attSize = (size_t)attlen*sizeof(char);
+ char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
+ len = (size_t)attlen;
+ cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
+ }
+ else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
+ {
+ size_t attSize = (size_t)attlen*sizeof(int);
+ int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
+ len = (size_t)attlen;
+ cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
+ }
+ else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
+ {
+ size_t attSize = (size_t)attlen * sizeof(double);
+ double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
+ len = (size_t)attlen;
+ if ( atttype == DATATYPE_FLT32 )
+ {
+ float attflt_sp[len];
+ for ( size_t i = 0; i < len; ++i ) attflt_sp[i] = (float)attflt[i];
+ cdf_put_att_float(fileID, ncvarID, attname, NC_FLOAT, len, attflt_sp);
+ }
+ else
+ cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
+ }
+ }
+
+ Free(attBuf);
+}
+
+static
+void cdfDefGlobalAtts(stream_t *streamptr)
+{
+ if ( streamptr->globalatts ) return;
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ cdfDefSource(streamptr);
+ cdfDefInstitut(streamptr);
+
+ int natts;
+ vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
+
+ if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+ cdfDefineAttributes(vlistID, CDI_GLOBAL, fileID, NC_GLOBAL);
+
+ if ( natts > 0 && streamptr->ncmode == 2 ) cdf_enddef(fileID);
+
+ streamptr->globalatts = 1;
+}
+
+static
+void cdfDefLocalAtts(stream_t *streamptr)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ if ( streamptr->localatts ) return;
+ if ( vlistInqInstitut(vlistID) != UNDEFID ) return;
+
+ streamptr->localatts = 1;
+
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+ for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ int instID = vlistInqVarInstitut(vlistID, varID);
+ if ( instID != UNDEFID )
+ {
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ const char *name = institutInqNamePtr(instID);
+ if ( name )
+ {
+ size_t len = strlen(name);
+ cdf_put_att_text(fileID, ncvarid, "institution", len, name);
+ }
+ }
+ }
+
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+}
+
+static
+int cdfDefVar(stream_t *streamptr, int varID)
+{
+ int ncvarid = -1;
+ int xid = UNDEFID, yid = UNDEFID;
+ size_t xsize = 0, ysize = 0;
+ char varname[CDI_MAX_NAME];
+ int dims[4];
+ int lchunk = FALSE;
+ size_t chunks[4] = {0,0,0,0};
+ int ndims = 0;
+ int tablenum;
+ int dimorder[3];
+ size_t iax = 0;
+ char axis[5];
+ int ensID, ensCount, forecast_type;
+ int retval;
+
+ int fileID = streamptr->fileID;
+
+ if ( CDI_Debug )
+ Message("streamID = %d, fileID = %d, varID = %d", streamptr->self, fileID, varID);
+
+ if ( streamptr->vars[varID].ncvarid != UNDEFID )
+ return streamptr->vars[varID].ncvarid;
+
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int code = vlistInqVarCode(vlistID, varID);
+ int param = vlistInqVarParam(vlistID, varID);
+ int pnum, pcat, pdis;
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+
+ int chunktype = vlistInqVarChunkType(vlistID, varID);
+
+ vlistInqVarDimorder(vlistID, varID, &dimorder);
+
+ int gridsize = gridInqSize(gridID);
+ if ( gridsize > 1 ) lchunk = TRUE;
+ int gridtype = gridInqType(gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ if ( gridtype != GRID_TRAJECTORY )
+ {
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize);
+ if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize);
+ }
+
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+ int zaxis_is_scalar = FALSE;
+ if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID);
+
+ if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
+
+ if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
+ {
+ printf("zid=%d yid=%d xid=%d\n", zid, yid, xid);
+ Error("Internal problem, dimension order missing!");
+ }
+
+ int tid = streamptr->basetime.ncdimid;
+
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ if ( tid == UNDEFID ) Error("Internal problem, time undefined!");
+ chunks[ndims] = 1;
+ dims[ndims++] = tid;
+ axis[iax++] = 'T';
+ }
+ /*
+ if ( zid != UNDEFID ) axis[iax++] = 'Z';
+ if ( zid != UNDEFID ) chunks[ndims] = 1;
+ if ( zid != UNDEFID ) dims[ndims++] = zid;
+
+ if ( yid != UNDEFID ) chunks[ndims] = ysize;
+ if ( yid != UNDEFID ) dims[ndims++] = yid;
+
+ if ( xid != UNDEFID ) chunks[ndims] = xsize;
+ if ( xid != UNDEFID ) dims[ndims++] = xid;
+ */
+ for ( int id = 0; id < 3; ++id )
+ {
+ if ( dimorder[id] == 3 && zid != UNDEFID )
+ {
+ axis[iax++] = 'Z';
+ chunks[ndims] = 1;
+ dims[ndims] = zid;
+ ndims++;
+ }
+ else if ( dimorder[id] == 2 && yid != UNDEFID )
+ {
+ if ( chunktype == CHUNK_LINES )
+ chunks[ndims] = 1;
+ else
+ chunks[ndims] = ysize;
+ dims[ndims] = yid;
+ ndims++;
+ }
+ else if ( dimorder[id] == 1 && xid != UNDEFID )
+ {
+ chunks[ndims] = xsize;
+ dims[ndims] = xid;
+ ndims++;
+ }
+ }
+
+ if ( CDI_Debug )
+ fprintf(stderr, "chunktype %d chunks %d %d %d %d\n", chunktype, (int)chunks[0], (int)chunks[1], (int)chunks[2], (int)chunks[3]);
+
+ int tableID = vlistInqVarTable(vlistID, varID);
+
+ const char *name = vlistInqVarNamePtr(vlistID, varID);
+ const char *longname = vlistInqVarLongnamePtr(vlistID, varID);
+ const char *stdname = vlistInqVarStdnamePtr(vlistID, varID);
+ const char *units = vlistInqVarUnitsPtr(vlistID, varID);
+
+ if ( name == NULL ) name = tableInqParNamePtr(tableID, code);
+ if ( longname == NULL ) longname = tableInqParLongnamePtr(tableID, code);
+ if ( units == NULL ) units = tableInqParUnitsPtr(tableID, code);
+ if ( name )
+ {
+ int checkname;
+ int iz;
+ int status;
+
+ sprintf(varname, "%s", name);
+
+ checkname = TRUE;
+ iz = 0;
+
+ while ( checkname )
+ {
+ if ( iz ) sprintf(varname, "%s_%d", name, iz+1);
+
+ status = nc_inq_varid(fileID, varname, &ncvarid);
+ if ( status != NC_NOERR )
+ {
+ checkname = FALSE;
+ }
+
+ if ( checkname ) iz++;
+
+ if ( iz >= CDI_MAX_NAME ) Error("Double entry of variable name '%s'!", name);
+ }
+
+ if ( strcmp(name, varname) != 0 )
+ {
+ if ( iz == 1 )
+ Warning("Changed double entry of variable name '%s' to '%s'!", name, varname);
+ else
+ Warning("Changed multiple entry of variable name '%s' to '%s'!", name, varname);
+ }
+
+ name = varname;
+ }
+ else
+ {
+ if ( code < 0 ) code = -code;
+ if ( pnum < 0 ) pnum = -pnum;
+
+ if ( pdis == 255 )
+ sprintf(varname, "var%d", code);
+ else
+ sprintf(varname, "param%d.%d.%d", pnum, pcat, pdis);
+
+ char *varname2 = varname+strlen(varname);
+
+ int checkname = TRUE;
+ int iz = 0;
+
+ while ( checkname )
+ {
+ if ( iz ) sprintf(varname2, "_%d", iz+1);
+
+ int status = nc_inq_varid(fileID, varname, &ncvarid);
+ if ( status != NC_NOERR ) checkname = FALSE;
+
+ if ( checkname ) iz++;
+
+ if ( iz >= CDI_MAX_NAME ) break;
+ }
+
+ name = varname;
+ code = 0;
+ pdis = 255;
+ }
+
+ /* if ( streamptr->ncmode == 2 ) cdf_redef(fileID); */
+
+ int dtype = vlistInqVarDatatype(vlistID, varID);
+ int xtype = cdfDefDatatype(dtype, streamptr->filetype);
+
+ cdf_def_var(fileID, name, (nc_type) xtype, ndims, dims, &ncvarid);
+
+#if defined (HAVE_NETCDF4)
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+ {
+ if ( chunktype == CHUNK_AUTO )
+ retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
+ else
+ retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
+
+ if ( retval ) Error("nc_def_var_chunking failed, status = %d", retval);
+ }
+#endif
+
+ if ( streamptr->comptype == COMPRESS_ZIP )
+ {
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+ {
+ cdfDefVarDeflate(fileID, ncvarid, streamptr->complevel);
+ }
+ else
+ {
+ if ( lchunk )
+ {
+ static int lwarn = TRUE;
+
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("Deflate compression is only available for NetCDF4!");
+ }
+ }
+ }
+ }
+
+ if ( streamptr->comptype == COMPRESS_SZIP )
+ {
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+ {
+#if defined (NC_SZIP_NN_OPTION_MASK)
+ cdfDefVarSzip(fileID, ncvarid);
+#else
+ static int lwarn = TRUE;
+
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("NetCDF4/SZIP compression not available!");
+ }
+#endif
+ }
+ else
+ {
+ static int lwarn = TRUE;
+
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("SZIP compression is only available for NetCDF4!");
+ }
+ }
+ }
+
+ if ( stdname && *stdname )
+ cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(stdname), stdname);
+
+ if ( longname && *longname )
+ cdf_put_att_text(fileID, ncvarid, "long_name", strlen(longname), longname);
+
+ if ( units && *units )
+ cdf_put_att_text(fileID, ncvarid, "units", strlen(units), units);
+
+ if ( code > 0 && pdis == 255 )
+ cdf_put_att_int(fileID, ncvarid, "code", NC_INT, 1, &code);
+
+ if ( pdis != 255 )
+ {
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ cdf_put_att_text(fileID, ncvarid, "param", strlen(paramstr), paramstr);
+ }
+
+ if ( tableID != UNDEFID )
+ {
+ tablenum = tableInqNum(tableID);
+ if ( tablenum > 0 )
+ cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum);
+ }
+
+ char coordinates[CDI_MAX_NAME];
+ coordinates[0] = 0;
+
+ if ( zaxis_is_scalar )
+ {
+ int nczvarID = streamptr->nczvarID[zaxisindex];
+ if ( nczvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, nczvarID, coordinates+len);
+ }
+ }
+
+ if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR )
+ {
+ size_t len = strlen(gridNamePtr(gridtype));
+ if ( len > 0 )
+ cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
+ }
+
+ if ( gridIsRotated(gridID) )
+ {
+ char mapping[] = "rotated_pole";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ }
+
+ if ( gridtype == GRID_SINUSOIDAL )
+ {
+ char mapping[] = "sinusoidal";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ }
+ else if ( gridtype == GRID_LAEA )
+ {
+ char mapping[] = "laea";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ }
+ else if ( gridtype == GRID_LCC2 )
+ {
+ char mapping[] = "Lambert_Conformal";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ }
+ else if ( gridtype == GRID_TRAJECTORY )
+ {
+ cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" );
+ }
+ else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 )
+ {
+ int ncxvarID = streamptr->ncxvarID[gridindex];
+ int ncyvarID = streamptr->ncyvarID[gridindex];
+ if ( ncyvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncyvarID, coordinates+len);
+ }
+ if ( ncxvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncxvarID, coordinates+len);
+ }
+ }
+ else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
+ {
+ char cellarea[CDI_MAX_NAME] = "area: ";
+ int ncxvarID = streamptr->ncxvarID[gridindex];
+ int ncyvarID = streamptr->ncyvarID[gridindex];
+ int ncavarID = streamptr->ncavarID[gridindex];
+ if ( ncyvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncyvarID, coordinates+len);
+ }
+ if ( ncxvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncxvarID, coordinates+len);
+ }
+
+ if ( ncavarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(cellarea);
+ cdf_inq_varname(fileID, ncavarID, cellarea+len);
+ len = strlen(cellarea);
+ cdf_put_att_text(fileID, ncvarid, "cell_measures", len, cellarea);
+ }
+
+ if ( gridtype == GRID_UNSTRUCTURED )
+ {
+ int position = gridInqPosition(gridID);
+ if ( position > 0 )
+ cdf_put_att_int(fileID, ncvarid, "number_of_grid_in_reference", NC_INT, 1, &position);
+ }
+ }
+ else if ( gridtype == GRID_SPECTRAL || gridtype == GRID_FOURIER )
+ {
+ int gridTruncation = gridInqTrunc(gridID);
+ axis[iax++] = '-';
+ axis[iax++] = '-';
+ cdf_put_att_text(fileID, ncvarid, "axis", iax, axis);
+ cdf_put_att_int(fileID, ncvarid, "truncation", NC_INT, 1, &gridTruncation);
+ }
+
+ size_t len = strlen(coordinates);
+ if ( len ) cdf_put_att_text(fileID, ncvarid, "coordinates", len, coordinates);
+
+ /* if ( xtype == NC_BYTE || xtype == NC_SHORT || xtype == NC_INT ) */
+ {
+ int laddoffset, lscalefactor;
+ double addoffset, scalefactor;
+ int astype = NC_DOUBLE;
+
+ addoffset = vlistInqVarAddoffset(vlistID, varID);
+ scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+ if ( laddoffset || lscalefactor )
+ {
+ if ( IS_EQUAL(addoffset, (double) ((float) addoffset)) &&
+ IS_EQUAL(scalefactor, (double) ((float) scalefactor)) )
+ {
+ astype = NC_FLOAT;
+ }
+
+ if ( xtype == (int) NC_FLOAT ) astype = NC_FLOAT;
+
+ cdf_put_att_double(fileID, ncvarid, "add_offset", (nc_type) astype, 1, &addoffset);
+ cdf_put_att_double(fileID, ncvarid, "scale_factor", (nc_type) astype, 1, &scalefactor);
+ }
+ }
+
+ if ( dtype == DATATYPE_UINT8 && xtype == NC_BYTE )
+ {
+ int validrange[2] = {0, 255};
+ cdf_put_att_int(fileID, ncvarid, "valid_range", NC_SHORT, 2, validrange);
+ cdf_put_att_text(fileID, ncvarid, "_Unsigned", 4, "true");
+ }
+
+ streamptr->vars[varID].ncvarid = ncvarid;
+
+ if ( vlistInqVarMissvalUsed(vlistID, varID) )
+ cdfDefVarMissval(streamptr, varID, vlistInqVarDatatype(vlistID, varID), 0);
+
+ if ( zid == -1 )
+ {
+ if ( zaxisInqType(zaxisID) == ZAXIS_CLOUD_BASE ||
+ zaxisInqType(zaxisID) == ZAXIS_CLOUD_TOP ||
+ zaxisInqType(zaxisID) == ZAXIS_ISOTHERM_ZERO ||
+ zaxisInqType(zaxisID) == ZAXIS_TOA ||
+ zaxisInqType(zaxisID) == ZAXIS_SEA_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_LAKE_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TA ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TW ||
+ zaxisInqType(zaxisID) == ZAXIS_MIX_LAYER ||
+ zaxisInqType(zaxisID) == ZAXIS_ATMOSPHERE )
+ {
+ zaxisInqName(zaxisID, varname);
+ cdf_put_att_text(fileID, ncvarid, "level_type", strlen(varname), varname);
+ }
+ }
+
+ if ( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
+ {
+ /* void cdf_put_att_int( int ncid, int varid, const char *name, nc_type xtype,
+ size_t len, const int *ip )
+ */
+ cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID);
+ cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount);
+ cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type);
+
+#ifdef DBG
+ if( DBG )
+ {
+ fprintf( stderr, "cdfDefVar :\n EnsID %d\n Enscount %d\n Forecast init type %d\n", ensID,
+ ensCount, forecast_type );
+ }
+#endif
+ }
+
+ /* Attributes */
+ cdfDefineAttributes(vlistID, varID, fileID, ncvarid);
+
+ /* if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); */
+
+ return ncvarid;
+}
+
+
+void cdfEndDef(stream_t *streamptr)
+{
+ cdfDefGlobalAtts(streamptr);
+ cdfDefLocalAtts(streamptr);
+
+ if ( streamptr->accessmode == 0 )
+ {
+ int fileID = streamptr->fileID;
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+
+ int nvars = streamptr->nvars;
+ for ( int varID = 0; varID < nvars; varID++ )
+ cdfDefVar(streamptr, varID);
+
+ if ( streamptr->ncmode == 2 )
+ {
+ if ( CDI_netcdf_hdr_pad == 0UL )
+ cdf_enddef(fileID);
+ else
+ cdf__enddef(fileID, CDI_netcdf_hdr_pad);
+ }
+
+ streamptr->accessmode = 1;
+ }
+}
+
+static
+void cdfWriteGridTraj(stream_t *streamptr, int gridID)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int lonID = streamptr->xdimID[gridindex];
+ int latID = streamptr->ydimID[gridindex];
+
+ double xlon = gridInqXval(gridID, 0);
+ double xlat = gridInqYval(gridID, 0);
+ int tsID = streamptr->curTsID;
+ size_t index = (size_t)tsID;
+
+ cdf_put_var1_double(fileID, lonID, &index, &xlon);
+ cdf_put_var1_double(fileID, latID, &index, &xlat);
+}
+
+static
+void cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, size_t nvals, size_t xsize, size_t ysize,
+ int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
+{
+ const double *pdata_dp = (const double *) data;
+ double *mdata_dp = NULL;
+ double *sdata_dp = NULL;
+ const float *pdata_sp = (const float *) data;
+ float *mdata_sp = NULL;
+ float *sdata_sp = NULL;
+
+ /* if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
+ {
+ double missval = vlistInqVarMissval(vlistID, varID);
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ bool laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ bool lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+ if ( laddoffset || lscalefactor )
+ {
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ mdata_sp = (float *) Malloc(nvals*sizeof(float));
+ memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+ pdata_sp = mdata_sp;
+
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ double temp = mdata_sp[i];
+ if ( !DBL_IS_EQUAL(temp, missval) )
+ {
+ if ( laddoffset ) temp -= addoffset;
+ if ( lscalefactor ) temp /= scalefactor;
+ mdata_sp[i] = (float)temp;
+ }
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ double temp = mdata_sp[i];
+ if ( laddoffset ) temp -= addoffset;
+ if ( lscalefactor ) temp /= scalefactor;
+ mdata_sp[i] = (float)temp;
+ }
+ }
+ }
+ else
+ {
+ mdata_dp = (double *) Malloc(nvals*sizeof(double));
+ memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+ pdata_dp = mdata_dp;
+
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
+ {
+ if ( laddoffset ) mdata_dp[i] -= addoffset;
+ if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+ }
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ if ( laddoffset ) mdata_dp[i] -= addoffset;
+ if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+ }
+ }
+ }
+ }
+
+ if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
+ dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
+ {
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ if ( mdata_sp == NULL )
+ {
+ mdata_sp = (float *) Malloc(nvals*sizeof(float));
+ memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+ pdata_sp = mdata_sp;
+ }
+
+ for ( size_t i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
+
+ if ( dtype == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < nvals; ++i )
+ if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
+ }
+ }
+ }
+ else
+ {
+ if ( mdata_dp == NULL )
+ {
+ mdata_dp = (double *) Malloc(nvals*sizeof(double));
+ memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+ pdata_dp = mdata_dp;
+ }
+
+ for ( size_t i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
+
+ if ( dtype == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < nvals; ++i )
+ if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
+ }
+ }
+ }
+ }
+
+ if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
+ {
+ double fmin, fmax;
+ fmin = 1.0e200;
+ fmax = -1.0e200;
+ for ( size_t i = 0; i < nvals; ++i )
+ {
+ if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
+ {
+ if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
+ if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
+ }
+ }
+ Message("nvals = %zu, nmiss = %d, missval = %g, minval = %g, maxval = %g",
+ nvals, nmiss, missval, fmin, fmax);
+ }
+ }
+
+ if ( swapxy ) // implemented only for cdf_write_var_slice()
+ {
+ size_t gridsize = xsize*ysize;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ sdata_sp = (float *) Malloc(gridsize*sizeof(float));
+ for ( size_t j = 0; j < ysize; ++j )
+ for ( size_t i = 0; i < xsize; ++i )
+ sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
+ pdata_sp = sdata_sp;
+ }
+ else
+ {
+ sdata_dp = (double *) Malloc(gridsize*sizeof (double));
+ for ( size_t j = 0; j < ysize; ++j )
+ for ( size_t i = 0; i < xsize; ++i )
+ sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
+ pdata_dp = sdata_dp;
+ }
+ }
+
+ if ( memtype == MEMTYPE_FLOAT )
+ cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
+ else
+ cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
+
+ if ( mdata_dp ) Free(mdata_dp);
+ if ( sdata_dp ) Free(sdata_dp);
+ if ( mdata_sp ) Free(mdata_sp);
+ if ( sdata_sp ) Free(sdata_sp);
+}
+
+
+void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+
+ size_t xsize = 0, ysize = 0;
+ size_t size;
+ size_t start[5];
+ size_t count[5];
+ int swapxy = FALSE;
+ int ndims = 0;
+ int idim;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ long ntsteps = streamptr->ntsteps;
+ if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
+
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+
+ int ncvarid = cdfDefVar(streamptr, varID);
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+
+ int xid = UNDEFID, yid = UNDEFID;
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
+
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
+ }
+
+ if ( zid != UNDEFID )
+ {
+ start[ndims] = 0;
+ count[ndims] = (size_t)zaxisInqSize(zaxisID);
+ ndims++;
+ }
+
+ if ( yid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, yid, &size);
+ /* count[ndims] = gridInqYsize(gridID); */
+ count[ndims] = size;
+ ndims++;
+ }
+
+ if ( xid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, xid, &size);
+ /* count[ndims] = gridInqXsize(gridID); */
+ count[ndims] = size;
+ ndims++;
+ }
+
+ if ( CDI_Debug )
+ for (idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+
+ if ( streamptr->ncmode == 1 )
+ {
+ cdf_enddef(fileID);
+ streamptr->ncmode = 2;
+ }
+
+ int dtype = vlistInqVarDatatype(vlistID, varID);
+
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
+
+ size_t nvals = (size_t)(gridInqSize(gridID)) * (size_t)(zaxisInqSize(zaxisID));
+
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
+
+
+void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
+ const int rect[][2], const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+
+ int xid = UNDEFID, yid = UNDEFID;
+ size_t xsize = 0, ysize = 0;
+ size_t start[5];
+ size_t count[5];
+ int swapxy = FALSE;
+ int ndims = 0;
+ int idim;
+ int streamID = streamptr->self;
+
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d", streamID, varID);
+
+ int vlistID = streamInqVlist(streamID);
+ int fileID = streamInqFileID(streamID);
+
+ long ntsteps = streamptr->ntsteps;
+ if ( CDI_Debug )
+ Message("ntsteps = %ld", ntsteps);
+
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+
+ int ncvarid = cdfDefVar(streamptr, varID);
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
+
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
+ }
+ if ( zid != UNDEFID )
+ {
+ int size = zaxisInqSize(zaxisID);
+ xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
+ && rect[2][1] <= size);
+ start[ndims] = (size_t)rect[2][0];
+ count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
+ ndims++;
+ }
+ if ( yid != UNDEFID )
+ {
+ size_t size;
+ cdf_inq_dimlen(fileID, yid, &size);
+ xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
+ && (size_t)rect[1][1] <= size);
+ start[ndims] = (size_t)rect[1][0];
+ count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
+ ndims++;
+ }
+ if ( xid != UNDEFID )
+ {
+ size_t size;
+ cdf_inq_dimlen(fileID, xid, &size);
+ xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
+ && (size_t)rect[0][1] <= size);
+ start[ndims] = (size_t)rect[0][0];
+ count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
+ ndims++;
+ }
+
+ if ( CDI_Debug )
+ for (idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+
+ if ( streamptr->ncmode == 1 )
+ {
+ cdf_enddef(fileID);
+ streamptr->ncmode = 2;
+ }
+
+ int dtype = vlistInqVarDatatype(vlistID, varID);
+
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
+
+ size_t nvals = (size_t)(gridInqSize(gridID)) * (size_t)(zaxisInqSize(zaxisID));
+
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals,
+ xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
+
+
+void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+
+ size_t xsize = 0, ysize = 0;
+ size_t start[5];
+ size_t count[5];
+ int dimorder[3];
+ int xid = UNDEFID, yid = UNDEFID;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ long ntsteps = streamptr->ntsteps;
+ if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
+
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+
+ int ncvarid = cdfDefVar(streamptr, varID);
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ vlistInqVarDimorder(vlistID, varID, &dimorder);
+
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
+
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+
+ int swapxy = (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID;
+
+ size_t ndims = 0;
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
+ }
+
+ for ( int id = 0; id < 3; ++id )
+ {
+ if ( dimorder[id] == 3 && zid != UNDEFID )
+ {
+ start[ndims] = (size_t)levelID;
+ count[ndims] = 1;
+ ndims++;
+ }
+ else if ( dimorder[id] == 2 && yid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, yid, &ysize);
+ count[ndims] = ysize;
+ ndims++;
+ }
+ else if ( dimorder[id] == 1 && xid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, xid, &xsize);
+ count[ndims] = xsize;
+ ndims++;
+ }
+ }
+
+ if ( CDI_Debug )
+ for (size_t idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+
+ int dtype = vlistInqVarDatatype(vlistID, varID);
+
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
+
+ size_t nvals = (size_t)(gridInqSize(gridID));
+
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
+
+
+void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
+{
+ int varID = streamptr->record->varID;
+ int levelID = streamptr->record->levelID;
+
+ cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+}
+
+#endif
diff --git a/libcdi/src/cdi.h b/libcdi/src/cdi.h
index 60d383e..7231b6a 100644
--- a/libcdi/src/cdi.h
+++ b/libcdi/src/cdi.h
@@ -9,11 +9,12 @@
#include <stdio.h>
#include <sys/types.h>
-/*
+
#ifdef __cplusplus
extern "C" {
#endif
-*/
+
+
#define CDI_MAX_NAME 256 /* max length of a name */
#define CDI_UNDEFID -1
@@ -38,7 +39,7 @@ extern "C" {
#define CDI_EUFTYPE -21 /* Unsupported file type */
#define CDI_ELIBNAVAIL -22 /* xxx library not available */
#define CDI_EUFSTRUCT -23 /* Unsupported file structure */
-#define CDI_EUNC4 -24 /* Unsupported netCDF4 structure */
+#define CDI_EUNC4 -24 /* Unsupported NetCDF4 structure */
#define CDI_ELIMIT -99 /* Internal limits exceeded */
/* File types */
@@ -46,10 +47,10 @@ extern "C" {
#define FILETYPE_UNDEF -1 /* Unknown/not yet defined file type */
#define FILETYPE_GRB 1 /* File type GRIB */
#define FILETYPE_GRB2 2 /* File type GRIB version 2 */
-#define FILETYPE_NC 3 /* File type netCDF */
-#define FILETYPE_NC2 4 /* File type netCDF version 2 (64-bit) */
-#define FILETYPE_NC4 5 /* File type netCDF version 4 */
-#define FILETYPE_NC4C 6 /* File type netCDF version 4 (classic) */
+#define FILETYPE_NC 3 /* File type NetCDF */
+#define FILETYPE_NC2 4 /* File type NetCDF version 2 (64-bit) */
+#define FILETYPE_NC4 5 /* File type NetCDF version 4 */
+#define FILETYPE_NC4C 6 /* File type NetCDF version 4 (classic) */
#define FILETYPE_SRV 7 /* File type SERVICE */
#define FILETYPE_EXT 8 /* File type EXTRA */
#define FILETYPE_IEG 9 /* File type IEG */
@@ -148,7 +149,7 @@ extern "C" {
#define ZAXIS_HYBRID 2 /* Hybrid level */
#define ZAXIS_HYBRID_HALF 3 /* Hybrid half level */
#define ZAXIS_PRESSURE 4 /* Isobaric pressure level in Pascal */
-#define ZAXIS_HEIGHT 5 /* Height above ground in meters */
+#define ZAXIS_HEIGHT 5 /* Height above ground */
#define ZAXIS_DEPTH_BELOW_SEA 6 /* Depth below sea level in meters */
#define ZAXIS_DEPTH_BELOW_LAND 7 /* Depth below land surface in centimeters */
#define ZAXIS_ISENTROPIC 8 /* Isentropic */
@@ -384,6 +385,7 @@ void streamInqRecord(int streamID, int *varID, int *levelID);
void streamWriteRecord(int streamID, const double data[], int nmiss);
void streamWriteRecordF(int streamID, const float data[], int nmiss);
void streamReadRecord(int streamID, double data[], int *nmiss);
+void streamReadRecordF(int streamID, float data[], int *nmiss);
void streamCopyRecord(int streamIDdest, int streamIDsrc);
void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
@@ -406,11 +408,15 @@ int cdiIterator_nextField(CdiIterator *me); //Points the iterator at the ne
//All outXXX arguments to these functions may be NULL.
char *cdiIterator_inqStartTime(CdiIterator *me); //Returns the (start) time as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
char *cdiIterator_inqEndTime(CdiIterator *me); //Returns the end time of an integration period as an ISO-8601 coded string, or NULL if there is no end time. The caller is responsible to Free() the returned string.
+char *cdiIterator_inqRTime(CdiIterator *me); //Returns the reference date as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
char *cdiIterator_inqVTime(CdiIterator *me); //Returns the validity date as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
int cdiIterator_inqLevelType(CdiIterator *me, int levelSelector, char **outName_optional, char **outLongName_optional, char **outStdName_optional, char **outUnit_optional); //callers are responsible to Free() strings that they request
int cdiIterator_inqLevel(CdiIterator *me, int levelSelector, double *outValue1_optional, double *outValue2_optional); //outValue2 is only written to if the level is a hybrid level
int cdiIterator_inqLevelUuid(CdiIterator *me, int *outVgridNumber_optional, int *outLevelCount_optional, unsigned char outUuid_optional[CDI_UUID_SIZE]); //outUuid must point to a buffer of 16 bytes, returns an error code if no generalized zaxis is used.
+int cdiIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute); //Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileIndex and *outTileAttribute will be set to -1 in this case.
+int cdiIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount); //outTileAttributeCount is the count for the tile associated with the current field, a total attribute count cannot be inquired. Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileCount and *outTileAttributeCount will be set to 0 in this case.
CdiParam cdiIterator_inqParam(CdiIterator *me);
+void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber); //Some FORTRAN compilers produce wrong code for the cdiIterator_inqParam()-wrapper, rendering it unusable from FORTRAN. This function is the workaround.
int cdiIterator_inqDatatype(CdiIterator *me);
int cdiIterator_inqTsteptype(CdiIterator *me);
char *cdiIterator_inqVariableName(CdiIterator *me); //The caller is responsible to Free() the returned buffer.
@@ -580,7 +586,7 @@ void vlistDefVarName(int vlistID, int varID, const char *name);
void vlistInqVarName(int vlistID, int varID, char *name);
/* vlistCopyVarName: Safe and convenient version of vlistInqVarName */
-char *vlistCopyVarName(int vlistId, int varId);
+char *vlistCopyVarName(int vlistId, int varId);
/* vlistDefVarStdname: Define the standard name of a Variable */
void vlistDefVarStdname(int vlistID, int varID, const char *stdname);
@@ -660,6 +666,10 @@ double vlistInqVarDblKey(int vlistID, int varID, const char *name);
/* vlistInqVarIntKey: raw access to GRIB meta-data */
int vlistInqVarIntKey(int vlistID, int varID, const char *name);
+/* needed only for CDO operator after */
+const char *vlistInqVarNamePtr(int vlistID, int varID);
+const char *vlistInqVarLongnamePtr(int vlistID, int varID);
+const char *vlistInqVarUnitsPtr(int vlistID, int varID);
/* VLIST attributes */
@@ -1136,6 +1146,7 @@ int tableInqParName(int tableID, int code, char *name);
int tableInqParLongname(int tableID, int code, char *longname);
int tableInqParUnits(int tableID, int code, char *units);
+/* needed only for CDO operator after */
const char *tableInqParNamePtr(int tableID, int parID);
const char *tableInqParLongnamePtr(int tableID, int parID);
const char *tableInqParUnitsPtr(int tableID, int parID);
@@ -1179,18 +1190,19 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion);
/* subtypeInqTile: Specialized version of subtypeInqSubEntry looking for tile/attribute pair. */
int subtypeInqTile(int subtypeID, int tileindex, int attribute);
+/* subtypeInqAttribute: Inquire the value of a subtype attribute. Returns CDI_EINVAL if the attribute does not exist.*/
+int subtypeInqAttribute(int subtypeID, int index, const char *key, int *outValue);
+
/* vlistInqVarSubtype: Return subtype ID for a given variable. */
int vlistInqVarSubtype(int vlistID, int varID);
-
void gribapiLibraryVersion(int *major_version, int *minor_version, int *revision_version);
-/*
#if defined (__cplusplus)
}
#endif
-*/
+
#endif /* CDI_H_ */
/*
* Local Variables:
diff --git a/libcdi/src/cdi.inc b/libcdi/src/cdi.inc
index 057f9f0..eb83f8c 100644
--- a/libcdi/src/cdi.inc
+++ b/libcdi/src/cdi.inc
@@ -1,10 +1,10 @@
! This file was automatically generated, don't edit!
!
-! Fortran interface for CDI library version 1.7.0
+! Fortran interface for CDI library version 1.7.1
!
! Author:
! -------
-! Uwe Schulzweida, MPI-MET, Hamburg, October 2015
+! Uwe Schulzweida, MPI-MET, Hamburg, February 2016
!
INTEGER CDI_MAX_NAME
@@ -703,6 +703,12 @@
! INTEGER nmiss)
EXTERNAL streamReadRecord
+! streamReadRecordF
+! (INTEGER streamID,
+! REAL data(*),
+! INTEGER nmiss)
+ EXTERNAL streamReadRecordF
+
! streamCopyRecord
! (INTEGER streamIDdest,
! INTEGER streamIDsrc)
@@ -1316,6 +1322,24 @@
EXTERNAL vlistInqVarIntKey
!
+! needed only for CDO operator after
+!
+ CHARACTER(80) vlistInqVarNamePtr
+! (INTEGER vlistID,
+! INTEGER varID)
+ EXTERNAL vlistInqVarNamePtr
+
+ CHARACTER(80) vlistInqVarLongnamePtr
+! (INTEGER vlistID,
+! INTEGER varID)
+ EXTERNAL vlistInqVarLongnamePtr
+
+ CHARACTER(80) vlistInqVarUnitsPtr
+! (INTEGER vlistID,
+! INTEGER varID)
+ EXTERNAL vlistInqVarUnitsPtr
+
+!
! VLIST attributes
!
INTEGER vlistInqNatts
@@ -2394,6 +2418,9 @@
! CHARACTER*(*) units)
EXTERNAL tableInqParUnits
+!
+! needed only for CDO operator after
+!
CHARACTER(80) tableInqParNamePtr
! (INTEGER tableID,
! INTEGER parID)
@@ -2475,6 +2502,13 @@
! INTEGER attribute)
EXTERNAL subtypeInqTile
+ INTEGER subtypeInqAttribute
+! (INTEGER subtypeID,
+! INTEGER index,
+! CHARACTER*(*) key,
+! INTEGER outValue)
+ EXTERNAL subtypeInqAttribute
+
INTEGER vlistInqVarSubtype
! (INTEGER vlistID,
! INTEGER varID)
diff --git a/libcdi/src/cdiFortran.c b/libcdi/src/cdiFortran.c
index dd53644..e8fd509 100644
--- a/libcdi/src/cdiFortran.c
+++ b/libcdi/src/cdiFortran.c
@@ -153,6 +153,7 @@ FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
FCALLSCSUB3 (streamWriteRecord, STREAMWRITERECORD, streamwriterecord, INT, DOUBLEV, INT)
FCALLSCSUB3 (streamWriteRecordF, STREAMWRITERECORDF, streamwriterecordf, INT, FLOATV, INT)
FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, DOUBLEV, PINT)
+FCALLSCSUB3 (streamReadRecordF, STREAMREADRECORDF, streamreadrecordf, INT, FLOATV, PINT)
FCALLSCSUB2 (streamCopyRecord, STREAMCOPYRECORD, streamcopyrecord, INT, INT)
/* File driven I/O (may yield better performance than using the streamXXX functions) */
@@ -280,6 +281,12 @@ FCALLSCFUN3 (INT, vlistHasVarKey, VLISTHASVARKEY, vlisthasvarkey, INT, INT, STRI
FCALLSCFUN3 (DOUBLE, vlistInqVarDblKey, VLISTINQVARDBLKEY, vlistinqvardblkey, INT, INT, STRING)
FCALLSCFUN3 (INT, vlistInqVarIntKey, VLISTINQVARINTKEY, vlistinqvarintkey, INT, INT, STRING)
+/* needed only for CDO operator after */
+
+FCALLSCFUN2 (STRING, vlistInqVarNamePtr, VLISTINQVARNAMEPTR, vlistinqvarnameptr, INT, INT)
+FCALLSCFUN2 (STRING, vlistInqVarLongnamePtr, VLISTINQVARLONGNAMEPTR, vlistinqvarlongnameptr, INT, INT)
+FCALLSCFUN2 (STRING, vlistInqVarUnitsPtr, VLISTINQVARUNITSPTR, vlistinqvarunitsptr, INT, INT)
+
/* VLIST attributes */
FCALLSCFUN3 (INT, vlistInqNatts, VLISTINQNATTS, vlistinqnatts, INT, INT, PINT)
@@ -522,6 +529,9 @@ FCALLSCFUN3 (INT, tableInqParCode, TABLEINQPARCODE, tableinqparcode, INT, PSTRIN
FCALLSCFUN3 (INT, tableInqParName, TABLEINQPARNAME, tableinqparname, INT, INT, PSTRING)
FCALLSCFUN3 (INT, tableInqParLongname, TABLEINQPARLONGNAME, tableinqparlongname, INT, INT, PSTRING)
FCALLSCFUN3 (INT, tableInqParUnits, TABLEINQPARUNITS, tableinqparunits, INT, INT, PSTRING)
+
+/* needed only for CDO operator after */
+
FCALLSCFUN2 (STRING, tableInqParNamePtr, TABLEINQPARNAMEPTR, tableinqparnameptr, INT, INT)
FCALLSCFUN2 (STRING, tableInqParLongnamePtr, TABLEINQPARLONGNAMEPTR, tableinqparlongnameptr, INT, INT)
FCALLSCFUN2 (STRING, tableInqParUnitsPtr, TABLEINQPARUNITSPTR, tableinqparunitsptr, INT, INT)
@@ -554,6 +564,7 @@ FCALLSCSUB2 (subtypeDefActiveIndex, SUBTYPEDEFACTIVEINDEX, subtypedefactiveindex
query objects. */
FCALLSCFUN3 (INT, subtypeInqTile, SUBTYPEINQTILE, subtypeinqtile, INT, INT, INT)
+FCALLSCFUN4 (INT, subtypeInqAttribute, SUBTYPEINQATTRIBUTE, subtypeinqattribute, INT, INT, STRING, PINT)
FCALLSCFUN2 (INT, vlistInqVarSubtype, VLISTINQVARSUBTYPE, vlistinqvarsubtype, INT, INT)
FCALLSCSUB3 (gribapiLibraryVersion, GRIBAPILIBRARYVERSION, gribapilibraryversion, PINT, PINT, PINT)
diff --git a/libcdi/src/cdi_error.c b/libcdi/src/cdi_error.c
index 36be80a..d0fd603 100644
--- a/libcdi/src/cdi_error.c
+++ b/libcdi/src/cdi_error.c
@@ -13,7 +13,7 @@ const char *cdiStringError(int cdiErrno)
static const char _EUFTYPE[] = "Unsupported file type";
static const char _ELIBNAVAIL[] = "Unsupported file type (library support not compiled in)";
static const char _EUFSTRUCT[] = "Unsupported file structure";
- static const char _EUNC4[] = "Unsupported netCDF4 structure";
+ static const char _EUNC4[] = "Unsupported NetCDF4 structure";
static const char _ELIMIT[] = "Internal limits exceeded";
switch (cdiErrno) {
diff --git a/libcdi/src/cdi_int.c b/libcdi/src/cdi_int.c
index 332b641..954122c 100644
--- a/libcdi/src/cdi_int.c
+++ b/libcdi/src/cdi_int.c
@@ -39,6 +39,7 @@ int cdiInventoryMode = 1;
int CDI_Version_Info = 1;
int CDI_cmor_mode = 0;
size_t CDI_netcdf_hdr_pad = 0UL;
+bool CDI_netcdf_lazy_grid_load = false;
char *cdiPartabPath = NULL;
int cdiPartabIntern = 1;
@@ -49,10 +50,10 @@ static const char Filetypes[][9] = {
"UNKNOWN",
"GRIB",
"GRIB2",
- "netCDF",
- "netCDF2",
- "netCDF4",
- "netCDF4c",
+ "NetCDF",
+ "NetCDF2",
+ "NetCDF4",
+ "NetCDF4c",
"SERVICE",
"EXTRA",
"IEG",
@@ -129,7 +130,7 @@ void cdiPrintVersion(void)
fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersionString());
#endif
#if defined (HAVE_LIBNETCDF)
- fprintf(stderr, " netCDF library version : %s\n", cdfLibraryVersion());
+ fprintf(stderr, " NetCDF library version : %s\n", cdfLibraryVersion());
#endif
#if defined (HAVE_LIBHDF5)
fprintf(stderr, " HDF5 library version : %s\n", hdfLibraryVersion());
@@ -423,6 +424,8 @@ void cdiDefGlobal(const char *string, int val)
else if ( strcmp(string, "NC_CHUNKSIZEHINT") == 0 ) cdiNcChunksizehint = val;
else if ( strcmp(string, "CMOR_MODE") == 0 ) CDI_cmor_mode = val;
else if ( strcmp(string, "NETCDF_HDR_PAD") == 0 ) CDI_netcdf_hdr_pad = (size_t) val;
+ else if ( strcmp(string, "NETCDF_LAZY_GRID_LOAD") == 0)
+ CDI_netcdf_lazy_grid_load = (bool)val;
else Warning("Unsupported global key: %s", string);
}
diff --git a/libcdi/src/cdi_int.h b/libcdi/src/cdi_int.h
index b53a829..f558ac6 100644
--- a/libcdi/src/cdi_int.h
+++ b/libcdi/src/cdi_int.h
@@ -151,7 +151,7 @@ typedef struct
int ilevel;
int ilevel2;
int ltype;
- int tsteptype;
+ short tsteptype;
short used;
short varID;
short levelID;
@@ -282,6 +282,13 @@ typedef struct
int subtype_index; /* tile index for this key-value pair */
} opt_key_val_pair_t;
+//enum for differenciating between the different times that we handle
+typedef enum {
+ kCdiTimeType_referenceTime,
+ kCdiTimeType_startTime,
+ kCdiTimeType_endTime
+} CdiTimeType;
+
@@ -309,6 +316,7 @@ extern int cdiInventoryMode;
extern int CDI_Version_Info;
extern int CDI_cmor_mode;
extern size_t CDI_netcdf_hdr_pad;
+extern bool CDI_netcdf_lazy_grid_load;
extern int STREAM_Debug;
@@ -375,21 +383,8 @@ int getByteswap(int byteorder);
void cdiStreamGetIndexList(unsigned numIDs, int IDs[]);
-
void cdiInitialize(void);
-void uuid2str(const unsigned char uuid[], char uuidstr[]);
-int str2uuid(const char *uuidstr, unsigned char uuid[]);
-
-static inline int cdiUUIDIsNull(const unsigned char uuid[])
-{
- int isNull = 1;
- for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
- isNull &= (uuid[i] == 0);
- return isNull;
-}
-
-
char *cdiEscapeSpaces(const char *string);
char *cdiUnescapeSpaces(const char *string, const char **outStringEnd);
@@ -420,9 +415,10 @@ streamOpenID(const char *filename, char filemode, int filetype,
void
cdiStreamDefVlist_(int streamID, int vlistID);
-void
-cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
- int nmiss);
+
+int
+cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss);
+
void
cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
const int rect[][2], const void *data, int nmiss);
@@ -436,14 +432,33 @@ void cdiStreamSync_(stream_t *streamptr);
const char *cdiUnitNamePtr(int cdi_unit);
+enum {
+ /* 8192 is known to work on most systems (4096 isn't on Alpha) */
+ commonPageSize = 8192,
+};
+
+size_t cdiGetPageSize(bool largePageAlign);
+
void zaxisGetIndexList(int nzaxis, int *zaxisIndexList);
void zaxisDefLtype2(int zaxisID, int ltype2);
int zaxisInqLtype2(int zaxisID);
-/* used by CDO */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// functions used in CDO !!!
+
void cdiDefTableID(int tableID);
+void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals);
+void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals);
+
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _CDI_INT_H */
/*
* Local Variables:
diff --git a/libcdi/src/cdi_util.c b/libcdi/src/cdi_util.c
index 600a974..6b5951f 100644
--- a/libcdi/src/cdi_util.c
+++ b/libcdi/src/cdi_util.c
@@ -2,8 +2,10 @@
# include "config.h"
#endif
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include "cdi.h"
#include "cdi_int.h"
@@ -114,6 +116,52 @@ const char *cdiUnitNamePtr(int cdi_unit)
return name;
}
+size_t
+cdiGetPageSize(bool largePageAlign)
+{
+ long pagesize = -1L;
+#if HAVE_DECL__SC_LARGE_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE || HAVE_DECL__SC_PAGESIZE
+ bool nameAssigned = false;
+ int name;
+# if HAVE_DECL__SC_LARGE_PAGESIZE
+ if (largePageAlign)
+ {
+ name = _SC_LARGE_PAGESIZE;
+ nameAssigned = true;
+ }
+ else
+# else
+ (void)largePageAlign;
+# endif
+ {
+# if HAVE_DECL__SC_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE
+ name =
+# if HAVE_DECL__SC_PAGESIZE
+ _SC_PAGESIZE
+# elif HAVE_DECL__SC_PAGE_SIZE
+ _SC_PAGE_SIZE
+# endif
+ ;
+ nameAssigned = true;
+# endif
+ }
+ if (nameAssigned)
+ pagesize = sysconf(name);
+#endif
+ if (pagesize == -1L)
+ pagesize =
+#if HAVE_DECL_PAGESIZE
+ PAGESIZE
+#elif HAVE_DECL_PAGE_SIZE
+ PAGE_SIZE
+#else
+ commonPageSize
+#endif
+ ;
+ return (size_t)pagesize;
+}
+
+
/*
* Local Variables:
* c-file-style: "Java"
diff --git a/libcdi/src/cdi_uuid.h b/libcdi/src/cdi_uuid.h
new file mode 100644
index 0000000..6f215ca
--- /dev/null
+++ b/libcdi/src/cdi_uuid.h
@@ -0,0 +1,42 @@
+#ifndef CDI_UUID_H
+#define CDI_UUID_H
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "cdi.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int cdiUUIDIsNull(const unsigned char uuid[])
+{
+ int isNull = 1;
+ for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
+ isNull &= (uuid[i] == 0);
+ return isNull;
+}
+
+void cdiCreateUUID(unsigned char uuid[CDI_UUID_SIZE]);
+
+void cdiUUID2Str(const unsigned char uuid[], char uuidstr[]);
+int cdiStr2UUID(const char *uuidstr, unsigned char uuid[]);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/libcdi/src/cdilib.c b/libcdi/src/cdilib.c
index 4f455df..5220402 100644
--- a/libcdi/src/cdilib.c
+++ b/libcdi/src/cdilib.c
@@ -1,7 +1,7 @@
-/* Automatically generated by m214003 at 2015-10-25, do not edit */
+/* Automatically generated by m214003 at 2016-02-19, do not edit */
-/* CDILIB_VERSION="1.7.0" */
+/* CDILIB_VERSION="1.7.1" */
#ifdef _ARCH_PWR6
#pragma options nostrict
@@ -68,9 +68,9 @@
#define WITH_CALLER_NAME
#endif
-#define _FATAL 1 /* Error flag: exit on error */
-#define _VERBOSE 2 /* Error flag: report errors */
-#define _DEBUG 4 /* Error flag: debug */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern int _ExitOnError; /* If set to 1, exit on error (default 1) */
extern int _Verbose; /* If set to 1, errors are reported (default 1) */
@@ -126,6 +126,10 @@ cdiAbortC_serial(const char *caller, const char *filename,
const char *errorString, va_list ap)
__attribute__((noreturn));
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _ERROR_H */
/*
* Local Variables:
@@ -147,11 +151,12 @@ cdiAbortC_serial(const char *caller, const char *filename,
#include <stdio.h>
#include <sys/types.h>
-/*
+
#ifdef __cplusplus
extern "C" {
#endif
-*/
+
+
#define CDI_MAX_NAME 256 /* max length of a name */
#define CDI_UNDEFID -1
@@ -176,7 +181,7 @@ extern "C" {
#define CDI_EUFTYPE -21 /* Unsupported file type */
#define CDI_ELIBNAVAIL -22 /* xxx library not available */
#define CDI_EUFSTRUCT -23 /* Unsupported file structure */
-#define CDI_EUNC4 -24 /* Unsupported netCDF4 structure */
+#define CDI_EUNC4 -24 /* Unsupported NetCDF4 structure */
#define CDI_ELIMIT -99 /* Internal limits exceeded */
/* File types */
@@ -184,10 +189,10 @@ extern "C" {
#define FILETYPE_UNDEF -1 /* Unknown/not yet defined file type */
#define FILETYPE_GRB 1 /* File type GRIB */
#define FILETYPE_GRB2 2 /* File type GRIB version 2 */
-#define FILETYPE_NC 3 /* File type netCDF */
-#define FILETYPE_NC2 4 /* File type netCDF version 2 (64-bit) */
-#define FILETYPE_NC4 5 /* File type netCDF version 4 */
-#define FILETYPE_NC4C 6 /* File type netCDF version 4 (classic) */
+#define FILETYPE_NC 3 /* File type NetCDF */
+#define FILETYPE_NC2 4 /* File type NetCDF version 2 (64-bit) */
+#define FILETYPE_NC4 5 /* File type NetCDF version 4 */
+#define FILETYPE_NC4C 6 /* File type NetCDF version 4 (classic) */
#define FILETYPE_SRV 7 /* File type SERVICE */
#define FILETYPE_EXT 8 /* File type EXTRA */
#define FILETYPE_IEG 9 /* File type IEG */
@@ -286,7 +291,7 @@ extern "C" {
#define ZAXIS_HYBRID 2 /* Hybrid level */
#define ZAXIS_HYBRID_HALF 3 /* Hybrid half level */
#define ZAXIS_PRESSURE 4 /* Isobaric pressure level in Pascal */
-#define ZAXIS_HEIGHT 5 /* Height above ground in meters */
+#define ZAXIS_HEIGHT 5 /* Height above ground */
#define ZAXIS_DEPTH_BELOW_SEA 6 /* Depth below sea level in meters */
#define ZAXIS_DEPTH_BELOW_LAND 7 /* Depth below land surface in centimeters */
#define ZAXIS_ISENTROPIC 8 /* Isentropic */
@@ -522,6 +527,7 @@ void streamInqRecord(int streamID, int *varID, int *levelID);
void streamWriteRecord(int streamID, const double data[], int nmiss);
void streamWriteRecordF(int streamID, const float data[], int nmiss);
void streamReadRecord(int streamID, double data[], int *nmiss);
+void streamReadRecordF(int streamID, float data[], int *nmiss);
void streamCopyRecord(int streamIDdest, int streamIDsrc);
void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
@@ -544,11 +550,15 @@ int cdiIterator_nextField(CdiIterator *me); //Points the iterator at the ne
//All outXXX arguments to these functions may be NULL.
char *cdiIterator_inqStartTime(CdiIterator *me); //Returns the (start) time as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
char *cdiIterator_inqEndTime(CdiIterator *me); //Returns the end time of an integration period as an ISO-8601 coded string, or NULL if there is no end time. The caller is responsible to Free() the returned string.
+char *cdiIterator_inqRTime(CdiIterator *me); //Returns the reference date as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
char *cdiIterator_inqVTime(CdiIterator *me); //Returns the validity date as an ISO-8601 coded string. The caller is responsible to Free() the returned string.
int cdiIterator_inqLevelType(CdiIterator *me, int levelSelector, char **outName_optional, char **outLongName_optional, char **outStdName_optional, char **outUnit_optional); //callers are responsible to Free() strings that they request
int cdiIterator_inqLevel(CdiIterator *me, int levelSelector, double *outValue1_optional, double *outValue2_optional); //outValue2 is only written to if the level is a hybrid level
int cdiIterator_inqLevelUuid(CdiIterator *me, int *outVgridNumber_optional, int *outLevelCount_optional, unsigned char outUuid_optional[CDI_UUID_SIZE]); //outUuid must point to a buffer of 16 bytes, returns an error code if no generalized zaxis is used.
+int cdiIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute); //Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileIndex and *outTileAttribute will be set to -1 in this case.
+int cdiIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount); //outTileAttributeCount is the count for the tile associated with the current field, a total attribute count cannot be inquired. Returns CDI_EINVAL if there is no tile information connected to the current field, *outTileCount and *outTileAttributeCount will be set to 0 in this case.
CdiParam cdiIterator_inqParam(CdiIterator *me);
+void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber); //Some FORTRAN compilers produce wrong code for the cdiIterator_inqParam()-wrapper, rendering it unusable from FORTRAN. This function is the workaround.
int cdiIterator_inqDatatype(CdiIterator *me);
int cdiIterator_inqTsteptype(CdiIterator *me);
char *cdiIterator_inqVariableName(CdiIterator *me); //The caller is responsible to Free() the returned buffer.
@@ -718,7 +728,7 @@ void vlistDefVarName(int vlistID, int varID, const char *name);
void vlistInqVarName(int vlistID, int varID, char *name);
/* vlistCopyVarName: Safe and convenient version of vlistInqVarName */
-char *vlistCopyVarName(int vlistId, int varId);
+char *vlistCopyVarName(int vlistId, int varId);
/* vlistDefVarStdname: Define the standard name of a Variable */
void vlistDefVarStdname(int vlistID, int varID, const char *stdname);
@@ -798,6 +808,10 @@ double vlistInqVarDblKey(int vlistID, int varID, const char *name);
/* vlistInqVarIntKey: raw access to GRIB meta-data */
int vlistInqVarIntKey(int vlistID, int varID, const char *name);
+/* needed only for CDO operator after */
+const char *vlistInqVarNamePtr(int vlistID, int varID);
+const char *vlistInqVarLongnamePtr(int vlistID, int varID);
+const char *vlistInqVarUnitsPtr(int vlistID, int varID);
/* VLIST attributes */
@@ -1274,6 +1288,7 @@ int tableInqParName(int tableID, int code, char *name);
int tableInqParLongname(int tableID, int code, char *longname);
int tableInqParUnits(int tableID, int code, char *units);
+/* needed only for CDO operator after */
const char *tableInqParNamePtr(int tableID, int parID);
const char *tableInqParLongnamePtr(int tableID, int parID);
const char *tableInqParUnitsPtr(int tableID, int parID);
@@ -1317,18 +1332,19 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion);
/* subtypeInqTile: Specialized version of subtypeInqSubEntry looking for tile/attribute pair. */
int subtypeInqTile(int subtypeID, int tileindex, int attribute);
+/* subtypeInqAttribute: Inquire the value of a subtype attribute. Returns CDI_EINVAL if the attribute does not exist.*/
+int subtypeInqAttribute(int subtypeID, int index, const char *key, int *outValue);
+
/* vlistInqVarSubtype: Return subtype ID for a given variable. */
int vlistInqVarSubtype(int vlistID, int varID);
-
void gribapiLibraryVersion(int *major_version, int *minor_version, int *revision_version);
-/*
#if defined (__cplusplus)
}
#endif
-*/
+
#endif /* CDI_H_ */
/*
* Local Variables:
@@ -1405,7 +1421,6 @@ void basetimeInit(basetime_t *basetime)
* require-trailing-newline: t
* End:
*/
-
#ifndef _FILE_H
#define _FILE_H
@@ -1600,7 +1615,7 @@ UINT32 get_UINT32(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
+ return ((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
case CDI_LITTLEENDIAN:
return ((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
default:
@@ -1615,9 +1630,9 @@ UINT32 get_SUINT32(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
+ return ((UINT32)(((UINT32)x[3]<<24)+((UINT32)x[2]<<16)+((UINT32)x[1]<< 8)+ (UINT32)x[0]));
case CDI_LITTLEENDIAN:
- return((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
+ return ((UINT32)(((UINT32)x[0]<<24)+((UINT32)x[1]<<16)+((UINT32)x[2]<< 8)+ (UINT32)x[3]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT32_C(0xFFFFFFFF);
@@ -1630,11 +1645,11 @@ UINT64 get_UINT64(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
- ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
+ return ((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
+ ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
case CDI_LITTLEENDIAN:
- return((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
- ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
+ return ((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
+ ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT64_C(0xFFFFFFFFFFFFFFFF);
@@ -1647,11 +1662,11 @@ UINT64 get_SUINT64(unsigned char *x)
switch (HOST_ENDIANNESS)
{
case CDI_BIGENDIAN:
- return((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
- ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
+ return ((UINT64)(((UINT64)x[7]<<56)+((UINT64)x[6]<<48)+((UINT64)x[5]<<40)+((UINT64)x[4]<<32)+
+ ((UINT64)x[3]<<24)+((UINT64)x[2]<<16)+((UINT64)x[1]<< 8)+ (UINT64)x[0]));
case CDI_LITTLEENDIAN:
- return((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
- ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
+ return ((UINT64)(((UINT64)x[0]<<56)+((UINT64)x[1]<<48)+((UINT64)x[2]<<40)+((UINT64)x[3]<<32)+
+ ((UINT64)x[4]<<24)+((UINT64)x[5]<<16)+((UINT64)x[6]<< 8)+ (UINT64)x[7]));
default:
Error("unhandled endianness %d", HOST_ENDIANNESS);
return UINT64_C(0xFFFFFFFFFFFFFFFF);
@@ -1861,15 +1876,22 @@ int binWriteFlt64(int fileID, int byteswap, size_t size, FLT64 *ptr)
#ifndef _CALENDAR_H
#define _CALENDAR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void encode_caldaysec(int calendar, int year, int month, int day, int hour, int minute, int second,
int *julday, int *secofday);
-void decode_caldaysec(int calendar, int julday, int secofday,
+void decode_caldaysec(int calendar, int julday, int secofday,
int *year, int *month, int *day, int *hour, int *minute, int *second);
int calendar_dpy(int calendar);
int days_per_year(int calendar, int year);
int days_per_month(int calendar, int year, int month);
+#if defined (__cplusplus)
+}
+#endif
#endif /* _CALENDAR_H */
/*
@@ -1886,6 +1908,10 @@ int days_per_month(int calendar, int year, int month);
#include <inttypes.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* date format: YYYYMMDD */
/* time format: hhmmss */
@@ -1905,6 +1931,10 @@ double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *d
void encode_juldaysec(int calendar, int year, int month, int day, int hour, int minute, int second, int *julday, int *secofday);
void decode_juldaysec(int calendar, int julday, int secofday, int *year, int *month, int *day, int *hour, int *minute, int *second);
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _TIMEBASE_H */
/*
@@ -2812,7 +2842,7 @@ typedef struct
int ilevel;
int ilevel2;
int ltype;
- int tsteptype;
+ short tsteptype;
short used;
short varID;
short levelID;
@@ -2943,6 +2973,13 @@ typedef struct
int subtype_index; /* tile index for this key-value pair */
} opt_key_val_pair_t;
+//enum for differenciating between the different times that we handle
+typedef enum {
+ kCdiTimeType_referenceTime,
+ kCdiTimeType_startTime,
+ kCdiTimeType_endTime
+} CdiTimeType;
+
@@ -2970,6 +3007,7 @@ extern int cdiInventoryMode;
extern int CDI_Version_Info;
extern int CDI_cmor_mode;
extern size_t CDI_netcdf_hdr_pad;
+extern bool CDI_netcdf_lazy_grid_load;
extern int STREAM_Debug;
@@ -3036,21 +3074,8 @@ int getByteswap(int byteorder);
void cdiStreamGetIndexList(unsigned numIDs, int IDs[]);
-
void cdiInitialize(void);
-void uuid2str(const unsigned char uuid[], char uuidstr[]);
-int str2uuid(const char *uuidstr, unsigned char uuid[]);
-
-static inline int cdiUUIDIsNull(const unsigned char uuid[])
-{
- int isNull = 1;
- for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
- isNull &= (uuid[i] == 0);
- return isNull;
-}
-
-
char *cdiEscapeSpaces(const char *string);
char *cdiUnescapeSpaces(const char *string, const char **outStringEnd);
@@ -3081,9 +3106,10 @@ streamOpenID(const char *filename, char filemode, int filetype,
void
cdiStreamDefVlist_(int streamID, int vlistID);
-void
-cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data,
- int nmiss);
+
+int
+cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss);
+
void
cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
const int rect[][2], const void *data, int nmiss);
@@ -3097,14 +3123,33 @@ void cdiStreamSync_(stream_t *streamptr);
const char *cdiUnitNamePtr(int cdi_unit);
+enum {
+ /* 8192 is known to work on most systems (4096 isn't on Alpha) */
+ commonPageSize = 8192,
+};
+
+size_t cdiGetPageSize(bool largePageAlign);
+
void zaxisGetIndexList(int nzaxis, int *zaxisIndexList);
void zaxisDefLtype2(int zaxisID, int ltype2);
int zaxisInqLtype2(int zaxisID);
-/* used by CDO */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// functions used in CDO !!!
+
void cdiDefTableID(int tableID);
+void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals);
+void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals);
+
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _CDI_INT_H */
/*
* Local Variables:
@@ -3511,7 +3556,7 @@ union namespaceSwitchValue
void namespaceCleanup ( void );
int namespaceGetNumber ( void );
//void namespaceSetActive(int namespaceID);
-int namespaceGetActive ( void );
+//int namespaceGetActive ( void );
int namespaceIdxEncode ( namespaceTuple_t );
int namespaceIdxEncode2 ( int, int );
namespaceTuple_t namespaceResHDecode ( int );
@@ -4484,7 +4529,7 @@ const char *cdiStringError(int cdiErrno)
static const char _EUFTYPE[] = "Unsupported file type";
static const char _ELIBNAVAIL[] = "Unsupported file type (library support not compiled in)";
static const char _EUFSTRUCT[] = "Unsupported file structure";
- static const char _EUNC4[] = "Unsupported netCDF4 structure";
+ static const char _EUNC4[] = "Unsupported NetCDF4 structure";
static const char _ELIMIT[] = "Internal limits exceeded";
switch (cdiErrno) {
@@ -4525,6 +4570,10 @@ const char *cdiStringError(int cdiErrno)
#define WITH_FUNCTION_NAME
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern size_t memTotal(void);
extern void memDebug(int debug);
extern void memExitOnError(void);
@@ -4536,6 +4585,10 @@ extern void *memCalloc (size_t nmemb, size_t size, const char *file, const cha
extern void *memMalloc (size_t size, const char *file, const char *functionname, int line);
extern void memFree (void *ptr, const char *file, const char *functionname, int line);
+#if defined (__cplusplus)
+}
+#endif
+
#if defined WITH_FUNCTION_NAME
# define Realloc(p, s) memRealloc((p), (s), __FILE__, __func__, __LINE__)
# define Calloc(n, s) memCalloc((n), (s), __FILE__, __func__, __LINE__)
@@ -4701,21 +4754,21 @@ void cdfDefRecord(stream_t * streamptr);
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss);
void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss);
-void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss);
-
+void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss);
void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
-void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
-void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss);
+void cdf_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss);
void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
const int rect[][2], const void *data, int nmiss);
+void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level);
+void cdfDefTime(stream_t* streamptr);
+
#endif
/*
* Local Variables:
@@ -4903,6 +4956,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
#define ISEC4_NumNonMissValues (isec4[20]) /* Number of non-missing values */
+#ifdef __cplusplus
+extern "C" {
+#endif
void gribFixZSE(int flag); /* 1: Fix ZeroShiftError of simple packed spherical harmonics */
@@ -4916,11 +4972,11 @@ void gribSetValueCheck(int vcheck);
void gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret);
+ int kleng, int *kword, const char *hoper, int *kret);
void gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret);
+ int kleng, int *kword, const char *hoper, int *kret);
const char *cgribexLibraryVersion(void);
@@ -4971,7 +5027,13 @@ int gribVersion(unsigned char *buffer, size_t buffersize);
int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
-double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation);
+double calculate_pfactor_float(const float* spectralField, long fieldTruncation, long subsetTruncation);
+double calculate_pfactor_double(const double* spectralField, long fieldTruncation, long subsetTruncation);
+
+
+#if defined (__cplusplus)
+}
+#endif
#endif /* _CGRIBEX_H */
@@ -5005,6 +5067,7 @@ int cdiInventoryMode = 1;
int CDI_Version_Info = 1;
int CDI_cmor_mode = 0;
size_t CDI_netcdf_hdr_pad = 0UL;
+bool CDI_netcdf_lazy_grid_load = false;
char *cdiPartabPath = NULL;
int cdiPartabIntern = 1;
@@ -5015,10 +5078,10 @@ static const char Filetypes[][9] = {
"UNKNOWN",
"GRIB",
"GRIB2",
- "netCDF",
- "netCDF2",
- "netCDF4",
- "netCDF4c",
+ "NetCDF",
+ "NetCDF2",
+ "NetCDF4",
+ "NetCDF4c",
"SERVICE",
"EXTRA",
"IEG",
@@ -5095,7 +5158,7 @@ void cdiPrintVersion(void)
fprintf(stderr, "GRIB_API library version : %s\n", gribapiLibraryVersionString());
#endif
#if defined (HAVE_LIBNETCDF)
- fprintf(stderr, " netCDF library version : %s\n", cdfLibraryVersion());
+ fprintf(stderr, " NetCDF library version : %s\n", cdfLibraryVersion());
#endif
#if defined (HAVE_LIBHDF5)
fprintf(stderr, " HDF5 library version : %s\n", hdfLibraryVersion());
@@ -5389,6 +5452,8 @@ void cdiDefGlobal(const char *string, int val)
else if ( strcmp(string, "NC_CHUNKSIZEHINT") == 0 ) cdiNcChunksizehint = val;
else if ( strcmp(string, "CMOR_MODE") == 0 ) CDI_cmor_mode = val;
else if ( strcmp(string, "NETCDF_HDR_PAD") == 0 ) CDI_netcdf_hdr_pad = (size_t) val;
+ else if ( strcmp(string, "NETCDF_LAZY_GRID_LOAD") == 0)
+ CDI_netcdf_lazy_grid_load = (bool)val;
else Warning("Unsupported global key: %s", string);
}
@@ -5421,8 +5486,10 @@ double cdiInqMissval(void)
#if defined (HAVE_CONFIG_H)
#endif
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
void cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis)
@@ -5531,6 +5598,52 @@ const char *cdiUnitNamePtr(int cdi_unit)
return name;
}
+size_t
+cdiGetPageSize(bool largePageAlign)
+{
+ long pagesize = -1L;
+#if HAVE_DECL__SC_LARGE_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE || HAVE_DECL__SC_PAGESIZE
+ bool nameAssigned = false;
+ int name;
+# if HAVE_DECL__SC_LARGE_PAGESIZE
+ if (largePageAlign)
+ {
+ name = _SC_LARGE_PAGESIZE;
+ nameAssigned = true;
+ }
+ else
+# else
+ (void)largePageAlign;
+# endif
+ {
+# if HAVE_DECL__SC_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE
+ name =
+# if HAVE_DECL__SC_PAGESIZE
+ _SC_PAGESIZE
+# elif HAVE_DECL__SC_PAGE_SIZE
+ _SC_PAGE_SIZE
+# endif
+ ;
+ nameAssigned = true;
+# endif
+ }
+ if (nameAssigned)
+ pagesize = sysconf(name);
+#endif
+ if (pagesize == -1L)
+ pagesize =
+#if HAVE_DECL_PAGESIZE
+ PAGESIZE
+#elif HAVE_DECL_PAGE_SIZE
+ PAGE_SIZE
+#else
+ commonPageSize
+#endif
+ ;
+ return (size_t)pagesize;
+}
+
+
/*
* Local Variables:
* c-file-style: "Java"
@@ -5541,9 +5654,9 @@ const char *cdiUnitNamePtr(int cdi_unit)
* End:
*/
-/* Automatically generated by m214003 at 2015-09-14, do not edit */
+/* Automatically generated by m214003 at 2016-02-19, do not edit */
-/* CGRIBEXLIB_VERSION="1.7.3" */
+/* CGRIBEXLIB_VERSION="1.7.4" */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined (__clang__)
#pragma GCC diagnostic push
@@ -5574,8 +5687,8 @@ const char *cdiUnitNamePtr(int cdi_unit)
#define TEMPLATE(X,Y) CAT(X,Y)
#endif
-#ifndef _GRIB_INT_H
-#define _GRIB_INT_H
+#ifndef GRIB_INT_H
+#define GRIB_INT_H
#if defined (HAVE_CONFIG_H)
#endif
@@ -5644,24 +5757,25 @@ const char *cdiUnitNamePtr(int cdi_unit)
#endif
#endif
-#ifndef DBL_IS_EQUAL
-/*#define DBL_IS_EQUAL(x,y) (!(x < y || y < x)) */
-# define DBL_IS_EQUAL(x,y) (DBL_IS_NAN(x)||DBL_IS_NAN(y)?(DBL_IS_NAN(x)&&DBL_IS_NAN(y)?1:0):!(x < y || y < x))
-#endif
-
#ifndef IS_EQUAL
# define IS_NOT_EQUAL(x,y) (x < y || y < x)
# define IS_EQUAL(x,y) (!IS_NOT_EQUAL(x,y))
#endif
/* dummy use of unused parameters to silence compiler warnings */
-#define UNUSED(x) (void)x
+#ifndef UNUSED
+# define UNUSED(x) (void)(x)
+#endif
#define JP23SET 0x7FFFFF /* 2**23 - 1 (---> 8388607) */
#define POW_2_M24 0.000000059604644775390625 /* pow(2.0, -24.0) */
-double intpow2(int x);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define intpow2(x) (ldexp(1.0, (x)))
int gribrec_len(unsigned b1, unsigned b2, unsigned b3);
int correct_bdslen(int bdslen, long recsize, long gribpos);
@@ -5708,8 +5822,8 @@ void scale_complex_double(double *fpdata, int pcStart, int pcScale, int trunc,
void scale_complex_float(float *fpdata, int pcStart, int pcScale, int trunc, int inv);
void scatter_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
void scatter_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
-void gather_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
-void gather_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
+void gather_complex_double(double *fpdata, size_t pcStart, size_t trunc, size_t nsp);
+void gather_complex_float(float *fpdata, size_t pcStart, size_t trunc, size_t nsp);
void scm0_double(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
@@ -5749,7 +5863,11 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
-#endif /* _GRIB_INT_H */
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* GRIB_INT_H */
#ifndef _GRIBDECODE_H
#define _GRIBDECODE_H
@@ -5851,7 +5969,7 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define GDS_ScanFlag GET_UINT1(gds[27])
#define GDS_LatSP GET_INT3(gds[32], gds[33], gds[34])
#define GDS_LonSP GET_INT3(gds[35], gds[36], gds[37])
-#define GDS_RotAngle GET_Real(&(gds[38]))
+#define GDS_RotAngle (GET_Real(&(gds[38])))
/* GRIB1 Lambert */
#define GDS_Lambert_Lov GET_INT3(gds[17], gds[18], gds[19])
@@ -5876,9 +5994,9 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define BDS_Len ((int) ((bds[0]<<16)+(bds[1]<<8)+bds[2]))
#define BDS_Flag (bds[3])
#define BDS_BinScale GET_INT2(bds[ 4], bds[ 5])
-#define BDS_RefValue decfp2((int)bds[ 6], GET_UINT3(bds[ 7], bds[ 8], bds[ 9]))
+#define BDS_RefValue (decfp2((int)bds[ 6], GET_UINT3(bds[ 7], bds[ 8], bds[ 9])))
#define BDS_NumBits ((int) bds[10])
-#define BDS_RealCoef decfp2((int)bds[zoff+11], GET_UINT3(bds[zoff+12], bds[zoff+13], bds[zoff+14]))
+#define BDS_RealCoef (decfp2((int)bds[zoff+11], GET_UINT3(bds[zoff+12], bds[zoff+13], bds[zoff+14])))
#define BDS_PackData ((int) ((bds[zoff+11]<<8) + bds[zoff+12]))
#define BDS_Power GET_INT2(bds[zoff+13], bds[zoff+14])
#define BDS_Z (bds[13])
@@ -5897,21 +6015,20 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define PutnZero(n) \
{ \
- int i; \
- for ( i = z; i < z+n; i++ ) lGrib[i] = 0; \
+ for ( size_t i = z >= 0 ? (size_t)z : 0; i < (size_t)(z+n); i++ ) lGrib[i] = 0; \
z += n; \
}
-#define Put1Byte(Value) (lGrib[z++] = (Value))
-#define Put2Byte(Value) ((lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
-#define Put3Byte(Value) ((lGrib[z++] = (Value) >> 16), \
- (lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
-#define Put4Byte(Value) ((lGrib[z++] = (Value) >> 24), \
- (lGrib[z++] = (Value) >> 16), \
- (lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
+#define Put1Byte(Value) (lGrib[z++] = (GRIBPACK)(Value))
+#define Put2Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
+#define Put3Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
+#define Put4Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 24)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
#define Put1Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x80 - ival; Put1Byte(ival);}
#define Put2Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x8000 - ival; Put2Byte(ival);}
@@ -5925,278 +6042,21 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
}
#endif /* _GRIB_ENCODE_H */
-#include <stdio.h>
-#include <math.h>
-
-
-const double _pow2tab[158] = {
- /* pow(2.0, 0.0) */ 1.0,
- /* pow(2.0, 1.0) */ 2.0,
- /* pow(2.0, 2.0) */ 4.0,
- /* pow(2.0, 3.0) */ 8.0,
- /* pow(2.0, 4.0) */ 16.0,
- /* pow(2.0, 5.0) */ 32.0,
- /* pow(2.0, 6.0) */ 64.0,
- /* pow(2.0, 7.0) */ 128.0,
- /* pow(2.0, 8.0) */ 256.0,
- /* pow(2.0, 9.0) */ 512.0,
- /* pow(2.0, 10.0) */ 1024.0,
- /* pow(2.0, 11.0) */ 2048.0,
- /* pow(2.0, 12.0) */ 4096.0,
- /* pow(2.0, 13.0) */ 8192.0,
- /* pow(2.0, 14.0) */ 16384.0,
- /* pow(2.0, 15.0) */ 32768.0,
- /* pow(2.0, 16.0) */ 65536.0,
- /* pow(2.0, 17.0) */ 131072.0,
- /* pow(2.0, 18.0) */ 262144.0,
- /* pow(2.0, 19.0) */ 524288.0,
- /* pow(2.0, 20.0) */ 1048576.0,
- /* pow(2.0, 21.0) */ 2097152.0,
- /* pow(2.0, 22.0) */ 4194304.0,
- /* pow(2.0, 23.0) */ 8388608.0,
- /* pow(2.0, 24.0) */ 16777216.0,
- /* pow(2.0, 25.0) */ 33554432.0,
- /* pow(2.0, 26.0) */ 67108864.0,
- /* pow(2.0, 27.0) */ 134217728.0,
- /* pow(2.0, 28.0) */ 268435456.0,
- /* pow(2.0, 29.0) */ 536870912.0,
- /* pow(2.0, 30.0) */ 1073741824.0,
- /* pow(2.0, 31.0) */ 2147483648.0,
- /* pow(2.0, 32.0) */ 4294967296.0,
- /* pow(2.0, 33.0) */ 8589934592.0,
- /* pow(2.0, 34.0) */ 17179869184.0,
- /* pow(2.0, 35.0) */ 34359738368.0,
- /* pow(2.0, 36.0) */ 68719476736.0,
- /* pow(2.0, 37.0) */ 137438953472.0,
- /* pow(2.0, 38.0) */ 274877906944.0,
- /* pow(2.0, 39.0) */ 549755813888.0,
- /* pow(2.0, 40.0) */ 1099511627776.0,
- /* pow(2.0, 41.0) */ 2199023255552.0,
- /* pow(2.0, 42.0) */ 4398046511104.0,
- /* pow(2.0, 43.0) */ 8796093022208.0,
- /* pow(2.0, 44.0) */ 17592186044416.0,
- /* pow(2.0, 45.0) */ 35184372088832.0,
- /* pow(2.0, 46.0) */ 70368744177664.0,
- /* pow(2.0, 47.0) */ 140737488355328.0,
- /* pow(2.0, 48.0) */ 281474976710656.0,
- /* pow(2.0, 49.0) */ 562949953421312.0,
- /* pow(2.0, 50.0) */ 1125899906842624.0,
- /* pow(2.0, 51.0) */ 2251799813685248.0,
- /* pow(2.0, 52.0) */ 4503599627370496.0,
- /* pow(2.0, 53.0) */ 9007199254740992.0,
- /* pow(2.0, 54.0) */ 18014398509481984.0,
- /* pow(2.0, 55.0) */ 36028797018963968.0,
- /* pow(2.0, 56.0) */ 72057594037927936.0,
- /* pow(2.0, 57.0) */ 144115188075855872.0,
- /* pow(2.0, 58.0) */ 288230376151711744.0,
- /* pow(2.0, 59.0) */ 576460752303423488.0,
- /* pow(2.0, 60.0) */ 1152921504606846976.0,
- /* pow(2.0, 61.0) */ 2305843009213693952.0,
- /* pow(2.0, 62.0) */ 4611686018427387904.0,
- /* pow(2.0, 63.0) */ 9223372036854775808.0,
- /* pow(2.0, 64.0) */ 18446744073709551616.0,
- /* pow(2.0, 65.0) */ 36893488147419103232.0,
- /* pow(2.0, 66.0) */ 73786976294838206464.0,
- /* pow(2.0, 67.0) */ 147573952589676412928.0,
- /* pow(2.0, 68.0) */ 295147905179352825856.0,
- /* pow(2.0, 69.0) */ 590295810358705651712.0,
- /* pow(2.0, 70.0) */ 1180591620717411303424.0,
- /* pow(2.0, 71.0) */ 2361183241434822606848.0,
- /* pow(2.0, 72.0) */ 4722366482869645213696.0,
- /* pow(2.0, 73.0) */ 9444732965739290427392.0,
- /* pow(2.0, 74.0) */ 18889465931478580854784.0,
- /* pow(2.0, 75.0) */ 37778931862957161709568.0,
- /* pow(2.0, 76.0) */ 75557863725914323419136.0,
- /* pow(2.0, 77.0) */ 151115727451828646838272.0,
- /* pow(2.0, 78.0) */ 302231454903657293676544.0,
- /* pow(2.0, 79.0) */ 604462909807314587353088.0,
- /* pow(2.0, 80.0) */ 1208925819614629174706176.0,
- /* pow(2.0, 81.0) */ 2417851639229258349412352.0,
- /* pow(2.0, 82.0) */ 4835703278458516698824704.0,
- /* pow(2.0, 83.0) */ 9671406556917033397649408.0,
- /* pow(2.0, 84.0) */ 19342813113834066795298816.0,
- /* pow(2.0, 85.0) */ 38685626227668133590597632.0,
- /* pow(2.0, 86.0) */ 77371252455336267181195264.0,
- /* pow(2.0, 87.0) */ 154742504910672534362390528.0,
- /* pow(2.0, 88.0) */ 309485009821345068724781056.0,
- /* pow(2.0, 89.0) */ 618970019642690137449562112.0,
- /* pow(2.0, 90.0) */ 1237940039285380274899124224.0,
- /* pow(2.0, 91.0) */ 2475880078570760549798248448.0,
- /* pow(2.0, 92.0) */ 4951760157141521099596496896.0,
- /* pow(2.0, 93.0) */ 9903520314283042199192993792.0,
- /* pow(2.0, 94.0) */ 19807040628566084398385987584.0,
- /* pow(2.0, 95.0) */ 39614081257132168796771975168.0,
- /* pow(2.0, 96.0) */ 79228162514264337593543950336.0,
- /* pow(2.0, 97.0) */ 158456325028528675187087900672.0,
- /* pow(2.0, 98.0) */ 316912650057057350374175801344.0,
- /* pow(2.0, 99.0) */ 633825300114114700748351602688.0,
- /* pow(2.0, 100.0) */ 1267650600228229401496703205376.0,
- /* pow(2.0, 101.0) */ 2535301200456458802993406410752.0,
- /* pow(2.0, 102.0) */ 5070602400912917605986812821504.0,
- /* pow(2.0, 103.0) */ 10141204801825835211973625643008.0,
- /* pow(2.0, 104.0) */ 20282409603651670423947251286016.0,
- /* pow(2.0, 105.0) */ 40564819207303340847894502572032.0,
- /* pow(2.0, 106.0) */ 81129638414606681695789005144064.0,
- /* pow(2.0, 107.0) */ 162259276829213363391578010288128.0,
- /* pow(2.0, 108.0) */ 324518553658426726783156020576256.0,
- /* pow(2.0, 109.0) */ 649037107316853453566312041152512.0,
- /* pow(2.0, 110.0) */ 1298074214633706907132624082305024.0,
- /* pow(2.0, 111.0) */ 2596148429267413814265248164610048.0,
- /* pow(2.0, 112.0) */ 5192296858534827628530496329220096.0,
- /* pow(2.0, 113.0) */ 10384593717069655257060992658440192.0,
- /* pow(2.0, 114.0) */ 20769187434139310514121985316880384.0,
- /* pow(2.0, 115.0) */ 41538374868278621028243970633760768.0,
- /* pow(2.0, 116.0) */ 83076749736557242056487941267521536.0,
- /* pow(2.0, 117.0) */ 166153499473114484112975882535043072.0,
- /* pow(2.0, 118.0) */ 332306998946228968225951765070086144.0,
- /* pow(2.0, 119.0) */ 664613997892457936451903530140172288.0,
- /* pow(2.0, 120.0) */ 1329227995784915872903807060280344576.0,
- /* pow(2.0, 121.0) */ 2658455991569831745807614120560689152.0,
- /* pow(2.0, 122.0) */ 5316911983139663491615228241121378304.0,
- /* pow(2.0, 123.0) */ 10633823966279326983230456482242756608.0,
- /* pow(2.0, 124.0) */ 21267647932558653966460912964485513216.0,
- /* pow(2.0, 125.0) */ 42535295865117307932921825928971026432.0,
- /* pow(2.0, 126.0) */ 85070591730234615865843651857942052864.0,
- /* pow(2.0, 127.0) */ 170141183460469231731687303715884105728.0,
- /* pow(2.0, 128.0) */ 340282366920938463463374607431768211456.0,
- /* pow(2.0, 129.0) */ 680564733841876926926749214863536422912.0,
- /* pow(2.0, 130.0) */ 1361129467683753853853498429727072845824.0,
- /* pow(2.0, 131.0) */ 2722258935367507707706996859454145691648.0,
- /* pow(2.0, 132.0) */ 5444517870735015415413993718908291383296.0,
- /* pow(2.0, 133.0) */ 10889035741470030830827987437816582766592.0,
- /* pow(2.0, 134.0) */ 21778071482940061661655974875633165533184.0,
- /* pow(2.0, 135.0) */ 43556142965880123323311949751266331066368.0,
- /* pow(2.0, 136.0) */ 87112285931760246646623899502532662132736.0,
- /* pow(2.0, 137.0) */ 174224571863520493293247799005065324265472.0,
- /* pow(2.0, 138.0) */ 348449143727040986586495598010130648530944.0,
- /* pow(2.0, 139.0) */ 696898287454081973172991196020261297061888.0,
- /* pow(2.0, 140.0) */ 1393796574908163946345982392040522594123776.0,
- /* pow(2.0, 141.0) */ 2787593149816327892691964784081045188247552.0,
- /* pow(2.0, 142.0) */ 5575186299632655785383929568162090376495104.0,
- /* pow(2.0, 143.0) */ 11150372599265311570767859136324180752990208.0,
- /* pow(2.0, 144.0) */ 22300745198530623141535718272648361505980416.0,
- /* pow(2.0, 145.0) */ 44601490397061246283071436545296723011960832.0,
- /* pow(2.0, 146.0) */ 89202980794122492566142873090593446023921664.0,
- /* pow(2.0, 147.0) */ 178405961588244985132285746181186892047843328.0,
- /* pow(2.0, 148.0) */ 356811923176489970264571492362373784095686656.0,
- /* pow(2.0, 149.0) */ 713623846352979940529142984724747568191373312.0,
- /* pow(2.0, 150.0) */ 1427247692705959881058285969449495136382746624.0,
- /* pow(2.0, 151.0) */ 2854495385411919762116571938898990272765493248.0,
- /* pow(2.0, 152.0) */ 5708990770823839524233143877797980545530986496.0,
- /* pow(2.0, 153.0) */ 11417981541647679048466287755595961091061972992.0,
- /* pow(2.0, 154.0) */ 22835963083295358096932575511191922182123945984.0,
- /* pow(2.0, 155.0) */ 45671926166590716193865151022383844364247891968.0,
- /* pow(2.0, 156.0) */ 91343852333181432387730302044767688728495783936.0,
- /* pow(2.0, 157.0) */ 182687704666362864775460604089535377456991567872.0,
-};
-
-
-const double _pow16tab[71] = {
- /* pow(16.0, 0.0) */ 1.0,
- /* pow(16.0, 1.0) */ 16.0,
- /* pow(16.0, 2.0) */ 256.0,
- /* pow(16.0, 3.0) */ 4096.0,
- /* pow(16.0, 4.0) */ 65536.0,
- /* pow(16.0, 5.0) */ 1048576.0,
- /* pow(16.0, 6.0) */ 16777216.0,
- /* pow(16.0, 7.0) */ 268435456.0,
- /* pow(16.0, 8.0) */ 4294967296.0,
- /* pow(16.0, 9.0) */ 68719476736.0,
- /* pow(16.0, 10.0) */ 1099511627776.0,
- /* pow(16.0, 11.0) */ 17592186044416.0,
- /* pow(16.0, 12.0) */ 281474976710656.0,
- /* pow(16.0, 13.0) */ 4503599627370496.0,
- /* pow(16.0, 14.0) */ 72057594037927936.0,
- /* pow(16.0, 15.0) */ 1152921504606846976.0,
- /* pow(16.0, 16.0) */ 18446744073709551616.0,
- /* pow(16.0, 17.0) */ 295147905179352825856.0,
- /* pow(16.0, 18.0) */ 4722366482869645213696.0,
- /* pow(16.0, 19.0) */ 75557863725914323419136.0,
- /* pow(16.0, 20.0) */ 1208925819614629174706176.0,
- /* pow(16.0, 21.0) */ 19342813113834066795298816.0,
- /* pow(16.0, 22.0) */ 309485009821345068724781056.0,
- /* pow(16.0, 23.0) */ 4951760157141521099596496896.0,
- /* pow(16.0, 24.0) */ 79228162514264337593543950336.0,
- /* pow(16.0, 25.0) */ 1267650600228229401496703205376.0,
- /* pow(16.0, 26.0) */ 20282409603651670423947251286016.0,
- /* pow(16.0, 27.0) */ 324518553658426726783156020576256.0,
- /* pow(16.0, 28.0) */ 5192296858534827628530496329220096.0,
- /* pow(16.0, 29.0) */ 83076749736557242056487941267521536.0,
- /* pow(16.0, 30.0) */ 1329227995784915872903807060280344576.0,
- /* pow(16.0, 31.0) */ 21267647932558653966460912964485513216.0,
- /* pow(16.0, 32.0) */ 340282366920938463463374607431768211456.0,
- /* pow(16.0, 33.0) */ 5444517870735015415413993718908291383296.0,
- /* pow(16.0, 34.0) */ 87112285931760246646623899502532662132736.0,
- /* pow(16.0, 35.0) */ 1393796574908163946345982392040522594123776.0,
- /* pow(16.0, 36.0) */ 22300745198530623141535718272648361505980416.0,
- /* pow(16.0, 37.0) */ 356811923176489970264571492362373784095686656.0,
- /* pow(16.0, 38.0) */ 5708990770823839524233143877797980545530986496.0,
- /* pow(16.0, 39.0) */ 91343852333181432387730302044767688728495783936.0,
- /* pow(16.0, 40.0) */ 1461501637330902918203684832716283019655932542976.0,
- /* pow(16.0, 41.0) */ 23384026197294446691258957323460528314494920687616.0,
- /* pow(16.0, 42.0) */ 374144419156711147060143317175368453031918731001856.0,
- /* pow(16.0, 43.0) */ 5986310706507378352962293074805895248510699696029696.0,
- /* pow(16.0, 44.0) */ 95780971304118053647396689196894323976171195136475136.0,
- /* pow(16.0, 45.0) */ 1532495540865888858358347027150309183618739122183602176.0,
- /* pow(16.0, 46.0) */ 24519928653854221733733552434404946937899825954937634816.0,
- /* pow(16.0, 47.0) */ 392318858461667547739736838950479151006397215279002157056.0,
- /* pow(16.0, 48.0) */ 6277101735386680763835789423207666416102355444464034512896.0,
- /* pow(16.0, 49.0) */ 100433627766186892221372630771322662657637687111424552206336.0,
- /* pow(16.0, 50.0) */ 1606938044258990275541962092341162602522202993782792835301376.0,
- /* pow(16.0, 51.0) */ 25711008708143844408671393477458601640355247900524685364822016.0,
- /* pow(16.0, 52.0) */ 411376139330301510538742295639337626245683966408394965837152256.0,
- /* pow(16.0, 53.0) */ 6582018229284824168619876730229402019930943462534319453394436096.0,
- /* pow(16.0, 54.0) */ 105312291668557186697918027683670432318895095400549111254310977536.0,
- /* pow(16.0, 55.0) */ 1684996666696914987166688442938726917102321526408785780068975640576.0,
- /* pow(16.0, 56.0) */ 26959946667150639794667015087019630673637144422540572481103610249216.0,
- /* pow(16.0, 57.0) */ 431359146674410236714672241392314090778194310760649159697657763987456.0,
- /* pow(16.0, 58.0) */ 6901746346790563787434755862277025452451108972170386555162524223799296.0,
- /* pow(16.0, 59.0) */ 110427941548649020598956093796432407239217743554726184882600387580788736.0,
- /* pow(16.0, 60.0) */ 1766847064778384329583297500742918515827483896875618958121606201292619776.0,
- /* pow(16.0, 61.0) */ 28269553036454149273332760011886696253239742350009903329945699220681916416.0,
- /* pow(16.0, 62.0) */ 452312848583266388373324160190187140051835877600158453279131187530910662656.0,
- /* pow(16.0, 63.0) */ 7237005577332262213973186563042994240829374041602535252466099000494570602496.0,
- /* pow(16.0, 64.0) */ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
- /* pow(16.0, 65.0) */ 1852673427797059126777135760139006525652319754650249024631321344126610074238976.0,
- /* pow(16.0, 66.0) */ 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0,
- /* pow(16.0, 67.0) */ 474284397516047136454946754595585670566993857190463750305618264096412179005177856.0,
- /* pow(16.0, 68.0) */ 7588550360256754183279148073529370729071901715047420004889892225542594864082845696.0,
- /* pow(16.0, 69.0) */ 121416805764108066932466369176469931665150427440758720078238275608681517825325531136.0,
- /* pow(16.0, 70.0) */ 1942668892225729070919461906823518906642406839052139521251812409738904285205208498176.0,
-};
-
-static int _pow2tab_size = sizeof(_pow2tab)/sizeof(double);
-
-void gen_pow2tab(void)
-{
- int jloop;
-
- for ( jloop = 0; jloop < 158; jloop++ )
- printf(" /* pow(2.0, %2d.0) */ %.1f,\n", jloop, pow(2.0, (double) jloop));
-}
-
-
-void gen_pow16tab(void)
-{
- double pval;
- int iexp;
-
- for ( iexp = 0; iexp < 71; iexp++ )
- {
- pval = pow(16.0, (double)(iexp));
- printf(" /* pow(16.0, %2d.0) */ %.1f,\n", iexp, pval);
- }
-}
-
-
-double intpow2(int x)
-{
- if ( x < _pow2tab_size )
- return (_pow2tab[x]);
- else
- return (pow(2.0, (double) x));
-}
+#ifndef CODEC_COMMON_H
+#define CODEC_COMMON_H
+#define gribSwapByteOrder_uint16(ui16) ((uint16_t)((ui16<<8) | (ui16>>8)))
+#endif /* CODEC_COMMON_H */
/*
+icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
+ result on hama2 (icc 16.0.0):
+ float:
+minmax_val: fmin: -500000 fmax: 499999 time: 0.63s
+ double:
+minmax_val: fmin: -500000 fmax: 499999 time: 2.98s
+orig : fmin: -500000 fmax: 499999 time: 2.83s
+simd : fmin: -500000 fmax: 499999 time: 2.82s
+avx : fmin: -500000 fmax: 499999 time: 3.17s
+
gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
result on bailung (gcc 4.8.2):
orig : fmin: -500000 fmax: 499999 time: 4.82s
@@ -6214,16 +6074,6 @@ icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp
simd : fmin: -500000 fmax: 499999 time: 2.83s
avx : fmin: -500000 fmax: 499999 time: 2.92s
-icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
- result on hama (icc 15.0.1):
- float:
- minmax_val: fmin: -500000 fmax: 499999 time: 0.60s
- double:
- minmax_val: fmin: -500000 fmax: 499999 time: 3.06s
- orig : fmin: -500000 fmax: 499999 time: 2.66s
- simd : fmin: -500000 fmax: 499999 time: 6.65s
- avx : fmin: -500000 fmax: 499999 time: 3.11s
-
xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax_val.c
result on blizzard (xlc 12):
orig : fmin: -500000 fmax: 499999 time: 7.26s
@@ -6469,10 +6319,9 @@ void sse2_minmax_val_double(const double *restrict buf, size_t nframes, double *
#if defined(_ARCH_PWR6)
static
-void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void pwr6_minmax_val_double_unrolled6(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
#define __UNROLL_DEPTH_1 6
- size_t datasize = idatasize;
// to allow pipelining we have to unroll
@@ -6516,9 +6365,9 @@ void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasiz
#if defined(TEST_MINMAXVAL) && defined(__GNUC__)
static
-void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
static
-void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
#endif
#if defined(GNUC_PUSH_POP)
@@ -6526,10 +6375,8 @@ void minmax_val_double_simd(const double *restrict data, long idatasize, double
#pragma GCC optimize ("O3", "fast-math")
#endif
static
-void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
- size_t i;
- size_t datasize = idatasize;
double dmin = *fmin, dmax = *fmax;
#if defined(CRAY)
@@ -6541,7 +6388,7 @@ void minmax_val_double_orig(const double *restrict data, long idatasize, double
#elif defined (__ICC)
#pragma ivdep
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -6554,8 +6401,7 @@ void minmax_val_double_orig(const double *restrict data, long idatasize, double
static
void minmax_val_float(const float *restrict data, long idatasize, float *fmin, float *fmax)
{
- size_t i;
- size_t datasize = idatasize;
+ size_t datasize = (size_t)idatasize;
float dmin = *fmin, dmax = *fmax;
#if defined(CRAY)
@@ -6567,7 +6413,7 @@ void minmax_val_float(const float *restrict data, long idatasize, float *fmin, f
#elif defined (__ICC)
#pragma ivdep
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -6583,25 +6429,19 @@ void minmax_val_float(const float *restrict data, long idatasize, float *fmin, f
// TEST
#if defined(OMP_SIMD)
-//#pragma omp declare reduction(xmin : double : omp_out = omp_in > omp_out ? omp_out : omp_in) initializer( omp_priv = { 1.e300 })
-//#pragma omp declare reduction(xmax : double : omp_out = omp_in < omp_out ? omp_out : omp_in) initializer( omp_priv = { -1.e300 })
-
#if defined(GNUC_PUSH_POP)
#pragma GCC push_options
#pragma GCC optimize ("O3", "fast-math")
#endif
static
-void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
- size_t i;
- size_t datasize = idatasize;
double dmin = *fmin, dmax = *fmax;
#if defined(_OPENMP)
- //#pragma omp simd reduction(xmin:dmin) reduction(xmax:dmax)
-#pragma omp simd
+#pragma omp simd reduction(min:dmin) reduction(max:dmax)
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -6621,9 +6461,9 @@ void minmax_val_double(const double *restrict data, long idatasize, double *fmin
#if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER)
uint64_t start_minmax, end_minmax;
#endif
- size_t datasize = idatasize;
+ size_t datasize = (size_t)idatasize;
- if ( idatasize < 1 ) return;
+ if ( idatasize >= 1 ) ; else return;
#if defined(_GET_X86_COUNTER)
start_minmax = _rdtsc();
@@ -6732,7 +6572,7 @@ int main(void)
{
float fmin, fmax;
- float *data_sp = (float*) Malloc(datasize*sizeof(float));
+ float *data_sp = (float*) malloc(datasize*sizeof(float));
for ( long i = 0; i < datasize/2; i++ ) data_sp[i] = (float) (i);
for ( long i = datasize/2; i < datasize; i++ ) data_sp[i] = (float) (-datasize + i);
@@ -6747,12 +6587,12 @@ int main(void)
}
t_end = dtime();
printf("minmax_val: fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
- Free(data_sp);
+ free(data_sp);
}
{
double fmin, fmax;
- double *data_dp = (double*) Malloc(datasize*sizeof(double));
+ double *data_dp = (double*) malloc(datasize*sizeof(double));
// for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
for ( long i = 0; i < datasize/2; i++ ) data_dp[i] = (double) (i);
@@ -6818,7 +6658,7 @@ int main(void)
t_end = dtime();
printf("pwr6u6 : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
#endif
- Free(data_dp);
+ free(data_dp);
}
return (0);
@@ -6829,20 +6669,48 @@ int main(void)
#undef _ENABLE_AVX
#undef _ENABLE_SSE2
#undef GNUC_PUSH_POP
-/*
+/*
+### new version with gribSwapByteOrder_uint16()
icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
- result on hama (icc 15.0.1):
- float:
- orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.7936s
+ result on hama2 (icc 16.0.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 1.8731s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 2.0898s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.68089s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.30798s
+ avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.23864s
+
+gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama2 (gcc 5.2.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.96739s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.30871s
double:
- orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 13.6093s
- avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.90009s
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 6.24448s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.66679s
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
- result on hama (gcc 4.8.2):
- orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 16.0471s
- sse41 : val1: 1 val2: 1 val3: 2 valn: 66 time: 15.4391s
+###
+icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
+ result on hama2 (icc 16.0.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.10691s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.63584s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 13.5768s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.17742s
+ avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.9488s
+
+gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama2 (gcc 5.2.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 5.32775s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.87125s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.85873s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 12.9979s
+###
gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
result on bailung (gcc 4.7):
orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 8.4166s
@@ -7207,14 +7075,11 @@ void pout(char *name, int s, unsigned char *lgrib, long datasize, double tt)
int main(void)
{
long datasize = 1000000;
- float *dataf = NULL;
- double *data = NULL;
double t_begin, t_end;
- unsigned char *lgrib;
- dataf = (float*) Malloc(datasize*sizeof(float));
- data = (double*) Malloc(datasize*sizeof(double));
- lgrib = (unsigned char*) Malloc(2*datasize*sizeof(unsigned char));
+ float *dataf = (float*) malloc(datasize*sizeof(float));
+ double *data = (double*) malloc(datasize*sizeof(double));
+ unsigned char *lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
for ( long i = 0; i < datasize; ++i ) dataf[i] = (float) (-datasize/2 + i);
for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
@@ -7232,7 +7097,6 @@ int main(void)
encode_array_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
}
-
#if defined(__ICC)
printf("icc\n");
#elif defined(__clang__)
@@ -7308,240 +7172,6 @@ int main(void)
#undef DISABLE_SIMD
#undef _ENABLE_AVX
#undef _ENABLE_SSE4_1
-//#undef _GET_X86_COUNTER
-//#undef _GET_MACH_COUNTER
-//#undef _GET_IBM_COUNTER
-//#undef _ARCH_PWR6
-
-#if defined _GET_IBM_COUNTER
-#include <libhpc.h>
-#elif defined _GET_X86_COUNTER
-#include <x86intrin.h>
-#elif defined _GET_MACH_COUNTER
-#include <mach/mach_time.h>
-#endif
-
-#ifdef __cplusplus
-#define __STDC_FORMAT_MACROS
-#endif
-#include <inttypes.h>
-
-#if defined(__GNUC__) && (__GNUC__ >= 4)
-#elif defined(__ICC) && (__ICC >= 1100)
-#elif defined(__clang__)
-#else
-#define DISABLE_SIMD
-#endif
-
-#define DISABLE_SIMD
-
-#ifdef DISABLE_SIMD
-# ifdef ENABLE_AVX
-# define _ENABLE_AVX
-# endif
-# ifdef ENABLE_SSE4_1
-# define _ENABLE_SSE4_1
-# endif
-#endif
-
-#ifndef DISABLE_SIMD
-# ifdef __AVX__
-# define _ENABLE_AVX
-# endif
-# ifdef __SSE4_1__
-# define _ENABLE_SSE4_1
-# endif
-#endif
-
-#if defined _ENABLE_AVX
-#include <immintrin.h>
-#elif defined _ENABLE_SSE4_1
-#include <smmintrin.h>
-#endif
-
-#if defined _ENABLE_AVX
-
-static
-void avx_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
- double * restrict fpdata, double fmin, double zscale)
-{
- size_t i, j;
- size_t nframes = datasize;
- size_t residual;
- size_t ofs;
-
- double dval;
-
- double *data = fpdata;
- __m128i *sgrib;
-
- __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
-
- __m256d ymm0 = _mm256_set1_pd(fmin);
- __m256d ymm1 = _mm256_set1_pd(zscale);
-
- __m128i xmm0, xmm1, xmm2, xmm3;
- __m256d ymm2, ymm3;
-
- i = -1;
- while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
- {
- i++;
- dval = (((int)igrib[2*i] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- data++;
- nframes--;
- }
-
- if (i == -1) i = 0;
- sgrib = (__m128i *) (igrib+i);
-
- while (nframes >= 16)
- {
- xmm0 = _mm_loadu_si128((__m128i *) sgrib);
- xmm0 = _mm_shuffle_epi8(xmm0, mask);
- xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
- xmm2 = _mm_cvtepu16_epi32(xmm0);
- xmm3 = _mm_cvtepu16_epi32(xmm1);
-
- ymm2 = _mm256_cvtepi32_pd(xmm2);
- ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
- (void) _mm256_stream_pd(data, ymm2);
- ymm3 = _mm256_cvtepi32_pd(xmm3);
- ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
- (void) _mm256_stream_pd(data+4, ymm3);
-
- xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
- xmm0 = _mm_shuffle_epi8(xmm0, mask);
- xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
- xmm2 = _mm_cvtepu16_epi32(xmm0);
- xmm3 = _mm_cvtepu16_epi32(xmm1);
-
- ymm2 = _mm256_cvtepi32_pd(xmm2);
- ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
- (void) _mm256_stream_pd(data+8, ymm2);
- ymm3 = _mm256_cvtepi32_pd(xmm3);
- ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
- (void) _mm256_stream_pd(data+12, ymm3);
-
- data += 16;
- sgrib += 2;
- nframes -= 16;
- }
-
- residual = nframes;
- ofs = datasize - residual;
- for ( j = 0; j < residual; j++ )
- {
- dval = (((int)igrib[2*(ofs+j)] << 8) | (int)igrib[2*(ofs+j)+1]);
- fpdata[ofs+j] = fmin + zscale * dval;
- }
-
- return;
-}
-
-#elif defined _ENABLE_SSE4_1
-
-static
-void sse41_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
- double * restrict fpdata, double fmin, double zscale)
-{
- size_t i, j;
- size_t nframes = datasize;
- size_t residual;
- size_t ofs;
-
- double dval;
-
- double *data = fpdata;
- __m128i *sgrib;
-
- __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
- __m128d dmm8 = _mm_set1_pd(fmin);
- __m128d dmm9 = _mm_set1_pd(zscale);
-
- __m128i xmm4, xmm5;
- __m128i xmm6, xmm7;
-
- __m128d dmm0, dmm1, dmm2, dmm3;
- __m128d dmm4, dmm5, dmm6, dmm7;
-
- i = -1;
- while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
- {
- i++;
- dval = (((int)igrib[2*i] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- data++;
- nframes--;
- }
-
- if (i == -1) i = 0;
- sgrib = (__m128i *) (igrib+i);
-
- while (nframes >= 16)
- {
- xmm5 = _mm_loadu_si128((__m128i *) sgrib);
- xmm5 = _mm_shuffle_epi8(xmm5, mask);
- xmm4 = _mm_srli_si128(xmm5, 8);
- xmm6 = _mm_cvtepu16_epi32(xmm5);
- dmm0 = _mm_cvtepi32_pd(xmm6);
- dmm0 = _mm_add_pd(_mm_mul_pd(dmm0, dmm9), dmm8);
- (void) _mm_stream_pd(data, dmm0);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm1 = _mm_cvtepi32_pd(xmm7);
- dmm1 = _mm_add_pd(_mm_mul_pd(dmm1, dmm9), dmm8);
- (void) _mm_stream_pd(data+2, dmm1);
- xmm6 = _mm_cvtepu16_epi32(xmm4);
- dmm2 = _mm_cvtepi32_pd(xmm6);
- dmm2 = _mm_add_pd(_mm_mul_pd(dmm2, dmm9), dmm8);
- (void) _mm_stream_pd(data+4, dmm2);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm3 = _mm_cvtepi32_pd(xmm7);
- dmm3 = _mm_add_pd(_mm_mul_pd(dmm3, dmm9), dmm8);
- (void) _mm_stream_pd(data+6, dmm3);
-
- xmm5 = _mm_loadu_si128((__m128i *) sgrib+1);
- xmm5 = _mm_shuffle_epi8(xmm5, mask);
- xmm4 = _mm_srli_si128(xmm5, 8);
- xmm6 = _mm_cvtepu16_epi32(xmm5);
- dmm4 = _mm_cvtepi32_pd(xmm6);
- dmm4 = _mm_add_pd(_mm_mul_pd(dmm4, dmm9), dmm8);
- (void) _mm_stream_pd(data+8, dmm4);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm5 = _mm_cvtepi32_pd(xmm7);
- dmm5 = _mm_add_pd(_mm_mul_pd(dmm5, dmm9), dmm8);
- (void) _mm_stream_pd(data+10, dmm5);
- xmm6 = _mm_cvtepu16_epi32(xmm4);
- dmm6 = _mm_cvtepi32_pd(xmm6);
- dmm6 = _mm_add_pd(_mm_mul_pd(dmm6, dmm9), dmm8);
- (void) _mm_stream_pd(data+12, dmm6);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm7 = _mm_cvtepi32_pd(xmm7);
- dmm7 = _mm_add_pd(_mm_mul_pd(dmm7, dmm9), dmm8);
- (void) _mm_stream_pd(data+14, dmm7);
-
- data += 16;
- sgrib += 2;
- nframes -= 16;
- }
-
- residual = nframes;
- ofs = datasize - residual;
- for ( j = 0; j < residual; j++ )
- {
- dval = (((int)igrib[2*(ofs+j)] << 8) | (int)igrib[2*(ofs+j)+1]);
- fpdata[ofs+j] = fmin + zscale * dval;
- }
-
- return;
-}
-
-#endif
-
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
@@ -7612,12 +7242,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
- replace 1.0 / pow(16.0, (double)(iexp - 70)) by rpow16m70tab[iexp]
*/
- double rpowref;
- double zref, zeps;
- int iexp, isign;
- int iround;
// extern int CGRIBEX_Debug;
- extern const double _pow16tab[71];
/* ----------------------------------------------------------------- */
/* Section 1 . Initialise */
@@ -7625,7 +7250,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* Check conversion type parameter. */
- iround = kround;
+ int iround = kround;
if ( iround != 0 && iround != 1 )
{
Error("Invalid conversion type = %d", iround);
@@ -7650,42 +7275,35 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* ----------------------------------------------------------------- */
/* Section 3 . Convert other values. */
/* ----------------------------------------------------------------- */
+ {
+ double zeps = kbits != 32 ? 1.0e-12 : 1.0e-8;
+ double zref = pval;
- zeps = 1.0e-12;
- if ( kbits == 32 ) zeps = 1.0e-8;
- zref = pval;
+ /* Sign of value. */
- /* Sign of value. */
-
- isign = 0;
- if ( zref < 0.0 )
- {
- isign = 128;
- zref = - zref;
- }
+ int isign = zref >= 0.0 ? 0 : 128;
+ zref = fabs(zref);
- /* Exponent. */
+ /* Exponent. */
- iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
+ int iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
- /* only ANSI C99 has log2 */
- /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
+ /* only ANSI C99 has log2 */
+ /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
- if ( iexp < 0 ) iexp = 0;
- if ( iexp > 127 ) iexp = 127;
+ if ( iexp < 0 ) iexp = 0;
+ if ( iexp > 127 ) iexp = 127;
- /*
- rpowref = zref / pow(16.0, (double)(iexp - 70));
- */
+ double rpowref;
+ /*
+ rpowref = zref / pow(16.0, (double)(iexp - 70));
+ */
- if ( (iexp - 70) < 0 )
- rpowref = zref * _pow16tab[-(iexp - 70)];
- else
- rpowref = zref / _pow16tab[(iexp - 70)];
+ rpowref = ldexp(zref, 4 * -(iexp - 70));
- /* Mantissa. */
+ /* Mantissa. */
- if ( iround == 0 )
+ if ( iround == 0 )
{
/* Closest number in GRIB format less than original number. */
/* Truncate for positive numbers. */
@@ -7696,7 +7314,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
else
*kmant = (int)lround(rpowref + 0.5);
}
- else
+ else
{
/* Closest number in GRIB format to the original number */
/* (equal to, greater than or less than original number). */
@@ -7704,12 +7322,12 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
*kmant = (int)lround(rpowref);
}
- /* Check that mantissa value does not exceed 24 bits. */
- /* If it does, adjust the exponent upwards and recalculate */
- /* the mantissa. */
- /* 16777215 = 2**24 - 1 */
+ /* Check that mantissa value does not exceed 24 bits. */
+ /* If it does, adjust the exponent upwards and recalculate */
+ /* the mantissa. */
+ /* 16777215 = 2**24 - 1 */
- if ( *kmant > 16777215 )
+ if ( *kmant > 16777215 )
{
LABEL350:
@@ -7719,47 +7337,44 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* Check for exponent overflow during adjustment */
if ( iexp > 127 )
- {
- Message("Exponent overflow");
- Message("Original number = %30.20f", pval);
- Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
- isign, iexp, *kmant);
+ {
+ Message("Exponent overflow");
+ Message("Original number = %30.20f", pval);
+ Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
+ isign, iexp, *kmant);
- Error("Exponent overflow");
+ Error("Exponent overflow");
- /* If not aborting, arbitrarily set value to zero */
+ /* If not aborting, arbitrarily set value to zero */
- Message("Value arbitrarily set to zero.");
- *kexp = 0;
- *kmant = 0;
- // iexp = 0;
- // isign = 0;
- goto LABEL900;
- }
+ Message("Value arbitrarily set to zero.");
+ *kexp = 0;
+ *kmant = 0;
+ // iexp = 0;
+ // isign = 0;
+ goto LABEL900;
+ }
- if ( (iexp - 70) < 0 )
- rpowref = zref * _pow16tab[-(iexp - 70)];
- else
- rpowref = zref / _pow16tab[(iexp - 70)];
+ rpowref = ldexp(zref, 4 * -(iexp - 70));
if ( iround == 0 )
- {
- /* Closest number in GRIB format less than original number. */
- /* Truncate for positive numbers. */
- /* Round up for negative numbers. */
+ {
+ /* Closest number in GRIB format less than original number. */
+ /* Truncate for positive numbers. */
+ /* Round up for negative numbers. */
- if ( isign == 0 )
- *kmant = (int)rpowref;
- else
- *kmant = (int)lround(rpowref + 0.5);
- }
+ if ( isign == 0 )
+ *kmant = (int)rpowref;
+ else
+ *kmant = (int)lround(rpowref + 0.5);
+ }
else
- {
- /* Closest number in GRIB format to the original number */
- /* (equal to, greater or less than original number). */
+ {
+ /* Closest number in GRIB format to the original number */
+ /* (equal to, greater or less than original number). */
- *kmant = (int)lround(rpowref);
- }
+ *kmant = (int)lround(rpowref);
+ }
/* Repeat calculation (with modified exponent) if still have */
/* mantissa overflow. */
@@ -7767,9 +7382,10 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
if ( *kmant > 16777215 ) goto LABEL350;
}
- /* Add sign bit to exponent. */
+ /* Add sign bit to exponent. */
- *kexp = iexp + isign;
+ *kexp = iexp + isign;
+ }
/* ----------------------------------------------------------------- */
/* Section 9. Return */
@@ -7792,6 +7408,7 @@ LABEL900:
*/
return;
} /* confp3 */
+#include <math.h>
double decfp2(int kexp, int kmant)
@@ -7853,7 +7470,7 @@ double decfp2(int kexp, int kmant)
Uwe Schulzweida MPIfM 01/04/2001
- Convert to C from EMOS library version 130
-
+
Uwe Schulzweida MPIfM 02/08/2002
- speed up by factor 2 on NEC SX6
@@ -7862,10 +7479,7 @@ double decfp2(int kexp, int kmant)
*/
double pval;
- int iexp, isign;
//extern int CGRIBEX_Debug;
- extern const double _pow16tab[71];
-
/* ----------------------------------------------------------------- */
/* Section 1 . Convert value of 0.0. Ignore sign bit. */
/* ----------------------------------------------------------------- */
@@ -7886,14 +7500,10 @@ double decfp2(int kexp, int kmant)
/* Sign of value. */
- iexp = kexp;
- isign = 1;
+ int iexp = kexp,
+ isign = (iexp < 128) * 2 - 1;
- if ( iexp >= 128 )
- {
- iexp -= 128;
- isign = -1;
- }
+ iexp -= iexp < 128 ? 0 : 128;
/* Decode value. */
@@ -7901,12 +7511,7 @@ double decfp2(int kexp, int kmant)
iexp -= 64;
- if ( iexp < 0 )
- pval = 1./_pow16tab[-iexp];
- else
- pval = _pow16tab[iexp];
-
- pval *= isign * POW_2_M24 * kmant;
+ pval = ldexp(1.0, 4 * iexp) * isign * POW_2_M24 * kmant;
/* ----------------------------------------------------------------- */
/* Section 9. Return to calling routine. */
@@ -8106,7 +7711,7 @@ void gprintf(const char *caller, const char *fmt, ...)
void
gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
+ int kleng, int *kword, const char *hoper, int *kret)
{
int yfunc = *hoper;
@@ -8137,7 +7742,7 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
void
gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
+ int kleng, int *kword, const char *hoper, int *kret)
{
int yfunc = *hoper;
@@ -8164,86 +7769,6 @@ gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
}
}
-
-void
-gribExSP_old(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
- float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
-{
- int inum, j;
- double fsec2dp[1024];
- double fsec3dp[2];
- double *fsec4dp = NULL;
- int yfunc = *hoper;
-
- if ( yfunc == 'C' )
- {
- inum = 10 + isec2[11];
- for ( j = 0; j < inum; j++ ) fsec2dp[j] = fsec2sp[j];
-
- fsec3dp[0] = fsec3sp[0];
- fsec3dp[1] = fsec3sp[1];
-
- inum = isec4[0];
- fsec4dp = (double*) Malloc(inum*sizeof(double));
- if ( fsec4dp == NULL ) SysError("No Memory!");
-
- for ( j = 0; j < inum; j++ ) fsec4dp[j] = fsec4sp[j];
-
- gribExDP(isec0, isec1, isec2, fsec2dp, isec3,
- fsec3dp, isec4, fsec4dp, klenp, kgrib,
- kleng, kword, hoper, kret);
-
- Free(fsec4dp);
- }
- else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
- {
- if ( yfunc == 'D' || yfunc == 'R' )
- {
- fsec4dp = (double*) Malloc(klenp*sizeof(double));
- if ( fsec4dp == NULL ) SysError("No Memory!");
- }
-
- for ( j = 0; j < 10; j++ ) fsec2dp[j] = 0.0;
- for ( j = 0; j < 2; j++ ) fsec3dp[j] = 0.0;
-
- gribExDP(isec0, isec1, isec2, fsec2dp, isec3,
- fsec3dp, isec4, fsec4dp, klenp, kgrib,
- kleng, kword, hoper, kret);
-
- inum = 10 + isec2[11];
- for ( j = 0; j < inum; j++ ) fsec2sp[j] = fsec2dp[j];
-
- fsec3sp[0] = fsec3dp[0];
- fsec3sp[1] = fsec3dp[1];
-
- if ( yfunc == 'D' || yfunc == 'R' )
- {
- inum = isec4[0];
- for ( j = 0; j < inum; j++ )
- {
- if ( fsec4dp[j] > -FLT_MIN && fsec4dp[j] < FLT_MIN )
- fsec4sp[j] = 0;
- else if ( fsec4dp[j] > FLT_MAX )
- fsec4sp[j] = FLT_MAX;
- else if ( fsec4dp[j] < -FLT_MAX )
- fsec4sp[j] = -FLT_MAX;
- else
- fsec4sp[j] = fsec4dp[j];
- }
-
- Free(fsec4dp);
- }
- }
- else if ( yfunc == 'V' )
- fprintf(stderr, " c-gribex: Version is %s\n", cgribexLibraryVersion());
- else
- {
- Error("oper %c unsupported!", yfunc);
- *kret=-9;
- }
-}
-
int CGRIBEX_Fix_ZSE = 0; /* 1: Fix ZeroShiftError of simple packed spherical harmonics */
int CGRIBEX_Const = 0; /* 1: Don't pack constant fields on regular grids */
int CGRIBEX_Debug = 0; /* 1: Debugging */
@@ -9524,7 +9049,7 @@ void gribPrintSec2SP(int *isec0, int *isec2, float *fsec2sp)
inum = 10 + isec2[11];
- fsec2 = (double*) Malloc(inum*sizeof(double));
+ fsec2 = (double*) Malloc((size_t)inum*sizeof(double));
if ( fsec2 == NULL ) SysError("No Memory!");
for ( j = 0; j < inum; j++ )
@@ -9871,29 +9396,30 @@ int gribCheckSeek(int fileID, long *offset, int *version)
int gribFileSeekOld(int fileID, long *offset)
{
/* position file pointer after GRIB */
- int ch;
- int buffersize = 4096;
- unsigned char buffer[4096];
+ enum { buffersize = 4096 };
+ unsigned char buffer[buffersize];
int retry = 4096;
- int i;
*offset = 0;
void *fileptr = filePtr(fileID);
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
+ for ( size_t i = 0; i < 4; ++i)
+ {
+ int ch = filePtrGetc(fileptr);
+ if ( ch == EOF ) return (-1);
+ buffer[i] = (unsigned char)ch;
+ }
/*
fileRead(fileID, buffer, 4);
*/
while ( retry-- )
{
+ size_t i;
for ( i = 0; i < buffersize-4; ++i )
{
- if (buffer[i ] == 'G' &&
+ if (buffer[i ] == 'G' &&
buffer[i+1] == 'R' &&
buffer[i+2] == 'I' &&
buffer[i+3] == 'B')
@@ -9904,7 +9430,7 @@ int gribFileSeekOld(int fileID, long *offset)
}
else
{
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
+ int ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = (unsigned char)ch;
(*offset)++;
}
}
@@ -9958,13 +9484,13 @@ int gribFileSeek(int fileID, long *offset)
int gribFileSeekTest(int fileID, long *offset)
{
/* position file pointer after GRIB */
- const long GRIB = 0x47524942;
+ const long GRIB = 0x47524942L;
long code = 0;
int ch;
int i = 0;
- const int buffersize = 8;
- unsigned char buffer[8];
- int retry = 4096*4096;
+ enum { buffersize = 8 };
+ unsigned char buffer[buffersize];
+ unsigned long retry = 4096L*4096L;
int nread = 0;
*offset = 0;
@@ -9981,7 +9507,7 @@ int gribFileSeekTest(int fileID, long *offset)
}
ch = buffer[i++];
- code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+ code = ( (code << 8) + ch ) & 0xFFFFFFFFL;
if ( code == GRIB )
{
@@ -10002,6 +9528,14 @@ int gribFileSeekTest(int fileID, long *offset)
return 1;
}
+static inline int
+read3ByteMSBFirst(void *fileptr)
+{
+ unsigned b1 = (unsigned)(filePtrGetc(fileptr));
+ unsigned b2 = (unsigned)(filePtrGetc(fileptr));
+ unsigned b3 = (unsigned)(filePtrGetc(fileptr));
+ return (int)((b1 << 16) + (b2 << 8) + b3);
+}
int gribReadSize(int fileID)
{
@@ -10027,7 +9561,7 @@ int gribReadSize(int fileID)
{
int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
int issize = 4, essize = 4;
- int flag;
+ int flag = 0;
pdssize = gribsize;
fileSetPos(fileID, (off_t) 3, SEEK_CUR);
@@ -10039,22 +9573,19 @@ int gribReadSize(int fileID)
if ( flag & 128 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- gdssize = (b1 << 16) + (b2 << 8) + b3;
+ gdssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("gdssize = %d", gdssize);
}
if ( flag & 64 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bmssize = (b1 << 16) + (b2 << 8) + b3;
+ bmssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("bmssize = %d", bmssize);
}
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bdssize = (b1 << 16) + (b2 << 8) + b3;
+ bdssize = read3ByteMSBFirst(fileptr);
if ( CGRIBEX_Debug ) Message("bdssize = %d", bdssize);
gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
@@ -10067,8 +9598,7 @@ int gribReadSize(int fileID)
int issize = 4, essize = 4;
int flag;
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- pdssize = (b1 << 16) + (b2 << 8) + b3;
+ pdssize = read3ByteMSBFirst(fileptr);
if ( CGRIBEX_Debug ) Message("pdssize = %d", pdssize);
for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
@@ -10078,22 +9608,19 @@ int gribReadSize(int fileID)
if ( flag & 128 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- gdssize = (b1 << 16) + (b2 << 8) + b3;
+ gdssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("gdssize = %d", gdssize);
}
if ( flag & 64 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bmssize = (b1 << 16) + (b2 << 8) + b3;
+ bmssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("bmssize = %d", bmssize);
}
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bdssize = (b1 << 16) + (b2 << 8) + b3;
+ bdssize = read3ByteMSBFirst(fileptr);
bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
if ( CGRIBEX_Debug ) Message("bdssize = %d", bdssize);
@@ -10162,7 +9689,7 @@ int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
if ( ierr == -1 ) { *buffersize = 0; return -1; }
else if ( ierr == 1 ) { *buffersize = 0; return -2; }
- size_t recSize = gribReadSize(fileID);
+ size_t recSize = (size_t)gribReadSize(fileID);
size_t readSize = recSize;
if ( readSize > *buffersize )
@@ -10193,7 +9720,7 @@ int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
{
int nwrite = 0;
- if ( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
+ if ( (nwrite = (int)(fileWrite(fileID, buffer, buffersize))) != (int) buffersize )
{
perror(__func__);
nwrite = -1;
@@ -10213,7 +9740,7 @@ int gribrec_len(unsigned b1, unsigned b2, unsigned b3)
*/
int needRescaling = b1 & (1 << 7);
- int gribsize = (((b1&127) << 16)+(b2<<8) + b3);
+ int gribsize = (int)((((b1&127) << 16)+(b2<<8) + b3));
if ( needRescaling ) gribsize *= 120;
@@ -11078,6 +10605,7 @@ void ref2ibm(double *pref, int kbits)
return;
} /* ref2ibm */
+#include <math.h>
#include <string.h>
@@ -11091,7 +10619,7 @@ int correct_bdslen(int bdslen, long recsize, long gribpos)
due to the count being only 24 bits. It is only possible because
the (default) rounding for GRIB products is 120 bytes.
*/
- if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
+ if ( recsize > JP23SET ) bdslen = (int)(recsize - gribpos - bdslen);
return (bdslen);
}
@@ -11455,19 +10983,20 @@ int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
}
- bsf = BDS_BinScale;
- if ( bsf > 32767 ) bsf = 32768-bsf;
- bsf = pow(2.0,(double)bsf);
+ {
+ int bs = BDS_BinScale;
+ if ( bs > 32767 ) bs = 32768-bs;
+ bsf = ldexpf(1.0f, bs);
+ }
bignum[0] = dpos;
- if ( bms ) bignum[1] = bpos;
- else bignum[1] = -999;
+ bignum[1] = bms ? bpos : -999;
intnum[0] = BDS_NumBits;
/* fltnum[0] = 1.0; */
- fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
+ fltnum[0] = powf(10.0f, (float)PDS_DecimalScale);
fltnum[1] = bsf;
- fltnum[2] = BDS_RefValue;
+ fltnum[2] = (float)BDS_RefValue;
/*
printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
@@ -11608,7 +11137,7 @@ void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned cha
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
@@ -11700,7 +11229,7 @@ void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
@@ -11761,7 +11290,7 @@ void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
@@ -11826,7 +11355,7 @@ void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
@@ -11916,7 +11445,7 @@ void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
@@ -11979,7 +11508,6 @@ void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
static
void repair1(unsigned char *gbuf, long gbufsize)
{
- long i;
int nerr;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
/* int recLen; */
@@ -12035,15 +11563,13 @@ void repair1(unsigned char *gbuf, long gbufsize)
source = bds + datstart;
- sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+ sourceLen = (size_t)(((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8);
if ( bds_nbits == 24 )
{
- long nelem;
- unsigned char *pbuf;
- nelem = sourceLen/3;
- pbuf = (unsigned char*) Malloc(sourceLen);
- for ( i = 0; i < nelem; i++ )
+ unsigned char *pbuf = (unsigned char*) Malloc(sourceLen);;
+ size_t nelem = sourceLen/3;
+ for ( size_t i = 0; i < nelem; i++ )
{
pbuf[3*i ] = source[ i];
pbuf[3*i+1] = source[ nelem+i];
@@ -12150,9 +11676,8 @@ int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
int bds_flag, lcompress;
long gribsize = 0;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
- int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ int gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 2 ) return (compress);
@@ -12507,22 +12032,20 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
static int libszwarn = 1;
#endif
- int nerr;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
- int bdsLen, recLen, gribLen = 0;
+ size_t gribLen = 0;
unsigned char *dest, *source;
size_t destLen, sourceLen;
int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
- int bds_head = 11;
+ enum { bds_head = 11 };
int bds_ext = 0;
int bds_zoffset, bds_zstart;
- int datstart = 0;
int llarge = FALSE;
UNUSED(dbufsize);
long gribrecsize;
- nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+ int nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
if ( nerr < 0 )
{
fprintf(stdout, "GRIB message error\n");
@@ -12537,7 +12060,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
bds_zstart = 14;
- recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
+ int recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
if ( recLen > JP23SET ) llarge = TRUE;
bds_zoffset = 12;
@@ -12565,7 +12088,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
}
- datstart = bds_head + bds_ext;
+ size_t datstart = bds_head + (size_t)bds_ext;
source = bds + datstart + bds_zoffset;
if ( llarge )
@@ -12587,14 +12110,14 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
dest = bds + datstart;
- if ( llarge )
+ if ( llarge )
destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
else
destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- BDS_Flag -= 16;
+ BDS_Flag = (unsigned char)(BDS_Flag - 16);
- bdsLen = datstart + destLen;
+ size_t bdsLen = datstart + destLen;
#if defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
{
@@ -12689,7 +12212,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
pbuf[3*i+2] = dest[2*nelem+i];
}
memcpy(dest, pbuf, tmpLen);
- Free(pbuf);
+ Free(pbuf);
}
#endif
@@ -12725,7 +12248,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
*/
while ( gribLen%120 ) dbuf[gribLen++] = 0;
- if ( gribLen != recLen )
+ if ( gribLen != (size_t)recLen )
fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
itemp = gribLen / (-120);
@@ -12766,119 +12289,12 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
#endif
- return (gribLen);
+ return (int)gribLen;
}
#include <stdio.h>
#include <math.h>
-/* calculate_pfactor: source code from grib_api-1.8.0 */
-double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation)
-{
- /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
- long loop, index, m, n = 0;
- double pFactor, zeps = 1.0e-15;
- long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
- double* weights, range, * norms;
- double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
- double numerator = 0.0, denominator = 0.0, slope;
-
- /*
- // Setup the weights
- */
-
- range = (double) (ismax - ismin +1);
-
- weights = (double*) Malloc((ismax+1)*sizeof(double));
- for( loop = ismin; loop <= ismax; loop++ )
- weights[loop] = range / (double) (loop-ismin+1);
- /*
- // Compute norms
- // Handle values 2 at a time (real and imaginary parts).
- */
- norms = (double*) Malloc((ismax+1)*sizeof(double));
-
- for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
- /*
- // Form norms for the rows which contain part of the unscaled subset.
- */
-
- index = -2;
- for( m = 0; m < subsetTruncation; m++ )
- for( n = m; n <= fieldTruncation; n++ ) {
- index += 2;
- if( n >= subsetTruncation ) {
- double tval = spectralField[index];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- tval = spectralField[index+1];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- }
- }
- /*
- // Form norms for the rows which do not contain part of the unscaled subset.
- */
-
- for( m = subsetTruncation; m <= fieldTruncation; m++ )
- for( n = m; n <= fieldTruncation; n++ ) {
- double tval = spectralField[index];
- index += 2;
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- tval = spectralField[index+1];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- }
-
- /*
- // Ensure the norms have a value which is not too small in case of
- // problems with math functions (e.g. LOG).
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
- norms[n] = norms[n] > zeps ? norms[n] : zeps;
- if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
- }
-
- /*
- // Do linear fit to find the slope
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
- x = log( (double) (loop*(loop+1)) );
- y = log( norms[loop] );
- weightedSumOverX = weightedSumOverX + x * weights[loop];
- weightedSumOverY = weightedSumOverY + y * weights[loop];
- sumOfWeights = sumOfWeights + weights[loop];
- }
- weightedSumOverX = weightedSumOverX / sumOfWeights;
- weightedSumOverY = weightedSumOverY / sumOfWeights;
-
- /*
- // Perform a least square fit for the equation
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
-
- x = log( (double)(loop*(loop+1)) );
- y = log( norms[loop] );
- numerator =
- numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
- denominator =
- denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
- }
- slope = numerator / denominator;
-
- Free(weights);
- Free(norms);
-
- pFactor = -slope;
- if( pFactor < -9999.9 ) pFactor = -9999.9;
- if( pFactor > 9999.9 ) pFactor = 9999.9;
-
- return pFactor;
-}
static
int rowina2(double *p, int ko, int ki, double *pw,
@@ -13065,10 +12481,10 @@ int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
int iregno, iquano, j210, j220, j230, j240, j225;
- zline = (double*) Malloc(2*klon*sizeof(double));
+ zline = (double*) Malloc(2*(size_t)klon*sizeof(double));
if ( zline == NULL ) SysError("No Memory!");
- zwork = (double*) Malloc(3*(2*klon+3)*sizeof(double));
+ zwork = (double*) Malloc(3*(2*(size_t)klon+3)*sizeof(double));
if ( zwork == NULL ) SysError("No Memory!");
/* Parameter adjustments */
@@ -13219,12 +12635,118 @@ L900:
#define T double
#ifdef T
+/* calculate_pfactor: source code from grib_api-1.8.0 */
+double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
+{
+ /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
+ long loop, index, m, n = 0;
+ double pFactor, zeps = 1.0e-15;
+ long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
+ double* weights, range, * norms;
+ double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
+ double numerator = 0.0, denominator = 0.0, slope;
+
+ /*
+ // Setup the weights
+ */
+
+ range = (double) (ismax - ismin +1);
+
+ weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+ for( loop = ismin; loop <= ismax; loop++ )
+ weights[loop] = range / (double) (loop-ismin+1);
+ /*
+ // Compute norms
+ // Handle values 2 at a time (real and imaginary parts).
+ */
+ norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+
+ for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
+ /*
+ // Form norms for the rows which contain part of the unscaled subset.
+ */
+
+ index = -2;
+ for( m = 0; m < subsetTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ index += 2;
+ if( n >= subsetTruncation ) {
+ double tval = spectralField[index];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+ }
+ /*
+ // Form norms for the rows which do not contain part of the unscaled subset.
+ */
+
+ for( m = subsetTruncation; m <= fieldTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ double tval = spectralField[index];
+ index += 2;
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+
+ /*
+ // Ensure the norms have a value which is not too small in case of
+ // problems with math functions (e.g. LOG).
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ norms[n] = norms[n] > zeps ? norms[n] : zeps;
+ if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
+ }
+
+ /*
+ // Do linear fit to find the slope
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ x = log( (double) (loop*(loop+1)) );
+ y = log( norms[loop] );
+ weightedSumOverX = weightedSumOverX + x * weights[loop];
+ weightedSumOverY = weightedSumOverY + y * weights[loop];
+ sumOfWeights = sumOfWeights + weights[loop];
+ }
+ weightedSumOverX = weightedSumOverX / sumOfWeights;
+ weightedSumOverY = weightedSumOverY / sumOfWeights;
+
+ /*
+ // Perform a least square fit for the equation
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+
+ x = log( (double)(loop*(loop+1)) );
+ y = log( norms[loop] );
+ numerator =
+ numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
+ denominator =
+ denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
+ }
+ slope = numerator / denominator;
+
+ Free(weights);
+ Free(norms);
+
+ pFactor = -slope;
+ if( pFactor < -9999.9 ) pFactor = -9999.9;
+ if( pFactor > 9999.9 ) pFactor = 9999.9;
+
+ return pFactor;
+}
+
void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
{
double power;
- double *scale = (double*) Malloc((trunc+1)*sizeof(double));
- int n, m;
- int index;
+ double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
if ( scale == NULL ) SysError("No Memory!");
@@ -13241,38 +12763,33 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
power = (double) pcScale / 1000.;
scale[0] = 1.0;
- for ( n = 1; n <= trunc; n++ )
- {
- if (pcScale != 1000)
- scale[n] = pow((double) (n*(n+1)), power);
- else
- scale[n] = (double) (n*(n+1));
- }
+ if (pcScale != 1000)
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = pow((double) (n*(n+1)), power);
+ else
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = (double) (n*(n+1));
if ( inv )
- for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+ for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
/* Scale the values */
- index = 0;
+ size_t index = 0;
- for ( m = 0; m < pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
- {
- if ( n >= pcStart )
- {
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- }
- index += 2;
- }
+ for ( int m = 0; m < pcStart; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
+ if ( n >= pcStart )
+ {
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
+ }
- for ( m = pcStart; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( int m = pcStart; m <= trunc; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
{
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- index += 2;
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
}
Free(scale);
@@ -13281,7 +12798,7 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
+ T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
int m, n;
int index, inext;
@@ -13318,18 +12835,13 @@ void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
}
-void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
- int m, n;
- int index, inext;
+ T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
+ size_t inext = 0;
- if ( fphelp == NULL ) SysError("No Memory!");
-
- index = inext = 0;
-
- for ( m = 0; m <= pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= pcStart; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( pcStart >= n )
{
@@ -13339,9 +12851,8 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- index = 0;
- for ( m = 0; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= trunc; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( n > pcStart )
{
@@ -13351,7 +12862,7 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+ for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
Free(fphelp);
}
@@ -13572,8 +13083,8 @@ C -----------------------------------------------------------------
{
/* Interpolate using the weighted values on either side */
/* of the output point position */
- p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
- zwt * pw[ip+2 + pw_dim1];
+ p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
+ + zwt * pw[ip+2 + pw_dim1]);
}
}
}
@@ -13603,14 +13114,14 @@ C -----------------------------------------------------------------
for ( jl = 1; jl <= i_1; ++jl )
{
pw[jl + (pw_dim1 << 1)] =
- - pw[jl - 1 + pw_dim1] / 3.0 -
- pw[jl + pw_dim1] * 0.5 +
- pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+ (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
+ pw[jl + pw_dim1] * 0.5 +
+ pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
pw[jl + 1 + pw_dim1 * 3] =
- pw[jl - 1 + pw_dim1] / 6.0 -
- pw[jl + pw_dim1] +
- pw[jl + 1 + pw_dim1] * 0.5 +
- pw[jl + 2 + pw_dim1] / 3.0;
+ (T)(pw[jl - 1 + pw_dim1] / 6.0 -
+ pw[jl + pw_dim1] +
+ pw[jl + 1 + pw_dim1] * 0.5 +
+ pw[jl + 2 + pw_dim1] / 3.0);
}
TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
@@ -13625,10 +13136,10 @@ C -----------------------------------------------------------------
ip = (int) zwt + 1;
zwt = zwt + 1.0 - ip;
zwt1 = 1.0 - zwt;
- p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
- zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
- ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
- zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+ p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+ zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+ ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+ zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
}
}
@@ -13757,14 +13268,11 @@ C
T *zline = NULL;
T *zwork = NULL;
- ztemp = (T*) Malloc(klon*klat*sizeof(T));
- if ( ztemp == NULL ) SysError("No Memory!");
+ ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
- zline = (T*) Malloc(2*klon*sizeof(T));
- if ( zline == NULL ) SysError("No Memory!");
+ zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
- zwork = (T*) Malloc(3*(2*klon+3)*sizeof(T));
- if ( zwork == NULL ) SysError("No Memory!");
+ zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
/* Parameter adjustments */
--pfield;
@@ -13876,18 +13384,130 @@ L900:
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
#define T float
#ifdef T
+/* calculate_pfactor: source code from grib_api-1.8.0 */
+double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
+{
+ /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
+ long loop, index, m, n = 0;
+ double pFactor, zeps = 1.0e-15;
+ long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
+ double* weights, range, * norms;
+ double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
+ double numerator = 0.0, denominator = 0.0, slope;
+
+ /*
+ // Setup the weights
+ */
+
+ range = (double) (ismax - ismin +1);
+
+ weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+ for( loop = ismin; loop <= ismax; loop++ )
+ weights[loop] = range / (double) (loop-ismin+1);
+ /*
+ // Compute norms
+ // Handle values 2 at a time (real and imaginary parts).
+ */
+ norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+
+ for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
+ /*
+ // Form norms for the rows which contain part of the unscaled subset.
+ */
+
+ index = -2;
+ for( m = 0; m < subsetTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ index += 2;
+ if( n >= subsetTruncation ) {
+ double tval = spectralField[index];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+ }
+ /*
+ // Form norms for the rows which do not contain part of the unscaled subset.
+ */
+
+ for( m = subsetTruncation; m <= fieldTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ double tval = spectralField[index];
+ index += 2;
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+
+ /*
+ // Ensure the norms have a value which is not too small in case of
+ // problems with math functions (e.g. LOG).
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ norms[n] = norms[n] > zeps ? norms[n] : zeps;
+ if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
+ }
+
+ /*
+ // Do linear fit to find the slope
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ x = log( (double) (loop*(loop+1)) );
+ y = log( norms[loop] );
+ weightedSumOverX = weightedSumOverX + x * weights[loop];
+ weightedSumOverY = weightedSumOverY + y * weights[loop];
+ sumOfWeights = sumOfWeights + weights[loop];
+ }
+ weightedSumOverX = weightedSumOverX / sumOfWeights;
+ weightedSumOverY = weightedSumOverY / sumOfWeights;
+
+ /*
+ // Perform a least square fit for the equation
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+
+ x = log( (double)(loop*(loop+1)) );
+ y = log( norms[loop] );
+ numerator =
+ numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
+ denominator =
+ denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
+ }
+ slope = numerator / denominator;
+
+ Free(weights);
+ Free(norms);
+
+ pFactor = -slope;
+ if( pFactor < -9999.9 ) pFactor = -9999.9;
+ if( pFactor > 9999.9 ) pFactor = 9999.9;
+
+ return pFactor;
+}
+
void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
{
double power;
- double *scale = (double*) Malloc((trunc+1)*sizeof(double));
- int n, m;
- int index;
+ double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
if ( scale == NULL ) SysError("No Memory!");
@@ -13904,38 +13524,33 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
power = (double) pcScale / 1000.;
scale[0] = 1.0;
- for ( n = 1; n <= trunc; n++ )
- {
- if (pcScale != 1000)
- scale[n] = pow((double) (n*(n+1)), power);
- else
- scale[n] = (double) (n*(n+1));
- }
+ if (pcScale != 1000)
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = pow((double) (n*(n+1)), power);
+ else
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = (double) (n*(n+1));
if ( inv )
- for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+ for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
/* Scale the values */
- index = 0;
+ size_t index = 0;
- for ( m = 0; m < pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
- {
- if ( n >= pcStart )
- {
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- }
- index += 2;
- }
+ for ( int m = 0; m < pcStart; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
+ if ( n >= pcStart )
+ {
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
+ }
- for ( m = pcStart; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( int m = pcStart; m <= trunc; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
{
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- index += 2;
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
}
Free(scale);
@@ -13944,7 +13559,7 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
+ T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
int m, n;
int index, inext;
@@ -13981,18 +13596,13 @@ void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
}
-void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
- int m, n;
- int index, inext;
-
- if ( fphelp == NULL ) SysError("No Memory!");
+ T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
+ size_t inext = 0;
- index = inext = 0;
-
- for ( m = 0; m <= pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= pcStart; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( pcStart >= n )
{
@@ -14002,9 +13612,8 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- index = 0;
- for ( m = 0; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= trunc; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( n > pcStart )
{
@@ -14014,7 +13623,7 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+ for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
Free(fphelp);
}
@@ -14235,8 +13844,8 @@ C -----------------------------------------------------------------
{
/* Interpolate using the weighted values on either side */
/* of the output point position */
- p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
- zwt * pw[ip+2 + pw_dim1];
+ p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
+ + zwt * pw[ip+2 + pw_dim1]);
}
}
}
@@ -14266,14 +13875,14 @@ C -----------------------------------------------------------------
for ( jl = 1; jl <= i_1; ++jl )
{
pw[jl + (pw_dim1 << 1)] =
- - pw[jl - 1 + pw_dim1] / 3.0 -
- pw[jl + pw_dim1] * 0.5 +
- pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+ (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
+ pw[jl + pw_dim1] * 0.5 +
+ pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
pw[jl + 1 + pw_dim1 * 3] =
- pw[jl - 1 + pw_dim1] / 6.0 -
- pw[jl + pw_dim1] +
- pw[jl + 1 + pw_dim1] * 0.5 +
- pw[jl + 2 + pw_dim1] / 3.0;
+ (T)(pw[jl - 1 + pw_dim1] / 6.0 -
+ pw[jl + pw_dim1] +
+ pw[jl + 1 + pw_dim1] * 0.5 +
+ pw[jl + 2 + pw_dim1] / 3.0);
}
TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
@@ -14288,10 +13897,10 @@ C -----------------------------------------------------------------
ip = (int) zwt + 1;
zwt = zwt + 1.0 - ip;
zwt1 = 1.0 - zwt;
- p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
- zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
- ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
- zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+ p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+ zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+ ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+ zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
}
}
@@ -14420,14 +14029,11 @@ C
T *zline = NULL;
T *zwork = NULL;
- ztemp = (T*) Malloc(klon*klat*sizeof(T));
- if ( ztemp == NULL ) SysError("No Memory!");
+ ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
- zline = (T*) Malloc(2*klon*sizeof(T));
- if ( zline == NULL ) SysError("No Memory!");
+ zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
- zwork = (T*) Malloc(3*(2*klon+3)*sizeof(T));
- if ( zwork == NULL ) SysError("No Memory!");
+ zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
/* Parameter adjustments */
--pfield;
@@ -14538,6 +14144,12 @@ L900:
} /* qu2reg3 */
#endif /* T */
+
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
#include <string.h>
@@ -14831,31 +14443,31 @@ void gribPrintSec3_float(int *isec0, int *isec3, float *fsec3) {gribPrintSec3SP(
void gribPrintSec4_float(int *isec0, int *isec4, float *fsec4) {gribPrintSec4SP(isec0, isec4, fsec4);}
-
#ifdef T
#undef T
#endif
#define T double
#ifdef T
+#include <inttypes.h>
+
static
-void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
- unsigned int jmask;
long i;
unsigned int tbits = 0;
int n_bits = NumBits;
int t_bits = 0;
-
- jmask = (1 << n_bits) - 1;
+
+ unsigned jmask = (1U << n_bits) - 1U;
for ( i = 0; i < jlend; i++ )
{
if (n_bits - t_bits > 8)
{
- tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+ tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
bits += 2;
t_bits += 16;
}
@@ -14866,35 +14478,32 @@ void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long
t_bits += 8;
}
t_bits -= n_bits;
- fpdata[i] = (tbits >> t_bits) & jmask;
+ fpdata[i] = (float)((tbits >> t_bits) & jmask);
}
/* at least this vectorizes :) */
for ( i = 0; i < jlend; i++ )
fpdata[i] = fmin + zscale*fpdata[i];
}
-#if !defined(_MASK_AND_SHIFT_)
-#define _MASK_AND_SHIFT_
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
-#endif
-
-static
-void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+static
+void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
+ static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
+ static const double shift[9]
+ = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
long i;
int n_bits = NumBits;
int c_bits, j_bits;
- double jj;
/* older unoptimized code, not often used */
c_bits = 8;
for ( i = 0; i < jlend; i++ )
{
- jj = 0.0;
+ double jj = 0.0;
j_bits = n_bits;
while (c_bits <= j_bits)
{
@@ -14915,12 +14524,36 @@ void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long
if (j_bits)
{
c_bits -= j_bits;
- jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+ jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
}
-
- fpdata[i] = fmin + zscale*jj;
+ fpdata[i] = (T)(fmin + zscale*jj);
+ }
+}
+
+static
+void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
+ T *fpdata, T fmin, T zscale)
+{
+ U_BYTEORDER;
+ const uint16_t *restrict sgrib = (uint16_t *) (igrib);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ fpdata[i] = fmin + zscale * sgrib[i];
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ ui16 = gribSwapByteOrder_uint16(sgrib[i]);
+ fpdata[i] = fmin + zscale * ui16;
+ }
}
-}
+}
static
void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
@@ -14931,7 +14564,6 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif
long i;
- T dval;
#if defined (VECTORCODE)
GRIBPACK *lgrib = NULL;
@@ -14955,26 +14587,26 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)lgrib[i];
+ T dval = (int)lgrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
+ T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
+ T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
(int)lgrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+ T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
@@ -15002,75 +14634,25 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)igrib[i];
+ T dval = (int)igrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
{
-#ifdef _GET_IBM_COUNTER
- hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER
- start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- start_decode = mach_absolute_time();
-#endif
-
- if ( sizeof(T) == sizeof(double) )
- {
-#if defined _ENABLE_AVX
- printf("AVX selected ...\n");
- avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
- printf("SSE4 selected ...\n");
- sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
-#endif
- }
- else
- {
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
- }
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER
- end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
- printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
- printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
- printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif
-#endif
-
-#ifdef _GET_IBM_COUNTER
- hpmStop(6);
-#endif
+ TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
- (int)igrib[3*i+2]);
+ T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
+ (int)igrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
- ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
+ T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+ ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits <= 25 )
@@ -15090,30 +14672,37 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
#define T float
#ifdef T
+#include <inttypes.h>
+
static
-void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
- unsigned int jmask;
long i;
unsigned int tbits = 0;
int n_bits = NumBits;
int t_bits = 0;
-
- jmask = (1 << n_bits) - 1;
+
+ unsigned jmask = (1U << n_bits) - 1U;
for ( i = 0; i < jlend; i++ )
{
if (n_bits - t_bits > 8)
{
- tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+ tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
bits += 2;
t_bits += 16;
}
@@ -15124,35 +14713,32 @@ void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long
t_bits += 8;
}
t_bits -= n_bits;
- fpdata[i] = (tbits >> t_bits) & jmask;
+ fpdata[i] = (float)((tbits >> t_bits) & jmask);
}
/* at least this vectorizes :) */
for ( i = 0; i < jlend; i++ )
fpdata[i] = fmin + zscale*fpdata[i];
}
-#if !defined(_MASK_AND_SHIFT_)
-#define _MASK_AND_SHIFT_
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
-#endif
-
-static
-void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+static
+void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
+ static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
+ static const double shift[9]
+ = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
long i;
int n_bits = NumBits;
int c_bits, j_bits;
- double jj;
/* older unoptimized code, not often used */
c_bits = 8;
for ( i = 0; i < jlend; i++ )
{
- jj = 0.0;
+ double jj = 0.0;
j_bits = n_bits;
while (c_bits <= j_bits)
{
@@ -15173,12 +14759,36 @@ void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long
if (j_bits)
{
c_bits -= j_bits;
- jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+ jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
}
-
- fpdata[i] = fmin + zscale*jj;
+ fpdata[i] = (T)(fmin + zscale*jj);
+ }
+}
+
+static
+void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
+ T *fpdata, T fmin, T zscale)
+{
+ U_BYTEORDER;
+ const uint16_t *restrict sgrib = (uint16_t *) (igrib);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ fpdata[i] = fmin + zscale * sgrib[i];
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ ui16 = gribSwapByteOrder_uint16(sgrib[i]);
+ fpdata[i] = fmin + zscale * ui16;
+ }
}
-}
+}
static
void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
@@ -15189,7 +14799,6 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif
long i;
- T dval;
#if defined (VECTORCODE)
GRIBPACK *lgrib = NULL;
@@ -15213,26 +14822,26 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)lgrib[i];
+ T dval = (int)lgrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
+ T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
+ T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
(int)lgrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+ T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
@@ -15260,75 +14869,25 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)igrib[i];
+ T dval = (int)igrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
{
-#ifdef _GET_IBM_COUNTER
- hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER
- start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- start_decode = mach_absolute_time();
-#endif
-
- if ( sizeof(T) == sizeof(double) )
- {
-#if defined _ENABLE_AVX
- printf("AVX selected ...\n");
- avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
- printf("SSE4 selected ...\n");
- sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
-#endif
- }
- else
- {
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
- }
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER
- end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
- printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
- printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
- printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif
-#endif
-
-#ifdef _GET_IBM_COUNTER
- hpmStop(6);
-#endif
+ TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
- (int)igrib[3*i+2]);
+ T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
+ (int)igrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
- ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
+ T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+ ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits <= 25 )
@@ -15348,6 +14907,12 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
@@ -15362,7 +14927,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
int ReducedGrid = FALSE, VertCoorTab = FALSE;
int locnv = 0, locnl;
int jlenl;
- long i;
int iexp, imant;
int ipvpl, ipl;
int gdsLen = 0;
@@ -15414,7 +14978,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
*numGridVals = 0;
ISEC2_Reduced = TRUE;
- for ( i = 0; i < jlenl; i++ )
+ for ( int i = 0; i < jlenl; i++ )
{
ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
*numGridVals += ISEC2_RowLon(i);
@@ -15454,7 +15018,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
ISEC2_LatSP = GDS_LatSP;
ISEC2_LonSP = GDS_LonSP;
- FSEC2_RotAngle = GDS_RotAngle;
+ FSEC2_RotAngle = (T)GDS_RotAngle;
}
/*
if ( Lons != Longitudes || Lats != Latitudes )
@@ -15564,31 +15128,34 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
igrib = &gds[locnv];
if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (lgrib[4*i ]);
imant =((lgrib[4*i+1]) << 16) +
((lgrib[4*i+2]) << 8) +
(lgrib[4*i+3]);
- fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+ fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
}
Free(lgrib);
#else
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (gds[locnv+4*i ]);
imant =((gds[locnv+4*i+1]) << 16) +
((gds[locnv+4*i+2]) << 8) +
(gds[locnv+4*i+3]);
- fsec2[10+i] = decfp2(iexp,imant);
+ fsec2[10+i] = (T)decfp2(iexp,imant);
}
#endif
}
- return (gdsLen);
+ return gdsLen;
}
+#define ldexp_double ldexp
+#define ldexp_float ldexpf
+
static
int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
@@ -15598,15 +15165,13 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
int lcompress;
int jup, kup, mup;
int locnd;
- long jlend;
- long i;
int bds_flag, jscale, imiss;
int bds_ubits;
int ioff = 0;
int iexp, imant;
int zoff;
int bds_head = 11;
- double zscale = 0.;
+ T zscale = 0.;
T fmin = 0.;
T *fpdata = fsec4;
int bdsLen;
@@ -15677,16 +15242,11 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* convert reference value and scale factor. */
- if ( ! (dfunc == 'J') )
- if ( imiss == 0 )
- {
- fmin = BDS_RefValue;
-
- if ( jscale < 0 )
- zscale = 1.0/intpow2(-jscale);
- else
- zscale = intpow2(jscale);
- }
+ if ( ! (dfunc == 'J') && imiss == 0 )
+ {
+ fmin = BDS_RefValue;
+ zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
+ }
/* get number of bits in each data value. */
@@ -15720,7 +15280,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( dfunc != 'J' )
{
if ( imiss ) *fpdata++ = 0.0;
- else *fpdata++ = BDS_RealCoef;
+ else *fpdata++ = (T)BDS_RealCoef;
}
}
else /* complex packed spherical harmonics */
@@ -15747,7 +15307,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
ioff = (jup+1)*(jup+2);
if ( dfunc != 'J' )
- for ( i = 0; i < ioff; i++ )
+ for ( int i = 0; i < ioff; i++ )
{
if ( imiss )
*fpdata++ = 0.0;
@@ -15758,7 +15318,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
((bds[locnd+4*i+2]) << 8) +
(bds[locnd+4*i+3]);
- *fpdata++ = decfp2(iexp,imant);
+ *fpdata++ = (T)decfp2(iexp,imant);
}
}
@@ -15772,7 +15332,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 1999;
gprintf(__func__, " Second order packed grids unsupported!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
}
@@ -15781,7 +15341,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* Take into account that spherical harmonics can be packed */
/* simple (lcomplex = 0) or complex (lcomplex = 1) */
- jlend = bdsLen - locnd;
+ int jlend = bdsLen - locnd;
if ( ISEC4_NumBits == 0 )
{
@@ -15790,7 +15350,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2001;
gprintf(__func__, " Number of bits per data value = 0!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
if ( numGridVals == 0 )
@@ -15798,7 +15358,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2002;
gprintf(__func__, " Constant field unsupported for this grid type!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
jlend = numGridVals;
@@ -15821,7 +15381,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
else
len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- ISEC4_NumValues = len*8/ISEC4_NumBits;
+ ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
if ( lspherc )
{
@@ -15832,7 +15392,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
}
}
- if ( dfunc == 'J' ) return (bdsLen);
+ if ( dfunc == 'J' ) return bdsLen;
/* check length of output array. */
@@ -15842,10 +15402,10 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
gprintf(__func__, " Output array too small. Length = %d", fsec4len);
gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
- if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+ if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
else
{
igrib += locnd;
@@ -15855,9 +15415,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( lspherc && lcomplex )
{
- int pcStart, pcScale;
- pcStart = isec4[19];
- pcScale = isec4[16];
+ int pcStart = isec4[19], pcScale = isec4[16];
TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
}
@@ -15869,17 +15427,17 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
{
T zserr = fsec4[1];
- for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+ for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
}
}
if ( decscale )
{
T scale = (T) pow(10.0, (double)-decscale);
- for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+ for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
}
- return (bdsLen);
+ return bdsLen;
}
@@ -15889,7 +15447,6 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
{
UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
- int gribLen = 0;
int gdsIncluded = FALSE;
int bmsIncluded = FALSE;
int bitmapSize = 0;
@@ -16080,7 +15637,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
{
lmissvalinfo = 0;
- FSEC3_MissVal = GRIB_MISSVAL;
+ FSEC3_MissVal = (T)GRIB_MISSVAL;
Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
}
@@ -16089,16 +15646,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
{
- long i, j;
- GRIBPACK *pbitmap;
GRIBPACK bitmap;
- GRIBPACK *imask;
-
/*
unsigned char *bitmap;
bitmap = BMS_Bitmap;
- j = ISEC4_NumNonMissValues;
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ int j = ISEC4_NumNonMissValues;
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
{
if ( (bitmap[i/8]>>(7-(i&7)))&1 )
fsec4[i] = fsec4[--j];
@@ -16107,13 +15660,13 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
}
*/
- imask = (GRIBPACK*) Malloc(imaskSize*sizeof(GRIBPACK));
+ GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
#if defined (VECTORCODE)
(void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
- pbitmap = imask;
+ GRIBPACK *pbitmap = imask;
#else
- pbitmap = BMS_Bitmap;
+ GRIBPACK *pbitmap = BMS_Bitmap;
#endif
#if defined (CRAY)
@@ -16125,7 +15678,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = imaskSize/8-1; i >= 0; i-- )
+ for ( int i = imaskSize/8-1; i >= 0; i-- )
{
bitmap = pbitmap[i];
imask[i*8+0] = 1 & (bitmap >> 7);
@@ -16138,8 +15691,8 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
imask[i*8+7] = 1 & (bitmap);
}
- j = 0;
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( imask[i] ) j++;
if ( ISEC4_NumNonMissValues != j )
@@ -16162,7 +15715,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
}
@@ -16172,24 +15725,18 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC2_Reduced )
{
- int nlon, nlat;
- int lperio = 1, lveggy;
- int ilat;
int nvalues = 0;
-
- nlat = ISEC2_NumLat;
- nlon = ISEC2_RowLonPtr[0];
- for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
- for ( ilat = 1; ilat < nlat; ++ilat )
+ int nlat = ISEC2_NumLat;
+ int nlon = ISEC2_RowLonPtr[0];
+ for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+ for ( int ilat = 1; ilat < nlat; ++ilat )
if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
// int dlon = ISEC2_LastLon-ISEC2_FirstLon;
// if ( dlon < 0 ) dlon += 360000;
- if ( nvalues != ISEC4_NumValues )
- {
- *iret = -801;
- }
+ if ( nvalues != ISEC4_NumValues ) *iret = -801;
+
//printf("nlat %d nlon %d \n", nlat, nlon);
//printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
@@ -16204,18 +15751,20 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC4_NumValues = nlon*nlat;
lsect3 = bitmapSize > 0;
- lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
- ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
- (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+ int lperio = 1;
+ int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
+ ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
+ (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
+ (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
+ (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
+ (ISEC1_Parameter == 43));
(void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
if ( bitmapSize > 0 )
{
- long i;
- int j = 0;
-
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
ISEC4_NumNonMissValues = j;
@@ -16227,7 +15776,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
esLen = 4;
- gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+ int gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
if ( ISEC0_GRIB_Len )
if ( ISEC0_GRIB_Len < gribLen )
@@ -16235,8 +15784,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC0_GRIB_Len = gribLen;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
/*
----------------------------------------------------------------
@@ -16281,6 +15829,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
@@ -16294,7 +15848,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
int ReducedGrid = FALSE, VertCoorTab = FALSE;
int locnv = 0, locnl;
int jlenl;
- long i;
int iexp, imant;
int ipvpl, ipl;
int gdsLen = 0;
@@ -16346,7 +15899,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
*numGridVals = 0;
ISEC2_Reduced = TRUE;
- for ( i = 0; i < jlenl; i++ )
+ for ( int i = 0; i < jlenl; i++ )
{
ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
*numGridVals += ISEC2_RowLon(i);
@@ -16386,7 +15939,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
ISEC2_LatSP = GDS_LatSP;
ISEC2_LonSP = GDS_LonSP;
- FSEC2_RotAngle = GDS_RotAngle;
+ FSEC2_RotAngle = (T)GDS_RotAngle;
}
/*
if ( Lons != Longitudes || Lats != Latitudes )
@@ -16496,31 +16049,34 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
igrib = &gds[locnv];
if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (lgrib[4*i ]);
imant =((lgrib[4*i+1]) << 16) +
((lgrib[4*i+2]) << 8) +
(lgrib[4*i+3]);
- fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+ fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
}
Free(lgrib);
#else
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (gds[locnv+4*i ]);
imant =((gds[locnv+4*i+1]) << 16) +
((gds[locnv+4*i+2]) << 8) +
(gds[locnv+4*i+3]);
- fsec2[10+i] = decfp2(iexp,imant);
+ fsec2[10+i] = (T)decfp2(iexp,imant);
}
#endif
}
- return (gdsLen);
+ return gdsLen;
}
+#define ldexp_double ldexp
+#define ldexp_float ldexpf
+
static
int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
@@ -16530,15 +16086,13 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
int lcompress;
int jup, kup, mup;
int locnd;
- long jlend;
- long i;
int bds_flag, jscale, imiss;
int bds_ubits;
int ioff = 0;
int iexp, imant;
int zoff;
int bds_head = 11;
- double zscale = 0.;
+ T zscale = 0.;
T fmin = 0.;
T *fpdata = fsec4;
int bdsLen;
@@ -16609,16 +16163,11 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* convert reference value and scale factor. */
- if ( ! (dfunc == 'J') )
- if ( imiss == 0 )
- {
- fmin = BDS_RefValue;
-
- if ( jscale < 0 )
- zscale = 1.0/intpow2(-jscale);
- else
- zscale = intpow2(jscale);
- }
+ if ( ! (dfunc == 'J') && imiss == 0 )
+ {
+ fmin = BDS_RefValue;
+ zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
+ }
/* get number of bits in each data value. */
@@ -16652,7 +16201,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( dfunc != 'J' )
{
if ( imiss ) *fpdata++ = 0.0;
- else *fpdata++ = BDS_RealCoef;
+ else *fpdata++ = (T)BDS_RealCoef;
}
}
else /* complex packed spherical harmonics */
@@ -16679,7 +16228,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
ioff = (jup+1)*(jup+2);
if ( dfunc != 'J' )
- for ( i = 0; i < ioff; i++ )
+ for ( int i = 0; i < ioff; i++ )
{
if ( imiss )
*fpdata++ = 0.0;
@@ -16690,7 +16239,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
((bds[locnd+4*i+2]) << 8) +
(bds[locnd+4*i+3]);
- *fpdata++ = decfp2(iexp,imant);
+ *fpdata++ = (T)decfp2(iexp,imant);
}
}
@@ -16704,7 +16253,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 1999;
gprintf(__func__, " Second order packed grids unsupported!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
}
@@ -16713,7 +16262,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* Take into account that spherical harmonics can be packed */
/* simple (lcomplex = 0) or complex (lcomplex = 1) */
- jlend = bdsLen - locnd;
+ int jlend = bdsLen - locnd;
if ( ISEC4_NumBits == 0 )
{
@@ -16722,7 +16271,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2001;
gprintf(__func__, " Number of bits per data value = 0!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
if ( numGridVals == 0 )
@@ -16730,7 +16279,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2002;
gprintf(__func__, " Constant field unsupported for this grid type!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
jlend = numGridVals;
@@ -16753,7 +16302,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
else
len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- ISEC4_NumValues = len*8/ISEC4_NumBits;
+ ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
if ( lspherc )
{
@@ -16764,7 +16313,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
}
}
- if ( dfunc == 'J' ) return (bdsLen);
+ if ( dfunc == 'J' ) return bdsLen;
/* check length of output array. */
@@ -16774,10 +16323,10 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
gprintf(__func__, " Output array too small. Length = %d", fsec4len);
gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
- if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+ if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
else
{
igrib += locnd;
@@ -16787,9 +16336,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( lspherc && lcomplex )
{
- int pcStart, pcScale;
- pcStart = isec4[19];
- pcScale = isec4[16];
+ int pcStart = isec4[19], pcScale = isec4[16];
TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
}
@@ -16801,17 +16348,17 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
{
T zserr = fsec4[1];
- for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+ for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
}
}
if ( decscale )
{
T scale = (T) pow(10.0, (double)-decscale);
- for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+ for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
}
- return (bdsLen);
+ return bdsLen;
}
@@ -16821,7 +16368,6 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
{
UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
- int gribLen = 0;
int gdsIncluded = FALSE;
int bmsIncluded = FALSE;
int bitmapSize = 0;
@@ -17012,7 +16558,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
{
lmissvalinfo = 0;
- FSEC3_MissVal = GRIB_MISSVAL;
+ FSEC3_MissVal = (T)GRIB_MISSVAL;
Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
}
@@ -17021,16 +16567,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
{
- long i, j;
- GRIBPACK *pbitmap;
GRIBPACK bitmap;
- GRIBPACK *imask;
-
/*
unsigned char *bitmap;
bitmap = BMS_Bitmap;
- j = ISEC4_NumNonMissValues;
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ int j = ISEC4_NumNonMissValues;
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
{
if ( (bitmap[i/8]>>(7-(i&7)))&1 )
fsec4[i] = fsec4[--j];
@@ -17039,13 +16581,13 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
}
*/
- imask = (GRIBPACK*) Malloc(imaskSize*sizeof(GRIBPACK));
+ GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
#if defined (VECTORCODE)
(void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
- pbitmap = imask;
+ GRIBPACK *pbitmap = imask;
#else
- pbitmap = BMS_Bitmap;
+ GRIBPACK *pbitmap = BMS_Bitmap;
#endif
#if defined (CRAY)
@@ -17057,7 +16599,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = imaskSize/8-1; i >= 0; i-- )
+ for ( int i = imaskSize/8-1; i >= 0; i-- )
{
bitmap = pbitmap[i];
imask[i*8+0] = 1 & (bitmap >> 7);
@@ -17070,8 +16612,8 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
imask[i*8+7] = 1 & (bitmap);
}
- j = 0;
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( imask[i] ) j++;
if ( ISEC4_NumNonMissValues != j )
@@ -17094,7 +16636,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
}
@@ -17104,24 +16646,18 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC2_Reduced )
{
- int nlon, nlat;
- int lperio = 1, lveggy;
- int ilat;
int nvalues = 0;
-
- nlat = ISEC2_NumLat;
- nlon = ISEC2_RowLonPtr[0];
- for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
- for ( ilat = 1; ilat < nlat; ++ilat )
+ int nlat = ISEC2_NumLat;
+ int nlon = ISEC2_RowLonPtr[0];
+ for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+ for ( int ilat = 1; ilat < nlat; ++ilat )
if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
// int dlon = ISEC2_LastLon-ISEC2_FirstLon;
// if ( dlon < 0 ) dlon += 360000;
- if ( nvalues != ISEC4_NumValues )
- {
- *iret = -801;
- }
+ if ( nvalues != ISEC4_NumValues ) *iret = -801;
+
//printf("nlat %d nlon %d \n", nlat, nlon);
//printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
@@ -17136,18 +16672,20 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC4_NumValues = nlon*nlat;
lsect3 = bitmapSize > 0;
- lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
- ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
- (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+ int lperio = 1;
+ int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
+ ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
+ (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
+ (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
+ (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
+ (ISEC1_Parameter == 43));
(void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
if ( bitmapSize > 0 )
{
- long i;
- int j = 0;
-
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
ISEC4_NumNonMissValues = j;
@@ -17159,7 +16697,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
esLen = 4;
- gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+ int gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
if ( ISEC0_GRIB_Len )
if ( ISEC0_GRIB_Len < gribLen )
@@ -17167,8 +16705,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC0_GRIB_Len = gribLen;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
/*
----------------------------------------------------------------
@@ -17213,6 +16750,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
/* GRIB block 0 - indicator block */
static
void encodeIS(GRIBPACK *lGrib, long *gribLen)
@@ -17275,20 +16818,20 @@ void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
itemp = z / (-120);
itemp = JP23SET - itemp + 1;
- lGrib[4] = itemp >> 16;
- lGrib[5] = itemp >> 8;
- lGrib[6] = itemp;
+ lGrib[4] = (GRIBPACK)(itemp >> 16);
+ lGrib[5] = (GRIBPACK)(itemp >> 8);
+ lGrib[6] = (GRIBPACK)itemp;
bdslen = z - bdslen;
- lGrib[bdsstart ] = bdslen >> 16;
- lGrib[bdsstart+1] = bdslen >> 8;
- lGrib[bdsstart+2] = bdslen;
+ lGrib[bdsstart ] = (GRIBPACK)(bdslen >> 16);
+ lGrib[bdsstart+1] = (GRIBPACK)(bdslen >> 8);
+ lGrib[bdsstart+2] = (GRIBPACK)bdslen;
}
else
{
- lGrib[4] = z >> 16;
- lGrib[5] = z >> 8;
- lGrib[6] = z;
+ lGrib[4] = (GRIBPACK)(z >> 16);
+ lGrib[5] = (GRIBPACK)(z >> 8);
+ lGrib[6] = (GRIBPACK)z;
while ( z%8 ) lGrib[z++] = 0;
}
@@ -17560,6 +17103,7 @@ int BitsPerInt = (int) (sizeof(int) * 8);
#define T double
#ifdef T
+
static
void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
const T *data, T zref, T factor, size_t *gz)
@@ -17577,7 +17121,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
for ( i = packStart; i < datasize; i++ )
{
/* note float -> unsigned int .. truncate */
- ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+ ival = (unsigned int) ((data[i] - zref) * factor + (T)0.5);
/*
if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
if ( ival < 0 ) ival = 0;
@@ -17593,7 +17137,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
else
{
jbits -= cbits;
- lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+ lGrib[z++] = (GRIBPACK)((c << cbits) + ((ival >> jbits) & mask[cbits]));
cbits = 8;
c = 0;
}
@@ -17605,11 +17149,39 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
cbits -= jbits;
}
}
- if ( cbits != 8 ) lGrib[z++] = c << cbits;
+ if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
*gz = z;
}
+
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+ const T *restrict data, T zref, T factor, size_t *gz)
+{
+ U_BYTEORDER;
+ uint16_t *restrict sgrib = (uint16_t *) (lGrib+*gz);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ sgrib[i] = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ ui16 = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ sgrib[i] = gribSwapByteOrder_uint16(ui16);
+ }
+ }
+
+ *gz += 2*datasize;
+}
+/*
static
void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
const T *restrict data, T zref, T factor, size_t *gz)
@@ -17629,7 +17201,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui16 = (uint16_t) tmp;
lGrib[z ] = ui16 >> 8;
lGrib[z+1] = ui16;
@@ -17638,7 +17210,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
*gz = z;
}
-
+*/
static
void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
GRIBPACK *restrict lGrib,
@@ -17648,7 +17220,6 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
uint64_t start_minmax, end_minmax;
#endif
-
uint32_t ui32;
size_t i, z = *gz;
T tmp;
@@ -17673,8 +17244,8 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
- lGrib[z ] = (uint16_t) tmp;
+ tmp = ((data[i] - zref) * factor + (T)0.5);
+ lGrib[z ] = (GRIBPACK)tmp;
z++;
}
@@ -17691,10 +17262,9 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#elif defined _GET_MACH_COUNTER
start_minmax = mach_absolute_time();
#endif
-
if ( sizeof(T) == sizeof(double) )
{
- grib_encode_array_2byte_double(datasize, lGrib, (const double * restrict) data, zref, factor, &z);
+ grib_encode_array_2byte_double(datasize, lGrib, (const double *) data, zref, factor, &z);
}
else
{
@@ -17737,11 +17307,11 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 16;
- lGrib[z+1] = ui32 >> 8;
- lGrib[z+2] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+2] = (GRIBPACK)ui32;
z += 3;
}
@@ -17766,12 +17336,12 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 24;
- lGrib[z+1] = ui32 >> 16;
- lGrib[z+2] = ui32 >> 8;
- lGrib[z+3] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 24);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+3] = (GRIBPACK)ui32;
z += 4;
}
@@ -17805,12 +17375,11 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _ARCH_PWR6
#define __UNROLL_DEPTH_2 8
#else
-#define __UNROLL_DEPTH_2 8
+#define __UNROLL_DEPTH_2 128
#endif
size_t residual;
size_t ofs;
T dval[__UNROLL_DEPTH_2];
- unsigned long ival;
data += packStart;
datasize -= packStart;
@@ -17821,29 +17390,37 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
if ( numBits == 8 )
{
- unsigned char *cgrib = (unsigned char *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(2, "pack 8 bit unrolled");
#endif
+ unsigned char *cgrib = (unsigned char *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += __UNROLL_DEPTH_2;
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += residual;
@@ -17853,21 +17430,31 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
}
else if ( numBits == 16 )
{
- unsigned short *sgrib = (unsigned short *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(3, "pack 16 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint16_t ival;
+#endif
+ uint16_t *sgrib = (uint16_t *) (lGrib+z);
+
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*__UNROLL_DEPTH_2;
}
@@ -17875,22 +17462,25 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
- z += 2;
+ ival = (uint16_t) dval[j];
+ *sgrib++ = gribSwapByteOrder_uint16(ival);
}
+ z += 2*__UNROLL_DEPTH_2;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*residual;
}
@@ -17898,9 +17488,9 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
+ ival = (uint16_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 8);
+ lGrib[z+1] = (GRIBPACK)ival;
z += 2;
}
}
@@ -17913,31 +17503,40 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(4, "pack 24 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+#else
+ ival = (uint32_t) dval[j];
+#endif
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
#ifdef _GET_IBM_COUNTER
@@ -17949,18 +17548,27 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(5, "pack 32 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
unsigned int *igrib = (unsigned int *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
- {
+ {
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
@@ -17969,37 +17577,41 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
}
else
{
- for (j = 0; j < residual; j++)
+ for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
@@ -18025,12 +17637,19 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
#define T float
#ifdef T
+
static
void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
const T *data, T zref, T factor, size_t *gz)
@@ -18048,7 +17667,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
for ( i = packStart; i < datasize; i++ )
{
/* note float -> unsigned int .. truncate */
- ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+ ival = (unsigned int) ((data[i] - zref) * factor + (T)0.5);
/*
if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
if ( ival < 0 ) ival = 0;
@@ -18064,7 +17683,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
else
{
jbits -= cbits;
- lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+ lGrib[z++] = (GRIBPACK)((c << cbits) + ((ival >> jbits) & mask[cbits]));
cbits = 8;
c = 0;
}
@@ -18076,11 +17695,39 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
cbits -= jbits;
}
}
- if ( cbits != 8 ) lGrib[z++] = c << cbits;
+ if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
*gz = z;
}
+
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+ const T *restrict data, T zref, T factor, size_t *gz)
+{
+ U_BYTEORDER;
+ uint16_t *restrict sgrib = (uint16_t *) (lGrib+*gz);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ sgrib[i] = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ ui16 = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ sgrib[i] = gribSwapByteOrder_uint16(ui16);
+ }
+ }
+
+ *gz += 2*datasize;
+}
+/*
static
void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
const T *restrict data, T zref, T factor, size_t *gz)
@@ -18100,7 +17747,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui16 = (uint16_t) tmp;
lGrib[z ] = ui16 >> 8;
lGrib[z+1] = ui16;
@@ -18109,7 +17756,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
*gz = z;
}
-
+*/
static
void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
GRIBPACK *restrict lGrib,
@@ -18119,7 +17766,6 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
uint64_t start_minmax, end_minmax;
#endif
-
uint32_t ui32;
size_t i, z = *gz;
T tmp;
@@ -18144,8 +17790,8 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
- lGrib[z ] = (uint16_t) tmp;
+ tmp = ((data[i] - zref) * factor + (T)0.5);
+ lGrib[z ] = (GRIBPACK)tmp;
z++;
}
@@ -18162,10 +17808,9 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#elif defined _GET_MACH_COUNTER
start_minmax = mach_absolute_time();
#endif
-
if ( sizeof(T) == sizeof(double) )
{
- grib_encode_array_2byte_double(datasize, lGrib, (const double * restrict) data, zref, factor, &z);
+ grib_encode_array_2byte_double(datasize, lGrib, (const double *) data, zref, factor, &z);
}
else
{
@@ -18208,11 +17853,11 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 16;
- lGrib[z+1] = ui32 >> 8;
- lGrib[z+2] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+2] = (GRIBPACK)ui32;
z += 3;
}
@@ -18237,12 +17882,12 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 24;
- lGrib[z+1] = ui32 >> 16;
- lGrib[z+2] = ui32 >> 8;
- lGrib[z+3] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 24);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+3] = (GRIBPACK)ui32;
z += 4;
}
@@ -18276,12 +17921,11 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _ARCH_PWR6
#define __UNROLL_DEPTH_2 8
#else
-#define __UNROLL_DEPTH_2 8
+#define __UNROLL_DEPTH_2 128
#endif
size_t residual;
size_t ofs;
T dval[__UNROLL_DEPTH_2];
- unsigned long ival;
data += packStart;
datasize -= packStart;
@@ -18292,29 +17936,37 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
if ( numBits == 8 )
{
- unsigned char *cgrib = (unsigned char *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(2, "pack 8 bit unrolled");
#endif
+ unsigned char *cgrib = (unsigned char *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += __UNROLL_DEPTH_2;
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += residual;
@@ -18324,21 +17976,31 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
}
else if ( numBits == 16 )
{
- unsigned short *sgrib = (unsigned short *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(3, "pack 16 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint16_t ival;
+#endif
+ uint16_t *sgrib = (uint16_t *) (lGrib+z);
+
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*__UNROLL_DEPTH_2;
}
@@ -18346,22 +18008,25 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
- z += 2;
+ ival = (uint16_t) dval[j];
+ *sgrib++ = gribSwapByteOrder_uint16(ival);
}
+ z += 2*__UNROLL_DEPTH_2;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*residual;
}
@@ -18369,9 +18034,9 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
+ ival = (uint16_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 8);
+ lGrib[z+1] = (GRIBPACK)ival;
z += 2;
}
}
@@ -18384,31 +18049,40 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(4, "pack 24 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+#else
+ ival = (uint32_t) dval[j];
+#endif
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
#ifdef _GET_IBM_COUNTER
@@ -18420,18 +18094,27 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(5, "pack 32 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
unsigned int *igrib = (unsigned int *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
- {
+ {
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
@@ -18440,37 +18123,41 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
}
else
{
- for (j = 0; j < residual; j++)
+ for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
@@ -18496,6 +18183,12 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
@@ -18596,8 +18289,8 @@ void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
}
else
{
- lonIncr = ISEC2_LonIncr;
- latIncr = ISEC2_LatIncr;
+ lonIncr = (unsigned)ISEC2_LonIncr;
+ latIncr = (unsigned)ISEC2_LatIncr;
}
Put2Byte(lonIncr); /* 23-24 i - direction increment */
if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
@@ -18710,7 +18403,7 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
{
data[fsec4size++] = data[i];
- bitmap[i/8] |= 1<<(7-(i&7));
+ bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
}
}
#endif
@@ -18736,36 +18429,33 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
/* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
/* Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow */
- size_t z = *gribLen;
- long i, jloop;
+ size_t z = (size_t)*gribLen;
+ long i;
int numBits;
int ival;
- int blockLength, PackStart = 0, Flag = 0;
+ long PackStart = 0, Flag = 0;
int binscale = 0;
int nbpv;
int bds_head = 11;
int bds_ext = 0;
/* ibits = BitsPerInt; */
- unsigned int max_nbpv_pow2;
int exponent, mantissa;
- int unused_bits = 0;
int lspherc = FALSE, lcomplex = FALSE;
int isubset = 0, itemp = 0, itrunc = 0;
T factor = 1, fmin, fmax;
double zref;
- double range, rangec;
+ double range;
double jpepsln = 1.0e-12; /* -----> tolerance used to check equality */
/* of floating point numbers - needed */
/* on some platforms (eg vpp700, linux) */
- extern const double _pow2tab[158];
extern int CGRIBEX_Const; /* 1: Don't pack constant fields on regular grids */
if ( isec2 )
{
/* If section 2 is present, it says if data is spherical harmonic */
- if ( isec2[0] == 50 || isec2[0] == 60 ||
- isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
+ lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
+ isec2[0] == 70 || isec2[0] == 80 );
if ( lspherc )
isec4[2] = 128;
@@ -18848,7 +18538,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
pcStart = isubset;
pcScale = isec4[16];
TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
- TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+ TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
}
fmin = fmax = data[PackStart];
@@ -18864,10 +18554,10 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
- blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
- if ( (blockLength%2) == 1 ) blockLength++;
+ long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+ blockLength += blockLength & 1;
- unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+ long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
Flag += unused_bits;
@@ -18905,57 +18595,54 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
else if ( range > 1.0 )
{
- rangec = range + jpepsln;
- for ( jloop = 1; jloop < 128; jloop++ )
- {
- if ( _pow2tab[jloop] > rangec ) break;
- }
- if ( jloop == 128 )
- {
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
- }
+ double rangec = range + jpepsln,
+ p2 = 2.0;
+ long jloop = 1;
+ while ( jloop < 128 && p2 <= rangec )
+ {
+ p2 *= 2.0;
+ ++jloop;
+ }
+ if (jloop < 128)
+ binscale = jloop - nbpv;
else
- {
- binscale = jloop - nbpv;
- }
+ {
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
+ }
}
else
{
- rangec = range - jpepsln;
- for ( jloop = 1; jloop < 127; jloop++ )
+ double rangec = range - jpepsln, p05 = 0.5;
+ long jloop = 1;
+ while ( jloop < 127 && p05 >= rangec )
{
- if ( 1.0/_pow2tab[jloop] < rangec ) break;
+ p05 *= 0.5;
+ jloop++;
}
- if ( jloop == 127 )
+ if ( jloop < 127 )
{
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
+ binscale = 1 - jloop - nbpv;
}
else
{
- binscale = 1 - jloop - nbpv;
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
}
}
- //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
- max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
+ uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
if ( binscale != 0 )
{
if ( binscale < 0 )
- {
- if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
else
- {
- if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- if ( binscale < 0 ) factor = intpow2(-binscale);
- else factor = 1.0/intpow2( binscale);
+ factor = intpow2(-binscale);
}
ref2ibm(&zref, BitsPerInt);
@@ -18972,7 +18659,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
if ( lcomplex )
{
int jup = isubset;
- int ioff = z + bds_ext;
+ int ioff = (int)z + bds_ext;
if ( ioff > 0xFFFF ) ioff = 0;
Put2Byte(ioff);
Put2Int(isec4[16]);
@@ -18990,14 +18677,14 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
*datsize = ((datasize-PackStart)*nbpv + 7)/8;
#if defined (_ARCH_PWR6)
- TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#else
- TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#endif
if ( unused_bits >= 8 ) Put1Byte(0); /* Fillbyte */
- *gribLen = z;
+ *gribLen = (long)z;
return (0);
}
@@ -19012,9 +18699,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
GRIBPACK *lpds;
unsigned char *CGrib;
long fsec4size = 0;
- int numBytes;
int bmsIncluded;
- size_t len;
GRIBPACK *lGrib;
long datstart, datsize, bdsstart;
int status = 0;
@@ -19029,15 +18714,15 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
bmsIncluded = ISEC1_Sec2Or3Flag & 64;
/* set max header len */
- len = 16384;
+ size_t len = 16384;
/* add data len */
- numBytes = (ISEC4_NumBits+7)>>3;
+ size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
- len += numBytes*klenp;
+ len += numBytes*(size_t)klenp;
/* add bitmap len */
- if ( bmsIncluded ) len += (klenp+7)>>3;
+ if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
#if defined (VECTORCODE)
lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
@@ -19093,7 +18778,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
encodeES(lGrib, &gribLen, bdsstart);
- if ( (size_t) gribLen > kleng*sizeof(int) )
+ if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
#if defined (VECTORCODE)
@@ -19105,17 +18790,22 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
Free(lGrib);
#endif
- ISEC0_GRIB_Len = gribLen;
+ ISEC0_GRIB_Len = (int)gribLen;
ISEC0_GRIB_Version = 1;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
*kret = status;
}
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
@@ -19215,8 +18905,8 @@ void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
}
else
{
- lonIncr = ISEC2_LonIncr;
- latIncr = ISEC2_LatIncr;
+ lonIncr = (unsigned)ISEC2_LonIncr;
+ latIncr = (unsigned)ISEC2_LatIncr;
}
Put2Byte(lonIncr); /* 23-24 i - direction increment */
if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
@@ -19329,7 +19019,7 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
{
data[fsec4size++] = data[i];
- bitmap[i/8] |= 1<<(7-(i&7));
+ bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
}
}
#endif
@@ -19355,36 +19045,33 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
/* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
/* Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow */
- size_t z = *gribLen;
- long i, jloop;
+ size_t z = (size_t)*gribLen;
+ long i;
int numBits;
int ival;
- int blockLength, PackStart = 0, Flag = 0;
+ long PackStart = 0, Flag = 0;
int binscale = 0;
int nbpv;
int bds_head = 11;
int bds_ext = 0;
/* ibits = BitsPerInt; */
- unsigned int max_nbpv_pow2;
int exponent, mantissa;
- int unused_bits = 0;
int lspherc = FALSE, lcomplex = FALSE;
int isubset = 0, itemp = 0, itrunc = 0;
T factor = 1, fmin, fmax;
double zref;
- double range, rangec;
+ double range;
double jpepsln = 1.0e-12; /* -----> tolerance used to check equality */
/* of floating point numbers - needed */
/* on some platforms (eg vpp700, linux) */
- extern const double _pow2tab[158];
extern int CGRIBEX_Const; /* 1: Don't pack constant fields on regular grids */
if ( isec2 )
{
/* If section 2 is present, it says if data is spherical harmonic */
- if ( isec2[0] == 50 || isec2[0] == 60 ||
- isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
+ lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
+ isec2[0] == 70 || isec2[0] == 80 );
if ( lspherc )
isec4[2] = 128;
@@ -19467,7 +19154,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
pcStart = isubset;
pcScale = isec4[16];
TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
- TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+ TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
}
fmin = fmax = data[PackStart];
@@ -19483,10 +19170,10 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
- blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
- if ( (blockLength%2) == 1 ) blockLength++;
+ long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+ blockLength += blockLength & 1;
- unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+ long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
Flag += unused_bits;
@@ -19524,57 +19211,54 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
else if ( range > 1.0 )
{
- rangec = range + jpepsln;
- for ( jloop = 1; jloop < 128; jloop++ )
- {
- if ( _pow2tab[jloop] > rangec ) break;
- }
- if ( jloop == 128 )
- {
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
- }
+ double rangec = range + jpepsln,
+ p2 = 2.0;
+ long jloop = 1;
+ while ( jloop < 128 && p2 <= rangec )
+ {
+ p2 *= 2.0;
+ ++jloop;
+ }
+ if (jloop < 128)
+ binscale = jloop - nbpv;
else
- {
- binscale = jloop - nbpv;
- }
+ {
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
+ }
}
else
{
- rangec = range - jpepsln;
- for ( jloop = 1; jloop < 127; jloop++ )
+ double rangec = range - jpepsln, p05 = 0.5;
+ long jloop = 1;
+ while ( jloop < 127 && p05 >= rangec )
{
- if ( 1.0/_pow2tab[jloop] < rangec ) break;
+ p05 *= 0.5;
+ jloop++;
}
- if ( jloop == 127 )
+ if ( jloop < 127 )
{
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
+ binscale = 1 - jloop - nbpv;
}
else
{
- binscale = 1 - jloop - nbpv;
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
}
}
- //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
- max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
+ uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
if ( binscale != 0 )
{
if ( binscale < 0 )
- {
- if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
else
- {
- if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- if ( binscale < 0 ) factor = intpow2(-binscale);
- else factor = 1.0/intpow2( binscale);
+ factor = intpow2(-binscale);
}
ref2ibm(&zref, BitsPerInt);
@@ -19591,7 +19275,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
if ( lcomplex )
{
int jup = isubset;
- int ioff = z + bds_ext;
+ int ioff = (int)z + bds_ext;
if ( ioff > 0xFFFF ) ioff = 0;
Put2Byte(ioff);
Put2Int(isec4[16]);
@@ -19609,14 +19293,14 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
*datsize = ((datasize-PackStart)*nbpv + 7)/8;
#if defined (_ARCH_PWR6)
- TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#else
- TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#endif
if ( unused_bits >= 8 ) Put1Byte(0); /* Fillbyte */
- *gribLen = z;
+ *gribLen = (long)z;
return (0);
}
@@ -19631,9 +19315,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
GRIBPACK *lpds;
unsigned char *CGrib;
long fsec4size = 0;
- int numBytes;
int bmsIncluded;
- size_t len;
GRIBPACK *lGrib;
long datstart, datsize, bdsstart;
int status = 0;
@@ -19648,15 +19330,15 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
bmsIncluded = ISEC1_Sec2Or3Flag & 64;
/* set max header len */
- len = 16384;
+ size_t len = 16384;
/* add data len */
- numBytes = (ISEC4_NumBits+7)>>3;
+ size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
- len += numBytes*klenp;
+ len += numBytes*(size_t)klenp;
/* add bitmap len */
- if ( bmsIncluded ) len += (klenp+7)>>3;
+ if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
#if defined (VECTORCODE)
lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
@@ -19712,7 +19394,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
encodeES(lGrib, &gribLen, bdsstart);
- if ( (size_t) gribLen > kleng*sizeof(int) )
+ if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
#if defined (VECTORCODE)
@@ -19724,23 +19406,28 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
Free(lGrib);
#endif
- ISEC0_GRIB_Len = gribLen;
+ ISEC0_GRIB_Len = (int)gribLen;
ISEC0_GRIB_Version = 1;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
*kret = status;
}
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
void encode_dummy(void)
{
(void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
(void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
}
-static const char grb_libvers[] = "1.7.3" " of ""Sep 14 2015"" ""10:58:44";
+static const char grb_libvers[] = "1.7.4" " of ""Feb 19 2016"" ""11:03:41";
const char *
cgribexLibraryVersion(void)
{
@@ -20526,6 +20213,7 @@ void SysError_(const char *caller, const char *fmt, ...)
void SysError_(const char *caller, const char *fmt, ...)
{
va_list args;
+ int saved_errno = errno;
va_start(args, fmt);
@@ -20536,8 +20224,11 @@ void SysError_(const char *caller, const char *fmt, ...)
va_end(args);
- if ( errno )
- perror("System error message ");
+ if ( saved_errno )
+ {
+ errno = saved_errno;
+ perror("System error message");
+ }
exit(EXIT_FAILURE);
}
@@ -22680,7 +22371,15 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
#ifndef _GAUSSGRID_H
#define _GAUSSGRID_H
-void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+
+#if defined (__cplusplus)
+}
+#endif
#endif /* _GAUSSGRID_H */
/*
@@ -23170,7 +22869,44 @@ void gribContainersDelete(stream_t * streamptr)
typedef unsigned char mask_t;
-typedef struct {
+typedef struct grid_t grid_t;
+
+struct gridVirtTable
+{
+ void (*destroy)(grid_t *gridptr);
+ grid_t *(*copy)(grid_t *gridptr);
+ void (*copyScalarFields)(grid_t *gridptrOrig, grid_t *gridptrDup);
+ void (*copyArrayFields)(grid_t *gridptrOrig, grid_t *gridptrDup);
+ void (*defXVals)(grid_t *gridptr, const double *xvals);
+ void (*defYVals)(grid_t *gridptr, const double *yvals);
+ void (*defMask)(grid_t *gridptr, const int *mask);
+ void (*defMaskGME)(grid_t *gridptr, const int *mask);
+ void (*defXBounds)(grid_t *gridptr, const double *xbounds);
+ void (*defYBounds)(grid_t *gridptr, const double *ybounds);
+ void (*defArea)(grid_t *gridptr, const double *area);
+ double (*inqXVal)(grid_t *gridptr, int index);
+ double (*inqYVal)(grid_t *gridptr, int index);
+ int (*inqXVals)(grid_t *gridptr, double *xvals);
+ int (*inqYVals)(grid_t *gridptr, double *yvals);
+ const double *(*inqXValsPtr)(grid_t *gridptr);
+ const double *(*inqYValsPtr)(grid_t *gridptr);
+ /* return if for both grids, all xval and all yval are equal */
+ int (*compareXYFull)(grid_t *gridRef, grid_t *gridTest);
+ /* return if for both grids, x[0], y[0], x[size-1] and y[size-1] are
+ * respectively equal */
+ int (*compareXYAO)(grid_t *gridRef, grid_t *gridTest);
+ void (*inqArea)(grid_t *gridptr, double *area);
+ const double *(*inqAreaPtr)(grid_t *gridptr);
+ int (*hasArea)(grid_t *gridptr);
+ int (*inqMask)(grid_t *gridptr, int *mask);
+ int (*inqMaskGME)(grid_t *gridptr, int *mask_gme);
+ int (*inqXBounds)(grid_t *gridptr, double *xbounds);
+ int (*inqYBounds)(grid_t *gridptr, double *ybounds);
+ const double *(*inqXBoundsPtr)(grid_t *gridptr);
+ const double *(*inqYBoundsPtr)(grid_t *gridptr);
+};
+
+struct grid_t {
int self;
int type; /* grid type */
int prec; /* grid precision */
@@ -23222,24 +22958,28 @@ typedef struct {
int xsize; /* number of values along X */
int ysize; /* number of values along Y */
int np; /* number of parallels between a pole and the equator */
- int locked;
- int lcomplex;
- int hasdims;
+ short lcomplex;
+ short hasdims;
+ const char *xstdname;
+ const char *ystdname;
char xname[CDI_MAX_NAME];
char yname[CDI_MAX_NAME];
char xlongname[CDI_MAX_NAME];
char ylongname[CDI_MAX_NAME];
- char xstdname[CDI_MAX_NAME];
- char ystdname[CDI_MAX_NAME];
char xunits[CDI_MAX_NAME];
char yunits[CDI_MAX_NAME];
char *name;
-}
-grid_t;
+ const struct gridVirtTable *vtable;
+ void *extraData;
+};
void grid_init(grid_t *gridptr);
+void
+cdiGridTypeInit(grid_t *gridptr, int gridtype, int size);
void grid_free(grid_t *gridptr);
+grid_t *gridID2Ptr(int gridID);
+extern const struct gridVirtTable cdiGridVtable;
unsigned cdiGridCount(void);
@@ -23260,16 +23000,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
int * unpackBufferPos, int originNamespace, void *context,
int force_id);
-int varDefGrid(int vlistID, const grid_t *grid, int mode);
-
-/* These are used by CDO. */
-void gridGenXvals(int xsize, double xfirst, double xlast,
- double xinc, double *xvals);
-void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast,
- double yinc, double *yvals);
-
-
+struct addIffNewRes
+{
+ int Id;
+ int isNew;
+};
+struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode);
#endif
/*
@@ -23306,7 +23043,7 @@ void gribGetDoubleArray(grib_handle* gribHandle, const char* key, double* array)
void gribGetLongArray(grib_handle* gribHandle, const char* key, long* array); //The caller is responsible to ensure a sufficiently large buffer.
long gribEditionNumber(grib_handle* gh);
-char* gribMakeTimeString(grib_handle* gh, bool getEndTime); //For statistical fields, setting getEndTime produces the time of the end of the integration period, otherwise the time of the start of the integration period is returned. Returns NULL if getEndTime is set and the field does not have an integration period.
+char* gribMakeTimeString(grib_handle* gh, CdiTimeType timeType); //Returns NULL if timeType is kCdiTimeType_endTime and the field does not have an integration period (statistical data).
int gribapiTimeIsFC(grib_handle *gh);
int gribapiGetTsteptype(grib_handle *gh);
int gribGetDatatype(grib_handle* gribHandle);
@@ -23597,7 +23334,8 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
*outHaveForecastTime = false, *outHaveTimeRange = false;
return 0;
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 60: case 1000: case 1002: case 1100: case 40033:
+ //case 55 and case 40455 are the same: 55 is the proposed standard value, 40455 is the value in the local use range that is used by the dwd until the standard is updated.
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 60: case 1000: case 1002: case 1100: case 40033: case 40455:
*outHaveForecastTime = true, *outHaveTimeRange = false;
return 0;
@@ -23610,24 +23348,15 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
}
}
-char* gribMakeTimeString(grib_handle* gh, bool getEndTime)
+char* gribMakeTimeString(grib_handle* gh, CdiTimeType timeType)
{
//Get the parts of the reference date.
-#ifdef __cplusplus
- struct tm date;
- date.tm_mon = (int) gribGetLong(gh, "month") - 1; //months are zero based in struct tm and one based in GRIBy
+ struct tm date;
+ date.tm_mon = (int)gribGetLong(gh, "month") - 1; //months are zero based in struct tm and one based in GRIB
+ date.tm_mday = (int)gribGetLong(gh, "day");
+ date.tm_hour = (int)gribGetLong(gh, "hour");
+ date.tm_min = (int)gribGetLong(gh, "minute");
- date.tm_mday = (int)gribGetLong(gh, "day");
- date.tm_hour = (int)gribGetLong(gh, "hour");
- date.tm_min = (int)gribGetLong(gh, "minute");
-#else
- struct tm date = {
- .tm_mon = (int)gribGetLong(gh, "month") - 1, //months are zero based in struct tm and one based in GRIBy
- .tm_mday = (int)gribGetLong(gh, "day"),
- .tm_hour = (int)gribGetLong(gh, "hour"),
- .tm_min = (int)gribGetLong(gh, "minute")
- };
-#endif
if(gribEditionNumber(gh) == 1)
{
date.tm_year = (int)gribGetLong(gh, "yearOfCentury"); //years are -1900 based both in struct tm and GRIB1
@@ -23637,23 +23366,27 @@ char* gribMakeTimeString(grib_handle* gh, bool getEndTime)
date.tm_year = (int)gribGetLong(gh, "year") - 1900; //years are -1900 based in struct tm and zero based in GRIB2
date.tm_sec = (int)gribGetLong(gh, "second");
- //Determine whether we have a forecast time and a time range.
- bool haveForecastTime, haveTimeRange;
- if(getAvailabilityOfRelativeTimes(gh, &haveForecastTime, &haveTimeRange)) return NULL;
- if(getEndTime && !haveTimeRange) return NULL; //tell the caller that the requested time does not exist
-
- //If we have relative times, apply them to the date
- if(haveForecastTime)
+ //If the start or end time are requested, we need to take the relative times into account.
+ if(timeType != kCdiTimeType_referenceTime)
{
- long offset = gribGetLongDefault(gh, "forecastTime", 0); //if(stepUnits == indicatorOfUnitOfTimeRange) assert(startStep == forecastTime)
- long offsetUnit = gribGetLongDefault(gh, "indicatorOfUnitOfTimeRange", 255);
- if(addToDate(&date, offset, offsetUnit)) return NULL;
- if(getEndTime)
+ //Determine whether we have a forecast time and a time range.
+ bool haveForecastTime, haveTimeRange;
+ if(getAvailabilityOfRelativeTimes(gh, &haveForecastTime, &haveTimeRange)) return NULL;
+ if(timeType == kCdiTimeType_endTime && !haveTimeRange) return NULL; //tell the caller that the requested time does not exist
+
+ //If we have relative times, apply the relative times to the date
+ if(haveForecastTime)
{
- assert(haveTimeRange);
- long range = gribGetLongDefault(gh, "lengthOfTimeRange", 0); //if(stepUnits == indicatorOfUnitForTimeRange) assert(endStep == startStep + lengthOfTimeRange)
- long rangeUnit = gribGetLongDefault(gh, "indicatorOfUnitForTimeRange", 255);
- if(addToDate(&date, range, rangeUnit)) return NULL;
+ long offset = gribGetLongDefault(gh, "forecastTime", 0); //if(stepUnits == indicatorOfUnitOfTimeRange) assert(startStep == forecastTime)
+ long offsetUnit = gribGetLongDefault(gh, "indicatorOfUnitOfTimeRange", 255);
+ if(addToDate(&date, offset, offsetUnit)) return NULL;
+ if(timeType == kCdiTimeType_endTime)
+ {
+ assert(haveTimeRange);
+ long range = gribGetLongDefault(gh, "lengthOfTimeRange", 0); //if(stepUnits == indicatorOfUnitForTimeRange) assert(endStep == startStep + lengthOfTimeRange)
+ long rangeUnit = gribGetLongDefault(gh, "indicatorOfUnitForTimeRange", 255);
+ if(addToDate(&date, range, rangeUnit)) return NULL;
+ }
}
}
}
@@ -23784,7 +23517,8 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
ISEC4_NumValues = ISEC2_NumLon*ISEC2_NumLat;
}
*/
- memset(grid, 0, sizeof(grid_t));
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
size_t datasize;
FAIL_ON_GRIB_ERROR(grib_get_size, gh, "values", &datasize);
@@ -24104,6 +23838,46 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
* require-trailing-newline: t
* End:
*/
+#ifndef CDI_UUID_H
+#define CDI_UUID_H
+
+#if defined (HAVE_CONFIG_H)
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int cdiUUIDIsNull(const unsigned char uuid[])
+{
+ int isNull = 1;
+ for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
+ isNull &= (uuid[i] == 0);
+ return isNull;
+}
+
+void cdiCreateUUID(unsigned char uuid[CDI_UUID_SIZE]);
+
+void cdiUUID2Str(const unsigned char uuid[], char uuidstr[]);
+int cdiStr2UUID(const char *uuidstr, unsigned char uuid[]);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
#ifndef RESOURCE_UNPACK_H
#define RESOURCE_UNPACK_H
@@ -24252,7 +24026,10 @@ var_t;
typedef struct
{
- int locked;
+ //set when a vlist is passed to streamDefVlist() to safeguard against modifications of the wrong vlist object
+ bool immutable;
+ //set if this vlist has been created by CDI itself, and must not be destroyed by the user, consequently
+ bool internal;
int self;
int nvars; /* number of variables */
int ngrids;
@@ -24274,15 +24051,15 @@ vlist_t;
vlist_t *vlist_to_pointer(int vlistID);
+void cdiVlistMakeInternal(int vlistID);
+void cdiVlistMakeImmutable(int vlistID);
void vlistCheckVarID(const char *caller, int vlistID, int varID);
-const char *vlistInqVarNamePtr(int vlistID, int varID);
-const char *vlistInqVarLongnamePtr(int vlistID, int varID);
const char *vlistInqVarStdnamePtr(int vlistID, int varID);
-const char *vlistInqVarUnitsPtr(int vlistID, int varID);
void vlistDestroyVarName(int vlistID, int varID);
void vlistDestroyVarLongname(int vlistID, int varID);
void vlistDestroyVarStdname(int vlistID, int varID);
void vlistDestroyVarUnits(int vlistID, int varID);
+void cdiVlistDestroy_(int vlistID);
void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype);
int vlistInqVarMissvalUsed(int vlistID, int varID);
int vlistHasTime(int vlistID);
@@ -24303,9 +24080,6 @@ void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]);
int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
-void vlist_lock(int vlistID);
-void vlist_unlock(int vlistID);
-
void resize_opt_grib_entries(var_t *var, int nentries);
@@ -24384,6 +24158,7 @@ resOps vlistOps;
#if defined (HAVE_CONFIG_H)
#endif
+#include <assert.h>
#include <string.h>
#include <float.h> /* FLT_EPSILON */
#include <limits.h> /* INT_MAX */
@@ -24413,6 +24188,23 @@ static const char Grids[][17] = {
/* 15 */ "projection",
};
+/* must match table below */
+enum xystdname_idx {
+ grid_xystdname_grid_latlon,
+ grid_xystdname_latlon,
+ grid_xystdname_projection,
+};
+static const char xystdname_tab[][2][24] = {
+ [grid_xystdname_grid_latlon] = { "grid_longitude",
+ "grid_latitude" },
+ [grid_xystdname_latlon] = { "longitude",
+ "latitude" },
+ [grid_xystdname_projection] = { "projection_x_coordinate",
+ "projection_y_coordinate" },
+
+};
+
+
static int gridCompareP ( void * gridptr1, void * gridptr2 );
static void gridDestroyP ( void * gridptr );
@@ -24433,7 +24225,13 @@ static const resOps gridOps = {
static int GRID_Debug = 0; /* If set to 1, debugging */
+grid_t *gridID2Ptr(int gridID)
+{
+ return (grid_t *)reshGetVal(gridID, &gridOps);
+}
#define gridID2Ptr(gridID) (grid_t *)reshGetVal(gridID, &gridOps)
+#define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
+
void grid_init(grid_t *gridptr)
{
@@ -24496,7 +24294,6 @@ void grid_init(grid_t *gridptr)
gridptr->xpole = 0.0;
gridptr->ypole = 0.0;
gridptr->angle = 0.0;
- gridptr->locked = FALSE;
gridptr->lcomplex = 0;
gridptr->hasdims = TRUE;
gridptr->xname[0] = 0;
@@ -24505,26 +24302,30 @@ void grid_init(grid_t *gridptr)
gridptr->ylongname[0] = 0;
gridptr->xunits[0] = 0;
gridptr->yunits[0] = 0;
- gridptr->xstdname[0] = 0;
- gridptr->ystdname[0] = 0;
+ gridptr->xstdname = NULL;
+ gridptr->ystdname = NULL;
memset(gridptr->uuid, 0, CDI_UUID_SIZE);
gridptr->name = NULL;
+ gridptr->vtable = &cdiGridVtable;
+ gridptr->extraData = NULL;
}
-void grid_free(grid_t *gridptr)
+static void
+grid_free_components(grid_t *gridptr)
{
- if ( gridptr->mask ) Free(gridptr->mask);
- if ( gridptr->mask_gme ) Free(gridptr->mask_gme);
- if ( gridptr->xvals ) Free(gridptr->xvals);
- if ( gridptr->yvals ) Free(gridptr->yvals);
- if ( gridptr->area ) Free(gridptr->area);
- if ( gridptr->xbounds ) Free(gridptr->xbounds);
- if ( gridptr->ybounds ) Free(gridptr->ybounds);
- if ( gridptr->rowlon ) Free(gridptr->rowlon);
- if ( gridptr->reference ) Free(gridptr->reference);
- if ( gridptr->name ) Free(gridptr->name);
+ void *p2free[] = { gridptr->mask, gridptr->mask_gme,
+ gridptr->xvals, gridptr->yvals,
+ gridptr->xbounds, gridptr->ybounds,
+ gridptr->rowlon, gridptr->area,
+ gridptr->reference, gridptr->name };
+ for (size_t i = 0; i < sizeof (p2free) / sizeof (p2free[0]); ++i)
+ if (p2free[i]) Free(p2free[i]);
+}
+void grid_free(grid_t *gridptr)
+{
+ grid_free_components(gridptr);
grid_init(gridptr);
}
@@ -24557,14 +24358,23 @@ void gridInit (void)
if ( env ) GRID_Debug = atoi(env);
}
-static
-void grid_copy(grid_t *gridptr2, grid_t *gridptr1)
+static void
+grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
{
- int gridID2;
+ memcpy(gridptrDup, gridptrOrig, sizeof(grid_t));
+ gridptrDup->self = CDI_UNDEFID;
+ if (gridptrOrig->reference)
+ gridptrDup->reference = strdupx(gridptrOrig->reference);
+}
- gridID2 = gridptr2->self;
- memcpy(gridptr2, gridptr1, sizeof(grid_t));
- gridptr2->self = gridID2;
+
+static grid_t *
+grid_copy_base(grid_t *gridptrOrig)
+{
+ grid_t *gridptrDup = (grid_t *)Malloc(sizeof (*gridptrDup));
+ gridptrOrig->vtable->copyScalarFields(gridptrOrig, gridptrDup);
+ gridptrOrig->vtable->copyArrayFields(gridptrOrig, gridptrDup);
+ return gridptrDup;
}
unsigned cdiGridCount(void)
@@ -24572,8 +24382,145 @@ unsigned cdiGridCount(void)
return reshCountType(&gridOps);
}
+static inline void
+gridSetXname(grid_t *gridptr, const char *xname)
+{
+ strncpy(gridptr->xname, xname, CDI_MAX_NAME);
+ gridptr->xname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetXlongname(grid_t *gridptr, const char *xlongname)
+{
+ strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
+ gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetXunits(grid_t *gridptr, const char *xunits)
+{
+ strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
+ gridptr->xunits[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYname(grid_t *gridptr, const char *yname)
+{
+ strncpy(gridptr->yname, yname, CDI_MAX_NAME);
+ gridptr->yname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYlongname(grid_t *gridptr, const char *ylongname)
+{
+ strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
+ gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYunits(grid_t *gridptr, const char *yunits)
+{
+ strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
+ gridptr->yunits[CDI_MAX_NAME - 1] = 0;
+}
+
+void
+cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
+{
+
+ gridptr->type = gridtype;
+ gridptr->size = size;
+
+ switch (gridtype)
+ {
+ case GRID_CURVILINEAR:
+ gridptr->nvertex = 4;
+ /* Fall through */
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ case GRID_GAUSSIAN_REDUCED:
+ case GRID_TRAJECTORY:
+ {
+ if ( gridtype == GRID_TRAJECTORY )
+ {
+ gridSetXname(gridptr, "tlon");
+ gridSetYname(gridptr, "tlat");
+ }
+ else
+ {
+ gridSetXname(gridptr, "lon");
+ gridSetYname(gridptr, "lat");
+ }
+ gridSetXlongname(gridptr, "longitude");
+ gridSetYlongname(gridptr, "latitude");
+
+ /*
+ if ( gridtype == GRID_CURVILINEAR )
+ {
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+ gridDefXunits(gridID, "degrees");
+ gridDefYunits(gridID, "degrees");
+ }
+ else
+ */
+ {
+ gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
+ gridSetXunits(gridptr, "degrees_east");
+ gridSetYunits(gridptr, "degrees_north");
+ }
+
+ break;
+ }
+ case GRID_UNSTRUCTURED:
+ gridptr->xsize = size;
+ /* Fall through */
+ case GRID_GME:
+ {
+ gridSetXname(gridptr, "lon");
+ gridSetYname(gridptr, "lat");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
+ gridSetXunits(gridptr, "degrees_east");
+ gridSetYunits(gridptr, "degrees_north");
+ break;
+ }
+ case GRID_GENERIC:
+ {
+
+ /* gridptr->xsize = size; */
+ gridSetXname(gridptr, "x");
+ gridSetYname(gridptr, "y");
+ /*
+ strcpy(gridptr->xstdname, "grid_longitude");
+ strcpy(gridptr->ystdname, "grid_latitude");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+ gridDefXunits(gridID, "degrees");
+ gridDefYunits(gridID, "degrees");
+ */
+ break;
+ }
+ case GRID_LCC2:
+ case GRID_SINUSOIDAL:
+ case GRID_LAEA:
+ {
+ gridSetXname(gridptr, "x");
+ gridSetYname(gridptr, "y");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
+ gridSetXunits(gridptr, "m");
+ gridSetYunits(gridptr, "m");
+ break;
+ }
+ }
+
+}
+
+
// used also in CDO
-void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
+void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *restrict xvals)
{
if ( (! (fabs(xinc) > 0)) && xsize > 1 )
{
@@ -24593,7 +24540,7 @@ void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *x
}
static
-void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
+void calc_gaussgrid(double *restrict yvals, int ysize, double yfirst, double ylast)
{
double *restrict yw = (double *) Malloc((size_t)ysize * sizeof(double));
gaussaw(yvals, yw, (size_t)ysize);
@@ -24614,7 +24561,7 @@ void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
}
// used also in CDO
-void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals)
+void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
{
const double deleps = 0.002;
@@ -24629,7 +24576,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
{
double *restrict ytmp = NULL;
int nstart, lfound = 0;
- int ny = (int) (180./fabs(ylast-yfirst)/(ysize-1) + 0.5);
+ int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
ny -= ny%2;
if ( ny > ysize && ny < 4096 )
{
@@ -24758,89 +24705,7 @@ int gridCreate(int gridtype, int size)
if ( CDI_Debug ) Message("gridID: %d", gridID);
- gridptr->type = gridtype;
- gridptr->size = size;
-
- /* if ( gridtype == GRID_GENERIC ) gridptr->xsize = size; */
- if ( gridtype == GRID_UNSTRUCTURED ) gridptr->xsize = size;
- if ( gridtype == GRID_CURVILINEAR ) gridptr->nvertex = 4;
-
- switch (gridtype)
- {
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- case GRID_GAUSSIAN_REDUCED:
- case GRID_CURVILINEAR:
- case GRID_TRAJECTORY:
- {
- if ( gridtype == GRID_TRAJECTORY )
- {
- gridDefXname(gridID, "tlon");
- gridDefYname(gridID, "tlat");
- }
- else
- {
- gridDefXname(gridID, "lon");
- gridDefYname(gridID, "lat");
- }
- gridDefXlongname(gridID, "longitude");
- gridDefYlongname(gridID, "latitude");
-
- /*
- if ( gridtype == GRID_CURVILINEAR )
- {
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
- gridDefXunits(gridID, "degrees");
- gridDefYunits(gridID, "degrees");
- }
- else
- */
- {
- strcpy(gridptr->xstdname, "longitude");
- strcpy(gridptr->ystdname, "latitude");
- gridDefXunits(gridID, "degrees_east");
- gridDefYunits(gridID, "degrees_north");
- }
-
- break;
- }
- case GRID_GME:
- case GRID_UNSTRUCTURED:
- {
- gridDefXname(gridID, "lon");
- gridDefYname(gridID, "lat");
- strcpy(gridptr->xstdname, "longitude");
- strcpy(gridptr->ystdname, "latitude");
- gridDefXunits(gridID, "degrees_east");
- gridDefYunits(gridID, "degrees_north");
- break;
- }
- case GRID_GENERIC:
- {
- gridDefXname(gridID, "x");
- gridDefYname(gridID, "y");
- /*
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
- gridDefXunits(gridID, "degrees");
- gridDefYunits(gridID, "degrees");
- */
- break;
- }
- case GRID_LCC2:
- case GRID_SINUSOIDAL:
- case GRID_LAEA:
- {
- gridDefXname(gridID, "x");
- gridDefYname(gridID, "y");
- strcpy(gridptr->xstdname, "projection_x_coordinate");
- strcpy(gridptr->ystdname, "projection_y_coordinate");
- gridDefXunits(gridID, "m");
- gridDefYunits(gridID, "m");
- break;
- }
- }
+ cdiGridTypeInit(gridptr, gridtype, size);
return (gridID);
}
@@ -24854,16 +24719,7 @@ void gridDestroyKernel( grid_t * gridptr )
id = gridptr->self;
- if ( gridptr->mask ) Free(gridptr->mask);
- if ( gridptr->mask_gme ) Free(gridptr->mask_gme);
- if ( gridptr->xvals ) Free(gridptr->xvals);
- if ( gridptr->yvals ) Free(gridptr->yvals);
- if ( gridptr->area ) Free(gridptr->area);
- if ( gridptr->xbounds ) Free(gridptr->xbounds);
- if ( gridptr->ybounds ) Free(gridptr->ybounds);
- if ( gridptr->rowlon ) Free(gridptr->rowlon);
- if ( gridptr->reference ) Free(gridptr->reference);
-
+ grid_free_components(gridptr);
Free( gridptr );
reshRemove ( id, &gridOps );
@@ -24882,13 +24738,12 @@ void gridDestroyKernel( grid_t * gridptr )
void gridDestroy(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- gridDestroyKernel ( gridptr );
+ gridptr->vtable->destroy(gridptr);
}
void gridDestroyP ( void * gridptr )
{
- gridDestroyKernel (( grid_t * ) gridptr );
+ ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
}
@@ -24923,16 +24778,15 @@ The function @func{gridDefXname} defines the name of a X-axis.
*/
void gridDefXname(int gridID, const char *xname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( xname )
+ if ( xname && *xname )
{
- strncpy(gridptr->xname, xname, CDI_MAX_NAME);
- gridptr->xname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXname(gridptr, xname);
+ gridMark4Update(gridID);
}
}
+
/*
@Function gridDefXlongname
@Title Define the longname of a X-axis
@@ -24949,12 +24803,11 @@ The function @func{gridDefXlongname} defines the longname of a X-axis.
*/
void gridDefXlongname(int gridID, const char *xlongname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
if ( xlongname )
{
- strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
- gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXlongname(gridptr, xlongname);
+ gridMark4Update(gridID);
}
}
@@ -24974,13 +24827,11 @@ The function @func{gridDefXunits} defines the units of a X-axis.
*/
void gridDefXunits(int gridID, const char *xunits)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( xunits )
{
- strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
- gridptr->xunits[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXunits(gridptr, xunits);
+ gridMark4Update(gridID);
}
}
@@ -25000,13 +24851,11 @@ The function @func{gridDefYname} defines the name of a Y-axis.
*/
void gridDefYname(int gridID, const char *yname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( yname )
+ if ( yname && *yname )
{
- strncpy(gridptr->yname, yname, CDI_MAX_NAME);
- gridptr->yname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYname(gridptr, yname);
+ gridMark4Update(gridID);
}
}
@@ -25026,13 +24875,11 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis.
*/
void gridDefYlongname(int gridID, const char *ylongname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( ylongname )
{
- strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
- gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYlongname(gridptr, ylongname);
+ gridMark4Update(gridID);
}
}
@@ -25052,13 +24899,11 @@ The function @func{gridDefYunits} defines the units of a Y-axis.
*/
void gridDefYunits(int gridID, const char *yunits)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( yunits )
{
- strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
- gridptr->yunits[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYunits(gridptr, yunits);
+ gridMark4Update(gridID);
}
}
@@ -25144,8 +24989,10 @@ void gridInqXunits(int gridID, char *xunits)
void gridInqXstdname(int gridID, char *xstdname)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- strcpy(xstdname, gridptr->xstdname);
+ if ( gridptr->xstdname )
+ strcpy(xstdname, gridptr->xstdname);
+ else
+ xstdname[0] = 0;
}
/*
@@ -25229,8 +25076,10 @@ void gridInqYunits(int gridID, char *yunits)
void gridInqYstdname(int gridID, char *ystdname)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- strcpy(ystdname, gridptr->ystdname);
+ if ( gridptr->ystdname )
+ strcpy(ystdname, gridptr->ystdname);
+ else
+ ystdname[0] = 0;
}
/*
@@ -25291,7 +25140,7 @@ int gridInqSize(int gridID)
ysize = gridptr->ysize;
if ( ysize )
- size = xsize *ysize;
+ size = xsize * ysize;
else
size = xsize;
@@ -25339,7 +25188,7 @@ void gridDefTrunc(int gridID, int trunc)
if (gridptr->trunc != trunc)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->trunc = trunc;
}
}
@@ -25366,16 +25215,17 @@ void gridDefXsize(int gridID, int xsize)
if ( xsize > gridSize )
Error("xsize %d is greater then gridsize %d", xsize, gridSize);
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED && xsize != gridSize )
+ int gridType = gridInqType(gridID);
+ if ( gridType == GRID_UNSTRUCTURED && xsize != gridSize )
Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridSize);
if (gridptr->xsize != xsize)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->xsize = xsize;
}
- if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
+ if ( gridType != GRID_UNSTRUCTURED )
{
long axisproduct = gridptr->xsize*gridptr->ysize;
if ( axisproduct > 0 && axisproduct != gridSize )
@@ -25400,7 +25250,7 @@ void gridDefPrec(int gridID, int prec)
if (gridptr->prec != prec)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->prec = prec;
}
}
@@ -25473,7 +25323,7 @@ void gridDefYsize(int gridID, int ysize)
if (gridptr->ysize != ysize)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->ysize = ysize;
}
@@ -25530,7 +25380,7 @@ void gridDefNP(int gridID, int np)
if (gridptr->np != np)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->np = np;
}
}
@@ -25576,7 +25426,7 @@ void gridDefRowlon(int gridID, int nrowlon, const int rowlon[])
gridptr->rowlon = (int *) Malloc((size_t)nrowlon * sizeof(int));
gridptr->nrowlon = nrowlon;
memcpy(gridptr->rowlon, rowlon, (size_t)nrowlon * sizeof(int));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
/*
@@ -25598,34 +25448,48 @@ void gridInqRowlon(int gridID, int *rowlon)
memcpy(rowlon, gridptr->rowlon, (size_t)gridptr->nrowlon * sizeof(int));
}
-
-int gridInqMask(int gridID, int *mask)
+static int
+gridInqMaskSerialGeneric(grid_t *gridptr, mask_t **internalMask,
+ int *restrict mask)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
long size = gridptr->size;
if ( CDI_Debug && size == 0 )
- Warning("Size undefined for gridID = %d", gridID);
-
- if (mask && gridptr->mask)
- for (long i = 0; i < size; ++i)
- mask[i] = (int)gridptr->mask[i];
+ Warning("Size undefined for gridID = %d", gridptr->self);
- if ( gridptr->mask == NULL ) size = 0;
+ const mask_t *restrict mask_src = *internalMask;
+ if (mask_src)
+ {
+ if (mask && size > 0)
+ for (size_t i = 0; i < (size_t)size; ++i)
+ mask[i] = (int)mask_src[i];
+ }
+ else
+ size = 0;
return (int)size;
}
+static int
+gridInqMaskSerial(grid_t *gridptr, int *mask)
+{
+ return gridInqMaskSerialGeneric(gridptr, &gridptr->mask, mask);
+}
+
-void gridDefMask(int gridID, const int *mask)
+int gridInqMask(int gridID, int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqMask(gridptr, mask);
+}
+static void
+gridDefMaskSerial(grid_t *gridptr, const int *mask)
+{
long size = gridptr->size;
if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
+ Error("Size undefined for gridID = %d", gridptr->self);
if ( mask == NULL )
{
@@ -25647,34 +25511,32 @@ void gridDefMask(int gridID, const int *mask)
}
}
-
-int gridInqMaskGME(int gridID, int *mask)
+void gridDefMask(int gridID, const int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- long size = gridptr->size;
-
- if ( CDI_Debug && size == 0 )
- Warning("Size undefined for gridID = %d", gridID);
-
- if ( mask && gridptr->mask_gme )
- for (long i = 0; i < size; ++i)
- mask[i] = (int)gridptr->mask_gme[i];
-
- if ( gridptr->mask_gme == NULL ) size = 0;
-
- return (int)size;
+ gridptr->vtable->defMask(gridptr, mask);
+ gridMark4Update(gridID);
}
+static int
+gridInqMaskGMESerial(grid_t *gridptr, int *mask_gme)
+{
+ return gridInqMaskSerialGeneric(gridptr, &gridptr->mask_gme, mask_gme);
+}
-void gridDefMaskGME(int gridID, const int *mask)
+int gridInqMaskGME(int gridID, int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqMaskGME(gridptr, mask);
+}
+static void
+gridDefMaskGMESerial(grid_t *gridptr, const int *mask)
+{
long size = gridptr->size;
if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
+ Error("Size undefined for gridID = %d", gridptr->self);
if ( gridptr->mask_gme == NULL )
gridptr->mask_gme = (mask_t *) Malloc((size_t)size * sizeof (mask_t));
@@ -25685,6 +25547,41 @@ void gridDefMaskGME(int gridID, const int *mask)
gridptr->mask_gme[i] = (mask_t)(mask[i] != 0);
}
+void gridDefMaskGME(int gridID, const int *mask)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defMaskGME(gridptr, mask);
+ gridMark4Update(gridID);
+}
+
+
+static int
+gridInqXValsSerial(grid_t *gridptr, double *xvals)
+{
+ long size;
+ if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
+ size = gridptr->size;
+ else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
+ size = 2;
+ else
+ size = gridptr->xsize;
+
+ if ( CDI_Debug && size == 0 )
+ Warning("size undefined for gridID = %d", gridptr->self);
+
+ if ( gridptr->xvals )
+ {
+ if ( size && xvals )
+ {
+ const double *gridptr_xvals = gridptr->vtable->inqXValsPtr(gridptr);
+ memcpy(xvals, gridptr_xvals, (size_t)size * sizeof (double));
+ }
+ }
+ else
+ size = 0;
+ return (int)size;
+}
+
/*
@Function gridInqXvals
@Title Get all values of a X-axis
@@ -25708,24 +25605,31 @@ Otherwise, 0 is returned and @func{xvals} is empty.
int gridInqXvals(int gridID, double *xvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXVals(gridptr, xvals);
+}
+
+
+static void
+gridDefXValsSerial(grid_t *gridptr, const double *xvals)
+{
+ int gridtype = gridptr->type;
long size;
- if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
+ if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
size = gridptr->size;
- else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
+ else if ( gridtype == GRID_GAUSSIAN_REDUCED )
size = 2;
else
size = gridptr->xsize;
- if ( CDI_Debug && size == 0 )
- Warning("size undefined for gridID = %d", gridID);
-
- if ( size && xvals && gridptr->xvals )
- memcpy(xvals, gridptr->xvals, (size_t)size * sizeof (double));
-
- if ( gridptr->xvals == NULL ) size = 0;
+ if ( size == 0 )
+ Error("Size undefined for gridID = %d", gridptr->self);
- return (int)size;
+ if (gridptr->xvals && CDI_Debug)
+ Warning("values already defined!");
+ gridptr->xvals = (double *)Realloc(gridptr->xvals,
+ (size_t)size * sizeof(double));
+ memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
}
/*
@@ -25745,26 +25649,33 @@ The function @func{gridDefXvals} defines all values of the X-axis.
void gridDefXvals(int gridID, const double *xvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defXVals(gridptr, xvals);
+ gridMark4Update(gridID);
+}
+
+static int
+gridInqYValsSerial(grid_t *gridptr, double *yvals)
+{
int gridtype = gridptr->type;
+ long size
+ = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+ ? gridptr->size : gridptr->ysize;
- long size;
+ if ( CDI_Debug && size == 0 )
+ Warning("size undefined for gridID = %d!", gridptr->self);
- if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
- size = gridptr->size;
- else if ( gridtype == GRID_GAUSSIAN_REDUCED )
- size = 2;
+ if ( gridptr->yvals )
+ {
+ if ( size && yvals )
+ {
+ const double *gridptr_yvals = gridptr->vtable->inqYValsPtr(gridptr);
+ memcpy(yvals, gridptr_yvals, (size_t)size * sizeof (double));
+ }
+ }
else
- size = gridptr->xsize;
+ size = 0;
- if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
-
- if (gridptr->xvals && CDI_Debug)
- Warning("values already defined!");
- gridptr->xvals = (double *) Realloc(gridptr->xvals,
- (size_t)size * sizeof(double));
- memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return (int)size;
}
/*
@@ -25790,23 +25701,28 @@ Otherwise, 0 is returned and @func{yvals} is empty.
int gridInqYvals(int gridID, double *yvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYVals(gridptr, yvals);
+}
+static void
+gridDefYValsSerial(grid_t *gridptr, const double *yvals)
+{
int gridtype = gridptr->type;
long size
= (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
? gridptr->size : gridptr->ysize;
- if ( CDI_Debug && size == 0 )
- Warning("size undefined for gridID = %d!", gridID);
-
- if ( size && yvals && gridptr->yvals )
- memcpy(yvals, gridptr->yvals, (size_t)size * sizeof (double));
+ if ( size == 0 )
+ Error("Size undefined for gridID = %d!", gridptr->self);
- if ( gridptr->yvals == NULL ) size = 0;
+ if (gridptr->yvals && CDI_Debug)
+ Warning("Values already defined!");
- return (int)size;
+ gridptr->yvals = (double *)Realloc(gridptr->yvals, (size_t)size * sizeof (double));
+ memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
}
+
/*
@Function gridDefYvals
@Title Define the values of a Y-axis
@@ -25824,32 +25740,29 @@ The function @func{gridDefYvals} defines all values of the Y-axis.
void gridDefYvals(int gridID, const double *yvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defYVals(gridptr, yvals);
+ gridMark4Update(gridID);
+}
- int gridtype = gridptr->type;
- long size
- = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
- ? gridptr->size : gridptr->ysize;
-
- if ( size == 0 )
- Error("Size undefined for gridID = %d!", gridID);
-
- if (gridptr->yvals && CDI_Debug)
- Warning("Values already defined!");
-
- gridptr->yvals = (double *) Realloc(gridptr->yvals, (size_t)size * sizeof (double));
- memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+static double
+gridInqXValSerial(grid_t *gridptr, int index)
+{
+ double xval = gridptr->xvals ? gridptr->xvals[index] : 0;
+ return xval;
}
double gridInqXval(int gridID, int index)
{
- double xval = 0;
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXVal(gridptr, index);
+}
- if ( gridptr->xvals ) xval = gridptr->xvals[index];
-
- return xval;
+static double
+gridInqYValSerial(grid_t *gridptr, int index)
+{
+ double yval = gridptr->yvals ? gridptr->yvals[index] : 0;
+ return yval;
}
/*
@@ -25864,12 +25777,8 @@ double gridInqXval(int gridID, int index)
*/
double gridInqYval(int gridID, int index)
{
- double yval = 0;
grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( gridptr->yvals ) yval = gridptr->yvals[index];
-
- return yval;
+ return gridptr->vtable->inqYVal(gridptr, index);
}
/*
@@ -25886,7 +25795,7 @@ double gridInqXinc(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
double xinc = gridptr->xinc;
- const double *restrict xvals = gridptr->xvals;
+ const double *restrict xvals = gridptr->vtable->inqXValsPtr(gridptr);
if ( (! (fabs(xinc) > 0)) && xvals )
{
@@ -25894,7 +25803,7 @@ double gridInqXinc(int gridID)
if ( xsize > 1 )
{
xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
- for ( size_t i = 2; i < (size_t)xsize; i++ )
+ for (size_t i = 2; i < (size_t)xsize; i++ )
if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc )
{
xinc = 0;
@@ -25922,7 +25831,7 @@ double gridInqYinc(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
double yinc = gridptr->yinc;
- const double *yvals = gridptr->yvals;
+ const double *yvals = gridptr->vtable->inqYValsPtr(gridptr);
if ( (! (fabs(yinc) > 0)) && yvals )
{
@@ -25931,8 +25840,8 @@ double gridInqYinc(int gridID)
{
yinc = yvals[1] - yvals[0];
double abs_yinc = fabs(yinc);
- for ( size_t i = 2; i < (size_t)ysize; i++ )
- if ( fabs(fabs(yvals[i] - yvals[i-1]) - abs_yinc) > (0.01*abs_yinc))
+ for (size_t i = 2; i < (size_t)ysize; i++ )
+ if ( fabs(fabs(yvals[i] - yvals[i-1]) - abs_yinc) > (0.01*abs_yinc) )
{
yinc = 0;
break;
@@ -25978,14 +25887,14 @@ void gridDefXpole(int gridID, double xpole)
// Xpole -> grid_north_pole_longitude
grid_t *gridptr = gridID2Ptr(gridID);
- if ( memcmp(gridptr->xstdname, "grid", 4) != 0 )
- strcpy(gridptr->xstdname, "grid_longitude");
+ if ( gridptr->xstdname && memcmp(gridptr->xstdname, "grid", 4) != 0 )
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) )
{
gridptr->isRotated = TRUE;
gridptr->xpole = xpole;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26022,14 +25931,14 @@ void gridDefYpole(int gridID, double ypole)
// Ypole -> grid_north_pole_latitude
grid_t *gridptr = gridID2Ptr(gridID);
- if ( memcmp(gridptr->ystdname, "grid", 4) != 0 )
- strcpy(gridptr->ystdname, "grid_latitude");
+ if ( gridptr->ystdname && memcmp(gridptr->ystdname, "grid", 4) != 0 )
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) )
{
gridptr->isRotated = TRUE;
gridptr->ypole = ypole;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26070,7 +25979,7 @@ void gridDefAngle(int gridID, double angle)
{
gridptr->isRotated = TRUE;
gridptr->angle = angle;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26108,7 +26017,7 @@ void gridDefGMEnd(int gridID, int nd)
if (gridptr->nd != nd)
{
gridptr->nd = nd;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26146,7 +26055,7 @@ void gridDefGMEni(int gridID, int ni)
if (gridptr->ni != ni)
{
gridptr->ni = ni;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26184,7 +26093,7 @@ void gridDefGMEni2(int gridID, int ni2)
if (gridptr->ni2 != ni2)
{
gridptr->ni2 = ni2;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26212,7 +26121,7 @@ void gridDefGMEni3(int gridID, int ni3)
if (gridptr->ni3 != ni3)
{
gridptr->ni3 = ni3;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26236,7 +26145,7 @@ void gridChangeType(int gridID, int gridtype)
if (gridptr->type != gridtype)
{
gridptr->type = gridtype;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -26244,18 +26153,20 @@ static
void grid_check_cyclic(grid_t *gridptr)
{
gridptr->isCyclic = FALSE;
-
- int xsize = gridptr->xsize,
- ysize = gridptr->ysize;
- const double *xvals = gridptr->xvals,
- *xbounds = gridptr->xbounds;
+ enum { numVertices = 4 };
+ size_t xsize = gridptr->xsize >= 0 ? (size_t)gridptr->xsize : 0,
+ ysize = gridptr->ysize >= 0 ? (size_t)gridptr->ysize : 0;
+ const double *xvals = gridptr->vtable->inqXValsPtr(gridptr),
+ (*xbounds)[numVertices]
+ = (const double (*)[numVertices])gridptr->vtable->inqXBoundsPtr(gridptr);
if ( gridptr->type == GRID_GAUSSIAN || gridptr->type == GRID_LONLAT )
{
if ( xvals && xsize > 1 )
{
double xinc = xvals[1] - xvals[0];
- if ( IS_EQUAL(xinc, 0) ) xinc = (xvals[xsize-1] - xvals[0])/(xsize-1);
+ if ( IS_EQUAL(xinc, 0) )
+ xinc = (xvals[xsize-1] - xvals[0])/(double)(xsize-1);
double x0 = 2*xvals[xsize-1]-xvals[xsize-2]-360;
@@ -26267,10 +26178,10 @@ void grid_check_cyclic(grid_t *gridptr)
{
if ( xvals && xsize > 1 )
{
- long nc = 0;
- for ( int j = 0; j < ysize; ++j )
+ size_t nc = 0;
+ for ( size_t j = 0; j < ysize; ++j )
{
- long i1 = j*xsize,
+ size_t i1 = j*xsize,
i2 = j*xsize+1,
in = j*xsize+(xsize-1);
double val1 = xvals[i1],
@@ -26289,23 +26200,22 @@ void grid_check_cyclic(grid_t *gridptr)
nc += fabs(x0-val1) < 0.5*xinc;
}
- gridptr->isCyclic = nc > 0.5*ysize ? TRUE : FALSE;
+ gridptr->isCyclic = nc > ysize/2 ? TRUE : FALSE;
}
if ( xbounds && xsize > 1 )
{
- gridptr->isCyclic = TRUE;
- for ( int j = 0; j < ysize; ++j )
+ short isCyclic = TRUE;
+ for ( size_t j = 0; j < ysize; ++j )
{
- long i1 = j*xsize*4,
- i2 = j*xsize*4+(xsize-1)*4;
- long nc = 0;
- for (unsigned k1 = 0; k1 < 4; ++k1 )
+ size_t i1 = j*xsize,
+ i2 = j*xsize+(xsize-1);
+ for (size_t k1 = 0; k1 < numVertices; ++k1 )
{
- double val1 = xbounds[i1+k1];
- for (unsigned k2 = 0; k2 < 4; ++k2 )
+ double val1 = xbounds[i1][k1];
+ for (size_t k2 = 0; k2 < numVertices; ++k2 )
{
- double val2 = xbounds[i2+k2];
+ double val2 = xbounds[i2][k2];
if ( val1 < 1 && val2 > 300 ) val1 += 360;
if ( val2 < 1 && val1 > 300 ) val2 += 360;
@@ -26314,19 +26224,16 @@ void grid_check_cyclic(grid_t *gridptr)
if ( fabs(val2-val1) > 180 ) val1 += 360;
if ( fabs(val1-val2) < 0.001 )
- {
- nc++;
- break;
- }
+ goto foundCloseVertices;
}
}
-
- if ( nc < 1 )
- {
- gridptr->isCyclic = FALSE;
- break;
- }
+ /* all vertices more than 0.001 degrees apart */
+ isCyclic = FALSE;
+ break;
+ foundCloseVertices:
+ ;
}
+ gridptr->isCyclic = isCyclic;
}
}
}
@@ -26350,67 +26257,60 @@ int gridIsRotated(int gridID)
}
static
-int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yvals0)
+int compareXYvals(grid_t *gridRef, grid_t *gridTest)
{
- long i;
int differ = 0;
- if ( !differ && xsize == gridInqXvals(gridID, NULL) )
+ int xsizeTest = gridTest->xsize, ysizeTest = gridTest->ysize;
+ if ( !differ && xsizeTest > 0 && xsizeTest == gridRef->vtable->inqXVals(gridRef, NULL) )
{
- double *xvals = (double *) Malloc((size_t)xsize * sizeof (double));
+ const double *restrict xvalsRef = gridRef->vtable->inqXValsPtr(gridRef),
+ *restrict xvalsTest = gridTest->vtable->inqXValsPtr(gridTest);
- gridInqXvals(gridID, xvals);
-
- for ( i = 0; i < xsize; ++i )
- if ( fabs(xvals0[i] - xvals[i]) > 1.e-10 )
+ for ( size_t i = 0; i < (size_t)xsizeTest; ++i )
+ if ( fabs(xvalsTest[i] - xvalsRef[i]) > 1.e-10 )
{
differ = 1;
break;
}
-
- Free(xvals);
}
- if ( !differ && ysize == gridInqYvals(gridID, NULL) )
+ if ( !differ && ysizeTest > 0 && ysizeTest == gridRef->vtable->inqYVals(gridRef, NULL) )
{
- double *yvals = (double *) Malloc((size_t)ysize * sizeof (double));
-
- gridInqYvals(gridID, yvals);
-
- for ( i = 0; i < ysize; ++i )
- if ( fabs(yvals0[i] - yvals[i]) > 1.e-10 )
+ const double *restrict yvalsRef = gridRef->vtable->inqYValsPtr(gridRef),
+ *restrict yvalsTest = gridTest->vtable->inqYValsPtr(gridTest);
+ for ( size_t i = 0; i < (size_t)ysizeTest; ++i )
+ if ( fabs(yvalsTest[i] - yvalsRef[i]) > 1.e-10 )
{
differ = 1;
break;
}
-
- Free(yvals);
}
return (differ);
}
static
-int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
+int compareXYvals2(grid_t *gridRef, grid_t *gridTest)
{
- int differ = 0;
+ int gridsize = gridTest->size;
+ int differ
+ = ((gridTest->xvals == NULL) ^ (gridRef->xvals == NULL))
+ || ((gridTest->yvals == NULL) ^ (gridRef->yvals == NULL));
- if ( !differ && ((xvals == NULL && gridInqXvalsPtr(gridID) != NULL) || (xvals != NULL && gridInqXvalsPtr(gridID) == NULL)) ) differ = 1;
- if ( !differ && ((yvals == NULL && gridInqYvalsPtr(gridID) != NULL) || (yvals != NULL && gridInqYvalsPtr(gridID) == NULL)) ) differ = 1;
+ typedef double (*inqVal)(grid_t *grid, int index);
+ inqVal inqXValRef = gridRef->vtable->inqXVal,
+ inqYValRef = gridRef->vtable->inqXVal,
+ inqXValTest = gridTest->vtable->inqXVal,
+ inqYValTest = gridTest->vtable->inqYVal;
- if ( !differ && xvals && gridInqXvalsPtr(gridID) )
- {
- if ( fabs(xvals[0] - gridInqXval(gridID, 0)) > 1.e-9 ||
- fabs(xvals[gridsize-1] - gridInqXval(gridID, gridsize-1)) > 1.e-9 )
- differ = 1;
- }
+ if ( !differ && gridTest->xvals )
+ differ = fabs(inqXValTest(gridTest, 0) - inqXValRef(gridRef, 0)) > 1.e-9
+ || fabs(inqXValTest(gridTest, gridsize-1) - inqXValRef(gridRef, gridsize-1)) > 1.e-9;
- if ( !differ && yvals && gridInqYvalsPtr(gridID) )
- {
- if ( fabs(yvals[0] - gridInqYval(gridID, 0)) > 1.e-9 ||
- fabs(yvals[gridsize-1] - gridInqYval(gridID, gridsize-1)) > 1.e-9 )
- differ = 1;
- }
+ if ( !differ && gridTest->yvals )
+ differ = fabs(inqYValTest(gridTest, 0) - inqYValRef(gridRef, 0)) > 1.e-9
+ || fabs(inqYValTest(gridTest, gridsize-1) - inqYValRef(gridRef, gridsize-1)) > 1.e-9;
return differ;
}
@@ -26419,10 +26319,11 @@ int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
int gridCompare(int gridID, const grid_t *grid)
{
int differ = 1;
+ grid_t *gridRef = gridID2Ptr(gridID);
- if ( grid->type == gridInqType(gridID) || grid->type == GRID_GENERIC )
+ if ( grid->type == gridRef->type || grid->type == GRID_GENERIC )
{
- if ( grid->size == gridInqSize(gridID) )
+ if ( grid->size == gridRef->size )
{
differ = 0;
if ( grid->type == GRID_LONLAT )
@@ -26442,7 +26343,7 @@ int gridCompare(int gridID, const grid_t *grid)
printf("grid.xinc %f\n", gridInqXinc(gridID));
printf("grid.yinc %f\n", gridInqYinc(gridID));
*/
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == grid->ysize )
{
if ( grid->xdef == 2 && grid->ydef == 2 )
{
@@ -26456,38 +26357,33 @@ int gridCompare(int gridID, const grid_t *grid)
differ = 1;
}
if ( !differ && fabs(grid->xinc) > 0 &&
- fabs(fabs(grid->xinc) - fabs(gridInqXinc(gridID))) > fabs(grid->xinc/1000))
+ fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000))
{
differ = 1;
}
if ( !differ && fabs(grid->yinc) > 0 &&
- fabs(fabs(grid->yinc) - fabs(gridInqYinc(gridID))) > fabs(grid->yinc/1000))
+ fabs(fabs(grid->yinc) - fabs(gridRef->yinc)) > fabs(grid->yinc/1000))
{
differ = 1;
}
}
}
- else
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ else if ( grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else
differ = 1;
}
else if ( grid->type == GRID_GENERIC )
{
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
{
- if ( grid->xdef == 1 && grid->ydef == 1 )
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ if ( grid->xdef == 1 && grid->ydef == 1
+ && grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else if ( (grid->ysize == 0 || grid->ysize == 1) &&
- grid->xsize == gridInqXsize(gridID)*gridInqYsize(gridID) )
+ grid->xsize == gridRef->xsize*gridRef->ysize )
{
}
else
@@ -26495,7 +26391,7 @@ int gridCompare(int gridID, const grid_t *grid)
}
else if ( grid->type == GRID_GAUSSIAN )
{
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
{
if ( grid->xdef == 2 && grid->ydef == 2 )
{
@@ -26503,16 +26399,13 @@ int gridCompare(int gridID, const grid_t *grid)
! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0)) )
if ( fabs(grid->xfirst - gridInqXval(gridID, 0)) > 0.0015 ||
fabs(grid->yfirst - gridInqYval(gridID, 0)) > 0.0015 ||
- (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridInqXinc(gridID))) > fabs(grid->xinc/1000)) )
+ (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) )
{
differ = 1;
}
}
- else
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ else if ( grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else
differ = 1;
@@ -26534,31 +26427,36 @@ int gridCompare(int gridID, const grid_t *grid)
printf("grid.nv %d\n", grid->nvertex);
printf("grid nv %d\n", gridInqNvertex(gridID));
*/
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
- differ = compareXYvals2(gridID, grid->size, grid->xvals, grid->yvals);
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+ differ = gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid);
}
else if ( grid->type == GRID_UNSTRUCTURED )
{
- unsigned char uuidOfHGrid[CDI_UUID_SIZE];
- gridInqUUID(gridID, uuidOfHGrid);
-
- if ( !differ && uuidOfHGrid[0] && grid->uuid[0] && memcmp(uuidOfHGrid, grid->uuid, CDI_UUID_SIZE) != 0 ) differ = 1;
+ /* FIXME: not octet 0 but octet 7 is guaranteed non-zero
+ * for any non-NULL UUID */
+ differ = differ || ( gridRef->uuid[0] && grid->uuid[0] && memcmp(gridRef->uuid, grid->uuid, CDI_UUID_SIZE) != 0 );
if ( !differ &&
- ((grid->xvals == NULL && gridInqXvalsPtr(gridID) != NULL) || (grid->xvals != NULL && gridInqXvalsPtr(gridID) == NULL)) &&
- ((grid->yvals == NULL && gridInqYvalsPtr(gridID) != NULL) || (grid->yvals != NULL && gridInqYvalsPtr(gridID) == NULL)) )
+ ((grid->xvals == NULL) ^ (gridRef->xvals == NULL)) &&
+ ((grid->yvals == NULL) ^ (gridRef->yvals == NULL)) )
{
- if ( !differ && grid->nvertex && gridInqNvertex(gridID) && grid->nvertex != gridInqNvertex(gridID) ) differ = 1;
- if ( !differ && grid->number && gridInqNumber(gridID) && grid->number != gridInqNumber(gridID) ) differ = 1;
- if ( !differ && grid->number && gridInqNumber(gridID) && grid->position != gridInqPosition(gridID) ) differ = 1;
+ int nvertexA, nvertexB, numberA, numberB;
+ differ = ( (nvertexA = grid->nvertex)
+ && (nvertexB = gridRef->nvertex)
+ && (nvertexA != nvertexB) )
+ || (numberA = grid->number, numberB = gridRef->number,
+ ( (numberA)
+ && numberB
+ && (numberA != numberB) )
+ || ( (numberA && numberB)
+ && (grid->position) != (gridRef->position) ) );
}
- else
+ else if ( !differ )
{
- if ( !differ && grid->nvertex != gridInqNvertex(gridID) ) differ = 1;
- if ( !differ && grid->number != gridInqNumber(gridID) ) differ = 1;
- if ( !differ && grid->number > 0 && grid->position != gridInqPosition(gridID) ) differ = 1;
- if ( !differ )
- differ = compareXYvals2(gridID, grid->size, grid->xvals, grid->yvals);
+ differ = grid->nvertex != gridRef->nvertex
+ || grid->number != gridRef->number
+ || (grid->number > 0 && grid->position != gridRef->position)
+ || gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid);
}
}
}
@@ -26602,7 +26500,6 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
if ( g1->size != g2->size ) return differ;
if ( g1->xsize != g2->xsize ) return differ;
if ( g1->ysize != g2->ysize ) return differ;
- if ( g1->locked != g2->locked ) return differ;
if ( g1->lcomplex != g2->lcomplex ) return differ;
if ( g1->rowlon )
@@ -26638,23 +26535,27 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
if ( IS_NOT_EQUAL(g1->ypole , g2->ypole) ) return differ;
if ( IS_NOT_EQUAL(g1->angle , g2->angle) ) return differ;
- if ( g1->xvals )
+ const double *restrict g1_xvals = g1->vtable->inqXValsPtr(g1),
+ *restrict g2_xvals = g2->vtable->inqXValsPtr(g2);
+ if ( g1_xvals )
{
if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
- size = g1->size;
+ size = g1->size;
else
- size = g1->xsize;
+ size = g1->xsize;
xassert ( size );
- if ( !g2->xvals ) return differ;
+ if ( !g2_xvals ) return differ;
for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->xvals[i], g2->xvals[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_xvals[i], g2_xvals[i]) ) return differ;
}
- else if ( g2->xvals )
+ else if ( g2_xvals )
return differ;
- if ( g1->yvals )
+ const double *restrict g1_yvals = g1->vtable->inqXValsPtr(g1),
+ *restrict g2_yvals = g2->vtable->inqXValsPtr(g2);
+ if ( g1_yvals )
{
if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
size = g1->size;
@@ -26662,66 +26563,74 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
size = g1->ysize;
xassert ( size );
- if ( !g2->yvals ) return differ;
+ if ( !g2_yvals ) return differ;
for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->yvals[i], g2->yvals[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_yvals[i], g2_yvals[i]) ) return differ;
}
- else if ( g2->yvals )
+ else if ( g2_yvals )
return differ;
- if ( g1->area )
+ const double *restrict g1_area = g1->vtable->inqAreaPtr(g1),
+ *restrict g2_area = g2->vtable->inqAreaPtr(g2);
+ if ( g1_area )
{
xassert ( g1->size );
- if ( !g2->area ) return differ;
+ if ( !g2_area ) return differ;
for ( i = 0; i < g1->size; i++ )
- if ( IS_NOT_EQUAL(g1->area[i], g2->area[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_area[i], g2_area[i]) ) return differ;
}
- else if ( g2->area )
+ else if ( g2_area )
return differ;
- if ( g1->xbounds )
- {
- xassert ( g1->nvertex );
- if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
- size = g1->nvertex * g1->size;
- else
- size = g1->nvertex * g1->xsize;
- xassert ( size );
+ {
+ const double *restrict g1_xbounds, *restrict g2_xbounds;
+ if ( (g1_xbounds = g1->vtable->inqXBoundsPtr(g1)) )
+ {
+ xassert ( g1->nvertex );
+ if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
+ size = g1->nvertex * g1->size;
+ else
+ size = g1->nvertex * g1->xsize;
+ xassert ( size );
- if ( !g2->xbounds ) return differ;
+ if ( !(g2_xbounds = g2->vtable->inqXBoundsPtr(g2)) ) return differ;
- for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->xbounds[i], g2->xbounds[i]) ) return differ;
- }
- else if ( g2->xbounds )
- return differ;
+ for ( i = 0; i < size; i++ )
+ if ( IS_NOT_EQUAL(g1_xbounds[i], g2_xbounds[i]) ) return differ;
+ }
+ else if ( g2->vtable->inqXBoundsPtr(g2) )
+ return differ;
+ }
- if ( g1->ybounds )
- {
- xassert ( g1->nvertex );
- if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
- size = g1->nvertex * g1->size;
- else
- size = g1->nvertex * g1->ysize;
- xassert ( size );
+ {
+ const double *restrict g1_ybounds, *restrict g2_ybounds;
+ if ( (g1_ybounds = g1->vtable->inqYBoundsPtr(g1)) )
+ {
+ xassert ( g1->nvertex );
+ if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
+ size = g1->nvertex * g1->size;
+ else
+ size = g1->nvertex * g1->ysize;
+ xassert ( size );
- if ( !g2->ybounds ) return differ;
+ if ( ! (g2_ybounds = g2->vtable->inqYBoundsPtr(g2)) ) return differ;
- for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ;
- }
- else if ( g2->ybounds )
- return differ;
+ for ( i = 0; i < size; i++ )
+ if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ;
+ }
+ else if ( g2->vtable->inqYBoundsPtr(g2) )
+ return differ;
+ }
if (strcmp(g1->xname, g2->xname)) return differ;
if (strcmp(g1->yname, g2->yname)) return differ;
if (strcmp(g1->xlongname, g2->xlongname)) return differ;
if (strcmp(g1->ylongname, g2->ylongname)) return differ;
- if (strcmp(g1->xstdname, g2->xstdname)) return differ;
- if (strcmp(g1->ystdname, g2->ystdname)) return differ;
+ if (g1->xstdname != g2->xstdname) return differ;
+ if (g1->ystdname != g2->ystdname) return differ;
if (strcmp(g1->xunits, g2->xunits)) return differ;
if (strcmp(g1->yunits, g2->yunits)) return differ;
@@ -26757,16 +26666,13 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
return equal;
}
-
-int gridGenerate(const grid_t *grid)
+static void gridComplete(grid_t *grid)
{
- int gridID = gridCreate(grid->type, grid->size);
-
- grid_t *gridptr = gridID2Ptr(gridID);
-
+ int gridID = grid->self;
gridDefPrec(gridID, grid->prec);
- switch (grid->type)
+ int gridtype = grid->type;
+ switch (gridtype)
{
case GRID_LONLAT:
case GRID_GAUSSIAN:
@@ -26782,42 +26688,32 @@ int gridGenerate(const grid_t *grid)
if ( grid->xsize > 0 ) gridDefXsize(gridID, grid->xsize);
if ( grid->ysize > 0 ) gridDefYsize(gridID, grid->ysize);
- if ( grid->type == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np);
+ if ( gridtype == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np);
if ( grid->nvertex > 0 )
gridDefNvertex(gridID, grid->nvertex);
- if ( grid->xdef == 1 )
- {
- gridDefXvals(gridID, grid->xvals);
- if ( grid->xbounds )
- gridDefXbounds(gridID, grid->xbounds);
- }
- else if ( grid->xdef == 2 )
+ if ( grid->xdef == 2 )
{
+ assert(gridtype != GRID_UNSTRUCTURED
+ && gridtype != GRID_CURVILINEAR);
double *xvals
= (double *) Malloc((size_t)grid->xsize * sizeof (double));
gridGenXvals(grid->xsize, grid->xfirst, grid->xlast, grid->xinc, xvals);
- gridDefXvals(gridID, xvals);
- Free(xvals);
+ grid->xvals = xvals;
/*
gridDefXinc(gridID, grid->xinc);
*/
}
- if ( grid->ydef == 1 )
- {
- gridDefYvals(gridID, grid->yvals);
- if ( grid->ybounds && grid->nvertex )
- gridDefYbounds(gridID, grid->ybounds);
- }
- else if ( grid->ydef == 2 )
+ if ( grid->ydef == 2 )
{
+ assert(gridtype != GRID_UNSTRUCTURED
+ && gridtype != GRID_CURVILINEAR);
double *yvals
= (double *) Malloc((size_t)grid->ysize * sizeof (double));
- gridGenYvals(grid->type, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
- gridDefYvals(gridID, yvals);
- Free(yvals);
+ gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
+ grid->yvals = yvals;
/*
gridDefYinc(gridID, grid->yinc);
*/
@@ -26829,8 +26725,8 @@ int gridGenerate(const grid_t *grid)
gridDefYname(gridID, "rlat");
gridDefXlongname(gridID, "longitude in rotated pole grid");
gridDefYlongname(gridID, "latitude in rotated pole grid");
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
+ grid->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ grid->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
gridDefXunits(gridID, "degrees");
gridDefYunits(gridID, "degrees");
@@ -26839,39 +26735,30 @@ int gridGenerate(const grid_t *grid)
gridDefAngle(gridID, grid->angle);
}
- if ( grid->area )
- {
- gridDefArea(gridID, grid->area);
- }
-
- if ( grid->type == GRID_LAEA )
- gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0);
-
- if ( grid->type == GRID_LCC2 )
- gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2);
-
- if ( grid->type == GRID_LCC )
- gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY,
- grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc,
- grid->lcc_projflag, grid->lcc_scanflag);
-
- if ( grid->type == GRID_UNSTRUCTURED )
+ switch (gridtype)
{
- int number = grid->number;
- int position = grid->position;
- if ( position < 0 ) position = 0;
- if ( number > 0 )
- {
- gridDefNumber(gridID, number);
- gridDefPosition(gridID, position);
- }
- gridDefUUID(gridID, grid->uuid);
- if ( grid->reference ) gridDefReference(gridID, grid->reference);
- }
-
- if ( grid->type == GRID_PROJECTION )
- {
- gridptr->name = strdup(grid->name);
+ case GRID_LAEA:
+ gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0);
+ break;
+ case GRID_LCC2:
+ gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2);
+ break;
+ case GRID_LCC:
+ gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY,
+ grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc,
+ grid->lcc_projflag, grid->lcc_scanflag);
+ break;
+ case GRID_UNSTRUCTURED:
+ {
+ int number = grid->number;
+ int position = grid->position >= 0 ? grid->position : 0;
+ if ( number > 0 )
+ {
+ gridDefNumber(gridID, number);
+ gridDefPosition(gridID, position);
+ }
+ }
+ break;
}
break;
@@ -26880,29 +26767,19 @@ int gridGenerate(const grid_t *grid)
{
gridDefNP(gridID, grid->np);
gridDefYsize(gridID, grid->ysize);
- gridDefRowlon(gridID, grid->ysize, grid->rowlon);
if ( grid->xdef == 2 )
{
- double xvals[2];
- xvals[0] = grid->xfirst;
- xvals[1] = grid->xlast;
+ double xvals[2] = { grid->xfirst, grid->xlast };
gridDefXvals(gridID, xvals);
}
- if ( grid->ydef == 1 )
- {
- gridDefYvals(gridID, grid->yvals);
- if ( grid->ybounds && grid->nvertex )
- gridDefYbounds(gridID, grid->ybounds);
- }
- else if ( grid->ydef == 2 )
+ if ( grid->ydef == 2 )
{
double *yvals
= (double *) Malloc((size_t)grid->ysize * sizeof (double));
- gridGenYvals(grid->type, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
- gridDefYvals(gridID, yvals);
- Free(yvals);
+ gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
+ grid->yvals = yvals;
/*
gridDefYinc(gridID, grid->yinc);
*/
@@ -26949,127 +26826,209 @@ int gridGenerate(const grid_t *grid)
}
default:
{
- Error("Gridtype %s unsupported!", gridNamePtr(grid->type));
+ Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
break;
}
}
- if ( grid->xname[0] ) gridDefXname(gridID, grid->xname);
- if ( grid->xlongname[0] ) gridDefXlongname(gridID, grid->xlongname);
- if ( grid->xunits[0] ) gridDefXunits(gridID, grid->xunits);
- if ( grid->yname[0] ) gridDefYname(gridID, grid->yname);
- if ( grid->ylongname[0] ) gridDefYlongname(gridID, grid->ylongname);
- if ( grid->yunits[0] ) gridDefYunits(gridID, grid->yunits);
+ grid->xname[CDI_MAX_NAME - 1] = 0;
+ grid->xlongname[CDI_MAX_NAME - 1] = 0;
+ grid->xunits[CDI_MAX_NAME - 1] = 0;
+ grid->yname[CDI_MAX_NAME - 1] = 0;
+ grid->ylongname[CDI_MAX_NAME - 1] = 0;
+ grid->yunits[CDI_MAX_NAME - 1] = 0;
- return (gridID);
}
-/*
- at Function gridDuplicate
- at Title Duplicate a horizontal Grid
-
- at Prototype int gridDuplicate(int gridID)
- at Parameter
- @Item gridID Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
-
- at Description
-The function @func{gridDuplicate} duplicates a horizontal Grid.
-
- at Result
- at func{gridDuplicate} returns an identifier to the duplicated Grid.
+#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
+ gridP->xlongname, gridP->ylongname, \
+ gridP->xunits, gridP->yunits }
- at EndFunction
-*/
-int gridDuplicate(int gridID)
+int gridGenerate(const grid_t *grid)
{
- grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
-
- int gridtype = gridInqType(gridID);
- int gridsize = gridInqSize(gridID);
-
- int gridIDnew = gridCreate(gridtype, gridsize);
- grid_t *gridptrnew = (grid_t *)reshGetVal(gridIDnew, &gridOps);
-
- grid_copy(gridptrnew, gridptr);
-
- strcpy(gridptrnew->xname, gridptr->xname);
- strcpy(gridptrnew->yname, gridptr->yname);
- strcpy(gridptrnew->xlongname, gridptr->xlongname);
- strcpy(gridptrnew->ylongname, gridptr->ylongname);
- strcpy(gridptrnew->xunits, gridptr->xunits);
- strcpy(gridptrnew->yunits, gridptr->yunits);
- strcpy(gridptrnew->xstdname, gridptr->xstdname);
- strcpy(gridptrnew->ystdname, gridptr->ystdname);
-
- if (gridptr->reference)
- gridptrnew->reference = strdupx(gridptr->reference);
+ int gridtype = grid->type;
+ int gridID = gridCreate(gridtype, grid->size);
+ grid_t *restrict gridptr = gridID2Ptr(gridID);
+ gridptr->prec = grid->prec;
+ gridptr->xsize = grid->xsize;
+ gridptr->ysize = grid->ysize;
+ gridptr->np = grid->np;
+ gridptr->nvertex = grid->nvertex;
+ gridptr->xdef = grid->xdef;
+ int valdef_group1 = 0;
+ static const int valdef_group1_tab[] = {
+ GRID_LONLAT, GRID_GAUSSIAN, GRID_UNSTRUCTURED, GRID_CURVILINEAR,
+ GRID_GENERIC, GRID_LCC, GRID_LCC2, GRID_SINUSOIDAL, GRID_LAEA,
+ GRID_PROJECTION
+ };
+ for ( size_t i = 0; i < sizeof (valdef_group1_tab) / sizeof (valdef_group1_tab[0]); ++i)
+ valdef_group1 |= (gridtype == valdef_group1_tab[i]);
+ if ( valdef_group1 && grid->xdef == 1 )
+ {
+ gridDefXvals(gridID, grid->xvals);
+ if ( grid->xbounds )
+ gridDefXbounds(gridID, grid->xbounds);
+ }
+ gridptr->xfirst = grid->xfirst;
+ gridptr->xlast = grid->xlast;
+ gridptr->xinc = grid->xinc;
+ gridptr->ydef = grid->ydef;
+ if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->ydef == 1)
+ {
+ gridDefYvals(gridID, grid->yvals);
+ if ( grid->ybounds )
+ gridDefYbounds(gridID, grid->ybounds);
+ }
+ gridptr->yfirst = grid->yfirst;
+ gridptr->ylast = grid->ylast;
+ gridptr->yinc = grid->yinc;
+ gridptr->isRotated = grid->isRotated;
+ gridptr->xpole = grid->xpole;
+ gridptr->ypole = grid->ypole;
+ gridptr->angle = grid->angle;
+ if ( valdef_group1 && grid->area)
+ gridDefArea(gridID, grid->area);
+ gridptr->laea_a = grid->laea_a;
+ gridptr->laea_lon_0 = grid->laea_lon_0;
+ gridptr->laea_lat_0 = grid->laea_lat_0;
+ gridptr->lcc2_a = grid->lcc2_a;
+ gridptr->lcc2_lon_0 = grid->lcc2_lon_0;
+ gridptr->lcc2_lat_0 = grid->lcc2_lat_0;
+ gridptr->lcc2_lat_1 = grid->lcc2_lat_1;
+ gridptr->lcc2_lat_2 = grid->lcc2_lat_2;
+ gridptr->lcc_originLon = grid->lcc_originLon;
+ gridptr->lcc_originLat = grid->lcc_originLat;
+ gridptr->lcc_lonParY = grid->lcc_lonParY;
+ gridptr->lcc_lat1 = grid->lcc_lat1;
+ gridptr->lcc_lat2 = grid->lcc_lat2;
+ gridptr->lcc_xinc = grid->lcc_xinc;
+ gridptr->lcc_yinc = grid->lcc_yinc;
+ gridptr->lcc_projflag = grid->lcc_projflag;
+ gridptr->lcc_scanflag = grid->lcc_scanflag;
+ gridptr->number = grid->number;
+ gridptr->position = grid->position;
+ memcpy(gridptr->uuid, grid->uuid, CDI_UUID_SIZE);
+ if ( gridtype == GRID_UNSTRUCTURED && grid->reference )
+ gridDefReference(gridID, grid->reference);
+ if ( gridtype == GRID_PROJECTION )
+ gridptr->name = strdup(grid->name);
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ gridDefRowlon(gridID, grid->ysize, grid->rowlon);
+ gridptr->trunc = grid->trunc;
+ gridptr->lcomplex = grid->lcomplex;
+ gridptr->nd = grid->nd;
+ gridptr->ni = grid->ni;
+ gridptr->ni2 = grid->ni2;
+ gridptr->ni3 = grid->ni3;
+ const char *grid_str_tab[] = GRID_STR_SERIALIZE(grid);
+ char *gridptr_str_tab[] = GRID_STR_SERIALIZE(gridptr);
+ for (size_t i = 0; i < sizeof (grid_str_tab) / sizeof (grid_str_tab[0]); ++i)
+ if ( grid_str_tab[i][0] )
+ memcpy(gridptr_str_tab[i], grid_str_tab[i], CDI_MAX_NAME);
+ gridComplete(gridptr);
+ return (gridID);
+}
- size_t nrowlon = (size_t)gridptr->nrowlon;
+static void
+grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ size_t nrowlon = (size_t)gridptrOrig->nrowlon;
+ size_t gridsize = (size_t)gridptrOrig->size;
+ int gridtype = gridptrOrig->type;
int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
if ( nrowlon )
{
- gridptrnew->rowlon = (int *) Malloc(nrowlon * sizeof (int));
- memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon * sizeof(int));
+ gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+ memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
}
- if ( gridptr->xvals != NULL )
+ if ( gridptrOrig->xvals != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->xsize);
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize;
- gridptrnew->xvals = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->xvals, gridptr->xvals, size * sizeof (double));
+ gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
}
- if ( gridptr->yvals != NULL )
+ if ( gridptrOrig->yvals != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->ysize);
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize;
- gridptrnew->yvals = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->yvals, gridptr->yvals, size * sizeof (double));
+ gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
}
- if ( gridptr->xbounds != NULL )
+ if ( gridptrOrig->xbounds != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->xsize)
- * (size_t)gridptr->nvertex;
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
+ * (size_t)gridptrOrig->nvertex;
- gridptrnew->xbounds = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->xbounds, gridptr->xbounds, size * sizeof (double));
+ gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
}
- if ( gridptr->ybounds != NULL )
+ if ( gridptrOrig->ybounds != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->ysize)
- * (size_t)gridptr->nvertex;
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
+ * (size_t)gridptrOrig->nvertex;
- gridptrnew->ybounds = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->ybounds, gridptr->ybounds, size * sizeof (double));
+ gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
}
- if ( gridptr->area != NULL )
- {
- size_t size = (size_t)gridsize;
+ {
+ const double *gridptrOrig_area
+ = gridptrOrig->vtable->inqAreaPtr(gridptrOrig);
+ if ( gridptrOrig_area != NULL )
+ {
+ size_t size = gridsize;
- gridptrnew->area = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->area, gridptr->area, size * sizeof (double));
- }
+ gridptrDup->area = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->area, gridptrOrig_area, size * sizeof (double));
+ }
+ }
- if ( gridptr->mask != NULL )
+ if ( gridptrOrig->mask != NULL )
{
- size_t size = (size_t)gridsize;
+ size_t size = gridsize;
- gridptrnew->mask = (mask_t *) Malloc(size * sizeof(mask_t));
- memcpy(gridptrnew->mask, gridptr->mask, size * sizeof (mask_t));
+ gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
+ memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
}
- if ( gridptr->mask_gme != NULL )
+ if ( gridptrOrig->mask_gme != NULL )
{
- size_t size = (size_t)gridsize;
+ size_t size = gridsize;
- gridptrnew->mask_gme = (mask_t *) Malloc(size * sizeof (mask_t));
- memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size * sizeof(mask_t));
+ gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
+ memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
}
+}
+
+
+/*
+ at Function gridDuplicate
+ at Title Duplicate a horizontal Grid
+
+ at Prototype int gridDuplicate(int gridID)
+ at Parameter
+ @Item gridID Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
+
+ at Description
+The function @func{gridDuplicate} duplicates a horizontal Grid.
+
+ at Result
+ at func{gridDuplicate} returns an identifier to the duplicated Grid.
+
+ at EndFunction
+*/
+int gridDuplicate(int gridID)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ grid_t *gridptrnew = gridptr->vtable->copy(gridptr);
+ int gridIDnew = reshPut(gridptrnew, &gridOps);
+ gridptrnew->self = gridIDnew;
return (gridIDnew);
}
@@ -27085,71 +27044,72 @@ void gridCompress(int gridID)
{
size_t gridsize = (size_t)gridInqSize(gridID);
size_t nv = (size_t)gridptr->nvertex;
-
- size_t j = 0;
- double *area = gridptr->area,
- *xvals = gridptr->xvals,
- *yvals = gridptr->yvals,
- *xbounds = gridptr->xbounds,
- *ybounds = gridptr->ybounds;
- mask_t *mask_gme = gridptr->mask_gme;
- for (size_t i = 0; i < gridsize; i++ )
- {
- if (mask_gme[i])
- {
- if (xvals) xvals[j] = xvals[i];
- if (yvals) yvals[j] = yvals[i];
- if (area) area[j] = area[i];
- if (xbounds != NULL)
- for (size_t iv = 0; iv < nv; iv++)
- xbounds[j * nv + iv] = xbounds[i * nv + iv];
- if (ybounds != NULL)
- for (size_t iv = 0; iv < nv; iv++)
- ybounds[j * nv + iv] = ybounds[i * nv + iv];
-
- j++;
- }
- }
+ double *restrict area
+ = (double *)gridptr->vtable->inqAreaPtr(gridptr),
+ *restrict xvals = (double *)gridptr->vtable->inqXValsPtr((grid_t *)gridptr),
+ *restrict yvals = (double *)gridptr->vtable->inqYValsPtr((grid_t *)gridptr),
+ *restrict xbounds = (double *)gridptr->vtable->inqXBoundsPtr(gridptr),
+ *restrict ybounds = (double *)gridptr->vtable->inqYBoundsPtr(gridptr);
+ mask_t *restrict mask_gme = gridptr->mask_gme;
+ size_t *restrict selection = (size_t *)Malloc(gridsize * sizeof (selection[0]));
+ size_t nselect;
+ {
+ size_t j = 0;
+ for (size_t i = 0; i < gridsize; i++ )
+ selection[j] = i, j += (mask_gme[i] != 0);
+ nselect = j;
+ }
+ selection = (size_t *)Realloc(selection, nselect * sizeof (selection[0]));
+ if (xvals)
+ for (size_t i = 0; i < nselect; i++ )
+ xvals[i] = xvals[selection[i]];
+ if (yvals)
+ for (size_t i = 0; i < nselect; i++ )
+ yvals[i] = yvals[selection[i]];
+ if (area)
+ for (size_t i = 0; i < nselect; i++ )
+ area[i] = area[selection[i]];
+ if (xbounds)
+ for (size_t i = 0; i < nselect; i++ )
+ for (size_t iv = 0; iv < nv; iv++)
+ xbounds[i * nv + iv] = xbounds[selection[i] * nv + iv];
+ if (ybounds)
+ for (size_t i = 0; i < nselect; i++ )
+ for (size_t iv = 0; iv < nv; iv++)
+ ybounds[i * nv + iv] = ybounds[selection[i] * nv + iv];
+ Free(selection);
/* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */
- gridsize = j;
+ gridsize = nselect;
gridptr->size = (int)gridsize;
gridptr->xsize = (int)gridsize;
gridptr->ysize = (int)gridsize;
- if ( gridptr->xvals )
- gridptr->xvals = (double *) Realloc(gridptr->xvals, gridsize*sizeof(double));
-
- if ( gridptr->yvals )
- gridptr->yvals = (double *) Realloc(gridptr->yvals, gridsize*sizeof(double));
-
- if ( gridptr->area )
- gridptr->area = (double *) Realloc(gridptr->area, gridsize*sizeof(double));
-
- if ( gridptr->xbounds )
- gridptr->xbounds = (double *) Realloc(gridptr->xbounds, nv*gridsize*sizeof(double));
-
- if ( gridptr->ybounds )
- gridptr->ybounds = (double *) Realloc(gridptr->ybounds, nv*gridsize*sizeof(double));
+ double **resizeP[] = { &gridptr->xvals, &gridptr->yvals,
+ &gridptr->area,
+ &gridptr->xbounds, &gridptr->ybounds };
+ size_t newSize[] = { gridsize, gridsize, gridsize, nv*gridsize,
+ nv*gridsize };
+ for ( size_t i = 0; i < sizeof (resizeP) / sizeof (resizeP[0]); ++i)
+ if ( *(resizeP[i]) )
+ *(resizeP[i]) = (double *)Realloc(*(resizeP[i]), newSize[i]*sizeof(double));
Free(gridptr->mask_gme);
gridptr->mask_gme = NULL;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
else
Warning("Unsupported grid type: %s", gridNamePtr(gridtype));
}
-
-void gridDefArea(int gridID, const double *area)
+static void
+gridDefAreaSerial(grid_t *gridptr, const double *area)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
size_t size = (size_t)gridptr->size;
if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
+ Error("size undefined for gridID = %d", gridptr->self);
if ( gridptr->area == NULL )
gridptr->area = (double *) Malloc(size*sizeof(double));
@@ -27157,34 +27117,52 @@ void gridDefArea(int gridID, const double *area)
Warning("values already defined!");
memcpy(gridptr->area, area, size * sizeof(double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
}
-void gridInqArea(int gridID, double *area)
+void gridDefArea(int gridID, const double *area)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defArea(gridptr, area);
+ gridMark4Update(gridID);
+}
+static void
+gridInqAreaSerial(grid_t *gridptr, double *area)
+{
if (gridptr->area)
memcpy(area, gridptr->area, (size_t)gridptr->size * sizeof (double));
}
-int gridHasArea(int gridID)
+void gridInqArea(int gridID, double *area)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->inqArea(gridptr, area);
+}
- int hasArea = (gridptr->area != NULL);
+static int
+gridHasAreaBase(grid_t *gridptr)
+{
+ return gridptr->area != NULL;
+}
- return (hasArea);
+int gridHasArea(int gridID)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->hasArea(gridptr);
}
+static const double *gridInqAreaPtrBase(grid_t *gridptr)
+{
+ return gridptr->area;
+}
+
const double *gridInqAreaPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return (gridptr->area);
+ return gridptr->vtable->inqAreaPtr(gridptr);
}
@@ -27195,7 +27173,7 @@ void gridDefNvertex(int gridID, int nvertex)
if (gridptr->nvertex != nvertex)
{
gridptr->nvertex = nvertex;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -27207,6 +27185,38 @@ int gridInqNvertex(int gridID)
return (gridptr->nvertex);
}
+static void
+gridDefBoundsGeneric(grid_t *gridptr, const double *bounds, int regularSize,
+ double **field)
+{
+ int irregular = gridptr->type == GRID_CURVILINEAR
+ || gridptr->type == GRID_UNSTRUCTURED;
+ size_t nvertex = (size_t)gridptr->nvertex;
+ if ( nvertex == 0 )
+ {
+ Warning("nvertex undefined for gridID = %d. Cannot define bounds!",
+ gridptr->self);
+ return;
+ }
+ size_t size = nvertex * (size_t)(irregular ? gridptr->size : regularSize);
+ if ( size == 0 )
+ Error("size undefined for gridID = %d", gridptr->self);
+
+ if (*field == NULL)
+ *field = (double *)Malloc(size * sizeof (double));
+ else if ( CDI_Debug )
+ Warning("values already defined!");
+
+ memcpy(*field, bounds, size * sizeof (double));
+}
+
+
+static void
+gridDefXBoundsSerial(grid_t *gridptr, const double *xbounds)
+{
+ gridDefBoundsGeneric(gridptr, xbounds, gridptr->xsize, &gridptr->xbounds);
+}
+
/*
@Function gridDefXbounds
@Title Define the bounds of a X-axis
@@ -27224,28 +27234,29 @@ The function @func{gridDefXbounds} defines all bounds of the X-axis.
void gridDefXbounds(int gridID, const double *xbounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defXBounds(gridptr, xbounds);
+ gridMark4Update(gridID);
+}
+static int
+gridInqXBoundsSerial(grid_t *gridptr, double *xbounds)
+{
size_t nvertex = (size_t)gridptr->nvertex;
- if ( nvertex == 0 )
- {
- Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
- return;
- }
int irregular = gridptr->type == GRID_CURVILINEAR
|| gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex
- * (size_t)(irregular ? gridptr->size : gridptr->xsize);
- if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
+ size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
- if (gridptr->xbounds == NULL)
- gridptr->xbounds = (double *) Malloc(size * sizeof (double));
- else if ( CDI_Debug )
- Warning("values already defined!");
+ const double *gridptr_xbounds = gridptr->vtable->inqXBoundsPtr(gridptr);
+ if ( gridptr_xbounds )
+ {
+ if ( size && xbounds )
+ memcpy(xbounds, gridptr_xbounds, size * sizeof (double));
+ }
+ else
+ size = 0;
- memcpy(gridptr->xbounds, xbounds, size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return ((int)size);
}
/*
@@ -27271,27 +27282,26 @@ Otherwise, 0 is returned and @func{xbounds} is empty.
int gridInqXbounds(int gridID, double *xbounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXBounds(gridptr, xbounds);
+}
- size_t nvertex = (size_t)gridptr->nvertex;
-
- int irregular = gridptr->type == GRID_CURVILINEAR
- || gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
-
- if ( size && xbounds && gridptr->xbounds )
- memcpy(xbounds, gridptr->xbounds, size * sizeof (double));
-
- if ( gridptr->xbounds == NULL ) size = 0;
-
- return ((int)size);
+static const double *
+gridInqXBoundsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->xbounds;
}
const double *gridInqXboundsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXBoundsPtr(gridptr);
+}
- return (gridptr->xbounds);
+static void
+gridDefYBoundsSerial(grid_t *gridptr, const double *ybounds)
+{
+ gridDefBoundsGeneric(gridptr, ybounds, gridptr->ysize, &gridptr->ybounds);
}
/*
@@ -27311,30 +27321,32 @@ The function @func{gridDefYbounds} defines all bounds of the Y-axis.
void gridDefYbounds(int gridID, const double *ybounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defYBounds(gridptr, ybounds);
+ gridMark4Update(gridID);
+}
+static int
+gridInqYBoundsSerial(grid_t *gridptr, double *ybounds)
+{
size_t nvertex = (size_t)gridptr->nvertex;
- if ( nvertex == 0 )
- {
- Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
- return;
- }
int irregular = gridptr->type == GRID_CURVILINEAR
|| gridptr->type == GRID_UNSTRUCTURED;
size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
- if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
-
- if ( gridptr->ybounds == NULL )
- gridptr->ybounds = (double *) Malloc(size * sizeof (double));
- else if ( CDI_Debug )
- Warning("values already defined!");
+ const double *gridptr_ybounds = gridptr->vtable->inqYBoundsPtr(gridptr);
+ if ( gridptr_ybounds )
+ {
+ if ( size && ybounds )
+ memcpy(ybounds, gridptr_ybounds, size * sizeof (double));
+ }
+ else
+ size = 0;
- memcpy(gridptr->ybounds, ybounds, size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return ((int)size);
}
+
/*
@Function gridInqYbounds
@Title Get the bounds of a Y-axis
@@ -27358,35 +27370,98 @@ Otherwise, 0 is returned and @func{ybounds} is empty.
int gridInqYbounds(int gridID, double *ybounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYBounds(gridptr, ybounds);
+}
- size_t nvertex = (size_t)gridptr->nvertex;
-
- int irregular = gridptr->type == GRID_CURVILINEAR
- || gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
-
- if ( size && ybounds && gridptr->ybounds )
- memcpy(ybounds, gridptr->ybounds, size * sizeof (double));
-
- if ( gridptr->ybounds == NULL ) size = 0;
-
- return ((int)size);
+static const double *
+gridInqYBoundsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->ybounds;
}
const double *gridInqYboundsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYBoundsPtr(gridptr);
+}
+
+static void
+printDblsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const double vals[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%.9g ", vals[i]);
+ }
+ fputs("\n", fp);
+}
+
+static void
+printIntsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const int vals[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%d ", vals[i]);
+ }
+ fputs("\n", fp);
+}
- return (gridptr->ybounds);
+static void
+printBounds(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, size_t nvertex, const double bounds[])
+{
+ fputs(prefix, fp);
+ if ( n > 0 )
+ {
+ for ( size_t iv = 0; iv < nvertex; iv++ )
+ fprintf(fp, "%.9g ", bounds[iv]);
+ for ( size_t i = 1; i < (size_t)n; i++ )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ for ( size_t iv = 0; iv < nvertex; iv++ )
+ fprintf(fp, "%.9g ", bounds[i*nvertex+iv]);
+ }
+ fputs("\n", fp);
+ }
}
+static void
+printMask(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const mask_t mask[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%d ", (int)mask[i]);
+ }
+ fputs("\n", fp);
+}
static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
{
int xdim, ydim;
- int nbyte;
- int i, iv;
unsigned char uuidOfHGrid[CDI_UUID_SIZE];
int gridID = gridptr->self;
const double *area = gridInqAreaPtr(gridID);
@@ -27402,12 +27477,11 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
int ysize = gridInqYsize(gridID);
int nvertex = gridInqNvertex(gridID);
- int nbyte0 = 0;
- fprintf(fp, "#\n");
- fprintf(fp, "# gridID %d\n", index);
- fprintf(fp, "#\n");
- fprintf(fp, "gridtype = %s\n", gridNamePtr(type));
- fprintf(fp, "gridsize = %d\n", gridsize);
+ fprintf(fp, "#\n"
+ "# gridID %d\n"
+ "#\n"
+ "gridtype = %s\n"
+ "gridsize = %d\n", index, gridNamePtr(type), gridsize);
if ( type != GRID_GME )
{
@@ -27491,20 +27565,21 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
{
double a = 0, lon_0 = 0, lat_0 = 0;
gridInqLaea(gridID, &a, &lon_0, &lat_0);
- fprintf(fp, "a = %g\n", a);
- fprintf(fp, "lon_0 = %g\n", lon_0);
- fprintf(fp, "lat_0 = %g\n", lat_0);
+ fprintf(fp, "a = %g\n"
+ "lon_0 = %g\n"
+ "lat_0 = %g\n", a, lon_0, lat_0);
}
if ( type == GRID_LCC2 )
{
double a = 0, lon_0 = 0, lat_0 = 0, lat_1 = 0, lat_2 = 0;
gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2);
- fprintf(fp, "a = %g\n", a);
- fprintf(fp, "lon_0 = %g\n", lon_0);
- fprintf(fp, "lat_0 = %g\n", lat_0);
- fprintf(fp, "lat_1 = %g\n", lat_1);
- fprintf(fp, "lat_2 = %g\n", lat_2);
+ fprintf(fp, "a = %g\n"
+ "lon_0 = %g\n"
+ "lat_0 = %g\n"
+ "lat_1 = %g\n"
+ "lat_2 = %g\n",
+ a, lon_0, lat_0, lat_1, lat_2);
}
if ( gridptr->isRotated )
@@ -27528,38 +27603,23 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( IS_NOT_EQUAL(xinc, 0) && opt )
{
- fprintf(fp, "xfirst = %g\n", xfirst);
- fprintf(fp, "xinc = %g\n", xinc);
+ fprintf(fp, "xfirst = %g\n"
+ "xinc = %g\n", xfirst, xinc);
}
else
{
- nbyte0 = fprintf(fp, "xvals = ");
- nbyte = nbyte0;
- for ( i = 0; i < xdim; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", xvals[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "xvals = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(xdim > 0 ? xdim : 0), xvals);
}
}
if ( xbounds )
{
- nbyte0 = fprintf(fp, "xbounds = ");
- for ( i = 0; i < xdim; i++ )
- {
- if ( i ) fprintf(fp, "%*s", nbyte0, "");
-
- for ( iv = 0; iv < nvertex; iv++ )
- fprintf(fp, "%.9g ", xbounds[i*nvertex+iv]);
- fprintf(fp, "\n");
- }
+ static const char prefix[] = "xbounds = ";
+ printBounds(fp, prefix, sizeof (prefix),
+ (size_t)(xdim > 0 ? xdim : 0),
+ (size_t)(nvertex > 0 ? nvertex : 0), xbounds);
}
if ( yvals )
@@ -27575,75 +27635,39 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( IS_NOT_EQUAL(yinc, 0) && opt )
{
- fprintf(fp, "yfirst = %g\n", yfirst);
- fprintf(fp, "yinc = %g\n", yinc);
+ fprintf(fp, "yfirst = %g\n"
+ "yinc = %g\n", yfirst, yinc);
}
else
{
- nbyte0 = fprintf(fp, "yvals = ");
- nbyte = nbyte0;
- for ( i = 0; i < ydim; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", yvals[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "yvals = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(ydim > 0 ? ydim : 0), yvals);
}
}
if ( ybounds )
{
- nbyte0 = fprintf(fp, "ybounds = ");
- for ( i = 0; i < ydim; i++ )
- {
- if ( i ) fprintf(fp, "%*s", nbyte0, "");
-
- for ( iv = 0; iv < nvertex; iv++ )
- fprintf(fp, "%.9g ", ybounds[i*nvertex+iv]);
- fprintf(fp, "\n");
- }
+ static const char prefix[] = "ybounds = ";
+ printBounds(fp, prefix, sizeof (prefix),
+ (size_t)(ydim > 0 ? ydim : 0),
+ (size_t)(nvertex > 0 ? nvertex : 0), ybounds);
}
if ( area )
{
- nbyte0 = fprintf(fp, "area = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridsize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", area[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "area = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(gridsize > 0 ? gridsize : 0), area);
}
if ( type == GRID_GAUSSIAN_REDUCED )
{
- int *rowlon;
- nbyte0 = fprintf(fp, "rowlon = ");
- nbyte = nbyte0;
- rowlon = (int *) Malloc((size_t)ysize*sizeof(int));
+ static const char prefix[] = "rowlon = ";
+ int *rowlon = (int *)Malloc((size_t)ysize*sizeof(int));
gridInqRowlon(gridID, rowlon);
- for ( i = 0; i < ysize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", rowlon[i]);
- }
- fprintf(fp, "\n");
+ printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(ysize > 0 ? ysize : 0), rowlon);
Free(rowlon);
}
@@ -27656,27 +27680,26 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
&projflag, &scanflag);
- fprintf(fp, "xsize = %d\n", xsize);
- fprintf(fp, "ysize = %d\n", ysize);
-
- fprintf(fp, "originLon = %g\n", originLon);
- fprintf(fp, "originLat = %g\n", originLat);
- fprintf(fp, "lonParY = %g\n", lonParY);
- fprintf(fp, "lat1 = %g\n", lat1);
- fprintf(fp, "lat2 = %g\n", lat2);
- fprintf(fp, "xinc = %g\n", xincm);
- fprintf(fp, "yinc = %g\n", yincm);
- if ( (projflag & 128) == 0 )
- fprintf(fp, "projection = northpole\n");
- else
- fprintf(fp, "projection = southpole\n");
-
+ fprintf(fp,
+ "xsize = %d\n"
+ "ysize = %d\n"
+ "originLon = %g\n"
+ "originLat = %g\n"
+ "lonParY = %g\n"
+ "lat1 = %g\n"
+ "lat2 = %g\n"
+ "xinc = %g\n"
+ "yinc = %g\n"
+ "projection = %s\n"
+ , xsize, ysize, originLon, originLat, lonParY, lat1, lat2,
+ xincm, yincm,
+ (projflag & 128) == 0 ? "northpole" : "southpole");
break;
}
case GRID_SPECTRAL:
{
- fprintf(fp, "truncation = %d\n", trunc);
- fprintf(fp, "complexpacking = %d\n", gridptr->lcomplex );
+ fprintf(fp, "truncation = %d\n"
+ "complexpacking = %d\n", trunc, gridptr->lcomplex );
break;
}
case GRID_FOURIER:
@@ -27700,26 +27723,16 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
fprintf(fp, "uuid = %s\n", uuidOfHGridStr);
}
if ( gridptr->mask )
{
- nbyte0 = fprintf(fp, "mask = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridsize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", (int) gridptr->mask[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "mask = ";
+ printMask(fp, prefix, sizeof (prefix),
+ (size_t)(gridsize > 0 ? gridsize : 0), gridptr->mask);
}
}
@@ -27735,72 +27748,64 @@ void gridPrint ( int gridID, int index, int opt )
void gridPrintP ( void * voidptr, FILE * fp )
{
grid_t * gridptr = ( grid_t * ) voidptr;
- int nbyte0, nbyte, i;
xassert ( gridptr );
gridPrintKernel ( gridptr , gridptr->self, 0, fp );
- fprintf ( fp, "precision = %d\n", gridptr->prec);
- fprintf ( fp, "nd = %d\n", gridptr->nd );
- fprintf ( fp, "ni = %d\n", gridptr->ni );
- fprintf ( fp, "ni2 = %d\n", gridptr->ni2 );
- fprintf ( fp, "ni3 = %d\n", gridptr->ni3 );
- fprintf ( fp, "number = %d\n", gridptr->number );
- fprintf ( fp, "position = %d\n", gridptr->position );
- fprintf ( fp, "trunc = %d\n", gridptr->trunc );
- fprintf ( fp, "lcomplex = %d\n", gridptr->lcomplex );
- fprintf ( fp, "nrowlon = %d\n", gridptr->nrowlon );
+ fprintf(fp,
+ "precision = %d\n"
+ "nd = %d\n"
+ "ni = %d\n"
+ "ni2 = %d\n"
+ "ni3 = %d\n"
+ "number = %d\n"
+ "position = %d\n"
+ "trunc = %d\n"
+ "lcomplex = %d\n"
+ "nrowlon = %d\n",
+ gridptr->prec, gridptr->nd, gridptr->ni, gridptr->ni2,
+ gridptr->ni3, gridptr->number, gridptr->position, gridptr->trunc,
+ gridptr->lcomplex, gridptr->nrowlon );
if ( gridptr->rowlon )
{
- nbyte0 = fprintf(fp, "rowlon = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridptr->nrowlon; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", gridptr->rowlon[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "rowlon = ";
+ printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(gridptr->nrowlon > 0
+ ? gridptr->nrowlon : 0), gridptr->rowlon);
}
if ( gridptr->mask_gme )
{
- nbyte0 = fprintf(fp, "mask_gme = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridptr->size; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", (int) gridptr->mask_gme[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "mask_gme = ";
+ printMask(fp, prefix, sizeof (prefix),
+ (size_t)(gridptr->size > 0 ? gridptr->size : 0),
+ gridptr->mask_gme);
}
}
+static const double *gridInqXValsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->xvals;
+}
const double *gridInqXvalsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return ( gridptr->xvals );
+ return gridptr->vtable->inqXValsPtr(gridptr);
}
+static const double *gridInqYValsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->yvals;
+}
+
const double *gridInqYvalsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return ( gridptr->yvals );
+ return gridptr->vtable->inqYValsPtr(gridptr);
}
/*
@@ -27846,7 +27851,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
gridptr->lcc_projflag = projflag;
gridptr->lcc_scanflag = scanflag;
gridptr->lcc_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -27915,7 +27920,7 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do
gridptr->lcc2_lat_1 = lat_1;
gridptr->lcc2_lat_2 = lat_2;
gridptr->lcc2_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -27955,7 +27960,7 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
gridptr->laea_lon_0 = lon_0;
gridptr->laea_lat_0 = lat_0;
gridptr->laea_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -27988,8 +27993,8 @@ void gridDefComplexPacking(int gridID, int lcomplex)
if (gridptr->lcomplex != lcomplex)
{
- gridptr->lcomplex = lcomplex;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridptr->lcomplex = (short)(lcomplex != 0);
+ gridMark4Update(gridID);
}
}
@@ -28006,10 +28011,10 @@ void gridDefHasDims(int gridID, int hasdims)
{
grid_t* gridptr = gridID2Ptr(gridID);
- if (gridptr->hasdims != hasdims)
+ if (gridptr->hasdims != (hasdims != 0))
{
- gridptr->hasdims = hasdims;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridptr->hasdims = hasdims != 0;
+ gridMark4Update(gridID);
}
}
@@ -28042,7 +28047,7 @@ void gridDefNumber(int gridID, const int number)
if (gridptr->number != number)
{
gridptr->number = number;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -28064,8 +28069,7 @@ The function @func{gridInqNumber} returns the reference number to an unstructure
int gridInqNumber(int gridID)
{
grid_t* gridptr = gridID2Ptr(gridID);
-
- return (gridptr->number);
+ return gridptr->number;
}
/*
@@ -28089,7 +28093,7 @@ void gridDefPosition(int gridID, int position)
if (gridptr->position != position)
{
gridptr->position = position;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -28142,7 +28146,7 @@ void gridDefReference(int gridID, const char *reference)
}
gridptr->reference = strdupx(reference);
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -28193,7 +28197,7 @@ void gridDefUUID(int gridID, const unsigned char uuid[CDI_UUID_SIZE])
grid_t* gridptr = gridID2Ptr(gridID);
memcpy(gridptr->uuid, uuid, CDI_UUID_SIZE);
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
/*
@@ -28231,7 +28235,7 @@ gridTxCode ()
return GRID;
}
-enum { gridNint = 27,
+enum { gridNint = 28,
gridNdouble = 24,
gridHasMaskFlag = 1 << 0,
gridHasGMEMaskFlag = 1 << 1,
@@ -28250,9 +28254,13 @@ static int gridGetComponentFlags(const grid_t * gridP)
{
int flags = (gridHasMaskFlag & (int)((unsigned)(gridP->mask == NULL) - 1U))
| (gridHasGMEMaskFlag & (int)((unsigned)(gridP->mask_gme == NULL) - 1U))
- | (gridHasXValsFlag & (int)((unsigned)(gridP->xvals == NULL) - 1U))
- | (gridHasYValsFlag & (int)((unsigned)(gridP->yvals == NULL) - 1U))
- | (gridHasAreaFlag & (int)((unsigned)(gridP->area == NULL) - 1U))
+ | (gridHasXValsFlag
+ & (int)((unsigned)(gridP->vtable->inqXValsPtr((grid_t *)gridP) == NULL) - 1U))
+ | (gridHasYValsFlag
+ & (int)((unsigned)(gridP->vtable->inqYValsPtr((grid_t *)gridP) == NULL) - 1U))
+ | (gridHasAreaFlag
+ & (int)((unsigned)(gridP->vtable->inqAreaPtr((grid_t *)gridP) == NULL)
+ - 1U))
| (gridHasXBoundsFlag & (int)((unsigned)(gridP->xbounds == NULL) - 1U))
| (gridHasYBoundsFlag & (int)((unsigned)(gridP->ybounds == NULL) - 1U))
| (gridHasReferenceFlag & (int)((unsigned)(gridP->reference == NULL) - 1U))
@@ -28262,9 +28270,8 @@ static int gridGetComponentFlags(const grid_t * gridP)
}
-#define GRID_STR_SERIALIZE { gridP->xname, gridP->yname, \
+#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
gridP->xlongname, gridP->ylongname, \
- gridP->xstdname, gridP->ystdname, \
gridP->xunits, gridP->yunits }
static int
@@ -28285,7 +28292,7 @@ gridGetPackSize(void * voidP, void *context)
packBuffSize += serializeGetSize(gridNdouble, DATATYPE_FLT64, context);
- if (gridP->xvals)
+ if (gridP->vtable->inqXValsPtr(gridP))
{
if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
count = gridP->size;
@@ -28296,7 +28303,7 @@ gridGetPackSize(void * voidP, void *context)
+ serializeGetSize(1, DATATYPE_UINT32, context);
}
- if (gridP->yvals)
+ if (gridP->vtable->inqYValsPtr(gridP))
{
if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
count = gridP->size;
@@ -28307,7 +28314,7 @@ gridGetPackSize(void * voidP, void *context)
+ serializeGetSize(1, DATATYPE_UINT32, context);
}
- if (gridP->area)
+ if (gridP->vtable->inqAreaPtr(gridP))
{
xassert(gridP->size);
packBuffSize +=
@@ -28342,7 +28349,7 @@ gridGetPackSize(void * voidP, void *context)
}
{
- const char *strTab[] = GRID_STR_SERIALIZE;
+ const char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = (int)(sizeof (strTab) / sizeof (strTab[0]));
packBuffSize
+= serializeStrTabGetPackSize(strTab, numStr, context);
@@ -28424,9 +28431,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
gridP->size = intBuffer[21];
gridP->xsize = intBuffer[22];
gridP->ysize = intBuffer[23];
- gridP->locked = intBuffer[24];
- gridP->lcomplex = intBuffer[25];
- memberMask = intBuffer[26];
+ gridP->lcomplex = (short)intBuffer[24];
+ memberMask = intBuffer[25];
+ gridP->xstdname = xystdname_tab[intBuffer[26]][0];
+ gridP->ystdname = xystdname_tab[intBuffer[27]][1];
}
if (memberMask & gridHasRowLonFlag)
@@ -28539,7 +28547,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
}
{
- char *strTab[] = GRID_STR_SERIALIZE;
+ char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = sizeof (strTab) / sizeof (strTab[0]);
serializeStrTabUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
strTab, numStr, context);
@@ -28626,9 +28634,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
intBuffer[21] = gridP->size;
intBuffer[22] = gridP->xsize;
intBuffer[23] = gridP->ysize;
- intBuffer[24] = gridP->locked;
- intBuffer[25] = gridP->lcomplex;
- intBuffer[26] = memberMask = gridGetComponentFlags(gridP);
+ intBuffer[24] = gridP->lcomplex;
+ intBuffer[25] = memberMask = gridGetComponentFlags(gridP);
+ intBuffer[26] = (int)((const char (*)[2][24])gridP->xstdname
+ - xystdname_tab);
+ intBuffer[27] = (int)((const char (*)[2][24])gridP->ystdname
+ - (const char (*)[2][24])xystdname_tab[0][1]);
serializePack(intBuffer, gridNint, DATATYPE_INT,
packBuffer, packBufferSize, packBufferPos, context);
@@ -28691,9 +28702,10 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
size = gridP->xsize;
xassert(size);
- serializePack(gridP->xvals, size, DATATYPE_FLT64,
+ const double *gridP_xvals = gridP->vtable->inqXValsPtr(gridP);
+ serializePack(gridP_xvals, size, DATATYPE_FLT64,
packBuffer, packBufferSize, packBufferPos, context);
- d = cdiCheckSum(DATATYPE_FLT, size, gridP->xvals);
+ d = cdiCheckSum(DATATYPE_FLT, size, gridP_xvals);
serializePack(&d, 1, DATATYPE_UINT32,
packBuffer, packBufferSize, packBufferPos, context);
}
@@ -28705,9 +28717,10 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
else
size = gridP->ysize;
xassert(size);
- serializePack(gridP->yvals, size, DATATYPE_FLT64,
+ const double *gridP_yvals = gridP->vtable->inqYValsPtr(gridP);
+ serializePack(gridP_yvals, size, DATATYPE_FLT64,
packBuffer, packBufferSize, packBufferPos, context);
- d = cdiCheckSum(DATATYPE_FLT, size, gridP->yvals);
+ d = cdiCheckSum(DATATYPE_FLT, size, gridP_yvals);
serializePack(&d, 1, DATATYPE_UINT32,
packBuffer, packBufferSize, packBufferPos, context);
}
@@ -28756,7 +28769,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
}
{
- const char *strTab[] = GRID_STR_SERIALIZE;
+ const char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = sizeof (strTab) / sizeof (strTab[0]);
serializeStrTabPack(strTab, numStr,
packBuffer, packBufferSize, packBufferPos, context);
@@ -28803,16 +28816,16 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
#undef GRID_STR_SERIALIZE
-struct varDefGridSearchState
+struct gridCompareSearchState
{
int resIDValue;
const grid_t *queryKey;
};
static enum cdiApplyRet
-varDefGridSearch(int id, void *res, void *data)
+gridCompareSearch(int id, void *res, void *data)
{
- struct varDefGridSearchState *state = (struct varDefGridSearchState*)data;
+ struct gridCompareSearchState *state = (struct gridCompareSearchState*)data;
(void)res;
if (gridCompare(id, state->queryKey) == 0)
{
@@ -28823,40 +28836,43 @@ varDefGridSearch(int id, void *res, void *data)
return CDI_APPLY_GO_ON;
}
-int varDefGrid(int vlistID, const grid_t *grid, int mode)
+/* Add grid (which must be Malloc'ed to vlist if not already found */
+struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
{
/*
mode: 0 search in vlist and grid table
1 search in grid table
*/
int gridglobdefined = FALSE;
- int griddefined;
+ int griddefined = FALSE;
int gridID = CDI_UNDEFID;
vlist_t *vlistptr = vlist_to_pointer(vlistID);
- griddefined = FALSE;
unsigned ngrids = (unsigned)vlistptr->ngrids;
if ( mode == 0 )
for (unsigned index = 0; index < ngrids; index++ )
{
- gridID = vlistptr->gridIDs[index];
- if ( gridID == UNDEFID )
- Error("Internal problem: undefined gridID %d!", gridID);
+ if ( (gridID = vlistptr->gridIDs[index]) != UNDEFID )
+ {
+ if ( gridCompare(gridID, grid) == 0 )
+ {
+ griddefined = TRUE;
+ break;
+ }
+ }
+ else
+ Error("Internal problem: undefined gridID in vlist "
+ "%d, position %u!", vlistID, index);
- if ( gridCompare(gridID, grid) == 0 )
- {
- griddefined = TRUE;
- break;
- }
}
if ( ! griddefined )
{
- struct varDefGridSearchState query;
+ struct gridCompareSearchState query;
query.queryKey = grid;// = { .queryKey = grid };
if ((gridglobdefined
- = (cdiResHFilterApply(&gridOps, varDefGridSearch, &query)
+ = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query)
== CDI_APPLY_STOP)))
gridID = query.resIDValue;
@@ -28871,14 +28887,50 @@ int varDefGrid(int vlistID, const grid_t *grid, int mode)
if ( ! griddefined )
{
- if ( ! gridglobdefined ) gridID = gridGenerate(grid);
- ngrids = (unsigned)vlistptr->ngrids;
+ if ( ! gridglobdefined )
+ {
+ grid->self = gridID = reshPut(grid, &gridOps);
+ gridComplete(grid);
+ }
vlistptr->gridIDs[ngrids] = gridID;
vlistptr->ngrids++;
}
- return (gridID);
-}
+ return (struct addIffNewRes){ .Id = gridID,
+ .isNew = !griddefined && !gridglobdefined };
+}
+
+const struct gridVirtTable cdiGridVtable
+ = {
+ .destroy = gridDestroyKernel,
+ .copy = grid_copy_base,
+ .copyScalarFields = grid_copy_base_scalar_fields,
+ .copyArrayFields = grid_copy_base_array_fields,
+ .defXVals = gridDefXValsSerial,
+ .defYVals = gridDefYValsSerial,
+ .defMask = gridDefMaskSerial,
+ .defMaskGME = gridDefMaskGMESerial,
+ .defXBounds = gridDefXBoundsSerial,
+ .defYBounds = gridDefYBoundsSerial,
+ .defArea = gridDefAreaSerial,
+ .inqXVal = gridInqXValSerial,
+ .inqYVal = gridInqYValSerial,
+ .inqXVals = gridInqXValsSerial,
+ .inqYVals = gridInqYValsSerial,
+ .inqXValsPtr = gridInqXValsPtrSerial,
+ .inqYValsPtr = gridInqYValsPtrSerial,
+ .compareXYFull = compareXYvals,
+ .compareXYAO = compareXYvals2,
+ .inqArea = gridInqAreaSerial,
+ .inqAreaPtr = gridInqAreaPtrBase,
+ .hasArea = gridHasAreaBase,
+ .inqMask = gridInqMaskSerial,
+ .inqMaskGME = gridInqMaskGMESerial,
+ .inqXBounds = gridInqXBoundsSerial,
+ .inqYBounds = gridInqYBoundsSerial,
+ .inqXBoundsPtr = gridInqXBoundsPtrSerial,
+ .inqYBoundsPtr = gridInqYBoundsPtrSerial,
+};
/*
* Local Variables:
@@ -29180,15 +29232,9 @@ int iegInqDataDP(void *ieg, double *data)
static int
iegDefData(iegrec_t *iegp, int prec, const void *data)
{
- int dprec;
- void *buffer;
+ int dprec = iegDefaultDprec ? iegDefaultDprec : iegp->dprec;
- if ( iegDefaultDprec ) dprec = iegDefaultDprec;
- else dprec = iegp->dprec;
-
- if ( ! dprec ) dprec = prec;
-
- iegp->dprec = dprec;
+ iegp->dprec = dprec = dprec ? dprec : prec;
size_t datasize = (size_t)IEG_G_NumLon(iegp->igdb) * (size_t)IEG_G_NumLat(iegp->igdb);
size_t blocklen = datasize * (size_t)dprec;
@@ -29197,16 +29243,14 @@ iegDefData(iegrec_t *iegp, int prec, const void *data)
size_t buffersize = iegp->buffersize;
+ void *buffer = iegp->buffer;
if ( buffersize != blocklen )
{
buffersize = blocklen;
- buffer = iegp->buffer;
buffer = Realloc(buffer, buffersize);
iegp->buffer = buffer;
iegp->buffersize = buffersize;
}
- else
- buffer = iegp->buffer;
switch ( dprec )
{
@@ -29782,7 +29826,7 @@ void instituteDefaultEntries ( void )
= { ECMWF = institutDef( 98, 0, "ECMWF", "European Centre for Medium-Range Weather Forecasts"),
MPIMET = institutDef( 98, 232, "MPIMET", "Max-Planck-Institute for Meteorology"),
institutDef( 98, 255, "MPIMET", "Max-Planck-Institute for Meteorology"),
- institutDef( 98, 232, "MPIMET", "Max-Planck Institute for Meteorology"),
+ institutDef( 98, 232, "MPIMET", "Max Planck Institute for Meteorology"),
institutDef( 78, 0, "DWD", "Deutscher Wetterdienst"),
institutDef( 78, 255, "DWD", "Deutscher Wetterdienst"),
MCH = institutDef(215, 255, "MCH", "MeteoSwiss"),
@@ -30149,11 +30193,13 @@ CdiFallbackIterator *cdiFallbackIterator_deserialize(const char *me);
int cdiFallbackIterator_nextField(CdiIterator *me);
-char *cdiFallbackIterator_inqTime(CdiIterator *me, bool getEndTime);
+char *cdiFallbackIterator_inqTime(CdiIterator *me, CdiTimeType timeType);
int cdiFallbackIterator_levelType(CdiIterator *me, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit);
int cdiFallbackIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiFallbackIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
char *cdiFallbackIterator_copyVariableName(CdiIterator *me);
+int cdiFallbackIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute);
+int cdiFallbackIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount);
void cdiFallbackIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
void cdiFallbackIterator_readFieldF(CdiIterator *me, float *buffer, size_t *nmiss);
@@ -30195,10 +30241,12 @@ CdiGribIterator *cdiGribIterator_deserialize(const char *me);
int cdiGribIterator_nextField(CdiIterator *me);
-char *cdiGribIterator_inqTime(CdiIterator *me, bool getEndTime);
+char *cdiGribIterator_inqTime(CdiIterator *me, CdiTimeType timeType);
int cdiGribIterator_levelType(CdiIterator *me, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit);
int cdiGribIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiGribIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
+int cdiGribIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute);
+int cdiGribIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount);
char *cdiGribIterator_copyVariableName(CdiIterator *me);
void cdiGribIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
@@ -30644,7 +30692,7 @@ int cdiIterator_nextField(CdiIterator* me)
}
}
-static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
+static char* cdiIterator_inqTime(CdiIterator* me, CdiTimeType timeType)
{
sanityCheck(me);
switch(me->filetype)
@@ -30652,7 +30700,7 @@ static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
#ifdef HAVE_LIBGRIB_API
case FILETYPE_GRB:
case FILETYPE_GRB2:
- return cdiGribIterator_inqTime(me, getEndTime);
+ return cdiGribIterator_inqTime(me, timeType);
#endif
#ifdef HAVE_LIBNETCDF
@@ -30670,7 +30718,7 @@ static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
#ifdef HAVE_LIBIEG
case FILETYPE_IEG:
#endif
- return cdiFallbackIterator_inqTime(me, getEndTime);
+ return cdiFallbackIterator_inqTime(me, timeType);
default:
Error(kUnexpectedFileTypeMessage);
@@ -30701,7 +30749,7 @@ This is due to the fact that GRIB-API version 1.12.3 still does not implement th
*/
char* cdiIterator_inqStartTime(CdiIterator* me)
{
- return cdiIterator_inqTime(me, false);
+ return cdiIterator_inqTime(me, kCdiTimeType_startTime);
}
/*
@@ -30727,7 +30775,34 @@ This is due to the fact that GRIB-API version 1.12.3 still does not implement th
*/
char* cdiIterator_inqEndTime(CdiIterator* me)
{
- return cdiIterator_inqTime(me, true);
+ return cdiIterator_inqTime(me, kCdiTimeType_endTime);
+}
+
+/*
+ at Function cdiIterator_inqRTime
+ at Title Get the validity time of the current field
+
+ at Prototype char* cdiIterator_inqRTime(CdiIterator* me)
+ at Parameter
+ @item iterator The iterator to operate on.
+
+ at Result A malloc'ed string containing the validity time of the current field in the format "YYYY-MM-DDTHH:MM:SS.mmm".
+
+ at Description
+The returned time is the validity time as it is returned by taxisInqVtime(), only more precise.
+That is, if the field is a time point, its time is returned,
+if it is a statistical field with an integration period, the end time of the integration period is returned.
+
+Converts the time to the ISO-8601 format and returns it in a newly allocated buffer.
+The caller is responsible to Free() the resulting string.
+
+If the file is a GRIB file, the calendar that is used to resolve the relative times is the proleptic calendar
+as it is implemented by the standard C mktime() function.
+This is due to the fact that GRIB-API version 1.12.3 still does not implement the calendar identification fields.
+*/
+char* cdiIterator_inqRTime(CdiIterator* me)
+{
+ return cdiIterator_inqTime(me, kCdiTimeType_referenceTime);
}
/*
@@ -30912,6 +30987,105 @@ int cdiIterator_inqLevelUuid(CdiIterator* me, int* outVgridNumber, int* outLevel
}
/*
+ at Function cdiIterator_inqTile
+ at Title Inquire the tile information for the current field
+
+ at Prototype int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outTileIndex The index of the current tile, -1 if no tile information is available.
+ @item outTileAttribute The attribute of the current tile, -1 if no tile information is available.
+
+ at Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
+
+ at Description
+Inquire the tile index and attribute for the current field.
+*/
+int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
+{
+ sanityCheck(me);
+ switch(me->filetype)
+ {
+ #ifdef HAVE_LIBGRIB_API
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ return cdiGribIterator_inqTile(me, outTileIndex, outTileAttribute);
+ #endif
+
+ #ifdef HAVE_LIBNETCDF
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ #endif
+ #ifdef HAVE_LIBSERVICE
+ case FILETYPE_SRV:
+ #endif
+ #ifdef HAVE_LIBEXTRA
+ case FILETYPE_EXT:
+ #endif
+ #ifdef HAVE_LIBIEG
+ case FILETYPE_IEG:
+ #endif
+ return cdiFallbackIterator_inqTile(me, outTileIndex, outTileAttribute);
+
+ default:
+ Error(kUnexpectedFileTypeMessage);
+ return CDI_ELIBNAVAIL;
+ }
+}
+
+/**
+ at Function cdiIterator_inqTileCount
+ at Title Inquire the tile count and tile attribute counts for the current field
+
+ at Prototype int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outTileCount The number of tiles used for this variable, zero if no tile information is available.
+ @item outTileAttributeCount The number of attributes available for the tile of this field, zero if no tile information is available.
+ Note: This is not the global attribute count, which would be impossible to infer without reading the entire file if it's a GRIB file.
+
+ at Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
+
+ at Description
+Inquire the tile count and tile attribute counts for the current field.
+*/
+int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
+{
+ sanityCheck(me);
+ switch(me->filetype)
+ {
+ #ifdef HAVE_LIBGRIB_API
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ return cdiGribIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
+ #endif
+
+ #ifdef HAVE_LIBNETCDF
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ #endif
+ #ifdef HAVE_LIBSERVICE
+ case FILETYPE_SRV:
+ #endif
+ #ifdef HAVE_LIBEXTRA
+ case FILETYPE_EXT:
+ #endif
+ #ifdef HAVE_LIBIEG
+ case FILETYPE_IEG:
+ #endif
+ return cdiFallbackIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
+
+ default:
+ Error(kUnexpectedFileTypeMessage);
+ return CDI_ELIBNAVAIL;
+ }
+}
+
+/*
@Function cdiIterator_inqParam
@Title Get discipline, category, and number
@@ -30931,6 +31105,31 @@ CdiParam cdiIterator_inqParam(CdiIterator* me)
}
/*
+ at Function cdiIterator_inqParamParts
+ at Title Get discipline, category, and number
+
+ at Prototype void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outDiscipline This is used to return the discipline.
+ @item outCategory This is used to return the category.
+ @item outNumber This is used to return the number.
+
+ at Description
+ Simple metadata inspection function.
+
+ Some FORTRAN compilers produce wrong code for the cdiIterator_inqParam()-wrapper,
+ rendering it unusable from FORTRAN. This function is the workaround.
+*/
+void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber)
+{
+ CdiParam result = cdiIterator_inqParam(me);
+ if(outDiscipline) *outDiscipline = result.discipline;
+ if(outCategory) *outCategory = result.category;
+ if(outNumber) *outNumber = result.number;
+}
+
+/*
@Function cdiIterator_inqDatatype
@Title Get the datatype of the current field
@@ -31203,11 +31402,12 @@ void baseIterDestruct(CdiIterator* me)
struct CdiFallbackIterator {
CdiIterator super;
- int streamId, vlistId;
+ int streamId, vlistId, subtypeId;
char *path; //needed for clone() & serialize()
int variableCount, curVariable;
int curLevelCount, curLevel;
+ int curSubtypeCount, curSubtype;
int curTimestep;
};
@@ -31231,12 +31431,15 @@ static CdiFallbackIterator *cdiFallbackIterator_condestruct(CdiFallbackIterator
if(me->vlistId == CDI_UNDEFID) goto closeStream;
me->variableCount = vlistNvars(me->vlistId);
if(me->variableCount <= 0) goto closeStream;
+ me->subtypeId = CDI_UNDEFID; //Will be set in cdiFallbackIterator_nextField()
+ me->curSubtypeCount = -1; //Will be set in cdiFallbackIterator_nextField()
me->curLevelCount = -1; //Will be set in cdiFallbackIterator_nextField()
//These values are chosen so that the natural increment at the start of cdiFallbackIterator_nextField() will correctly position us at the first slice.
me->curTimestep = 0;
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
- me->curVariable = 0;
+ me->curVariable = -1;
+ me->curSubtype = -1;
me->curLevel = -1;
me->path = strdup(path);
if(!me->path) goto closeStream;
@@ -31262,14 +31465,20 @@ CdiIterator *cdiFallbackIterator_new(const char *path, int filetype)
return &cdiFallbackIterator_condestruct(NULL, path, filetype)->super;
}
-//Fetches the info that is published by the variables in the base class from the current field.
-static void fetchSuperInfo(CdiFallbackIterator *me)
+//Fetches the info that is derived from the current variable. Most of this is published by the data members in the base class.
+static void fetchVariableInfo(CdiFallbackIterator *me)
{
+ //Fetch data that's published via base class data members.
me->super.datatype = vlistInqVarDatatype(me->vlistId, me->curVariable);
me->super.timesteptype = vlistInqVarTsteptype(me->vlistId, me->curVariable);
me->super.gridId = vlistInqVarGrid(me->vlistId, me->curVariable);
int param = vlistInqVarParam(me->vlistId, me->curVariable);
cdiDecodeParam(param, &me->super.param.number, &me->super.param.category, &me->super.param.discipline);
+
+ //Fetch the current level and subtype counts.
+ me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
+ me->subtypeId = vlistInqVarSubtype(me->vlistId, me->curVariable);
+ me->curSubtypeCount = (me->subtypeId == CDI_UNDEFID) ? 1 : subtypeInqSize(me->subtypeId);
}
CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
@@ -31285,10 +31494,12 @@ CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
clone->curVariable = me->curVariable;
clone->curLevelCount = me->curLevelCount;
clone->curLevel = me->curLevel;
+ clone->curSubtypeCount = me->curSubtypeCount;
+ clone->curSubtype = me->curSubtype;
clone->curTimestep = me->curTimestep;
clone->super.isAdvanced = super->isAdvanced;
- if(super->isAdvanced) fetchSuperInfo(clone);
+ if(super->isAdvanced) fetchVariableInfo(clone);
return clone;
}
@@ -31299,8 +31510,8 @@ char *cdiFallbackIterator_serialize(CdiIterator *super)
char *escapedPath = cdiEscapeSpaces(me->path);
char *result = (char *) Malloc(strlen(escapedPath)
- + 5 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
- sprintf(result, "%s %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curTimestep);
+ + 7 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
+ sprintf(result, "%s %d %d %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curSubtypeCount, me->curSubtype, me->curTimestep);
Free(escapedPath);
return result;
}
@@ -31334,11 +31545,13 @@ CdiFallbackIterator *cdiFallbackIterator_deserialize(const char *description)
decodeValue(me->curVariable, description);
decodeValue(me->curLevelCount, description);
decodeValue(me->curLevel, description);
+ decodeValue(me->curSubtypeCount, description);
+ decodeValue(me->curSubtype, description);
decodeValue(me->curTimestep, description);
#undef decodeValue
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
- if(me->super.isAdvanced) fetchSuperInfo(me);
+ if(me->super.isAdvanced) fetchVariableInfo(me);
return me;
@@ -31356,15 +31569,20 @@ fail:
static int advance(CdiFallbackIterator *me)
{
me->curLevel++;
- if(me->curLevel == me->curLevelCount)
+ if(me->curLevel >= me->curLevelCount)
{
me->curLevel = 0;
- me->curVariable++;
- if(me->curVariable == me->variableCount)
+ me->curSubtype++;
+ if(me->curSubtype >= me->curSubtypeCount)
{
- me->curVariable = 0;
- me->curTimestep++;
- if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) return CDI_EEOF;
+ me->curSubtype = 0;
+ me->curVariable++;
+ if(me->curVariable >= me->variableCount)
+ {
+ me->curVariable = 0;
+ me->curTimestep++;
+ if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) return CDI_EEOF;
+ }
}
}
return CDI_NOERR;
@@ -31376,21 +31594,37 @@ int cdiFallbackIterator_nextField(CdiIterator *super)
int result = advance(me);
if(result) return result;
- if(!me->curLevel)
- { //Fetch the information that may have changed (we are processing a new variable/timestep if this point is reached).
- fetchSuperInfo(me);
- me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
- }
+ if(!me->curLevel && !me->curSubtype) fetchVariableInfo(me); //Check whether we are processing a new variable/timestep and fetch the information that may have changed in this case.
return CDI_NOERR;
}
-char *cdiFallbackIterator_inqTime(CdiIterator *super, bool getEndTime)
+char *cdiFallbackIterator_inqTime(CdiIterator *super, CdiTimeType timeType)
{
CdiFallbackIterator *me = (CdiFallbackIterator *)(void *)super;
- if(getEndTime) return NULL; //The stream interface does not export the start/end times of statistical fields, so we treat all data as point of time data, returning the validity time as the start time.
+
+ //retrieve the time information
int taxisId = vlistInqTaxis(me->vlistId);
- int date = taxisInqVdate(taxisId);
- int time = taxisInqVtime(taxisId);
+ int date = 0, time = 0;
+ switch(timeType)
+ {
+ case kCdiTimeType_referenceTime:
+ date = taxisInqRdate(taxisId);
+ time = taxisInqRtime(taxisId);
+ break;
+
+ case kCdiTimeType_startTime:
+ date = taxisInqVdate(taxisId);
+ time = taxisInqVtime(taxisId);
+ break;
+
+ case kCdiTimeType_endTime:
+ return NULL; //The stream interface does not export the start/end times of statistical fields, so we treat all data as point of time data, returning the validity time as the start time.
+
+ default:
+ assert(0 && "internal error, please report this bug");
+ }
+
+ //decode the time information and reencode it into an ISO-compliant string
int year, month, day, hour, minute, second;
cdiDecodeDate(date, &year, &month, &day);
cdiDecodeTime(time, &hour, &minute, &second);
@@ -31470,6 +31704,58 @@ int cdiFallbackIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *
return CDI_NOERR;
}
+int cdiFallbackIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
+{
+ CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
+#ifndef __cplusplus
+ if(!outTileIndex) outTileIndex = &(int){0};
+ if(!outTileAttribute) outTileAttribute = &(int){0};
+#else
+ int dummy = 0;
+ if(!outTileIndex) outTileIndex = &dummy;
+ if(!outTileAttribute) outTileAttribute = &dummy;
+#endif
+
+ int error = CDI_NOERR;
+ if(me->subtypeId == CDI_UNDEFID) //must not call subtypeInqAttribute() with an invalid subtype ID, because it would abort the program instead of returning an error
+ {
+ error = CDI_EINVAL;
+ }
+ else
+ {
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileIndex", outTileIndex)) error = CDI_EINVAL;
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileAttribute", outTileAttribute)) error = CDI_EINVAL;
+ }
+ if(error) *outTileIndex = *outTileAttribute = -1; //Guarantee defined values in case of an error.
+ return error;
+}
+
+int cdiFallbackIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
+{
+ CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
+#ifndef __cplusplus
+ if(!outTileCount) outTileCount = &(int){0};
+ if(!outTileAttributeCount) outTileAttributeCount = &(int){0};
+#else
+ int temp = 0;
+ if(!outTileCount) outTileCount = &temp;
+ if(!outTileAttributeCount) outTileAttributeCount = &temp;
+#endif
+
+ int error = CDI_NOERR;
+ if(me->subtypeId == CDI_UNDEFID) //must not call subtypeInqAttribute() with an invalid subtype ID, because it would abort the program instead of returning an error
+ {
+ error = CDI_EINVAL;
+ }
+ else
+ {
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTiles", outTileCount)) error = CDI_EINVAL;
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTileAttributes", outTileAttributeCount)) error = CDI_EINVAL;
+ }
+ if(error) *outTileCount = *outTileAttributeCount = -1; //Guarantee defined values in case of an error.
+ return CDI_NOERR;
+}
+
char *cdiFallbackIterator_copyVariableName(CdiIterator *super)
{
CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
@@ -31512,19 +31798,19 @@ void cdiFallbackIterator_delete(CdiIterator *super)
int grbBitsPerValue(int datatype);
-int grbInqContents(stream_t * streamptr);
-int grbInqTimestep(stream_t * streamptr, int tsID);
+int grbInqContents(stream_t *streamptr);
+int grbInqTimestep(stream_t *streamptr, int tsID);
-int grbInqRecord(stream_t * streamptr, int *varID, int *levelID);
-void grbDefRecord(stream_t * streamptr);
-void grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
-void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
-void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
+int grbInqRecord(stream_t *streamptr, int *varID, int *levelID);
+void grbDefRecord(stream_t *streamptr);
+void grb_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss);
+void grb_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
+void grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss);
-void grb_write_var(stream_t * streamptr, int varID, int memtype, const void *data, int nmiss);
+void grb_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss);
+void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
-void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss);
+void grb_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss);
void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
int grib1ltypeToZaxisType(int grib_ltype);
@@ -31585,14 +31871,14 @@ const resOps *getZaxisOps(void);
struct CdiGribIterator {
CdiIterator super;
- CdiInputFile* file;
+ CdiInputFile *file;
off_t fileOffset;
- unsigned char* gribBuffer;
+ unsigned char *gribBuffer;
size_t bufferSize, curRecordSize;
#ifdef HAVE_LIBGRIB_API
- grib_handle* gribHandle;
+ grib_handle *gribHandle;
#else
- void* gribHandle;
+ void *gribHandle;
#endif
};
@@ -31652,7 +31938,7 @@ CdiGribIterator *cdiGribIterator_makeClone(CdiIterator *super)
CdiGribIterator *me = (CdiGribIterator*)super;
//Allocate memory and copy data. (operations that may fail)
- CdiGribIterator* result = (struct CdiGribIterator *) Malloc(sizeof(*result));
+ CdiGribIterator *result = (struct CdiGribIterator *) Malloc(sizeof(*result));
if(!result) goto fail;
result->file = me->file;
@@ -31703,9 +31989,9 @@ char *cdiGribIterator_serialize(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
- const char* path = cdiInputFile_getPath(me->file);
- char* escapedPath = cdiEscapeSpaces(path);
- char* result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
+ const char *path = cdiInputFile_getPath(me->file);
+ char *escapedPath = cdiEscapeSpaces(path);
+ char *result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
sprintf(result, "%s %zu", escapedPath, me->fileOffset);
Free(escapedPath);
return result;
@@ -31714,8 +32000,8 @@ char *cdiGribIterator_serialize(CdiIterator *super)
CdiGribIterator *cdiGribIterator_deserialize(const char *description)
{
- char* path;
- CdiGribIterator* me = (CdiGribIterator *) Malloc(sizeof(*me));
+ char *path;
+ CdiGribIterator *me = (CdiGribIterator *) Malloc(sizeof(*me));
if(!me) goto fail;
description = baseIter_constructFromString(&me->super, description);
@@ -31800,7 +32086,7 @@ static ssize_t scanToGribMarker(CdiGribIterator *me)
if(scannedBytes + scanSize > kMaxScanSize) scanSize = kMaxScanSize - scannedBytes;
assert(scanSize <= me->bufferSize);
int status = cdiInputFile_read(me->file, me->fileOffset + (off_t)scannedBytes, scanSize, &scanSize, me->gribBuffer);
- if(status != CDI_NOERR && status != CDI_EEOF) return status;
+ if(status != CDI_NOERR && status != CDI_EEOF) return -1;
const unsigned char *startPosition = positionOfGribMarker(me->gribBuffer, scanSize);
if(startPosition)
@@ -31810,21 +32096,21 @@ static ssize_t scanToGribMarker(CdiGribIterator *me)
//Get the offset for the next iteration if there is a next iteration.
scanSize -= 3; //so that we won't miss a 'GRIB' sequence that happens to be cut off
- scannedBytes += scanSize;
- scannedBytes &= ~(size_t)0xf; //make 16 bytes aligned
+ scanSize &= ~(size_t)0xf; //make 16 bytes aligned
+ if((ssize_t)scanSize <= 0) return -1; //ensure that we make progress
}
return -1;
}
static unsigned decode24(void *beData)
{
- unsigned char* bytes = (unsigned char *)beData;
+ unsigned char *bytes = (unsigned char *)beData;
return ((unsigned)bytes[0] << 16) + ((unsigned)bytes[1] << 8) + (unsigned)bytes[2];
}
static uint64_t decode64(void *beData)
{
- unsigned char* bytes = (unsigned char *)beData;
+ unsigned char *bytes = (unsigned char *)beData;
uint64_t result = 0;
for(size_t i = 0; i < 8; i++) result = (result << 8) + bytes[i];
return result;
@@ -31931,10 +32217,10 @@ int cdiGribIterator_nextField(CdiIterator *super)
return CDI_NOERR;
}
-char *cdiGribIterator_inqTime(CdiIterator *super, bool getEndTime)
+char *cdiGribIterator_inqTime(CdiIterator *super, CdiTimeType timeType)
{
CdiGribIterator *me = (CdiGribIterator*)super;
- return gribMakeTimeString(me->gribHandle, getEndTime);
+ return gribMakeTimeString(me->gribHandle, timeType);
}
int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit)
@@ -31945,13 +32231,13 @@ int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outN
int zaxisType = ZAXIS_GENERIC;
if(gribEditionNumber(me->gribHandle) <= 1)
{
- int levelType = gribGetLongDefault(me->gribHandle, "indicatorOfTypeOfLevel", 255);
+ int levelType = (int)gribGetLongDefault(me->gribHandle, "indicatorOfTypeOfLevel", 255);
if(levelSelector && !isGrib1DualLevel(levelType)) levelType = 255;
zaxisType = grib1ltypeToZaxisType(levelType);
}
else
{
- int levelType = gribGetLongDefault(me->gribHandle, levelSelector ? "typeOfSecondFixedSurface" : "typeOfFirstFixedSurface", 255);
+ int levelType = (int)gribGetLongDefault(me->gribHandle, levelSelector ? "typeOfSecondFixedSurface" : "typeOfFirstFixedSurface", 255);
zaxisType = grib2ltypeToZaxisType(levelType);
}
@@ -31969,6 +32255,7 @@ int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outN
static double logicalLevelValue2(long gribType, long storedValue, long power)
{
double factor = 1;
+ assert(power >= 0);
while(power--) factor *= 10; //this is precise up to factor == 22.
switch(gribType)
{
@@ -32014,7 +32301,7 @@ static int readLevel2(grib_handle *gribHandle, const char *levelTypeKey, const c
default:
{
- long power = gribGetLongDefault(gribHandle, powerKey, 0); //1 byte
+ long power = 255 & gribGetLongDefault(gribHandle, powerKey, 0); //1 byte
if(power == 255) power = 0;
long value = gribGetLongDefault(gribHandle, valueKey, 0); //4 bytes
*outValue1 = logicalLevelValue2(levelType, value, power);
@@ -32089,6 +32376,46 @@ int cdiGribIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *outL
return CDI_NOERR;
}
+int cdiGribIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
+{
+ CdiGribIterator *me = (CdiGribIterator*)super;
+ int trash;
+ if(!outTileIndex) outTileIndex = &trash;
+ if(!outTileAttribute) outTileAttribute = &trash;
+
+ //Get the values if possible.
+ int error = CDI_NOERR;
+ long value;
+ if(grib_get_long(me->gribHandle, "tileIndex", &value)) error = CDI_EINVAL;
+ *outTileIndex = (int)value;
+ if(grib_get_long(me->gribHandle, "tileAttribute", &value)) error = CDI_EINVAL;
+ *outTileAttribute = (int)value;
+
+ //Ensure defined return values in case of failure.
+ if(error) *outTileIndex = *outTileAttribute = -1;
+ return error;
+}
+
+int cdiGribIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
+{
+ CdiGribIterator *me = (CdiGribIterator*)super;
+ int trash;
+ if(!outTileCount) outTileCount = &trash;
+ if(!outTileAttributeCount) outTileAttributeCount = &trash;
+
+ //Get the values if possible.
+ int error = CDI_NOERR;
+ long value;
+ if(grib_get_long(me->gribHandle, "numberOfTiles", &value)) error = CDI_EINVAL;
+ *outTileCount = (int)value;
+ if(grib_get_long(me->gribHandle, "numberOfTileAttributes", &value)) error = CDI_EINVAL;
+ *outTileAttributeCount = (int)value;
+
+ //Ensure defined return values in case of failure.
+ if(error) *outTileCount = *outTileAttributeCount = 0;
+ return error;
+}
+
char *cdiGribIterator_copyVariableName(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
@@ -32113,7 +32440,7 @@ void cdiGribIterator_readFieldF(CdiIterator *super, float *buffer, size_t *nmiss
CdiGribIterator *me = (CdiGribIterator*)super;
size_t valueCount = gribGetArraySize(me->gribHandle, "values");
- double* temp = (double *) Malloc(valueCount*sizeof(*temp));
+ double *temp = (double *) Malloc(valueCount*sizeof(*temp));
cdiGribIterator_readField(super, temp, nmiss);
for(size_t i = valueCount; i--; ) buffer[i] = (float)temp[i];
Free(temp);
@@ -32136,8 +32463,8 @@ void cdiGribIterator_delete(CdiGribIterator *me)
#ifdef HAVE_LIBGRIB_API
if(me) cdiGribIterator_condestruct(me, NULL, 0);
#else
- (void)me;
- xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+ if (me)
+ xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
#endif
}
@@ -34816,9 +35143,6 @@ void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levelID, const dou
#endif
#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-
@@ -34936,6 +35260,7 @@ int cdiGetFiletype(const char *filename, int *byteorder)
if ( CDI_Debug ) Message("found IEG file = %s", filename);
}
#endif
+#if defined (HAVE_LIBCGRIBEX)
else if ( gribCheckSeek(fileID, &recpos, &version) == 0 )
{
if ( version <= 1 )
@@ -34949,6 +35274,7 @@ int cdiGetFiletype(const char *filename, int *byteorder)
if ( CDI_Debug ) Message("found seeked GRIB2 file = %s", filename);
}
}
+#endif
fileClose(fileID);
@@ -34979,9 +35305,6 @@ The valid CDI file format types are @func{FILETYPE_GRB}, @func{FILETYPE_GRB2}, @
int streamInqFiletype(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->filetype);
}
@@ -35025,9 +35348,6 @@ with the file format type @func{FILETYPE_SRV}, @func{FILETYPE_EXT} or @func{FILE
void streamDefByteorder(int streamID, int byteorder)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
streamptr->byteorder = byteorder;
int filetype = streamptr->filetype;
@@ -35085,9 +35405,6 @@ The valid CDI byte order types are @func{CDI_BIGENDIAN} and @func{CDI_LITTLEENDI
int streamInqByteorder(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->byteorder);
}
@@ -35111,9 +35428,6 @@ const char *streamFilesuffix(int filetype)
const char *streamFilename(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->filename);
}
@@ -35122,9 +35436,6 @@ long cdiInqTimeSize(int streamID)
{
int tsID = 0, nrecs;
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
long ntsteps = streamptr->ntsteps;
if ( ntsteps == (long)CDI_UNDEFID )
@@ -35218,7 +35529,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
case FILETYPE_GRB:
case FILETYPE_GRB2:
{
+#ifndef __cplusplus
fileID = gribOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = gribOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -35231,7 +35547,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBSERVICE)
case FILETYPE_SRV:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -35245,7 +35566,13 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBEXTRA)
case FILETYPE_EXT:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
+
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -35259,7 +35586,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBIEG)
case FILETYPE_IEG:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -35273,18 +35605,33 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBNETCDF)
case FILETYPE_NC:
{
+#ifndef __cplusplus
fileID = cdfOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdfOpen(filename, temp);
+#endif
break;
}
case FILETYPE_NC2:
{
+#ifndef __cplusplus
fileID = cdfOpen64(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdfOpen64(filename, temp);
+#endif
break;
}
case FILETYPE_NC4:
case FILETYPE_NC4C:
{
+#ifndef __cplusplus
fileID = cdf4Open(filename, (char [2]){filemode, 0}, &filetype);
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdf4Open(filename, temp, &filetype);
+#endif
break;
}
#endif
@@ -35301,9 +35648,7 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
}
-int
-streamOpenID(const char *filename, char filemode, int filetype,
- int resH)
+int streamOpenID(const char *filename, char filemode, int filetype, int resH)
{
int fileID = CDI_UNDEFID;
int status;
@@ -35326,37 +35671,49 @@ streamOpenID(const char *filename, char filemode, int filetype,
fileID = streamOpenDelegate(filename, filemode, filetype, streamptr, 1);
}
- if (fileID < 0)
+ if ( fileID < 0 )
{
- Free(streamptr->record);
- stream_delete_entry(streamptr);
streamID = fileID;
}
else
{
- streamID = streamptr->self;
+ streamID = streamptr->self;
- if ( streamID < 0 ) return (CDI_ELIMIT);
+ if ( streamID < 0 ) return CDI_ELIMIT;
streamptr->filemode = filemode;
streamptr->filename = strdupx(filename);
streamptr->fileID = fileID;
if ( filemode == 'r' )
- {
- int vlistID = vlistCreate();
- if ( vlistID < 0 ) return(CDI_ELIMIT);
-
- streamptr->vlistID = vlistID;
- /* cdiReadByteorder(streamID); */
- status = cdiInqContents(streamptr);
- if ( status < 0 ) return (status);
- vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
- vlistptr->ntsteps = streamptr->ntsteps;
- }
+ {
+ int vlistID = vlistCreate();
+ if ( vlistID < 0 ) return(CDI_ELIMIT);
+
+ cdiVlistMakeInternal(vlistID);
+ streamptr->vlistID = vlistID;
+ /* cdiReadByteorder(streamID); */
+ status = cdiInqContents(streamptr);
+ if ( status < 0 )
+ {
+ streamID = status;
+ }
+ else
+ {
+ vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
+ vlistptr->ntsteps = streamptr->ntsteps;
+ cdiVlistMakeImmutable(vlistID);
+ }
+ }
}
- return (streamID);
+ if ( streamID < 0 )
+ {
+ Free(streamptr->record);
+ stream_delete_entry(streamptr);
+ }
+
+ return streamID;
}
static int streamOpen(const char *filename, const char *filemode, int filetype)
@@ -35398,11 +35755,13 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
streamptr->fileID = fileID;
streamptr->vlistID = vlistCreate();
+ cdiVlistMakeInternal(streamptr->vlistID);
/* cdiReadByteorder(streamID); */
status = cdiInqContents(streamptr);
if ( status < 0 ) return (status);
vlistptr = vlist_to_pointer(streamptr->vlistID);
vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
+ if(!strcmp(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID);
{
void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
@@ -35503,7 +35862,7 @@ open stream. Otherwise, a negative number with the error status is returned.
@EndList
@Example
-Here is an example using @func{streamOpenRead} to open an existing netCDF
+Here is an example using @func{streamOpenRead} to open an existing NetCDF
file named @func{foo.nc} for reading:
@Source
@@ -35584,7 +35943,7 @@ open stream. Otherwise, a negative number with the error status is returned.
@EndList
@Example
-Here is an example using @func{streamOpenWrite} to create a new netCDF file named @func{foo.nc} for writing:
+Here is an example using @func{streamOpenWrite} to create a new NetCDF file named @func{foo.nc} for writing:
@Source
...
@@ -35769,8 +36128,6 @@ void streamClose(int streamID)
int index;
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
if ( CDI_Debug )
Message("streamID = %d filename = %s", streamID, streamptr->filename);
@@ -35828,8 +36185,7 @@ void streamClose(int streamID)
taxisDestroy(vlistInqTaxis(vlistID));
}
- vlist_unlock(vlistID);
- vlistDestroy(vlistID);
+ cdiVlistDestroy_(vlistID);
}
stream_delete_entry(streamptr);
@@ -35907,8 +36263,6 @@ void streamSync(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
void (*myStreamSync_)(stream_t *streamptr)
= (void (*)(stream_t *))namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func;
myStreamSync_(streamptr);
@@ -35919,11 +36273,11 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
{
int taxisID = 0;
+ stream_check_ptr(__func__, streamptr);
+
if ( CDI_Debug )
Message("streamID = %d tsID = %d", streamptr->self, tsID);
- stream_check_ptr(__func__, streamptr);
-
int vlistID = streamptr->vlistID;
int time_is_varying = vlistHasTime(vlistID);
@@ -35960,7 +36314,7 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
streamptr->filetype == FILETYPE_NC2 ||
streamptr->filetype == FILETYPE_NC4 ||
streamptr->filetype == FILETYPE_NC4C)
- && vlistHasTime(vlistID))
+ && time_is_varying)
{
void (*myCdfDefTimestep)(stream_t *streamptr, int tsID)
= (void (*)(stream_t *, int))
@@ -36029,9 +36383,6 @@ int streamInqTimestep(int streamID, int tsID)
int nrecs = 0;
int taxisID;
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
int vlistID = streamptr->vlistID;
if ( tsID < streamptr->rtsteps )
@@ -36114,752 +36465,189 @@ int streamInqTimestep(int streamID, int tsID)
return (nrecs);
}
-/* the single image implementation */
-static
-void cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
+#if 0
+void streamWriteContents(int streamID, char *cname)
{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+ stream_t *streamptr = stream_to_pointer(streamID);
- check_parg(data);
- check_parg(nmiss);
+ int vlistID = streamptr->vlistID;
- stream_t *streamptr = stream_to_pointer(streamID);
+ FILE *cnp = fopen(cname, "w");
- stream_check_ptr(__func__, streamptr);
+ if ( cnp == NULL ) SysError(cname);
+
+ fprintf(cnp, "#CDI library version %s\n", cdiLibraryVersion());
+ fprintf(cnp, "#\n");
+ fprintf(cnp, "filename: %s\n", streamptr->filename);
int filetype = streamptr->filetype;
+ fprintf(cnp, "filetype: %s\n", strfiletype(filetype));
- *nmiss = 0;
+ fprintf(cnp, "#\n");
+ fprintf(cnp, "#grids:\n");
- switch (filetype)
+ int ngrids = vlistNgrids(vlistID);
+ for ( int i = 0; i < ngrids; i++ )
{
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("grbReadVar not implemented for memtype float!");
- grbReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvReadVar not implemented for memtype float!");
- srvReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extReadVar not implemented for memtype float!");
- extReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegReadVar not implemented for memtype float!");
- iegReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( memtype == MEMTYPE_FLOAT )
- cdfReadVarSP(streamptr, varID, (float *)data, nmiss);
- else
- cdfReadVarDP(streamptr, varID, (double *)data, nmiss);
+ int gridID = vlistGrid(vlistID, i);
+ int gridtype = gridInqType(gridID);
+ int xsize = gridInqXsize(gridID);
+ int ysize = gridInqYsize(gridID);
+ fprintf(cnp, "%4d:%4d:%4d:%4d\n", i+1, gridtype, xsize, ysize);
+ }
+ fprintf(cnp, "#\n");
+
+ fprintf(cnp, "varID:code:gridID:zaxisID:tsteptype:datatype\n");
+
+ int nvars = vlistNvars(vlistID);
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int code = vlistInqVarCode(vlistID, varID);
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int datatype = vlistInqVarDatatype(vlistID, varID);
+ fprintf(cnp, "%4d:%4d:%4d:%4d:%4d:%4d:\n",
+ varID+1, code, gridID, zaxisID, tsteptype, datatype);
+ }
+
+ fprintf(cnp, "#\n");
+
+ fprintf(cnp, "tsID:nrecs:date:time\n");
+
+ int tsID = 0;
+ while (1)
+ {
+ int nrecs = streamptr->tsteps[tsID].nallrecs;
+ int date = streamptr->tsteps[tsID].taxis.vdate;
+ int time = streamptr->tsteps[tsID].taxis.vtime;
+ off_t position = streamptr->tsteps[tsID].position;
+
+ fprintf(cnp, "%4d:%4d:%4d:%4d:%ld\n",
+ tsID, nrecs, date, time, (long) position);
+
+ if ( streamptr->tsteps[tsID].next )
+ tsID++;
+ else
break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
}
-}
-/*
- at Function streamReadVar
- at Title Read a variable
+ fprintf(cnp, "#\n");
- at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
+ fprintf(cnp, "tsID:recID:varID:levID:size:pos\n");
- at Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+ tsID = 0;
+ while (1)
+ {
+ int nrecs = streamptr->tsteps[tsID].nallrecs;
+ for ( int recID = 0; recID < nrecs; recID++ )
+ {
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ int levelID = streamptr->tsteps[tsID].records[recID].levelID;
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ long recsize = (long)streamptr->tsteps[tsID].records[recID].size;
+ fprintf(cnp, "%4d:%4d:%4d:%4d:%4ld:%ld\n",
+ tsID, recID, varID, levelID, recsize, (long) recpos);
+ }
+
+ if ( streamptr->tsteps[tsID].next )
+ tsID++;
+ else
+ break;
+ }
+
+ fclose(cnp);
+}
+#endif
+
+// This function is used in CDO!
+off_t streamNvals(int streamID)
{
- cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ return (streamptr->numvals);
}
/*
- at Function streamReadVarF
- at Title Read a variable
+ at Function streamDefVlist
+ at Title Define the variable list
- at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
+ at Prototype void streamDefVlist(int streamID, int vlistID)
@Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate}.
@Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
+The function @func{streamDefVlist} defines the variable list of a stream.
+
+To safeguard against errors by modifying the wrong vlist object,
+this function makes the passed vlist object immutable.
+All further vlist changes have to use the vlist object returned by streamInqVlist().
+
@EndFunction
*/
-void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
+void streamDefVlist(int streamID, int vlistID)
{
- cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+ void (*myStreamDefVlist)(int streamID, int vlistID)
+ = (void (*)(int, int))namespaceSwitchGet(NSSWITCH_STREAM_DEF_VLIST_).func;
+ myStreamDefVlist(streamID, vlistID);
}
-/* the single image implementation */
-void cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
+/* the single image implementation of streamDefVlist */
+void
+cdiStreamDefVlist_(int streamID, int vlistID)
{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
-
stream_t *streamptr = stream_to_pointer(streamID);
- if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
- Error("Writing of non-trivial subtypes not yet implemented!");
- stream_check_ptr(__func__, streamptr);
-
- // check taxis
- if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
+ if ( streamptr->vlistID == CDI_UNDEFID )
{
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- grb_write_var(streamptr, varID, memtype, data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteVar not implemented for memtype float!");
- srvWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteVar not implemented for memtype float!");
- extWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteVar not implemented for memtype float!");
- iegWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var(streamptr, varID, memtype, (double *)data, nmiss);
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
+ int vlistCopy = vlistDuplicate(vlistID);
+ cdiVlistMakeInternal(vlistCopy);
+ cdiVlistMakeImmutable(vlistID);
+ cdiStreamSetupVlist(streamptr, vlistCopy);
}
+ else
+ Warning("vlist already defined for %s!", streamptr->filename);
}
/*
- at Function streamWriteVar
- at Title Write a variable
+ at Function streamInqVlist
+ at Title Get the variable list
- at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+ at Prototype int streamInqVlist(int streamID)
@Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
@Description
-The function streamWriteVar writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
-{
- void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
- const void *data, int nmiss)
- = (void (*)(int, int, int, const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
- myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
-}
-
-/*
- at Function streamWriteVarF
- at Title Write a variable
+The function @func{streamInqVlist} returns the variable list of a stream.
- at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item data Pointer to a block of single precision floating point data values to be written.
- @Item nmiss Number of missing values.
+ at Result
+ at func{streamInqVlist} returns an identifier to the variable list.
- at Description
-The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
@EndFunction
*/
-void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+int streamInqVlist(int streamID)
{
- void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
- const void *data, int nmiss)
- = (void (*)(int, int, int, const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
- myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
+ stream_t *streamptr = stream_to_pointer(streamID);
+ return (streamptr->vlistID);
}
-static
-int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
-{
- // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
- // A value > 0 is returned in this case, otherwise it returns zero.
- int status = 0;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
- check_parg(nmiss);
+void streamDefCompType(int streamID, int comptype)
+{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- int filetype = streamptr->filetype;
-
- *nmiss = 0;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- grbReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- srvReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- extReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- iegReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( memtype == MEMTYPE_FLOAT )
- cdfReadVarSliceSP(streamptr, varID, levelID, (float *)data, nmiss);
- else
- cdfReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- status = 2;
- break;
- }
- }
-
- return status;
-}
-
-/*
- at Function streamReadVarSlice
- at Title Read a horizontal slice of a variable
-
- at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVarSlice reads all the values of a horizontal slice of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
-{
- if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
- {
- Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
- size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
- memset(data, 0, elementCount * sizeof(*data));
- }
-}
-
-/*
- at Function streamReadVarSliceF
- at Title Read a horizontal slice of a variable
-
- at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
-{
- if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss) )
- {
- // In case the file format does not support single precision reading,
- // we fall back to double precision reading, converting the data on the fly.
- size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
- double *conversionBuffer = (double *) Malloc(elementCount * sizeof(*conversionBuffer));
- streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
- for (size_t i = elementCount; i--; ) data[i] = (float)conversionBuffer[i];
- Free(conversionBuffer);
- }
-}
-
-static
-void cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
- Error("Writing of non-trivial subtypes not yet implemented!");
-
- stream_check_ptr(__func__, streamptr);
-
- // check taxis
- if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteVarSlice not implemented for memtype float!");
- srvWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteVarSlice not implemented for memtype float!");
- extWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteVarSlice not implemented for memtype float!");
- iegWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
- break;
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
- }
-}
-
-/*
- at Function streamWriteVarSlice
- at Title Write a horizontal slice of a variable
-
- at Prototype void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVarSlice writes the values of a horizontal slice of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
-{
- cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
-}
-
-/*
- at Function streamWriteVarSliceF
- at Title Write a horizontal slice of a variable
-
- at Prototype void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to a block of single precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVarSliceF writes the values of a horizontal slice of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
- at EndFunction
-*/
-void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
-{
- cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
-}
-
-
-void
-streamWriteVarChunk(int streamID, int varID,
- const int rect[][2], const double *data, int nmiss)
-{
- void (*myCdiStreamWriteVarChunk_)(int streamID, int varID, int memtype,
- const int rect[][2], const void *data,
- int nmiss)
- = (void (*)(int, int, int, const int [][2], const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_CHUNK_).func;
- myCdiStreamWriteVarChunk_(streamID, varID, MEMTYPE_DOUBLE, rect, data, nmiss);
-}
-
-/* single image implementation */
-void
-cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
- const int rect[][2], const void *data, int nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- // streamDefineTaxis(streamID);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
-#endif
-#if defined (HAVE_LIBGRIB) || defined (HAVE_LIBSERVICE) \
- || defined (HAVE_LIBEXTRA) || defined (HAVE_LIBIEG)
- xabort("streamWriteVarChunk not implemented for filetype %s!",
- strfiletype(filetype));
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var_chunk(streamptr, varID, memtype, rect, data, nmiss);
- break;
-#endif
- default:
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
-}
-
-#if 0
-void streamWriteContents(int streamID, char *cname)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- int vlistID = streamptr->vlistID;
-
- FILE *cnp = fopen(cname, "w");
-
- if ( cnp == NULL ) SysError(cname);
-
- fprintf(cnp, "#CDI library version %s\n", cdiLibraryVersion());
- fprintf(cnp, "#\n");
-
- fprintf(cnp, "filename: %s\n", streamptr->filename);
- int filetype = streamptr->filetype;
- fprintf(cnp, "filetype: %s\n", strfiletype(filetype));
-
- fprintf(cnp, "#\n");
- fprintf(cnp, "#grids:\n");
-
- int ngrids = vlistNgrids(vlistID);
- for ( int i = 0; i < ngrids; i++ )
- {
- int gridID = vlistGrid(vlistID, i);
- int gridtype = gridInqType(gridID);
- int xsize = gridInqXsize(gridID);
- int ysize = gridInqYsize(gridID);
- fprintf(cnp, "%4d:%4d:%4d:%4d\n", i+1, gridtype, xsize, ysize);
- }
-
- fprintf(cnp, "#\n");
-
- fprintf(cnp, "varID:code:gridID:zaxisID:tsteptype:datatype\n");
-
- int nvars = vlistNvars(vlistID);
- for ( int varID = 0; varID < nvars; varID++ )
- {
- int code = vlistInqVarCode(vlistID, varID);
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- int datatype = vlistInqVarDatatype(vlistID, varID);
- fprintf(cnp, "%4d:%4d:%4d:%4d:%4d:%4d:\n",
- varID+1, code, gridID, zaxisID, tsteptype, datatype);
- }
-
- fprintf(cnp, "#\n");
-
- fprintf(cnp, "tsID:nrecs:date:time\n");
-
- int tsID = 0;
- while (1)
- {
- int nrecs = streamptr->tsteps[tsID].nallrecs;
- int date = streamptr->tsteps[tsID].taxis.vdate;
- int time = streamptr->tsteps[tsID].taxis.vtime;
- off_t position = streamptr->tsteps[tsID].position;
-
- fprintf(cnp, "%4d:%4d:%4d:%4d:%ld\n",
- tsID, nrecs, date, time, (long) position);
-
- if ( streamptr->tsteps[tsID].next )
- tsID++;
- else
- break;
- }
-
- fprintf(cnp, "#\n");
-
- fprintf(cnp, "tsID:recID:varID:levID:size:pos\n");
-
- tsID = 0;
- while (1)
- {
- int nrecs = streamptr->tsteps[tsID].nallrecs;
- for ( int recID = 0; recID < nrecs; recID++ )
- {
- int varID = streamptr->tsteps[tsID].records[recID].varID;
- int levelID = streamptr->tsteps[tsID].records[recID].levelID;
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- long recsize = (long)streamptr->tsteps[tsID].records[recID].size;
- fprintf(cnp, "%4d:%4d:%4d:%4d:%4ld:%ld\n",
- tsID, recID, varID, levelID, recsize, (long) recpos);
- }
-
- if ( streamptr->tsteps[tsID].next )
- tsID++;
- else
- break;
- }
-
- fclose(cnp);
-}
-#endif
-
-// This function is used in CDO!
-off_t streamNvals(int streamID)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- return (streamptr->numvals);
-}
-
-/*
- at Function streamDefVlist
- at Title Define the variable list
-
- at Prototype void streamDefVlist(int streamID, int vlistID)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate}.
-
- at Description
-The function @func{streamDefVlist} defines the variable list of a stream.
-
- at EndFunction
-*/
-void streamDefVlist(int streamID, int vlistID)
-{
- void (*myStreamDefVlist)(int streamID, int vlistID)
- = (void (*)(int, int))namespaceSwitchGet(NSSWITCH_STREAM_DEF_VLIST_).func;
- myStreamDefVlist(streamID, vlistID);
-}
-
-/* the single image implementation of streamDefVlist */
-void
-cdiStreamDefVlist_(int streamID, int vlistID)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- if ( streamptr->vlistID == CDI_UNDEFID )
- cdiStreamSetupVlist(streamptr, vlistDuplicate(vlistID));
- else
- Warning("vlist already defined for %s!", streamptr->filename);
-}
-
-/*
- at Function streamInqVlist
- at Title Get the variable list
-
- at Prototype int streamInqVlist(int streamID)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
-
- at Description
-The function @func{streamInqVlist} returns the variable list of a stream.
-
- at Result
- at func{streamInqVlist} returns an identifier to the variable list.
-
- at EndFunction
-*/
-int streamInqVlist(int streamID)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- return (streamptr->vlistID);
-}
-
-
-void streamDefCompType(int streamID, int comptype)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- if (streamptr->comptype != comptype)
- {
- streamptr->comptype = comptype;
- reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
- }
-}
+ if (streamptr->comptype != comptype)
+ {
+ streamptr->comptype = comptype;
+ reshSetStatus(streamID, &streamOps, RESH_DESYNC_IN_USE);
+ }
+}
void streamDefCompLevel(int streamID, int complevel)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
if (streamptr->complevel != complevel)
{
streamptr->complevel = complevel;
@@ -36871,9 +36659,6 @@ void streamDefCompLevel(int streamID, int complevel)
int streamInqCompType(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->comptype);
}
@@ -36881,9 +36666,6 @@ int streamInqCompType(int streamID)
int streamInqCompLevel(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->complevel);
}
@@ -36936,7 +36718,6 @@ cdiStreamSetupVlist(stream_t *streamptr, int vlistID)
void
cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
{
- vlist_lock(vlistID);
int nvars = vlistNvars(vlistID);
streamptr->vlistID = vlistID;
for (int varID = 0; varID < nvars; varID++ )
@@ -36966,10 +36747,14 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
}
break;
#endif
+#ifdef HAVE_LIBGRIB
case FILETYPE_GRB:
case FILETYPE_GRB2:
gribContainersNew(streamptr);
break;
+#endif
+ default:
+ ;
}
}
@@ -37151,8 +36936,6 @@ streamUnpack(char * unpackBuffer, int unpackBufferSize,
return retval;
}
-
-
/*
* Local Variables:
* c-file-style: "Java"
@@ -37162,952 +36945,1491 @@ streamUnpack(char * unpackBuffer, int unpackBufferSize,
* require-trailing-newline: t
* End:
*/
-#ifndef _VARSCAN_H
-#define _VARSCAN_H
-
-#ifndef _GRID_H
+#ifdef HAVE_CONFIG_H
#endif
-void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
- int level1, int level2, int level_sf, int level_unit, int prec,
- int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
- const char *name, const char *stdname, const char *longname, const char *units,
- const var_tile_t *tiles, int *tile_index);
-void varDefVCT(size_t vctsize, double *vctptr);
-void varDefZAxisReference(int nlev, int nvgrid, unsigned char uuid[CDI_UUID_SIZE]);
+/* the single image implementation */
+int cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
-int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
- double *levels1, double *levels2, int vctsize, double *vct, char *name,
- char *longname, const char *units, int prec, int mode, int ltype);
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-void varDefMissval(int varID, double missval);
-void varDefCompType(int varID, int comptype);
-void varDefCompLevel(int varID, int complevel);
-void varDefInst(int varID, int instID);
-int varInqInst(int varID);
-void varDefModel(int varID, int modelID);
-int varInqModel(int varID);
-void varDefTable(int varID, int tableID);
-int varInqTable(int varID);
-void varDefEnsembleInfo(int varID, int ens_idx, int ens_count, int forecast_type);
-
-void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess);
-void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate);
+ check_parg(data);
+ stream_t *streamptr = stream_to_pointer(streamID);
+ if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
+ Error("Writing of non-trivial subtypes not yet implemented!");
-void varDefOptGribInt(int varID, int tile_index, long lval, const char *keyword);
-void varDefOptGribDbl(int varID, int tile_index, double dval, const char *keyword);
-int varOptGribNentries(int varID);
+ // check taxis
+ if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
-int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, const double *levels, const char *longname, const char *units, int ltype);
+ int filetype = streamptr->filetype;
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_write_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
#endif
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
#endif
-
-#ifdef HAVE_LIBNETCDF
-
-//#define TEST_GROUPS 1
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include <float.h>
-
-#include <netcdf.h>
-
-
-//#define PROJECTION_TEST
-extern int CDI_cmor_mode;
-
-#undef UNDEFID
-#define UNDEFID CDI_UNDEFID
-
-
-#if defined HAVE_LIBNETCDF
-static void cdfDefGlobalAtts(stream_t *streamptr);
-static void cdfDefLocalAtts(stream_t *streamptr);
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_write_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+ }
-#define BNDS_NAME "bnds"
-
-#define X_AXIS 1
-#define Y_AXIS 2
-#define Z_AXIS 3
-#define T_AXIS 4
-
-#define POSITIVE_UP 1
-#define POSITIVE_DOWN 2
-
-typedef struct {
- int ncvarid;
- int dimtype;
- size_t len;
- char name[CDI_MAX_NAME];
+ return status;
}
-ncdim_t;
-#define MAX_COORDVARS 4
-#define MAX_AUXVARS 4
+/*
+ at Function streamWriteVar
+ at Title Write a variable
-typedef struct {
- int ncid;
- int ignore;
- short isvar;
- short islon;
- int islat;
- int islev;
- int istime;
- int warn;
- int tsteptype;
- int param;
- int code;
- int tabnum;
- int climatology;
- int bounds;
- int lformula;
- int lformulaterms;
- int gridID;
- int zaxisID;
- int gridtype;
- int zaxistype;
- int xdim;
- int ydim;
- int zdim;
- int xvarid;
- int yvarid;
- int zvarid;
- int tvarid;
- int psvarid;
- int ncoordvars;
- int coordvarids[MAX_COORDVARS];
- int nauxvars;
- int auxvarids[MAX_AUXVARS];
- int cellarea;
- int calendar;
- int tableID;
- int truncation;
- int position;
- int defmissval;
- int deffillval;
- int xtype;
- int ndims;
- int gmapid;
- int positive;
- int dimids[8];
- int dimtype[8];
- int chunks[8];
- int chunked;
- int chunktype;
- int natts;
- int deflate;
- int lunsigned;
- int lvalidrange;
- int *atts;
- size_t vctsize;
- double *vct;
- double missval;
- double fillval;
- double addoffset;
- double scalefactor;
- double validrange[2];
- char name[CDI_MAX_NAME];
- char longname[CDI_MAX_NAME];
- char stdname[CDI_MAX_NAME];
- char units[CDI_MAX_NAME];
- char extra[CDI_MAX_NAME];
- ensinfo_t *ensdata; /* Ensemble information */
-}
-ncvar_t;
+ at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
-static
-void strtolower(char *str)
+ at Description
+The function streamWriteVar writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
{
- if ( str )
- for (size_t i = 0; str[i]; ++i)
- str[i] = (char)tolower((int)str[i]);
+ void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+ const void *data, int nmiss)
+ = (void (*)(int, int, int, const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+
+ myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
}
-static
-int get_timeunit(size_t len, const char *ptu)
-{
- int timeunit = -1;
+/*
+ at Function streamWriteVarF
+ at Title Write a variable
- if ( len > 2 )
- {
- if ( memcmp(ptu, "sec", 3) == 0 ) timeunit = TUNIT_SECOND;
- else if ( memcmp(ptu, "minute", 6) == 0 ) timeunit = TUNIT_MINUTE;
- else if ( memcmp(ptu, "hour", 4) == 0 ) timeunit = TUNIT_HOUR;
- else if ( memcmp(ptu, "day", 3) == 0 ) timeunit = TUNIT_DAY;
- else if ( memcmp(ptu, "month", 5) == 0 ) timeunit = TUNIT_MONTH;
- else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH;
- else if ( memcmp(ptu, "year", 4) == 0 ) timeunit = TUNIT_YEAR;
- }
- else if ( len == 1 )
- {
- if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
- }
+ at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item data Pointer to a block of single precision floating point data values to be written.
+ @Item nmiss Number of missing values.
- return (timeunit);
+ at Description
+The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+{
+ int (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+ const void *data, int nmiss)
+ = (int (*)(int, int, int, const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+
+ if ( myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, (const void *) conversionBuffer, nmiss);
+ Free(conversionBuffer);
+ }
}
static
-int isTimeUnits(const char *timeunits)
+int cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
int status = 0;
- if ( strncmp(timeunits, "sec", 3) == 0 ||
- strncmp(timeunits, "minute", 6) == 0 ||
- strncmp(timeunits, "hour", 4) == 0 ||
- strncmp(timeunits, "day", 3) == 0 ||
- strncmp(timeunits, "month", 5) == 0 ) status = 1;
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
- return (status);
-}
+ check_parg(data);
-static
-int isTimeAxisUnits(const char *timeunits)
-{
- char *ptu, *tu;
- int timetype = -1;
- int timeunit;
- int status = FALSE;
+ stream_t *streamptr = stream_to_pointer(streamID);
+ if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
+ Error("Writing of non-trivial subtypes not yet implemented!");
- size_t len = strlen(timeunits);
- tu = (char *) Malloc((len+1)*sizeof(char));
- memcpy(tu, timeunits, (len+1) * sizeof(char));
- ptu = tu;
+ // check taxis
+ if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
- for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
+ int filetype = streamptr->filetype;
- timeunit = get_timeunit(len, ptu);
- if ( timeunit != -1 )
+ switch (filetype)
{
-
- while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
- if ( *ptu )
- {
- while ( isspace(*ptu) ) ptu++;
-
- if ( memcmp(ptu, "as", 2) == 0 )
- timetype = TAXIS_ABSOLUTE;
- else if ( memcmp(ptu, "since", 5) == 0 )
- timetype = TAXIS_RELATIVE;
-
- if ( timetype != -1 ) status = TRUE;
- }
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
}
- Free(tu);
-
- return (status);
+ return status;
}
-static
-void scanTimeString(const char *ptu, int *rdate, int *rtime)
-{
- int year = 1, month = 1, day = 1;
- int hour = 0, minute = 0, second = 0;
- int v1 = 1, v2 = 1, v3 = 1;
+/*
+ at Function streamWriteVarSlice
+ at Title Write a horizontal slice of a variable
- *rdate = 0;
- *rtime = 0;
+ at Prototype void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
- if ( *ptu )
- {
- v1 = atoi(ptu);
- if ( v1 < 0 ) ptu++;
- while ( isdigit((int) *ptu) ) ptu++;
- if ( *ptu )
- {
- v2 = atoi(++ptu);
- while ( isdigit((int) *ptu) ) ptu++;
- if ( *ptu )
- {
- v3 = atoi(++ptu);
- while ( isdigit((int) *ptu) ) ptu++;
- }
- }
- }
+ at Description
+The function streamWriteVarSlice writes the values of a horizontal slice of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
+{
+ cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+}
- if ( v3 > 999 && v1 < 32 )
- { year = v3; month = v2; day = v1; }
- else
- { year = v1; month = v2; day = v3; }
+/*
+ at Function streamWriteVarSliceF
+ at Title Write a horizontal slice of a variable
- while ( isspace((int) *ptu) ) ptu++;
+ at Prototype void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to a block of single precision floating point data values to be written.
+ @Item nmiss Number of missing values.
- if ( *ptu )
+ at Description
+The function streamWriteVarSliceF writes the values of a horizontal slice of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
+{
+ if ( cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
{
- while ( ! isdigit((int) *ptu) ) ptu++;
-
- hour = atoi(ptu);
- while ( isdigit((int) *ptu) ) ptu++;
- if ( *ptu == ':' )
- {
- ptu++;
- minute = atoi(ptu);
- while ( isdigit((int) *ptu) ) ptu++;
- if ( *ptu == ':' )
- {
- ptu++;
- second = atoi(ptu);
- }
- }
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ streamWriteVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+ Free(conversionBuffer);
}
-
- *rdate = cdiEncodeDate(year, month, day);
- *rtime = cdiEncodeTime(hour, minute, second);
}
-static
-int scanTimeUnit(const char *unitstr)
-{
- int timeunit = -1;
- size_t len = strlen(unitstr);
- timeunit = get_timeunit(len, unitstr);
- if ( timeunit == -1 )
- Message("Unsupported TIMEUNIT: %s!", unitstr);
- return (timeunit);
+void
+streamWriteVarChunk(int streamID, int varID,
+ const int rect[][2], const double *data, int nmiss)
+{
+ void (*myCdiStreamWriteVarChunk_)(int streamID, int varID, int memtype,
+ const int rect[][2], const void *data,
+ int nmiss)
+ = (void (*)(int, int, int, const int [][2], const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_CHUNK_).func;
+ myCdiStreamWriteVarChunk_(streamID, varID, MEMTYPE_DOUBLE, rect, data, nmiss);
}
-static
-void setForecastTime(const char *timestr, taxis_t *taxis)
+/* single image implementation */
+void
+cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
+ const int rect[][2], const void *data, int nmiss)
{
- int len;
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
- (*taxis).fdate = 0;
- (*taxis).ftime = 0;
+ stream_t *streamptr = stream_to_pointer(streamID);
- len = (int) strlen(timestr);
- if ( len == 0 ) return;
+ // streamDefineTaxis(streamID);
- int fdate = 0, ftime = 0;
- scanTimeString(timestr, &fdate, &ftime);
+ int filetype = streamptr->filetype;
- (*taxis).fdate = fdate;
- (*taxis).ftime = ftime;
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+#endif
+#if defined (HAVE_LIBGRIB) || defined (HAVE_LIBSERVICE) \
+ || defined (HAVE_LIBEXTRA) || defined (HAVE_LIBIEG)
+ xabort("streamWriteVarChunk not implemented for filetype %s!",
+ strfiletype(filetype));
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_write_var_chunk(streamptr, varID, memtype, rect, data, nmiss);
+ break;
+#endif
+ default:
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
}
static
-int setBaseTime(const char *timeunits, taxis_t *taxis)
+int stream_write_record(int streamID, int memtype, const void *data, int nmiss)
{
- char *ptu, *tu;
- int timetype = TAXIS_ABSOLUTE;
- int rdate = -1, rtime = -1;
- int timeunit;
-
- size_t len = strlen(timeunits);
- tu = (char *) Malloc((len+1) * sizeof (char));
- memcpy(tu, timeunits, (len+1) * sizeof (char));
- ptu = tu;
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
- for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
+ check_parg(data);
- timeunit = get_timeunit(len, ptu);
- if ( timeunit == -1 )
- {
- Message("Unsupported TIMEUNIT: %s!", timeunits);
- return (1);
- }
+ stream_t *streamptr = stream_to_pointer(streamID);
- while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
- if ( *ptu )
+ switch (streamptr->filetype)
{
- while ( isspace(*ptu) ) ptu++;
-
- if ( memcmp(ptu, "as", 2) == 0 )
- timetype = TAXIS_ABSOLUTE;
- else if ( memcmp(ptu, "since", 5) == 0 )
- timetype = TAXIS_RELATIVE;
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grb_write_record(streamptr, memtype, data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_write_record(streamptr, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+ break;
+ }
+ }
- while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
- if ( *ptu )
- {
- while ( isspace(*ptu) ) ptu++;
+ return status;
+}
- if ( timetype == TAXIS_ABSOLUTE )
- {
- if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
- {
- Message("Unsupported format %s for TIMEUNIT day!", ptu);
- timeunit = -1;
- }
- else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
- {
- Message("Unsupported format %s for TIMEUNIT month!", ptu);
- timeunit = -1;
- }
- }
- else if ( timetype == TAXIS_RELATIVE )
- {
- scanTimeString(ptu, &rdate, &rtime);
+/*
+ at Function streamWriteRecord
+ at Title Write a horizontal slice of a variable
- (*taxis).rdate = rdate;
- (*taxis).rtime = rtime;
+ at Prototype void streamWriteRecord(int streamID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
- if ( CDI_Debug )
- Message("rdate = %d rtime = %d", rdate, rtime);
- }
- }
- }
+ at Description
+The function streamWriteRecord writes the values of a horizontal slice (record) of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteRecord(int streamID, const double *data, int nmiss)
+{
+ stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+}
- (*taxis).type = timetype;
- (*taxis).unit = timeunit;
- Free(tu);
+void streamWriteRecordF(int streamID, const float *data, int nmiss)
+{
+ if ( stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int varID = streamptr->record->varID;
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ streamWriteRecord(streamID, conversionBuffer, nmiss);
+ Free(conversionBuffer);
+ }
+}
- if ( CDI_Debug )
- Message("timetype = %d unit = %d", timetype, timeunit);
+#ifdef HAVE_CONFIG_H
+#endif
- return (0);
-}
+
+/* the single image implementation */
static
-void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint)
+int cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
{
- nc_type atttype;
- size_t nc_attlen;
-
- *attint = 0;
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
- cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
- cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
- if ( atttype != NC_CHAR )
- {
- int *pintatt = NULL;
+ check_parg(data);
+ check_parg(nmiss);
- if ( (int)nc_attlen > attlen )
- pintatt = (int *) Malloc(nc_attlen * sizeof (int));
- else
- pintatt = attint;
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int filetype = streamptr->filetype;
- cdf_get_att_int(fileID, ncvarid, attname, pintatt);
+ *nmiss = 0;
- if ( (int)nc_attlen > attlen )
- {
- memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
- Free(pintatt);
- }
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_read_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_read_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
}
-}
-static
-void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
-{
- nc_type atttype;
- size_t nc_attlen;
+ return status;
+}
- *attdouble = 0;
+/*
+ at Function streamReadVar
+ at Title Read a variable
- cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
- cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+ at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
- if ( atttype != NC_CHAR )
- {
- double *pdoubleatt = NULL;
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+{
+ cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+}
- if ( (int)nc_attlen > attlen )
- pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
- else
- pdoubleatt = attdouble;
+/*
+ at Function streamReadVarF
+ at Title Read a variable
- cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);
+ at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
- if ( (int)nc_attlen > attlen )
- {
- memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
- Free(pdoubleatt);
- }
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
+{
+ if ( cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss) )
+ {
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadVar(streamID, varID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
}
}
+
static
-void cdfGetAttText(int fileID, int ncvarid,const char *attname, int attlen, char *atttext)
+int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
{
- nc_type atttype;
- size_t nc_attlen;
-
- cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
- cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
- if ( atttype == NC_CHAR )
- {
- char attbuf[65636];
- if ( nc_attlen < sizeof(attbuf) )
- {
- cdf_get_att_text(fileID, ncvarid, attname, attbuf);
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
- if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
+ check_parg(data);
+ check_parg(nmiss);
- attbuf[nc_attlen++] = 0;
- memcpy(atttext, attbuf, nc_attlen);
- }
- else
- {
- atttext[0] = 0;
- }
- }
-#if defined (HAVE_NETCDF4)
- else if ( atttype == NC_STRING )
- {
- if ( nc_attlen == 1 )
- {
- char *attbuf = NULL;
- cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int filetype = streamptr->filetype;
- size_t ssize = strlen(attbuf) + 1;
+ *nmiss = 0;
- if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
- memcpy(atttext, attbuf, ssize);
- atttext[ssize - 1] = 0;
- Free(attbuf);
- }
- else
- {
- atttext[0] = 0;
- }
- }
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_read_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
#endif
-}
-
-static
-int xtypeIsText(int xtype)
-{
- int isText = FALSE;
-
- if ( xtype == NC_CHAR )
- isText = TRUE;
-#if defined (HAVE_NETCDF4)
- else if ( xtype == NC_STRING )
- isText = TRUE;
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_read_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ status = 2;
+ break;
+ }
+ }
- return isText;
+ return status;
}
-static
-int xtypeIsFloat(int xtype)
-{
- int isFloat = FALSE;
-
- if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
+/*
+ at Function streamReadVarSlice
+ at Title Read a horizontal slice of a variable
- return isFloat;
-}
+ at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
-static
-int cdfInqDatatype(int xtype, int lunsigned)
+ at Description
+The function streamReadVarSlice reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
{
- int datatype = -1;
+ if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
+ {
+ Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
+ size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ memset(data, 0, elementCount * sizeof(*data));
+ }
+}
-#if defined (HAVE_NETCDF4)
- if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
-#endif
+/*
+ at Function streamReadVarSliceF
+ at Title Read a horizontal slice of a variable
- if ( xtype == NC_BYTE ) datatype = DATATYPE_INT8;
- /* else if ( xtype == NC_CHAR ) datatype = DATATYPE_UINT8; */
- else if ( xtype == NC_SHORT ) datatype = DATATYPE_INT16;
- else if ( xtype == NC_INT ) datatype = DATATYPE_INT32;
- else if ( xtype == NC_FLOAT ) datatype = DATATYPE_FLT32;
- else if ( xtype == NC_DOUBLE ) datatype = DATATYPE_FLT64;
-#if defined (HAVE_NETCDF4)
- else if ( xtype == NC_UBYTE ) datatype = DATATYPE_UINT8;
- else if ( xtype == NC_LONG ) datatype = DATATYPE_INT32;
- else if ( xtype == NC_USHORT ) datatype = DATATYPE_UINT16;
- else if ( xtype == NC_UINT ) datatype = DATATYPE_UINT32;
- else if ( xtype == NC_INT64 ) datatype = DATATYPE_FLT64;
- else if ( xtype == NC_UINT64 ) datatype = DATATYPE_FLT64;
-#endif
+ at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
- return (datatype);
+ at Description
+The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+{
+ if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss) )
+ {
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
+ }
}
static
-int cdfDefDatatype(int datatype, int filetype)
+int stream_read_record(int streamID, int memtype, void *data, int *nmiss)
{
- int xtype;
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
- if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- Error("CDI/netCDF library does not support complex numbers!");
+ check_parg(data);
+ check_parg(nmiss);
- if ( filetype == FILETYPE_NC4 )
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ *nmiss = 0;
+
+ switch (streamptr->filetype)
{
- if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
- else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
-#if defined (HAVE_NETCDF4)
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_UBYTE;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
-#else
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grb_read_record(streamptr, memtype, data, nmiss);
+ break;
#endif
- else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
- else xtype = NC_FLOAT;
- }
- else
- {
- if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
- else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
- else xtype = NC_FLOAT;
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_read_record(streamptr, memtype, data, nmiss);
+ break;
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+ break;
+ }
}
- return (xtype);
+ return status;
}
-static inline void *
-resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
+
+void streamReadRecord(int streamID, double *data, int *nmiss)
{
- if (reqSize > *bufSize)
- {
- *buf = Realloc(*buf, reqSize);
- *bufSize = reqSize;
- }
- return *buf;
+ stream_read_record(streamID, MEMTYPE_DOUBLE, (void *) data, nmiss);
}
-static
-void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
-{
- int natts, iatt;
- int atttype, attlen;
- size_t len;
- char attname[CDI_MAX_NAME+1];
- void *attBuf = NULL;
- size_t attBufSize = 0;
- vlistInqNatts(vlistID, varID, &natts);
-
- for ( iatt = 0; iatt < natts; iatt++ )
+void streamReadRecordF(int streamID, float *data, int *nmiss)
+{
+ if ( stream_read_record(streamID, MEMTYPE_FLOAT, (void *) data, nmiss) )
{
- vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
-
- if ( attlen == 0 ) continue;
-
- if ( atttype == DATATYPE_TXT )
- {
- size_t attSize = (size_t)attlen*sizeof(char);
- char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
- len = (size_t)attlen;
- cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
- }
- else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
- {
- size_t attSize = (size_t)attlen*sizeof(int);
- int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
- len = (size_t)attlen;
- cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
- }
- else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
- {
- size_t attSize = (size_t)attlen * sizeof(double);
- double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
- len = (size_t)attlen;
- if ( atttype == DATATYPE_FLT32 )
- {
- float attflt_sp[len];
- for ( size_t i = 0; i < len; ++i ) attflt_sp[i] = (float)attflt[i];
- cdf_put_att_float(fileID, ncvarID, attname, NC_FLOAT, len, attflt_sp);
- }
- else
- cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
- }
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadRecord(streamID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
}
- Free(attBuf);
}
+#ifndef _VARSCAN_H
+#define _VARSCAN_H
+#ifndef _GRID_H
+#endif
-void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
-{
- int memtype = MEMTYPE_DOUBLE;
- int vlistID1 = streamptr1->vlistID;
- int tsID = streamptr1->curTsID;
- int vrecID = streamptr1->tsteps[tsID].curRecID;
- int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
- int ivarID = streamptr1->tsteps[tsID].records[recID].varID;
- int gridID = vlistInqVarGrid(vlistID1, ivarID);
- int datasize = gridInqSize(gridID);
-
- double *data = (double *) Malloc((size_t)datasize * sizeof (double));
-
- int nmiss;
- cdfReadRecord(streamptr1, data, &nmiss);
- cdf_write_record(streamptr2, memtype, data, nmiss);
- Free(data);
-}
+void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
+ int level1, int level2, int level_sf, int level_unit, int prec,
+ int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
+ const char *name, const char *stdname, const char *longname, const char *units,
+ const var_tile_t *tiles, int *tile_index);
-/* not used
-int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
-{
- int tsID, recID;
+void varDefVCT(size_t vctsize, double *vctptr);
+void varDefZAxisReference(int nlev, int nvgrid, unsigned char uuid[CDI_UUID_SIZE]);
- recID = streamptr->tsteps[0].curRecID++;
- printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
- printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
+int varDefZaxis(int vlistID, int zaxistype, int nlevels, const double *levels, int lbounds,
+ const double *levels1, const double *levels2, int vctsize, const double *vct, char *name,
+ const char *longname, const char *units, int prec, int mode, int ltype);
- if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
- {
- streamptr->tsteps[0].curRecID = 0;
- }
+void varDefMissval(int varID, double missval);
+void varDefCompType(int varID, int comptype);
+void varDefCompLevel(int varID, int complevel);
+void varDefInst(int varID, int instID);
+int varInqInst(int varID);
+void varDefModel(int varID, int modelID);
+int varInqModel(int varID);
+void varDefTable(int varID, int tableID);
+int varInqTable(int varID);
+void varDefEnsembleInfo(int varID, int ens_idx, int ens_count, int forecast_type);
- *varID = streamptr->tsteps[0].records[recID].varID;
- *levelID = streamptr->tsteps[0].records[recID].levelID;
+void varDefTypeOfGeneratingProcess(int varID, int typeOfGeneratingProcess);
+void varDefProductDefinitionTemplate(int varID, int productDefinitionTemplate);
- streamptr->record->varID = *varID;
- streamptr->record->levelID = *levelID;
- if ( CDI_Debug )
- Message("recID = %d varID = %d levelID = %d", recID, *varID, *levelID);
+void varDefOptGribInt(int varID, int tile_index, long lval, const char *keyword);
+void varDefOptGribDbl(int varID, int tile_index, double dval, const char *keyword);
+int varOptGribNentries(int varID);
- return (recID+1);
-}
-*/
+int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, const double *levels, const char *longname, const char *units, int ltype);
+#endif
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
+#endif
-void cdfDefRecord(stream_t *streamptr)
-{
- (void)streamptr;
-}
+#ifdef HAVE_LIBNETCDF
+//#define TEST_GROUPS 1
-static
-void cdfWriteGridTraj(stream_t *streamptr, int gridID)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+#include <limits.h>
+#include <ctype.h>
+#include <math.h>
+#include <float.h>
+#ifdef HAVE_MMAP
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+#endif
- int gridindex = vlistGridIndex(vlistID, gridID);
- int lonID = streamptr->xdimID[gridindex],
- latID = streamptr->ydimID[gridindex];
+#include <netcdf.h>
- double xlon = gridInqXval(gridID, 0),
- xlat = gridInqYval(gridID, 0);
- int tsID = streamptr->curTsID;
- size_t index = (size_t)tsID;
- cdf_put_var1_double(fileID, lonID, &index, &xlon);
- cdf_put_var1_double(fileID, latID, &index, &xlat);
-}
+//#define PROJECTION_TEST
-static
-void cdfReadGridTraj(stream_t *streamptr, int gridID)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
- int gridindex = vlistGridIndex(vlistID, gridID);
- int lonID = streamptr->xdimID[gridindex];
- int latID = streamptr->ydimID[gridindex];
+#define BNDS_NAME "bnds"
- int tsID = streamptr->curTsID;
- size_t index = (size_t)tsID;
+#define X_AXIS 1
+#define Y_AXIS 2
+#define Z_AXIS 3
+#define T_AXIS 4
- double xlon, xlat;
- cdf_get_var1_double(fileID, lonID, &index, &xlon);
- cdf_get_var1_double(fileID, latID, &index, &xlat);
+#define POSITIVE_UP 1
+#define POSITIVE_DOWN 2
- gridDefXvals(gridID, &xlon);
- gridDefYvals(gridID, &xlat);
+typedef struct {
+ int ncvarid;
+ int dimtype;
+ size_t len;
+ char name[CDI_MAX_NAME];
}
+ncdim_t;
+#define MAX_COORDVARS 4
+#define MAX_AUXVARS 4
+typedef struct {
+ int ncid;
+ int ignore;
+ short isvar;
+ short islon;
+ int islat;
+ int islev;
+ int istime;
+ int warn;
+ int tsteptype;
+ int param;
+ int code;
+ int tabnum;
+ int climatology;
+ int bounds;
+ int lformula;
+ int lformulaterms;
+ int gridID;
+ int zaxisID;
+ int gridtype;
+ int zaxistype;
+ int xdim;
+ int ydim;
+ int zdim;
+ int xvarid;
+ int yvarid;
+ int zvarid;
+ int tvarid;
+ int psvarid;
+ int ncoordvars;
+ int coordvarids[MAX_COORDVARS];
+ int nauxvars;
+ int auxvarids[MAX_AUXVARS];
+ int cellarea;
+ int calendar;
+ int tableID;
+ int truncation;
+ int position;
+ int defmissval;
+ int deffillval;
+ int xtype;
+ int ndims;
+ int gmapid;
+ int positive;
+ int dimids[8];
+ int dimtype[8];
+ int chunks[8];
+ int chunked;
+ int chunktype;
+ int natts;
+ int deflate;
+ int lunsigned;
+ int lvalidrange;
+ int *atts;
+ size_t vctsize;
+ double *vct;
+ double missval;
+ double fillval;
+ double addoffset;
+ double scalefactor;
+ double validrange[2];
+ char name[CDI_MAX_NAME];
+ char longname[CDI_MAX_NAME];
+ char stdname[CDI_MAX_NAME];
+ char units[CDI_MAX_NAME];
+ char extra[CDI_MAX_NAME];
+ ensinfo_t *ensdata; /* Ensemble information */
+}
+ncvar_t;
static
-void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
+void strtolower(char *str)
{
-#if defined (HAVE_NETCDF4)
- int retval;
- /* Set chunking, shuffle, and deflate. */
- int shuffle = 1;
- int deflate = 1;
+ if ( str )
+ for (size_t i = 0; str[i]; ++i)
+ str[i] = (char)tolower((int)str[i]);
+}
- if ( deflate_level < 1 || deflate_level > 9 ) deflate_level = 1;
+static
+int get_timeunit(size_t len, const char *ptu)
+{
+ int timeunit = -1;
- if ((retval = nc_def_var_deflate(ncid, ncvarid, shuffle, deflate, deflate_level)))
+ if ( len > 2 )
{
- Error("nc_def_var_deflate failed, status = %d", retval);
+ if ( memcmp(ptu, "sec", 3) == 0 ) timeunit = TUNIT_SECOND;
+ else if ( memcmp(ptu, "minute", 6) == 0 ) timeunit = TUNIT_MINUTE;
+ else if ( memcmp(ptu, "hour", 4) == 0 ) timeunit = TUNIT_HOUR;
+ else if ( memcmp(ptu, "day", 3) == 0 ) timeunit = TUNIT_DAY;
+ else if ( memcmp(ptu, "month", 5) == 0 ) timeunit = TUNIT_MONTH;
+ else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH;
+ else if ( memcmp(ptu, "year", 4) == 0 ) timeunit = TUNIT_YEAR;
}
-#else
- static int lwarn = TRUE;
-
- if ( lwarn )
+ else if ( len == 1 )
{
- lwarn = FALSE;
- Warning("Deflate compression failed, netCDF4 not available!");
+ if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
}
-#endif
+
+ return timeunit;
}
+static
+bool isTimeUnits(const char *timeunits)
+{
+ bool status = false;
+
+ if ( strncmp(timeunits, "sec", 3) == 0 ||
+ strncmp(timeunits, "minute", 6) == 0 ||
+ strncmp(timeunits, "hour", 4) == 0 ||
+ strncmp(timeunits, "day", 3) == 0 ||
+ strncmp(timeunits, "month", 5) == 0 ) status = true;
+
+ return status;
+}
-#if defined(NC_SZIP_NN_OPTION_MASK)
static
-void cdfDefVarSzip(int ncid, int ncvarid)
+bool isTimeAxisUnits(const char *timeunits)
{
- int retval;
- /* Set options_mask and bits_per_pixel. */
- int options_mask = NC_SZIP_NN_OPTION_MASK;
- int bits_per_pixel = 16;
+ char *ptu, *tu;
+ int timetype = -1;
+ int timeunit;
+ bool status = false;
- if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
+ size_t len = strlen(timeunits);
+ tu = (char *) Malloc((len+1)*sizeof(char));
+ memcpy(tu, timeunits, (len+1) * sizeof(char));
+ ptu = tu;
+
+ for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
+
+ timeunit = get_timeunit(len, ptu);
+ if ( timeunit != -1 )
{
- if ( retval == NC_EINVAL )
+
+ while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+ if ( *ptu )
{
- static int lwarn = TRUE;
+ while ( isspace(*ptu) ) ptu++;
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("netCDF4/Szip compression not compiled in!");
- }
+ if ( memcmp(ptu, "as", 2) == 0 )
+ timetype = TAXIS_ABSOLUTE;
+ else if ( memcmp(ptu, "since", 5) == 0 )
+ timetype = TAXIS_RELATIVE;
+
+ if ( timetype != -1 ) status = true;
}
- else
- Error("nc_def_var_szip failed, status = %d", retval);
}
+
+ Free(tu);
+
+ return status;
}
-#endif
static
-void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
+void scanTimeString(const char *ptu, int *rdate, int *rtime)
{
- if ( streamptr->vars[varID].defmiss == FALSE )
- {
- int fileID;
- int ncvarid;
- double missval;
- int vlistID;
- int xtype;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- ncvarid = streamptr->vars[varID].ncvarid;
- missval = vlistInqVarMissval(vlistID, varID);
+ int year = 1, month = 1, day = 1;
+ int hour = 0, minute = 0, second = 0;
+ int v1 = 1, v2 = 1, v3 = 1;
- if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
+ *rdate = 0;
+ *rtime = 0;
- xtype = cdfDefDatatype(dtype, streamptr->filetype);
+ if ( *ptu )
+ {
+ v1 = atoi(ptu);
+ if ( v1 < 0 ) ptu++;
+ while ( isdigit((int) *ptu) ) ptu++;
+ if ( *ptu )
+ {
+ v2 = atoi(++ptu);
+ while ( isdigit((int) *ptu) ) ptu++;
+ if ( *ptu )
+ {
+ v3 = atoi(++ptu);
+ while ( isdigit((int) *ptu) ) ptu++;
+ }
+ }
+ }
- if ( xtype == NC_BYTE && missval > 127 && missval < 256 ) xtype = NC_INT;
+ if ( v3 > 999 && v1 < 32 )
+ { year = v3; month = v2; day = v1; }
+ else
+ { year = v1; month = v2; day = v3; }
- cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
- cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
+ while ( isspace((int) *ptu) ) ptu++;
- if ( lcheck && streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ if ( *ptu )
+ {
+ while ( ! isdigit((int) *ptu) ) ptu++;
- streamptr->vars[varID].defmiss = TRUE;
+ hour = atoi(ptu);
+ while ( isdigit((int) *ptu) ) ptu++;
+ if ( *ptu == ':' )
+ {
+ ptu++;
+ minute = atoi(ptu);
+ while ( isdigit((int) *ptu) ) ptu++;
+ if ( *ptu == ':' )
+ {
+ ptu++;
+ second = atoi(ptu);
+ }
+ }
}
-}
+ *rdate = cdiEncodeDate(year, month, day);
+ *rtime = cdiEncodeTime(hour, minute, second);
+}
-void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
+static
+int scanTimeUnit(const char *unitstr)
{
- int varID;
- int levelID;
-
- varID = streamptr->record->varID;
- levelID = streamptr->record->levelID;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+ size_t len = strlen(unitstr);
+ int timeunit = get_timeunit(len, unitstr);
+ if ( timeunit == -1 )
+ Message("Unsupported TIMEUNIT: %s!", unitstr);
- cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ return timeunit;
}
-void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
+static
+void setForecastTime(const char *timestr, taxis_t *taxis)
{
- if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
+ (*taxis).fdate = 0;
+ (*taxis).ftime = 0;
- int tsID = streamptr->curTsID;
- int vrecID = streamptr->tsteps[tsID].curRecID;
- int recID = streamptr->tsteps[tsID].recIDs[vrecID];
- int varID = streamptr->tsteps[tsID].records[recID].varID;
- int levelID = streamptr->tsteps[tsID].records[recID].levelID;
+ int len = (int) strlen(timestr);
+ if ( len == 0 ) return;
+
+ int fdate = 0, ftime = 0;
+ scanTimeString(timestr, &fdate, &ftime);
- cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
+ (*taxis).fdate = fdate;
+ (*taxis).ftime = ftime;
}
static
-void cdfDefTimeValue(stream_t *streamptr, int tsID)
+int setBaseTime(const char *timeunits, taxis_t *taxis)
{
- int fileID = streamptr->fileID;
+ int timetype = TAXIS_ABSOLUTE;
+ int rdate = -1, rtime = -1;
- if ( CDI_Debug )
- Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+ size_t len = strlen(timeunits);
+ char *tu = (char *) Malloc((len+1) * sizeof (char));
+ memcpy(tu, timeunits, (len+1) * sizeof (char));
+ char *ptu = tu;
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
- if ( streamptr->ncmode == 1 )
+ int timeunit = get_timeunit(len, ptu);
+ if ( timeunit == -1 )
{
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
+ Message("Unsupported TIMEUNIT: %s!", timeunits);
+ return (1);
}
- size_t index = (size_t)tsID;
-
- double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
- if ( CDI_Debug ) Message("tsID = %d timevalue = %f", tsID, timevalue);
+ while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+ if ( *ptu )
+ {
+ while ( isspace(*ptu) ) ptu++;
- int ncvarid = streamptr->basetime.ncvarid;
- cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
+ if ( memcmp(ptu, "as", 2) == 0 )
+ timetype = TAXIS_ABSOLUTE;
+ else if ( memcmp(ptu, "since", 5) == 0 )
+ timetype = TAXIS_RELATIVE;
- if ( taxis->has_bounds )
- {
- size_t start[2], count[2];
+ while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
+ if ( *ptu )
+ {
+ while ( isspace(*ptu) ) ptu++;
- ncvarid = streamptr->basetime.ncvarboundsid;
+ if ( timetype == TAXIS_ABSOLUTE )
+ {
+ if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
+ {
+ Message("Unsupported format %s for TIMEUNIT day!", ptu);
+ timeunit = -1;
+ }
+ else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
+ {
+ Message("Unsupported format %s for TIMEUNIT month!", ptu);
+ timeunit = -1;
+ }
+ }
+ else if ( timetype == TAXIS_RELATIVE )
+ {
+ scanTimeString(ptu, &rdate, &rtime);
- timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
- start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
- cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+ (*taxis).rdate = rdate;
+ (*taxis).rtime = rtime;
- timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
- start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
- cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+ if ( CDI_Debug )
+ Message("rdate = %d rtime = %d", rdate, rtime);
+ }
+ }
}
- ncvarid = streamptr->basetime.leadtimeid;
- if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
- {
- timevalue = taxis->fc_period;
- cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
- }
+ (*taxis).type = timetype;
+ (*taxis).unit = timeunit;
- /*
-printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
- */
+ Free(tu);
+
+ if ( CDI_Debug )
+ Message("timetype = %d unit = %d", timetype, timeunit);
+
+ return 0;
}
static
-int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
+void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint)
{
- int time_bndsid = -1;
- int dims[2];
- char tmpstr[CDI_MAX_NAME];
-
+ nc_type atttype;
+ size_t nc_attlen;
+
+ *attint = 0;
+
+ cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+ cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+ if ( atttype != NC_CHAR )
+ {
+ int *pintatt = NULL;
+
+ if ( (int)nc_attlen > attlen )
+ pintatt = (int *) Malloc(nc_attlen * sizeof (int));
+ else
+ pintatt = attint;
+
+ cdf_get_att_int(fileID, ncvarid, attname, pintatt);
+
+ if ( (int)nc_attlen > attlen )
+ {
+ memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
+ Free(pintatt);
+ }
+ }
+}
+
+static
+void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
+{
+ nc_type atttype;
+ size_t nc_attlen;
+
+ *attdouble = 0;
+
+ cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+ cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+ if ( atttype != NC_CHAR )
+ {
+ double *pdoubleatt = NULL;
+
+ if ( (int)nc_attlen > attlen )
+ pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
+ else
+ pdoubleatt = attdouble;
+
+ cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);
+
+ if ( (int)nc_attlen > attlen )
+ {
+ memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
+ Free(pdoubleatt);
+ }
+ }
+}
+
+static
+void cdfGetAttText(int fileID, int ncvarid,const char *attname, int attlen, char *atttext)
+{
+ nc_type atttype;
+ size_t nc_attlen;
+
+ cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
+ cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
+
+ if ( atttype == NC_CHAR )
+ {
+ char attbuf[65636];
+ if ( nc_attlen < sizeof(attbuf) )
+ {
+ cdf_get_att_text(fileID, ncvarid, attname, attbuf);
+
+ if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
+
+ attbuf[nc_attlen++] = 0;
+ memcpy(atttext, attbuf, nc_attlen);
+ }
+ else
+ {
+ atttext[0] = 0;
+ }
+ }
+#if defined (HAVE_NETCDF4)
+ else if ( atttype == NC_STRING )
+ {
+ if ( nc_attlen == 1 )
+ {
+ char *attbuf = NULL;
+ cdf_get_att_string(fileID, ncvarid, attname, &attbuf);
+
+ size_t ssize = strlen(attbuf) + 1;
+
+ if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
+ memcpy(atttext, attbuf, ssize);
+ atttext[ssize - 1] = 0;
+ Free(attbuf);
+ }
+ else
+ {
+ atttext[0] = 0;
+ }
+ }
+#endif
+}
+
+static
+int xtypeIsText(int xtype)
+{
+ int isText = FALSE;
+
+ if ( xtype == NC_CHAR )
+ isText = TRUE;
+#if defined (HAVE_NETCDF4)
+ else if ( xtype == NC_STRING )
+ isText = TRUE;
+#endif
+
+ return isText;
+}
+
+static
+int xtypeIsFloat(int xtype)
+{
+ int isFloat = FALSE;
+
+ if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
+
+ return isFloat;
+}
+
+static
+int cdfInqDatatype(int xtype, int lunsigned)
+{
+ int datatype = -1;
+
+#if defined (HAVE_NETCDF4)
+ if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
+#endif
+
+ if ( xtype == NC_BYTE ) datatype = DATATYPE_INT8;
+ /* else if ( xtype == NC_CHAR ) datatype = DATATYPE_UINT8; */
+ else if ( xtype == NC_SHORT ) datatype = DATATYPE_INT16;
+ else if ( xtype == NC_INT ) datatype = DATATYPE_INT32;
+ else if ( xtype == NC_FLOAT ) datatype = DATATYPE_FLT32;
+ else if ( xtype == NC_DOUBLE ) datatype = DATATYPE_FLT64;
+#if defined (HAVE_NETCDF4)
+ else if ( xtype == NC_UBYTE ) datatype = DATATYPE_UINT8;
+ else if ( xtype == NC_LONG ) datatype = DATATYPE_INT32;
+ else if ( xtype == NC_USHORT ) datatype = DATATYPE_UINT16;
+ else if ( xtype == NC_UINT ) datatype = DATATYPE_UINT32;
+ else if ( xtype == NC_INT64 ) datatype = DATATYPE_FLT64;
+ else if ( xtype == NC_UINT64 ) datatype = DATATYPE_FLT64;
+#endif
+
+ return datatype;
+}
+
+
+void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+{
+ int memtype = MEMTYPE_DOUBLE;
+ int vlistID1 = streamptr1->vlistID;
+ int tsID = streamptr1->curTsID;
+ int vrecID = streamptr1->tsteps[tsID].curRecID;
+ int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
+ int ivarID = streamptr1->tsteps[tsID].records[recID].varID;
+ int gridID = vlistInqVarGrid(vlistID1, ivarID);
+ int datasize = gridInqSize(gridID);
+ int datatype = vlistInqVarDatatype(vlistID1, ivarID);
+
+ if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;
+
+ void *data = NULL;
+ if ( memtype == MEMTYPE_DOUBLE )
+ data = Malloc((size_t)datasize*sizeof(double));
+ else
+ data = Malloc((size_t)datasize*sizeof(float));
+
+ int nmiss;
+ cdf_read_record(streamptr1, memtype, data, &nmiss);
+ cdf_write_record(streamptr2, memtype, data, nmiss);
+
+ Free(data);
+}
+
+/* not used
+int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
+{
+ int tsID, recID;
+
+ recID = streamptr->tsteps[0].curRecID++;
+ printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
+ printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
+
+ if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
+ {
+ streamptr->tsteps[0].curRecID = 0;
+ }
+
+ *varID = streamptr->tsteps[0].records[recID].varID;
+ *levelID = streamptr->tsteps[0].records[recID].levelID;
+
+ streamptr->record->varID = *varID;
+ streamptr->record->levelID = *levelID;
+
+ if ( CDI_Debug )
+ Message("recID = %d varID = %d levelID = %d", recID, *varID, *levelID);
+
+ return (recID+1);
+}
+*/
+
+
+void cdfDefRecord(stream_t *streamptr)
+{
+ (void)streamptr;
+}
+
+#if defined(NC_SZIP_NN_OPTION_MASK)
+static
+void cdfDefVarSzip(int ncid, int ncvarid)
+{
+ int retval;
+ /* Set options_mask and bits_per_pixel. */
+ int options_mask = NC_SZIP_NN_OPTION_MASK;
+ int bits_per_pixel = 16;
+
+ if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
+ {
+ if ( retval == NC_EINVAL )
+ {
+ static int lwarn = TRUE;
+
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("NetCDF4/Szip compression not compiled in!");
+ }
+ }
+ else
+ Error("nc_def_var_szip failed, status = %d", retval);
+ }
+}
+#endif
+
+static
+void cdfDefTimeValue(stream_t *streamptr, int tsID)
+{
+ int fileID = streamptr->fileID;
+
+ if ( CDI_Debug )
+ Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+
+ if ( streamptr->ncmode == 1 )
+ {
+ cdf_enddef(fileID);
+ streamptr->ncmode = 2;
+ }
+
+ size_t index = (size_t)tsID;
+
+ double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
+ if ( CDI_Debug ) Message("tsID = %d timevalue = %f", tsID, timevalue);
+
+ int ncvarid = streamptr->basetime.ncvarid;
+ cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
+
+ if ( taxis->has_bounds )
+ {
+ size_t start[2], count[2];
+
+ ncvarid = streamptr->basetime.ncvarboundsid;
+
+ timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
+ start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
+ cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+
+ timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
+ start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
+ cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
+ }
+
+ ncvarid = streamptr->basetime.leadtimeid;
+ if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
+ {
+ timevalue = taxis->fc_period;
+ cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
+ }
+
+ /*
+printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
+ */
+}
+
+static
+int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
+{
+ int time_bndsid = -1;
+ int dims[2];
+ char tmpstr[CDI_MAX_NAME];
+
dims[0] = nctimedimid;
/* fprintf(stderr, "time has bounds\n"); */
@@ -38213,7 +38535,7 @@ void cdfDefCalendar(int fileID, int ncvarid, int calendar)
if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
}
-static
+
void cdfDefTime(stream_t* streamptr)
{
int time_varid;
@@ -38315,7 +38637,6 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
{
char axisname[] = "nc2";
int dimID = UNDEFID;
- int gridID0, gridtype0;
int vlistID = streamptr->vlistID;
int fileID = streamptr->fileID;
@@ -38325,8 +38646,8 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
{
dimID = streamptr->xdimID[index];
@@ -38360,16 +38681,12 @@ void cdfDefSP(stream_t *streamptr, int gridID)
*/
char axisname[5] = "nspX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID)/2;
@@ -38377,8 +38694,8 @@ void cdfDefSP(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_SPECTRAL )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
@@ -38406,7 +38723,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->ydimID[gridindex] = dimID;
}
@@ -38416,16 +38733,12 @@ void cdfDefFC(stream_t *streamptr, int gridID)
{
char axisname[5] = "nfcX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID)/2;
@@ -38433,8 +38746,8 @@ void cdfDefFC(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_FOURIER )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
@@ -38462,142 +38775,117 @@ void cdfDefFC(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->ydimID[gridindex] = dimID;
}
+struct cdfDefTrajLatLonInqs {
+ int (*gridInqDimSize)(int gridID);
+ void (*gridInqDimName)(int gridID, char *dimname);
+ void (*gridInqDimStdname)(int gridID, char *dimstdname);
+ void (*gridInqDimLongname)(int gridID, char *dimlongname);
+ void (*gridInqDimUnits)(int gridID, char *dimunits);
+};
-static
-void cdfDefTrajLon(stream_t *streamptr, int gridID)
-{
- char units[CDI_MAX_NAME];
- char longname[CDI_MAX_NAME];
- char stdname[CDI_MAX_NAME];
- char axisname[CDI_MAX_NAME];
- int gridtype, gridindex;
- int dimID = UNDEFID;
- int fileID;
- int dimlen;
- size_t len;
- int ncvarid;
- int vlistID;
- int xtype = NC_DOUBLE;
-
- if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- gridtype = gridInqType(gridID);
- dimlen = gridInqXsize(gridID);
- if ( dimlen != 1 ) Error("Xsize isn't 1 for %s grid!", gridNamePtr(gridtype));
+static void
+cdfDefTrajLatLon(stream_t *streamptr, int gridID,
+ const struct cdfDefTrajLatLonInqs *inqs,
+ int *dimID, const char *sizeName)
+{
+ nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
- gridindex = vlistGridIndex(vlistID, gridID);
- ncvarid = streamptr->xdimID[gridindex];
+ int vlistID = streamptr->vlistID;
+ int dimlen = inqs->gridInqDimSize(gridID);
+ if ( dimlen != 1 )
+ Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID)));
- gridInqXname(gridID, axisname);
- gridInqXlongname(gridID, longname);
- gridInqXstdname(gridID, stdname);
- gridInqXunits(gridID, units);
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int ncvarid = dimID[gridindex];
if ( ncvarid == UNDEFID )
{
- dimID = streamptr->basetime.ncvarid;
-
+ size_t len;
+ int dimNcID = streamptr->basetime.ncvarid;
+ int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
-
- if ( (len = strlen(stdname)) )
- cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
- if ( (len = strlen(longname)) )
- cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
- if ( (len = strlen(units)) )
- cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
+ {
+ char axisname[CDI_MAX_NAME];
+ inqs->gridInqDimName(gridID, axisname);
+ cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
+ }
+ {
+ char stdname[CDI_MAX_NAME];
+ inqs->gridInqDimStdname(gridID, stdname);
+ if ( (len = strlen(stdname)) )
+ cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
+ }
+ {
+ char longname[CDI_MAX_NAME];
+ inqs->gridInqDimLongname(gridID, longname);
+ if ( (len = strlen(longname)) )
+ cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
+ }
+ {
+ char units[CDI_MAX_NAME];
+ inqs->gridInqDimUnits(gridID, units);
+ if ( (len = strlen(units)) )
+ cdf_put_att_text(fileID, ncvarid, "units", len, units);
+ }
cdf_enddef(fileID);
streamptr->ncmode = 2;
}
- streamptr->xdimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
+ dimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
}
-
static
-void cdfDefTrajLat(stream_t *streamptr, int gridID)
+void cdfDefTrajLon(stream_t *streamptr, int gridID)
{
- char units[] = "degrees_north";
- char longname[] = "latitude";
- char stdname[] = "latitude";
- char axisname[] = "tlat";
- int gridtype, gridindex;
- int dimID = UNDEFID;
- int fileID;
- int dimlen;
- size_t len;
- int ncvarid;
- int vlistID;
- int xtype = NC_DOUBLE;
-
- if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
-
- gridtype = gridInqType(gridID);
- dimlen = gridInqYsize(gridID);
- if ( dimlen != 1 ) Error("Ysize isn't 1 for %s grid!", gridNamePtr(gridtype));
-
- gridindex = vlistGridIndex(vlistID, gridID);
- ncvarid = streamptr->ydimID[gridindex];
-
- gridInqYname(gridID, axisname);
- gridInqYlongname(gridID, longname);
- gridInqYstdname(gridID, stdname);
- gridInqYunits(gridID, units);
-
- if ( ncvarid == UNDEFID )
- {
- dimID = streamptr->basetime.ncvarid;
-
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
-
- if ( (len = strlen(stdname)) )
- cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
- if ( (len = strlen(longname)) )
- cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
- if ( (len = strlen(units)) )
- cdf_put_att_text(fileID, ncvarid, "units", len, units);
+ static const struct cdfDefTrajLatLonInqs inqs =
+ { .gridInqDimSize = gridInqXsize,
+ .gridInqDimName = gridInqXname,
+ .gridInqDimStdname = gridInqXstdname,
+ .gridInqDimLongname = gridInqXlongname,
+ .gridInqDimUnits = gridInqXunits
+ };
+ cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->xdimID, "Xsize");
+}
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
- }
- streamptr->ydimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
+static
+void cdfDefTrajLat(stream_t *streamptr, int gridID)
+{
+ static const struct cdfDefTrajLatLonInqs inqs =
+ { .gridInqDimSize = gridInqYsize,
+ .gridInqDimName = gridInqYname,
+ .gridInqDimStdname = gridInqYstdname,
+ .gridInqDimLongname = gridInqYlongname,
+ gridInqYunits
+ };
+ cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->ydimID, "Ysize");
}
static
int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
{
- int iz, index;
+ int index;
int gridID0;
int ncdimid;
char axisname0[CDI_MAX_NAME];
char axisname2[CDI_MAX_NAME];
- int checkname;
int status;
/* check that the name is not already defined */
- checkname = TRUE;
- iz = 0;
+ int checkname = TRUE;
+ unsigned iz = 0;
do
{
strcpy(axisname2, axisname);
- if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%d", iz+1);
+ if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%u", iz+1);
//status = nc_inq_varid(fileID, axisname2, &ncvarid);
if ( type == 'V' ) /* type Var oder Dim */
@@ -38636,12 +38924,11 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
while (checkname && iz <= 99);
- if ( iz ) sprintf(&axisname[strlen(axisname)], "_%d", iz+1);
+ if ( iz ) sprintf(&axisname[strlen(axisname)], "_%u", iz+1);
- return (iz);
+ return (int)iz;
}
-
static
void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
{
@@ -38651,40 +38938,37 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
char axisname[CDI_MAX_NAME];
int index;
/* int index2; */
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
int dimIDs[2];
int ngrids = 0;
- int fileID;
size_t len;
int ncvarid = UNDEFID, ncbvarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
if ( ndims ) ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqXsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, axisname);
+ if ( axisname[0] == 0 ) Error("axis name undefined!");
+
gridInqXlongname(gridID, longname);
gridInqXstdname(gridID, stdname);
gridInqXunits(gridID, units);
- if ( axisname[0] == 0 ) Error("axis name undefined!");
-
for ( index = 0; index < ngrids; index++ )
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -38710,28 +38994,21 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
if ( dimID == UNDEFID )
{
- int status;
- status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
+ int status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
if ( status == 0 && ndims )
status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- if ( ndims )
- {
- cdf_def_dim(fileID, axisname, dimlen, &dimID);
+ if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
- if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
- {
- size_t nvertex = 2;
- if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
- cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
- }
- }
-
- if ( gridInqXvalsPtr(gridID) )
+ int gen_bounds = FALSE;
+ int grid_is_cyclic = gridIsCircular(gridID);
+ const double *pvals = gridInqXvalsPtr(gridID);
+ double *pbounds = NULL;
+ if ( pvals )
{
- cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
+ cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
if ( (len = strlen(stdname)) )
cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
@@ -38742,13 +39019,34 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
cdf_put_att_text(fileID, ncvarid, "axis", 1, "X");
- if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
+ if ( gridInqXboundsPtr(gridID) )
+ pbounds = (double*) gridInqXboundsPtr(gridID);
+
+ if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+ {
+ gen_bounds = TRUE;
+ pbounds = (double*) malloc(2*dimlen*sizeof(double));
+ for ( size_t i = 0; i < dimlen-1; ++i )
+ {
+ pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2;
+ pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+ }
+ pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)/2;
+ pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)/2;
+ }
+ if ( pbounds )
+ {
+ size_t nvertex = 2;
+ if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
+ cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+ }
+ if ( pbounds && nvdimID != UNDEFID )
{
strcat(axisname, "_");
strcat(axisname, BNDS_NAME);
dimIDs[0] = dimID;
dimIDs[1] = nvdimID;
- cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
+ cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
}
/*
@@ -38763,8 +39061,9 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
cdf_enddef(fileID);
streamptr->ncmode = 2;
- if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, gridInqXvalsPtr(gridID));
- if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, gridInqXboundsPtr(gridID));
+ if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
+ if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
+ if ( gen_bounds ) Free(pbounds);
if ( ndims == 0 ) streamptr->ncxvarID[gridindex] = ncvarid;
}
@@ -38772,7 +39071,6 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
{
@@ -38782,40 +39080,37 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
char axisname[CDI_MAX_NAME];
int index;
/* int index2; */
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
int dimIDs[2];
int ngrids = 0;
- int fileID;
size_t len;
int ncvarid = UNDEFID, ncbvarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
if ( ndims ) ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqYsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqYname(gridID, axisname);
+ if ( axisname[0] == 0 ) Error("axis name undefined!");
+
gridInqYlongname(gridID, longname);
gridInqYstdname(gridID, stdname);
gridInqYunits(gridID, units);
- if ( axisname[0] == 0 ) Error("axis name undefined!");
-
for ( index = 0; index < ngrids; index++ )
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -38848,21 +39143,15 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- if ( ndims )
- {
- cdf_def_dim(fileID, axisname, dimlen, &dimID);
+ if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
- if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
- {
- size_t nvertex = 2;
- if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
- cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
- }
- }
-
- if ( gridInqYvalsPtr(gridID) )
+ int gen_bounds = FALSE;
+ int grid_is_cyclic = gridIsCircular(gridID);
+ const double *pvals = gridInqYvalsPtr(gridID);
+ double *pbounds = NULL;
+ if ( pvals )
{
- cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
+ cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
if ( (len = strlen(stdname)) )
cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
@@ -38873,13 +39162,34 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
cdf_put_att_text(fileID, ncvarid, "axis", 1, "Y");
- if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
+ if ( gridInqYboundsPtr(gridID) )
+ pbounds = (double*) gridInqYboundsPtr(gridID);
+
+ if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+ {
+ gen_bounds = TRUE;
+ pbounds = (double*) malloc(2*dimlen*sizeof(double));
+ for ( size_t i = 0; i < dimlen-1; ++i )
+ {
+ pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2;
+ pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+ }
+ pbounds[0] = (pvals[0] < 0) ? -90 : 90;
+ pbounds[2*dimlen-1] = (pvals[dimlen-1] < 0) ? -90 : 90;
+ }
+ if ( pbounds )
+ {
+ size_t nvertex = 2;
+ if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
+ cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+ }
+ if ( pbounds && nvdimID != UNDEFID )
{
strcat(axisname, "_");
strcat(axisname, BNDS_NAME);
dimIDs[0] = dimID;
dimIDs[1] = nvdimID;
- cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
+ cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
}
/*
@@ -38894,8 +39204,9 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
cdf_enddef(fileID);
streamptr->ncmode = 2;
- if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, gridInqYvalsPtr(gridID));
- if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, gridInqYboundsPtr(gridID));
+ if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
+ if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
+ if ( gen_bounds ) Free(pbounds);
if ( ndims == 0 ) streamptr->ncyvarID[gridindex] = ncvarid;
}
@@ -38903,7 +39214,6 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
streamptr->ydimID[gridindex] = dimID;
}
-
static
void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype)
{
@@ -38931,29 +39241,25 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
char xdimname[4] = "x";
char ydimname[4] = "y";
int index;
- int gridID0, gridtype0, gridindex;
int xdimID = UNDEFID;
int ydimID = UNDEFID;
int dimIDs[3];
- int ngrids;
- int fileID;
size_t len;
int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t xdimlen = (size_t)gridInqXsize(gridID);
size_t ydimlen = (size_t)gridInqYsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, xaxisname);
gridInqXlongname(gridID, xlongname);
@@ -38968,8 +39274,8 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -39021,7 +39327,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
if ( gridInqXvalsPtr(gridID) )
{
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
if ( (len = strlen(xstdname)) )
@@ -39041,7 +39347,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
dimIDs[0] = ydimID;
dimIDs[1] = xdimID;
dimIDs[2] = nvdimID;
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 3, dimIDs, &ncbxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
@@ -39050,7 +39356,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
if ( gridInqYvalsPtr(gridID) )
{
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
if ( (len = strlen(ystdname)) )
@@ -39070,7 +39376,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
dimIDs[0] = ydimID;
dimIDs[1] = xdimID;
dimIDs[2] = nvdimID;
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 3, dimIDs, &ncbyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
@@ -39084,7 +39390,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
static const char longname[] = "area of grid cell";
static const char stdname[] = "cell_area";
- cdf_def_var(fileID, yaxisname_, (nc_type) xtype, 2, dimIDs, &ncavarid);
+ cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid);
cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
@@ -39108,23 +39414,18 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
streamptr->ncavarID[gridindex] = ncavarid;
}
-
static
void cdfDefRgrid(stream_t *streamptr, int gridID)
{
char axisname[7] = "rgridX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
int lwarn = TRUE;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
@@ -39132,8 +39433,8 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -39153,7 +39454,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
{
if ( lwarn )
{
- Warning("Creating a netCDF file with data on a gaussian reduced grid.");
+ Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
Warning("The further processing of the resulting file is unsupported!");
lwarn = FALSE;
}
@@ -39169,25 +39470,20 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefGdim(stream_t *streamptr, int gridID)
{
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
@@ -39196,8 +39492,8 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GENERIC )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -39217,8 +39513,8 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GENERIC )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -39252,11 +39548,10 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefGridReference(stream_t *streamptr, int gridID)
{
@@ -39287,7 +39582,7 @@ void cdfDefGridUUID(stream_t *streamptr, int gridID)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
{
int fileID = streamptr->fileID;
@@ -39307,7 +39602,7 @@ void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
if ( uuidOfVGrid[0] != 0 )
{
char uuidOfVGridStr[37];
- uuid2str(uuidOfVGrid, uuidOfVGridStr);
+ cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
{
int fileID = streamptr->fileID;
@@ -39330,26 +39625,22 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
char xaxisname[CDI_MAX_NAME];
char yaxisname[CDI_MAX_NAME];
int index;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
size_t len;
int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, xaxisname);
gridInqXlongname(gridID, xlongname);
@@ -39364,8 +39655,8 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_UNSTRUCTURED )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -39409,7 +39700,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
if ( gridInqXvalsPtr(gridID) )
{
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 1, &dimID, &ncxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
if ( (len = strlen(xstdname)) )
@@ -39426,7 +39717,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
dimIDs[1] = nvdimID;
strcat(xaxisname, "_");
strcat(xaxisname, BNDS_NAME);
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncbxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
@@ -39435,7 +39726,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
if ( gridInqYvalsPtr(gridID) )
{
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 1, &dimID, &ncyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
if ( (len = strlen(ystdname)) )
@@ -39452,7 +39743,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
dimIDs[1] = nvdimID;
strcat(yaxisname, "_");
strcat(yaxisname, BNDS_NAME);
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncbyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
@@ -39466,7 +39757,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
static const char longname[] = "area of grid cell";
static const char stdname[] = "cell_area";
- cdf_def_var(fileID, yaxisname_, (nc_type) xtype, 1, &dimID, &ncavarid);
+ cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid);
cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
@@ -39497,6 +39788,8 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
int ilev = zaxisInqVctSize(zaxisID)/2;
+ if ( ilev == 0 ) return;
+
int mlev = ilev - 1;
size_t start;
size_t count = 1;
@@ -39512,12 +39805,6 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
return;
}
- if ( ilev == 0 )
- {
- Warning("VCT missing");
- return;
- }
-
int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -39579,6 +39866,8 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
int ilev = zaxisInqVctSize(zaxisID)/2;
+ if ( ilev == 0 ) return;
+
int mlev = ilev - 1;
int hyaiid = 0, hybiid = 0, hyamid, hybmid;
char tmpname[CDI_MAX_NAME];
@@ -39590,12 +39879,6 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
return;
}
- if ( ilev == 0 )
- {
- Warning("VCT missing");
- return;
- }
-
int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -40087,8 +40370,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
if ( gridInqType(gridID) == GRID_SINUSOIDAL )
{
- char varname[] = "sinusoidal";
- char mapname[] = "sinusoidal";
+ static const char varname[] = "sinusoidal";
+ static const char mapname[] = "sinusoidal";
cdf_redef(fileID);
@@ -40106,8 +40389,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
}
else if ( gridInqType(gridID) == GRID_LAEA )
{
- char varname[] = "laea";
- char mapname[] = "lambert_azimuthal_equal_area";
+ static const char varname[] = "laea";
+ static const char mapname[] = "lambert_azimuthal_equal_area";
cdf_redef(fileID);
@@ -40128,8 +40411,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
}
else if ( gridInqType(gridID) == GRID_LCC2 )
{
- char varname[] = "Lambert_Conformal";
- char mapname[] = "lambert_conformal_conic";
+ static const char varname[] = "Lambert_Conformal";
+ static const char mapname[] = "lambert_conformal_conic";
cdf_redef(fileID);
@@ -40261,5581 +40544,6737 @@ void cdfDefGrid(stream_t *streamptr, int gridID)
}
static
-int cdfDefVar(stream_t *streamptr, int varID)
+void scale_add(size_t size, double *data, double addoffset, double scalefactor)
{
- int ncvarid = -1;
- int xid = UNDEFID, yid = UNDEFID;
- size_t xsize = 0, ysize = 0;
- char varname[CDI_MAX_NAME];
- int dims[4];
- int lchunk = FALSE;
- size_t chunks[4] = {0,0,0,0};
- int ndims = 0;
- int tablenum;
- int dimorder[3];
- size_t iax = 0;
- char axis[5];
- int ensID, ensCount, forecast_type;
- int retval;
-
- int fileID = streamptr->fileID;
+ int laddoffset;
+ int lscalefactor;
- if ( CDI_Debug )
- Message("streamID = %d, fileID = %d, varID = %d", streamptr->self, fileID, varID);
+ laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
- if ( streamptr->vars[varID].ncvarid != UNDEFID )
- return streamptr->vars[varID].ncvarid;
+ if ( laddoffset || lscalefactor )
+ {
+ for (size_t i = 0; i < size; ++i )
+ {
+ if ( lscalefactor ) data[i] *= scalefactor;
+ if ( laddoffset ) data[i] += addoffset;
+ }
+ }
+}
- int vlistID = streamptr->vlistID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- int code = vlistInqVarCode(vlistID, varID);
- int param = vlistInqVarParam(vlistID, varID);
- int pnum, pcat, pdis;
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
+static
+void cdfCreateRecords(stream_t *streamptr, int tsID)
+{
+ if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return;
- int chunktype = vlistInqVarChunkType(vlistID, varID);
+ if ( streamptr->tsteps[tsID].nallrecs > 0 ) return;
- vlistInqVarDimorder(vlistID, varID, &dimorder);
+ int vlistID = streamptr->vlistID;
- int gridsize = gridInqSize(gridID);
- if ( gridsize > 1 ) lchunk = TRUE;
- int gridtype = gridInqType(gridID);
- int gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridtype != GRID_TRAJECTORY )
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize);
- if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize);
- }
+ tsteps_t* sourceTstep = streamptr->tsteps;
+ tsteps_t* destTstep = sourceTstep + tsID;
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- int zid = streamptr->zaxisID[zaxisindex];
- int zaxis_is_scalar = FALSE;
- if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID);
+ int nvars = vlistNvars(vlistID);
+ int nrecs = vlistNrecs(vlistID);
- if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
+ if ( nrecs <= 0 ) return;
- if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
+ if ( tsID == 0 )
{
- printf("zid=%d yid=%d xid=%d\n", zid, yid, xid);
- Error("Internal problem, dimension order missing!");
- }
+ int nvrecs = nrecs; /* use all records at first timestep */
- int tid = streamptr->basetime.ncdimid;
+ streamptr->nrecs += nrecs;
- if ( tsteptype != TSTEP_CONSTANT )
- {
- if ( tid == UNDEFID ) Error("Internal problem, time undefined!");
- chunks[ndims] = 1;
- dims[ndims++] = tid;
- axis[iax++] = 'T';
- }
- /*
- if ( zid != UNDEFID ) axis[iax++] = 'Z';
- if ( zid != UNDEFID ) chunks[ndims] = 1;
- if ( zid != UNDEFID ) dims[ndims++] = zid;
+ destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+ destTstep->nrecs = nrecs;
+ destTstep->nallrecs = nrecs;
+ destTstep->recordSize = nrecs;
+ destTstep->curRecID = UNDEFID;
+ destTstep->recIDs = (int *) Malloc((size_t)nvrecs*sizeof (int));;
+ for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
- if ( yid != UNDEFID ) chunks[ndims] = ysize;
- if ( yid != UNDEFID ) dims[ndims++] = yid;
+ record_t *records = destTstep->records;
- if ( xid != UNDEFID ) chunks[ndims] = xsize;
- if ( xid != UNDEFID ) dims[ndims++] = xid;
- */
- for ( int id = 0; id < 3; ++id )
- {
- if ( dimorder[id] == 3 && zid != UNDEFID )
- {
- axis[iax++] = 'Z';
- chunks[ndims] = 1;
- dims[ndims] = zid;
- ndims++;
- }
- else if ( dimorder[id] == 2 && yid != UNDEFID )
- {
- if ( chunktype == CHUNK_LINES )
- chunks[ndims] = 1;
- else
- chunks[ndims] = ysize;
- dims[ndims] = yid;
- ndims++;
- }
- else if ( dimorder[id] == 1 && xid != UNDEFID )
+ for ( int varID = 0, recID = 0; varID < nvars; varID++ )
{
- chunks[ndims] = xsize;
- dims[ndims] = xid;
- ndims++;
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int nlev = zaxisInqSize(zaxisID);
+ for ( int levelID = 0; levelID < nlev; levelID++ )
+ {
+ recordInitEntry(&records[recID]);
+ records[recID].varID = (short)varID;
+ records[recID].levelID = (short)levelID;
+ recID++;
+ }
}
}
-
- if ( CDI_Debug )
- fprintf(stderr, "chunktype %d chunks %d %d %d %d\n", chunktype, (int)chunks[0], (int)chunks[1], (int)chunks[2], (int)chunks[3]);
-
- int tableID = vlistInqVarTable(vlistID, varID);
-
- const char *name = vlistInqVarNamePtr(vlistID, varID);
- const char *longname = vlistInqVarLongnamePtr(vlistID, varID);
- const char *stdname = vlistInqVarStdnamePtr(vlistID, varID);
- const char *units = vlistInqVarUnitsPtr(vlistID, varID);
-
- if ( name == NULL ) name = tableInqParNamePtr(tableID, code);
- if ( longname == NULL ) longname = tableInqParLongnamePtr(tableID, code);
- if ( units == NULL ) units = tableInqParUnitsPtr(tableID, code);
- if ( name )
+ else if ( tsID == 1 )
{
- int checkname;
- int iz;
- int status;
-
- sprintf(varname, "%s", name);
-
- checkname = TRUE;
- iz = 0;
-
- while ( checkname )
+ int nvrecs = 0;
+ for ( int varID = 0; varID < nvars; varID++ )
{
- if ( iz ) sprintf(varname, "%s_%d", name, iz+1);
-
- status = nc_inq_varid(fileID, varname, &ncvarid);
- if ( status != NC_NOERR )
+ if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
{
- checkname = FALSE;
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ nvrecs += zaxisInqSize(zaxisID);
}
+ }
- if ( checkname ) iz++;
+ streamptr->nrecs += nvrecs;
- if ( iz >= CDI_MAX_NAME ) Error("Double entry of variable name '%s'!", name);
- }
+ destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+ destTstep->nrecs = nvrecs;
+ destTstep->nallrecs = nrecs;
+ destTstep->recordSize = nrecs;
+ destTstep->curRecID = UNDEFID;
- if ( strcmp(name, varname) != 0 )
+ memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
+
+ if ( nvrecs )
{
- if ( iz == 1 )
- Warning("Changed double entry of variable name '%s' to '%s'!", name, varname);
- else
- Warning("Changed multiple entry of variable name '%s' to '%s'!", name, varname);
+ destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int));
+ for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ )
+ {
+ int varID = destTstep->records[recID].varID;
+ if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+ {
+ destTstep->recIDs[vrecID++] = recID;
+ }
+ }
}
-
- name = varname;
}
else
{
- if ( code < 0 ) code = -code;
- if ( pnum < 0 ) pnum = -pnum;
-
- if ( pdis == 255 )
- sprintf(varname, "var%d", code);
- else
- sprintf(varname, "param%d.%d.%d", pnum, pcat, pdis);
-
- char *varname2 = varname+strlen(varname);
+ if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1);
- int checkname = TRUE;
- int iz = 0;
+ int nvrecs = streamptr->tsteps[1].nrecs;
- while ( checkname )
- {
- if ( iz ) sprintf(varname2, "_%d", iz+1);
+ streamptr->nrecs += nvrecs;
- int status = nc_inq_varid(fileID, varname, &ncvarid);
- if ( status != NC_NOERR ) checkname = FALSE;
+ destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
+ destTstep->nrecs = nvrecs;
+ destTstep->nallrecs = nrecs;
+ destTstep->recordSize = nrecs;
+ destTstep->curRecID = UNDEFID;
- if ( checkname ) iz++;
+ memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
- if ( iz >= CDI_MAX_NAME ) break;
- }
+ destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof(int));
- name = varname;
- code = 0;
- pdis = 255;
+ memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int));
}
+}
- /* if ( streamptr->ncmode == 2 ) cdf_redef(fileID); */
-
- int dtype = vlistInqVarDatatype(vlistID, varID);
- int xtype = cdfDefDatatype(dtype, streamptr->filetype);
-
- cdf_def_var(fileID, name, (nc_type) xtype, ndims, dims, &ncvarid);
-#if defined (HAVE_NETCDF4)
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+static
+int cdfTimeDimID(int fileID, int ndims, int nvars)
+{
+ for ( int dimid = 0; dimid < ndims; dimid++ )
{
- if ( chunktype == CHUNK_AUTO )
- retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
- else
- retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
-
- if ( retval ) Error("nc_def_var_chunking failed, status = %d", retval);
+ char dimname[80];
+ cdf_inq_dimname(fileID, dimid, dimname);
+ if ( memcmp(dimname, "time", 4) == 0 )
+ return dimid;
}
-#endif
- if ( streamptr->comptype == COMPRESS_ZIP )
+
+ for ( int varid = 0; varid < nvars; varid++ )
{
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
- {
- cdfDefVarDeflate(fileID, ncvarid, streamptr->complevel);
- }
- else
+ int nvdims, nvatts, dimids[9];
+ cdf_inq_var(fileID, varid, NULL, NULL, &nvdims, dimids, &nvatts);
+ if ( nvdims == 1 )
{
- if ( lchunk )
+ for ( int iatt = 0; iatt < nvatts; iatt++ )
{
- static int lwarn = TRUE;
-
- if ( lwarn )
+ char sbuf[CDI_MAX_NAME];
+ cdf_inq_attname(fileID, varid, iatt, sbuf);
+ if ( strncmp(sbuf, "units", 5) == 0 )
{
- lwarn = FALSE;
- Warning("Deflate compression is only available for netCDF4!");
+ cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
+ strtolower(sbuf);
+
+ if ( isTimeUnits(sbuf) )
+ return dimids[0];
}
}
}
}
- if ( streamptr->comptype == COMPRESS_SZIP )
+ return UNDEFID;
+}
+
+static
+void init_ncdims(long ndims, ncdim_t *ncdims)
+{
+ for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ )
{
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
- {
-#if defined (NC_SZIP_NN_OPTION_MASK)
- cdfDefVarSzip(fileID, ncvarid);
-#else
- static int lwarn = TRUE;
+ ncdims[ncdimid].ncvarid = UNDEFID;
+ ncdims[ncdimid].dimtype = UNDEFID;
+ ncdims[ncdimid].len = 0;
+ ncdims[ncdimid].name[0] = 0;
+ }
+}
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("netCDF4/SZIP compression not available!");
- }
-#endif
- }
- else
- {
- static int lwarn = TRUE;
+static
+void init_ncvars(long nvars, ncvar_t *ncvars)
+{
+ for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid )
+ {
+ ncvars[ncvarid].ncid = UNDEFID;
+ ncvars[ncvarid].ignore = FALSE;
+ ncvars[ncvarid].isvar = UNDEFID;
+ ncvars[ncvarid].islon = FALSE;
+ ncvars[ncvarid].islat = FALSE;
+ ncvars[ncvarid].islev = FALSE;
+ ncvars[ncvarid].istime = FALSE;
+ ncvars[ncvarid].warn = FALSE;
+ ncvars[ncvarid].tsteptype = TSTEP_CONSTANT;
+ ncvars[ncvarid].param = UNDEFID;
+ ncvars[ncvarid].code = UNDEFID;
+ ncvars[ncvarid].tabnum = 0;
+ ncvars[ncvarid].calendar = FALSE;
+ ncvars[ncvarid].climatology = FALSE;
+ ncvars[ncvarid].bounds = UNDEFID;
+ ncvars[ncvarid].lformula = FALSE;
+ ncvars[ncvarid].lformulaterms = FALSE;
+ ncvars[ncvarid].gridID = UNDEFID;
+ ncvars[ncvarid].zaxisID = UNDEFID;
+ ncvars[ncvarid].gridtype = UNDEFID;
+ ncvars[ncvarid].zaxistype = UNDEFID;
+ ncvars[ncvarid].xdim = UNDEFID;
+ ncvars[ncvarid].ydim = UNDEFID;
+ ncvars[ncvarid].zdim = UNDEFID;
+ ncvars[ncvarid].xvarid = UNDEFID;
+ ncvars[ncvarid].yvarid = UNDEFID;
+ ncvars[ncvarid].zvarid = UNDEFID;
+ ncvars[ncvarid].tvarid = UNDEFID;
+ ncvars[ncvarid].psvarid = UNDEFID;
+ ncvars[ncvarid].ncoordvars = 0;
+ for ( int i = 0; i < MAX_COORDVARS; ++i )
+ ncvars[ncvarid].coordvarids[i] = UNDEFID;
+ ncvars[ncvarid].nauxvars = 0;
+ for ( int i = 0; i < MAX_AUXVARS; ++i )
+ ncvars[ncvarid].auxvarids[i] = UNDEFID;
+ ncvars[ncvarid].cellarea = UNDEFID;
+ ncvars[ncvarid].tableID = UNDEFID;
+ ncvars[ncvarid].xtype = 0;
+ ncvars[ncvarid].ndims = 0;
+ ncvars[ncvarid].gmapid = UNDEFID;
+ ncvars[ncvarid].vctsize = 0;
+ ncvars[ncvarid].vct = NULL;
+ ncvars[ncvarid].truncation = 0;
+ ncvars[ncvarid].position = 0;
+ ncvars[ncvarid].positive = 0;
+ ncvars[ncvarid].chunked = 0;
+ ncvars[ncvarid].chunktype = UNDEFID;
+ ncvars[ncvarid].defmissval = 0;
+ ncvars[ncvarid].deffillval = 0;
+ ncvars[ncvarid].missval = 0;
+ ncvars[ncvarid].fillval = 0;
+ ncvars[ncvarid].addoffset = 0;
+ ncvars[ncvarid].scalefactor = 1;
+ ncvars[ncvarid].name[0] = 0;
+ ncvars[ncvarid].longname[0] = 0;
+ ncvars[ncvarid].stdname[0] = 0;
+ ncvars[ncvarid].units[0] = 0;
+ ncvars[ncvarid].extra[0] = 0;
+ ncvars[ncvarid].natts = 0;
+ ncvars[ncvarid].atts = NULL;
+ ncvars[ncvarid].deflate = 0;
+ ncvars[ncvarid].lunsigned = 0;
+ ncvars[ncvarid].lvalidrange = 0;
+ ncvars[ncvarid].validrange[0] = VALIDMISS;
+ ncvars[ncvarid].validrange[1] = VALIDMISS;
+ ncvars[ncvarid].ensdata = NULL;
+ }
+}
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("SZIP compression is only available for netCDF4!");
- }
- }
+static
+void cdfSetVar(ncvar_t *ncvars, int ncvarid, short isvar)
+{
+ if ( ncvars[ncvarid].isvar != UNDEFID &&
+ ncvars[ncvarid].isvar != isvar &&
+ ncvars[ncvarid].warn == FALSE )
+ {
+ if ( ! ncvars[ncvarid].ignore )
+ Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name);
+
+ ncvars[ncvarid].warn = TRUE;
+ isvar = FALSE;
}
- if ( stdname && *stdname )
- cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(stdname), stdname);
+ ncvars[ncvarid].isvar = isvar;
+}
- if ( longname && *longname )
- cdf_put_att_text(fileID, ncvarid, "long_name", strlen(longname), longname);
+static
+void cdfSetDim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype)
+{
+ if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID &&
+ ncvars[ncvarid].dimtype[dimid] != dimtype )
+ {
+ Warning("Inconsistent dimension definition for %s! dimid = %d; type = %d; newtype = %d",
+ ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype);
+ }
- if ( units && *units )
- cdf_put_att_text(fileID, ncvarid, "units", strlen(units), units);
+ ncvars[ncvarid].dimtype[dimid] = dimtype;
+}
- if ( code > 0 && pdis == 255 )
- cdf_put_att_int(fileID, ncvarid, "code", NC_INT, 1, &code);
+static
+bool isLonAxis(const char *units, const char *stdname)
+{
+ bool status = false;
+ char lc_units[16];
- if ( pdis != 255 )
+ memcpy(lc_units, units, 15);
+ lc_units[15] = 0;
+ strtolower(lc_units);
+
+ if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
+ (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) )
{
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- cdf_put_att_text(fileID, ncvarid, "param", strlen(paramstr), paramstr);
+ status = true;
}
- if ( tableID != UNDEFID )
+ if ( status == false &&
+ memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) &&
+ memcmp(lc_units, "degree", 6) == 0 )
{
- tablenum = tableInqNum(tableID);
- if ( tablenum > 0 )
- cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum);
+ int ioff = 6;
+ if ( lc_units[ioff] == 's' ) ioff++;
+ if ( lc_units[ioff] == '_' ) ioff++;
+ if ( lc_units[ioff] == 'e' ) status = true;
}
- char coordinates[CDI_MAX_NAME];
- coordinates[0] = 0;
+ return status;
+}
- if ( zaxis_is_scalar )
- {
- int nczvarID = streamptr->nczvarID[zaxisindex];
- if ( nczvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, nczvarID, coordinates+len);
- }
- }
+static
+bool isLatAxis(const char *units, const char *stdname)
+{
+ bool status = false;
+ char lc_units[16];
- if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR )
+ memcpy(lc_units, units, 15);
+ lc_units[15] = 0;
+ strtolower(lc_units);
+
+ if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
+ (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) )
{
- size_t len = strlen(gridNamePtr(gridtype));
- if ( len > 0 )
- cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
+ status = true;
}
- if ( gridIsRotated(gridID) )
+ if ( status == false &&
+ memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) &&
+ memcmp(lc_units, "degree", 6) == 0 )
{
- char mapping[] = "rotated_pole";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ int ioff = 6;
+ if ( lc_units[ioff] == 's' ) ioff++;
+ if ( lc_units[ioff] == '_' ) ioff++;
+ if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true;
}
- if ( gridtype == GRID_SINUSOIDAL )
+ return status;
+}
+
+static
+bool isDBLAxis(/*const char *units,*/ const char *longname)
+{
+ bool status = false;
+
+ if ( strcmp(longname, "depth below land") == 0 ||
+ strcmp(longname, "depth_below_land") == 0 ||
+ strcmp(longname, "levels below the surface") == 0 )
{
- char mapping[] = "sinusoidal";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ /*
+ if ( strcmp(ncvars[ncvarid].units, "cm") == 0 ||
+ strcmp(ncvars[ncvarid].units, "dm") == 0 ||
+ strcmp(ncvars[ncvarid].units, "m") == 0 )
+ */
+ status = true;
}
- else if ( gridtype == GRID_LAEA )
+
+ return status;
+}
+
+static
+bool unitsIsHeight(const char *units)
+{
+ bool status = false;
+ int u0 = units[0];
+
+ if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) ||
+ (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) )
{
- char mapping[] = "laea";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ status = true;
}
- else if ( gridtype == GRID_LCC2 )
- {
- char mapping[] = "Lambert_Conformal";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
- }
- else if ( gridtype == GRID_TRAJECTORY )
- {
- cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" );
- }
- else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 )
- {
- int ncxvarID = streamptr->ncxvarID[gridindex];
- int ncyvarID = streamptr->ncyvarID[gridindex];
- if ( ncyvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncyvarID, coordinates+len);
- }
- if ( ncxvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncxvarID, coordinates+len);
- }
- }
- else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
- {
- char cellarea[CDI_MAX_NAME] = "area: ";
- int ncxvarID = streamptr->ncxvarID[gridindex];
- int ncyvarID = streamptr->ncyvarID[gridindex];
- int ncavarID = streamptr->ncavarID[gridindex];
- if ( ncyvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncyvarID, coordinates+len);
- }
- if ( ncxvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncxvarID, coordinates+len);
- }
-
- if ( ncavarID != CDI_UNDEFID )
- {
- size_t len = strlen(cellarea);
- cdf_inq_varname(fileID, ncavarID, cellarea+len);
- len = strlen(cellarea);
- cdf_put_att_text(fileID, ncvarid, "cell_measures", len, cellarea);
- }
- if ( gridtype == GRID_UNSTRUCTURED )
- {
- int position = gridInqPosition(gridID);
- if ( position > 0 )
- cdf_put_att_int(fileID, ncvarid, "number_of_grid_in_reference", NC_INT, 1, &position);
- }
- }
- else if ( gridtype == GRID_SPECTRAL || gridtype == GRID_FOURIER )
- {
- int gridTruncation = gridInqTrunc(gridID);
- axis[iax++] = '-';
- axis[iax++] = '-';
- cdf_put_att_text(fileID, ncvarid, "axis", iax, axis);
- cdf_put_att_int(fileID, ncvarid, "truncation", NC_INT, 1, &gridTruncation);
- }
+ return status;
+}
- size_t len = strlen(coordinates);
- if ( len ) cdf_put_att_text(fileID, ncvarid, "coordinates", len, coordinates);
+static
+bool isDepthAxis(const char *stdname, const char *longname)
+{
+ bool status = false;
- /* if ( xtype == NC_BYTE || xtype == NC_SHORT || xtype == NC_INT ) */
- {
- int laddoffset, lscalefactor;
- double addoffset, scalefactor;
- int astype = NC_DOUBLE;
+ if ( strcmp(stdname, "depth") == 0 ) status = true;
- addoffset = vlistInqVarAddoffset(vlistID, varID);
- scalefactor = vlistInqVarScalefactor(vlistID, varID);
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+ if ( status == false )
+ if ( strcmp(longname, "depth_below_sea") == 0 ||
+ strcmp(longname, "depth below sea") == 0 )
+ {
+ status = true;
+ }
- if ( laddoffset || lscalefactor )
- {
- if ( IS_EQUAL(addoffset, (double) ((float) addoffset)) &&
- IS_EQUAL(scalefactor, (double) ((float) scalefactor)) )
- {
- astype = NC_FLOAT;
- }
+ return status;
+}
- if ( xtype == (int) NC_FLOAT ) astype = NC_FLOAT;
+static
+bool isHeightAxis(const char *stdname, const char *longname)
+{
+ bool status = false;
- cdf_put_att_double(fileID, ncvarid, "add_offset", (nc_type) astype, 1, &addoffset);
- cdf_put_att_double(fileID, ncvarid, "scale_factor", (nc_type) astype, 1, &scalefactor);
- }
- }
+ if ( strcmp(stdname, "height") == 0 ) status = true;
- if ( dtype == DATATYPE_UINT8 && xtype == NC_BYTE )
- {
- int validrange[2] = {0, 255};
- cdf_put_att_int(fileID, ncvarid, "valid_range", NC_SHORT, 2, validrange);
- cdf_put_att_text(fileID, ncvarid, "_Unsigned", 4, "true");
- }
+ if ( status == false )
+ if ( strcmp(longname, "height") == 0 ||
+ strcmp(longname, "height above the surface") == 0 )
+ {
+ status = true;
+ }
- streamptr->vars[varID].ncvarid = ncvarid;
+ return status;
+}
- if ( vlistInqVarMissvalUsed(vlistID, varID) )
- cdfDefVarMissval(streamptr, varID, vlistInqVarDatatype(vlistID, varID), 0);
+static
+bool unitsIsPressure(const char *units)
+{
+ bool status = false;
- if ( zid == -1 )
+ if ( memcmp(units, "millibar", 8) == 0 ||
+ memcmp(units, "mb", 2) == 0 ||
+ memcmp(units, "hectopas", 8) == 0 ||
+ memcmp(units, "hPa", 3) == 0 ||
+ memcmp(units, "Pa", 2) == 0 )
{
- if ( zaxisInqType(zaxisID) == ZAXIS_CLOUD_BASE ||
- zaxisInqType(zaxisID) == ZAXIS_CLOUD_TOP ||
- zaxisInqType(zaxisID) == ZAXIS_ISOTHERM_ZERO ||
- zaxisInqType(zaxisID) == ZAXIS_TOA ||
- zaxisInqType(zaxisID) == ZAXIS_SEA_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_LAKE_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TA ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TW ||
- zaxisInqType(zaxisID) == ZAXIS_MIX_LAYER ||
- zaxisInqType(zaxisID) == ZAXIS_ATMOSPHERE )
- {
- zaxisInqName(zaxisID, varname);
- cdf_put_att_text(fileID, ncvarid, "level_type", strlen(varname), varname);
- }
+ status = true;
}
- if ( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
+ return status;
+}
+
+static
+void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid)
+{
+ *apvarid = -1;
+ *bvarid = -1;
+ *psvarid = -1;
+ const int attstringlen = 8192; char attstring[8192];
+ cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
+ if ( strcmp(attstring, "p = ap + b*ps") == 0 )
{
- /* void cdf_put_att_int( int ncid, int varid, const char *name, nc_type xtype,
- size_t len, const int *ip )
- */
- cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID);
- cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount);
- cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type);
+ int lstop = FALSE;
+ int dimvarid;
+ cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
+ char *pstring = attstring;
-#ifdef DBG
- if( DBG )
- {
- fprintf( stderr, "cdfDefVar :\n EnsID %d\n Enscount %d\n Forecast init type %d\n", ensID,
- ensCount, forecast_type );
- }
-#endif
- }
+ for ( int i = 0; i < 3; i++ )
+ {
+ while ( isspace((int) *pstring) ) pstring++;
+ if ( *pstring == 0 ) break;
+ char *tagname = pstring;
+ while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+ if ( *pstring == 0 ) lstop = TRUE;
+ *pstring++ = 0;
- /* Attributes */
- defineAttributes(vlistID, varID, fileID, ncvarid);
+ while ( isspace((int) *pstring) ) pstring++;
+ if ( *pstring == 0 ) break;
+ char *varname = pstring;
+ while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+ if ( *pstring == 0 ) lstop = TRUE;
+ *pstring++ = 0;
- /* if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); */
+ int status = nc_inq_varid(ncid, varname, &dimvarid);
+ if ( status == NC_NOERR )
+ {
+ if ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
+ else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid;
+ else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
+ }
+ else if ( strcmp(tagname, "ps:") != 0 )
+ {
+ Warning("%s - %s", nc_strerror(status), varname);
+ }
- return ncvarid;
+ if ( lstop ) break;
+ }
+ }
}
static
-void scale_add(size_t size, double *data, double addoffset, double scalefactor)
+bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
{
- int laddoffset;
- int lscalefactor;
-
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+ bool status = false;
+ int ncfvarid = ncvarid;
+ ncvar_t *ncvar = &ncvars[ncvarid];
- if ( laddoffset || lscalefactor )
+ if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 )
{
- for (size_t i = 0; i < size; ++i )
+ cdiConvention = CDI_CONVENTION_CF;
+
+ status = true;
+ ncvar->zaxistype = ZAXIS_HYBRID;
+ int dimid = ncvar->dimids[0];
+ size_t dimlen = ncdims[dimid].len;
+
+ int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1;
+ if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
+ scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1);
+ if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
+ if ( bvarid1 != -1 ) ncvars[bvarid1].isvar = FALSE;
+ if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
+
+ if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
{
- if ( lscalefactor ) data[i] *= scalefactor;
- if ( laddoffset ) data[i] += addoffset;
+ ncfvarid = ncvar->bounds;
+ int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1;
+ if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
+ scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2);
+ if ( apvarid2 != -1 && bvarid2 != -1 )
+ {
+ ncvars[apvarid2].isvar = FALSE;
+ ncvars[bvarid2].isvar = FALSE;
+
+ if ( dimid == ncvars[apvarid2].dimids[0] && ncdims[ncvars[apvarid2].dimids[1]].len == 2 )
+ {
+ double abuf[dimlen*2], bbuf[dimlen*2];
+ cdf_get_var_double(ncid, apvarid2, abuf);
+ cdf_get_var_double(ncid, bvarid2, bbuf);
+ /*
+ for ( int i = 0; i < dimlen; ++i )
+ printf("%d %g %g %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]);
+ */
+ size_t vctsize = (dimlen+1)*2;
+ double *vct = (double *) Malloc(vctsize * sizeof(double));
+ for ( size_t i = 0; i < dimlen; ++i )
+ {
+ vct[i] = abuf[i*2];
+ vct[i+dimlen+1] = bbuf[i*2];
+ }
+ vct[dimlen] = abuf[dimlen*2-1];
+ vct[dimlen*2+1] = bbuf[dimlen*2-1];
+
+ ncvar->vct = vct;
+ ncvar->vctsize = vctsize;
+ }
+ }
}
}
+
+ return status;
}
+
static
-void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
+int isGaussGrid(size_t ysize, double yinc, const double *yvals)
{
- int vlistID = streamptr->vlistID;
- int tsID = streamptr->curTsID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- int gridindex = vlistGridIndex(vlistID, gridID);
-
- if ( CDI_Debug ) Message("tsID = %d", tsID);
+ int lgauss = FALSE;
+ double *yv, *yw;
- int xid = UNDEFID, yid = UNDEFID;
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfReadGridTraj(streamptr, gridID);
- }
- else
+ if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */
{
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- int zid = streamptr->zaxisID[zaxisindex];
+ size_t i;
+ yv = (double *) Malloc(ysize*sizeof(double));
+ yw = (double *) Malloc(ysize*sizeof(double));
+ gaussaw(yv, yw, ysize);
+ Free(yw);
+ for ( i = 0; i < ysize; i++ )
+ yv[i] = asin(yv[i])/M_PI*180.0;
- int ndims = 0;
-#define addDimension(startCoord, length) do \
- { \
- (*start)[ndims] = startCoord; \
- (*count)[ndims] = length; \
- ndims++; \
- } while(0)
- if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
- if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
- if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
- if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
-#undef addDimension
+ for ( i = 0; i < ysize; i++ )
+ if ( fabs(yv[i] - yvals[i]) >
+ ((yv[0] - yv[1])/500) ) break;
- assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
- assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+ if ( i == ysize ) lgauss = TRUE;
- if ( CDI_Debug )
- for (int idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+ /* check S->N */
+ if ( lgauss == FALSE )
+ {
+ for ( i = 0; i < ysize; i++ )
+ if ( fabs(yv[i] - yvals[ysize-i-1]) >
+ ((yv[0] - yv[1])/500) ) break;
+
+ if ( i == ysize ) lgauss = TRUE;
+ }
+
+ Free(yv);
+ }
+
+ return (lgauss);
}
-//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
-//Returns the number of missing + out-of-range values encountered.
static
-size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
- {
- const bool haveOffset = IS_NOT_EQUAL(offset, 0);
- const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
- size_t missValCount = 0;
-
- if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
- if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
+void printNCvars(const ncvar_t *ncvars, int nvars, const char *oname)
+{
+ char axis[7];
+ int ncvarid, i;
+ int ndim;
+ static const char iaxis[] = {'t', 'z', 'y', 'x'};
- bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
- assert(!haveRangeCheck || haveMissVal);
+ fprintf(stderr, "%s:\n", oname);
- switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
- | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
{
- case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] * scaleFactor + offset;
- }
- break;
- case 13: /* haveRangeCheck & haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] + offset;
- }
- break;
- case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
+ ndim = 0;
+ if ( ncvars[ncvarid].isvar )
{
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] * scaleFactor;
+ axis[ndim++] = 'v';
+ axis[ndim++] = ':';
+ for ( i = 0; i < ncvars[ncvarid].ndims; i++ )
+ {/*
+ if ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0];
+ else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1];
+ else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2];
+ else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3];
+ else
+ */
+ if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0];
+ else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1];
+ else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2];
+ else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3];
+ else axis[ndim++] = '?';
+ }
}
- break;
- case 9: /* haveRangeCheck & haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
+ else
{
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal : data[i];
+ axis[ndim++] = 'c';
+ axis[ndim++] = ':';
+ if ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0];
+ else if ( ncvars[ncvarid].islev ) axis[ndim++] = iaxis[1];
+ else if ( ncvars[ncvarid].islat ) axis[ndim++] = iaxis[2];
+ else if ( ncvars[ncvarid].islon ) axis[ndim++] = iaxis[3];
+ else axis[ndim++] = '?';
}
- break;
- case 7: /* haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = data[i] * scaleFactor + offset;
- break;
- case 6: /* haveOffset & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = data[i] * scaleFactor + offset;
- break;
- case 5: /* haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] += offset;
- break;
- case 4: /* haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] += offset;
- break;
- case 3: /* haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] *= scaleFactor;
- break;
- case 2: /* haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] *= scaleFactor;
- break;
- case 1: /* haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
- break;
- }
- return missValCount;
+ axis[ndim++] = 0;
+
+ fprintf(stderr, "%3d %3d %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name);
+ }
}
static
-size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
- {
- const bool haveOffset = IS_NOT_EQUAL(offset, 0);
- const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
- size_t missValCount = 0;
-
- if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
- if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
+void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
+ int timedimid, int modelID, int format)
+{
+ int ncid;
+ int ncdimid;
+ int nvdims, nvatts;
+ int *dimidsp;
+ int iatt;
+ nc_type xtype, atttype;
+ size_t attlen;
+ char name[CDI_MAX_NAME];
+ char attname[CDI_MAX_NAME];
+ const int attstringlen = 8192; char attstring[8192];
- bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
- assert(!haveRangeCheck || haveMissVal);
+ int nchecked_vars = 0;
+ enum { max_check_vars = 9 };
+ char *checked_vars[max_check_vars];
+ for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL;
- switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
- | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
{
- case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] * scaleFactor + offset);
- }
- break;
- case 13: /* haveRangeCheck & haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
+ ncid = ncvars[ncvarid].ncid;
+ dimidsp = ncvars[ncvarid].dimids;
+
+ cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
+ strcpy(ncvars[ncvarid].name, name);
+
+ for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ )
+ ncvars[ncvarid].dimtype[ncdimid] = -1;
+
+ ncvars[ncvarid].xtype = xtype;
+ ncvars[ncvarid].ndims = nvdims;
+
+#if defined (HAVE_NETCDF4)
+ if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
{
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] + offset);
- }
- break;
- case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] * scaleFactor);
- }
- break;
- case 9: /* haveRangeCheck & haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal : data[i];
- }
- break;
- case 7: /* haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] * scaleFactor + offset);
- break;
- case 6: /* haveOffset & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] * scaleFactor + offset);
- break;
- case 5: /* haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] + offset);
- break;
- case 4: /* haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] + offset);
- break;
- case 3: /* haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] * scaleFactor);
- break;
- case 2: /* haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] * scaleFactor);
- break;
- case 1: /* haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
- break;
- }
-
- return missValCount;
-}
-
-static void
-cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
-{
- const double *pdata_dp = (const double *) data;
- double *mdata_dp = NULL;
- double *sdata_dp = NULL;
- const float *pdata_sp = (const float *) data;
- float *mdata_sp = NULL;
- float *sdata_sp = NULL;
-
- /* if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
- {
- bool laddoffset, lscalefactor;
- double addoffset, scalefactor;
- double missval;
-
- addoffset = vlistInqVarAddoffset(vlistID, varID);
- scalefactor = vlistInqVarScalefactor(vlistID, varID);
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
- missval = vlistInqVarMissval(vlistID, varID);
+ char buf[CDI_MAX_NAME];
+ int shuffle, deflate, deflate_level;
+ size_t chunks[nvdims];
+ int storage_in;
+ nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level);
+ if ( deflate > 0 ) ncvars[ncvarid].deflate = 1;
- if ( laddoffset || lscalefactor )
- {
- if ( memtype == MEMTYPE_FLOAT )
+ if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR )
{
- mdata_sp = (float *) Malloc((size_t)nvals*sizeof(float));
- memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof (float));
- pdata_sp = mdata_sp;
-
- if ( nmiss > 0 )
+ if ( storage_in == NC_CHUNKED )
{
- for (long i = 0; i < nvals; i++ )
+ ncvars[ncvarid].chunked = 1;
+ for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
+ if ( CDI_Debug )
{
- double temp = mdata_sp[i];
- if ( !DBL_IS_EQUAL(temp, missval) )
- {
- if ( laddoffset ) temp -= addoffset;
- if ( lscalefactor ) temp /= scalefactor;
- mdata_sp[i] = (float)temp;
- }
+ fprintf(stderr, "%s: chunking %d %d %d chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED);
+ for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
+ fprintf(stderr, "\n");
}
- }
- else
- {
- for (long i = 0; i < nvals; i++ )
+ strcat(ncvars[ncvarid].extra, "chunks=");
+ for ( int i = nvdims-1; i >= 0; --i )
{
- double temp = mdata_sp[i];
- if ( laddoffset ) temp -= addoffset;
- if ( lscalefactor ) temp /= scalefactor;
- mdata_sp[i] = (float)temp;
+ sprintf(buf, "%ld", (long) chunks[i]);
+ strcat(ncvars[ncvarid].extra, buf);
+ if ( i > 0 ) strcat(ncvars[ncvarid].extra, "x");
}
+ strcat(ncvars[ncvarid].extra, " ");
}
}
+ }
+#endif
+
+ if ( nvdims > 0 )
+ {
+ if ( timedimid == dimidsp[0] )
+ {
+ ncvars[ncvarid].tsteptype = TSTEP_INSTANT;
+ cdfSetDim(ncvars, ncvarid, 0, T_AXIS);
+ }
else
{
- mdata_dp = (double *) Malloc((size_t)nvals * sizeof(double));
- memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof(double));
- pdata_dp = mdata_dp;
-
- if ( nmiss > 0 )
- {
- for (long i = 0; i < nvals; i++ )
- {
- if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
- {
- if ( laddoffset ) mdata_dp[i] -= addoffset;
- if ( lscalefactor ) mdata_dp[i] /= scalefactor;
- }
- }
- }
- else
+ for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ )
{
- for (long i = 0; i < nvals; i++ )
+ if ( timedimid == dimidsp[ncdimid] )
{
- if ( laddoffset ) mdata_dp[i] -= addoffset;
- if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+ Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
+ ncvars[ncvarid].isvar = FALSE;
}
}
}
}
- if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
- dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
+ for ( iatt = 0; iatt < nvatts; iatt++ )
{
- if ( memtype == MEMTYPE_FLOAT )
+ cdf_inq_attname(ncid, ncvarid, iatt, attname);
+ cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
+ cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+
+ if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) )
{
- if ( mdata_sp == NULL )
+ cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname);
+ }
+ else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname);
+ }
+ else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
+ }
+ else if ( strcmp(attname, "calendar") == 0 )
+ {
+ ncvars[ncvarid].calendar = TRUE;
+ }
+ else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
+ {
+ char paramstr[32];
+ int pnum = 0, pcat = 255, pdis = 255;
+ cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr);
+ sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis);
+ ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
+ {
+ int tablenum;
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
+ if ( tablenum > 0 )
{
- mdata_sp = (float *) Malloc((size_t)nvals * sizeof(float));
- memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof(float));
- pdata_sp = mdata_sp;
+ ncvars[ncvarid].tabnum = tablenum;
+ ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL);
+ if ( ncvars[ncvarid].tableID == CDI_UNDEFID )
+ ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL);
+ }
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ if ( memcmp(attstring, "Triangular", attlen) == 0 )
+ ncvars[ncvarid].gridtype = GRID_SPECTRAL;
+ }
+ else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ strtolower(attstring);
+
+ if ( strcmp(attstring, "gaussian reduced") == 0 )
+ ncvars[ncvarid].gridtype = GRID_GAUSSIAN_REDUCED;
+ else if ( strcmp(attstring, "gaussian") == 0 )
+ ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
+ else if ( strncmp(attstring, "spectral", 8) == 0 )
+ ncvars[ncvarid].gridtype = GRID_SPECTRAL;
+ else if ( strncmp(attstring, "fourier", 7) == 0 )
+ ncvars[ncvarid].gridtype = GRID_FOURIER;
+ else if ( strcmp(attstring, "trajectory") == 0 )
+ ncvars[ncvarid].gridtype = GRID_TRAJECTORY;
+ else if ( strcmp(attstring, "generic") == 0 )
+ ncvars[ncvarid].gridtype = GRID_GENERIC;
+ else if ( strcmp(attstring, "cell") == 0 )
+ ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
+ else if ( strcmp(attstring, "unstructured") == 0 )
+ ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
+ else if ( strcmp(attstring, "curvilinear") == 0 )
+ ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
+ else if ( strcmp(attstring, "sinusoidal") == 0 )
+ ;
+ else if ( strcmp(attstring, "laea") == 0 )
+ ;
+ else if ( strcmp(attstring, "lcc2") == 0 )
+ ;
+ else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear
+ ;
+ else
+ {
+ static int warn = TRUE;
+ if ( warn )
+ {
+ warn = FALSE;
+ Warning("NetCDF attribute grid_type='%s' unsupported!", attstring);
+ }
}
- for (long i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ strtolower(attstring);
- if ( dtype == DATATYPE_UINT8 )
+ if ( strcmp(attstring, "toa") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_TOA;
+ else if ( strcmp(attstring, "cloudbase") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_BASE;
+ else if ( strcmp(attstring, "cloudtop") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_TOP;
+ else if ( strcmp(attstring, "isotherm0") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_ISOTHERM_ZERO;
+ else if ( strcmp(attstring, "seabottom") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_SEA_BOTTOM;
+ else if ( strcmp(attstring, "lakebottom") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_LAKE_BOTTOM;
+ else if ( strcmp(attstring, "sedimentbottom") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM;
+ else if ( strcmp(attstring, "sedimentbottomta") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;
+ else if ( strcmp(attstring, "sedimentbottomtw") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;
+ else if ( strcmp(attstring, "mixlayer") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_MIX_LAYER;
+ else if ( strcmp(attstring, "atmosphere") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_ATMOSPHERE;
+ else
{
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
+ static int warn = TRUE;
+ if ( warn )
{
- for ( long i = 0; i < nvals; ++i )
- if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
+ warn = FALSE;
+ Warning("NetCDF attribute level_type='%s' unsupported!", attstring);
}
}
+
+ cdfSetVar(ncvars, ncvarid, TRUE);
}
- else
+ else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
{
- if ( mdata_dp == NULL )
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+ }
+ else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+ }
+ else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position);
+ }
+ else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
+ /*
+ if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
+ if ( ncvars[ncvarid].addoffset != 0 )
+ Warning("attribute add_offset not supported for atttype %d", atttype);
+ */
+ /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
+ /*
+ if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
+ if ( ncvars[ncvarid].scalefactor != 1 )
+ Warning("attribute scale_factor not supported for atttype %d", atttype);
+ */
+ /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ int ncboundsid;
+ int status = nc_inq_varid(ncid, attstring, &ncboundsid);
+ if ( status == NC_NOERR )
{
- mdata_dp = (double *) Malloc((size_t)nvals * sizeof (double));
- memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof (double));
- pdata_dp = mdata_dp;
+ ncvars[ncvarid].climatology = TRUE;
+ ncvars[ncvarid].bounds = ncboundsid;
+ cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ }
+ else
+ Warning("%s - %s", nc_strerror(status), attstring);
+ }
+ else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ int ncboundsid;
+ int status = nc_inq_varid(ncid, attstring, &ncboundsid);
+ if ( status == NC_NOERR )
+ {
+ ncvars[ncvarid].bounds = ncboundsid;
+ cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
+ cdfSetVar(ncvars, ncvarid, FALSE);
}
+ else
+ Warning("%s - %s", nc_strerror(status), attstring);
+ }
+ else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 )
+ {
+ ncvars[ncvarid].lformulaterms = TRUE;
+ }
+ else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 )
+ {
+ ncvars[ncvarid].lformula = TRUE;
+ }
+ else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
+ {
+ char *cell_measures = NULL, *cell_var = NULL;
- for (long i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ char *pstring = attstring;
- if ( dtype == DATATYPE_UINT8 )
+ while ( isspace((int) *pstring) ) pstring++;
+ cell_measures = pstring;
+ while ( isalnum((int) *pstring) ) pstring++;
+ *pstring++ = 0;
+ while ( isspace((int) *pstring) ) pstring++;
+ cell_var = pstring;
+ while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
+ *pstring++ = 0;
+ /*
+ printf("cell_measures >%s<\n", cell_measures);
+ printf("cell_var >%s<\n", cell_var);
+ */
+ if ( memcmp(cell_measures, "area", 4) == 0 )
{
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
+ int nc_cell_id;
+ int status = nc_inq_varid(ncid, cell_var, &nc_cell_id);
+ if ( status == NC_NOERR )
{
- for (long i = 0; i < nvals; ++i )
- if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
+ ncvars[ncvarid].cellarea = nc_cell_id;
+ /* ncvars[nc_cell_id].isvar = UNDEFID; */
+ cdfSetVar(ncvars, nc_cell_id, FALSE);
}
+ else
+ Warning("%s - %s", nc_strerror(status), cell_var);
}
- }
- }
-
- if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
- {
- double fmin, fmax;
- fmin = 1.0e200;
- fmax = -1.0e200;
- for ( long i = 0; i < nvals; ++i )
- {
- if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
+ else
{
- if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
- if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
+ Warning("%s has an unexpected contents: %s", attname, cell_measures);
}
+ cdfSetVar(ncvars, ncvarid, TRUE);
}
- Message("nvals = %d, nmiss = %d, missval = %g, minval = %g, maxval = %g",
- nvals, nmiss, missval, fmin, fmax);
- }
- }
-
- if ( swapxy )
- {
- if ( memtype == MEMTYPE_FLOAT )
- {
- /* malloc and the loop imply nvals >= ysize * xsize,
- * but that is not checked and the types don't match */
- sdata_sp = (float *) Malloc((size_t)nvals * sizeof (float));
- for ( size_t j = 0; j < ysize; ++j )
- for ( size_t i = 0; i < xsize; ++i )
- sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
- pdata_sp = sdata_sp;
- }
- else
- {
- sdata_dp = (double *) Malloc((size_t)nvals * sizeof (double));
- for ( size_t j = 0; j < ysize; ++j )
- for ( size_t i = 0; i < xsize; ++i )
- sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
- pdata_dp = sdata_dp;
- }
- }
+ /*
+ else if ( strcmp(attname, "coordinates") == 0 )
+ {
+ char *pstring, *xvarname = NULL, *yvarname = NULL;
- if ( memtype == MEMTYPE_FLOAT )
- cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
- else
- cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ pstring = attstring;
- if ( mdata_dp ) Free(mdata_dp);
- if ( sdata_dp ) Free(sdata_dp);
- if ( mdata_sp ) Free(mdata_sp);
- if ( sdata_sp ) Free(sdata_sp);
-}
+ while ( isspace((int) *pstring) ) pstring++;
+ xvarname = pstring;
+ while ( isgraph((int) *pstring) ) pstring++;
+ *pstring++ = 0;
+ while ( isspace((int) *pstring) ) pstring++;
+ yvarname = pstring;
+ while ( isgraph((int) *pstring) ) pstring++;
+ *pstring++ = 0;
+ cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid);
+ cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid);
-void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
-{
- int fileID;
- int gridID;
- int zaxisID;
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
- int ncvarid;
- size_t xsize = 0, ysize = 0;
- size_t size;
- size_t start[5];
- size_t count[5];
- long nvals;
- int swapxy = FALSE;
- int ndims = 0;
- int idim;
- int tsteptype;
- int gridindex, zaxisindex;
- int dtype;
- int vlistID;
+ cdfSetVar(ncvars, ncvars[ncvarid].xvarid, FALSE);
+ cdfSetVar(ncvars, ncvars[ncvarid].yvarid, FALSE);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ */
+ else if ( (strcmp(attname, "associate") == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
+ {
+ int status;
+ char *varname = NULL;
+ int lstop = FALSE;
+ int dimvarid;
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ char *pstring = attstring;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ for ( int i = 0; i < MAX_COORDVARS; i++ )
+ {
+ while ( isspace((int) *pstring) ) pstring++;
+ if ( *pstring == 0 ) break;
+ varname = pstring;
+ while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+ if ( *pstring == 0 ) lstop = TRUE;
+ *pstring++ = 0;
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
+ status = nc_inq_varid(ncid, varname, &dimvarid);
+ if ( status == NC_NOERR )
+ {
+ cdfSetVar(ncvars, dimvarid, FALSE);
+ if ( cdiIgnoreAttCoordinates == FALSE )
+ {
+ ncvars[ncvarid].coordvarids[i] = dimvarid;
+ ncvars[ncvarid].ncoordvars++;
+ }
+ }
+ else
+ {
+ int k;
+ for ( k = 0; k < nchecked_vars; ++k )
+ if ( strcmp(checked_vars[k], varname) == 0 ) break;
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+ if ( k == nchecked_vars )
+ {
+ if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname);
+ Warning("%s - %s", nc_strerror(status), varname);
+ }
+ }
- ncvarid = cdfDefVar(streamptr, varID);
+ if ( lstop ) break;
+ }
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
- gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfWriteGridTraj(streamptr, gridID);
- }
- else
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
-
- zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
-
- if ( tsteptype != TSTEP_CONSTANT )
- {
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
- }
- if ( zid != UNDEFID )
- {
- start[ndims] = 0;
- count[ndims] = (size_t)zaxisInqSize(zaxisID);
- ndims++;
- }
- if ( yid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, yid, &size);
- /* count[ndims] = gridInqYsize(gridID); */
- count[ndims] = size;
- ndims++;
- }
- if ( xid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, xid, &size);
- /* count[ndims] = gridInqXsize(gridID); */
- count[ndims] = size;
- ndims++;
- }
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
+ {
+ int status;
+ char *varname = NULL;
+ int lstop = FALSE;
+ int dimvarid;
- if ( CDI_Debug )
- for (idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ char *pstring = attstring;
- if ( streamptr->ncmode == 1 )
- {
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
- }
+ for ( int i = 0; i < MAX_AUXVARS; i++ )
+ {
+ while ( isspace((int) *pstring) ) pstring++;
+ if ( *pstring == 0 ) break;
+ varname = pstring;
+ while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
+ if ( *pstring == 0 ) lstop = TRUE;
+ *pstring++ = 0;
- dtype = vlistInqVarDatatype(vlistID, varID);
+ status = nc_inq_varid(ncid, varname, &dimvarid);
+ if ( status == NC_NOERR )
+ {
+ cdfSetVar(ncvars, dimvarid, FALSE);
+ // if ( cdiIgnoreAttCoordinates == FALSE )
+ {
+ ncvars[ncvarid].auxvarids[i] = dimvarid;
+ ncvars[ncvarid].nauxvars++;
+ }
+ }
+ else
+ Warning("%s - %s", nc_strerror(status), varname);
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
+ if ( lstop ) break;
+ }
- nvals = gridInqSize(gridID)*zaxisInqSize(zaxisID);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ int nc_gmap_id;
+ int status = nc_inq_varid(ncid, attstring, &nc_gmap_id);
+ if ( status == NC_NOERR )
+ {
+ ncvars[ncvarid].gmapid = nc_gmap_id;
+ cdfSetVar(ncvars, ncvars[ncvarid].gmapid, FALSE);
+ }
+ else
+ Warning("%s - %s", nc_strerror(status), attstring);
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ strtolower(attstring);
-}
+ if ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN;
+ else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP;
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
+ ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
+ }
+ }
+ else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval);
+ ncvars[ncvarid].deffillval = TRUE;
+ /* cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
+ ncvars[ncvarid].defmissval = TRUE;
+ /* cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 )
+ {
+ if ( ncvars[ncvarid].lvalidrange == FALSE )
+ {
+ extern int cdiIgnoreValidRange;
+ int lignore = FALSE;
+ if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+ if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
+ ncvars[ncvarid].lvalidrange = TRUE;
+ if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 )
+ ncvars[ncvarid].lunsigned = TRUE;
+ /* cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( lignore )
+ {
+ Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name);
+ }
+ }
+ }
+ else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 )
+ {
+ if ( ncvars[ncvarid].lvalidrange == FALSE )
+ {
+ extern int cdiIgnoreValidRange;
+ int lignore = FALSE;
+ if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+ if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
+ ncvars[ncvarid].lvalidrange = TRUE;
+ }
+ else if ( lignore )
+ {
+ Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name);
+ }
+ }
+ }
+ else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 )
+ {
+ if ( ncvars[ncvarid].lvalidrange == FALSE )
+ {
+ extern int cdiIgnoreValidRange;
+ int lignore = FALSE;
+ if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
+ if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
+ ncvars[ncvarid].lvalidrange = TRUE;
+ }
+ else if ( lignore )
+ {
+ Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name);
+ }
+ }
+ }
+ else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ strtolower(attstring);
-void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
- const int rect[][2], const void *data, int nmiss)
-{
- int fileID;
- int gridID;
- int zaxisID;
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
- int ncvarid;
- size_t xsize = 0, ysize = 0;
- size_t start[5];
- size_t count[5];
- long nvals;
- int swapxy = FALSE;
- int ndims = 0;
- int idim;
- int tsteptype;
- int gridindex, zaxisindex;
- int dtype;
- int vlistID;
- int streamID = streamptr->self;
+ if ( memcmp(attstring, "true", 4) == 0 )
+ {
+ ncvars[ncvarid].lunsigned = TRUE;
+ /*
+ ncvars[ncvarid].lvalidrange = TRUE;
+ ncvars[ncvarid].validrange[0] = 0;
+ ncvars[ncvarid].validrange[1] = 255;
+ */
+ }
+ /* cdfSetVar(ncvars, ncvarid, TRUE); */
+ }
+ else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ strtolower(attstring);
- if ( CDI_Debug )
- Message("streamID = %d varID = %d", streamID, varID);
+ if ( memcmp(attstring, "ignore", 6) == 0 )
+ {
+ ncvars[ncvarid].ignore = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ }
+ }
+ else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ attlen = strlen(attstring);
- vlistID = streamInqVlist(streamID);
- fileID = streamInqFileID(streamID);
+ if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 )
+ {
+ Warning("Unexpected axis attribute length for %s, ignored!", name);
+ }
+ else if ( nvdims == 0 && attlen == 1 )
+ {
+ if ( attstring[0] == 'z' || attstring[0] == 'Z' )
+ {
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ ncvars[ncvarid].islev = TRUE;
+ }
+ }
+ else
+ {
+ strtolower(attstring);
+ int i;
+ for ( i = 0; i < (int)attlen; ++i )
+ {
+ if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' &&
+ attstring[i] != 'y' && attstring[i] != 'x' )
+ {
+ Warning("Unexpected character in axis attribute for %s, ignored!", name);
+ break;
+ }
+ }
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug )
- Message("ntsteps = %ld", ntsteps);
+ if ( i == (int) attlen && (int) attlen == nvdims )
+ {
+ while ( attlen-- )
+ {
+ if ( (int) attstring[attlen] == 't' )
+ {
+ if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
+ cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS);
+ }
+ else if ( (int) attstring[attlen] == 'z' )
+ {
+ ncvars[ncvarid].zdim = dimidsp[attlen];
+ cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS);
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
+ }
+ }
+ else if ( (int) attstring[attlen] == 'y' )
+ {
+ ncvars[ncvarid].ydim = dimidsp[attlen];
+ cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS);
- ncvarid = cdfDefVar(streamptr, varID);
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS;
+ }
+ }
+ else if ( (int) attstring[attlen] == 'x' )
+ {
+ ncvars[ncvarid].xdim = dimidsp[attlen];
+ cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS);
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if ( ( strcmp(attname, "realization") == 0 ) ||
+ ( strcmp(attname, "ensemble_members") == 0 ) ||
+ ( strcmp(attname, "forecast_init_type") == 0 ) )
+ {
+ int temp;
- gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfWriteGridTraj(streamptr, gridID);
- }
- else
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
+ if( ncvars[ncvarid].ensdata == NULL )
+ ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) );
- zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &temp);
- if ( tsteptype != TSTEP_CONSTANT )
- {
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
- }
- if ( zid != UNDEFID )
- {
- int size = zaxisInqSize(zaxisID);
- xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
- && rect[2][1] <= size);
- start[ndims] = (size_t)rect[2][0];
- count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
- ndims++;
- }
- if ( yid != UNDEFID )
- {
- size_t size;
- cdf_inq_dimlen(fileID, yid, &size);
- xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
- && (size_t)rect[1][1] <= size);
- start[ndims] = (size_t)rect[1][0];
- count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
- ndims++;
- }
- if ( xid != UNDEFID )
- {
- size_t size;
- cdf_inq_dimlen(fileID, xid, &size);
- xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
- && (size_t)rect[0][1] <= size);
- start[ndims] = (size_t)rect[0][0];
- count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
- ndims++;
- }
+ if( strcmp(attname, "realization") == 0 )
+ ncvars[ncvarid].ensdata->ens_index = temp;
+ else if( strcmp(attname, "ensemble_members") == 0 )
+ ncvars[ncvarid].ensdata->ens_count = temp;
+ else if( strcmp(attname, "forecast_init_type") == 0 )
+ ncvars[ncvarid].ensdata->forecast_init_type = temp;
- if ( CDI_Debug )
- for (idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+ cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else
+ {
+ if ( ncvars[ncvarid].natts == 0 )
+ ncvars[ncvarid].atts
+ = (int *) Malloc((size_t)nvatts * sizeof (int));
- if ( streamptr->ncmode == 1 )
- {
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
+ ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
+ /*
+ int attrint;
+ double attrflt;
+ nc_type attrtype;
+ cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+ cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
+ if ( attlen == 1 && (attrtype == NC_INT || attrtype == NC_SHORT) )
+ {
+ cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint);
+ printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint);
+ }
+ else if ( attlen == 1 && (attrtype == NC_FLOAT || attrtype == NC_DOUBLE) )
+ {
+ cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt);
+ printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt);
+ }
+ else if ( attrtype == NC_CHAR )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ attstring[attlen] = 0;
+ printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring);
+ }
+ else
+ printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
+ */
+ }
+ }
}
- dtype = vlistInqVarDatatype(vlistID, varID);
-
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-
- nvals = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals,
- xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+ for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]);
}
static
-size_t min_size(size_t a, size_t b)
+void setDimType(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
{
- return a < b ? a : b;
-}
+ int ndims;
+ int ncvarid, ncdimid;
+ int i;
-static
-void transpose2dArrayDP(size_t inWidth, size_t inHeight, double* data)
-{
- const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
- // which should be a decent compromise on many architectures.
-
-#ifdef __cplusplus
- double *temp[inHeight];
- double *out[inWidth];
-
- temp[0] = (double *) Malloc(inHeight * inWidth * sizeof(double));
- out[0] = data;
-
- for(int i = 0; i < inWidth; i++)
- {
- out[i] = out[0] + (inHeight * i);
- }
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].isvar == TRUE )
+ {
+ int lxdim = 0, lydim = 0, lzdim = 0/* , ltdim = 0 */;
+ ndims = ncvars[ncvarid].ndims;
+ for ( i = 0; i < ndims; i++ )
+ {
+ ncdimid = ncvars[ncvarid].dimids[i];
+ if ( ncdims[ncdimid].dimtype == X_AXIS ) cdfSetDim(ncvars, ncvarid, i, X_AXIS);
+ else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
+ else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
+ else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdfSetDim(ncvars, ncvarid, i, T_AXIS);
+ }
- for(int i = 1; i < inHeight; i++)
- {
- temp[i] = temp[0] + (inWidth * i);
- }
- memcpy(temp[0], data, inHeight * inWidth * sizeof(double));
-#else
- double (*temp)[inWidth] = (double (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
- double (*out)[inHeight] = (double (*)[inHeight])data;
- memcpy(temp, data, inHeight*sizeof(*temp));
-#endif
-
- /*
- for ( size_t y = 0; y < inHeight; ++y )
- for ( size_t x = 0; x < inWidth; ++x )
- out[x][y] = temp[y][x];
- */
+ if ( CDI_Debug )
+ {
+ Message("var %d %s", ncvarid, ncvars[ncvarid].name);
+ for ( i = 0; i < ndims; i++ )
+ printf(" dim%d type=%d ", i, ncvars[ncvarid].dimtype[i]);
+ printf("\n");
+ }
- for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
- {
- for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
- {
- for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+ for ( i = 0; i < ndims; i++ )
+ {
+ if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = TRUE;
+ else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = TRUE;
+ else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = TRUE;
+ /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = TRUE; */
+ }
+
+ if ( lxdim == FALSE && ncvars[ncvarid].xvarid != UNDEFID )
{
- for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
- {
- out[x][y] = temp[y][x];
- }
+ if ( ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = TRUE;
}
- }
- }
- Free(temp[0]);
+ if ( lydim == FALSE && ncvars[ncvarid].yvarid != UNDEFID )
+ {
+ if ( ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = TRUE;
+ }
+
+ // if ( ndims > 1 )
+ for ( i = ndims-1; i >= 0; i-- )
+ {
+ if ( ncvars[ncvarid].dimtype[i] == -1 )
+ {
+ if ( lxdim == FALSE )
+ {
+ cdfSetDim(ncvars, ncvarid, i, X_AXIS);
+ lxdim = TRUE;
+ }
+ else if ( lydim == FALSE && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED )
+ {
+ cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
+ lydim = TRUE;
+ }
+ else if ( lzdim == FALSE )
+ {
+ cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
+ lzdim = TRUE;
+ }
+ }
+ }
+ }
+ }
}
+/* verify coordinate vars - first scan (dimname == varname) */
static
-void transpose2dArraySP(size_t inWidth, size_t inHeight, float* data)
+void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid)
{
- const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
- // which should be a decent compromise on many architectures.
-
-#ifndef __cplusplus
- float (*temp)[inWidth] = (float (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
- float (*out)[inHeight] = (float (*)[inHeight])data;
- memcpy(temp, data, inHeight*sizeof(*temp));
- #else
- float *temp[inWidth];
- temp[0] = (float *) Malloc(inWidth * inHeight * sizeof(float));
- for(int i = 1; i < inHeight; i++)
- {
- temp[i] = temp[0] + (inWidth * i);
- }
+ int ncdimid, ncvarid;
- float **out = (float **)data;
-#endif
-
- /*
- for ( size_t y = 0; y < inHeight; ++y )
- for ( size_t x = 0; x < inWidth; ++x )
- out[x][y] = temp[y][x];
- */
-
- for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
+ for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
{
- for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
- {
- for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
- {
- for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+ ncvarid = ncdims[ncdimid].ncvarid;
+ if ( ncvarid != -1 )
+ {
+ if ( ncvars[ncvarid].dimids[0] == timedimid )
+ {
+ ncvars[ncvarid].istime = TRUE;
+ ncdims[ncdimid].dimtype = T_AXIS;
+ continue;
+ }
+
+ if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue;
+
+ if ( ncvars[ncvarid].units[0] != 0 )
+ {
+ if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+ {
+ ncvars[ncvarid].islon = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
+ ncdims[ncdimid].dimtype = X_AXIS;
+ }
+ else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+ {
+ ncvars[ncvarid].islat = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
+ ncdims[ncdimid].dimtype = Y_AXIS;
+ }
+ else if ( unitsIsPressure(ncvars[ncvarid].units) )
+ {
+ ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
+ }
+ else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
+ {
+ if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+ else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+ else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+ else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+ else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
+ }
+ else if ( isDBLAxis(ncvars[ncvarid].longname) )
{
- out[x][y] = temp[y][x];
- }
+ ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
+ }
+ else if ( unitsIsHeight(ncvars[ncvarid].units) )
+ {
+ if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+ ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
+ else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+ ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
+ }
+ }
+ else
+ {
+ if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 ||
+ strcmp(ncvars[ncvarid].longname, "generalized height") == 0) &&
+ strcmp(ncvars[ncvarid].stdname, "height") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE;
}
- }
- }
- Free(temp);
+ if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
+ ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
+ {
+ if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
+ {
+ ncvars[ncvarid].islon = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
+ ncdims[ncdimid].dimtype = X_AXIS;
+ continue;
+ }
+ else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
+ {
+ ncvars[ncvarid].islat = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
+ ncdims[ncdimid].dimtype = Y_AXIS;
+ continue;
+ }
+ }
+
+ if ( ncvars[ncvarid].zaxistype != UNDEFID )
+ {
+ ncvars[ncvarid].islev = TRUE;
+ cdfSetVar(ncvars, ncvarid, FALSE);
+ cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
+ ncdims[ncdimid].dimtype = Z_AXIS;
+ }
+ }
+ }
}
+/* verify coordinate vars - second scan (all other variables) */
static
-void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
+void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
{
- int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
- int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
+ int ncvarid;
- (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
- switch ( gridInqType(gridId) )
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
{
- case GRID_TRAJECTORY:
- cdfReadGridTraj(streamptr, gridId);
- break;
-
- case GRID_UNSTRUCTURED:
- (*outDimIds)[0] = streamptr->xdimID[gridindex];
- break;
+ if ( ncvars[ncvarid].isvar == 0 )
+ {
+ if ( ncvars[ncvarid].units[0] != 0 )
+ {
+ if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+ {
+ ncvars[ncvarid].islon = TRUE;
+ continue;
+ }
+ else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
+ {
+ ncvars[ncvarid].islat = TRUE;
+ continue;
+ }
+ else if ( unitsIsPressure(ncvars[ncvarid].units) )
+ {
+ ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
+ continue;
+ }
+ else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
+ {
+ if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+ else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
+ else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+ else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
+ else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
+ ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
+ continue;
+ }
+ else if ( isDBLAxis(ncvars[ncvarid].longname) )
+ {
+ ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
+ continue;
+ }
+ else if ( unitsIsHeight(ncvars[ncvarid].units) )
+ {
+ if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+ ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
+ else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
+ ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
+ continue;
+ }
+ }
- default:
- (*outDimIds)[0] = streamptr->xdimID[gridindex];
- (*outDimIds)[1] = streamptr->ydimID[gridindex];
- break;
+ /* not needed anymore for rotated grids */
+ if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
+ ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
+ {
+ if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
+ {
+ ncvars[ncvarid].islon = TRUE;
+ continue;
+ }
+ else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
+ {
+ ncvars[ncvarid].islat = TRUE;
+ continue;
+ }
+ }
+ }
}
-
- int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
- int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
- (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
}
+#if defined (PROJECTION_TEST)
static
-int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
+void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID)
{
- if((*dimIds)[0] != UNDEFID) return 0;
- if((*dimIds)[1] != UNDEFID) return 0;
- int nvdims;
- cdf_inq_varndims(fileId, ncvarid, &nvdims);
- if(nvdims != 3) return 0;
+ int iatt, nvatts;
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
+ nc_type xtype;
- int varDimIds[3];
- cdf_inq_vardimid(fileId, ncvarid, varDimIds);
- size_t size = 0;
- if ( (*dimIds)[2] == varDimIds[2] )
- {
- cdf_inq_dimlen(fileId, varDimIds[1], &size);
- if ( size == 1 ) return 1;
- }
- else if ( (*dimIds)[2] == varDimIds[1] )
+ cdf_inq_varnatts(ncfileID, ncvarID, &nvatts);
+
+ for ( iatt = 0; iatt < nvatts; iatt++ )
{
- cdf_inq_dimlen(fileId, varDimIds[2], &size);
- if ( size == 1 ) return 2;
+ cdf_inq_attname(ncfileID, ncvarID, iatt, attname);
+ cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype);
+ cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen);
+
+ // printf("%s %d\n", attname, (int)attlen);
}
- return 0;
-}
+}
+#endif
static
-void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
+void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
{
- int tsID = streamptr->curTsID;
- if ( CDI_Debug ) Message("tsID = %d", tsID);
-
- int fileId = streamptr->fileID;
- int vlistId = streamptr->vlistID;
- int ncvarid = streamptr->vars[varId].ncvarid;
+ if ( ncvar->chunked )
+ {
+ int ndims = ncvar->ndims;
- int gridId = vlistInqVarGrid(vlistId, varId);
- int tsteptype = vlistInqVarTsteptype(vlistId, varId);
- int gridsize = gridInqSize(gridId);
+ if ( grid->type == GRID_UNSTRUCTURED )
+ {
+ if ( ncvar->chunks[ndims-1] == grid->size )
+ ncvar->chunktype = CHUNK_GRID;
+ else
+ ncvar->chunktype = CHUNK_AUTO;
+ }
+ else
+ {
+ if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 &&
+ grid->xsize == ncvar->chunks[ndims-1] &&
+ grid->ysize == ncvar->chunks[ndims-2] )
+ ncvar->chunktype = CHUNK_GRID;
+ else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] )
+ ncvar->chunktype = CHUNK_LINES;
+ else
+ ncvar->chunktype = CHUNK_AUTO;
+ }
+ }
+}
- streamptr->numvals += gridsize;
+static struct gridVirtTable cdfLazyGridVtable;
+static double *cdfPendingLoad;
+#ifdef HAVE_LIBPTHREAD
+static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT;
+#else
+static bool cdfLazyInitialized;
+#endif
- int dimIds[3]; //this array joins the old variables xid, yid, and zid
- cdfInqDimIds(streamptr, varId, &dimIds);
+struct cdfLazyGrid
+{
+ grid_t base;
+ const struct gridVirtTable *baseVtable;
+ struct {
+ int datasetNCId, varNCId;
+ } cellAreaGet, xBoundsGet, yBoundsGet;
+ struct xyValGet {
+ double scalefactor, addoffset;
+ size_t start[3], count[3], size, dimsize;
+ int datasetNCId, varNCId;
+ short ndims;
+ } xValsGet, yValsGet;
+#ifdef HAVE_LIBPTHREAD
+ pthread_mutex_t loadSerialize;
+#endif
+};
- int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
+#ifdef HAVE_LIBPTHREAD
+#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize))
+#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize))
+#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize))
+#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL)
+#else
+#define lock_lazy_load(plGrid)
+#define unlock_lazy_load(plGrid)
+#define destroy_lazy_load_lock(plGrid)
+#define init_lazy_load_lock(plGrid)
+#endif
- int dimorder[3];
- vlistInqVarDimorder(vlistId, varId, &dimorder);
+static void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid)
+{
+ lazyGrid->base.extraData = NULL;
+ if (lazyGrid->base.area == cdfPendingLoad)
+ lazyGrid->base.area = NULL;
+ if (lazyGrid->base.xvals == cdfPendingLoad)
+ lazyGrid->base.xvals = NULL;
+ if (lazyGrid->base.yvals == cdfPendingLoad)
+ lazyGrid->base.yvals = NULL;
+ if (lazyGrid->base.xbounds == cdfPendingLoad)
+ lazyGrid->base.xbounds = NULL;
+ if (lazyGrid->base.ybounds == cdfPendingLoad)
+ lazyGrid->base.ybounds = NULL;
+ destroy_lazy_load_lock(lazyGrid);
+}
- *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
+static void cdfLazyGridDelete(grid_t *grid)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy;
+ cdfLazyGridDestroy(cdfGrid);
+ baseDestroy(grid);
+}
- int ndims = 0;
+static void cdfLazyGridDestroyOnce(void)
+{
+ /*
+#ifdef HAVE_MMAP
+ size_t pgSize = cdiGetPageSize(false);
+ munmap(cdfPendingLoad, pgSize);
+#endif
+ */
+}
-#define addDimension(startIndex, extent) do { \
- (*start)[ndims] = startIndex; \
- (*count)[ndims] = extent; \
- ndims++; \
- } while(0)
+static void
+cdfLazyGridDefArea(grid_t *grid, const double *area)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->area == cdfPendingLoad)
+ grid->area = NULL;
+ cdfGrid->cellAreaGet.datasetNCId = -1;
+ cdfGrid->cellAreaGet.varNCId = -1;
+ cdfGrid->baseVtable->defArea(grid, area);
+ unlock_lazy_load(cdfGrid);
+}
- if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
- if ( skipdim == 1 ) addDimension(0, 1);
- for ( int id = 0; id < 3; ++id )
+static const double *
+cdfLazyGridInqAreaPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->area == cdfPendingLoad)
{
- size_t size;
- int curDimId = dimIds[dimorder[id]-1];
- if ( curDimId == UNDEFID ) continue;
- switch ( dimorder[id] )
- {
- Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
- case 1:
- case 2:
- cdf_inq_dimlen(fileId, curDimId, &size);
- addDimension(0, size);
- break;
+ grid->area = (double *)Malloc((size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId,
+ lazyGrid->cellAreaGet.varNCId, grid->area);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqAreaPtr(grid);
+}
- case 3:
- addDimension((size_t)levelId, 1);
- break;
+static void
+cdfLazyGridInqArea(grid_t *grid, double *area)
+{
+ grid->vtable->inqAreaPtr(grid);
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lazyGrid->baseVtable->inqArea(grid, area);
+}
- default:
- Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
- }
- }
- if ( skipdim == 2 ) addDimension(0, 1);
+static void
+cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp)
+{
+ double *grid_vals
+ = (double *)Malloc(valsGet->size * sizeof (double));
+ *valsp = grid_vals;
+ if ( valsGet->ndims == 3 )
+ cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId,
+ valsGet->start, valsGet->count, grid_vals);
+ else
+ cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals);
+ scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor);
+}
- assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
- assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
+static const double *
+cdfLazyGridInqXValsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->xvals == cdfPendingLoad)
+ cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->xvals);
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqXValsPtr(grid);
+}
-#undef addDimension
+static const double *
+cdfLazyGridInqYValsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->yvals == cdfPendingLoad)
+ cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->yvals);
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqYValsPtr(grid);
+}
- if ( CDI_Debug )
- for (int idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+static double
+cdfLazyGridInqXYVal(grid_t *grid, size_t index,
+ const struct xyValGet *valsGet, double *vals,
+ const double *(*inqValsPtr)(grid_t *gridptr))
+{
+ size_t size = valsGet->size;
+ double v;
+ if ( vals == cdfPendingLoad )
+ {
+ /* prevent full load if only first/last values get inspected */
+ if ( index == 0 || index == size - 1 )
+ {
+ size_t indexND[3];
+ if ( valsGet->ndims == 3 )
+ {
+ indexND[0] = 0;
+ indexND[1] = index / valsGet->count[2];
+ indexND[2] = index % valsGet->count[2];
+ }
+ else if ( valsGet->ndims == 2)
+ {
+ indexND[0] = index / (size_t)grid->xsize;
+ indexND[1] = index % (size_t)grid->xsize;
+ }
+ else
+ indexND[0] = index;
+ cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId,
+ indexND, &v);
+ }
+ else
+ {
+ const double *grid_vals = inqValsPtr(grid);
+ v = grid_vals[index];
+ }
+ }
+ else if ( vals )
+ v = vals[index];
+ else
+ v = 0.0;
+ return v;
+}
- int nvdims;
- cdf_inq_varndims(fileId, ncvarid, &nvdims);
+static void
+cdfLazyGridDefXVals(grid_t *grid, const double *vals)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->xvals == cdfPendingLoad)
+ grid->xvals = NULL;
+ cdfGrid->xValsGet.datasetNCId = -1;
+ cdfGrid->xValsGet.varNCId = -1;
+ cdfGrid->baseVtable->defXVals(grid, vals);
+ unlock_lazy_load(cdfGrid);
+}
- if ( nvdims != ndims )
- Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
+static void
+cdfLazyGridDefYVals(grid_t *grid, const double *vals)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->yvals == cdfPendingLoad)
+ grid->yvals = NULL;
+ cdfGrid->yValsGet.datasetNCId = -1;
+ cdfGrid->yValsGet.varNCId = -1;
+ cdfGrid->baseVtable->defYVals(grid, vals);
+ unlock_lazy_load(cdfGrid);
}
+static double
+cdfLazyGridInqXVal(grid_t *grid, int index)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet,
+ grid->xvals, grid->vtable->inqXValsPtr);
+ unlock_lazy_load(lazyGrid);
+ return rv;
+}
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+static double
+cdfLazyGridInqYVal(grid_t *grid, int index)
{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet,
+ grid->yvals, grid->vtable->inqYValsPtr);
+ unlock_lazy_load(lazyGrid);
+ return rv;
+}
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+static int
+cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
+ struct cdfLazyGrid *lazyGridTest)
+{
+ struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet,
+ *valsGetYRef = &lazyGridRef->yValsGet,
+ *valsGetXTest = &lazyGridTest->xValsGet,
+ *valsGetYTest = &lazyGridTest->yValsGet;
+ if (valsGetXRef->datasetNCId == -1
+ || valsGetXTest->datasetNCId == -1
+ || valsGetYRef->datasetNCId == -1
+ || valsGetYTest->datasetNCId == -1)
+ return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base,
+ &lazyGridTest->base);
+ return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId
+ || valsGetXRef->varNCId != valsGetXTest->varNCId
+ || valsGetYRef->datasetNCId != valsGetYTest->datasetNCId
+ || valsGetYRef->varNCId != valsGetYTest->varNCId;
+}
- int ncvarid = streamptr->vars[varID].ncvarid;
+static int
+cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
+{
+ int diff;
+ struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+ if (gridTest->vtable == &cdfLazyGridVtable)
+ diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+ else
+ diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest);
+ return diff;
+}
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
+static int
+cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest)
+{
+ int diff;
+ struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+ if (gridTest->vtable == &cdfLazyGridVtable)
+ diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+ else
+ diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest);
+ return diff;
+}
- size_t start[4];
- size_t count[4];
- cdfGetSlapDescription(streamptr, varID, &start, &count);
- cdf_get_vara_double(fileID, ncvarid, start, count, data);
+static const double *
+cdfLazyGridInqXBoundsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->xbounds == cdfPendingLoad)
+ {
+ grid->xbounds = (double *)Malloc((size_t)grid->nvertex
+ * (size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId,
+ lazyGrid->xBoundsGet.varNCId, grid->xbounds);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqXBoundsPtr(grid);
+}
- size_t size = (size_t)gridInqSize(gridID)*(size_t)zaxisInqSize(zaxisID);
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationDP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
+static void
+cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->xbounds == cdfPendingLoad)
+ grid->xbounds = NULL;
+ cdfGrid->xBoundsGet.datasetNCId = -1;
+ cdfGrid->xBoundsGet.varNCId = -1;
+ cdfGrid->baseVtable->defXBounds(grid, xbounds);
+ unlock_lazy_load(cdfGrid);
}
+static void
+cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->ybounds == cdfPendingLoad)
+ grid->ybounds = NULL;
+ cdfGrid->yBoundsGet.datasetNCId = -1;
+ cdfGrid->yBoundsGet.varNCId = -1;
+ cdfGrid->baseVtable->defYBounds(grid, ybounds);
+ unlock_lazy_load(cdfGrid);
+}
-void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
+static const double *
+cdfLazyGridInqYBoundsPtr(grid_t *grid)
{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->ybounds == cdfPendingLoad)
+ {
+ grid->ybounds = (double *)Malloc((size_t)grid->nvertex
+ * (size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId,
+ lazyGrid->yBoundsGet.varNCId, grid->ybounds);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqYBoundsPtr(grid);
+}
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+static void
+cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup,
+ *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig;
+ lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+ lazyGridDup->baseVtable = lazyGridOrig->baseVtable;
+ lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet;
+ lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet;
+ lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet;
+ lazyGridDup->xValsGet = lazyGridOrig->xValsGet;
+ lazyGridDup->yValsGet = lazyGridOrig->yValsGet;
+ init_lazy_load_lock(lazyGridDup);
+}
- int ncvarid = streamptr->vars[varID].ncvarid;
+static void
+cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ size_t nrowlon = (size_t)gridptrOrig->nrowlon;
+ size_t gridsize = (size_t)gridptrOrig->size;
+ int gridtype = gridptrOrig->type;
+ int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
+ if ( nrowlon )
+ {
+ gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+ memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
+ }
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ if ( gridptrOrig->xvals != NULL && gridptrOrig->xvals != cdfPendingLoad )
+ {
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize;
- size_t start[4];
- size_t count[4];
- cdfGetSlapDescription(streamptr, varID, &start, &count);
+ gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
+ }
- cdf_get_vara_float(fileID, ncvarid, start, count, data);
+ if ( gridptrOrig->yvals != NULL && gridptrOrig->yvals != cdfPendingLoad )
+ {
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize;
- size_t size = (size_t)gridInqSize(gridID) * (size_t)zaxisInqSize(zaxisID);
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationSP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
-}
+ gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
+ }
+ if ( gridptrOrig->xbounds != NULL && gridptrOrig->xbounds != cdfPendingLoad )
+ {
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
+ * (size_t)gridptrOrig->nvertex;
-void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
-{
- size_t start[4];
- size_t count[4];
+ gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
+ }
- if ( CDI_Debug )
- Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
+ if ( gridptrOrig->ybounds != NULL && gridptrOrig->ybounds != cdfPendingLoad )
+ {
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
+ * (size_t)gridptrOrig->nvertex;
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+ gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
+ }
- bool swapxy;
- cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+ {
+ if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad )
+ {
+ size_t size = gridsize;
- int ncvarid = streamptr->vars[varID].ncvarid;
- int gridId = vlistInqVarGrid(vlistID, varID);
- size_t gridsize = (size_t)gridInqSize(gridId);
- size_t xsize = (size_t)gridInqXsize(gridId);
- size_t ysize = (size_t)gridInqYsize(gridId);
+ gridptrDup->area = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double));
+ }
+ }
- if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
- {
- float *data_fp = (float *) Malloc(gridsize*sizeof(*data_fp));
- cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
- for ( size_t i = 0; i < gridsize; i++ )
- data[i] = (double) data_fp[i];
- Free(data_fp);
- }
- else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+ if ( gridptrOrig->mask != NULL )
{
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for ( size_t i = 0; i < gridsize; i++ )
- if ( data[i] < 0 ) data[i] += 256;
- }
+ size_t size = gridsize;
+
+ gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
+ memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
}
- else
+
+ if ( gridptrOrig->mask_gme != NULL )
{
- cdf_get_vara_double(fileID, ncvarid, start, count, data);
+ size_t size = gridsize;
+
+ gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
+ memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
}
+}
- if ( swapxy ) transpose2dArrayDP(ysize, xsize, data);
+static grid_t *
+cdfLazyGridCopy(grid_t *gridptrOrig)
+{
+ struct cdfLazyGrid *lazyGridDup
+ = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup));
+ gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+ gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base);
+ return &lazyGridDup->base;
+}
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationDP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
+static void
+cdfLazyGridInitOnce(void)
+{
+ cdfLazyGridVtable = cdiGridVtable;
+ cdfLazyGridVtable.destroy = cdfLazyGridDelete;
+ cdfLazyGridVtable.copy = cdfLazyGridCopy;
+ cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields;
+ cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields;
+ cdfLazyGridVtable.defArea = cdfLazyGridDefArea;
+ cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr;
+ cdfLazyGridVtable.inqArea = cdfLazyGridInqArea;
+ cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr;
+ cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr;
+ cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal;
+ cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal;
+ cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals;
+ cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals;
+ cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull;
+ cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO;
+ cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds;
+ cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds;
+ cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr;
+ cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr;
+ /* create inaccessible memory area, if possible, this serves as
+ * dummy value for pointers to data not yet loaded */
+ /*
+#ifdef HAVE_MMAP
+ {
+ size_t pgSize = cdiGetPageSize(false);
+ static const char devZero[] = "/dev/zero";
+ int fd = open(devZero, O_RDWR);
+ if (fd == -1)
+ SysError("Could not open %s to map anonymous memory", devZero);
+ void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0);
+ if (cdfInvalid == MAP_FAILED)
+ SysError("Could not mmap anonymous memory");
+ cdfPendingLoad = cdfInvalid;
+ int rc = close(fd);
+ if (rc == -1)
+ SysError("Could not close %s file handle %d after mapping anonymous"
+ " memory", devZero, fd);
+ }
+#else
+ */
+ cdfPendingLoad = (double *)&cdfPendingLoad;
+ //#endif
+ atexit(cdfLazyGridDestroyOnce);
+#ifndef HAVE_LIBPTHREAD
+ cdfLazyInitialized = true;
+#endif
}
-
-void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
+static void
+cdfBaseGridInit(grid_t *grid, int gridtype)
{
- size_t start[4];
- size_t count[4];
-
- if ( CDI_Debug )
- Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- bool swapxy;
- cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
-
- int ncvarid = streamptr->vars[varID].ncvarid;
- int gridId = vlistInqVarGrid(vlistID, varID);
- size_t gridsize = (size_t)gridInqSize(gridId);
- size_t xsize = (size_t)gridInqXsize(gridId);
- size_t ysize = (size_t)gridInqYsize(gridId);
-
- if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
- {
- double *data_dp = (double *) Malloc(gridsize*sizeof(*data_dp));
- cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
- for ( size_t i = 0; i < gridsize; i++ )
- data[i] = (float) data_dp[i];
- Free(data_dp);
- }
- else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
- {
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for ( size_t i = 0; i < gridsize; i++ )
- if ( data[i] < 0 ) data[i] += 256;
- }
- }
- else
- {
- cdf_get_vara_float(fileID, ncvarid, start, count, data);
- }
-
- if ( swapxy ) transpose2dArraySP(ysize, xsize, data);
-
- double missval = vlistInqVarMissval(vlistID, varID);
- bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationSP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
}
-
-void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+static void
+cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype)
{
- size_t xsize = 0, ysize = 0;
- size_t start[5];
- size_t count[5];
- int dimorder[3];
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
-
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
- int ncvarid = cdfDefVar(streamptr, varID);
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- vlistInqVarDimorder(vlistID, varID, &dimorder);
-
-
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfWriteGridTraj(streamptr, gridID);
- }
- else
- {
- int gridindex = vlistGridIndex(vlistID, gridID);
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
- {
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
- }
-
- int swapxy = (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID;
- /*
- printf("swapxy %d\n", swapxy);
- printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
- */
-
- size_t ndims = 0;
- if ( tsteptype != TSTEP_CONSTANT )
- {
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
- }
-
- for ( int id = 0; id < 3; ++id )
- {
- if ( dimorder[id] == 3 && zid != UNDEFID )
- {
- start[ndims] = (size_t)levelID;
- count[ndims] = 1;
- ndims++;
- }
- else if ( dimorder[id] == 2 && yid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, yid, &ysize);
- count[ndims] = ysize;
- ndims++;
- }
- else if ( dimorder[id] == 1 && xid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, xid, &xsize);
- count[ndims] = xsize;
- ndims++;
- }
- }
-
- if ( CDI_Debug )
- for (size_t idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-
- int dtype = vlistInqVarDatatype(vlistID, varID);
-
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-
- long nvals = gridInqSize(gridID);
+#ifdef HAVE_LIBPTHREAD
+ pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce);
+#else
+ if (cdfLazyInitialized) ; else cdfLazyGridInitOnce();
+#endif
+ cdfBaseGridInit(&grid->base, gridtype);
+ grid->baseVtable = grid->base.vtable;
+ grid->cellAreaGet.datasetNCId = -1;
+ grid->cellAreaGet.varNCId = -1;
+ grid->xValsGet.datasetNCId = -1;
+ grid->xValsGet.varNCId = -1;
+ grid->yValsGet.datasetNCId = -1;
+ grid->yValsGet.varNCId = -1;
+ grid->xBoundsGet.datasetNCId = -1;
+ grid->xBoundsGet.varNCId = -1;
+ grid->yBoundsGet.datasetNCId = -1;
+ grid->yBoundsGet.varNCId = -1;
+ grid->base.vtable = &cdfLazyGridVtable;
+ init_lazy_load_lock(grid);
+}
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+static void
+cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+ struct cdfLazyGrid *restrict grid = *gridpptr;
+ if (!grid)
+ *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid));
+ cdfLazyGridInit(grid, gridtype);
+}
+static void
+cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+ struct cdfLazyGrid *restrict grid = *gridpptr;
+ if (!grid)
+ *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t));
+ cdfBaseGridInit((grid_t*)grid, gridtype);
}
+/* define all input grids */
static
-void cdfCreateRecords(stream_t *streamptr, int tsID)
+void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used)
{
- int varID, levelID, recID, vrecID, zaxisID;
- int nlev, nvrecs;
-
- int vlistID = streamptr->vlistID;
+ int ltwarn = TRUE;
+ struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL;
+#define grid (&lazyGrid->base)
+#define proj (&lazyProj->base)
- if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return;
+ for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid )
+ {
+ if ( ncvars[ncvarid].isvar && ncvars[ncvarid].gridID == UNDEFID )
+ {
+ int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
+ int xdimid = -1, ydimid = -1;
+ int islon = 0, islat = 0;
+ int nxdims = 0, nydims = 0;
+ size_t size = 0;
+ size_t xsize = 0, ysize = 0;
+ double yinc = 0;
+ struct addIffNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 },
+ gridAdded = { .Id = CDI_UNDEFID, .isNew = 0 };
- if ( streamptr->tsteps[tsID].nallrecs > 0 ) return;
+ int ndims = ncvars[ncvarid].ndims;
+ for ( int i = 0; i < ndims; i++ )
+ {
+ if ( ncvars[ncvarid].dimtype[i] == X_AXIS && nxdims < 2 )
+ {
+ xdimids[nxdims] = ncvars[ncvarid].dimids[i];
+ nxdims++;
+ }
+ else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS && nydims < 2 )
+ {
+ ydimids[nydims] = ncvars[ncvarid].dimids[i];
+ nydims++;
+ }
+ }
- tsteps_t* sourceTstep = streamptr->tsteps;
- tsteps_t* destTstep = sourceTstep + tsID;
+ if ( nxdims == 2 )
+ {
+ xdimid = xdimids[1];
+ ydimid = xdimids[0];
+ }
+ else if ( nydims == 2 )
+ {
+ xdimid = ydimids[1];
+ ydimid = ydimids[0];
+ }
+ else
+ {
+ xdimid = xdimids[0];
+ ydimid = ydimids[0];
+ }
- int nvars = vlistNvars(vlistID);
- int nrecs = vlistNrecs(vlistID);
+ int xvarid = ncvars[ncvarid].xvarid != UNDEFID
+ ? ncvars[ncvarid].xvarid
+ : (xdimid != UNDEFID ? ncdims[xdimid].ncvarid : -1);
+ int yvarid = ncvars[ncvarid].yvarid != UNDEFID
+ ? ncvars[ncvarid].yvarid
+ : (ydimid != UNDEFID ? ncdims[ydimid].ncvarid : -1);
- if ( nrecs <= 0 ) return;
+ /*
+ if ( xdimid != UNDEFID )
+ xvarid = ncdims[xdimid].ncvarid;
+ if ( xvarid == UNDEFID && ncvars[ncvarid].xvarid != UNDEFID )
+ xvarid = ncvars[ncvarid].xvarid;
- if ( tsID == 0 )
- {
- nvrecs = nrecs; /* use all records at first timestep */
+ if ( ydimid != UNDEFID )
+ yvarid = ncdims[ydimid].ncvarid;
+ if ( yvarid == UNDEFID && ncvars[ncvarid].yvarid != UNDEFID )
+ yvarid = ncvars[ncvarid].yvarid;
+ */
- streamptr->nrecs += nrecs;
+ if ( xdimid != UNDEFID ) xsize = ncdims[xdimid].len;
+ if ( ydimid != UNDEFID ) ysize = ncdims[ydimid].len;
- destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
- destTstep->nrecs = nrecs;
- destTstep->nallrecs = nrecs;
- destTstep->recordSize = nrecs;
- destTstep->curRecID = UNDEFID;
- destTstep->recIDs = (int *) Malloc((size_t)nvrecs*sizeof (int));;
- for ( recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
+ if ( ydimid == UNDEFID && yvarid != UNDEFID )
+ {
+ if ( ncvars[yvarid].ndims == 1 )
+ {
+ ydimid = ncvars[yvarid].dimids[0];
+ ysize = ncdims[ydimid].len;
+ }
+ }
- record_t *records = destTstep->records;
+ if ( ncvars[ncvarid].gridtype == UNDEFID || ncvars[ncvarid].gridtype == GRID_GENERIC )
+ if ( xdimid != UNDEFID && xdimid == ydimid && nydims == 0 ) ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
- recID = 0;
- for ( varID = 0; varID < nvars; varID++ )
- {
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlev = zaxisInqSize(zaxisID);
- for ( levelID = 0; levelID < nlev; levelID++ )
+ if (CDI_netcdf_lazy_grid_load)
{
- recordInitEntry(&records[recID]);
- records[recID].varID = (short)varID;
- records[recID].levelID = (short)levelID;
- recID++;
+ cdfLazyGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
+ cdfLazyGridRenew(&lazyProj, GRID_PROJECTION);
}
- }
- }
- else if ( tsID == 1 )
- {
- nvrecs = 0;
- for ( varID = 0; varID < nvars; varID++ )
- {
- if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+ else
{
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nvrecs += zaxisInqSize(zaxisID);
+ cdfBaseGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
+ cdfBaseGridRenew(&lazyProj, GRID_PROJECTION);
}
- }
- streamptr->nrecs += nvrecs;
+ grid->prec = DATATYPE_FLT64;
+ grid->trunc = ncvars[ncvarid].truncation;
- destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
- destTstep->nrecs = nvrecs;
- destTstep->nallrecs = nrecs;
- destTstep->recordSize = nrecs;
- destTstep->curRecID = UNDEFID;
+ if ( ncvars[ncvarid].gridtype == GRID_TRAJECTORY )
+ {
+ if ( ncvars[ncvarid].xvarid == UNDEFID )
+ Error("Longitude coordinate undefined for %s!", ncvars[ncvarid].name);
+ if ( ncvars[ncvarid].yvarid == UNDEFID )
+ Error("Latitude coordinate undefined for %s!", ncvars[ncvarid].name);
+ }
+ else
+ {
+ size_t start[3], count[3];
+ int ltgrid = FALSE;
- memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
+ if ( xvarid != UNDEFID && yvarid != UNDEFID )
+ {
+ if ( ncvars[xvarid].ndims != ncvars[yvarid].ndims )
+ {
+ Warning("Inconsistent grid structure for variable %s!", ncvars[ncvarid].name);
+ ncvars[ncvarid].xvarid = UNDEFID;
+ ncvars[ncvarid].yvarid = UNDEFID;
+ xvarid = UNDEFID;
+ yvarid = UNDEFID;
+ }
- if ( nvrecs )
- {
- destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int));
- vrecID = 0;
- for ( recID = 0; recID < nrecs; recID++ )
- {
- varID = destTstep->records[recID].varID;
- if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
+ if ( ncvars[xvarid].ndims > 2 || ncvars[yvarid].ndims > 2 )
+ {
+ if ( ncvars[xvarid].ndims == 3 && ncvars[xvarid].dimids[0] == timedimid &&
+ ncvars[yvarid].ndims == 3 && ncvars[yvarid].dimids[0] == timedimid )
+ {
+ if ( ltwarn )
+ Warning("Time varying grids unsupported, using grid at time step 1!");
+ ltgrid = TRUE;
+ ltwarn = FALSE;
+ start[0] = start[1] = start[2] = 0;
+ count[0] = 1; count[1] = ysize; count[2] = xsize;
+ }
+ else
+ {
+ Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvars[ncvarid].name);
+ ncvars[ncvarid].xvarid = UNDEFID;
+ ncvars[ncvarid].yvarid = UNDEFID;
+ xvarid = UNDEFID;
+ yvarid = UNDEFID;
+ }
+ }
+ }
+
+ if ( xvarid != UNDEFID )
{
- destTstep->recIDs[vrecID++] = recID;
+ if ( ncvars[xvarid].ndims > 3 || (ncvars[xvarid].ndims == 3 && ltgrid == FALSE) )
+ {
+ Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims);
+ //ncvars[ncvarid].xvarid = UNDEFID;
+ xvarid = UNDEFID;
+ }
}
- }
- }
- }
- else
- {
- if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1);
- nvrecs = streamptr->tsteps[1].nrecs;
+ if ( yvarid != UNDEFID )
+ {
+ if ( ncvars[yvarid].ndims > 3 || (ncvars[yvarid].ndims == 3 && ltgrid == FALSE) )
+ {
+ Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims);
+ //ncvars[ncvarid].yvarid = UNDEFID;
+ yvarid = UNDEFID;
+ }
+ }
- streamptr->nrecs += nvrecs;
+ if ( xvarid != UNDEFID )
+ {
+ bool skipvar = true;
+ islon = ncvars[xvarid].islon;
+ ndims = ncvars[xvarid].ndims;
+ if ( ndims == 2 || ndims == 3 )
+ {
+ ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
+ size = xsize*ysize;
+ /* Check size of 2 dimensional coordinate variables */
+ int dimid = ncvars[xvarid].dimids[ndims-2];
+ size_t dimsize1 = ncdims[dimid].len;
+ dimid = ncvars[xvarid].dimids[ndims-1];
+ size_t dimsize2 = ncdims[dimid].len;
+ skipvar = dimsize1*dimsize2 != size;
+ }
+ else if ( ndims == 1 )
+ {
+ size = xsize;
+ /* Check size of 1 dimensional coordinate variables */
+ int dimid = ncvars[xvarid].dimids[0];
+ size_t dimsize = ncdims[dimid].len;
+ skipvar = dimsize != size;
+ }
+ else if ( ndims == 0 && xsize == 0 )
+ {
+ size = xsize = 1;
+ skipvar = false;
+ }
- destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t));
- destTstep->nrecs = nvrecs;
- destTstep->nallrecs = nrecs;
- destTstep->recordSize = nrecs;
- destTstep->curRecID = UNDEFID;
+ if ( skipvar )
+ {
+ Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
+ ncvars[ncvarid].isvar = -1;
+ continue;
+ }
- memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t));
+ if ( ncvars[xvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->xValsGet = (struct xyValGet){
+ .scalefactor = ncvars[xvarid].scalefactor,
+ .addoffset = ncvars[xvarid].addoffset,
+ .start = { start[0], start[1], start[2] },
+ .count = { count[0], count[1], count[2] },
+ .size = size,
+ .datasetNCId = ncvars[xvarid].ncid,
+ .varNCId = xvarid,
+ .ndims = (short)ndims,
+ };
+ grid->xvals = cdfPendingLoad;
+ }
+ else
+ {
+ grid->xvals = (double *) Malloc(size*sizeof(double));
+ if ( ltgrid )
+ cdf_get_vara_double(ncvars[xvarid].ncid, xvarid,
+ start, count, grid->xvals);
+ else
+ cdf_get_var_double(ncvars[xvarid].ncid, xvarid,
+ grid->xvals);
+ scale_add(size, grid->xvals,
+ ncvars[xvarid].addoffset,
+ ncvars[xvarid].scalefactor);
+ }
+ strcpy(grid->xname, ncvars[xvarid].name);
+ strcpy(grid->xlongname, ncvars[xvarid].longname);
+ strcpy(grid->xunits, ncvars[xvarid].units);
+ /* don't change the name !!! */
+ /*
+ if ( (len = strlen(grid->xname)) > 2 )
+ if ( grid->xname[len-2] == '_' && isdigit((int) grid->xname[len-1]) )
+ grid->xname[len-2] = 0;
+ */
+ }
- destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof(int));
+ if ( yvarid != UNDEFID )
+ {
+ bool skipvar = true;
+ islat = ncvars[yvarid].islat;
+ ndims = ncvars[yvarid].ndims;
+ if ( ndims == 2 || ndims == 3 )
+ {
+ ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
+ size = xsize*ysize;
+ /* Check size of 2 dimensional coordinate variables */
+ {
+ int dimid;
+ size_t dimsize1, dimsize2;
+ dimid = ncvars[yvarid].dimids[ndims-2];
+ dimsize1 = ncdims[dimid].len;
+ dimid = ncvars[yvarid].dimids[ndims-1];
+ dimsize2 = ncdims[dimid].len;
+ skipvar = dimsize1*dimsize2 != size;
+ }
+ }
+ else if ( ndims == 1 )
+ {
+ if ( (int) ysize == 0 ) size = xsize;
+ else size = ysize;
- memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int));
- }
-}
+ /* Check size of 1 dimensional coordinate variables */
+ {
+ int dimid;
+ size_t dimsize;
+ dimid = ncvars[yvarid].dimids[0];
+ dimsize = ncdims[dimid].len;
+ skipvar = dimsize != size;
+ }
+ }
+ else if ( ndims == 0 && ysize == 0 )
+ {
+ size = ysize = 1;
+ skipvar = false;
+ }
+ if ( skipvar )
+ {
+ Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
+ ncvars[ncvarid].isvar = -1;
+ continue;
+ }
-static
-int cdfTimeDimID(int fileID, int ndims, int nvars)
-{
- int dimid = UNDEFID;
- int timedimid = UNDEFID;
- char dimname[80];
- char timeunits[CDI_MAX_NAME];
- char attname[CDI_MAX_NAME];
- char name[CDI_MAX_NAME];
- nc_type xtype;
- int nvdims, nvatts;
- int dimids[9];
- int varid, iatt;
+ if ( ncvars[yvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+ /* see below for when it's impossible to operate
+ * without y values */
+ if ( !CDI_netcdf_lazy_grid_load
+ || ((ncvars[ncvarid].gridtype == UNDEFID ||
+ ncvars[ncvarid].gridtype == GRID_GENERIC)
+ && islat && (islon || xsize == 0)) )
+ {
+ grid->yvals = (double *) Malloc(size*sizeof(double));
- for ( dimid = 0; dimid < ndims; dimid++ )
- {
- cdf_inq_dimname(fileID, dimid, dimname);
- if ( memcmp(dimname, "time", 4) == 0 )
- {
- timedimid = dimid;
- break;
- }
- }
+ if ( ltgrid )
+ cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid->yvals);
+ else
+ cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid->yvals);
- if ( timedimid == UNDEFID )
- {
- for ( varid = 0; varid < nvars; varid++ )
- {
- cdf_inq_var(fileID, varid, name, &xtype, &nvdims, dimids, &nvatts);
- if ( nvdims == 1 )
- {
- for ( iatt = 0; iatt < nvatts; iatt++ )
- {
- cdf_inq_attname(fileID, varid, iatt, attname);
- if ( strncmp(attname, "units", 5) == 0 )
- {
- cdfGetAttText(fileID, varid, "units", sizeof(timeunits), timeunits);
- strtolower(timeunits);
+ scale_add(size, grid->yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor);
- if ( isTimeUnits(timeunits) )
+ /* don't change the name !!! */
+ /*
+ if ( (len = strlen(grid->yname)) > 2 )
+ if ( grid->yname[len-2] == '_' && isdigit((int) grid->yname[len-1]) )
+ grid->yname[len-2] = 0;
+ */
+ if ( islon && (int) ysize > 1 )
{
- timedimid = dimids[0];
- break;
+ yinc = fabs(grid->yvals[0] - grid->yvals[1]);
+ for ( size_t i = 2; i < ysize; i++ )
+ if ( (fabs(grid->yvals[i-1] - grid->yvals[i]) - yinc) > (yinc/1000) )
+ {
+ yinc = 0;
+ break;
+ }
}
}
- }
- }
- }
- }
+ else
+ {
+ lazyGrid->yValsGet = (struct xyValGet){
+ .scalefactor = ncvars[yvarid].scalefactor,
+ .addoffset = ncvars[yvarid].addoffset,
+ .start = { start[0], start[1], start[2] },
+ .count = { count[0], count[1], count[2] },
+ .size = size,
+ .datasetNCId = ncvars[yvarid].ncid,
+ .varNCId = yvarid,
+ .ndims = (short)ndims,
+ };
+ grid->yvals = cdfPendingLoad;
+ }
+ strcpy(grid->yname, ncvars[yvarid].name);
+ strcpy(grid->ylongname, ncvars[yvarid].longname);
+ strcpy(grid->yunits, ncvars[yvarid].units);
+ }
- return (timedimid);
-}
+ if ( (int) ysize == 0 ) size = xsize;
+ else if ( (int) xsize == 0 ) size = ysize;
+ else if ( ncvars[ncvarid].gridtype == GRID_UNSTRUCTURED ) size = xsize;
+ else size = xsize*ysize;
+ }
-static
-void init_ncdims(long ndims, ncdim_t *ncdims)
-{
- for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ )
- {
- ncdims[ncdimid].ncvarid = UNDEFID;
- ncdims[ncdimid].dimtype = UNDEFID;
- ncdims[ncdimid].len = 0;
- ncdims[ncdimid].name[0] = 0;
- }
-}
+ if ( ncvars[ncvarid].gridtype == UNDEFID ||
+ ncvars[ncvarid].gridtype == GRID_GENERIC )
+ {
+ if ( islat && (islon || xsize == 0) )
+ {
+ if ( isGaussGrid(ysize, yinc, grid->yvals) )
+ {
+ ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
+ grid->np = (int)(ysize/2);
+ }
+ else
+ ncvars[ncvarid].gridtype = GRID_LONLAT;
+ }
+ else if ( islon && !islat && ysize == 0 )
+ {
+ ncvars[ncvarid].gridtype = GRID_LONLAT;
+ }
+ else
+ ncvars[ncvarid].gridtype = GRID_GENERIC;
+ }
-static
-void init_ncvars(long nvars, ncvar_t *ncvars)
-{
- for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid )
- {
- ncvars[ncvarid].ncid = UNDEFID;
- ncvars[ncvarid].ignore = FALSE;
- ncvars[ncvarid].isvar = UNDEFID;
- ncvars[ncvarid].islon = FALSE;
- ncvars[ncvarid].islat = FALSE;
- ncvars[ncvarid].islev = FALSE;
- ncvars[ncvarid].istime = FALSE;
- ncvars[ncvarid].warn = FALSE;
- ncvars[ncvarid].tsteptype = TSTEP_CONSTANT;
- ncvars[ncvarid].param = UNDEFID;
- ncvars[ncvarid].code = UNDEFID;
- ncvars[ncvarid].tabnum = 0;
- ncvars[ncvarid].calendar = FALSE;
- ncvars[ncvarid].climatology = FALSE;
- ncvars[ncvarid].bounds = UNDEFID;
- ncvars[ncvarid].lformula = FALSE;
- ncvars[ncvarid].lformulaterms = FALSE;
- ncvars[ncvarid].gridID = UNDEFID;
- ncvars[ncvarid].zaxisID = UNDEFID;
- ncvars[ncvarid].gridtype = UNDEFID;
- ncvars[ncvarid].zaxistype = UNDEFID;
- ncvars[ncvarid].xdim = UNDEFID;
- ncvars[ncvarid].ydim = UNDEFID;
- ncvars[ncvarid].zdim = UNDEFID;
- ncvars[ncvarid].xvarid = UNDEFID;
- ncvars[ncvarid].yvarid = UNDEFID;
- ncvars[ncvarid].zvarid = UNDEFID;
- ncvars[ncvarid].tvarid = UNDEFID;
- ncvars[ncvarid].psvarid = UNDEFID;
- ncvars[ncvarid].ncoordvars = 0;
- for ( int i = 0; i < MAX_COORDVARS; ++i )
- ncvars[ncvarid].coordvarids[i] = UNDEFID;
- ncvars[ncvarid].nauxvars = 0;
- for ( int i = 0; i < MAX_AUXVARS; ++i )
- ncvars[ncvarid].auxvarids[i] = UNDEFID;
- ncvars[ncvarid].cellarea = UNDEFID;
- ncvars[ncvarid].tableID = UNDEFID;
- ncvars[ncvarid].xtype = 0;
- ncvars[ncvarid].ndims = 0;
- ncvars[ncvarid].gmapid = UNDEFID;
- ncvars[ncvarid].vctsize = 0;
- ncvars[ncvarid].vct = NULL;
- ncvars[ncvarid].truncation = 0;
- ncvars[ncvarid].position = 0;
- ncvars[ncvarid].positive = 0;
- ncvars[ncvarid].chunked = 0;
- ncvars[ncvarid].chunktype = UNDEFID;
- ncvars[ncvarid].defmissval = 0;
- ncvars[ncvarid].deffillval = 0;
- ncvars[ncvarid].missval = 0;
- ncvars[ncvarid].fillval = 0;
- ncvars[ncvarid].addoffset = 0;
- ncvars[ncvarid].scalefactor = 1;
- ncvars[ncvarid].name[0] = 0;
- ncvars[ncvarid].longname[0] = 0;
- ncvars[ncvarid].stdname[0] = 0;
- ncvars[ncvarid].units[0] = 0;
- ncvars[ncvarid].extra[0] = 0;
- ncvars[ncvarid].natts = 0;
- ncvars[ncvarid].atts = NULL;
- ncvars[ncvarid].deflate = 0;
- ncvars[ncvarid].lunsigned = 0;
- ncvars[ncvarid].lvalidrange = 0;
- ncvars[ncvarid].validrange[0] = VALIDMISS;
- ncvars[ncvarid].validrange[1] = VALIDMISS;
- ncvars[ncvarid].ensdata = NULL;
- }
-}
-
-static
-void cdfSetVar(ncvar_t *ncvars, int ncvarid, short isvar)
-{
- if ( ncvars[ncvarid].isvar != UNDEFID &&
- ncvars[ncvarid].isvar != isvar &&
- ncvars[ncvarid].warn == FALSE )
- {
- if ( ! ncvars[ncvarid].ignore )
- Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name);
-
- ncvars[ncvarid].warn = TRUE;
- isvar = FALSE;
- }
+ switch (ncvars[ncvarid].gridtype)
+ {
+ case GRID_GENERIC:
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ case GRID_UNSTRUCTURED:
+ case GRID_CURVILINEAR:
+ {
+ grid->size = (int)size;
+ grid->xsize = (int)xsize;
+ grid->ysize = (int)ysize;
+ if ( xvarid != UNDEFID )
+ {
+ grid->xdef = 1;
+ if ( ncvars[xvarid].bounds != UNDEFID )
+ {
+ int nbdims = ncvars[ncvars[xvarid].bounds].ndims;
+ if ( nbdims == 2 || nbdims == 3 )
+ {
+ size_t nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
+ grid->nvertex = (int)nvertex;
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->xBoundsGet.datasetNCId
+ = ncvars[xvarid].ncid;
+ lazyGrid->xBoundsGet.varNCId
+ = ncvars[xvarid].bounds;
+ grid->xbounds = cdfPendingLoad;
+ }
+ else
+ {
+ grid->xbounds
+ = (double *)Malloc(nvertex * size
+ * sizeof(double));
+ cdf_get_var_double(ncvars[xvarid].ncid,
+ ncvars[xvarid].bounds,
+ grid->xbounds);
+ }
+ }
+ }
+ }
+ if ( yvarid != UNDEFID )
+ {
+ grid->ydef = 1;
+ if ( ncvars[yvarid].bounds != UNDEFID )
+ {
+ int nbdims = ncvars[ncvars[yvarid].bounds].ndims;
+ if ( nbdims == 2 || nbdims == 3 )
+ {
+ /* size_t nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len;
+ if ( nvertex != grid->nvertex )
+ Warning("nvertex problem! nvertex x %d, nvertex y %d",
+ grid->nvertex, (int) nvertex);
+ */
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->yBoundsGet.datasetNCId
+ = ncvars[yvarid].ncid;
+ lazyGrid->yBoundsGet.varNCId
+ = ncvars[yvarid].bounds;
+ grid->ybounds = cdfPendingLoad;
+ }
+ else
+ {
+ int vid
+ = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
+ size_t nvertex = ncdims[vid].len;
+ /*
+ if ( nvertex != grid->nvertex )
+ Warning("nvertex problem! nvertex x %d, nvertex y %d",
+ grid->nvertex, (int) nvertex);
+ */
+ grid->ybounds
+ = (double *)Malloc(nvertex * size
+ * sizeof(double));
+ cdf_get_var_double(ncvars[yvarid].ncid,
+ ncvars[yvarid].bounds,
+ grid->ybounds);
+ }
+ }
+ }
+ }
- ncvars[ncvarid].isvar = isvar;
-}
+ if ( ncvars[ncvarid].cellarea != UNDEFID )
+ {
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ grid->area = cdfPendingLoad;
+ lazyGrid->cellAreaGet.datasetNCId
+ = ncvars[ncvarid].ncid;
+ lazyGrid->cellAreaGet.varNCId
+ = ncvars[ncvarid].cellarea;
+ }
+ else
+ {
+ grid->area = (double *) Malloc(size*sizeof(double));
+ cdf_get_var_double(ncvars[ncvarid].ncid,
+ ncvars[ncvarid].cellarea,
+ grid->area);
+ }
+ }
-static
-void cdfSetDim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype)
-{
- if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID &&
- ncvars[ncvarid].dimtype[dimid] != dimtype )
- {
- Warning("Inconsistent dimension definition for %s! dimid = %d; type = %d; newtype = %d",
- ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype);
- }
+ break;
+ }
+ case GRID_SPECTRAL:
+ {
+ grid->size = (int)size;
+ grid->lcomplex = 1;
+ break;
+ }
+ case GRID_FOURIER:
+ {
+ grid->size = (int)size;
+ break;
+ }
+ case GRID_TRAJECTORY:
+ {
+ grid->size = 1;
+ break;
+ }
+ }
- ncvars[ncvarid].dimtype[dimid] = dimtype;
-}
+ if (grid->type != ncvars[ncvarid].gridtype)
+ {
+ int gridtype = ncvars[ncvarid].gridtype;
+ grid->type = gridtype;
+ cdiGridTypeInit(grid, gridtype, grid->size);
+ }
-static
-int isLonAxis(const char *units, const char *stdname)
-{
- int status = FALSE;
- char lc_units[16];
+ if ( grid->size == 0 )
+ {
+ if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
+ (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == Z_AXIS) ||
+ (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS && ncvars[ncvarid].dimtype[1] == Z_AXIS) )
+ {
+ grid->type = GRID_GENERIC;
+ grid->size = 1;
+ grid->xsize = 0;
+ grid->ysize = 0;
+ }
+ else
+ {
+ Warning("Variable %s has an unsupported grid, skipped!", ncvars[ncvarid].name);
+ ncvars[ncvarid].isvar = -1;
+ continue;
+ }
+ }
- memcpy(lc_units, units, 15);
- lc_units[15] = 0;
- strtolower(lc_units);
+ if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) )
+ grid->type = GRID_UNSTRUCTURED;
- if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
- (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) )
- {
- status = TRUE;
- }
+ if ( number_of_grid_used != UNDEFID && grid->type == GRID_UNSTRUCTURED )
+ grid->number = number_of_grid_used;
- if ( status == FALSE &&
- memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) &&
- memcmp(lc_units, "degree", 6) == 0 )
- {
- int ioff = 6;
- if ( lc_units[ioff] == 's' ) ioff++;
- if ( lc_units[ioff] == '_' ) ioff++;
- if ( lc_units[ioff] == 'e' ) status = TRUE;
- }
+ if ( ncvars[ncvarid].gmapid >= 0 && ncvars[ncvarid].gridtype != GRID_CURVILINEAR )
+ {
+ int nvatts;
+ cdf_inq_varnatts(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, &nvatts);
- return (status);
-}
+ for ( int iatt = 0; iatt < nvatts; iatt++ )
+ {
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
+ cdf_inq_attname(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, iatt, attname);
+ cdf_inq_attlen(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, &attlen);
-static
-int isLatAxis(const char *units, const char *stdname)
-{
- int status = FALSE;
- char lc_units[16];
+ if ( strcmp(attname, "grid_mapping_name") == 0 )
+ {
+ enum {
+ attstringlen = 8192,
+ };
+ char attstring[attstringlen];
- memcpy(lc_units, units, 15);
- lc_units[15] = 0;
- strtolower(lc_units);
+ cdfGetAttText(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, attstringlen, attstring);
+ strtolower(attstring);
- if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
- (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) )
- {
- status = TRUE;
- }
+ if ( strcmp(attstring, "rotated_latitude_longitude") == 0 )
+ grid->isRotated = TRUE;
+ else if ( strcmp(attstring, "sinusoidal") == 0 )
+ grid->type = GRID_SINUSOIDAL;
+ else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 )
+ grid->type = GRID_LAEA;
+ else if ( strcmp(attstring, "lambert_conformal_conic") == 0 )
+ grid->type = GRID_LCC2;
+ else if ( strcmp(attstring, "lambert_cylindrical_equal_area") == 0 )
+ {
+ proj->type = GRID_PROJECTION;
+ proj->name = strdup(attstring);
+ }
+ }
+ else if ( strcmp(attname, "earth_radius") == 0 )
+ {
+ double datt;
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
+ grid->laea_a = datt;
+ grid->lcc2_a = datt;
+ }
+ else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )
+ {
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->laea_lon_0);
+ }
+ else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )
+ {
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->lcc2_lon_0);
+ }
+ else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )
+ {
+ double datt;
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
+ grid->laea_lat_0 = datt;
+ grid->lcc2_lat_0 = datt;
+ }
+ else if ( strcmp(attname, "standard_parallel") == 0 )
+ {
+ if ( attlen == 1 )
+ {
+ double datt;
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
+ grid->lcc2_lat_1 = datt;
+ grid->lcc2_lat_2 = datt;
+ }
+ else
+ {
+ double datt2[2];
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 2, datt2);
+ grid->lcc2_lat_1 = datt2[0];
+ grid->lcc2_lat_2 = datt2[1];
+ }
+ }
+ else if ( strcmp(attname, "grid_north_pole_latitude") == 0 )
+ {
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->ypole);
+ }
+ else if ( strcmp(attname, "grid_north_pole_longitude") == 0 )
+ {
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->xpole);
+ }
+ else if ( strcmp(attname, "north_pole_grid_longitude") == 0 )
+ {
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->angle);
+ }
+ }
+ }
- if ( status == FALSE &&
- memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) &&
- memcmp(lc_units, "degree", 6) == 0 )
- {
- int ioff = 6;
- if ( lc_units[ioff] == 's' ) ioff++;
- if ( lc_units[ioff] == '_' ) ioff++;
- if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = TRUE;
- }
+ if ( grid->type == GRID_UNSTRUCTURED )
+ {
+ int zdimid = UNDEFID;
+ int xdimidx = -1, ydimidx = -1;
- return (status);
-}
+ for ( int i = 0; i < ndims; i++ )
+ {
+ if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) xdimidx = i;
+ else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) ydimidx = i;
+ else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) zdimid = ncvars[ncvarid].dimids[i];
+ }
-static
-int isDBLAxis(/*const char *units,*/ const char *longname)
-{
- int status = FALSE;
+ if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID )
+ {
+ if ( grid->xsize > grid->ysize && grid->ysize < 1000 )
+ {
+ ncvars[ncvarid].dimtype[ydimidx] = Z_AXIS;
+ ydimid = UNDEFID;
+ grid->size = grid->xsize;
+ grid->ysize = 0;
+ }
+ else if ( grid->ysize > grid->xsize && grid->xsize < 1000 )
+ {
+ ncvars[ncvarid].dimtype[xdimidx] = Z_AXIS;
+ xdimid = ydimid;
+ ydimid = UNDEFID;
+ grid->size = grid->ysize;
+ grid->xsize = grid->ysize;
+ grid->ysize = 0;
+ }
+ }
- if ( strcmp(longname, "depth below land") == 0 ||
- strcmp(longname, "depth_below_land") == 0 ||
- strcmp(longname, "levels below the surface") == 0 )
- {
- /*
- if ( strcmp(ncvars[ncvarid].units, "cm") == 0 ||
- strcmp(ncvars[ncvarid].units, "dm") == 0 ||
- strcmp(ncvars[ncvarid].units, "m") == 0 )
- */
- status = TRUE;
- }
+ if ( grid->size != grid->xsize )
+ {
+ Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
+ ncvars[ncvarid].isvar = -1;
+ continue;
+ }
- return (status);
-}
+ if ( ncvars[ncvarid].position > 0 ) grid->position = ncvars[ncvarid].position;
+ if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16);
+ }
-static
-int unitsIsMeter(const char *units)
-{
- return (units[0] == 'm' && (!units[1] || strncmp(units, "meter", 5) == 0));
-}
+#if defined (PROJECTION_TEST)
+ if ( proj->type == GRID_PROJECTION )
+ {
+ if ( grid->type == GRID_GENERIC )
+ {
+ grid->type = GRID_CURVILINEAR;
+ }
-static
-int isDepthAxis(const char *stdname, const char *longname)
-{
- int status = FALSE;
+ if ( grid->type == GRID_CURVILINEAR )
+ {
+ proj->size = grid->size;
+ proj->xsize = grid->xsize;
+ proj->ysize = grid->ysize;
+ }
- if ( strcmp(stdname, "depth") == 0 ) status = TRUE;
+ // grid->proj = gridGenerate(proj);
+ }
+#endif
- if ( status == FALSE )
- if ( strcmp(longname, "depth_below_sea") == 0 ||
- strcmp(longname, "depth below sea") == 0 )
- {
- status = TRUE;
- }
+ if ( CDI_Debug )
+ {
+ Message("grid: type = %d, size = %d, nx = %d, ny %d",
+ grid->type, grid->size, grid->xsize, grid->ysize);
+ Message("proj: type = %d, size = %d, nx = %d, ny %d",
+ proj->type, proj->size, proj->xsize, proj->ysize);
+ }
- return (status);
-}
+#if defined (PROJECTION_TEST)
+ if ( proj->type == GRID_PROJECTION )
+ {
+ projAdded = cdiVlistAddGridIfNew(vlistID, proj, 1);
+ ncvars[ncvarid].gridID = projAdded.Id;
+ copy_numeric_projatts(ncvars[ncvarid].gridID, ncvars[ncvarid].gmapid, ncvars[ncvarid].ncid);
+ }
+ else
+#endif
+ {
+ gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1);
+ ncvars[ncvarid].gridID = gridAdded.Id;
+ }
-static
-int isHeightAxis(const char *stdname, const char *longname)
-{
- int status = FALSE;
+ if ( grid->type == GRID_UNSTRUCTURED )
+ {
+ if ( gridfile[0] != 0 ) gridDefReference(ncvars[ncvarid].gridID, gridfile);
+ }
- if ( strcmp(stdname, "height") == 0 ) status = TRUE;
+ if ( ncvars[ncvarid].chunked ) grid_set_chunktype(grid, &ncvars[ncvarid]);
- if ( status == FALSE )
- if ( strcmp(longname, "height") == 0 ||
- strcmp(longname, "height above the surface") == 0 )
- {
- status = TRUE;
- }
+ int gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID);
+ streamptr->xdimID[gridindex] = xdimid;
+ streamptr->ydimID[gridindex] = ydimid;
+ if ( xdimid == -1 && ydimid == -1 && grid->size == 1 )
+ gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
- return (status);
-}
+ if ( CDI_Debug )
+ Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
-static
-int unitsIsPressure(const char *units)
-{
- int status = FALSE;
+ for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
+ if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].gridID == UNDEFID )
+ {
+ int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID;
+ int xdimidx = -1, ydimidx = -1;
+ int ndims2 = ncvars[ncvarid2].ndims;
- if ( memcmp(units, "millibar", 8) == 0 ||
- memcmp(units, "mb", 2) == 0 ||
- memcmp(units, "hectopas", 8) == 0 ||
- memcmp(units, "hPa", 3) == 0 ||
- memcmp(units, "Pa", 2) == 0 )
- {
- status = TRUE;
- }
+ for ( int i = 0; i < ndims2; i++ )
+ {
+ if ( ncvars[ncvarid2].dimtype[i] == X_AXIS )
+ { xdimid2 = ncvars[ncvarid2].dimids[i]; xdimidx = i; }
+ else if ( ncvars[ncvarid2].dimtype[i] == Y_AXIS )
+ { ydimid2 = ncvars[ncvarid2].dimids[i]; ydimidx = i; }
+ else if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
+ { zdimid2 = ncvars[ncvarid2].dimids[i]; }
+ }
- return status;
-}
+ if ( ncvars[ncvarid2].gridtype == UNDEFID && grid->type == GRID_UNSTRUCTURED )
+ {
+ if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID )
+ {
+ ncvars[ncvarid2].dimtype[ydimidx] = Z_AXIS;
+ ydimid2 = UNDEFID;
+ }
-static
-void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid)
-{
- *apvarid = -1;
- *bvarid = -1;
- *psvarid = -1;
- const int attstringlen = 8192; char attstring[8192];
- cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring);
- if ( strcmp(attstring, "p = ap + b*ps") == 0 )
- {
- int lstop = FALSE;
- int dimvarid;
- cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring);
- char *pstring = attstring;
+ if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID )
+ {
+ ncvars[ncvarid2].dimtype[xdimidx] = Z_AXIS;
+ xdimid2 = ydimid2;
+ ydimid2 = UNDEFID;
+ }
+ }
- for ( int i = 0; i < 3; i++ )
- {
- while ( isspace((int) *pstring) ) pstring++;
- if ( *pstring == 0 ) break;
- char *tagname = pstring;
- while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
- if ( *pstring == 0 ) lstop = TRUE;
- *pstring++ = 0;
+ if ( xdimid == xdimid2 &&
+ (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) )
+ {
+ int same_grid = ncvars[ncvarid].xvarid == ncvars[ncvarid2].xvarid
+ && ncvars[ncvarid].yvarid == ncvars[ncvarid2].yvarid
+ && ncvars[ncvarid].position == ncvars[ncvarid2].position;
+ /*
+ if ( xvarid != -1 && ncvars[ncvarid2].xvarid != UNDEFID &&
+ xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
- while ( isspace((int) *pstring) ) pstring++;
- if ( *pstring == 0 ) break;
- char *varname = pstring;
- while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
- if ( *pstring == 0 ) lstop = TRUE;
- *pstring++ = 0;
+ if ( yvarid != -1 && ncvars[ncvarid2].yvarid != UNDEFID &&
+ yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
+ */
- int status = nc_inq_varid(ncid, varname, &dimvarid);
- if ( status == NC_NOERR )
- {
- if ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid;
- else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid;
- else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid;
- }
- else if ( strcmp(tagname, "ps:") != 0 )
- {
- Warning("%s - %s", nc_strerror(status), varname);
- }
+ if ( same_grid )
+ {
+ if ( CDI_Debug )
+ Message("Same gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid2, ncvars[ncvarid2].name);
+ ncvars[ncvarid2].gridID = ncvars[ncvarid].gridID;
+ ncvars[ncvarid2].chunktype = ncvars[ncvarid].chunktype;
+ }
+ }
+ }
- if ( lstop ) break;
- }
+ if (gridAdded.isNew)
+ lazyGrid = NULL;
+ if (projAdded.isNew)
+ lazyProj = NULL;
+ }
+ }
+ if (lazyGrid)
+ {
+ if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyGrid);
+ grid_free(grid);
+ Free(grid);
}
+ if (lazyProj)
+ {
+ if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyProj);
+ grid_free(proj);
+ Free(proj);
+ }
+#undef proj
+#undef grid
}
+/* define all input zaxes */
static
-int isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
+void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars,
+ size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid)
{
- int status = FALSE;
- int ncfvarid = ncvarid;
- ncvar_t *ncvar = &ncvars[ncvarid];
+ int ncvarid, ncvarid2;
+ int i, ilev;
+ int zaxisindex;
+ int nbdims, nvertex, nlevel;
+ int psvarid = -1;
+ char *pname, *plongname, *punits;
+ size_t vctsize = vctsize_echam;
+ double *vct = vct_echam;
- if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 )
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
{
- cdiConvention = CDI_CONVENTION_CF;
-
- status = TRUE;
- ncvar->zaxistype = ZAXIS_HYBRID;
- int dimid = ncvar->dimids[0];
- size_t dimlen = ncdims[dimid].len;
+ if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].zaxisID == UNDEFID )
+ {
+ int is_scalar = FALSE;
+ int with_bounds = FALSE;
+ int zdimid = UNDEFID;
+ int zvarid = UNDEFID;
+ int zsize = 1;
+ double *lbounds = NULL;
+ double *ubounds = NULL;
- int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1;
- if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
- scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1);
- if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE;
- if ( bvarid1 != -1 ) ncvars[bvarid1].isvar = FALSE;
- if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1;
+ int positive = 0;
+ int ndims = ncvars[ncvarid].ndims;
- if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms )
- {
- ncfvarid = ncvar->bounds;
- int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1;
- if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms )
- scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2);
- if ( apvarid2 != -1 && bvarid2 != -1 )
+ if ( ncvars[ncvarid].zvarid != -1 && ncvars[ncvars[ncvarid].zvarid].ndims == 0 )
{
- ncvars[apvarid2].isvar = FALSE;
- ncvars[bvarid2].isvar = FALSE;
-
- if ( dimid == ncvars[apvarid2].dimids[0] && ncdims[ncvars[apvarid2].dimids[1]].len == 2 )
+ zvarid = ncvars[ncvarid].zvarid;
+ is_scalar = TRUE;
+ }
+ else
+ {
+ for ( i = 0; i < ndims; i++ )
{
- double abuf[dimlen*2], bbuf[dimlen*2];
- cdf_get_var_double(ncid, apvarid2, abuf);
- cdf_get_var_double(ncid, bvarid2, bbuf);
- /*
- for ( int i = 0; i < dimlen; ++i )
- printf("%d %g %g %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]);
- */
- size_t vctsize = (dimlen+1)*2;
- double *vct = (double *) Malloc(vctsize * sizeof(double));
- for ( size_t i = 0; i < dimlen; ++i )
- {
- vct[i] = abuf[i*2];
- vct[i+dimlen+1] = bbuf[i*2];
- }
- vct[dimlen] = abuf[dimlen*2-1];
- vct[dimlen*2+1] = bbuf[dimlen*2-1];
+ if ( ncvars[ncvarid].dimtype[i] == Z_AXIS )
+ zdimid = ncvars[ncvarid].dimids[i];
+ }
- ncvar->vct = vct;
- ncvar->vctsize = vctsize;
+ if ( zdimid != UNDEFID )
+ {
+ zvarid = ncdims[zdimid].ncvarid;
+ zsize = (int)ncdims[zdimid].len;
}
}
- }
- }
- return status;
-}
+ if ( CDI_Debug ) Message("nlevs = %d", zsize);
+ double *zvar = (double *) Malloc((size_t)zsize * sizeof (double));
-static
-int isGaussGrid(size_t ysize, double yinc, const double *yvals)
-{
- int lgauss = FALSE;
- double *yv, *yw;
-
- if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */
- {
- size_t i;
- yv = (double *) Malloc(ysize*sizeof(double));
- yw = (double *) Malloc(ysize*sizeof(double));
- gaussaw(yv, yw, ysize);
- Free(yw);
- for ( i = 0; i < ysize; i++ )
- yv[i] = asin(yv[i])/M_PI*180.0;
+ int zaxisType = UNDEFID;
+ if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype;
+ if ( zaxisType == UNDEFID ) zaxisType = ZAXIS_GENERIC;
- for ( i = 0; i < ysize; i++ )
- if ( fabs(yv[i] - yvals[i]) >
- ((yv[0] - yv[1])/500) ) break;
+ int zprec = DATATYPE_FLT64;
- if ( i == ysize ) lgauss = TRUE;
+ if ( zvarid != UNDEFID )
+ {
+ positive = ncvars[zvarid].positive;
+ pname = ncvars[zvarid].name;
+ plongname = ncvars[zvarid].longname;
+ punits = ncvars[zvarid].units;
+ if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32;
+ /* don't change the name !!! */
+ /*
+ if ( (len = strlen(pname)) > 2 )
+ if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) )
+ pname[len-2] = 0;
+ */
+ psvarid = -1;
+ if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct )
+ {
+ vct = ncvars[zvarid].vct;
+ vctsize = ncvars[zvarid].vctsize;
- /* check S->N */
- if ( lgauss == FALSE )
- {
- for ( i = 0; i < ysize; i++ )
- if ( fabs(yv[i] - yvals[ysize-i-1]) >
- ((yv[0] - yv[1])/500) ) break;
+ if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid;
+ }
- if ( i == ysize ) lgauss = TRUE;
- }
+ cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar);
- Free(yv);
- }
+ if ( ncvars[zvarid].bounds != UNDEFID )
+ {
+ nbdims = ncvars[ncvars[zvarid].bounds].ndims;
+ if ( nbdims == 2 )
+ {
+ nlevel = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
+ nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
+ if ( nlevel == zsize && nvertex == 2 )
+ {
+ with_bounds = TRUE;
+ lbounds = (double *) Malloc((size_t)nlevel*sizeof(double));
+ ubounds = (double *) Malloc((size_t)nlevel*sizeof(double));
+ double zbounds[2*nlevel];
+ cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
+ for ( i = 0; i < nlevel; ++i )
+ {
+ lbounds[i] = zbounds[i*2];
+ ubounds[i] = zbounds[i*2+1];
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ pname = NULL;
+ plongname = NULL;
+ punits = NULL;
- return (lgauss);
-}
+ if ( zsize == 1 )
+ {
+ if ( ncvars[ncvarid].zaxistype != UNDEFID )
+ zaxisType = ncvars[ncvarid].zaxistype;
+ else
+ zaxisType = ZAXIS_SURFACE;
-static
-void printNCvars(const ncvar_t *ncvars, int nvars, const char *oname)
-{
- char axis[7];
- int ncvarid, i;
- int ndim;
- static const char iaxis[] = {'t', 'z', 'y', 'x'};
+ zvar[0] = 0;
+ /*
+ if ( zdimid == UNDEFID )
+ zvar[0] = 9999;
+ else
+ zvar[0] = 0;
+ */
+ }
+ else
+ {
+ for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
+ }
+ }
- fprintf(stderr, "%s:\n", oname);
+ ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds,
+ (int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- ndim = 0;
- if ( ncvars[ncvarid].isvar )
- {
- axis[ndim++] = 'v';
- axis[ndim++] = ':';
- for ( i = 0; i < ncvars[ncvarid].ndims; i++ )
- {/*
- if ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0];
- else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1];
- else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2];
- else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3];
- else
- */
- if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0];
- else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1];
- else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2];
- else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3];
- else axis[ndim++] = '?';
+ if ( uuidOfVGrid[0] != 0 )
+ {
+ // printf("uuidOfVGrid: defined\n");
+ zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid);
}
- }
- else
- {
- axis[ndim++] = 'c';
- axis[ndim++] = ':';
- if ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0];
- else if ( ncvars[ncvarid].islev ) axis[ndim++] = iaxis[1];
- else if ( ncvars[ncvarid].islat ) axis[ndim++] = iaxis[2];
- else if ( ncvars[ncvarid].islon ) axis[ndim++] = iaxis[3];
- else axis[ndim++] = '?';
- }
- axis[ndim++] = 0;
+ if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvars[ncvarid].zaxisID, ncvars[psvarid].name);
- fprintf(stderr, "%3d %3d %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name);
+ if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
+ if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID);
+
+ Free(zvar);
+ Free(lbounds);
+ Free(ubounds);
+
+ zaxisindex = vlistZaxisIndex(vlistID, ncvars[ncvarid].zaxisID);
+ streamptr->zaxisID[zaxisindex] = zdimid;
+
+ if ( CDI_Debug )
+ Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid, ncvars[ncvarid].name);
+
+ for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
+ if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ )
+ {
+ int zvarid2 = UNDEFID;
+ if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 )
+ zvarid2 = ncvars[ncvarid2].zvarid;
+
+ int zdimid2 = UNDEFID;
+ ndims = ncvars[ncvarid2].ndims;
+ for ( i = 0; i < ndims; i++ )
+ {
+ if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
+ zdimid2 = ncvars[ncvarid2].dimids[i];
+ }
+
+ if ( zdimid == zdimid2 /* && zvarid == zvarid2 */)
+ {
+ if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ||
+ (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) ||
+ (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) ||
+ (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) )
+ {
+ if ( CDI_Debug )
+ Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid2, ncvars[ncvarid2].name);
+ ncvars[ncvarid2].zaxisID = ncvars[ncvarid].zaxisID;
+ }
+ }
+ }
+ }
}
}
-static
-void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
- int timedimid, int modelID, int format)
+struct varinfo
{
- int ncid;
- int ncdimid;
- int nvdims, nvatts;
- int *dimidsp;
- int iatt;
- nc_type xtype, atttype;
- size_t attlen;
- char name[CDI_MAX_NAME];
- char attname[CDI_MAX_NAME];
- const int attstringlen = 8192; char attstring[8192];
+ int ncvarid;
+ const char *name;
+};
- int nchecked_vars = 0;
- enum { max_check_vars = 9 };
- char *checked_vars[max_check_vars];
- for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL;
+static
+int cmpvarname(const void *s1, const void *s2)
+{
+ const struct varinfo *x = (const struct varinfo *)s1,
+ *y = (const struct varinfo *)s2;
+ return (strcmp(x->name, y->name));
+}
- for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+/* define all input data variables */
+static
+void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars)
+{
+ if ( CDI_Debug )
{
- ncid = ncvars[ncvarid].ncid;
- dimidsp = ncvars[ncvarid].dimids;
+ for(int i = 0; i < nvars; i++) Message("varids[%d] = %d", i, varids[i]);
+ }
+ if ( streamptr->sortname )
+ {
+ struct varinfo *varInfo
+ = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo));
- cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
- strcpy(ncvars[ncvarid].name, name);
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int ncvarid = varids[varID];
+ varInfo[varID].ncvarid = ncvarid;
+ varInfo[varID].name = ncvars[ncvarid].name;
+ }
+ qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname);
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ varids[varID] = varInfo[varID].ncvarid;
+ }
+ Free(varInfo);
+ if ( CDI_Debug )
+ {
+ for(int i = 0; i < nvars; i++) Message("sorted varids[%d] = %d", i, varids[i]);
+ }
+ }
- for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ )
- ncvars[ncvarid].dimtype[ncdimid] = -1;
+ for ( int varID1 = 0; varID1 < nvars; varID1++ )
+ {
+ int ncvarid = varids[varID1];
+ int gridID = ncvars[ncvarid].gridID;
+ int zaxisID = ncvars[ncvarid].zaxisID;
- ncvars[ncvarid].xtype = xtype;
- ncvars[ncvarid].ndims = nvdims;
+ stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID);
+ int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype);
#if defined (HAVE_NETCDF4)
- if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 )
- {
- char buf[CDI_MAX_NAME];
- int shuffle, deflate, deflate_level;
- size_t chunks[nvdims];
- int storage_in;
- nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level);
- if ( deflate > 0 ) ncvars[ncvarid].deflate = 1;
+ if ( ncvars[ncvarid].deflate )
+ vlistDefVarCompType(vlistID, varID, COMPRESS_ZIP);
- if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR )
- {
- if ( storage_in == NC_CHUNKED )
- {
- ncvars[ncvarid].chunked = 1;
- for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i];
- if ( CDI_Debug )
- {
- fprintf(stderr, "%s: chunking %d %d %d chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED);
- for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]);
- fprintf(stderr, "\n");
- }
- strcat(ncvars[ncvarid].extra, "chunks=");
- for ( int i = nvdims-1; i >= 0; --i )
- {
- sprintf(buf, "%ld", (long) chunks[i]);
- strcat(ncvars[ncvarid].extra, buf);
- if ( i > 0 ) strcat(ncvars[ncvarid].extra, "x");
- }
- strcat(ncvars[ncvarid].extra, " ");
- }
- }
- }
+ if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID )
+ vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype);
#endif
- if ( nvdims > 0 )
+ streamptr->vars[varID1].defmiss = 0;
+ streamptr->vars[varID1].ncvarid = ncvarid;
+
+ vlistDefVarName(vlistID, varID, ncvars[ncvarid].name);
+ if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param);
+ if ( ncvars[ncvarid].code != UNDEFID ) vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code);
+ if ( ncvars[ncvarid].code != UNDEFID )
+ {
+ int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255);
+ vlistDefVarParam(vlistID, varID, param);
+ }
+ if ( ncvars[ncvarid].longname[0] ) vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname);
+ if ( ncvars[ncvarid].stdname[0] ) vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname);
+ if ( ncvars[ncvarid].units[0] ) vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units);
+
+ if ( ncvars[ncvarid].lvalidrange )
+ vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange);
+
+ if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) )
+ vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset);
+ if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) )
+ vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor);
+
+ vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned));
+
+ vlistDefVarInstitut(vlistID, varID, instID);
+ vlistDefVarModel(vlistID, varID, modelID);
+ if ( ncvars[ncvarid].tableID != UNDEFID )
+ vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID);
+
+ if ( ncvars[ncvarid].deffillval == FALSE && ncvars[ncvarid].defmissval == TRUE )
{
- if ( timedimid == dimidsp[0] )
- {
- ncvars[ncvarid].tsteptype = TSTEP_INSTANT;
- cdfSetDim(ncvars, ncvarid, 0, T_AXIS);
- }
- else
- {
- for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ )
- {
- if ( timedimid == dimidsp[ncdimid] )
- {
- Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
- ncvars[ncvarid].isvar = FALSE;
- }
- }
- }
+ ncvars[ncvarid].deffillval = TRUE;
+ ncvars[ncvarid].fillval = ncvars[ncvarid].missval;
}
- for ( iatt = 0; iatt < nvatts; iatt++ )
- {
- cdf_inq_attname(ncid, ncvarid, iatt, attname);
- cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
- cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+ if ( ncvars[ncvarid].deffillval == TRUE )
+ vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval);
- if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname);
- }
- else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname);
- }
- else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units);
- }
- else if ( strcmp(attname, "calendar") == 0 )
- {
- ncvars[ncvarid].calendar = TRUE;
- }
- else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) )
- {
- char paramstr[32];
- int pnum = 0, pcat = 255, pdis = 255;
- cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr);
- sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis);
- ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis);
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) )
- {
- cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code);
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) )
- {
- int tablenum;
- cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum);
- if ( tablenum > 0 )
- {
- ncvars[ncvarid].tabnum = tablenum;
- ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL);
- if ( ncvars[ncvarid].tableID == CDI_UNDEFID )
- ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL);
- }
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- if ( memcmp(attstring, "Triangular", attlen) == 0 )
- ncvars[ncvarid].gridtype = GRID_SPECTRAL;
- }
- else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- strtolower(attstring);
+ if ( CDI_Debug )
+ Message("varID = %d gridID = %d zaxisID = %d", varID,
+ vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID));
- if ( strcmp(attstring, "gaussian reduced") == 0 )
- ncvars[ncvarid].gridtype = GRID_GAUSSIAN_REDUCED;
- else if ( strcmp(attstring, "gaussian") == 0 )
- ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
- else if ( strncmp(attstring, "spectral", 8) == 0 )
- ncvars[ncvarid].gridtype = GRID_SPECTRAL;
- else if ( strncmp(attstring, "fourier", 7) == 0 )
- ncvars[ncvarid].gridtype = GRID_FOURIER;
- else if ( strcmp(attstring, "trajectory") == 0 )
- ncvars[ncvarid].gridtype = GRID_TRAJECTORY;
- else if ( strcmp(attstring, "generic") == 0 )
- ncvars[ncvarid].gridtype = GRID_GENERIC;
- else if ( strcmp(attstring, "cell") == 0 )
- ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
- else if ( strcmp(attstring, "unstructured") == 0 )
- ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
- else if ( strcmp(attstring, "curvilinear") == 0 )
- ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
- else if ( strcmp(attstring, "sinusoidal") == 0 )
- ;
- else if ( strcmp(attstring, "laea") == 0 )
- ;
- else if ( strcmp(attstring, "lcc2") == 0 )
- ;
- else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear
- ;
- else
- {
- static int warn = TRUE;
- if ( warn )
- {
- warn = FALSE;
- Warning("netCDF attribute grid_type='%s' unsupported!", attstring);
- }
- }
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int xdimid = streamptr->xdimID[gridindex];
+ int ydimid = streamptr->ydimID[gridindex];
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- strtolower(attstring);
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zdimid = streamptr->zaxisID[zaxisindex];
- if ( strcmp(attstring, "toa") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_TOA;
- else if ( strcmp(attstring, "cloudbase") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_BASE;
- else if ( strcmp(attstring, "cloudtop") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_TOP;
- else if ( strcmp(attstring, "isotherm0") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_ISOTHERM_ZERO;
- else if ( strcmp(attstring, "seabottom") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_SEA_BOTTOM;
- else if ( strcmp(attstring, "lakebottom") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_LAKE_BOTTOM;
- else if ( strcmp(attstring, "sedimentbottom") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM;
- else if ( strcmp(attstring, "sedimentbottomta") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;
- else if ( strcmp(attstring, "sedimentbottomtw") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;
- else if ( strcmp(attstring, "mixlayer") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_MIX_LAYER;
- else if ( strcmp(attstring, "atmosphere") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_ATMOSPHERE;
- else
- {
- static int warn = TRUE;
- if ( warn )
- {
- warn = FALSE;
- Warning("netCDF attribute level_type='%s' unsupported!", attstring);
- }
- }
+ int ndims = ncvars[ncvarid].ndims;
+ int iodim = 0;
+ int ixyz = 0;
+ int ipow10[4] = {1, 10, 100, 1000};
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) )
+ if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++;
+
+ if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid )
+ {
+ if ( xdimid == ncvars[ncvarid].dimids[ndims-1] )
{
- cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+ ixyz = 321;
}
- else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) )
+ else
{
- cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation);
+ ixyz = 213;
}
- else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) )
+ }
+ else
+ {
+ for ( int idim = iodim; idim < ndims; idim++ )
{
- cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position);
+ if ( xdimid == ncvars[ncvarid].dimids[idim] )
+ ixyz += 1*ipow10[ndims-idim-1];
+ else if ( ydimid == ncvars[ncvarid].dimids[idim] )
+ ixyz += 2*ipow10[ndims-idim-1];
+ else if ( zdimid == ncvars[ncvarid].dimids[idim] )
+ ixyz += 3*ipow10[ndims-idim-1];
}
- else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset);
- /*
- if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
- if ( ncvars[ncvarid].addoffset != 0 )
- Warning("attribute add_offset not supported for atttype %d", atttype);
- */
- /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor);
+ }
+
+ vlistDefVarXYZ(vlistID, varID, ixyz);
+ /*
+ printf("ixyz %d\n", ixyz);
+ printf("ndims %d\n", ncvars[ncvarid].ndims);
+ for ( int i = 0; i < ncvars[ncvarid].ndims; ++i )
+ printf("dimids: %d %d\n", i, ncvars[ncvarid].dimids[i]);
+ printf("xdimid, ydimid %d %d\n", xdimid, ydimid);
+ */
+ if ( ncvars[ncvarid].ensdata != NULL )
+ {
+ vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index,
+ ncvars[ncvarid].ensdata->ens_count,
+ ncvars[ncvarid].ensdata->forecast_init_type );
+ Free(ncvars[ncvarid].ensdata);
+ ncvars[ncvarid].ensdata = NULL;
+ }
+
+ if ( ncvars[ncvarid].extra[0] != 0 )
+ {
+ vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
+ }
+ }
+
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int ncvarid = varids[varID];
+ int ncid = ncvars[ncvarid].ncid;
+
+ if ( ncvars[ncvarid].natts )
+ {
+ int attnum;
+ int iatt;
+ nc_type attrtype;
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
+ const int attstringlen = 8192; char attstring[8192];
+ int nvatts = ncvars[ncvarid].natts;
+
+ for ( iatt = 0; iatt < nvatts; iatt++ )
+ {
+ attnum = ncvars[ncvarid].atts[iatt];
+ cdf_inq_attname(ncid, ncvarid, attnum, attname);
+ cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
+ cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
+
+ if ( attrtype == NC_SHORT || attrtype == NC_INT )
+ {
+ int attint[attlen];
+ cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
+ if ( attrtype == NC_SHORT )
+ vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint);
+ else
+ vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT32, (int)attlen, attint);
+ }
+ else if ( attrtype == NC_FLOAT || attrtype == NC_DOUBLE )
+ {
+ double attflt[attlen];
+ cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
+ if ( attrtype == NC_FLOAT )
+ vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt);
+ else
+ vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT64, (int)attlen, attflt);
+ }
+ else if ( xtypeIsText(attrtype) )
+ {
+ cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
+ vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring);
+ }
+ else
+ {
+ if ( CDI_Debug ) printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
+ }
+ }
+
+ if (ncvars[ncvarid].vct) Free(ncvars[ncvarid].vct);
+ if (ncvars[ncvarid].atts) Free(ncvars[ncvarid].atts);
+ ncvars[ncvarid].vct = NULL;
+ ncvars[ncvarid].atts = NULL;
+ }
+ }
+
+ /* release mem of not freed attributes */
+ for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ )
+ if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts);
+
+ if ( varids ) Free(varids);
+
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ if ( vlistInqVarCode(vlistID, varID) == -varID-1 )
+ {
+ const char *pname = vlistInqVarNamePtr(vlistID, varID);
+ size_t len = strlen(pname);
+ if ( len > 3 && isdigit((int) pname[3]) )
+ {
+ if ( memcmp("var", pname, 3) == 0 )
+ {
+ vlistDefVarCode(vlistID, varID, atoi(pname+3));
+ // vlistDestroyVarName(vlistID, varID);
+ }
+ }
+ else if ( len > 4 && isdigit((int) pname[4]) )
+ {
+ if ( memcmp("code", pname, 4) == 0 )
+ {
+ vlistDefVarCode(vlistID, varID, atoi(pname+4));
+ // vlistDestroyVarName(vlistID, varID);
+ }
+ }
+ else if ( len > 5 && isdigit((int) pname[5]) )
+ {
+ if ( memcmp("param", pname, 5) == 0 )
+ {
+ int pnum = -1, pcat = 255, pdis = 255;
+ sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis);
+ vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis));
+ // vlistDestroyVarName(vlistID, varID);
+ }
+ }
+ }
+ }
+
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int varInstID = vlistInqVarInstitut(vlistID, varID);
+ int varModelID = vlistInqVarModel(vlistID, varID);
+ int varTableID = vlistInqVarTable(vlistID, varID);
+ int code = vlistInqVarCode(vlistID, varID);
+ if ( cdiDefaultTableID != UNDEFID )
+ {
+ if ( tableInqParNamePtr(cdiDefaultTableID, code) )
+ {
+ vlistDestroyVarName(vlistID, varID);
+ vlistDestroyVarLongname(vlistID, varID);
+ vlistDestroyVarUnits(vlistID, varID);
+
+ if ( varTableID != UNDEFID )
+ {
+ vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code));
+ if ( tableInqParLongnamePtr(cdiDefaultTableID, code) )
+ vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code));
+ if ( tableInqParUnitsPtr(cdiDefaultTableID, code) )
+ vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code));
+ }
+ else
+ {
+ varTableID = cdiDefaultTableID;
+ }
+ }
+
+ if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID;
+ if ( cdiDefaultInstID != UNDEFID ) varInstID = cdiDefaultInstID;
+ }
+ if ( varInstID != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID);
+ if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID);
+ if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID);
+ }
+}
+
+static
+void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, int *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used)
+{
+ nc_type xtype;
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
+ enum { attstringlen = 65636 };
+ char attstring[attstringlen];
+ int iatt;
+
+ for ( iatt = 0; iatt < ngatts; iatt++ )
+ {
+ cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname);
+ cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
+ cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
+
+ if ( xtypeIsText(xtype) )
+ {
+ cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring);
+
+ size_t attstrlen = strlen(attstring);
+
+ if ( attlen > 0 && attstring[0] != 0 )
+ {
+ if ( strcmp(attname, "history") == 0 )
+ {
+ streamptr->historyID = iatt;
+ }
+ else if ( strcmp(attname, "institution") == 0 )
+ {
+ *instID = institutInq(0, 0, NULL, attstring);
+ if ( *instID == UNDEFID )
+ *instID = institutDef(0, 0, NULL, attstring);
+ }
+ else if ( strcmp(attname, "source") == 0 )
+ {
+ *modelID = modelInq(-1, 0, attstring);
+ if ( *modelID == UNDEFID )
+ *modelID = modelDef(-1, 0, attstring);
+ }
+ else if ( strcmp(attname, "Source") == 0 )
+ {
+ if ( strncmp(attstring, "UCLA-LES", 8) == 0 )
+ *ucla_les = TRUE;
+ }
/*
- if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT )
- if ( ncvars[ncvarid].scalefactor != 1 )
- Warning("attribute scale_factor not supported for atttype %d", atttype);
+ else if ( strcmp(attname, "Conventions") == 0 )
+ {
+ }
*/
- /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- int ncboundsid;
- int status = nc_inq_varid(ncid, attstring, &ncboundsid);
- if ( status == NC_NOERR )
- {
- ncvars[ncvarid].climatology = TRUE;
- ncvars[ncvarid].bounds = ncboundsid;
- cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
- cdfSetVar(ncvars, ncvarid, FALSE);
- }
- else
- Warning("%s - %s", nc_strerror(status), attstring);
- }
- else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 )
+ else if ( strcmp(attname, "CDI") == 0 )
+ {
+ }
+ else if ( strcmp(attname, "CDO") == 0 )
+ {
+ }
+ /*
+ else if ( strcmp(attname, "forecast_reference_time") == 0 )
+ {
+ memcpy(fcreftime, attstring, attstrlen+1);
+ }
+ */
+ else if ( strcmp(attname, "grid_file_uri") == 0 )
+ {
+ memcpy(gridfile, attstring, attstrlen+1);
+ }
+ else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 )
+ {
+ attstring[36] = 0;
+ cdiStr2UUID(attstring, uuidOfHGrid);
+ // printf("uuid: %d %s\n", attlen, attstring);
+ }
+ else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
+ {
+ attstring[36] = 0;
+ cdiStr2UUID(attstring, uuidOfVGrid);
+ }
+ else
+ {
+ if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
+ {
+ memcpy(gridfile, attstring, attstrlen+1);
+ }
+
+ vlistDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring);
+ }
+ }
+ }
+ else if ( xtype == NC_SHORT || xtype == NC_INT )
+ {
+ if ( strcmp(attname, "number_of_grid_used") == 0 )
+ {
+ (*number_of_grid_used) = UNDEFID;
+ cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used);
+ }
+ else
{
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- int ncboundsid;
- int status = nc_inq_varid(ncid, attstring, &ncboundsid);
- if ( status == NC_NOERR )
- {
- ncvars[ncvarid].bounds = ncboundsid;
- cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
- cdfSetVar(ncvars, ncvarid, FALSE);
- }
+ int attint[attlen];
+ cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
+ if ( xtype == NC_SHORT )
+ vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint);
else
- Warning("%s - %s", nc_strerror(status), attstring);
- }
- else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 )
- {
- ncvars[ncvarid].lformulaterms = TRUE;
+ vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT32, (int)attlen, attint);
}
- else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 )
+ }
+ else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE )
+ {
+ double attflt[attlen];
+ cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
+ if ( xtype == NC_FLOAT )
+ vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt);
+ else
+ vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT64, (int)attlen, attflt);
+ }
+ }
+}
+
+static
+int find_leadtime(int nvars, ncvar_t *ncvars)
+{
+ int leadtime_id = UNDEFID;
+
+ for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].stdname[0] )
+ {
+ if ( strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 )
{
- ncvars[ncvarid].lformula = TRUE;
+ leadtime_id = ncvarid;
+ break;
}
- else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) )
- {
- char *cell_measures = NULL, *cell_var = NULL;
+ }
+ }
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- char *pstring = attstring;
+ return (leadtime_id);
+}
- while ( isspace((int) *pstring) ) pstring++;
- cell_measures = pstring;
- while ( isalnum((int) *pstring) ) pstring++;
- *pstring++ = 0;
- while ( isspace((int) *pstring) ) pstring++;
- cell_var = pstring;
- while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++;
- *pstring++ = 0;
- /*
- printf("cell_measures >%s<\n", cell_measures);
- printf("cell_var >%s<\n", cell_var);
- */
- if ( memcmp(cell_measures, "area", 4) == 0 )
+static
+void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr,
+ int *time_has_units, int *time_has_bounds, int *time_climatology)
+{
+ int ncvarid;
+
+ if ( timedimid == UNDEFID )
+ {
+ char timeunits[CDI_MAX_NAME];
+
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 )
+ {
+ if ( ncvars[ncvarid].units[0] )
{
- int nc_cell_id;
- int status = nc_inq_varid(ncid, cell_var, &nc_cell_id);
- if ( status == NC_NOERR )
+ strcpy(timeunits, ncvars[ncvarid].units);
+ strtolower(timeunits);
+
+ if ( isTimeUnits(timeunits) )
{
- ncvars[ncvarid].cellarea = nc_cell_id;
- /* ncvars[nc_cell_id].isvar = UNDEFID; */
- cdfSetVar(ncvars, nc_cell_id, FALSE);
+ streamptr->basetime.ncvarid = ncvarid;
+ break;
}
- else
- Warning("%s - %s", nc_strerror(status), cell_var);
}
- else
- {
- Warning("%s has an unexpected contents: %s", attname, cell_measures);
- }
- cdfSetVar(ncvars, ncvarid, TRUE);
}
- /*
- else if ( strcmp(attname, "coordinates") == 0 )
- {
- char *pstring, *xvarname = NULL, *yvarname = NULL;
+ }
+ }
+ else
+ {
+ int ltimevar = FALSE;
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- pstring = attstring;
+ if ( ncdims[timedimid].ncvarid != UNDEFID )
+ {
+ streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid;
+ ltimevar = TRUE;
+ }
- while ( isspace((int) *pstring) ) pstring++;
- xvarname = pstring;
- while ( isgraph((int) *pstring) ) pstring++;
- *pstring++ = 0;
- while ( isspace((int) *pstring) ) pstring++;
- yvarname = pstring;
- while ( isgraph((int) *pstring) ) pstring++;
- *pstring++ = 0;
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ if ( ncvarid != streamptr->basetime.ncvarid &&
+ ncvars[ncvarid].ndims == 1 &&
+ timedimid == ncvars[ncvarid].dimids[0] &&
+ !xtypeIsText(ncvars[ncvarid].xtype) &&
+ isTimeAxisUnits(ncvars[ncvarid].units) )
+ {
+ ncvars[ncvarid].isvar = FALSE;
- cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid);
- cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid);
+ if ( !ltimevar )
+ {
+ streamptr->basetime.ncvarid = ncvarid;
+ ltimevar = TRUE;
+ if ( CDI_Debug )
+ fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name);
+ }
+ else
+ {
+ Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name);
+ }
+ }
- cdfSetVar(ncvars, ncvars[ncvarid].xvarid, FALSE);
- cdfSetVar(ncvars, ncvars[ncvarid].yvarid, FALSE);
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- */
- else if ( (strcmp(attname, "associate") == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) )
+ if ( ltimevar == FALSE ) /* search for WRF time description */
+ {
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ if ( ncvarid != streamptr->basetime.ncvarid &&
+ ncvars[ncvarid].ndims == 2 &&
+ timedimid == ncvars[ncvarid].dimids[0] &&
+ xtypeIsText(ncvars[ncvarid].xtype) &&
+ ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
+ {
+ streamptr->basetime.ncvarid = ncvarid;
+ streamptr->basetime.lwrf = TRUE;
+ break;
+ }
+ }
+
+ /* time varID */
+ ncvarid = streamptr->basetime.ncvarid;
+
+ if ( ncvarid == UNDEFID )
+ {
+ Warning("Time variable >%s< not found!", ncdims[timedimid].name);
+ }
+ }
+
+ /* time varID */
+ ncvarid = streamptr->basetime.ncvarid;
+
+ if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == FALSE )
+ {
+ if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = TRUE;
+
+ if ( ncvars[ncvarid].bounds != UNDEFID )
+ {
+ int nbdims = ncvars[ncvars[ncvarid].bounds].ndims;
+ if ( nbdims == 2 )
{
- int status;
- char *varname = NULL;
- int lstop = FALSE;
- int dimvarid;
+ int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len;
+ if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] )
+ {
+ *time_has_bounds = TRUE;
+ streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds;
+ if ( ncvars[ncvarid].climatology ) *time_climatology = TRUE;
+ }
+ }
+ }
+ }
+}
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- char *pstring = attstring;
+static
+void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize)
+{
+ /* find ECHAM VCT */
+ int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID;
- for ( int i = 0; i < MAX_COORDVARS; i++ )
+ for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ size_t len = strlen(ncvars[ncvarid].name);
+ if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' )
+ {
+ if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai
{
- while ( isspace((int) *pstring) ) pstring++;
- if ( *pstring == 0 ) break;
- varname = pstring;
- while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
- if ( *pstring == 0 ) lstop = TRUE;
- *pstring++ = 0;
+ vcta_id = ncvarid;
+ nvcth_id = ncvars[ncvarid].dimids[0];
+ ncvars[ncvarid].isvar = FALSE;
+ }
+ else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi
+ {
+ vctb_id = ncvarid;
+ nvcth_id = ncvars[ncvarid].dimids[0];
+ ncvars[ncvarid].isvar = FALSE;
+ }
+ else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' )
+ {
+ ncvars[ncvarid].isvar = FALSE; // hyam or hybm
+ }
+ }
+ }
+ }
+
+ /* read VCT */
+ if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID )
+ {
+ size_t vctsize = ncdims[nvcth_id].len;
+ vctsize *= 2;
+ *vct = (double *) Malloc(vctsize*sizeof(double));
+ cdf_get_var_double(fileID, vcta_id, *vct);
+ cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2);
+ *pvctsize = vctsize;
+ }
+}
+
+
+int cdfInqContents(stream_t *streamptr)
+{
+ int ndims, nvars, ngatts, unlimdimid;
+ int ncvarid;
+ int ncdimid;
+ size_t ntsteps;
+ int timedimid = -1;
+ int *varids;
+ int nvarids;
+ int time_has_units = FALSE;
+ int time_has_bounds = FALSE;
+ int time_climatology = FALSE;
+ int leadtime_id = UNDEFID;
+ int nvars_data;
+ int instID = UNDEFID;
+ int modelID = UNDEFID;
+ int taxisID;
+ int i;
+ int calendar = UNDEFID;
+ ncdim_t *ncdims;
+ ncvar_t *ncvars = NULL;
+ int format = 0;
+ int ucla_les = FALSE;
+ unsigned char uuidOfHGrid[CDI_UUID_SIZE];
+ unsigned char uuidOfVGrid[CDI_UUID_SIZE];
+ char gridfile[8912];
+ char fcreftime[CDI_MAX_NAME];
+ int number_of_grid_used = UNDEFID;
+
+ memset(uuidOfHGrid, 0, CDI_UUID_SIZE);
+ memset(uuidOfVGrid, 0, CDI_UUID_SIZE);
+ gridfile[0] = 0;
+ fcreftime[0] = 0;
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+
+ if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+
+#if defined (HAVE_NETCDF4)
+ nc_inq_format(fileID, &format);
+#endif
+
+ cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid);
+
+ if ( CDI_Debug )
+ Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts);
+
+ if ( ndims == 0 )
+ {
+ Warning("ndims = %d", ndims);
+ return (CDI_EUFSTRUCT);
+ }
+
+ /* alloc ncdims */
+ ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t));
+ init_ncdims(ndims, ncdims);
+
+ if ( nvars > 0 )
+ {
+ /* alloc ncvars */
+ ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t));
+ init_ncvars(nvars, ncvars);
+
+ for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
+ ncvars[ncvarid].ncid = fileID;
+ }
+
+#if defined (TEST_GROUPS)
+#if defined (HAVE_NETCDF4)
+ if ( format == NC_FORMAT_NETCDF4 )
+ {
+ int ncid;
+ int numgrps;
+ int ncids[NC_MAX_VARS];
+ char name1[CDI_MAX_NAME];
+ int gndims, gnvars, gngatts, gunlimdimid;
+ nc_inq_grps(fileID, &numgrps, ncids);
+ for ( int i = 0; i < numgrps; ++i )
+ {
+ ncid = ncids[i];
+ nc_inq_grpname (ncid, name1);
+ cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid);
+
+ if ( CDI_Debug )
+ Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts);
+
+ if ( gndims == 0 )
+ {
+ }
+ }
+ }
+#endif
+#endif
+
+ if ( nvars == 0 )
+ {
+ Warning("nvars = %d", nvars);
+ return (CDI_EUFSTRUCT);
+ }
+
+ /* scan global attributes */
+ scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les,
+ uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used);
+
+ /* find time dim */
+ if ( unlimdimid >= 0 )
+ timedimid = unlimdimid;
+ else
+ timedimid = cdfTimeDimID(fileID, ndims, nvars);
+
+ streamptr->basetime.ncdimid = timedimid;
+
+ if ( timedimid != UNDEFID )
+ cdf_inq_dimlen(fileID, timedimid, &ntsteps);
+ else
+ ntsteps = 0;
+
+ if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps);
+ if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid);
+
+ /* read ncdims */
+ for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ {
+ cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len);
+ cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name);
+ if ( timedimid == ncdimid )
+ ncdims[ncdimid].dimtype = T_AXIS;
+ }
+
+ if ( CDI_Debug ) printNCvars(ncvars, nvars, "cdfScanVarAttributes");
+
+ /* scan attributes of all variables */
+ cdfScanVarAttributes(nvars, ncvars, ncdims, timedimid, modelID, format);
+
+
+ if ( CDI_Debug ) printNCvars(ncvars, nvars, "find coordinate vars");
+
+ /* find coordinate vars */
+ for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ {
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].ndims == 1 )
+ {
+ if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] )
+ {
+ if ( ncvars[ncvarid].isvar != FALSE ) cdfSetVar(ncvars, ncvarid, TRUE);
+ }
+ else
+ {
+ // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
+ }
+ // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
+
+ if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID )
+ if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 )
+ {
+ ncdims[ncdimid].ncvarid = ncvarid;
+ ncvars[ncvarid].isvar = FALSE;
+ }
+ }
+ }
+ }
+
+ /* find time vars */
+ find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology);
+
+ leadtime_id = find_leadtime(nvars, ncvars);
+ if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE;
+
+ /* check ncvars */
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( timedimid != UNDEFID )
+ if ( ncvars[ncvarid].isvar == -1 &&
+ ncvars[ncvarid].ndims > 1 &&
+ timedimid == ncvars[ncvarid].dimids[0] )
+ cdfSetVar(ncvars, ncvarid, TRUE);
+
+ if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 )
+ cdfSetVar(ncvars, ncvarid, FALSE);
+
+ //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 )
+ if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 )
+ cdfSetVar(ncvars, ncvarid, TRUE);
+
+ if ( ncvars[ncvarid].isvar == -1 )
+ {
+ ncvars[ncvarid].isvar = 0;
+ Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name);
+ continue;
+ }
+
+ if ( ncvars[ncvarid].ndims > 4 )
+ {
+ ncvars[ncvarid].isvar = 0;
+ Warning("%d dimensional variables are not supported, skipped variable %s!",
+ ncvars[ncvarid].ndims, ncvars[ncvarid].name);
+ continue;
+ }
+
+ if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID )
+ {
+ ncvars[ncvarid].isvar = 0;
+ Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!",
+ ncvars[ncvarid].ndims, ncvars[ncvarid].name);
+ continue;
+ }
+
+ if ( xtypeIsText(ncvars[ncvarid].xtype) )
+ {
+ ncvars[ncvarid].isvar = 0;
+ continue;
+ }
+
+ if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 )
+ {
+ ncvars[ncvarid].isvar = 0;
+ Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name);
+ continue;
+ }
+
+ if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 )
+ {
+ if ( timedimid == ncvars[ncvarid].dimids[0] )
+ {
+ ncvars[ncvarid].isvar = 0;
+ Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name);
+ continue;
+ }
+ }
+ }
+
+ /* verify coordinate vars - first scan (dimname == varname) */
+ verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid);
+
+ /* verify coordinate vars - second scan (all other variables) */
+ verify_coordinate_vars_2(nvars, ncvars);
+
+ if ( CDI_Debug ) printNCvars(ncvars, nvars, "verify_coordinate_vars");
+
+ if ( ucla_les == TRUE )
+ {
+ for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ {
+ ncvarid = ncdims[ncdimid].ncvarid;
+ if ( ncvarid != -1 )
+ {
+ if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' )
+ {
+ if ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS;
+ else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS;
+ else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS;
+ }
+ }
+ }
+ }
+ /*
+ for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ {
+ ncvarid = ncdims[ncdimid].ncvarid;
+ if ( ncvarid != -1 )
+ {
+ printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units);
+ if ( ncdims[ncdimid].dimtype == X_AXIS )
+ printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name);
+ if ( ncdims[ncdimid].dimtype == Y_AXIS )
+ printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name);
+ if ( ncdims[ncdimid].dimtype == Z_AXIS )
+ printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name);
+ if ( ncdims[ncdimid].dimtype == T_AXIS )
+ printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name);
+
+ if ( ncvars[ncvarid].islon )
+ printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name);
+ if ( ncvars[ncvarid].islat )
+ printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name);
+ if ( ncvars[ncvarid].islev )
+ printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name);
+ }
+ }
+ */
+
+ /* Set coordinate varids (att: associate) */
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ {
+ if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].ncoordvars )
+ {
+ /* ndims = ncvars[ncvarid].ndims; */
+ ndims = ncvars[ncvarid].ncoordvars;
+ for ( i = 0; i < ndims; i++ )
+ {
+ if ( ncvars[ncvars[ncvarid].coordvarids[i]].islon )
+ ncvars[ncvarid].xvarid = ncvars[ncvarid].coordvarids[i];
+ else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islat )
+ ncvars[ncvarid].yvarid = ncvars[ncvarid].coordvarids[i];
+ else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islev )
+ ncvars[ncvarid].zvarid = ncvars[ncvarid].coordvarids[i];
+ }
+ }
+ }
+
+ /* set dim type */
+ setDimType(nvars, ncvars, ncdims);
+
+ /* read ECHAM VCT if present */
+ size_t vctsize = 0;
+ double *vct = NULL;
+ read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize);
+
+
+ if ( CDI_Debug ) printNCvars(ncvars, nvars, "define_all_grids");
+
+ /* define all grids */
+ define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used);
+
+
+ /* define all zaxes */
+ define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
+ if ( vct ) Free(vct);
+
+
+ /* select vars */
+ varids = (int *) Malloc((size_t)nvars * sizeof (int));
+ nvarids = 0;
+ for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
+
+ nvars_data = nvarids;
+
+ if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid);
+ if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+ if ( CDI_Debug ) Message("nvars_data = %d", nvars_data);
+
+
+ if ( nvars_data == 0 )
+ {
+ streamptr->ntsteps = 0;
+ return (CDI_EUFSTRUCT);
+ }
+
+ if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
+ ntsteps = 1;
+
+ streamptr->ntsteps = (long)ntsteps;
+
+ /* define all data variables */
+ define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
+
+
+ cdiCreateTimesteps(streamptr);
+
+ /* time varID */
+ int nctimevarid = streamptr->basetime.ncvarid;
+
+ if ( time_has_units )
+ {
+ taxis_t *taxis = &streamptr->tsteps[0].taxis;
+
+ if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 )
+ {
+ nctimevarid = UNDEFID;
+ streamptr->basetime.ncvarid = UNDEFID;
+ }
+
+ if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE )
+ {
+ streamptr->basetime.leadtimeid = leadtime_id;
+ taxis->type = TAXIS_FORECAST;
+
+ int timeunit = -1;
+ if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units);
+ if ( timeunit == -1 ) timeunit = taxis->unit;
+ taxis->fc_unit = timeunit;
+
+ setForecastTime(fcreftime, taxis);
+ }
+ }
+
+ if ( time_has_bounds )
+ {
+ streamptr->tsteps[0].taxis.has_bounds = TRUE;
+ if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = TRUE;
+ }
+
+ if ( nctimevarid != UNDEFID )
+ {
+ taxis_t *taxis = &streamptr->tsteps[0].taxis;
+ ptaxisDefName(taxis, ncvars[nctimevarid].name);
+ if ( ncvars[nctimevarid].longname[0] )
+ ptaxisDefLongname(taxis, ncvars[nctimevarid].longname);
+ }
+
+ if ( nctimevarid != UNDEFID )
+ if ( ncvars[nctimevarid].calendar == TRUE )
+ {
+ enum {attstringlen = 8192};
+ char attstring[attstringlen];
+
+ cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring);
+ strtolower(attstring);
+
+ if ( memcmp(attstring, "standard", 8) == 0 ||
+ memcmp(attstring, "gregorian", 9) == 0 )
+ calendar = CALENDAR_STANDARD;
+ else if ( memcmp(attstring, "none", 4) == 0 )
+ calendar = CALENDAR_NONE;
+ else if ( memcmp(attstring, "proleptic", 9) == 0 )
+ calendar = CALENDAR_PROLEPTIC;
+ else if ( memcmp(attstring, "360", 3) == 0 )
+ calendar = CALENDAR_360DAYS;
+ else if ( memcmp(attstring, "365", 3) == 0 ||
+ memcmp(attstring, "noleap", 6) == 0 )
+ calendar = CALENDAR_365DAYS;
+ else if ( memcmp(attstring, "366", 3) == 0 ||
+ memcmp(attstring, "all_leap", 8) == 0 )
+ calendar = CALENDAR_366DAYS;
+ else
+ Warning("calendar >%s< unsupported!", attstring);
+ }
+
+ if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST )
+ {
+ taxisID = taxisCreate(TAXIS_FORECAST);
+ }
+ else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE )
+ {
+ taxisID = taxisCreate(TAXIS_RELATIVE);
+ }
+ else
+ {
+ taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ if ( !time_has_units )
+ {
+ taxisDefTunit(taxisID, TUNIT_DAY);
+ streamptr->tsteps[0].taxis.unit = TUNIT_DAY;
+ }
+ }
+
+
+ if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE )
+ {
+ calendar = CALENDAR_STANDARD;
+ }
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wstrict-overflow"
+#endif
+ if ( calendar != UNDEFID )
+ {
+ taxis_t *taxis = &streamptr->tsteps[0].taxis;
+ taxis->calendar = calendar;
+ taxisDefCalendar(taxisID, calendar);
+ }
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic pop
+#endif
+
+ vlistDefTaxis(vlistID, taxisID);
+
+ streamptr->curTsID = 0;
+ streamptr->rtsteps = 1;
+
+ (void) cdfInqTimestep(streamptr, 0);
+
+ cdfCreateRecords(streamptr, 0);
+
+ /* free ncdims */
+ Free(ncdims);
+
+ /* free ncvars */
+ Free(ncvars);
+
+ return (0);
+}
+
+static
+void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis)
+{
+ size_t start[2], count[2];
+ char stvalue[32];
+ start[0] = (size_t) tsID; start[1] = 0;
+ count[0] = 1; count[1] = 19;
+ stvalue[0] = 0;
+ cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
+ stvalue[19] = 0;
+ {
+ int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0;
+ if ( strlen(stvalue) == 19 )
+ sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
+ taxis->vdate = cdiEncodeDate(year, month, day);
+ taxis->vtime = cdiEncodeTime(hour, minute, second);
+ taxis->type = TAXIS_ABSOLUTE;
+ }
+}
+
+static
+double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache)
+{
+ double timevalue = 0;
+ size_t index = (size_t) tsID;
+
+ if ( tcache )
+ {
+ if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) )
+ {
+ int maxvals = MAX_TIMECACHE_SIZE;
+ tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE;
+ if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE;
+ tcache->size = maxvals;
+ index = (size_t) tcache->startid;
+ // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals);
+ for ( int ival = 0; ival < maxvals; ++ival )
+ {
+ cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
+ if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+ tcache->cache[ival] = timevalue;
+ index++;
+ }
+ }
+
+ timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE];
+ }
+ else
+ {
+ cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
+ if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+ }
+
+ return timevalue;
+}
- status = nc_inq_varid(ncid, varname, &dimvarid);
- if ( status == NC_NOERR )
- {
- cdfSetVar(ncvars, dimvarid, FALSE);
- if ( cdiIgnoreAttCoordinates == FALSE )
- {
- ncvars[ncvarid].coordvarids[i] = dimvarid;
- ncvars[ncvarid].ncoordvars++;
- }
- }
- else
- {
- int k;
- for ( k = 0; k < nchecked_vars; ++k )
- if ( strcmp(checked_vars[k], varname) == 0 ) break;
- if ( k == nchecked_vars )
- {
- if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname);
- Warning("%s - %s", nc_strerror(status), varname);
- }
- }
+int cdfInqTimestep(stream_t * streamptr, int tsID)
+{
+ long nrecs = 0;
+ double timevalue;
+ int fileID;
+ taxis_t *taxis;
- if ( lstop ) break;
- }
+ if ( CDI_Debug ) Message("streamID = %d tsID = %d", streamptr->self, tsID);
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) )
- {
- int status;
- char *varname = NULL;
- int lstop = FALSE;
- int dimvarid;
+ if ( tsID < 0 ) Error("unexpected tsID = %d", tsID);
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- char *pstring = attstring;
+ if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 )
+ {
+ cdfCreateRecords(streamptr, tsID);
- for ( int i = 0; i < MAX_AUXVARS; i++ )
- {
- while ( isspace((int) *pstring) ) pstring++;
- if ( *pstring == 0 ) break;
- varname = pstring;
- while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++;
- if ( *pstring == 0 ) lstop = TRUE;
- *pstring++ = 0;
+ taxis = &streamptr->tsteps[tsID].taxis;
+ if ( tsID > 0 )
+ ptaxisCopy(taxis, &streamptr->tsteps[0].taxis);
- status = nc_inq_varid(ncid, varname, &dimvarid);
- if ( status == NC_NOERR )
- {
- cdfSetVar(ncvars, dimvarid, FALSE);
- // if ( cdiIgnoreAttCoordinates == FALSE )
- {
- ncvars[ncvarid].auxvarids[i] = dimvarid;
- ncvars[ncvarid].nauxvars++;
- }
- }
- else
- Warning("%s - %s", nc_strerror(status), varname);
+ timevalue = tsID;
- if ( lstop ) break;
- }
+ int nctimevarid = streamptr->basetime.ncvarid;
+ if ( nctimevarid != UNDEFID )
+ {
+ fileID = streamptr->fileID;
+ size_t index = (size_t)tsID;
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- int nc_gmap_id;
- int status = nc_inq_varid(ncid, attstring, &nc_gmap_id);
- if ( status == NC_NOERR )
+ if ( streamptr->basetime.lwrf )
+ {
+ wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
+ }
+ else
+ {
+#if defined (USE_TIMECACHE)
+ if ( streamptr->basetime.timevar_cache == NULL )
{
- ncvars[ncvarid].gmapid = nc_gmap_id;
- cdfSetVar(ncvars, ncvars[ncvarid].gmapid, FALSE);
+ streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t));
+ streamptr->basetime.timevar_cache->size = 0;
+ streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps;
}
- else
- Warning("%s - %s", nc_strerror(status), attstring);
+#endif
+ timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache);
+ cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime);
+ }
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- strtolower(attstring);
+ int nctimeboundsid = streamptr->basetime.ncvarboundsid;
+ if ( nctimeboundsid != UNDEFID )
+ {
+ size_t start[2], count[2];
+ start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
+ cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
+ if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
- if ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN;
- else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP;
+ cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb);
- if ( ncvars[ncvarid].ndims == 1 )
- {
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
- ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
- }
- }
- else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval);
- ncvars[ncvarid].deffillval = TRUE;
- /* cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval);
- ncvars[ncvarid].defmissval = TRUE;
- /* cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 )
- {
- if ( ncvars[ncvarid].lvalidrange == FALSE )
- {
- extern int cdiIgnoreValidRange;
- int lignore = FALSE;
- if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
- if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange);
- ncvars[ncvarid].lvalidrange = TRUE;
- if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 )
- ncvars[ncvarid].lunsigned = TRUE;
- /* cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( lignore )
- {
- Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name);
- }
- }
- }
- else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 )
- {
- if ( ncvars[ncvarid].lvalidrange == FALSE )
- {
- extern int cdiIgnoreValidRange;
- int lignore = FALSE;
- if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
- if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]);
- ncvars[ncvarid].lvalidrange = TRUE;
- }
- else if ( lignore )
- {
- Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name);
- }
- }
- }
- else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 )
+ start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1;
+ cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
+ if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+
+ cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub);
+ }
+
+ int leadtimeid = streamptr->basetime.leadtimeid;
+ if ( leadtimeid != UNDEFID )
{
- if ( ncvars[ncvarid].lvalidrange == FALSE )
- {
- extern int cdiIgnoreValidRange;
- int lignore = FALSE;
- if ( xtypeIsFloat(atttype) != xtypeIsFloat(xtype) ) lignore = TRUE;
- if ( cdiIgnoreValidRange == FALSE && lignore == FALSE )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]);
- ncvars[ncvarid].lvalidrange = TRUE;
- }
- else if ( lignore )
- {
- Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name);
- }
- }
+ timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
+ cdiSetForecastPeriod(timevalue, taxis);
}
- else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- strtolower(attstring);
+ }
+ }
- if ( memcmp(attstring, "true", 4) == 0 )
- {
- ncvars[ncvarid].lunsigned = TRUE;
- /*
- ncvars[ncvarid].lvalidrange = TRUE;
- ncvars[ncvarid].validrange[0] = 0;
- ncvars[ncvarid].validrange[1] = 255;
- */
- }
- /* cdfSetVar(ncvars, ncvarid, TRUE); */
- }
- else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- strtolower(attstring);
+ streamptr->curTsID = tsID;
+ nrecs = streamptr->tsteps[tsID].nrecs;
- if ( memcmp(attstring, "ignore", 6) == 0 )
- {
- ncvars[ncvarid].ignore = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- }
- }
- else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- attlen = strlen(attstring);
+ return ((int) nrecs);
+}
- if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 )
- {
- Warning("Unexpected axis attribute length for %s, ignored!", name);
- }
- else if ( nvdims == 0 && attlen == 1 )
- {
- if ( attstring[0] == 'z' || attstring[0] == 'Z' )
- {
- cdfSetVar(ncvars, ncvarid, FALSE);
- ncvars[ncvarid].islev = TRUE;
- }
- }
- else
- {
- strtolower(attstring);
- int i;
- for ( i = 0; i < (int)attlen; ++i )
- {
- if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' &&
- attstring[i] != 'y' && attstring[i] != 'x' )
- {
- Warning("Unexpected character in axis attribute for %s, ignored!", name);
- break;
- }
- }
- if ( i == (int) attlen && (int) attlen == nvdims )
- {
- while ( attlen-- )
- {
- if ( (int) attstring[attlen] == 't' )
- {
- if ( attlen != 0 ) Warning("axis attribute 't' not on first position");
- cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS);
- }
- else if ( (int) attstring[attlen] == 'z' )
- {
- ncvars[ncvarid].zdim = dimidsp[attlen];
- cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS);
+void cdfDefHistory(stream_t *streamptr, int size, const char *history)
+{
+ int ncid = streamptr->fileID;
+ cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history);
+}
- if ( ncvars[ncvarid].ndims == 1 )
- {
- cdfSetVar(ncvars, ncvarid, FALSE);
- ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS;
- }
- }
- else if ( (int) attstring[attlen] == 'y' )
- {
- ncvars[ncvarid].ydim = dimidsp[attlen];
- cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS);
- if ( ncvars[ncvarid].ndims == 1 )
- {
- cdfSetVar(ncvars, ncvarid, FALSE);
- ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS;
- }
- }
- else if ( (int) attstring[attlen] == 'x' )
- {
- ncvars[ncvarid].xdim = dimidsp[attlen];
- cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS);
+int cdfInqHistorySize(stream_t *streamptr)
+{
+ size_t size = 0;
+ int ncid = streamptr->fileID;
+ if ( streamptr->historyID != UNDEFID )
+ cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size);
- if ( ncvars[ncvarid].ndims == 1 )
- {
- cdfSetVar(ncvars, ncvarid, FALSE);
- ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS;
- }
- }
- }
- }
- }
- }
- else if ( ( strcmp(attname, "realization") == 0 ) ||
- ( strcmp(attname, "ensemble_members") == 0 ) ||
- ( strcmp(attname, "forecast_init_type") == 0 ) )
- {
- int temp;
+ return ((int) size);
+}
- if( ncvars[ncvarid].ensdata == NULL )
- ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) );
- cdfGetAttInt(ncid, ncvarid, attname, 1, &temp);
+void cdfInqHistoryString(stream_t *streamptr, char *history)
+{
+ int ncid = streamptr->fileID;
+ if ( streamptr->historyID != UNDEFID )
+ {
+ nc_type atttype;
+ cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype);
- if( strcmp(attname, "realization") == 0 )
- ncvars[ncvarid].ensdata->ens_index = temp;
- else if( strcmp(attname, "ensemble_members") == 0 )
- ncvars[ncvarid].ensdata->ens_count = temp;
- else if( strcmp(attname, "forecast_init_type") == 0 )
- ncvars[ncvarid].ensdata->forecast_init_type = temp;
+ if ( atttype == NC_CHAR )
+ {
+ cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
+ }
+#if defined (HAVE_NETCDF4)
+ else if ( atttype == NC_STRING )
+ {
+ // ToDo
+ Warning("History attribute with type NC_STRING unsupported!");
+ }
+#endif
+ }
+}
- cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else
- {
- if ( ncvars[ncvarid].natts == 0 )
- ncvars[ncvarid].atts
- = (int *) Malloc((size_t)nvatts * sizeof (int));
- ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt;
- /*
- int attrint;
- double attrflt;
- nc_type attrtype;
- cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
- cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
- if ( attlen == 1 && (attrtype == NC_INT || attrtype == NC_SHORT) )
- {
- cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint);
- printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint);
- }
- else if ( attlen == 1 && (attrtype == NC_FLOAT || attrtype == NC_DOUBLE) )
- {
- cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt);
- printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt);
- }
- else if ( attrtype == NC_CHAR )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- attstring[attlen] = 0;
- printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring);
- }
- else
- printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
- */
- }
- }
+void cdfDefVars(stream_t *streamptr)
+{
+ int vlistID = streamptr->vlistID;
+ if ( vlistID == UNDEFID )
+ Error("Internal problem! vlist undefined for streamptr %p", streamptr);
+
+ int ngrids = vlistNgrids(vlistID);
+ int nzaxis = vlistNzaxis(vlistID);
+ /*
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+ */
+ if ( ngrids > 0 )
+ for ( int index = 0; index < ngrids; index++ )
+ {
+ int gridID = vlistGrid(vlistID, index);
+ cdfDefGrid(streamptr, gridID);
+ }
+
+ if ( nzaxis > 0 )
+ for ( int index = 0; index < nzaxis; index++ )
+ {
+ int zaxisID = vlistZaxis(vlistID, index);
+ if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID);
+ }
+
+ /* define time first!!!
+ int nvars = vlistNvars(vlistID);
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int ncvarid = cdfDefVar(streamptr, varID);
}
+ */
+}
+#endif
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#ifndef CDI_DATETIME_H
+#define CDI_DATETIME_H
- for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]);
+typedef struct
+{
+ long date;
+ long time;
}
+DateTime;
-static
-void setDimType(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
+static inline int
+datetimeCmp(DateTime dt1, DateTime dt2)
{
- int ndims;
- int ncvarid, ncdimid;
- int i;
+ return 2 * ((dt1.date > dt2.date) - (dt1.date < dt2.date))
+ + (dt1.time > dt2.time) - (dt1.time < dt2.time);
+}
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- if ( ncvars[ncvarid].isvar == TRUE )
- {
- int lxdim = 0, lydim = 0, lzdim = 0/* , ltdim = 0 */;
- ndims = ncvars[ncvarid].ndims;
- for ( i = 0; i < ndims; i++ )
- {
- ncdimid = ncvars[ncvarid].dimids[i];
- if ( ncdims[ncdimid].dimtype == X_AXIS ) cdfSetDim(ncvars, ncvarid, i, X_AXIS);
- else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
- else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
- else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdfSetDim(ncvars, ncvarid, i, T_AXIS);
- }
- if ( CDI_Debug )
- {
- Message("var %d %s", ncvarid, ncvars[ncvarid].name);
- for ( i = 0; i < ndims; i++ )
- printf(" dim%d type=%d ", i, ncvars[ncvarid].dimtype[i]);
- printf("\n");
- }
+#endif
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#ifndef _STREAM_CGRIBEX_H
+#define _STREAM_CGRIBEX_H
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = TRUE;
- else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = TRUE;
- else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = TRUE;
- /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = TRUE; */
- }
+int cgribexScanTimestep1(stream_t * streamptr);
+int cgribexScanTimestep2(stream_t * streamptr);
+int cgribexScanTimestep(stream_t * streamptr);
- if ( lxdim == FALSE && ncvars[ncvarid].xvarid != UNDEFID )
- {
- if ( ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = TRUE;
- }
+int cgribexDecode(int memtype, void *gribbuffer, int gribsize, void *data, long datasize,
+ int unreduced, int *nmiss, double missval);
+
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize);
+
+#endif /* _STREAM_CGRIBEX_H */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
+#endif
+
+#include <limits.h>
+#include <stdio.h>
+
+
+#if defined (HAVE_LIBCGRIBEX)
+#endif
- if ( lydim == FALSE && ncvars[ncvarid].yvarid != UNDEFID )
- {
- if ( ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = TRUE;
- }
+typedef struct {
+ int param;
+ int level1;
+ int level2;
+ int ltype;
+ int tsteptype;
+} compvar_t;
- // if ( ndims > 1 )
- for ( i = ndims-1; i >= 0; i-- )
- {
- if ( ncvars[ncvarid].dimtype[i] == -1 )
- {
- if ( lxdim == FALSE )
- {
- cdfSetDim(ncvars, ncvarid, i, X_AXIS);
- lxdim = TRUE;
- }
- else if ( lydim == FALSE && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED )
- {
- cdfSetDim(ncvars, ncvarid, i, Y_AXIS);
- lydim = TRUE;
- }
- else if ( lzdim == FALSE )
- {
- cdfSetDim(ncvars, ncvarid, i, Z_AXIS);
- lzdim = TRUE;
- }
- }
- }
- }
- }
-}
-/* verify coordinate vars - first scan (dimname == varname) */
+#if defined (HAVE_LIBCGRIBEX)
static
-void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid)
+int cgribexGetGridType(int *isec2)
{
- int ncdimid, ncvarid;
+ int gridtype = GRID_GENERIC;
- for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ switch (ISEC2_GridType)
{
- ncvarid = ncdims[ncdimid].ncvarid;
- if ( ncvarid != -1 )
- {
- if ( ncvars[ncvarid].dimids[0] == timedimid )
- {
- ncvars[ncvarid].istime = TRUE;
- ncdims[ncdimid].dimtype = T_AXIS;
- continue;
- }
-
- if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue;
+ case GRIB1_GTYPE_LATLON: { if ( ISEC2_Reduced ) break; }
+ case GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT; break; }
+ case GRIB1_GTYPE_LCC: { gridtype = GRID_LCC; break; }
+ case GRIB1_GTYPE_GAUSSIAN: { if ( ISEC2_Reduced )
+ gridtype = GRID_GAUSSIAN_REDUCED;
+ else
+ gridtype = GRID_GAUSSIAN;
+ break;
+ }
+ case GRIB1_GTYPE_SPECTRAL: { gridtype = GRID_SPECTRAL; break; }
+ case GRIB1_GTYPE_GME: { gridtype = GRID_GME; break; }
+ }
- if ( ncvars[ncvarid].units[0] != 0 )
- {
- if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
- {
- ncvars[ncvarid].islon = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
- ncdims[ncdimid].dimtype = X_AXIS;
- }
- else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
- {
- ncvars[ncvarid].islat = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
- ncdims[ncdimid].dimtype = Y_AXIS;
- }
- else if ( unitsIsPressure(ncvars[ncvarid].units) )
- {
- ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
- }
- else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
- {
- if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
- else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
- else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
- else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
- else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
- }
- else if ( isDBLAxis(ncvars[ncvarid].longname) )
- {
- ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
- }
- else if ( unitsIsMeter(ncvars[ncvarid].units) )
- {
- if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
- ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
- else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
- ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
- }
- }
- else
- {
- if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 ||
- strcmp(ncvars[ncvarid].longname, "generalized height") == 0) &&
- strcmp(ncvars[ncvarid].stdname, "height") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE;
- }
+ return (gridtype);
+}
- if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
- ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
- {
- if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
- {
- ncvars[ncvarid].islon = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, X_AXIS);
- ncdims[ncdimid].dimtype = X_AXIS;
- continue;
- }
- else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
- {
- ncvars[ncvarid].islat = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, Y_AXIS);
- ncdims[ncdimid].dimtype = Y_AXIS;
- continue;
- }
- }
+static
+int cgribexGetIsRotated(int *isec2)
+{
+ int isRotated = 0;
- if ( ncvars[ncvarid].zaxistype != UNDEFID )
- {
- ncvars[ncvarid].islev = TRUE;
- cdfSetVar(ncvars, ncvarid, FALSE);
- cdfSetDim(ncvars, ncvarid, 0, Z_AXIS);
- ncdims[ncdimid].dimtype = Z_AXIS;
- }
- }
+ if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
+ {
+ isRotated = 1;
}
+
+ return (isRotated);
}
-/* verify coordinate vars - second scan (all other variables) */
static
-void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
+int cgribexGetZaxisHasBounds(int grb_ltype)
{
- int ncvarid;
+ int lbounds = 0;
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ switch (grb_ltype)
{
- if ( ncvars[ncvarid].isvar == 0 )
- {
- if ( ncvars[ncvarid].units[0] != 0 )
- {
- if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
- {
- ncvars[ncvarid].islon = TRUE;
- continue;
- }
- else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) )
- {
- ncvars[ncvarid].islat = TRUE;
- continue;
- }
- else if ( unitsIsPressure(ncvars[ncvarid].units) )
- {
- ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE;
- continue;
- }
- else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 )
- {
- if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
- else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID;
- else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
- else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF;
- else if ( strcmp(ncvars[ncvarid].units, "level") == 0 )
- ncvars[ncvarid].zaxistype = ZAXIS_GENERIC;
- continue;
- }
- else if ( isDBLAxis(ncvars[ncvarid].longname) )
- {
- ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
- continue;
- }
- else if ( unitsIsMeter(ncvars[ncvarid].units) )
- {
- if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
- ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
- else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
- ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT;
- continue;
- }
- }
-
- /* not needed anymore for rotated grids */
- if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 &&
- ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 )
- {
- if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 )
- {
- ncvars[ncvarid].islon = TRUE;
- continue;
- }
- else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 )
- {
- ncvars[ncvarid].islat = TRUE;
- continue;
- }
- }
- }
+ case GRIB1_LTYPE_SIGMA_LAYER:
+ case GRIB1_LTYPE_HYBRID_LAYER:
+ case GRIB1_LTYPE_LANDDEPTH_LAYER:
+ {
+ lbounds = 1;
+ break;
+ }
}
+
+ return (lbounds);
}
-#if defined (PROJECTION_TEST)
static
-void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID)
+int cgribexGetTimeUnit(int *isec1)
{
- int iatt, nvatts;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- nc_type xtype;
-
- cdf_inq_varnatts(ncfileID, ncvarID, &nvatts);
+ int timeunit = TUNIT_HOUR;
+ static int lprint = TRUE;
- for ( iatt = 0; iatt < nvatts; iatt++ )
+ switch ( ISEC1_TimeUnit )
{
- cdf_inq_attname(ncfileID, ncvarID, iatt, attname);
- cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype);
- cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen);
-
- // printf("%s %d\n", attname, (int)attlen);
+ case ISEC1_TABLE4_MINUTE: timeunit = TUNIT_MINUTE; break;
+ case ISEC1_TABLE4_QUARTER: timeunit = TUNIT_QUARTER; break;
+ case ISEC1_TABLE4_30MINUTES: timeunit = TUNIT_30MINUTES; break;
+ case ISEC1_TABLE4_HOUR: timeunit = TUNIT_HOUR; break;
+ case ISEC1_TABLE4_3HOURS: timeunit = TUNIT_3HOURS; break;
+ case ISEC1_TABLE4_6HOURS: timeunit = TUNIT_6HOURS; break;
+ case ISEC1_TABLE4_12HOURS: timeunit = TUNIT_12HOURS; break;
+ case ISEC1_TABLE4_DAY: timeunit = TUNIT_DAY; break;
+ default:
+ if ( lprint )
+ {
+ Message("GRIB time unit %d unsupported!", ISEC1_TimeUnit);
+ lprint = FALSE;
+ }
+ break;
}
+ return (timeunit);
}
-#endif
static
-void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
+int cgribexTimeIsFC(int *isec1)
{
- if ( ncvar->chunked )
- {
- int ndims = ncvar->ndims;
+ int isFC = TRUE;
- if ( grid->type == GRID_UNSTRUCTURED )
- {
- if ( ncvar->chunks[ndims-1] == grid->size )
- ncvar->chunktype = CHUNK_GRID;
- else
- ncvar->chunktype = CHUNK_AUTO;
- }
- else
- {
- if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 &&
- grid->xsize == ncvar->chunks[ndims-1] &&
- grid->ysize == ncvar->chunks[ndims-2] )
- ncvar->chunktype = CHUNK_GRID;
- else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] )
- ncvar->chunktype = CHUNK_LINES;
- else
- ncvar->chunktype = CHUNK_AUTO;
- }
- }
+ if ( ISEC1_TimeRange == 10 && ISEC1_TimePeriod1 == 0 && ISEC1_TimePeriod2 == 0 )
+ isFC = FALSE;
+
+ return (isFC);
}
-/* define all input grids */
static
-void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used)
+int cgribexGetTsteptype(int timerange)
{
- int ncvarid, ncvarid2;
- int nbdims;
- int i;
- int nvatts;
- int skipvar;
- size_t nvertex;
- grid_t grid;
- grid_t proj;
- int gridindex;
- char name[CDI_MAX_NAME];
- int iatt;
- int ltwarn = TRUE;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- double datt;
+ int tsteptype = TSTEP_INSTANT;
+ static int lprint = TRUE;
- for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
+ switch ( timerange )
{
- if ( ncvars[ncvarid].isvar && ncvars[ncvarid].gridID == UNDEFID )
+ case 0: tsteptype = TSTEP_INSTANT; break;
+ case 1: tsteptype = TSTEP_INSTANT2; break;
+ case 2: tsteptype = TSTEP_RANGE; break;
+ case 3: tsteptype = TSTEP_AVG; break;
+ case 4: tsteptype = TSTEP_ACCUM; break;
+ case 5: tsteptype = TSTEP_DIFF; break;
+ case 10: tsteptype = TSTEP_INSTANT3; break;
+ default:
+ if ( lprint )
{
- int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
- int xdimid = -1, ydimid = -1;
- int xvarid = -1, yvarid = -1;
- int islon = 0, islat = 0;
- int nxdims = 0, nydims = 0;
- size_t size = 0, np = 0;
- size_t xsize = 0, ysize = 0;
- double xinc = 0, yinc = 0;
+ Message("Time range indicator %d unsupported, set to 0!", timerange);
+ lprint = FALSE;
+ }
+ break;
+ }
- int ndims = ncvars[ncvarid].ndims;
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvarid].dimtype[i] == X_AXIS && nxdims < 2 )
- {
- xdimids[nxdims] = ncvars[ncvarid].dimids[i];
- nxdims++;
- }
- else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS && nydims < 2 )
- {
- ydimids[nydims] = ncvars[ncvarid].dimids[i];
- nydims++;
- }
- }
+ return (tsteptype);
+}
- if ( nxdims == 2 )
- {
- xdimid = xdimids[1];
- ydimid = xdimids[0];
- }
- else if ( nydims == 2 )
- {
- xdimid = ydimids[1];
- ydimid = ydimids[0];
- }
- else
- {
- xdimid = xdimids[0];
- ydimid = ydimids[0];
- }
+static
+void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4, grid_t *grid, int iret)
+{
+ int compyinc = TRUE;
+ int gridtype = cgribexGetGridType(isec2);
- if ( ncvars[ncvarid].xvarid != UNDEFID )
- xvarid = ncvars[ncvarid].xvarid;
- else if ( xdimid != UNDEFID )
- xvarid = ncdims[xdimid].ncvarid;
+ if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
+ {
+ int ilat, nlon = 0;
+ for ( ilat = 0; ilat < ISEC2_NumLat; ++ilat )
+ if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
+ gridtype = GRID_GAUSSIAN;
+ ISEC2_NumLon = nlon;
+ ISEC4_NumValues = nlon*ISEC2_NumLat;
+ compyinc = FALSE;
+ }
- if ( ncvars[ncvarid].yvarid != UNDEFID )
- yvarid = ncvars[ncvarid].yvarid;
- else if ( ydimid != UNDEFID )
- yvarid = ncdims[ydimid].ncvarid;
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
+ switch (gridtype)
+ {
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ {
+ if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
+ Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
+ grid->size = ISEC4_NumValues;
+ grid->xsize = ISEC2_NumLon;
+ grid->ysize = ISEC2_NumLat;
+ if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar;
+ grid->xinc = 0;
+ grid->yinc = 0;
+ grid->xdef = 0;
+ /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
+ {
+ if ( grid->xsize > 1 )
+ {
+ int recompinc = TRUE;
- /*
- if ( xdimid != UNDEFID )
- xvarid = ncdims[xdimid].ncvarid;
- if ( xvarid == UNDEFID && ncvars[ncvarid].xvarid != UNDEFID )
- xvarid = ncvars[ncvarid].xvarid;
+ if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
- if ( ydimid != UNDEFID )
- yvarid = ncdims[ydimid].ncvarid;
- if ( yvarid == UNDEFID && ncvars[ncvarid].yvarid != UNDEFID )
- yvarid = ncvars[ncvarid].yvarid;
- */
+ if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+ {
+ if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->xsize-1))) <= 2 )
+ {
+ recompinc = FALSE;
+ grid->xinc = ISEC2_LonIncr * 0.001;
+ }
+ }
- if ( xdimid != UNDEFID ) xsize = ncdims[xdimid].len;
- if ( ydimid != UNDEFID ) ysize = ncdims[ydimid].len;
+ /* recompute xinc if necessary */
+ if ( recompinc ) grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize-1);
- if ( ydimid == UNDEFID && yvarid != UNDEFID )
- {
- if ( ncvars[yvarid].ndims == 1 )
- {
- ydimid = ncvars[yvarid].dimids[0];
- ysize = ncdims[ydimid].len;
- }
- }
+ /* correct xinc if necessary */
+ if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 )
+ {
+ double xinc = 360. / grid->xsize;
- if ( ncvars[ncvarid].gridtype == UNDEFID || ncvars[ncvarid].gridtype == GRID_GENERIC )
- if ( xdimid != UNDEFID && xdimid == ydimid && nydims == 0 ) ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
+ if ( fabs(grid->xinc-xinc) > 0.0 )
+ {
+ grid->xinc = xinc;
+ if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
+ }
+ }
+ }
+ grid->xfirst = ISEC2_FirstLon * 0.001;
+ grid->xlast = ISEC2_LastLon * 0.001;
+ grid->xdef = 2;
+ }
+ grid->ydef = 0;
+ /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
+ {
+ if ( grid->ysize > 1 && compyinc )
+ {
+ int recompinc = TRUE;
+ if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+ {
+ if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
+ {
+ recompinc = FALSE;
+ grid->yinc = ISEC2_LatIncr * 0.001;
+ }
+ }
- grid_init(&grid);
- grid_init(&proj);
+ /* recompute yinc if necessary */
+ if ( recompinc ) grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
+ }
+ grid->yfirst = ISEC2_FirstLat * 0.001;
+ grid->ylast = ISEC2_LastLat * 0.001;
+ grid->ydef = 2;
+ }
+ break;
+ }
+ case GRID_GAUSSIAN_REDUCED:
+ {
+ grid->np = ISEC2_NumPar;
+ grid->size = ISEC4_NumValues;
+ grid->rowlon = ISEC2_RowLonPtr;
+ grid->ysize = ISEC2_NumLat;
+ grid->xinc = 0;
+ grid->yinc = 0;
+ grid->xdef = 0;
+ /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
+ {
+ if ( grid->xsize > 1 )
+ {
+ if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
- grid.prec = DATATYPE_FLT64;
- grid.trunc = ncvars[ncvarid].truncation;
+ if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+ grid->xinc = ISEC2_LonIncr * 0.001;
+ else
+ grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize - 1);
+ }
+ grid->xfirst = ISEC2_FirstLon * 0.001;
+ grid->xlast = ISEC2_LastLon * 0.001;
+ grid->xdef = 2;
+ }
+ grid->ydef = 0;
+ /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
+ {
+ if ( grid->ysize > 1 )
+ {
+ if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+ grid->yinc = ISEC2_LatIncr * 0.001;
+ else
+ grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
+ }
+ grid->yfirst = ISEC2_FirstLat * 0.001;
+ grid->ylast = ISEC2_LastLat * 0.001;
+ grid->ydef = 2;
+ }
+ break;
+ }
+ case GRID_LCC:
+ {
+ if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
+ Error("numberOfPoints (%d) and gridSize (%d) differ!",
+ ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
- if ( ncvars[ncvarid].gridtype == GRID_TRAJECTORY )
- {
- if ( ncvars[ncvarid].xvarid == UNDEFID )
- Error("Longitude coordinate undefined for %s!", name);
- if ( ncvars[ncvarid].yvarid == UNDEFID )
- Error("Latitude coordinate undefined for %s!", name);
- }
- else
- {
- size_t start[3], count[3];
- int ltgrid = FALSE;
+ grid->size = ISEC4_NumValues;
+ grid->xsize = ISEC2_NumLon;
+ grid->ysize = ISEC2_NumLat;
- if ( xvarid != UNDEFID && yvarid != UNDEFID )
- {
- if ( ncvars[xvarid].ndims != ncvars[yvarid].ndims )
- {
- Warning("Inconsistent grid structure for variable %s!", ncvars[ncvarid].name);
- ncvars[ncvarid].xvarid = UNDEFID;
- ncvars[ncvarid].yvarid = UNDEFID;
- xvarid = UNDEFID;
- yvarid = UNDEFID;
- }
+ grid->lcc_xinc = ISEC2_Lambert_dx;
+ grid->lcc_yinc = ISEC2_Lambert_dy;
+ grid->lcc_originLon = ISEC2_FirstLon * 0.001;
+ grid->lcc_originLat = ISEC2_FirstLat * 0.001;
+ grid->lcc_lonParY = ISEC2_Lambert_Lov * 0.001;
+ grid->lcc_lat1 = ISEC2_Lambert_LatS1 * 0.001;
+ grid->lcc_lat2 = ISEC2_Lambert_LatS2 * 0.001;
+ grid->lcc_projflag = ISEC2_Lambert_ProjFlag;
+ grid->lcc_scanflag = ISEC2_ScanFlag;
- if ( ncvars[xvarid].ndims > 2 || ncvars[yvarid].ndims > 2 )
- {
- if ( ncvars[xvarid].ndims == 3 && ncvars[xvarid].dimids[0] == timedimid &&
- ncvars[yvarid].ndims == 3 && ncvars[yvarid].dimids[0] == timedimid )
- {
- if ( ltwarn )
- Warning("Time varying grids unsupported, using grid at time step 1!");
- ltgrid = TRUE;
- ltwarn = FALSE;
- start[0] = start[1] = start[2] = 0;
- count[0] = 1; count[1] = ysize; count[2] = xsize;
- }
- else
- {
- Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvars[ncvarid].name);
- ncvars[ncvarid].xvarid = UNDEFID;
- ncvars[ncvarid].yvarid = UNDEFID;
- xvarid = UNDEFID;
- yvarid = UNDEFID;
- }
- }
- }
+ grid->xdef = 0;
+ grid->ydef = 0;
- if ( xvarid != UNDEFID )
- {
- if ( ncvars[xvarid].ndims > 3 || (ncvars[xvarid].ndims == 3 && ltgrid == FALSE) )
- {
- Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims);
- //ncvars[ncvarid].xvarid = UNDEFID;
- xvarid = UNDEFID;
- }
- }
+ break;
+ }
+ case GRID_SPECTRAL:
+ {
+ grid->size = ISEC4_NumValues;
+ grid->trunc = ISEC2_PentaJ;
+ if ( ISEC2_RepMode == 2 )
+ grid->lcomplex = 1;
+ else
+ grid->lcomplex = 0;
- if ( yvarid != UNDEFID )
- {
- if ( ncvars[yvarid].ndims > 3 || (ncvars[yvarid].ndims == 3 && ltgrid == FALSE) )
- {
- Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims);
- //ncvars[ncvarid].yvarid = UNDEFID;
- yvarid = UNDEFID;
- }
- }
+ break;
+ }
+ case GRID_GME:
+ {
+ grid->size = ISEC4_NumValues;
+ grid->nd = ISEC2_GME_ND;
+ grid->ni = ISEC2_GME_NI;
+ grid->ni2 = ISEC2_GME_NI2;
+ grid->ni3 = ISEC2_GME_NI3;
+ break;
+ }
+ case GRID_GENERIC:
+ {
+ grid->size = ISEC4_NumValues;
+ grid->xsize = 0;
+ grid->ysize = 0;
+ break;
+ }
+ default:
+ {
+ Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+ break;
+ }
+ }
- if ( xvarid != UNDEFID )
- {
- skipvar = TRUE;
- islon = ncvars[xvarid].islon;
- ndims = ncvars[xvarid].ndims;
- if ( ndims == 2 || ndims == 3 )
- {
- ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
- size = xsize*ysize;
- /* Check size of 2 dimensional coordinate variables */
- {
- int dimid = ncvars[xvarid].dimids[ndims-2];
- size_t dimsize1 = ncdims[dimid].len;
- dimid = ncvars[xvarid].dimids[ndims-1];
- size_t dimsize2 = ncdims[dimid].len;
- if ( dimsize1*dimsize2 == size ) skipvar = FALSE;
- }
- }
- else if ( ndims == 1 )
- {
- size = xsize;
- /* Check size of 1 dimensional coordinate variables */
- {
- int dimid = ncvars[xvarid].dimids[0];
- size_t dimsize = ncdims[dimid].len;
- if ( dimsize == size ) skipvar = FALSE;
- }
- }
- else if ( ndims == 0 && xsize == 0 )
- {
- xsize = 1;
- size = xsize;
- skipvar = FALSE;
- }
+ grid->isRotated = FALSE;
+ if ( cgribexGetIsRotated(isec2) )
+ {
+ grid->isRotated = TRUE;
+ grid->ypole = - ISEC2_LatSP*0.001;
+ grid->xpole = ISEC2_LonSP*0.001 - 180;
+ grid->angle = - FSEC2_RotAngle;
+ }
- if ( skipvar )
- {
- Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
- ncvars[ncvarid].isvar = -1;
- continue;
- }
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+ grid->type = gridtype;
+}
- if ( ncvars[xvarid].xtype == NC_FLOAT ) grid.prec = DATATYPE_FLT32;
- grid.xvals = (double *) Malloc(size*sizeof(double));
+static
+void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, double *fsec2, double *fsec3,
+ int *isec4, long recsize, off_t position, int datatype, int comptype, int lmv, int iret)
+{
+ int varID;
+ int levelID = 0;
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
- if ( ltgrid )
- cdf_get_vara_double(ncvars[xvarid].ncid, xvarid, start, count, grid.xvals);
- else
- cdf_get_var_double(ncvars[xvarid].ncid, xvarid, grid.xvals);
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
- scale_add(size, grid.xvals, ncvars[xvarid].addoffset, ncvars[xvarid].scalefactor);
+ int tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
+ int numavg = ISEC1_AvgNum;
- strcpy(grid.xname, ncvars[xvarid].name);
- strcpy(grid.xlongname, ncvars[xvarid].longname);
- strcpy(grid.xunits, ncvars[xvarid].units);
- /* don't change the name !!! */
- /*
- if ( (len = strlen(grid.xname)) > 2 )
- if ( grid.xname[len-2] == '_' && isdigit((int) grid.xname[len-1]) )
- grid.xname[len-2] = 0;
- */
- if ( islon && xsize > 1 )
- {
- xinc = fabs(grid.xvals[0] - grid.xvals[1]);
- for ( i = 2; i < (int) xsize; i++ )
- if ( (fabs(grid.xvals[i-1] - grid.xvals[i]) - xinc) > (xinc/1000) ) break;
+ int level1 = ISEC1_Level1;
+ int level2 = ISEC1_Level2;
- if ( i < (int) xsize ) xinc = 0;
- }
- }
+ /* fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, ISEC1_LevelType); */
- if ( yvarid != UNDEFID )
- {
- skipvar = TRUE;
- islat = ncvars[yvarid].islat;
- ndims = ncvars[yvarid].ndims;
- if ( ndims == 2 || ndims == 3 )
- {
- ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
- size = xsize*ysize;
- /* Check size of 2 dimensional coordinate variables */
- {
- int dimid;
- size_t dimsize1, dimsize2;
- dimid = ncvars[yvarid].dimids[ndims-2];
- dimsize1 = ncdims[dimid].len;
- dimid = ncvars[yvarid].dimids[ndims-1];
- dimsize2 = ncdims[dimid].len;
- if ( dimsize1*dimsize2 == size ) skipvar = FALSE;
- }
- }
- else if ( ndims == 1 )
- {
- if ( (int) ysize == 0 ) size = xsize;
- else size = ysize;
+ record->size = (size_t)recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level1;
+ record->ilevel2 = level2;
+ record->ltype = ISEC1_LevelType;
+ record->tsteptype = (short)tsteptype;
- /* Check size of 1 dimensional coordinate variables */
- {
- int dimid;
- size_t dimsize;
- dimid = ncvars[yvarid].dimids[0];
- dimsize = ncdims[dimid].len;
- if ( dimsize == size ) skipvar = FALSE;
- }
- }
- else if ( ndims == 0 && ysize == 0 )
- {
- ysize = 1;
- size = ysize;
- skipvar = FALSE;
- }
+ cgribexGetGrid(streamptr, isec2, fsec2, isec4, grid, iret);
- if ( skipvar )
- {
- Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
- ncvars[ncvarid].isvar = -1;
- continue;
- }
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
- if ( ncvars[yvarid].xtype == NC_FLOAT ) grid.prec = DATATYPE_FLT32;
- grid.yvals = (double *) Malloc(size*sizeof(double));
+ int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
- if ( ltgrid )
- cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid.yvals);
- else
- cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid.yvals);
+ if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
+ {
+ size_t vctsize = (size_t)ISEC2_NumVCP;
+ double *vctptr = &fsec2[10];
- scale_add(size, grid.yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor);
+ varDefVCT(vctsize, vctptr);
+ }
- strcpy(grid.yname, ncvars[yvarid].name);
- strcpy(grid.ylongname, ncvars[yvarid].longname);
- strcpy(grid.yunits, ncvars[yvarid].units);
- /* don't change the name !!! */
- /*
- if ( (len = strlen(grid.yname)) > 2 )
- if ( grid.yname[len-2] == '_' && isdigit((int) grid.yname[len-1]) )
- grid.yname[len-2] = 0;
- */
- if ( islon && (int) ysize > 1 )
- {
- yinc = fabs(grid.yvals[0] - grid.yvals[1]);
- for ( i = 2; i < (int) ysize; i++ )
- if ( (fabs(grid.yvals[i-1] - grid.yvals[i]) - yinc) > (yinc/1000) ) break;
+ int lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
- if ( i < (int) ysize ) yinc = 0;
- }
- }
+ if ( datatype > 32 ) datatype = DATATYPE_PACK32;
+ if ( datatype < 0 ) datatype = DATATYPE_PACK;
- if ( (int) ysize == 0 ) size = xsize;
- else if ( (int) xsize == 0 ) size = ysize;
- else if ( ncvars[ncvarid].gridtype == GRID_UNSTRUCTURED ) size = xsize;
- else size = xsize*ysize;
- }
+ varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, 0, 0,
+ datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, -1,
+ NULL, NULL, NULL, NULL, NULL, NULL);
- if ( ncvars[ncvarid].gridtype == UNDEFID ||
- ncvars[ncvarid].gridtype == GRID_GENERIC )
- {
- if ( islat && islon )
- {
- if ( isGaussGrid(ysize, yinc, grid.yvals) )
- {
- ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
- np = ysize/2;
- }
- else
- ncvars[ncvarid].gridtype = GRID_LONLAT;
- }
- else if ( islat && !islon && xsize == 0 )
- {
- if ( isGaussGrid(ysize, yinc, grid.yvals) )
- {
- ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
- np = ysize/2;
- }
- else
- ncvars[ncvarid].gridtype = GRID_LONLAT;
- }
- else if ( islon && !islat && ysize == 0 )
- {
- ncvars[ncvarid].gridtype = GRID_LONLAT;
- }
- else
- ncvars[ncvarid].gridtype = GRID_GENERIC;
- }
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
- switch (ncvars[ncvarid].gridtype)
- {
- case GRID_GENERIC:
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- case GRID_UNSTRUCTURED:
- case GRID_CURVILINEAR:
- {
- grid.size = (int)size;
- grid.xsize = (int)xsize;
- grid.ysize = (int)ysize;
- grid.np = (int)np;
- if ( xvarid != UNDEFID )
- {
- grid.xdef = 1;
- if ( ncvars[xvarid].bounds != UNDEFID )
- {
- nbdims = ncvars[ncvars[xvarid].bounds].ndims;
- if ( nbdims == 2 || nbdims == 3 )
- {
- nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
- grid.nvertex = (int) nvertex;
- grid.xbounds = (double *) Malloc(nvertex*size*sizeof(double));
- cdf_get_var_double(ncvars[xvarid].ncid, ncvars[xvarid].bounds, grid.xbounds);
- }
- }
- }
- if ( yvarid != UNDEFID )
- {
- grid.ydef = 1;
- if ( ncvars[yvarid].bounds != UNDEFID )
- {
- nbdims = ncvars[ncvars[yvarid].bounds].ndims;
- if ( nbdims == 2 || nbdims == 3 )
- {
- nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len;
- /*
- if ( nvertex != grid.nvertex )
- Warning("nvertex problem! nvertex x %d, nvertex y %d",
- grid.nvertex, (int) nvertex);
- */
- grid.ybounds = (double *) Malloc(nvertex*size*sizeof(double));
- cdf_get_var_double(ncvars[yvarid].ncid, ncvars[yvarid].bounds, grid.ybounds);
- }
- }
- }
+ varDefCompType(varID, comptype);
- if ( ncvars[ncvarid].cellarea != UNDEFID )
- {
- grid.area = (double *) Malloc(size*sizeof(double));
- cdf_get_var_double(ncvars[ncvarid].ncid, ncvars[ncvarid].cellarea, grid.area);
- }
+ if ( ISEC1_LocalFLag )
+ {
+ if ( ISEC1_CenterID == 78 && isec1[36] == 253 ) // DWD local extension
+ varDefEnsembleInfo(varID, isec1[54], isec1[53], isec1[52]);
+ else if ( ISEC1_CenterID == 252 && isec1[36] == 1 ) // MPIM local extension
+ varDefEnsembleInfo(varID, isec1[38], isec1[39], isec1[37]);
+ }
- break;
- }
- case GRID_SPECTRAL:
- {
- grid.size = (int)size;
- grid.lcomplex = 1;
- break;
- }
- case GRID_FOURIER:
- {
- grid.size = (int)size;
- break;
- }
- case GRID_TRAJECTORY:
- {
- grid.size = 1;
- break;
- }
- }
+ if ( lmv ) varDefMissval(varID, FSEC3_MissVal);
- grid.type = ncvars[ncvarid].gridtype;
+ if ( varInqInst(varID) == CDI_UNDEFID )
+ {
+ int center, subcenter, instID;
+ center = ISEC1_CenterID;
+ subcenter = ISEC1_SubCenterID;
+ instID = institutInq(center, subcenter, NULL, NULL);
+ if ( instID == CDI_UNDEFID )
+ instID = institutDef(center, subcenter, NULL, NULL);
+ varDefInst(varID, instID);
+ }
- if ( grid.size == 0 )
- {
- if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
- (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == Z_AXIS) ||
- (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS && ncvars[ncvarid].dimtype[1] == Z_AXIS) )
- {
- grid.type = GRID_GENERIC;
- grid.size = 1;
- grid.xsize = 0;
- grid.ysize = 0;
- }
- else
- {
- Warning("Variable %s has an unsupported grid, skipped!", ncvars[ncvarid].name);
- ncvars[ncvarid].isvar = -1;
- continue;
- }
- }
+ if ( varInqModel(varID) == CDI_UNDEFID )
+ {
+ int modelID;
+ modelID = modelInq(varInqInst(varID), ISEC1_ModelID, NULL);
+ if ( modelID == CDI_UNDEFID )
+ modelID = modelDef(varInqInst(varID), ISEC1_ModelID, NULL);
+ varDefModel(varID, modelID);
+ }
- if ( number_of_grid_used != UNDEFID && (grid.type == UNDEFID || grid.type == GRID_GENERIC) )
- grid.type = GRID_UNSTRUCTURED;
+ if ( varInqTable(varID) == CDI_UNDEFID )
+ {
+ int tableID;
- if ( number_of_grid_used != UNDEFID && grid.type == GRID_UNSTRUCTURED )
- grid.number = number_of_grid_used;
+ tableID = tableInq(varInqModel(varID), ISEC1_CodeTable, NULL);
- if ( ncvars[ncvarid].gmapid >= 0 && ncvars[ncvarid].gridtype != GRID_CURVILINEAR )
- {
- cdf_inq_varnatts(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, &nvatts);
+ if ( tableID == CDI_UNDEFID )
+ tableID = tableDef(varInqModel(varID), ISEC1_CodeTable, NULL);
+ varDefTable(varID, tableID);
+ }
- for ( iatt = 0; iatt < nvatts; iatt++ )
- {
- cdf_inq_attname(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, iatt, attname);
- cdf_inq_attlen(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, &attlen);
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
+}
- if ( strcmp(attname, "grid_mapping_name") == 0 )
- {
- enum {
- attstringlen = 8192,
- };
- char attstring[attstringlen];
+static
+void MCH_get_undef(int *isec1, double *undef_pds, double *undef_eps)
+{
+ /* 2010-01-13: Oliver Fuhrer */
+ if ( ISEC1_CenterID == 215 ) {
+ if (isec1[34] != 0 && isec1[34] != 255) {
+ if (isec1[34] & 2) {
+ if (isec1[34] & 1) {
+ *undef_pds = -0.99*pow(10.0,-isec1[35]);
+ } else {
+ *undef_pds = +0.99*pow(10.0,-isec1[35]);
+ }
+ *undef_eps = pow(10.0,-isec1[35]-1);
+ } else {
+ if (isec1[34] & 1) {
+ *undef_pds = -0.99*pow(10.0,+isec1[35]);
+ } else {
+ *undef_pds = +0.99*pow(10.0,+isec1[35]);
+ }
+ *undef_eps = pow(10.0,isec1[35]-1);
+ }
+ }
+ }
+}
- cdfGetAttText(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, attstringlen, attstring);
- strtolower(attstring);
+static
+void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
+ int *isec3, double *fsec3, int *isec4, double *fsec4,
+ int *gribbuffer, int recsize, int *lmv, int *iret)
+{
+ int ipunp = 0, iword = 0;
- if ( strcmp(attstring, "rotated_latitude_longitude") == 0 )
- grid.isRotated = TRUE;
- else if ( strcmp(attstring, "sinusoidal") == 0 )
- grid.type = GRID_SINUSOIDAL;
- else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 )
- grid.type = GRID_LAEA;
- else if ( strcmp(attstring, "lambert_conformal_conic") == 0 )
- grid.type = GRID_LCC2;
- else if ( strcmp(attstring, "lambert_cylindrical_equal_area") == 0 )
- {
- proj.type = GRID_PROJECTION;
- proj.name = strdup(attstring);
- }
- }
- else if ( strcmp(attname, "earth_radius") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.laea_a = datt;
- grid.lcc2_a = datt;
- }
- else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.laea_lon_0);
- }
- else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.lcc2_lon_0);
- }
- else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.laea_lat_0 = datt;
- grid.lcc2_lat_0 = datt;
- }
- else if ( strcmp(attname, "standard_parallel") == 0 )
- {
- if ( attlen == 1 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.lcc2_lat_1 = datt;
- grid.lcc2_lat_2 = datt;
- }
- else
- {
- double datt2[2];
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 2, datt2);
- grid.lcc2_lat_1 = datt2[0];
- grid.lcc2_lat_2 = datt2[1];
- }
- }
- else if ( strcmp(attname, "grid_north_pole_latitude") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.ypole);
- }
- else if ( strcmp(attname, "grid_north_pole_longitude") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.xpole);
- }
- else if ( strcmp(attname, "north_pole_grid_longitude") == 0 )
- {
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.angle);
- }
- }
- }
+ memset(isec1, 0, 256*sizeof(int));
- if ( grid.type == GRID_UNSTRUCTURED )
- {
- int zdimid = UNDEFID;
- int xdimidx = -1, ydimidx = -1;
+ gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
+ ipunp, (int *) gribbuffer, recsize, &iword, "J", iret);
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) xdimidx = i;
- else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) ydimidx = i;
- else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) zdimid = ncvars[ncvarid].dimids[i];
- }
+ *lmv = 0;
- if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID )
- {
- if ( grid.xsize > grid.ysize && grid.ysize < 1000 )
- {
- ncvars[ncvarid].dimtype[ydimidx] = Z_AXIS;
- ydimid = UNDEFID;
- grid.size = grid.xsize;
- grid.ysize = 0;
- }
- else if ( grid.ysize > grid.xsize && grid.xsize < 1000 )
- {
- ncvars[ncvarid].dimtype[xdimidx] = Z_AXIS;
- xdimid = ydimid;
- ydimid = UNDEFID;
- grid.size = grid.ysize;
- grid.xsize = grid.ysize;
- grid.ysize = 0;
- }
- }
+ if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
+ {
+ double undef_pds, undef_eps;
- if ( grid.size != grid.xsize )
- {
- Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
- ncvars[ncvarid].isvar = -1;
- continue;
- }
+ MCH_get_undef(isec1, &undef_pds, &undef_eps);
+ FSEC3_MissVal = undef_pds;
+ *lmv = 1;
+ }
+}
- if ( ncvars[ncvarid].position > 0 ) grid.position = ncvars[ncvarid].position;
- if ( uuidOfHGrid[0] != 0 ) memcpy(grid.uuid, uuidOfHGrid, 16);
- }
+static
+compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int trange)
+{
+ compvar_t compVar;
+ int tsteptype = cgribexGetTsteptype(trange);
-#if defined (PROJECTION_TEST)
- if ( proj.type == GRID_PROJECTION )
- {
- if ( grid.type == GRID_GENERIC )
- {
- grid.type = GRID_CURVILINEAR;
- }
+ compVar.param = param;
+ compVar.level1 = level1;
+ compVar.level2 = level2;
+ compVar.ltype = leveltype;
+ compVar.tsteptype = tsteptype;
- if ( grid.type == GRID_CURVILINEAR )
- {
- proj.size = grid.size;
- proj.xsize = grid.xsize;
- proj.ysize = grid.ysize;
- }
+ return (compVar);
+}
- // grid.proj = gridGenerate(proj);
- }
+static inline int
+cgribexVarCompare(compvar_t compVar, record_t record, int flag)
+{
+ int tstepDiff = (!((flag == 0) & (((compVar.tsteptype == TSTEP_INSTANT)
+ & (record.tsteptype == TSTEP_INSTANT3))
+ |((compVar.tsteptype == TSTEP_INSTANT3)
+ & (record.tsteptype == TSTEP_INSTANT)))))
+ & (compVar.tsteptype != record.tsteptype);
+ int rstatus = (compVar.param != record.param)
+ | (compVar.level1 != record.ilevel)
+ | (compVar.level2 != record.ilevel2)
+ | (compVar.ltype != record.ltype)
+ | tstepDiff;
+ return (rstatus);
+}
#endif
- if ( CDI_Debug )
- {
- Message("grid: type = %d, size = %d, nx = %d, ny %d",
- grid.type, grid.size, grid.xsize, grid.ysize);
- Message("proj: type = %d, size = %d, nx = %d, ny %d",
- proj.type, proj.size, proj.xsize, proj.ysize);
- }
-
-#if defined (PROJECTION_TEST)
- if ( proj.type == GRID_PROJECTION )
- {
- ncvars[ncvarid].gridID = varDefGrid(vlistID, &proj, 1);
- copy_numeric_projatts(ncvars[ncvarid].gridID, ncvars[ncvarid].gmapid, ncvars[ncvarid].ncid);
- }
- else
-#endif
- ncvars[ncvarid].gridID = varDefGrid(vlistID, &grid, 1);
+#define gribWarning(text, nrecs, timestep, paramstr, level1, level2) \
+ Warning("Record %2d (id=%s lev1=%d lev2=%d) timestep %d: %s", nrecs, paramstr, level1, level2, timestep, text)
- if ( grid.type == GRID_UNSTRUCTURED )
- {
- if ( gridfile[0] != 0 ) gridDefReference(ncvars[ncvarid].gridID, gridfile);
- }
+#if defined (HAVE_LIBCGRIBEX)
- if ( ncvars[ncvarid].chunked ) grid_set_chunktype(&grid, &ncvars[ncvarid]);
+static inline void
+cgribexScanTsFixNtsteps(stream_t *streamptr, off_t recpos)
+{
+ if ( streamptr->ntsteps == -1 )
+ {
+ int tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID);
- streamptr->xdimID[gridindex] = xdimid;
- streamptr->ydimID[gridindex] = ydimid;
- if ( xdimid == -1 && ydimid == -1 && grid.size == 1 )
- gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
+}
- if ( CDI_Debug )
- Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
+static inline void
+cgribexScanTsConstAdjust(stream_t *streamptr, taxis_t *taxis)
+{
+ int vlistID = streamptr->vlistID;
+ if ( streamptr->ntsteps == 1 )
+ {
+ if ( taxis->vdate == 0 && taxis->vtime == 0 )
+ {
+ streamptr->ntsteps = 0;
+ for (int varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ }
+ }
+}
- for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
- if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].gridID == UNDEFID )
- {
- int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID;
- int xdimidx = -1, ydimidx = -1;
- int ndims2 = ncvars[ncvarid2].ndims;
- for ( i = 0; i < ndims2; i++ )
- {
- if ( ncvars[ncvarid2].dimtype[i] == X_AXIS )
- { xdimid2 = ncvars[ncvarid2].dimids[i]; xdimidx = i; }
- else if ( ncvars[ncvarid2].dimtype[i] == Y_AXIS )
- { ydimid2 = ncvars[ncvarid2].dimids[i]; ydimidx = i; }
- else if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
- { zdimid2 = ncvars[ncvarid2].dimids[i]; }
- }
+int cgribexScanTimestep1(stream_t * streamptr)
+{
+ double fsec2[512], fsec3[2], *fsec4 = NULL;
+ int lmv = 0, iret = 0;
+ off_t recpos = 0;
+ void *gribbuffer = NULL;
+ size_t buffersize = 0;
+ int rstatus;
+ int param = 0;
+ int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
+ DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
+ size_t readsize;
+ unsigned nrecords, recID;
+ int nrecs_scanned = 0;
+ int datatype;
+ long recsize = 0;
+ int warn_time = TRUE;
+ int warn_numavg = TRUE;
+ int taxisID = -1;
+ int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
+ int vlistID;
+ int comptype;
+ long unzipsize;
+ char paramstr[32];
+ int nskip = cdiSkipRecords;
- if ( ncvars[ncvarid2].gridtype == UNDEFID && grid.type == GRID_UNSTRUCTURED )
- {
- if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID )
- {
- ncvars[ncvarid2].dimtype[ydimidx] = Z_AXIS;
- ydimid2 = UNDEFID;
- }
+ streamptr->curTsID = 0;
- if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID )
- {
- ncvars[ncvarid2].dimtype[xdimidx] = Z_AXIS;
- xdimid2 = ydimid2;
- ydimid2 = UNDEFID;
- }
- }
+ int *isec0 = streamptr->record->sec0;
+ int *isec1 = streamptr->record->sec1;
+ int *isec2 = streamptr->record->sec2;
+ int *isec3 = streamptr->record->sec3;
+ int *isec4 = streamptr->record->sec4;
- if ( xdimid == xdimid2 &&
- (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) )
- {
- int same_grid = TRUE;
- /*
- if ( xvarid != -1 && ncvars[ncvarid2].xvarid != UNDEFID &&
- xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
+ int tsID = tstepsNewEntry(streamptr);
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
- if ( yvarid != -1 && ncvars[ncvarid2].yvarid != UNDEFID &&
- yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
- */
- if ( ncvars[ncvarid].xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
- if ( ncvars[ncvarid].yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
+ if ( tsID != 0 )
+ Error("Internal problem! tstepsNewEntry returns %d", tsID);
- if ( ncvars[ncvarid].position != ncvars[ncvarid2].position ) same_grid = FALSE;
+ int fileID = streamptr->fileID;
- if ( same_grid )
- {
- if ( CDI_Debug )
- Message("Same gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid2, ncvars[ncvarid2].name);
- ncvars[ncvarid2].gridID = ncvars[ncvarid].gridID;
- ncvars[ncvarid2].chunktype = ncvars[ncvarid].chunktype;
- }
- }
- }
+ while ( nskip-- > 0 )
+ {
+ recsize = gribGetSize(fileID);
+ if ( recsize == 0 )
+ Error("Skipping of %d records failed!", cdiSkipRecords);
- grid_free(&grid);
- grid_free(&proj);
- }
+ recpos = fileGetPos(fileID);
+ fileSetPos(fileID, (off_t)recsize, SEEK_CUR);
}
-}
-
-/* define all input zaxes */
-static
-void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars,
- size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid)
-{
- int ncvarid, ncvarid2;
- int i, ilev;
- int zaxisindex;
- int nbdims, nvertex, nlevel;
- int psvarid = -1;
- char *pname, *plongname, *punits;
- size_t vctsize = vctsize_echam;
- double *vct = vct_echam;
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ unsigned nrecs = 0;
+ while ( TRUE )
{
- if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].zaxisID == UNDEFID )
- {
- int is_scalar = FALSE;
- int with_bounds = FALSE;
- int zdimid = UNDEFID;
- int zvarid = UNDEFID;
- int zsize = 1;
- double *lbounds = NULL;
- double *ubounds = NULL;
+ recsize = gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
- int positive = 0;
- int ndims = ncvars[ncvarid].ndims;
+ if ( recsize == 0 )
+ {
+ if ( nrecs == 0 )
+ Error("No GRIB records found!");
- if ( ncvars[ncvarid].zvarid != -1 && ncvars[ncvars[ncvarid].zvarid].ndims == 0 )
- {
- zvarid = ncvars[ncvarid].zvarid;
- is_scalar = TRUE;
- }
- else
- {
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvarid].dimtype[i] == Z_AXIS )
- zdimid = ncvars[ncvarid].dimids[i];
- }
+ streamptr->ntsteps = 1;
+ break;
+ }
+ if ( (size_t)recsize > buffersize )
+ {
+ buffersize = (size_t)recsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
+ }
- if ( zdimid != UNDEFID )
- {
- zvarid = ncdims[zdimid].ncvarid;
- zsize = (int)ncdims[zdimid].len;
- }
- }
+ readsize = (size_t)recsize;
+ rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
+ if ( rstatus ) break;
- if ( CDI_Debug ) Message("nlevs = %d", zsize);
+ comptype = COMPRESS_NONE;
+ if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
+ {
+ comptype = COMPRESS_SZIP;
+ unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+ if ( buffersize < (size_t)unzipsize )
+ {
+ buffersize = (size_t)unzipsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
+ }
+ }
- double *zvar = (double *) Malloc((size_t)zsize * sizeof (double));
+ nrecs_scanned++;
+ cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
+ (int *) gribbuffer, (int)recsize, &lmv, &iret);
- int zaxisType = UNDEFID;
- if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype;
- if ( zaxisType == UNDEFID ) zaxisType = ZAXIS_GENERIC;
+ param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
+ cdiParamToString(param, paramstr, sizeof(paramstr));
- int zprec = DATATYPE_FLT64;
+ if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
+ if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
+ level1 = ISEC1_Level1;
+ level2 = ISEC1_Level2;
- if ( zvarid != UNDEFID )
- {
- positive = ncvars[zvarid].positive;
- pname = ncvars[zvarid].name;
- plongname = ncvars[zvarid].longname;
- punits = ncvars[zvarid].units;
- if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32;
- /* don't change the name !!! */
- /*
- if ( (len = strlen(pname)) > 2 )
- if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) )
- pname[len-2] = 0;
- */
- psvarid = -1;
- if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct )
- {
- vct = ncvars[zvarid].vct;
- vctsize = ncvars[zvarid].vctsize;
+ gribDateTime(isec1, &vdate, &vtime);
- if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid;
- }
+ if ( ISEC4_NumBits > 0 && ISEC4_NumBits <= 32 )
+ datatype = ISEC4_NumBits;
+ else
+ datatype = DATATYPE_PACK;
- cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar);
+ if ( nrecs == 0 )
+ {
+ datetime0.date = vdate;
+ datetime0.time = vtime;
+ rdate = gribRefDate(isec1);
+ rtime = gribRefTime(isec1);
+ tunit = cgribexGetTimeUnit(isec1);
+ fcast = cgribexTimeIsFC(isec1);
+ }
+ else
+ {
+ datetime.date = vdate;
+ datetime.time = vtime;
+ compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
+ for ( recID = 0; recID < nrecs; recID++ )
+ {
+ if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID], 0) == 0 ) break;
+ }
- if ( ncvars[zvarid].bounds != UNDEFID )
- {
- nbdims = ncvars[ncvars[zvarid].bounds].ndims;
- if ( nbdims == 2 )
- {
- nlevel = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
- nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
- if ( nlevel == zsize && nvertex == 2 )
- {
- with_bounds = TRUE;
- lbounds = (double *) Malloc((size_t)nlevel*sizeof(double));
- ubounds = (double *) Malloc((size_t)nlevel*sizeof(double));
- double zbounds[2*nlevel];
- cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds);
- for ( i = 0; i < nlevel; ++i )
- {
- lbounds[i] = zbounds[i*2];
- ubounds[i] = zbounds[i*2+1];
- }
- }
- }
- }
+ if ( cdiInventoryMode == 1 )
+ {
+ if ( recID < nrecs ) break;
+ if ( warn_time )
+ if ( datetimeCmp(datetime, datetime0) != 0 )
+ {
+ gribWarning("Inconsistent verification time!", nrecs_scanned, tsID+1, paramstr, level1, level2);
+ warn_time = FALSE;
+ }
}
else
{
- pname = NULL;
- plongname = NULL;
- punits = NULL;
-
- if ( zsize == 1 )
- {
- if ( ncvars[ncvarid].zaxistype != UNDEFID )
- zaxisType = ncvars[ncvarid].zaxistype;
- else
- zaxisType = ZAXIS_SURFACE;
+ if ( datetimeCmp(datetime, datetime0) != 0 ) break;
- zvar[0] = 0;
- /*
- if ( zdimid == UNDEFID )
- zvar[0] = 9999;
- else
- zvar[0] = 0;
- */
- }
- else
+ if ( recID < nrecs )
{
- for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1;
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr, level1, level2);
+ continue;
}
}
+ }
- ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds,
- (int)vctsize, vct, pname, plongname, punits, zprec, 1, 0);
+ if ( ISEC1_AvgNum )
+ {
+ if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
+ {
+ Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
+ warn_numavg = FALSE;
+ }
+ else
+ {
+ taxis->numavg = ISEC1_AvgNum;
+ }
+ }
- if ( uuidOfVGrid[0] != 0 )
- {
- // printf("uuidOfVGrid: defined\n");
- zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid);
- }
+ nrecs++;
- if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvars[ncvarid].zaxisID, ncvars[psvarid].name);
+ if ( CDI_Debug )
+ Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
- if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive);
- if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID);
+ cgribexAddRecord(streamptr, param, isec1, isec2, fsec2, fsec3,
+ isec4, recsize, recpos, datatype, comptype, lmv, iret);
+ }
- Free(zvar);
- Free(lbounds);
- Free(ubounds);
+ streamptr->rtsteps = 1;
- zaxisindex = vlistZaxisIndex(vlistID, ncvars[ncvarid].zaxisID);
- streamptr->zaxisID[zaxisindex] = zdimid;
+ if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
- if ( CDI_Debug )
- Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid, ncvars[ncvarid].name);
+ cdi_generate_vars(streamptr);
- for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
- if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ )
- {
- int zvarid2 = UNDEFID;
- if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 )
- zvarid2 = ncvars[ncvarid2].zvarid;
+ if ( fcast )
+ {
+ taxisID = taxisCreate(TAXIS_RELATIVE);
+ taxis->type = TAXIS_RELATIVE;
+ taxis->rdate = rdate;
+ taxis->rtime = rtime;
+ taxis->unit = tunit;
+ }
+ else
+ {
+ taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->unit = tunit;
+ }
- int zdimid2 = UNDEFID;
- ndims = ncvars[ncvarid2].ndims;
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS )
- zdimid2 = ncvars[ncvarid2].dimids[i];
- }
+ taxis->vdate = (int)datetime0.date;
+ taxis->vtime = (int)datetime0.time;
- if ( zdimid == zdimid2 /* && zvarid == zvarid2 */)
- {
- if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ||
- (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) ||
- (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) ||
- (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) )
- {
- if ( CDI_Debug )
- Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid2, ncvars[ncvarid2].name);
- ncvars[ncvarid2].zaxisID = ncvars[ncvarid].zaxisID;
- }
- }
- }
- }
+ vlistID = streamptr->vlistID;
+ vlistDefTaxis(vlistID, taxisID);
+
+ nrecords = (unsigned)streamptr->tsteps[0].nallrecs;
+ if ( nrecords < (unsigned)streamptr->tsteps[0].recordSize )
+ {
+ streamptr->tsteps[0].recordSize = (int)nrecords;
+ streamptr->tsteps[0].records =
+ (record_t *) Realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
}
+
+ streamptr->tsteps[0].recIDs = (int *) Malloc(nrecords*sizeof(int));
+ streamptr->tsteps[0].nrecs = (int)nrecords;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[0].recIDs[recID] = (int)recID;
+
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = (size_t)buffersize;
+
+ cgribexScanTsFixNtsteps(streamptr, recpos);
+ cgribexScanTsConstAdjust(streamptr, taxis);
+
+ return (0);
}
-struct varinfo
-{
- int ncvarid;
- const char *name;
-};
-static
-int cmpvarname(const void *s1, const void *s2)
+int cgribexScanTimestep2(stream_t * streamptr)
{
- const struct varinfo *x = (const struct varinfo *)s1,
- *y = (const struct varinfo *)s2;
- return (strcmp(x->name, y->name));
-}
+ int rstatus = 0;
+ double fsec2[512], fsec3[2], *fsec4 = NULL;
+ int lmv = 0, iret = 0;
+ off_t recpos = 0;
+ int param = 0;
+ int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
+ DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
+ int varID, gridID;
+ size_t readsize;
+ int nrecs, recID;
+ long recsize = 0;
+ int warn_numavg = TRUE;
+ int tsteptype;
+ long unzipsize;
+ char paramstr[32];
+
+ streamptr->curTsID = 1;
+
+ int *isec0 = streamptr->record->sec0;
+ int *isec1 = streamptr->record->sec1;
+ int *isec2 = streamptr->record->sec2;
+ int *isec3 = streamptr->record->sec3;
+ int *isec4 = streamptr->record->sec4;
+
+ int fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int taxisID = vlistInqTaxis(vlistID);
+
+ void *gribbuffer = streamptr->record->buffer;
+ size_t buffersize = streamptr->record->buffersize;
+
+ int tsID = streamptr->rtsteps;
+ if ( tsID != 1 )
+ Error("Internal problem! unexpected timestep %d", tsID+1);
+
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+
+ cdi_create_records(streamptr, tsID);
+
+ int nrecords = streamptr->tsteps[tsID].nallrecs;
+ if ( nrecords ) streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
+ streamptr->tsteps[1].nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[1].recIDs[recID] = -1;
+
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ varID = streamptr->tsteps[0].records[recID].varID;
+ streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position;
+ streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size;
+ }
-/* define all input data variables */
-static
-void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars)
-{
- if ( streamptr->sortname )
+ int nrecs_scanned = nrecords;
+ int rindex = 0;
+ while ( TRUE )
{
- struct varinfo *varInfo
- = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo));
+ if ( rindex > nrecords ) break;
- for ( int varID = 0; varID < nvars; varID++ )
+ recsize = gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
+ if ( recsize == 0 )
{
- int ncvarid = varids[varID];
- varInfo[varID].ncvarid = ncvarid;
- varInfo[varID].name = ncvars[ncvarid].name;
+ streamptr->ntsteps = 2;
+ break;
}
- qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname);
- for ( int varID = 0; varID < nvars; varID++ )
+ if ( (size_t)recsize > buffersize )
{
- varids[varID] = varInfo[varID].ncvarid;
+ buffersize = (size_t)recsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
}
- Free(varInfo);
- }
- for ( int varID1 = 0; varID1 < nvars; varID1++ )
- {
- int ncvarid = varids[varID1];
- int gridID = ncvars[ncvarid].gridID;
- int zaxisID = ncvars[ncvarid].zaxisID;
+ readsize = (size_t)recsize;
+ rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
+ if ( rstatus ) break;
- stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID);
- int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype);
+ if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
+ {
+ unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+ if ( buffersize < (size_t)unzipsize )
+ {
+ buffersize = (size_t)unzipsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
+ }
+ }
-#if defined (HAVE_NETCDF4)
- if ( ncvars[ncvarid].deflate )
- vlistDefVarCompType(vlistID, varID, COMPRESS_ZIP);
+ cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
+ (int *) gribbuffer, (int)recsize, &lmv, &iret);
- if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID )
- vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype);
-#endif
+ nrecs_scanned++;
- streamptr->vars[varID1].defmiss = 0;
- streamptr->vars[varID1].ncvarid = ncvarid;
+ param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
+ cdiParamToString(param, paramstr, sizeof(paramstr));
- vlistDefVarName(vlistID, varID, ncvars[ncvarid].name);
- if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param);
- if ( ncvars[ncvarid].code != UNDEFID ) vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code);
- if ( ncvars[ncvarid].code != UNDEFID )
+ if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
+ if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
+ level1 = ISEC1_Level1;
+ level2 = ISEC1_Level2;
+
+ gribDateTime(isec1, &vdate, &vtime);
+
+ if ( rindex == 0 )
{
- int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255);
- vlistDefVarParam(vlistID, varID, param);
+ if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
+ {
+ taxis->type = TAXIS_RELATIVE;
+ taxis->rdate = gribRefDate(isec1);
+ taxis->rtime = gribRefTime(isec1);
+ }
+ else
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ }
+ taxis->unit = cgribexGetTimeUnit(isec1);
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
+
+ datetime0.date = vdate;
+ datetime0.time = vtime;
}
- if ( ncvars[ncvarid].longname[0] ) vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname);
- if ( ncvars[ncvarid].stdname[0] ) vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname);
- if ( ncvars[ncvarid].units[0] ) vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units);
- if ( ncvars[ncvarid].lvalidrange )
- vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange);
+ tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
- if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) )
- vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset);
- if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) )
- vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor);
+ if ( ISEC1_AvgNum )
+ {
+ if ( taxis->numavg && warn_numavg &&
+ (taxis->numavg != ISEC1_AvgNum) )
+ {
+ /*
+ Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
+ */
+ warn_numavg = FALSE;
+ }
+ else
+ {
+ taxis->numavg = ISEC1_AvgNum;
+ }
+ }
- vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned));
+ datetime.date = vdate;
+ datetime.time = vtime;
- vlistDefVarInstitut(vlistID, varID, instID);
- vlistDefVarModel(vlistID, varID, modelID);
- if ( ncvars[ncvarid].tableID != UNDEFID )
- vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID);
+ compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
- if ( ncvars[ncvarid].deffillval == FALSE && ncvars[ncvarid].defmissval == TRUE )
- {
- ncvars[ncvarid].deffillval = TRUE;
- ncvars[ncvarid].fillval = ncvars[ncvarid].missval;
- }
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
+ }
- if ( ncvars[ncvarid].deffillval == TRUE )
- vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval);
+ if ( recID == nrecords )
+ {
+ gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
+ return (CDI_EUFSTRUCT);
+ }
- if ( CDI_Debug )
- Message("varID = %d gridID = %d zaxisID = %d", varID,
- vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID));
+ if ( cdiInventoryMode == 1 )
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ break;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ }
+ else
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ if ( datetimeCmp(datetime, datetime0) != 0 ) break;
- int gridindex = vlistGridIndex(vlistID, gridID);
- int xdimid = streamptr->xdimID[gridindex];
- int ydimid = streamptr->ydimID[gridindex];
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr, level1, level2);
+ continue;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ }
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- int zdimid = streamptr->zaxisID[zaxisindex];
+ if ( CDI_Debug )
+ Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
- int ndims = ncvars[ncvarid].ndims;
- int iodim = 0;
- int ixyz = 0;
- int ipow10[4] = {1, 10, 100, 1000};
+ streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
- if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++;
+ if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, level1);
+ return (CDI_EUFSTRUCT);
+ }
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid )
- {
- if ( xdimid == ncvars[ncvarid].dimids[ndims-1] )
- {
- ixyz = 321;
- }
- else
- {
- ixyz = 213;
- }
- }
- else
- {
- for ( int idim = iodim; idim < ndims; idim++ )
- {
- if ( xdimid == ncvars[ncvarid].dimids[idim] )
- ixyz += 1*ipow10[ndims-idim-1];
- else if ( ydimid == ncvars[ncvarid].dimids[idim] )
- ixyz += 2*ipow10[ndims-idim-1];
- else if ( zdimid == ncvars[ncvarid].dimids[idim] )
- ixyz += 3*ipow10[ndims-idim-1];
- }
- }
+ streamptr->tsteps[1].records[recID].position = recpos;
+ varID = streamptr->tsteps[tsID].records[recID].varID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ if ( gridInqSize(gridID) == 1 && gridInqType(gridID) == GRID_LONLAT )
+ {
+ if ( IS_NOT_EQUAL(gridInqXval(gridID, 0),ISEC2_FirstLon*0.001) ||
+ IS_NOT_EQUAL(gridInqYval(gridID, 0),ISEC2_FirstLat*0.001) )
+ gridChangeType(gridID, GRID_TRAJECTORY);
+ }
- vlistDefVarXYZ(vlistID, varID, ixyz);
- /*
- printf("ixyz %d\n", ixyz);
- printf("ndims %d\n", ncvars[ncvarid].ndims);
- for ( int i = 0; i < ncvars[ncvarid].ndims; ++i )
- printf("dimids: %d %d\n", i, ncvars[ncvarid].dimids[i]);
- printf("xdimid, ydimid %d %d\n", xdimid, ydimid);
- */
- if ( ncvars[ncvarid].ensdata != NULL )
- {
- vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index,
- ncvars[ncvarid].ensdata->ens_count,
- ncvars[ncvarid].ensdata->forecast_init_type );
- Free(ncvars[ncvarid].ensdata);
- ncvars[ncvarid].ensdata = NULL;
- }
+ if ( tsteptype != vlistInqVarTsteptype(vlistID, varID) )
+ vlistDefVarTsteptype(vlistID, varID, tsteptype);
- if ( ncvars[ncvarid].extra[0] != 0 )
- {
- vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra);
- }
+ rindex++;
}
- for ( int varID = 0; varID < nvars; varID++ )
+ nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
{
- int ncvarid = varids[varID];
- int ncid = ncvars[ncvarid].ncid;
-
- if ( ncvars[ncvarid].natts )
+ if ( ! streamptr->tsteps[tsID].records[recID].used )
{
- int attnum;
- int iatt;
- nc_type attrtype;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- const int attstringlen = 8192; char attstring[8192];
- int nvatts = ncvars[ncvarid].natts;
+ varID = streamptr->tsteps[tsID].records[recID].varID;
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ else
+ {
+ nrecs++;
+ }
+ }
+ streamptr->tsteps[tsID].nrecs = nrecs;
- for ( iatt = 0; iatt < nvatts; iatt++ )
- {
- attnum = ncvars[ncvarid].atts[iatt];
- cdf_inq_attname(ncid, ncvarid, attnum, attname);
- cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
- cdf_inq_atttype(ncid, ncvarid, attname, &attrtype);
+ streamptr->rtsteps = 2;
- if ( attrtype == NC_SHORT || attrtype == NC_INT )
- {
- int attint[attlen];
- cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint);
- if ( attrtype == NC_SHORT )
- vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint);
- else
- vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT32, (int)attlen, attint);
- }
- else if ( attrtype == NC_FLOAT || attrtype == NC_DOUBLE )
- {
- double attflt[attlen];
- cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt);
- if ( attrtype == NC_FLOAT )
- vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt);
- else
- vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT64, (int)attlen, attflt);
- }
- else if ( xtypeIsText(attrtype) )
- {
- cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring);
- vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring);
- }
- else
- {
- if ( CDI_Debug ) printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname);
- }
- }
+ cgribexScanTsFixNtsteps(streamptr, recpos);
- if (ncvars[ncvarid].vct) Free(ncvars[ncvarid].vct);
- if (ncvars[ncvarid].atts) Free(ncvars[ncvarid].atts);
- ncvars[ncvarid].vct = NULL;
- ncvars[ncvarid].atts = NULL;
- }
- }
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = buffersize;
- /* release mem of not freed attributes */
- for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ )
- if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts);
+ return (rstatus);
+}
+#endif
- if ( varids ) Free(varids);
- for ( int varID = 0; varID < nvars; varID++ )
+#if defined (HAVE_LIBCGRIBEX)
+int cgribexScanTimestep(stream_t * streamptr)
+{
+ int rstatus = 0;
+ double fsec2[512], fsec3[2], *fsec4 = NULL;
+ int lmv = 0, iret = 0;
+ long recsize = 0;
+ off_t recpos = 0;
+ void *gribbuffer;
+ size_t buffersize = 0;
+ int fileID;
+ int param = 0;
+ int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
+ DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
+ int vrecID, recID;
+ int warn_numavg = TRUE;
+ size_t readsize;
+ int taxisID = -1;
+ int rindex, nrecs = 0;
+ int nrecs_scanned;
+ long unzipsize;
+ char paramstr[32];
+
+ /*
+ if ( CDI_Debug )
{
- if ( vlistInqVarCode(vlistID, varID) == -varID-1 )
+ Message("streamID = %d", streamptr->self);
+ Message("cts = %d", streamptr->curTsID);
+ Message("rts = %d", streamptr->rtsteps);
+ Message("nts = %d", streamptr->ntsteps);
+ }
+ */
+ int *isec0 = streamptr->record->sec0;
+ int *isec1 = streamptr->record->sec1;
+ int *isec2 = streamptr->record->sec2;
+ int *isec3 = streamptr->record->sec3;
+ int *isec4 = streamptr->record->sec4;
+
+ int tsID = streamptr->rtsteps;
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+
+ if ( streamptr->tsteps[tsID].recordSize == 0 )
+ {
+ gribbuffer = streamptr->record->buffer;
+ buffersize = streamptr->record->buffersize;
+
+ cdi_create_records(streamptr, tsID);
+
+ nrecs = streamptr->tsteps[1].nrecs;
+
+ streamptr->tsteps[tsID].nrecs = nrecs;
+ streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
+ for ( recID = 0; recID < nrecs; recID++ )
+ streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
+
+ fileID = streamptr->fileID;
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+
+ nrecs_scanned = streamptr->tsteps[0].nallrecs + streamptr->tsteps[1].nrecs*(tsID-1);
+ rindex = 0;
+ while ( TRUE )
{
- const char *pname = vlistInqVarNamePtr(vlistID, varID);
- size_t len = strlen(pname);
- if ( len > 3 && isdigit((int) pname[3]) )
+ if ( rindex > nrecs ) break;
+
+ recsize = gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
+ if ( recsize == 0 )
{
- if ( memcmp("var", pname, 3) == 0 )
- {
- vlistDefVarCode(vlistID, varID, atoi(pname+3));
- // vlistDestroyVarName(vlistID, varID);
- }
+ streamptr->ntsteps = streamptr->rtsteps + 1;
+ break;
}
- else if ( len > 4 && isdigit((int) pname[4]) )
+ if ( recsize > 0 && (size_t)recsize > buffersize )
{
- if ( memcmp("code", pname, 4) == 0 )
- {
- vlistDefVarCode(vlistID, varID, atoi(pname+4));
- // vlistDestroyVarName(vlistID, varID);
- }
+ buffersize = (size_t)recsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
}
- else if ( len > 5 && isdigit((int) pname[5]) )
+
+ if ( rindex >= nrecs ) break;
+
+ readsize = (size_t)recsize;
+ rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
+ if ( rstatus )
{
- if ( memcmp("param", pname, 5) == 0 )
- {
- int pnum = -1, pcat = 255, pdis = 255;
- sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis);
- vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis));
- // vlistDestroyVarName(vlistID, varID);
- }
+ Warning("Inconsistent timestep %d (GRIB record %d/%d)!", tsID+1, rindex+1,
+ streamptr->tsteps[tsID].recordSize);
+ break;
}
- }
- }
- for ( int varID = 0; varID < nvars; varID++ )
- {
- int varInstID = vlistInqVarInstitut(vlistID, varID);
- int varModelID = vlistInqVarModel(vlistID, varID);
- int varTableID = vlistInqVarTable(vlistID, varID);
- int code = vlistInqVarCode(vlistID, varID);
- if ( cdiDefaultTableID != UNDEFID )
- {
- if ( tableInqParNamePtr(cdiDefaultTableID, code) )
+ if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
{
- vlistDestroyVarName(vlistID, varID);
- vlistDestroyVarLongname(vlistID, varID);
- vlistDestroyVarUnits(vlistID, varID);
-
- if ( varTableID != UNDEFID )
- {
- vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code));
- if ( tableInqParLongnamePtr(cdiDefaultTableID, code) )
- vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code));
- if ( tableInqParUnitsPtr(cdiDefaultTableID, code) )
- vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code));
- }
- else
+ unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+ if ( buffersize < (size_t)unzipsize )
{
- varTableID = cdiDefaultTableID;
+ buffersize = (size_t)unzipsize;
+ gribbuffer = Realloc(gribbuffer, buffersize);
}
}
- if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID;
- if ( cdiDefaultInstID != UNDEFID ) varInstID = cdiDefaultInstID;
- }
- if ( varInstID != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID);
- if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID);
- if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID);
- }
-}
+ cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
+ (int *) gribbuffer, (int)recsize, &lmv, &iret);
-static
-void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, int *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used)
-{
- nc_type xtype;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- enum { attstringlen = 65636 };
- char attstring[attstringlen];
- int iatt;
+ nrecs_scanned++;
- for ( iatt = 0; iatt < ngatts; iatt++ )
- {
- cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname);
- cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype);
- cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen);
+ param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
+ cdiParamToString(param, paramstr, sizeof(paramstr));
- if ( xtypeIsText(xtype) )
- {
- cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring);
+ if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
+ if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
+ level1 = ISEC1_Level1;
+ level2 = ISEC1_Level2;
- size_t attstrlen = strlen(attstring);
+ gribDateTime(isec1, &vdate, &vtime);
- if ( attlen > 0 && attstring[0] != 0 )
+ if ( rindex == nrecs ) break;
+
+ if ( rindex == 0 )
{
- if ( strcmp(attname, "history") == 0 )
- {
- streamptr->historyID = iatt;
- }
- else if ( strcmp(attname, "institution") == 0 )
+ int vlistID = streamptr->vlistID;
+ taxisID = vlistInqTaxis(vlistID);
+ if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
{
- *instID = institutInq(0, 0, NULL, attstring);
- if ( *instID == UNDEFID )
- *instID = institutDef(0, 0, NULL, attstring);
+ taxis->type = TAXIS_RELATIVE;
+ taxis->rdate = gribRefDate(isec1);
+ taxis->rtime = gribRefTime(isec1);
}
- else if ( strcmp(attname, "source") == 0 )
+ else
{
- *modelID = modelInq(-1, 0, attstring);
- if ( *modelID == UNDEFID )
- *modelID = modelDef(-1, 0, attstring);
+ taxis->type = TAXIS_ABSOLUTE;
}
- else if ( strcmp(attname, "Source") == 0 )
+ taxis->unit = cgribexGetTimeUnit(isec1);
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
+
+ datetime0.date = vdate;
+ datetime0.time = vtime;
+ }
+
+ if ( ISEC1_AvgNum )
+ {
+ if ( taxis->numavg && warn_numavg &&
+ (taxis->numavg != ISEC1_AvgNum) )
{
- if ( strncmp(attstring, "UCLA-LES", 8) == 0 )
- *ucla_les = TRUE;
- }
/*
- else if ( strcmp(attname, "Conventions") == 0 )
- {
- }
+ Warning("Changing numavg from %d to %d not supported!", streamptr->tsteps[tsID].taxis.numavg, ISEC1_AvgNum);
*/
- else if ( strcmp(attname, "CDI") == 0 )
- {
- }
- else if ( strcmp(attname, "CDO") == 0 )
- {
- }
- /*
- else if ( strcmp(attname, "forecast_reference_time") == 0 )
- {
- memcpy(fcreftime, attstring, attstrlen+1);
- }
- */
- else if ( strcmp(attname, "grid_file_uri") == 0 )
- {
- memcpy(gridfile, attstring, attstrlen+1);
- }
- else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 )
- {
- attstring[36] = 0;
- str2uuid(attstring, uuidOfHGrid);
- // printf("uuid: %d %s\n", attlen, attstring);
- }
- else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
- {
- attstring[36] = 0;
- str2uuid(attstring, uuidOfVGrid);
+ warn_numavg = FALSE;
}
else
{
- if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 )
- {
- memcpy(gridfile, attstring, attstrlen+1);
- }
-
- vlistDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring);
+ taxis->numavg = ISEC1_AvgNum;
}
}
- }
- else if ( xtype == NC_SHORT || xtype == NC_INT )
- {
- if ( strcmp(attname, "number_of_grid_used") == 0 )
- {
- (*number_of_grid_used) = UNDEFID;
- cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used);
- }
- else
- {
- int attint[attlen];
- cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint);
- if ( xtype == NC_SHORT )
- vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint);
- else
- vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT32, (int)attlen, attint);
- }
- }
- else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE )
- {
- double attflt[attlen];
- cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt);
- if ( xtype == NC_FLOAT )
- vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt);
- else
- vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT64, (int)attlen, attflt);
- }
- }
-}
-static
-int find_leadtime(int nvars, ncvar_t *ncvars)
-{
- int leadtime_id = UNDEFID;
+ datetime.date = vdate;
+ datetime.time = vtime;
- for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- if ( ncvars[ncvarid].stdname[0] )
- {
- if ( strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 )
- {
- leadtime_id = ncvarid;
- break;
- }
- }
- }
+ compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
- return (leadtime_id);
-}
+ for ( vrecID = 0; vrecID < nrecs; vrecID++ )
+ {
+ recID = streamptr->tsteps[1].recIDs[vrecID];
+ if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
+ }
-static
-void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr,
- int *time_has_units, int *time_has_bounds, int *time_climatology)
-{
- int ncvarid;
+ if ( vrecID == nrecs )
+ {
+ gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
- if ( timedimid == UNDEFID )
- {
- char timeunits[CDI_MAX_NAME];
+ if ( cdiInventoryMode == 1 )
+ return (CDI_EUFSTRUCT);
+ else
+ continue;
+ }
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 )
- {
- if ( ncvars[ncvarid].units[0] )
- {
- strcpy(timeunits, ncvars[ncvarid].units);
- strtolower(timeunits);
+ if ( cdiInventoryMode == 1 )
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ else
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ char paramstr_[32];
+ cdiParamToString(param, paramstr_, sizeof(paramstr_));
- if ( isTimeUnits(timeunits) )
- {
- streamptr->basetime.ncvarid = ncvarid;
- break;
- }
- }
- }
- }
- }
- else
- {
- int ltimevar = FALSE;
+ if ( datetimeCmp(datetime, datetime0) != 0 ) break;
- if ( ncdims[timedimid].ncvarid != UNDEFID )
- {
- streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid;
- ltimevar = TRUE;
- }
+ if ( CDI_Debug )
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr_, level1, level2);
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- if ( ncvarid != streamptr->basetime.ncvarid &&
- ncvars[ncvarid].ndims == 1 &&
- timedimid == ncvars[ncvarid].dimids[0] &&
- !xtypeIsText(ncvars[ncvarid].xtype) &&
- isTimeAxisUnits(ncvars[ncvarid].units) )
- {
- ncvars[ncvarid].isvar = FALSE;
+ continue;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ }
- if ( !ltimevar )
- {
- streamptr->basetime.ncvarid = ncvarid;
- ltimevar = TRUE;
- if ( CDI_Debug )
- fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name);
- }
- else
- {
- Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name);
- }
- }
+ if ( CDI_Debug )
+ Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
- if ( ltimevar == FALSE ) /* search for WRF time description */
- {
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- if ( ncvarid != streamptr->basetime.ncvarid &&
- ncvars[ncvarid].ndims == 2 &&
- timedimid == ncvars[ncvarid].dimids[0] &&
- xtypeIsText(ncvars[ncvarid].xtype) &&
- ncdims[ncvars[ncvarid].dimids[1]].len == 19 )
- {
- streamptr->basetime.ncvarid = ncvarid;
- streamptr->basetime.lwrf = TRUE;
- break;
- }
- }
+ if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, level1);
+ Error("Invalid, unsupported or inconsistent record structure");
+ }
- /* time varID */
- ncvarid = streamptr->basetime.ncvarid;
+ streamptr->tsteps[tsID].records[recID].position = recpos;
+ streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
- if ( ncvarid == UNDEFID )
- {
- Warning("Time variable >%s< not found!", ncdims[timedimid].name);
- }
- }
+ rindex++;
+ }
- /* time varID */
- ncvarid = streamptr->basetime.ncvarid;
+ for ( vrecID = 0; vrecID < nrecs; vrecID++ )
+ {
+ recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ if ( ! streamptr->tsteps[tsID].records[recID].used ) break;
+ }
- if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == FALSE )
- {
- if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = TRUE;
+ if ( vrecID < nrecs )
+ {
+ cdiParamToString(streamptr->tsteps[tsID].records[recID].param, paramstr, sizeof(paramstr));
+ gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, paramstr,
+ streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
+ return (CDI_EUFSTRUCT);
+ }
- if ( ncvars[ncvarid].bounds != UNDEFID )
- {
- int nbdims = ncvars[ncvars[ncvarid].bounds].ndims;
- if ( nbdims == 2 )
- {
- int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len;
- if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] )
- {
- *time_has_bounds = TRUE;
- streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds;
- if ( ncvars[ncvarid].climatology ) *time_climatology = TRUE;
- }
- }
- }
- }
-}
+ streamptr->rtsteps++;
-static
-void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize)
-{
- /* find ECHAM VCT */
- int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID;
+ if ( streamptr->ntsteps != streamptr->rtsteps )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- if ( ncvars[ncvarid].ndims == 1 )
- {
- size_t len = strlen(ncvars[ncvarid].name);
- if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' )
- {
- if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai
- {
- vcta_id = ncvarid;
- nvcth_id = ncvars[ncvarid].dimids[0];
- ncvars[ncvarid].isvar = FALSE;
- }
- else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi
- {
- vctb_id = ncvarid;
- nvcth_id = ncvars[ncvarid].dimids[0];
- ncvars[ncvarid].isvar = FALSE;
- }
- else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' )
- {
- ncvars[ncvarid].isvar = FALSE; // hyam or hybm
- }
- }
+ streamptr->tsteps[tsID-1].next = 1;
+ streamptr->tsteps[tsID].position = recpos;
}
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ streamptr->tsteps[tsID].position = recpos;
+
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = buffersize;
}
- /* read VCT */
- if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID )
+ if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
{
- size_t vctsize = ncdims[nvcth_id].len;
- vctsize *= 2;
- *vct = (double *) Malloc(vctsize*sizeof(double));
- cdf_get_var_double(fileID, vcta_id, *vct);
- cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2);
- *pvctsize = vctsize;
+ Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
+ streamptr->ntsteps = tsID;
}
-}
-
-int cdfInqContents(stream_t *streamptr)
-{
- int ndims, nvars, ngatts, unlimdimid;
- int ncvarid;
- int ncdimid;
- size_t ntsteps;
- int timedimid = -1;
- int *varids;
- int nvarids;
- int time_has_units = FALSE;
- int time_has_bounds = FALSE;
- int time_climatology = FALSE;
- int leadtime_id = UNDEFID;
- int nvars_data;
- int instID = UNDEFID;
- int modelID = UNDEFID;
- int taxisID;
- int i;
- int calendar = UNDEFID;
- ncdim_t *ncdims;
- ncvar_t *ncvars = NULL;
- int format = 0;
- int ucla_les = FALSE;
- unsigned char uuidOfHGrid[CDI_UUID_SIZE];
- unsigned char uuidOfVGrid[CDI_UUID_SIZE];
- char gridfile[8912];
- char fcreftime[CDI_MAX_NAME];
- int number_of_grid_used = UNDEFID;
-
- memset(uuidOfHGrid, 0, CDI_UUID_SIZE);
- memset(uuidOfVGrid, 0, CDI_UUID_SIZE);
- gridfile[0] = 0;
- fcreftime[0] = 0;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID);
+ rstatus = (int)streamptr->ntsteps;
-#if defined (HAVE_NETCDF4)
- nc_inq_format(fileID, &format);
+ return (rstatus);
+}
#endif
- cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid);
+#ifdef gribWarning
+#undef gribWarning
+#endif
- if ( CDI_Debug )
- Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts);
+#if defined (HAVE_LIBCGRIBEX)
+int cgribexDecode(int memtype, void *gribbuffer, int gribsize, void *data, long datasize,
+ int unreduced, int *nmiss, double missval)
+{
+ int status = 0;
+ int iret = 0, iword = 0;
+ int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
+ float fsec2f[512], fsec3f[2];
+ double fsec2[512], fsec3[2];
+ char hoper[2];
- if ( ndims == 0 )
- {
- Warning("ndims = %d", ndims);
- return (CDI_EUFSTRUCT);
- }
+ if ( unreduced ) strcpy(hoper, "R");
+ else strcpy(hoper, "D");
- /* alloc ncdims */
- ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t));
- init_ncdims(ndims, ncdims);
+ FSEC3_MissVal = missval;
- if ( nvars > 0 )
- {
- /* alloc ncvars */
- ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t));
- init_ncvars(nvars, ncvars);
+ if ( memtype == MEMTYPE_FLOAT )
+ gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, hoper, &iret);
+ else
+ gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, hoper, &iret);
- for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
- ncvars[ncvarid].ncid = fileID;
- }
+ if ( ISEC1_Sec2Or3Flag & 64 )
+ *nmiss = ISEC4_NumValues - ISEC4_NumNonMissValues;
+ else
+ *nmiss = 0;
-#if defined (TEST_GROUPS)
-#if defined (HAVE_NETCDF4)
- if ( format == NC_FORMAT_NETCDF4 )
+ if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
{
- int ncid;
- int numgrps;
- int ncids[NC_MAX_VARS];
- char name1[CDI_MAX_NAME];
- int gndims, gnvars, gngatts, gunlimdimid;
- nc_inq_grps(fileID, &numgrps, ncids);
- for ( int i = 0; i < numgrps; ++i )
- {
- ncid = ncids[i];
- nc_inq_grpname (ncid, name1);
- cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid);
-
- if ( CDI_Debug )
- Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts);
+ double undef_pds, undef_eps;
+ MCH_get_undef(isec1, &undef_pds, &undef_eps);
- if ( gndims == 0 )
- {
+ *nmiss = 0;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ float *restrict dataf = (float*) data;
+ for ( long i = 0; i < datasize; i++ )
+ if ( (fabs(dataf[i]-undef_pds) < undef_eps) || IS_EQUAL(dataf[i],FSEC3_MissVal) ) {
+ dataf[i] = (float)missval;
+ (*nmiss)++;
+ }
+ }
+ else
+ {
+ double *restrict datad = (double*) data;
+ for ( long i = 0; i < datasize; i++ )
+ if ( (fabs(datad[i]-undef_pds) < undef_eps) || IS_EQUAL(datad[i],FSEC3_MissVal) ) {
+ datad[i] = missval;
+ (*nmiss)++;
}
}
- }
-#endif
-#endif
-
- if ( nvars == 0 )
- {
- Warning("nvars = %d", nvars);
- return (CDI_EUFSTRUCT);
}
- /* scan global attributes */
- scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les,
- uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used);
+ return status;
+}
+#endif
- /* find time dim */
- if ( unlimdimid >= 0 )
- timedimid = unlimdimid;
- else
- timedimid = cdfTimeDimID(fileID, ndims, nvars);
- streamptr->basetime.ncdimid = timedimid;
+#if defined (HAVE_LIBCGRIBEX)
+static
+void cgribexDefInstitut(int *isec1, int vlistID, int varID)
+{
+ int instID;
- if ( timedimid != UNDEFID )
- cdf_inq_dimlen(fileID, timedimid, &ntsteps);
+ if ( vlistInqInstitut(vlistID) != CDI_UNDEFID )
+ instID = vlistInqInstitut(vlistID);
else
- ntsteps = 0;
-
- if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps);
- if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid);
+ instID = vlistInqVarInstitut(vlistID, varID);
- /* read ncdims */
- for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
+ if ( instID != CDI_UNDEFID )
{
- cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len);
- cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name);
- if ( timedimid == ncdimid )
- ncdims[ncdimid].dimtype = T_AXIS;
+ int center, subcenter;
+ center = institutInqCenter(instID);
+ subcenter = institutInqSubcenter(instID);
+ ISEC1_CenterID = center;
+ ISEC1_SubCenterID = subcenter;
}
+}
- if ( CDI_Debug ) printNCvars(ncvars, nvars, "cdfScanVarAttributes");
-
- /* scan attributes of all variables */
- cdfScanVarAttributes(nvars, ncvars, ncdims, timedimid, modelID, format);
-
+static
+void cgribexDefModel(int *isec1, int vlistID, int varID)
+{
+ int modelID;
- if ( CDI_Debug ) printNCvars(ncvars, nvars, "find coordinate vars");
+ if ( vlistInqModel(vlistID) != CDI_UNDEFID )
+ modelID = vlistInqModel(vlistID);
+ else
+ modelID = vlistInqVarModel(vlistID, varID);
- /* find coordinate vars */
- for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
- {
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- {
- if ( ncvars[ncvarid].ndims == 1 )
- {
- if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] )
- {
- if ( ncvars[ncvarid].isvar != FALSE ) cdfSetVar(ncvars, ncvarid, TRUE);
- }
- else
- {
- // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
- }
- // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE);
+ if ( modelID != CDI_UNDEFID )
+ ISEC1_ModelID = modelInqGribID(modelID);
+}
- if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID )
- if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 )
- {
- ncdims[ncdimid].ncvarid = ncvarid;
- ncvars[ncvarid].isvar = FALSE;
- }
- }
- }
- }
+static
+void cgribexDefParam(int *isec1, int param)
+{
+ int pdis, pcat, pnum;
- /* find time vars */
- find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology);
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
- leadtime_id = find_leadtime(nvars, ncvars);
- if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE;
+ if ( pnum < 0 ) pnum = -pnum;
- /* check ncvars */
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ static bool lwarn_pdis = true;
+ if ( pdis != 255 && lwarn_pdis )
{
- if ( timedimid != UNDEFID )
- if ( ncvars[ncvarid].isvar == -1 &&
- ncvars[ncvarid].ndims > 1 &&
- timedimid == ncvars[ncvarid].dimids[0] )
- cdfSetVar(ncvars, ncvarid, TRUE);
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ Warning("Can't convert GRIB2 parameter ID (%s) to GRIB1, set to %d.%d!", paramstr, pnum, pcat);
+ lwarn_pdis = false;
+ }
- if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 )
- cdfSetVar(ncvars, ncvarid, FALSE);
+ static bool lwarn_pnum = true;
+ if ( pnum > 255 && lwarn_pnum )
+ {
+ Warning("Parameter number %d out of range (1-255), set to %d!", pnum, pnum%256);
+ lwarn_pnum = false;
+ pnum = pnum%256;
+ }
- //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 )
- if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 )
- cdfSetVar(ncvars, ncvarid, TRUE);
+ ISEC1_CodeTable = pcat;
+ ISEC1_Parameter = pnum;
+}
- if ( ncvars[ncvarid].isvar == -1 )
- {
- ncvars[ncvarid].isvar = 0;
- Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name);
- continue;
- }
+static
+int cgribexDefTimerange(int tsteptype, int factor, int calendar,
+ int rdate, int rtime, int vdate, int vtime, int *pip1, int *pip2)
+{
+ int timerange = -1;
+ int year, month, day, hour, minute, second;
+ int julday1, secofday1, julday2, secofday2, days, secs;
+ int ip, ip1 = 0, ip2 = 0;
- if ( ncvars[ncvarid].ndims > 4 )
- {
- ncvars[ncvarid].isvar = 0;
- Warning("%d dimensional variables are not supported, skipped variable %s!",
- ncvars[ncvarid].ndims, ncvars[ncvarid].name);
- continue;
- }
+ cdiDecodeDate(rdate, &year, &month, &day);
+ cdiDecodeTime(rtime, &hour, &minute, &second);
+ encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday1, &secofday1);
- if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID )
- {
- ncvars[ncvarid].isvar = 0;
- Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!",
- ncvars[ncvarid].ndims, ncvars[ncvarid].name);
- continue;
- }
+ cdiDecodeDate(vdate, &year, &month, &day);
+ cdiDecodeTime(vtime, &hour, &minute, &second);
+ encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
- if ( xtypeIsText(ncvars[ncvarid].xtype) )
- {
- ncvars[ncvarid].isvar = 0;
- continue;
- }
+ (void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
- if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 )
- {
- ncvars[ncvarid].isvar = 0;
- Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name);
- continue;
- }
+ if ( !(int)(fmod(days*86400.0 + secs, factor)) )
+ {
+ ip = (int) ((days*86400.0 + secs)/factor);
- if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 )
+ switch ( tsteptype )
{
- if ( timedimid == ncvars[ncvarid].dimids[0] )
- {
- ncvars[ncvarid].isvar = 0;
- Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name);
- continue;
- }
+ case TSTEP_INSTANT: timerange = 0; ip1 = ip; ip2 = 0; break;
+ case TSTEP_INSTANT2: timerange = 1; ip1 = 0; ip2 = 0; break;
+ case TSTEP_RANGE: timerange = 2; ip1 = 0; ip2 = ip; break;
+ case TSTEP_AVG: timerange = 3; ip1 = 0; ip2 = ip; break;
+ case TSTEP_ACCUM: timerange = 4; ip1 = 0; ip2 = ip; break;
+ case TSTEP_DIFF: timerange = 5; ip1 = 0; ip2 = ip; break;
+ case TSTEP_INSTANT3:
+ default: timerange = 10; ip1 = ip/256; ip2 = ip%256; break;
}
}
- /* verify coordinate vars - first scan (dimname == varname) */
- verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid);
+ *pip1 = ip1;
+ *pip2 = ip2;
- /* verify coordinate vars - second scan (all other variables) */
- verify_coordinate_vars_2(nvars, ncvars);
+ return (timerange);
+}
- if ( CDI_Debug ) printNCvars(ncvars, nvars, "verify_coordinate_vars");
+static
+int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
+{
+ int year, month, day, hour, minute, second;
+ int century = 0;
+ int factor = 1;
- if ( ucla_les == TRUE )
- {
- for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
- {
- ncvarid = ncdims[ncdimid].ncvarid;
- if ( ncvarid != -1 )
- {
- if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' )
- {
- if ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS;
- else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS;
- else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS;
- }
- }
- }
- }
- /*
- for ( ncdimid = 0; ncdimid < ndims; ncdimid++ )
- {
- ncvarid = ncdims[ncdimid].ncvarid;
- if ( ncvarid != -1 )
- {
- printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units);
- if ( ncdims[ncdimid].dimtype == X_AXIS )
- printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name);
- if ( ncdims[ncdimid].dimtype == Y_AXIS )
- printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name);
- if ( ncdims[ncdimid].dimtype == Z_AXIS )
- printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name);
- if ( ncdims[ncdimid].dimtype == T_AXIS )
- printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name);
+ cdiDecodeDate(date, &year, &month, &day);
+ cdiDecodeTime(time, &hour, &minute, &second);
- if ( ncvars[ncvarid].islon )
- printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name);
- if ( ncvars[ncvarid].islat )
- printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name);
- if ( ncvars[ncvarid].islev )
- printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name);
- }
+ century = year / 100;
+
+ ISEC1_Year = year - century*100;
+
+ if ( year < 0 )
+ {
+ century = -century;
+ ISEC1_Year = -ISEC1_Year;
}
- */
- /* Set coordinate varids (att: associate) */
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
+ if ( ISEC1_Year == 0 )
{
- if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].ncoordvars )
- {
- /* ndims = ncvars[ncvarid].ndims; */
- ndims = ncvars[ncvarid].ncoordvars;
- for ( i = 0; i < ndims; i++ )
- {
- if ( ncvars[ncvars[ncvarid].coordvarids[i]].islon )
- ncvars[ncvarid].xvarid = ncvars[ncvarid].coordvarids[i];
- else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islat )
- ncvars[ncvarid].yvarid = ncvars[ncvarid].coordvarids[i];
- else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islev )
- ncvars[ncvarid].zvarid = ncvars[ncvarid].coordvarids[i];
- }
- }
+ century -= 1;
+ ISEC1_Year = 100;
}
- /* set dim type */
- setDimType(nvars, ncvars, ncdims);
+ century += 1;
+ if ( year < 0 ) century = -century;
- /* read ECHAM VCT if present */
- size_t vctsize = 0;
- double *vct = NULL;
- read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize);
+ ISEC1_Month = month;
+ ISEC1_Day = day;
+ ISEC1_Hour = hour;
+ ISEC1_Minute = minute;
+ ISEC1_Century = century;
- if ( CDI_Debug ) printNCvars(ncvars, nvars, "define_all_grids");
+ switch (timeunit)
+ {
+ case TUNIT_MINUTE: factor = 60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE; break;
+ case TUNIT_QUARTER: factor = 900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER; break;
+ case TUNIT_30MINUTES: factor = 1800; ISEC1_TimeUnit = ISEC1_TABLE4_30MINUTES; break;
+ case TUNIT_HOUR: factor = 3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR; break;
+ case TUNIT_3HOURS: factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS; break;
+ case TUNIT_6HOURS: factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS; break;
+ case TUNIT_12HOURS: factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS; break;
+ case TUNIT_DAY: factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY; break;
+ default: factor = 3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR; break;
+ }
- /* define all grids */
- define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used);
+ return (factor);
+}
+static
+void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg, int taxisID)
+{
+ int timetype = TAXIS_ABSOLUTE;
+ int timerange = 0;
+ int timeunit = TUNIT_HOUR;
- /* define all zaxes */
- define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid);
- if ( vct ) Free(vct);
+ if ( taxisID != -1 )
+ {
+ timetype = taxisInqType(taxisID);
+ timeunit = taxisInqTunit(taxisID);
+ }
+ if ( timetype == TAXIS_RELATIVE )
+ {
+ int factor = 1;
+ int rdate, rtime;
+ int ip1 = 0, ip2 = 0;
+ int calendar;
- /* select vars */
- varids = (int *) Malloc((size_t)nvars * sizeof (int));
- nvarids = 0;
- for ( ncvarid = 0; ncvarid < nvars; ncvarid++ )
- if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid;
+ calendar = taxisInqCalendar(taxisID);
+ rdate = taxisInqRdate(taxisID);
+ rtime = taxisInqRtime(taxisID);
- nvars_data = nvarids;
+ factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
+ timerange = cgribexDefTimerange(tsteptype, factor, calendar,
+ rdate, rtime, vdate, vtime, &ip1, &ip2);
- if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid);
- if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
- if ( CDI_Debug ) Message("nvars_data = %d", nvars_data);
+ if ( ip2 > 0xFF && timeunit < TUNIT_YEAR )
+ {
+ timeunit++;
+ factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
+ timerange = cgribexDefTimerange(tsteptype, factor, calendar,
+ rdate, rtime, vdate, vtime, &ip1, &ip2);
+ }
+ if ( timerange == -1 || timerange == 3 )
+ {
+ timetype = TAXIS_ABSOLUTE;
+ }
+ /*
+ else if ( timerange == 10 )
+ {
+ if ( ip1 < 0 || ip1 > 0xFFFF ) timetype = TAXIS_ABSOLUTE;
+ if ( ip2 < 0 || ip2 > 0xFFFF ) timetype = TAXIS_ABSOLUTE;
+ }
+ */
+ else
+ {
+ if ( ip1 < 0 || ip1 > 0xFF ) timetype = TAXIS_ABSOLUTE;
+ if ( ip2 < 0 || ip2 > 0xFF ) timetype = TAXIS_ABSOLUTE;
+ }
- if ( nvars_data == 0 )
- {
- streamptr->ntsteps = 0;
- return (CDI_EUFSTRUCT);
+ ISEC1_TimeRange = timerange;
+ ISEC1_TimePeriod1 = ip1;
+ ISEC1_TimePeriod2 = ip2;
}
- if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID )
- ntsteps = 1;
+ if ( timetype == TAXIS_ABSOLUTE )
+ {
+ (void) cgribexDefDateTime(isec1, timeunit, vdate, vtime);
- streamptr->ntsteps = (long)ntsteps;
+ /*
+ if ( numavg > 0 )
+ ISEC1_TimeRange = 0;
+ else
+ */
+ if ( ISEC1_TimeRange != 3 )
+ ISEC1_TimeRange = 10;
- /* define all data variables */
- define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars);
+ ISEC1_TimePeriod1 = 0;
+ ISEC1_TimePeriod2 = 0;
+ }
+ ISEC1_AvgNum = numavg;
+ ISEC1_AvgMiss = 0;
+ ISEC1_DecScaleFactor = 0;
+}
- cdiCreateTimesteps(streamptr);
+static
+void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID)
+{
+ int gridtype;
+ bool lcurvi = false;
+ static bool lwarning = true;
- /* time varID */
- int nctimevarid = streamptr->basetime.ncvarid;
+ memset(isec2, 0, 16*sizeof(int));
- if ( time_has_units )
- {
- taxis_t *taxis = &streamptr->tsteps[0].taxis;
+ ISEC1_Sec2Or3Flag = 128;
- if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 )
- {
- nctimevarid = UNDEFID;
- streamptr->basetime.ncvarid = UNDEFID;
- }
+ gridtype = gridInqType(gridID);
- if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE )
- {
- streamptr->basetime.leadtimeid = leadtime_id;
- taxis->type = TAXIS_FORECAST;
+ ISEC1_GridDefinition = 255;
- int timeunit = -1;
- if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units);
- if ( timeunit == -1 ) timeunit = taxis->unit;
- taxis->fc_unit = timeunit;
+ if ( gridtype == GRID_GENERIC )
+ {
+ int xsize, ysize, gridsize;
- setForecastTime(fcreftime, taxis);
- }
- }
+ gridsize = gridInqSize(gridID);
+ xsize = gridInqXsize(gridID);
+ ysize = gridInqYsize(gridID);
- if ( time_has_bounds )
- {
- streamptr->tsteps[0].taxis.has_bounds = TRUE;
- if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = TRUE;
+ if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
+ ysize == 96 || ysize == 160 || ysize == 192 ||
+ ysize == 240 || ysize == 320 || ysize == 384 ||
+ ysize == 480 || ysize == 768 ) &&
+ (xsize == 2*ysize || xsize == 1) )
+ {
+ gridtype = GRID_GAUSSIAN;
+ gridChangeType(gridID, gridtype);
+ }
+ else if ( gridsize == 1 )
+ {
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
+ }
+ else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+ {
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
+ }
}
-
- if ( nctimevarid != UNDEFID )
+ else if ( gridtype == GRID_CURVILINEAR )
{
- taxis_t *taxis = &streamptr->tsteps[0].taxis;
- ptaxisDefName(taxis, ncvars[nctimevarid].name);
- if ( ncvars[nctimevarid].longname[0] )
- ptaxisDefLongname(taxis, ncvars[nctimevarid].longname);
+ if ( lwarning && gridInqSize(gridID) > 1 )
+ {
+ lwarning = false;
+ Warning("Curvilinear grids are unsupported in GRIB1! Created wrong GDS!");
+ }
+ gridtype = GRID_LONLAT;
+ lcurvi = true;
}
- if ( nctimevarid != UNDEFID )
- if ( ncvars[nctimevarid].calendar == TRUE )
+ ISEC2_Reduced = FALSE;
+ ISEC2_ScanFlag = 0;
+
+ switch (gridtype)
+ {
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ case GRID_GAUSSIAN_REDUCED:
+ case GRID_TRAJECTORY:
{
- enum {attstringlen = 8192};
- char attstring[attstringlen];
+ int nlon = 0, nlat;
+ double xfirst = 0, xlast = 0, xinc = 0;
+ double yfirst = 0, ylast = 0, yinc = 0;
- cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring);
- strtolower(attstring);
+ if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
+ ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN;
+ else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+ ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT;
+ else
+ ISEC2_GridType = GRIB1_GTYPE_LATLON;
- if ( memcmp(attstring, "standard", 8) == 0 ||
- memcmp(attstring, "gregorian", 9) == 0 )
- calendar = CALENDAR_STANDARD;
- else if ( memcmp(attstring, "none", 4) == 0 )
- calendar = CALENDAR_NONE;
- else if ( memcmp(attstring, "proleptic", 9) == 0 )
- calendar = CALENDAR_PROLEPTIC;
- else if ( memcmp(attstring, "360", 3) == 0 )
- calendar = CALENDAR_360DAYS;
- else if ( memcmp(attstring, "365", 3) == 0 ||
- memcmp(attstring, "noleap", 6) == 0 )
- calendar = CALENDAR_365DAYS;
- else if ( memcmp(attstring, "366", 3) == 0 ||
- memcmp(attstring, "all_leap", 8) == 0 )
- calendar = CALENDAR_366DAYS;
+ nlon = gridInqXsize(gridID);
+ nlat = gridInqYsize(gridID);
+
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ ISEC2_Reduced = TRUE;
+ nlon = 0;
+ gridInqRowlon(gridID, ISEC2_RowLonPtr);
+ }
else
- Warning("calendar >%s< unsupported!", attstring);
- }
+ {
+ if ( nlon == 0 )
+ {
+ nlon = 1;
+ }
+ else
+ {
+ xfirst = gridInqXval(gridID, 0);
+ if ( lcurvi )
+ xlast = gridInqXval(gridID, nlon*nlat-1);
+ else
+ xlast = gridInqXval(gridID, nlon-1);
+ xinc = gridInqXinc(gridID);
+ }
+ }
- if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST )
- {
- taxisID = taxisCreate(TAXIS_FORECAST);
- }
- else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE )
- {
- taxisID = taxisCreate(TAXIS_RELATIVE);
- }
- else
- {
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- if ( !time_has_units )
- {
- taxisDefTunit(taxisID, TUNIT_DAY);
- streamptr->tsteps[0].taxis.unit = TUNIT_DAY;
- }
- }
+ if ( nlat == 0 )
+ {
+ nlat = 1;
+ }
+ else
+ {
+ yfirst = gridInqYval(gridID, 0);
+ if ( lcurvi )
+ ylast = gridInqYval(gridID, nlon*nlat-1);
+ else
+ ylast = gridInqYval(gridID, nlat-1);
+ yinc = gridInqYinc(gridID);
+ if ( yinc < 0 ) yinc = -yinc;
+ }
+
+ ISEC2_NumLon = nlon;
+ ISEC2_NumLat = nlat;
+ ISEC2_FirstLat = (int)lround(yfirst*1000);
+ ISEC2_LastLat = (int)lround(ylast*1000);
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ ISEC2_FirstLon = 0;
+ ISEC2_LastLon = (int)lround(1000*(360.-360./(nlat*2)));
+ ISEC2_LonIncr = (int)lround(1000*360./(nlat*2));
+ }
+ else
+ {
+ ISEC2_FirstLon = (int)lround(xfirst*1000);
+ ISEC2_LastLon = (int)lround(xlast*1000);
+ ISEC2_LonIncr = (int)lround(xinc*1000);
+ }
+
+ if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ int np = gridInqNP(gridID);
+ if ( np == 0 ) np = nlat/2;
+ ISEC2_NumPar = np;
+ }
+ else
+ {
+ ISEC2_LatIncr = (int)lround(yinc*1000);
+ if ( ISEC2_LatIncr < 0 ) ISEC2_LatIncr = -ISEC2_LatIncr;
+ }
+ if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
+ if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr;
- if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE )
- {
- calendar = CALENDAR_STANDARD;
- }
+ if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
+ if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow"
-#endif
- if ( calendar != UNDEFID )
- {
- taxis_t *taxis = &streamptr->tsteps[0].taxis;
- taxis->calendar = calendar;
- taxisDefCalendar(taxisID, calendar);
- }
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
-#pragma GCC diagnostic pop
-#endif
+ if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
+ ISEC2_ResFlag = 0;
+ else
+ ISEC2_ResFlag = 128;
- vlistDefTaxis(vlistID, taxisID);
+ if ( gridIsRotated(gridID) )
+ {
+ ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000);
+ ISEC2_LonSP = (int)lround((gridInqXpole(gridID) + 180) * 1000);
+ double angle = gridInqAngle(gridID);
+ if ( fabs(angle) > 0 ) angle = -angle;
+ FSEC2_RotAngle = angle;
+ }
- streamptr->curTsID = 0;
- streamptr->rtsteps = 1;
+ /* East -> West */
+ if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
- (void) cdfInqTimestep(streamptr, 0);
+ /* South -> North */
+ if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
- cdfCreateRecords(streamptr, 0);
+ break;
+ }
+ case GRID_LCC:
+ {
+ double originLon = 0.0, originLat = 0.0, lonParY = 0.0,
+ lat1 = 0.0, lat2 = 0.0, xincm = 0.0, yincm = 0.0;
+ int projflag = 0, scanflag = 0;
- /* free ncdims */
- Free(ncdims);
+ int xsize = gridInqXsize(gridID),
+ ysize = gridInqYsize(gridID);
- /* free ncvars */
- Free(ncvars);
+ gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
+ &projflag, &scanflag);
- return (0);
-}
+ ISEC2_GridType = GRIB1_GTYPE_LCC;
+ ISEC2_NumLon = xsize;
+ ISEC2_NumLat = ysize;
+ ISEC2_FirstLon = (int)lround(originLon * 1000);
+ ISEC2_FirstLat = (int)lround(originLat * 1000);
+ ISEC2_Lambert_Lov = (int)lround(lonParY * 1000);
+ ISEC2_Lambert_LatS1 = (int)lround(lat1 * 1000);
+ ISEC2_Lambert_LatS2 = (int)lround(lat2 * 1000);
+ ISEC2_Lambert_dx = (int)lround(xincm);
+ ISEC2_Lambert_dy = (int)lround(yincm);
+ ISEC2_Lambert_LatSP = 0;
+ ISEC2_Lambert_LonSP = 0;
+ ISEC2_Lambert_ProjFlag = projflag;
+ ISEC2_ScanFlag = scanflag;
-static
-void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis)
-{
- size_t start[2], count[2];
- char stvalue[32];
- start[0] = (size_t) tsID; start[1] = 0;
- count[0] = 1; count[1] = 19;
- stvalue[0] = 0;
- cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
- stvalue[19] = 0;
- {
- int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0;
- if ( strlen(stvalue) == 19 )
- sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second);
- taxis->vdate = cdiEncodeDate(year, month, day);
- taxis->vtime = cdiEncodeTime(hour, minute, second);
- taxis->type = TAXIS_ABSOLUTE;
- }
+ break;
+ }
+ case GRID_SPECTRAL:
+ {
+ ISEC2_GridType = GRIB1_GTYPE_SPECTRAL;
+ ISEC2_PentaJ = gridInqTrunc(gridID);
+ ISEC2_PentaK = ISEC2_PentaJ;
+ ISEC2_PentaM = ISEC2_PentaJ;
+ ISEC2_RepType = 1;
+ isec4[2] = 128;
+ if ( gridInqComplexPacking(gridID) && ISEC2_PentaJ >= 21 )
+ {
+ ISEC2_RepMode = 2;
+ isec4[3] = 64;
+ isec4[16] = 0;
+ isec4[17] = 20;
+ isec4[18] = 20;
+ isec4[19] = 20;
+ }
+ else
+ {
+ ISEC2_RepMode = 1;
+ isec4[3] = 0;
+ }
+ break;
+ }
+ case GRID_GME:
+ {
+ ISEC2_GridType = GRIB1_GTYPE_GME;
+ ISEC2_GME_ND = gridInqGMEnd(gridID);
+ ISEC2_GME_NI = gridInqGMEni(gridID);
+ ISEC2_GME_NI2 = gridInqGMEni2(gridID);
+ ISEC2_GME_NI3 = gridInqGMEni3(gridID);
+ ISEC2_GME_AFlag = 0;
+ ISEC2_GME_LatPP = 90000;
+ ISEC2_GME_LonPP = 0;
+ ISEC2_GME_LonMPL = 0;
+ ISEC2_GME_BFlag = 0;
+ break;
+ }
+ default:
+ {
+ Warning("The CGRIBEX library can not store fields on the used grid!");
+ Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+ break;
+ }
+ }
}
static
-double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache)
+void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int levelID)
{
- double timevalue = 0;
- size_t index = (size_t) tsID;
+ double level;
+ int ilevel, zaxistype, ltype;
+ static bool lwarning_vct = true;
- if ( tcache )
- {
- if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) )
- {
- int maxvals = MAX_TIMECACHE_SIZE;
- tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE;
- if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE;
- tcache->size = maxvals;
- index = (size_t) tcache->startid;
- // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals);
- for ( int ival = 0; ival < maxvals; ++ival )
- {
- cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
- if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
- tcache->cache[ival] = timevalue;
- index++;
- }
- }
+ zaxistype = zaxisInqType(zaxisID);
+ ltype = zaxisInqLtype(zaxisID);
- timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE];
- }
- else
+ if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
{
- cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue);
- if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+ Message("Changed zaxis type from %s to %s",
+ zaxisNamePtr(zaxistype),
+ zaxisNamePtr(ZAXIS_PRESSURE));
+ zaxistype = ZAXIS_PRESSURE;
+ zaxisChangeType(zaxisID, zaxistype);
+ zaxisDefUnits(zaxisID, "Pa");
}
- return timevalue;
-}
-
-
-int cdfInqTimestep(stream_t * streamptr, int tsID)
-{
- long nrecs = 0;
- double timevalue;
- int fileID;
- taxis_t *taxis;
-
- if ( CDI_Debug ) Message("streamID = %d tsID = %d", streamptr->self, tsID);
-
- if ( tsID < 0 ) Error("unexpected tsID = %d", tsID);
+ ISEC2_NumVCP = 0;
- if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 )
+ switch (zaxistype)
{
- cdfCreateRecords(streamptr, tsID);
-
- taxis = &streamptr->tsteps[tsID].taxis;
- if ( tsID > 0 )
- ptaxisCopy(taxis, &streamptr->tsteps[0].taxis);
-
- timevalue = tsID;
-
- int nctimevarid = streamptr->basetime.ncvarid;
- if ( nctimevarid != UNDEFID )
- {
- fileID = streamptr->fileID;
- size_t index = (size_t)tsID;
-
- if ( streamptr->basetime.lwrf )
- {
- wrf_read_timestep(fileID, nctimevarid, tsID, taxis);
- }
- else
- {
-#if defined (USE_TIMECACHE)
- if ( streamptr->basetime.timevar_cache == NULL )
- {
- streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t));
- streamptr->basetime.timevar_cache->size = 0;
- streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps;
- }
-#endif
- timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache);
- cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime);
- }
+ case ZAXIS_SURFACE:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_SURFACE;
+ ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_CLOUD_BASE:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_CLOUD_BASE;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_CLOUD_TOP:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_CLOUD_TOP;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_ISOTHERM_ZERO:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_ISOTHERM0;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_TOA:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_TOA;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_SEA_BOTTOM:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_SEA_BOTTOM;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_ATMOSPHERE:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_ATMOSPHERE;
+ ISEC1_Level1 = 0;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_MEANSEA:
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_MEANSEA;
+ ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_HYBRID:
+ case ZAXIS_HYBRID_HALF:
+ {
+ int vctsize;
- int nctimeboundsid = streamptr->basetime.ncvarboundsid;
- if ( nctimeboundsid != UNDEFID )
- {
- size_t start[2], count[2];
- start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1;
- cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
- if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_HYBRID_LAYER;
+ ISEC1_Level1 = (int)(zaxisInqLbound(zaxisID, levelID));
+ ISEC1_Level2 = (int)(zaxisInqUbound(zaxisID, levelID));
+ }
+ else
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_HYBRID;
+ ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
+ ISEC1_Level2 = 0;
+ }
- cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb);
+ vctsize = zaxisInqVctSize(zaxisID);
+ if ( vctsize > 255 )
+ {
+ ISEC2_NumVCP = 0;
+ if ( lwarning_vct )
+ {
+ Warning("VCT size of %d is too large (maximum is 255). Set to 0!", vctsize);
+ lwarning_vct = false;
+ }
+ }
+ else
+ {
+ ISEC2_NumVCP = vctsize;
+ zaxisInqVct(zaxisID, &fsec2[10]);
+ }
+ break;
+ }
+ case ZAXIS_PRESSURE:
+ {
+ double dum;
+ char units[128];
- start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1;
- cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue);
- if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0;
+ level = zaxisInqLevel(zaxisID, levelID);
+ if ( level < 0 )
+ Warning("Pressure level of %f Pa is below zero!", level);
- cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub);
- }
+ zaxisInqUnits(zaxisID, units);
+ if ( (units[0] != 'P') | (units[1] != 'a') ) level *= 100;
- int leadtimeid = streamptr->basetime.leadtimeid;
- if ( leadtimeid != UNDEFID )
- {
- timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL);
- cdiSetForecastPeriod(timevalue, taxis);
- }
- }
- }
+ ilevel = (int) level;
+ if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_99;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
+ }
+ else
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_ISOBARIC;
+ ISEC1_Level1 = ilevel/100;
+ ISEC1_Level2 = 0;
+ }
+ break;
+ }
+ case ZAXIS_HEIGHT:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- streamptr->curTsID = tsID;
- nrecs = streamptr->tsteps[tsID].nrecs;
+ char units[128];
+ zaxisInqUnits(zaxisID, units);
+ if ( units[1] == 'm' && !units[2] )
+ {
+ if ( units[0] == 'c' ) level *= 0.01;
+ else if ( units[0] == 'd' ) level *= 0.1;
+ else if ( units[0] == 'k' ) level *= 1000;
+ }
- return ((int) nrecs);
-}
+ ilevel = (int) level;
+ ISEC1_LevelType = GRIB1_LTYPE_HEIGHT;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_ALTITUDE:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
-void cdfEndDef(stream_t *streamptr)
-{
- int varID;
- int nvars;
- int fileID;
+ ilevel = (int) level;
+ ISEC1_LevelType = GRIB1_LTYPE_ALTITUDE;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
- fileID = streamptr->fileID;
+ break;
+ }
+ case ZAXIS_SIGMA:
+ {
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+ {
+ ISEC1_LevelType = GRIB1_LTYPE_SIGMA_LAYER;
+ ISEC1_Level1 = (int)(zaxisInqLbound(zaxisID, levelID));
+ ISEC1_Level2 = (int)(zaxisInqUbound(zaxisID, levelID));
+ }
+ else
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- cdfDefGlobalAtts(streamptr);
- cdfDefLocalAtts(streamptr);
+ ilevel = (int) level;
+ ISEC1_LevelType = GRIB1_LTYPE_SIGMA;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
+ }
- if ( streamptr->accessmode == 0 )
- {
- nvars = streamptr->nvars;
+ break;
+ }
+ case ZAXIS_DEPTH_BELOW_LAND:
+ {
+ char units[128];
+ double factor;
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ zaxisInqUnits(zaxisID, units);
- for ( varID = 0; varID < nvars; varID++ )
- cdfDefVar(streamptr, varID);
+ if ( units[0] == 'm' && units[1] == 'm' ) factor = 0.1;
+ else if ( units[0] == 'c' && units[1] == 'm' ) factor = 1;
+ else if ( units[0] == 'd' && units[1] == 'm' ) factor = 10;
+ else factor = 100; // meter
- if ( streamptr->ncmode == 2 )
- {
- if ( CDI_netcdf_hdr_pad == 0UL )
- cdf_enddef(fileID);
- else
- cdf__enddef(fileID, CDI_netcdf_hdr_pad);
- }
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+ {
+ double level1, level2;
+ level1 = zaxisInqLbound(zaxisID, levelID);
+ level2 = zaxisInqUbound(zaxisID, levelID);
+ ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH_LAYER;
+ ISEC1_Level1 = (int) (level1*factor);
+ ISEC1_Level2 = (int) (level2*factor);
+ }
+ else
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- streamptr->accessmode = 1;
- }
-}
+ ilevel = (int) (level*factor);
+ ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
+ }
+ break;
+ }
+ case ZAXIS_DEPTH_BELOW_SEA:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
-static void cdfDefInstitut(stream_t *streamptr)
-{
- int fileID, instID;
- size_t len;
- int vlistID;
+ ilevel = (int) level;
+ ISEC1_LevelType = GRIB1_LTYPE_SEADEPTH;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- instID = vlistInqInstitut(vlistID);
+ break;
+ }
+ case ZAXIS_ISENTROPIC:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- if ( instID != UNDEFID )
- {
- const char *longname = institutInqLongnamePtr(instID);
- if ( longname )
- {
- len = strlen(longname);
- if ( len > 0 )
- {
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_put_att_text(fileID, NC_GLOBAL, "institution", len, longname);
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
- }
- }
- }
-}
+ ilevel = (int) level;
+ ISEC1_LevelType = GRIB1_LTYPE_ISENTROPIC;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
+ break;
+ }
+ case ZAXIS_GENERIC:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
-static void cdfDefSource(stream_t *streamptr)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int modelID = vlistInqModel(vlistID);
+ ilevel = (int) level;
+ ISEC1_LevelType = ltype;
+ ISEC1_Level1 = ilevel;
+ ISEC1_Level2 = 0;
- if ( modelID != UNDEFID )
- {
- const char *longname = modelInqNamePtr(modelID);
- if ( longname )
- {
- size_t len = strlen(longname);
- if ( len > 0 )
- {
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_put_att_text(fileID, NC_GLOBAL, "source", len, longname);
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
- }
- }
+ break;
+ }
+ default:
+ {
+ Error("Unsupported zaxis type: %s", zaxisNamePtr(zaxistype));
+ break;
+ }
}
}
-
-static void cdfDefGlobalAtts(stream_t *streamptr)
+static
+void cgribexDefaultSec0(int *isec0)
{
- int natts;
-
- if ( streamptr->globalatts ) return;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- cdfDefSource(streamptr);
- cdfDefInstitut(streamptr);
-
- vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
-
- if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- defineAttributes(vlistID, CDI_GLOBAL, fileID, NC_GLOBAL);
-
- if ( natts > 0 && streamptr->ncmode == 2 ) cdf_enddef(fileID);
-
- streamptr->globalatts = 1;
+ ISEC0_GRIB_Len = 0;
+ ISEC0_GRIB_Version = 0;
}
+static
+void cgribexDefaultSec1(int *isec1)
+{
+ ISEC1_CenterID = 0;
+ ISEC1_SubCenterID = 0;
+ ISEC1_LocalFLag = 0;
+}
-static void cdfDefLocalAtts(stream_t *streamptr)
+static
+void cgribexDefaultSec4(int *isec4)
{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
+ for ( int i = 2; i <= 10; ++i ) isec4[i] = 0;
+}
- if ( streamptr->localatts ) return;
- if ( vlistInqInstitut(vlistID) != UNDEFID ) return;
+static
+void cgribexDefEnsembleVar(int *isec1, int vlistID, int varID)
+{
+ int ensID, ensCount, forecast_type;
- streamptr->localatts = 1;
+ /* For Ensemble info */
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ //Put1Byte(isec1[36]); /* MPIM local GRIB use definition identifier */
+ /* (extension identifier) */
+ //Put1Byte(isec1[37]); /* type of ensemble forecast */
+ //Put2Byte(isec1[38]); /* individual ensemble member */
+ //Put2Byte(isec1[39]); /* number of forecasts in ensemble */
- for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ if ( vlistInqVarEnsemble(vlistID, varID, &ensID, &ensCount, &forecast_type) )
{
- int instID = vlistInqVarInstitut(vlistID, varID);
- if ( instID != UNDEFID )
- {
- int ncvarid = streamptr->vars[varID].ncvarid;
- const char *name = institutInqNamePtr(instID);
- if ( name )
- {
- size_t len = strlen(name);
- cdf_put_att_text(fileID, ncvarid, "institution", len, name);
- }
- }
- }
+ if ( ISEC1_CenterID == 252 )
+ {
+ ISEC1_LocalFLag = 1;
+ isec1[36] = 1;
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ isec1[37] = forecast_type;
+ isec1[38] = ensID;
+ isec1[39] = ensCount;
+ }
+ }
}
+#endif
-void cdfDefHistory(stream_t *streamptr, int size, const char *history)
+#if defined (HAVE_LIBCGRIBEX)
+size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize)
{
- int ncid = streamptr->fileID;
- cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history);
-}
+ size_t nbytes = 0;
+ int gribsize;
+ int iret = 0, iword = 0;
+ int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
+ float fsec2f[512], fsec3f[2];
+ double fsec2[512], fsec3[2];
+ int datatype;
+ int param;
+ memset(isec1, 0, 256*sizeof(int));
+ fsec2[0] = 0; fsec2[1] = 0;
+ fsec2f[0] = 0; fsec2f[1] = 0;
-int cdfInqHistorySize(stream_t *streamptr)
-{
- size_t size = 0;
- int ncid = streamptr->fileID;
- if ( streamptr->historyID != UNDEFID )
- cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size);
+ gribsize = (int)(gribbuffersize / sizeof(int));
+ param = vlistInqVarParam(vlistID, varID);
- return ((int) size);
-}
+ cgribexDefaultSec0(isec0);
+ cgribexDefaultSec1(isec1);
+ cgribexDefaultSec4(isec4);
+ cgribexDefInstitut(isec1, vlistID, varID);
+ cgribexDefModel(isec1, vlistID, varID);
-void cdfInqHistoryString(stream_t *streamptr, char *history)
-{
- int ncid = streamptr->fileID;
- if ( streamptr->historyID != UNDEFID )
- cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
-}
+ datatype = vlistInqVarDatatype(vlistID, varID);
+ cgribexDefParam(isec1, param);
+ cgribexDefTime(isec1, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID));
+ cgribexDefGrid(isec1, isec2, fsec2, isec4, gridID);
+ cgribexDefLevel(isec1, isec2, fsec2, zaxisID, levelID);
-void cdfDefVars(stream_t *streamptr)
-{
- int vlistID = streamptr->vlistID;
- if ( vlistID == UNDEFID )
- Error("Internal problem! vlist undefined for streamptr %p", streamptr);
+ cgribexDefEnsembleVar(isec1, vlistID, varID);
- int ngrids = vlistNgrids(vlistID);
- int nzaxis = vlistNzaxis(vlistID);
- /*
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
- */
- if ( ngrids > 0 )
- for ( int index = 0; index < ngrids; index++ )
- {
- int gridID = vlistGrid(vlistID, index);
- cdfDefGrid(streamptr, gridID);
- }
+ ISEC4_NumValues = gridInqSize(gridID);
+ ISEC4_NumBits = grbBitsPerValue(datatype);
- if ( nzaxis > 0 )
- for ( int index = 0; index < nzaxis; index++ )
- {
- int zaxisID = vlistZaxis(vlistID, index);
- if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID);
- }
+ if ( nmiss > 0 )
+ {
+ FSEC3_MissVal = vlistInqVarMissval(vlistID, varID);
+ ISEC1_Sec2Or3Flag |= 64;
+ }
- /* define time first!!!
- int nvars = vlistNvars(vlistID);
- for ( int varID = 0; varID < nvars; varID++ )
+ if ( isec4[2] == 128 && isec4[3] == 64 )
{
- int ncvarid = cdfDefVar(streamptr, varID);
+ if ( memtype == MEMTYPE_FLOAT )
+ isec4[16] = (int) (1000*calculate_pfactor_float((const float*) data, ISEC2_PentaJ, isec4[17]));
+ else
+ isec4[16] = (int) (1000*calculate_pfactor_double((const double*) data, ISEC2_PentaJ, isec4[17]));
+ if ( isec4[16] < -10000 ) isec4[16] = -10000;
+ if ( isec4[16] > 10000 ) isec4[16] = 10000;
}
- */
-}
-#endif
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#ifndef CDI_DATETIME_H
-#define CDI_DATETIME_H
+ //printf("isec4[16] %d\n", isec4[16]);
-typedef struct
-{
- long date;
- long time;
-}
-DateTime;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ size_t numVCP = ISEC2_NumVCP > 0 ? (size_t)ISEC2_NumVCP : (size_t)0;
+ for ( size_t i = 0; i < numVCP; ++i ) fsec2f[10+i] = (float)fsec2[10+i];
+ fsec3f[ 1] = (float)fsec3[ 1];
+ }
-static inline int
-datetimeCmp(DateTime dt1, DateTime dt2)
-{
- return 2 * ((dt1.date > dt2.date) - (dt1.date < dt2.date))
- + (dt1.time > dt2.time) - (dt1.time < dt2.time);
-}
+ if ( memtype == MEMTYPE_FLOAT )
+ gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, "C", &iret);
+ else
+ gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, "C", &iret);
+ if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
+ nbytes = (size_t)iword * sizeof (int);
+ return nbytes;
+}
#endif
/*
* Local Variables:
@@ -45846,21 +47285,16 @@ datetimeCmp(DateTime dt1, DateTime dt2)
* require-trailing-newline: t
* End:
*/
-#ifndef _STREAM_CGRIBEX_H
-#define _STREAM_CGRIBEX_H
-
-int cgribexScanTimestep1(stream_t * streamptr);
-int cgribexScanTimestep2(stream_t * streamptr);
-int cgribexScanTimestep(stream_t * streamptr);
+#ifndef STREAM_FCOMMON_H
+#define STREAM_FCOMMON_H
-int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval);
+#ifndef _CDI_INT_H
+#endif
-size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize);
+void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
+ const char *container_name);
-#endif /* _STREAM_CGRIBEX_H */
+#endif
/*
* Local Variables:
* c-file-style: "Java"
@@ -45875,833 +47309,407 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
#include <limits.h>
#include <stdio.h>
-// #include <float.h> /* FLT_EPSILON */
-
-
-#if defined (HAVE_LIBCGRIBEX)
-#endif
-
-typedef struct {
- int param;
- int level1;
- int level2;
- int ltype;
- int tsteptype;
-} compvar_t;
-
-
-#if defined (HAVE_LIBCGRIBEX)
-static
-int cgribexGetGridType(int *isec2)
-{
- int gridtype = GRID_GENERIC;
-
- switch (ISEC2_GridType)
- {
- case GRIB1_GTYPE_LATLON: { if ( ISEC2_Reduced ) break; }
- case GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT; break; }
- case GRIB1_GTYPE_LCC: { gridtype = GRID_LCC; break; }
- case GRIB1_GTYPE_GAUSSIAN: { if ( ISEC2_Reduced )
- gridtype = GRID_GAUSSIAN_REDUCED;
- else
- gridtype = GRID_GAUSSIAN;
- break;
- }
- case GRIB1_GTYPE_SPECTRAL: { gridtype = GRID_SPECTRAL; break; }
- case GRIB1_GTYPE_GME: { gridtype = GRID_GME; break; }
- }
-
- return (gridtype);
-}
-
-static
-int cgribexGetIsRotated(int *isec2)
-{
- int isRotated = 0;
-
- if ( ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT )
- {
- isRotated = 1;
- }
-
- return (isRotated);
-}
-
-static
-int cgribexGetZaxisHasBounds(int grb_ltype)
-{
- int lbounds = 0;
-
- switch (grb_ltype)
- {
- case GRIB1_LTYPE_SIGMA_LAYER:
- case GRIB1_LTYPE_HYBRID_LAYER:
- case GRIB1_LTYPE_LANDDEPTH_LAYER:
- {
- lbounds = 1;
- break;
- }
- }
-
- return (lbounds);
-}
-
-static
-int cgribexGetTimeUnit(int *isec1)
-{
- int timeunit = TUNIT_HOUR;
- static int lprint = TRUE;
-
- switch ( ISEC1_TimeUnit )
- {
- case ISEC1_TABLE4_MINUTE: timeunit = TUNIT_MINUTE; break;
- case ISEC1_TABLE4_QUARTER: timeunit = TUNIT_QUARTER; break;
- case ISEC1_TABLE4_30MINUTES: timeunit = TUNIT_30MINUTES; break;
- case ISEC1_TABLE4_HOUR: timeunit = TUNIT_HOUR; break;
- case ISEC1_TABLE4_3HOURS: timeunit = TUNIT_3HOURS; break;
- case ISEC1_TABLE4_6HOURS: timeunit = TUNIT_6HOURS; break;
- case ISEC1_TABLE4_12HOURS: timeunit = TUNIT_12HOURS; break;
- case ISEC1_TABLE4_DAY: timeunit = TUNIT_DAY; break;
- default:
- if ( lprint )
- {
- Message("GRIB time unit %d unsupported!", ISEC1_TimeUnit);
- lprint = FALSE;
- }
- break;
- }
-
- return (timeunit);
-}
-
-static
-int cgribexTimeIsFC(int *isec1)
-{
- int isFC = TRUE;
-
- if ( ISEC1_TimeRange == 10 && ISEC1_TimePeriod1 == 0 && ISEC1_TimePeriod2 == 0 )
- isFC = FALSE;
-
- return (isFC);
-}
-
-static
-int cgribexGetTsteptype(int timerange)
-{
- int tsteptype = TSTEP_INSTANT;
- static int lprint = TRUE;
-
- switch ( timerange )
- {
- case 0: tsteptype = TSTEP_INSTANT; break;
- case 1: tsteptype = TSTEP_INSTANT2; break;
- case 2: tsteptype = TSTEP_RANGE; break;
- case 3: tsteptype = TSTEP_AVG; break;
- case 4: tsteptype = TSTEP_ACCUM; break;
- case 5: tsteptype = TSTEP_DIFF; break;
- case 10: tsteptype = TSTEP_INSTANT3; break;
- default:
- if ( lprint )
- {
- Message("Time range indicator %d unsupported, set to 0!", timerange);
- lprint = FALSE;
- }
- break;
- }
-
- return (tsteptype);
-}
-
-static
-void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4, grid_t *grid, int iret)
-{
- int compyinc = TRUE;
- int gridtype = cgribexGetGridType(isec2);
-
- if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
- {
- int ilat, nlon = 0;
- for ( ilat = 0; ilat < ISEC2_NumLat; ++ilat )
- if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
- gridtype = GRID_GAUSSIAN;
- ISEC2_NumLon = nlon;
- ISEC4_NumValues = nlon*ISEC2_NumLat;
- compyinc = FALSE;
- }
-
- memset(grid, 0, sizeof(grid_t));
- switch (gridtype)
- {
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- {
- if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
- Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
- grid->size = ISEC4_NumValues;
- grid->xsize = ISEC2_NumLon;
- grid->ysize = ISEC2_NumLat;
- if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar;
- grid->xinc = 0;
- grid->yinc = 0;
- grid->xdef = 0;
- /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
- {
- if ( grid->xsize > 1 )
- {
- int recompinc = TRUE;
-
- if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
-
- if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
- {
- if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->xsize-1))) <= 2 )
- {
- recompinc = FALSE;
- grid->xinc = ISEC2_LonIncr * 0.001;
- }
- }
-
- /* recompute xinc if necessary */
- if ( recompinc ) grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize-1);
-
- /* correct xinc if necessary */
- if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 )
- {
- double xinc = 360. / grid->xsize;
+#include <string.h>
- if ( fabs(grid->xinc-xinc) > 0.0 )
- {
- grid->xinc = xinc;
- if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
- }
- }
- }
- grid->xfirst = ISEC2_FirstLon * 0.001;
- grid->xlast = ISEC2_LastLon * 0.001;
- grid->xdef = 2;
- }
- grid->ydef = 0;
- /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
- {
- if ( grid->ysize > 1 && compyinc )
- {
- int recompinc = TRUE;
- if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
- {
- if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 )
- {
- recompinc = FALSE;
- grid->yinc = ISEC2_LatIncr * 0.001;
- }
- }
- /* recompute yinc if necessary */
- if ( recompinc ) grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
- }
- grid->yfirst = ISEC2_FirstLat * 0.001;
- grid->ylast = ISEC2_LastLat * 0.001;
- grid->ydef = 2;
- }
- break;
- }
- case GRID_GAUSSIAN_REDUCED:
- {
- grid->np = ISEC2_NumPar;
- grid->size = ISEC4_NumValues;
- grid->rowlon = ISEC2_RowLonPtr;
- grid->ysize = ISEC2_NumLat;
- grid->xinc = 0;
- grid->yinc = 0;
- grid->xdef = 0;
- /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
- {
- if ( grid->xsize > 1 )
- {
- if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
- if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
- grid->xinc = ISEC2_LonIncr * 0.001;
- else
- grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize - 1);
- }
- grid->xfirst = ISEC2_FirstLon * 0.001;
- grid->xlast = ISEC2_LastLon * 0.001;
- grid->xdef = 2;
- }
- grid->ydef = 0;
- /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
- {
- if ( grid->ysize > 1 )
- {
- if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
- grid->yinc = ISEC2_LatIncr * 0.001;
- else
- grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1);
- }
- grid->yfirst = ISEC2_FirstLat * 0.001;
- grid->ylast = ISEC2_LastLat * 0.001;
- grid->ydef = 2;
- }
- break;
- }
- case GRID_LCC:
- {
- if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
- Error("numberOfPoints (%d) and gridSize (%d) differ!",
- ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
- grid->size = ISEC4_NumValues;
- grid->xsize = ISEC2_NumLon;
- grid->ysize = ISEC2_NumLat;
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
- grid->lcc_xinc = ISEC2_Lambert_dx;
- grid->lcc_yinc = ISEC2_Lambert_dy;
- grid->lcc_originLon = ISEC2_FirstLon * 0.001;
- grid->lcc_originLat = ISEC2_FirstLat * 0.001;
- grid->lcc_lonParY = ISEC2_Lambert_Lov * 0.001;
- grid->lcc_lat1 = ISEC2_Lambert_LatS1 * 0.001;
- grid->lcc_lat2 = ISEC2_Lambert_LatS2 * 0.001;
- grid->lcc_projflag = ISEC2_Lambert_ProjFlag;
- grid->lcc_scanflag = ISEC2_ScanFlag;
+#define SINGLE_PRECISION 4
+#define DOUBLE_PRECISION 8
- grid->xdef = 0;
- grid->ydef = 0;
+#if defined (HAVE_LIBEXTRA)
- break;
- }
- case GRID_SPECTRAL:
- {
- grid->size = ISEC4_NumValues;
- grid->trunc = ISEC2_PentaJ;
- if ( ISEC2_RepMode == 2 )
- grid->lcomplex = 1;
- else
- grid->lcomplex = 0;
- break;
- }
- case GRID_GME:
- {
- grid->size = ISEC4_NumValues;
- grid->nd = ISEC2_GME_ND;
- grid->ni = ISEC2_GME_NI;
- grid->ni2 = ISEC2_GME_NI2;
- grid->ni3 = ISEC2_GME_NI3;
- break;
- }
- case GRID_GENERIC:
- {
- grid->size = ISEC4_NumValues;
- grid->xsize = 0;
- grid->ysize = 0;
- break;
- }
- default:
- {
- Error("Unsupported grid type: %s", gridNamePtr(gridtype));
- break;
- }
- }
+typedef struct {
+ int param;
+ int level;
+} extcompvar_t;
- grid->isRotated = FALSE;
- if ( cgribexGetIsRotated(isec2) )
+static
+int extInqDatatype(int prec, int number)
+{
+ int datatype;
+
+ if ( number == 2 )
{
- grid->isRotated = TRUE;
- grid->ypole = - ISEC2_LatSP*0.001;
- grid->xpole = ISEC2_LonSP*0.001 - 180;
- grid->angle = - FSEC2_RotAngle;
+ if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_CPX64;
+ else datatype = DATATYPE_CPX32;
+ }
+ else
+ {
+ if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
+ else datatype = DATATYPE_FLT32;
}
- grid->xvals = NULL;
- grid->yvals = NULL;
- grid->type = gridtype;
+ return (datatype);
}
static
-void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, double *fsec2, double *fsec3,
- int *isec4, long recsize, off_t position, int datatype, int comptype, int lmv, int iret)
+void extDefDatatype(int datatype, int *prec, int *number)
{
- int varID;
- int levelID = 0;
- grid_t grid;
- int vlistID = streamptr->vlistID;
- int tsID = streamptr->curTsID;
- int recID = recordNewEntry(streamptr, tsID);
- record_t *record = &streamptr->tsteps[tsID].records[recID];
+ if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 &&
+ datatype != DATATYPE_CPX32 && datatype != DATATYPE_CPX64 )
+ datatype = DATATYPE_FLT32;
- int tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
- int numavg = ISEC1_AvgNum;
+ if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
+ *number = 2;
+ else
+ *number = 1;
- int level1 = ISEC1_Level1;
- int level2 = ISEC1_Level2;
+ if ( datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64 )
+ *prec = DOUBLE_PRECISION;
+ else
+ *prec = SINGLE_PRECISION;
+}
- /* fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, ISEC1_LevelType); */
+/* not used
+int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
+{
+ int status;
+ int fileID;
+ int icode, ilevel;
+ int zaxisID = -1;
+ int header[4];
+ int vlistID;
+ void *extp = streamptr->record->exsep;
- record->size = (size_t)recsize;
- record->position = position;
- record->param = param;
- record->ilevel = level1;
- record->ilevel2 = level2;
- record->ltype = ISEC1_LevelType;
- record->tsteptype = tsteptype;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
- cgribexGetGrid(streamptr, isec2, fsec2, isec4, &grid, iret);
+ *varID = -1;
+ *levelID = -1;
- int gridID = varDefGrid(vlistID, &grid, 0);
+ status = extRead(fileID, extp);
+ if ( status != 0 ) return (0);
- int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
+ extInqHeader(extp, header);
- if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
- {
- size_t vctsize = (size_t)ISEC2_NumVCP;
- double *vctptr = &fsec2[10];
+ icode = header[1];
+ ilevel = header[2];
- varDefVCT(vctsize, vctptr);
- }
+ *varID = vlistInqVarID(vlistID, icode);
- int lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
+ if ( *varID == UNDEFID ) Error("Code %d undefined", icode);
- if ( datatype > 32 ) datatype = DATATYPE_PACK32;
- if ( datatype < 0 ) datatype = DATATYPE_PACK;
+ zaxisID = vlistInqVarZaxis(vlistID, *varID);
- varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, 0, 0,
- datatype, &varID, &levelID, tsteptype, numavg, ISEC1_LevelType, -1,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
- record->varID = (short)varID;
- record->levelID = (short)levelID;
+ return (1);
+}
+*/
- varDefCompType(varID, comptype);
+void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
+{
+ int vlistID, fileID;
+ int status;
+ int recID, vrecID, tsID;
+ off_t recpos;
+ int header[4];
+ int varID, gridID;
+ int i, size;
+ double missval;
+ void *extp = streamptr->record->exsep;
- if ( ISEC1_LocalFLag )
- {
- if ( ISEC1_CenterID == 78 && isec1[36] == 253 ) // DWD local extension
- varDefEnsembleInfo(varID, isec1[54], isec1[53], isec1[52]);
- else if ( ISEC1_CenterID == 252 && isec1[36] == 1 ) // MPIM local extension
- varDefEnsembleInfo(varID, isec1[38], isec1[39], isec1[37]);
- }
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ vrecID = streamptr->tsteps[tsID].curRecID;
+ recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ recpos = streamptr->tsteps[tsID].records[recID].position;
+ varID = streamptr->tsteps[tsID].records[recID].varID;
- if ( lmv ) varDefMissval(varID, FSEC3_MissVal);
+ fileSetPos(fileID, recpos, SEEK_SET);
- if ( varInqInst(varID) == CDI_UNDEFID )
- {
- int center, subcenter, instID;
- center = ISEC1_CenterID;
- subcenter = ISEC1_SubCenterID;
- instID = institutInq(center, subcenter, NULL, NULL);
- if ( instID == CDI_UNDEFID )
- instID = institutDef(center, subcenter, NULL, NULL);
- varDefInst(varID, instID);
- }
+ status = extRead(fileID, extp);
+ if ( status != 0 )
+ Error("Failed to read EXTRA record");
- if ( varInqModel(varID) == CDI_UNDEFID )
- {
- int modelID;
- modelID = modelInq(varInqInst(varID), ISEC1_ModelID, NULL);
- if ( modelID == CDI_UNDEFID )
- modelID = modelDef(varInqInst(varID), ISEC1_ModelID, NULL);
- varDefModel(varID, modelID);
- }
+ extInqHeader(extp, header);
+ extInqDataDP(extp, data);
- if ( varInqTable(varID) == CDI_UNDEFID )
- {
- int tableID;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ size = gridInqSize(gridID);
- tableID = tableInq(varInqModel(varID), ISEC1_CodeTable, NULL);
+ streamptr->numvals += size;
- if ( tableID == CDI_UNDEFID )
- tableID = tableDef(varInqModel(varID), ISEC1_CodeTable, NULL);
- varDefTable(varID, tableID);
+ *nmiss = 0;
+ if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
+ {
+ for ( i = 0; i < size; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
+ }
+ else
+ {
+ for ( i = 0; i < 2*size; i+=2 )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
}
-
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
}
-static
-void MCH_get_undef(int *isec1, double *undef_pds, double *undef_eps)
+
+void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
{
- /* 2010-01-13: Oliver Fuhrer */
- if ( ISEC1_CenterID == 215 ) {
- if (isec1[34] != 0 && isec1[34] != 255) {
- if (isec1[34] & 2) {
- if (isec1[34] & 1) {
- *undef_pds = -0.99*pow(10.0,-isec1[35]);
- } else {
- *undef_pds = +0.99*pow(10.0,-isec1[35]);
- }
- *undef_eps = pow(10.0,-isec1[35]-1);
- } else {
- if (isec1[34] & 1) {
- *undef_pds = -0.99*pow(10.0,+isec1[35]);
- } else {
- *undef_pds = +0.99*pow(10.0,+isec1[35]);
- }
- *undef_eps = pow(10.0,isec1[35]-1);
- }
- }
- }
+ streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
}
-static
-void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
- int *isec3, double *fsec3, int *isec4, double *fsec4,
- int *gribbuffer, int recsize, int *lmv, int *iret)
-{
- int ipunp = 0, iword = 0;
- memset(isec1, 0, 256*sizeof(int));
+void extDefRecord(stream_t *streamptr)
+{
+ int gridID;
+ int header[4];
+ int pdis, pcat, pnum;
+ extrec_t *extp = (extrec_t*) streamptr->record->exsep;
- gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
- ipunp, (int *) gribbuffer, recsize, &iword, "J", iret);
+ gridID = streamptr->record->gridID;
- *lmv = 0;
+ cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
+ header[0] = streamptr->record->date;
+ header[1] = pnum;
+ header[2] = streamptr->record->level;
+ header[3] = gridInqSize(gridID);
- if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
- {
- double undef_pds, undef_eps;
+ extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
- MCH_get_undef(isec1, &undef_pds, &undef_eps);
- FSEC3_MissVal = undef_pds;
- *lmv = 1;
- }
+ extDefHeader(extp, header);
}
-static
-compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int trange)
-{
- compvar_t compVar;
- int tsteptype = cgribexGetTsteptype(trange);
- compVar.param = param;
- compVar.level1 = level1;
- compVar.level2 = level2;
- compVar.ltype = leveltype;
- compVar.tsteptype = tsteptype;
+void extWriteRecord(stream_t *streamptr, const double *data)
+{
+ int fileID = streamptr->fileID;
+ void *extp = streamptr->record->exsep;
- return (compVar);
+ extDefDataDP(extp, data);
+ extWrite(fileID, extp);
}
-static inline int
-cgribexVarCompare(compvar_t compVar, record_t record, int flag)
+static
+void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
+ size_t recsize, off_t position, int prec, int number)
{
- int tstepDiff = (!((flag == 0) & (((compVar.tsteptype == TSTEP_INSTANT)
- & (record.tsteptype == TSTEP_INSTANT3))
- |((compVar.tsteptype == TSTEP_INSTANT3)
- & (record.tsteptype == TSTEP_INSTANT)))))
- & (compVar.tsteptype != record.tsteptype);
- int rstatus = (compVar.param != record.param)
- | (compVar.level1 != record.ilevel)
- | (compVar.level2 != record.ilevel2)
- | (compVar.ltype != record.ltype)
- | tstepDiff;
- return (rstatus);
-}
-#endif
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
-#define gribWarning(text, nrecs, timestep, paramstr, level1, level2) \
- Warning("Record %2d (id=%s lev1=%d lev2=%d) timestep %d: %s", nrecs, paramstr, level1, level2, timestep, text)
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level;
-#if defined (HAVE_LIBCGRIBEX)
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, GRID_GENERIC, xysize);
+ grid->xsize = xysize;
+ grid->ysize = 0;
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
+ /*
+ if ( level == 0 ) leveltype = ZAXIS_SURFACE;
+ else leveltype = ZAXIS_GENERIC;
+ */
+ int leveltype = ZAXIS_GENERIC;
-static inline void
-cgribexScanTsFixNtsteps(stream_t *streamptr, off_t recpos)
-{
- if ( streamptr->ntsteps == -1 )
- {
- int tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ int varID, levelID = 0;
+ varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
+ extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
- }
-}
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
-static inline void
-cgribexScanTsConstAdjust(stream_t *streamptr, taxis_t *taxis)
-{
- int vlistID = streamptr->vlistID;
- if ( streamptr->ntsteps == 1 )
- {
- if ( taxis->vdate == 0 && taxis->vtime == 0 )
- {
- streamptr->ntsteps = 0;
- for (int varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- }
- }
+ if ( CDI_Debug )
+ Message("varID = %d gridID = %d levelID = %d",
+ varID, gridID, levelID);
}
-
-int cgribexScanTimestep1(stream_t * streamptr)
+static
+void extScanTimestep1(stream_t *streamptr)
{
- double fsec2[512], fsec3[2], *fsec4 = NULL;
- int lmv = 0, iret = 0;
- off_t recpos = 0;
- void *gribbuffer = NULL;
- size_t buffersize = 0;
- int rstatus;
+ int header[4];
+ int status;
+ int fileID;
+ int rxysize = 0;
int param = 0;
- int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
- DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
- size_t readsize;
- unsigned nrecords, recID;
- int nrecs_scanned = 0;
- int datatype;
- long recsize = 0;
- int warn_time = TRUE;
- int warn_numavg = TRUE;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ DateTime datetime0 = { LONG_MIN, LONG_MIN };
+ int tsID;
+ int varID;
+ long recsize;
+ off_t recpos;
+ int nrecords, nrecs, recID;
int taxisID = -1;
- int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
+ taxis_t *taxis;
int vlistID;
- int comptype;
- long unzipsize;
- char paramstr[32];
- int nskip = cdiSkipRecords;
+ extcompvar_t compVar, compVar0;
+ extrec_t *extp = (extrec_t*) streamptr->record->exsep;
streamptr->curTsID = 0;
- int *isec0 = streamptr->record->sec0;
- int *isec1 = streamptr->record->sec1;
- int *isec2 = streamptr->record->sec2;
- int *isec3 = streamptr->record->sec3;
- int *isec4 = streamptr->record->sec4;
-
- int tsID = tstepsNewEntry(streamptr);
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ tsID = tstepsNewEntry(streamptr);
+ taxis = &streamptr->tsteps[tsID].taxis;
if ( tsID != 0 )
Error("Internal problem! tstepsNewEntry returns %d", tsID);
- int fileID = streamptr->fileID;
-
- while ( nskip-- > 0 )
- {
- recsize = gribGetSize(fileID);
- if ( recsize == 0 )
- Error("Skipping of %d records failed!", cdiSkipRecords);
-
- recpos = fileGetPos(fileID);
- fileSetPos(fileID, (off_t)recsize, SEEK_CUR);
- }
+ fileID = streamptr->fileID;
- unsigned nrecs = 0;
+ nrecs = 0;
while ( TRUE )
{
- recsize = gribGetSize(fileID);
- recpos = fileGetPos(fileID);
-
- if ( recsize == 0 )
+ recpos = fileGetPos(fileID);
+ status = extRead(fileID, extp);
+ if ( status != 0 )
{
- if ( nrecs == 0 )
- Error("No GRIB records found!");
-
streamptr->ntsteps = 1;
break;
}
- if ( (size_t)recsize > buffersize )
- {
- buffersize = (size_t)recsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
-
- readsize = (size_t)recsize;
- rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
- if ( rstatus ) break;
-
- comptype = COMPRESS_NONE;
- if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
- {
- comptype = COMPRESS_SZIP;
- unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
- if ( buffersize < (size_t)unzipsize )
- {
- buffersize = (size_t)unzipsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
- }
-
- nrecs_scanned++;
- cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
- (int *) gribbuffer, (int)recsize, &lmv, &iret);
-
- param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
- cdiParamToString(param, paramstr, sizeof(paramstr));
+ recsize = fileGetPos(fileID) - recpos;
- if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
- if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
- level1 = ISEC1_Level1;
- level2 = ISEC1_Level2;
+ extInqHeader(extp, header);
- gribDateTime(isec1, &vdate, &vtime);
+ vdate = header[0];
+ vtime = 0;
+ rcode = header[1];
+ rlevel = header[2];
+ rxysize = header[3];
- if ( ISEC4_NumBits > 0 && ISEC4_NumBits <= 32 )
- datatype = ISEC4_NumBits;
- else
- datatype = DATATYPE_PACK;
+ param = cdiEncodeParam(rcode, 255, 255);
if ( nrecs == 0 )
{
datetime0.date = vdate;
datetime0.time = vtime;
- rdate = gribRefDate(isec1);
- rtime = gribRefTime(isec1);
- tunit = cgribexGetTimeUnit(isec1);
- fcast = cgribexTimeIsFC(isec1);
}
else
{
- datetime.date = vdate;
- datetime.time = vtime;
- compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
- for ( recID = 0; recID < nrecs; recID++ )
- {
- if ( cgribexVarCompare(compVar, streamptr->tsteps[0].records[recID], 0) == 0 ) break;
- }
-
- if ( cdiInventoryMode == 1 )
- {
- if ( recID < nrecs ) break;
- if ( warn_time )
- if ( datetimeCmp(datetime, datetime0) != 0 )
- {
- gribWarning("Inconsistent verification time!", nrecs_scanned, tsID+1, paramstr, level1, level2);
- warn_time = FALSE;
- }
- }
- else
- {
- if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-
- if ( recID < nrecs )
- {
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr, level1, level2);
- continue;
- }
- }
- }
-
- if ( ISEC1_AvgNum )
- {
- if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
- {
- Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
- warn_numavg = FALSE;
- }
- else
+ compVar.param = param;
+ compVar.level = rlevel;
+ for ( recID = 0; recID < nrecs; recID++ )
{
- taxis->numavg = ISEC1_AvgNum;
+ compVar0.param = streamptr->tsteps[0].records[recID].param;
+ compVar0.level = streamptr->tsteps[0].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 ) break;
}
+ if ( recID < nrecs ) break;
+ DateTime datetime = { .date = vdate, .time = vtime};
+ if ( datetimeCmp(datetime, datetime0) )
+ Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
}
nrecs++;
if ( CDI_Debug )
- Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
+ Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
- cgribexAddRecord(streamptr, param, isec1, isec2, fsec2, fsec3,
- isec4, recsize, recpos, datatype, comptype, lmv, iret);
+ extAddRecord(streamptr, param, rlevel, rxysize, (size_t)recsize, recpos, extp->prec, extp->number);
}
streamptr->rtsteps = 1;
- if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
-
cdi_generate_vars(streamptr);
- if ( fcast )
- {
- taxisID = taxisCreate(TAXIS_RELATIVE);
- taxis->type = TAXIS_RELATIVE;
- taxis->rdate = rdate;
- taxis->rtime = rtime;
- taxis->unit = tunit;
- }
- else
- {
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- taxis->type = TAXIS_ABSOLUTE;
- taxis->unit = tunit;
- }
-
+ taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ taxis->type = TAXIS_ABSOLUTE;
taxis->vdate = (int)datetime0.date;
taxis->vtime = (int)datetime0.time;
vlistID = streamptr->vlistID;
vlistDefTaxis(vlistID, taxisID);
- nrecords = (unsigned)streamptr->tsteps[0].nallrecs;
- if ( nrecords < (unsigned)streamptr->tsteps[0].recordSize )
+ vlist_check_contents(vlistID);
+
+ nrecords = streamptr->tsteps[0].nallrecs;
+ if ( nrecords < streamptr->tsteps[0].recordSize )
{
- streamptr->tsteps[0].recordSize = (int)nrecords;
+ streamptr->tsteps[0].recordSize = nrecords;
streamptr->tsteps[0].records =
- (record_t *) Realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
+ (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
}
- streamptr->tsteps[0].recIDs = (int *) Malloc(nrecords*sizeof(int));
- streamptr->tsteps[0].nrecs = (int)nrecords;
+ streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
+ streamptr->tsteps[0].nrecs = nrecords;
for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[0].recIDs[recID] = (int)recID;
+ streamptr->tsteps[0].recIDs[recID] = recID;
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = (size_t)buffersize;
+ if ( streamptr->ntsteps == -1 )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- cgribexScanTsFixNtsteps(streamptr, recpos);
- cgribexScanTsConstAdjust(streamptr, taxis);
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
- return (0);
+ if ( streamptr->ntsteps == 1 )
+ {
+ if ( taxis->vdate == 0 && taxis->vtime == 0 )
+ {
+ streamptr->ntsteps = 0;
+ for ( varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ }
+ }
}
-
-int cgribexScanTimestep2(stream_t * streamptr)
+static
+int extScanTimestep2(stream_t *streamptr)
{
- int rstatus = 0;
- double fsec2[512], fsec3[2], *fsec4 = NULL;
- int lmv = 0, iret = 0;
- off_t recpos = 0;
+ int header[4];
+ int status;
+ int fileID;
+ // int rxysize = 0;
int param = 0;
- int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
- DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
- int varID, gridID;
- size_t readsize;
- int nrecs, recID;
- long recsize = 0;
- int warn_numavg = TRUE;
- int tsteptype;
- long unzipsize;
- char paramstr[32];
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ int tsID;
+ int varID;
+ off_t recpos = 0;
+ int nrecords, nrecs, recID, rindex;
+ int nextstep;
+ taxis_t *taxis;
+ int vlistID;
+ extcompvar_t compVar, compVar0;
+ void *extp = streamptr->record->exsep;
streamptr->curTsID = 1;
- int *isec0 = streamptr->record->sec0;
- int *isec1 = streamptr->record->sec1;
- int *isec2 = streamptr->record->sec2;
- int *isec3 = streamptr->record->sec3;
- int *isec4 = streamptr->record->sec4;
-
- int fileID = streamptr->fileID;
- int vlistID = streamptr->vlistID;
- int taxisID = vlistInqTaxis(vlistID);
-
- void *gribbuffer = streamptr->record->buffer;
- size_t buffersize = streamptr->record->buffersize;
+ fileID = streamptr->fileID;
+ vlistID = streamptr->vlistID;
- int tsID = streamptr->rtsteps;
+ tsID = streamptr->rtsteps;
if ( tsID != 1 )
Error("Internal problem! unexpected timestep %d", tsID+1);
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ taxis = &streamptr->tsteps[tsID].taxis;
fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
cdi_create_records(streamptr, tsID);
- int nrecords = streamptr->tsteps[tsID].nallrecs;
- if ( nrecords ) streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
+ nrecords = streamptr->tsteps[0].nallrecs;
+ streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
streamptr->tsteps[1].nrecs = 0;
for ( recID = 0; recID < nrecords; recID++ )
streamptr->tsteps[1].recIDs[recID] = -1;
@@ -46709,168 +47717,88 @@ int cgribexScanTimestep2(stream_t * streamptr)
for ( recID = 0; recID < nrecords; recID++ )
{
varID = streamptr->tsteps[0].records[recID].varID;
- streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position;
- streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size;
+ streamptr->tsteps[tsID].records[recID].position =
+ streamptr->tsteps[0].records[recID].position;
+ streamptr->tsteps[tsID].records[recID].size =
+ streamptr->tsteps[0].records[recID].size;
}
- int nrecs_scanned = nrecords;
- int rindex = 0;
- while ( TRUE )
+ for ( rindex = 0; rindex <= nrecords; rindex++ )
{
- if ( rindex > nrecords ) break;
-
- recsize = gribGetSize(fileID);
- recpos = fileGetPos(fileID);
- if ( recsize == 0 )
+ recpos = fileGetPos(fileID);
+ status = extRead(fileID, extp);
+ if ( status != 0 )
{
streamptr->ntsteps = 2;
break;
}
- if ( (size_t)recsize > buffersize )
- {
- buffersize = (size_t)recsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
-
- readsize = (size_t)recsize;
- rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
- if ( rstatus ) break;
-
- if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
- {
- unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
- if ( buffersize < (size_t)unzipsize )
- {
- buffersize = (size_t)unzipsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
- }
-
- cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
- (int *) gribbuffer, (int)recsize, &lmv, &iret);
-
- nrecs_scanned++;
+ size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
- param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
- cdiParamToString(param, paramstr, sizeof(paramstr));
+ extInqHeader(extp, header);
- if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
- if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
- level1 = ISEC1_Level1;
- level2 = ISEC1_Level2;
+ vdate = header[0];
+ vtime = 0;
+ rcode = header[1];
+ rlevel = header[2];
+ // rxysize = header[3];
- gribDateTime(isec1, &vdate, &vtime);
+ param = cdiEncodeParam(rcode, 255, 255);
if ( rindex == 0 )
{
- if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
- {
- taxis->type = TAXIS_RELATIVE;
- taxis->rdate = gribRefDate(isec1);
- taxis->rtime = gribRefTime(isec1);
- }
- else
- {
- taxis->type = TAXIS_ABSOLUTE;
- }
- taxis->unit = cgribexGetTimeUnit(isec1);
+ taxis->type = TAXIS_ABSOLUTE;
taxis->vdate = vdate;
taxis->vtime = vtime;
-
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
-
- tsteptype = cgribexGetTsteptype(ISEC1_TimeRange);
-
- if ( ISEC1_AvgNum )
- {
- if ( taxis->numavg && warn_numavg &&
- (taxis->numavg != ISEC1_AvgNum) )
- {
- /*
- Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
- */
- warn_numavg = FALSE;
- }
- else
- {
- taxis->numavg = ISEC1_AvgNum;
- }
}
- datetime.date = vdate;
- datetime.time = vtime;
-
- compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
-
+ compVar.param = param;
+ compVar.level = rlevel;
+ nextstep = FALSE;
for ( recID = 0; recID < nrecords; recID++ )
{
- if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
- }
-
- if ( recID == nrecords )
- {
- gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
- return (CDI_EUFSTRUCT);
- }
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
- if ( cdiInventoryMode == 1 )
- {
- if ( streamptr->tsteps[tsID].records[recID].used )
+ if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
{
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ nextstep = TRUE;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
break;
}
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
}
- else
+ if ( recID == nrecords )
{
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr, level1, level2);
- continue;
- }
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
+ Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
+ return (CDI_EUFSTRUCT);
}
+ if ( nextstep ) break;
+
if ( CDI_Debug )
- Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
+ Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
- streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
{
Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
tsID, recID,
streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, level1);
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
return (CDI_EUFSTRUCT);
}
streamptr->tsteps[1].records[recID].position = recpos;
- varID = streamptr->tsteps[tsID].records[recID].varID;
- gridID = vlistInqVarGrid(vlistID, varID);
- if ( gridInqSize(gridID) == 1 && gridInqType(gridID) == GRID_LONLAT )
- {
- if ( IS_NOT_EQUAL(gridInqXval(gridID, 0),ISEC2_FirstLon*0.001) ||
- IS_NOT_EQUAL(gridInqYval(gridID, 0),ISEC2_FirstLat*0.001) )
- gridChangeType(gridID, GRID_TRAJECTORY);
- }
-
- if ( tsteptype != vlistInqVarTsteptype(vlistID, varID) )
- vlistDefVarTsteptype(vlistID, varID, tsteptype);
-
- rindex++;
}
nrecs = 0;
@@ -46890,39 +47818,52 @@ int cgribexScanTimestep2(stream_t * streamptr)
streamptr->rtsteps = 2;
- cgribexScanTsFixNtsteps(streamptr, recpos);
+ if ( streamptr->ntsteps == -1 )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = buffersize;
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
- return (rstatus);
+ return (0);
}
-#endif
-#if defined (HAVE_LIBCGRIBEX)
-int cgribexScanTimestep(stream_t * streamptr)
+int extInqContents(stream_t *streamptr)
{
- int rstatus = 0;
- double fsec2[512], fsec3[2], *fsec4 = NULL;
- int lmv = 0, iret = 0;
- long recsize = 0;
- off_t recpos = 0;
- void *gribbuffer;
- size_t buffersize = 0;
int fileID;
+ int status = 0;
+
+ fileID = streamptr->fileID;
+
+ streamptr->curTsID = 0;
+
+ extScanTimestep1(streamptr);
+
+ if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamptr);
+
+ fileSetPos(fileID, 0, SEEK_SET);
+
+ return (status);
+}
+
+static
+long extScanTimestep(stream_t *streamptr)
+{
+ int header[4];
+ int status;
+ int fileID;
+ // int rxysize = 0;
int param = 0;
- int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
- DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
- int vrecID, recID;
- int warn_numavg = TRUE;
- size_t readsize;
- int taxisID = -1;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ off_t recpos = 0;
+ int recID;
int rindex, nrecs = 0;
- int nrecs_scanned;
- long unzipsize;
- char paramstr[32];
-
+ extcompvar_t compVar, compVar0;
+ void *extp = streamptr->record->exsep;
/*
if ( CDI_Debug )
{
@@ -46932,20 +47873,12 @@ int cgribexScanTimestep(stream_t * streamptr)
Message("nts = %d", streamptr->ntsteps);
}
*/
- int *isec0 = streamptr->record->sec0;
- int *isec1 = streamptr->record->sec1;
- int *isec2 = streamptr->record->sec2;
- int *isec3 = streamptr->record->sec3;
- int *isec4 = streamptr->record->sec4;
int tsID = streamptr->rtsteps;
taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
if ( streamptr->tsteps[tsID].recordSize == 0 )
{
- gribbuffer = streamptr->record->buffer;
- buffersize = streamptr->record->buffersize;
-
cdi_create_records(streamptr, tsID);
nrecs = streamptr->tsteps[1].nrecs;
@@ -46959,178 +47892,57 @@ int cgribexScanTimestep(stream_t * streamptr)
fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- nrecs_scanned = streamptr->tsteps[0].nallrecs + streamptr->tsteps[1].nrecs*(tsID-1);
- rindex = 0;
- while ( TRUE )
+ for ( rindex = 0; rindex <= nrecs; rindex++ )
{
- if ( rindex > nrecs ) break;
-
- recsize = gribGetSize(fileID);
- recpos = fileGetPos(fileID);
- if ( recsize == 0 )
+ recpos = fileGetPos(fileID);
+ status = extRead(fileID, extp);
+ if ( status != 0 )
{
streamptr->ntsteps = streamptr->rtsteps + 1;
break;
}
- if ( recsize > 0 && (size_t)recsize > buffersize )
- {
- buffersize = (size_t)recsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
-
- if ( rindex >= nrecs ) break;
-
- readsize = (size_t)recsize;
- rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize);
- if ( rstatus )
- {
- Warning("Inconsistent timestep %d (GRIB record %d/%d)!", tsID+1, rindex+1,
- streamptr->tsteps[tsID].recordSize);
- break;
- }
-
- if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 )
- {
- unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
- if ( buffersize < (size_t)unzipsize )
- {
- buffersize = (size_t)unzipsize;
- gribbuffer = Realloc(gribbuffer, buffersize);
- }
- }
-
- cgribexDecodeHeader(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
- (int *) gribbuffer, (int)recsize, &lmv, &iret);
-
- nrecs_scanned++;
+ size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
- param = cdiEncodeParam(ISEC1_Parameter, ISEC1_CodeTable, 255);
- cdiParamToString(param, paramstr, sizeof(paramstr));
+ extInqHeader(extp, header);
- if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
- if ( ISEC1_LevelType == 99 ) ISEC1_LevelType = 100;
- level1 = ISEC1_Level1;
- level2 = ISEC1_Level2;
+ vdate = header[0];
+ vtime = 0;
+ rcode = header[1];
+ rlevel = header[2];
+ // rxysize = header[3];
- gribDateTime(isec1, &vdate, &vtime);
+ param = cdiEncodeParam(rcode, 255, 255);
- if ( rindex == nrecs ) break;
+ // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
+ if ( rindex == nrecs ) continue;
+ recID = streamptr->tsteps[tsID].recIDs[rindex];
if ( rindex == 0 )
{
- int vlistID = streamptr->vlistID;
- taxisID = vlistInqTaxis(vlistID);
- if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
- {
- taxis->type = TAXIS_RELATIVE;
- taxis->rdate = gribRefDate(isec1);
- taxis->rtime = gribRefTime(isec1);
- }
- else
- {
- taxis->type = TAXIS_ABSOLUTE;
- }
- taxis->unit = cgribexGetTimeUnit(isec1);
+ taxis->type = TAXIS_ABSOLUTE;
taxis->vdate = vdate;
taxis->vtime = vtime;
-
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
-
- if ( ISEC1_AvgNum )
- {
- if ( taxis->numavg && warn_numavg &&
- (taxis->numavg != ISEC1_AvgNum) )
- {
- /*
- Warning("Changing numavg from %d to %d not supported!", streamptr->tsteps[tsID].taxis.numavg, ISEC1_AvgNum);
- */
- warn_numavg = FALSE;
- }
- else
- {
- taxis->numavg = ISEC1_AvgNum;
- }
- }
-
- datetime.date = vdate;
- datetime.time = vtime;
-
- compvar_t compVar = cgribexVarSet(param, level1, level2, ISEC1_LevelType, ISEC1_TimeRange);
-
- for ( vrecID = 0; vrecID < nrecs; vrecID++ )
- {
- recID = streamptr->tsteps[1].recIDs[vrecID];
- if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
- }
-
- if ( vrecID == nrecs )
- {
- gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, paramstr, level1, level2);
-
- if ( cdiInventoryMode == 1 )
- return (CDI_EUFSTRUCT);
- else
- continue;
- }
-
- if ( cdiInventoryMode == 1 )
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
- else
- {
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- char paramstr_[32];
- cdiParamToString(param, paramstr_, sizeof(paramstr_));
-
- if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-
- if ( CDI_Debug )
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, paramstr_, level1, level2);
-
- continue;
- }
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
}
- if ( CDI_Debug )
- Message("Read record %2d (id=%s lev1=%d lev2=%d) %8d %6d", nrecs_scanned, paramstr, level1, level2, vdate, vtime);
-
- if ( cgribexVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ compVar.param = param;
+ compVar.level = rlevel;
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
{
Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
tsID, recID,
streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, level1);
- Error("Invalid, unsupported or inconsistent record structure");
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
+ Error("Invalid, unsupported or inconsistent record structure!");
}
streamptr->tsteps[tsID].records[recID].position = recpos;
- streamptr->tsteps[tsID].records[recID].size = (size_t)recsize;
-
- rindex++;
- }
-
- for ( vrecID = 0; vrecID < nrecs; vrecID++ )
- {
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- if ( ! streamptr->tsteps[tsID].records[recID].used ) break;
- }
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- if ( vrecID < nrecs )
- {
- cdiParamToString(streamptr->tsteps[tsID].records[recID].param, paramstr, sizeof(paramstr));
- gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, paramstr,
- streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
- return (CDI_EUFSTRUCT);
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
}
streamptr->rtsteps++;
@@ -47147,9 +47959,6 @@ int cgribexScanTimestep(stream_t * streamptr)
fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
streamptr->tsteps[tsID].position = recpos;
-
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = buffersize;
}
if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
@@ -47158,933 +47967,635 @@ int cgribexScanTimestep(stream_t * streamptr)
streamptr->ntsteps = tsID;
}
- rstatus = (int)streamptr->ntsteps;
-
- return (rstatus);
+ return (streamptr->ntsteps);
}
-#endif
-#ifdef gribWarning
-#undef gribWarning
-#endif
-#if defined (HAVE_LIBCGRIBEX)
-int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval)
+int extInqTimestep(stream_t *streamptr, int tsID)
{
- int status = 0;
- int iret = 0, iword = 0;
- int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
- double fsec2[512], fsec3[2];
- char hoper[2];
-
- if ( unreduced ) strcpy(hoper, "R");
- else strcpy(hoper, "D");
-
- FSEC3_MissVal = missval;
-
- gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, data,
- gridsize, (int *)(void *)gribbuffer, gribsize, &iword, hoper, &iret);
-
- if ( ISEC1_Sec2Or3Flag & 64 )
- *nmiss = ISEC4_NumValues - ISEC4_NumNonMissValues;
- else
- *nmiss = 0;
-
- if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
- {
- double undef_pds, undef_eps;
- int i;
-
- MCH_get_undef(isec1, &undef_pds, &undef_eps);
-
- *nmiss = 0;
- for ( i = 0; i < gridsize; i++ )
- if ( (fabs(data[i]-undef_pds) < undef_eps) || IS_EQUAL(data[i],FSEC3_MissVal) ) {
- data[i] = missval;
- (*nmiss)++;
- }
- }
-
- return (status);
-}
-#endif
+ int nrecs;
+ long ntsteps;
+ if ( tsID == 0 && streamptr->rtsteps == 0 )
+ Error("Call to cdiInqContents missing!");
-#if defined (HAVE_LIBCGRIBEX)
-static
-void cgribexDefInstitut(int *isec1, int vlistID, int varID)
-{
- int instID;
+ if ( CDI_Debug )
+ Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
- if ( vlistInqInstitut(vlistID) != CDI_UNDEFID )
- instID = vlistInqInstitut(vlistID);
- else
- instID = vlistInqVarInstitut(vlistID, varID);
+ ntsteps = UNDEFID;
+ while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
+ ntsteps = extScanTimestep(streamptr);
- if ( instID != CDI_UNDEFID )
+ if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
{
- int center, subcenter;
- center = institutInqCenter(instID);
- subcenter = institutInqSubcenter(instID);
- ISEC1_CenterID = center;
- ISEC1_SubCenterID = subcenter;
+ nrecs = 0;
}
-}
-
-static
-void cgribexDefModel(int *isec1, int vlistID, int varID)
-{
- int modelID;
-
- if ( vlistInqModel(vlistID) != CDI_UNDEFID )
- modelID = vlistInqModel(vlistID);
else
- modelID = vlistInqVarModel(vlistID, varID);
-
- if ( modelID != CDI_UNDEFID )
- ISEC1_ModelID = modelInqGribID(modelID);
-}
-
-static
-void cgribexDefParam(int *isec1, int param)
-{
- int pdis, pcat, pnum;
-
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
- if ( pnum < 0 ) pnum = -pnum;
-
- static bool lwarn_pdis = true;
- if ( pdis != 255 && lwarn_pdis )
{
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Warning("Can't convert GRIB2 parameter ID (%s) to GRIB1, set to %d.%d!", paramstr, pnum, pcat);
- lwarn_pdis = false;
- }
-
- static bool lwarn_pnum = true;
- if ( pnum > 255 && lwarn_pnum )
- {
- Warning("Parameter number %d out of range (1-255), set to %d!", pnum, pnum%256);
- lwarn_pnum = false;
- pnum = pnum%256;
+ streamptr->curTsID = tsID;
+ nrecs = streamptr->tsteps[tsID].nrecs;
}
- ISEC1_CodeTable = pcat;
- ISEC1_Parameter = pnum;
+ return (nrecs);
}
-static
-int cgribexDefTimerange(int tsteptype, int factor, int calendar,
- int rdate, int rtime, int vdate, int vtime, int *pip1, int *pip2)
-{
- int timerange = -1;
- int year, month, day, hour, minute, second;
- int julday1, secofday1, julday2, secofday2, days, secs;
- int ip, ip1 = 0, ip2 = 0;
-
- cdiDecodeDate(rdate, &year, &month, &day);
- cdiDecodeTime(rtime, &hour, &minute, &second);
- encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday1, &secofday1);
-
- cdiDecodeDate(vdate, &year, &month, &day);
- cdiDecodeTime(vtime, &hour, &minute, &second);
- encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
-
- (void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
-
- if ( !(int)(fmod(days*86400.0 + secs, factor)) )
- {
- ip = (int) ((days*86400.0 + secs)/factor);
-
- switch ( tsteptype )
- {
- case TSTEP_INSTANT: timerange = 0; ip1 = ip; ip2 = 0; break;
- case TSTEP_INSTANT2: timerange = 1; ip1 = 0; ip2 = 0; break;
- case TSTEP_RANGE: timerange = 2; ip1 = 0; ip2 = ip; break;
- case TSTEP_AVG: timerange = 3; ip1 = 0; ip2 = ip; break;
- case TSTEP_ACCUM: timerange = 4; ip1 = 0; ip2 = ip; break;
- case TSTEP_DIFF: timerange = 5; ip1 = 0; ip2 = ip; break;
- case TSTEP_INSTANT3:
- default: timerange = 10; ip1 = ip/256; ip2 = ip%256; break;
- }
- }
-
- *pip1 = ip1;
- *pip2 = ip2;
-
- return (timerange);
-}
-static
-int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
+void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
{
- int year, month, day, hour, minute, second;
- int century = 0;
- int factor = 1;
+ int vlistID, fileID;
+ int levID, nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int header[4];
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *extp = streamptr->record->exsep;
- cdiDecodeDate(date, &year, &month, &day);
- cdiDecodeTime(time, &hour, &minute, &second);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
- century = year / 100;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- ISEC1_Year = year - century*100;
+ currentfilepos = fileGetPos(fileID);
- if ( year < 0 )
+ for (levID = 0; levID < nlevs; levID++)
{
- century = -century;
- ISEC1_Year = -ISEC1_Year;
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ extRead(fileID, extp);
+ extInqHeader(extp, header);
+ extInqDataDP(extp, &data[levID*gridsize]);
}
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
- if ( ISEC1_Year == 0 )
+ *nmiss = 0;
+ if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
{
- century -= 1;
- ISEC1_Year = 100;
+ for ( i = 0; i < nlevs*gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
}
-
- century += 1;
- if ( year < 0 ) century = -century;
-
- ISEC1_Month = month;
- ISEC1_Day = day;
- ISEC1_Hour = hour;
- ISEC1_Minute = minute;
-
- ISEC1_Century = century;
-
- switch (timeunit)
+ else
{
- case TUNIT_MINUTE: factor = 60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE; break;
- case TUNIT_QUARTER: factor = 900; ISEC1_TimeUnit = ISEC1_TABLE4_QUARTER; break;
- case TUNIT_30MINUTES: factor = 1800; ISEC1_TimeUnit = ISEC1_TABLE4_30MINUTES; break;
- case TUNIT_HOUR: factor = 3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR; break;
- case TUNIT_3HOURS: factor = 10800; ISEC1_TimeUnit = ISEC1_TABLE4_3HOURS; break;
- case TUNIT_6HOURS: factor = 21600; ISEC1_TimeUnit = ISEC1_TABLE4_6HOURS; break;
- case TUNIT_12HOURS: factor = 43200; ISEC1_TimeUnit = ISEC1_TABLE4_12HOURS; break;
- case TUNIT_DAY: factor = 86400; ISEC1_TimeUnit = ISEC1_TABLE4_DAY; break;
- default: factor = 3600; ISEC1_TimeUnit = ISEC1_TABLE4_HOUR; break;
+ for ( i = 0; i < 2*nlevs*gridsize; i+=2 )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
}
-
- return (factor);
}
-static
-void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg, int taxisID)
-{
- int timetype = TAXIS_ABSOLUTE;
- int timerange = 0;
- int timeunit = TUNIT_HOUR;
-
- if ( taxisID != -1 )
- {
- timetype = taxisInqType(taxisID);
- timeunit = taxisInqTunit(taxisID);
- }
-
- if ( timetype == TAXIS_RELATIVE )
- {
- int factor = 1;
- int rdate, rtime;
- int ip1 = 0, ip2 = 0;
- int calendar;
-
- calendar = taxisInqCalendar(taxisID);
- rdate = taxisInqRdate(taxisID);
- rtime = taxisInqRtime(taxisID);
-
- factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
-
- timerange = cgribexDefTimerange(tsteptype, factor, calendar,
- rdate, rtime, vdate, vtime, &ip1, &ip2);
-
- if ( timerange == -1 || timerange == 3 )
- {
- timetype = TAXIS_ABSOLUTE;
- }
- /*
- else if ( timerange == 10 )
- {
- if ( ip1 < 0 || ip1 > 0xFFFF ) timetype = TAXIS_ABSOLUTE;
- if ( ip2 < 0 || ip2 > 0xFFFF ) timetype = TAXIS_ABSOLUTE;
- }
- */
- else
- {
- if ( ip1 < 0 || ip1 > 0xFF ) timetype = TAXIS_ABSOLUTE;
- if ( ip2 < 0 || ip2 > 0xFF ) timetype = TAXIS_ABSOLUTE;
- }
-
- ISEC1_TimeRange = timerange;
- ISEC1_TimePeriod1 = ip1;
- ISEC1_TimePeriod2 = ip2;
- }
-
- if ( timetype == TAXIS_ABSOLUTE )
- {
- (void) cgribexDefDateTime(isec1, timeunit, vdate, vtime);
-
- /*
- if ( numavg > 0 )
- ISEC1_TimeRange = 0;
- else
- */
- if ( ISEC1_TimeRange != 3 )
- ISEC1_TimeRange = 10;
-
- ISEC1_TimePeriod1 = 0;
- ISEC1_TimePeriod2 = 0;
- }
-
- ISEC1_AvgNum = numavg;
- ISEC1_AvgMiss = 0;
- ISEC1_DecScaleFactor = 0;
-}
-static
-void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID)
+void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
{
- int gridtype;
- bool lcurvi = false;
- static bool lwarning = true;
-
- memset(isec2, 0, 16*sizeof(int));
-
- ISEC1_Sec2Or3Flag = 128;
-
- gridtype = gridInqType(gridID);
+ int vlistID, fileID;
+ int nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int header[4];
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *extp = streamptr->record->exsep;
- ISEC1_GridDefinition = 255;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
- if ( gridtype == GRID_GENERIC )
- {
- int xsize, ysize, gridsize;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d",
+ nlevs, gridID, gridsize);
- gridsize = gridInqSize(gridID);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ currentfilepos = fileGetPos(fileID);
- if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
- ysize == 96 || ysize == 160 || ysize == 192 ||
- ysize == 240 || ysize == 320 || ysize == 384 ||
- ysize == 480 || ysize == 768 ) &&
- (xsize == 2*ysize || xsize == 1) )
- {
- gridtype = GRID_GAUSSIAN;
- gridChangeType(gridID, gridtype);
- }
- else if ( gridsize == 1 )
- {
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
- }
- else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
- {
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
- }
- }
- else if ( gridtype == GRID_CURVILINEAR )
- {
- if ( lwarning && gridInqSize(gridID) > 1 )
- {
- lwarning = false;
- Warning("Curvilinear grids are unsupported in GRIB1! Created wrong GDS!");
- }
- gridtype = GRID_LONLAT;
- lcurvi = true;
- }
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ extRead(fileID, extp);
+ extInqHeader(extp, header);
+ extInqDataDP(extp, data);
- ISEC2_Reduced = FALSE;
- ISEC2_ScanFlag = 0;
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
- switch (gridtype)
+ *nmiss = 0;
+ if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
{
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- case GRID_GAUSSIAN_REDUCED:
- case GRID_TRAJECTORY:
- {
- int nlon = 0, nlat;
- double xfirst = 0, xlast = 0, xinc = 0;
- double yfirst = 0, ylast = 0, yinc = 0;
-
- if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
- ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN;
- else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
- ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT;
- else
- ISEC2_GridType = GRIB1_GTYPE_LATLON;
-
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
-
- if ( gridtype == GRID_GAUSSIAN_REDUCED )
- {
- ISEC2_Reduced = TRUE;
- nlon = 0;
- gridInqRowlon(gridID, ISEC2_RowLonPtr);
- }
- else
- {
- if ( nlon == 0 )
- {
- nlon = 1;
- }
- else
- {
- xfirst = gridInqXval(gridID, 0);
- if ( lcurvi )
- xlast = gridInqXval(gridID, nlon*nlat-1);
- else
- xlast = gridInqXval(gridID, nlon-1);
- xinc = gridInqXinc(gridID);
- }
- }
-
- if ( nlat == 0 )
- {
- nlat = 1;
- }
- else
- {
- yfirst = gridInqYval(gridID, 0);
- if ( lcurvi )
- ylast = gridInqYval(gridID, nlon*nlat-1);
- else
- ylast = gridInqYval(gridID, nlat-1);
- yinc = gridInqYinc(gridID);
- if ( yinc < 0 ) yinc = -yinc;
- }
-
- ISEC2_NumLon = nlon;
- ISEC2_NumLat = nlat;
- ISEC2_FirstLat = (int)lround(yfirst*1000);
- ISEC2_LastLat = (int)lround(ylast*1000);
- if ( gridtype == GRID_GAUSSIAN_REDUCED )
- {
- ISEC2_FirstLon = 0;
- ISEC2_LastLon = (int)lround(1000*(360.-360./(nlat*2)));
- ISEC2_LonIncr = (int)lround(1000*360./(nlat*2));
- }
- else
+ for ( i = 0; i < gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
{
- ISEC2_FirstLon = (int)lround(xfirst*1000);
- ISEC2_LastLon = (int)lround(xlast*1000);
- ISEC2_LonIncr = (int)lround(xinc*1000);
+ data[i] = missval;
+ (*nmiss)++;
}
-
- // if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON ) ISEC2_LonIncr = 0;
-
- if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
- {
- int np = gridInqNP(gridID);
- if ( np == 0 ) np = nlat/2;
- ISEC2_NumPar = np;
- }
- else
+ }
+ else
+ {
+ for ( i = 0; i < 2*gridsize; i+=2 )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
{
- ISEC2_LatIncr = (int)lround(yinc*1000);
- // if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON ) ISEC2_LatIncr = 0;
-
- if ( ISEC2_LatIncr < 0 ) ISEC2_LatIncr = -ISEC2_LatIncr;
+ data[i] = missval;
+ (*nmiss)++;
}
+ }
+}
- if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
- if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr;
-
- if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
- if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
- if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
- ISEC2_ResFlag = 0;
- else
- ISEC2_ResFlag = 128;
+void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
+{
+ int fileID;
+ int levID, nlevs, gridID, gridsize;
+ int zaxisID;
+ double level;
+ int header[4];
+ int tsID;
+ int vlistID;
+ int pdis, pcat, pnum;
+ extrec_t *extp = (extrec_t*) streamptr->record->exsep;
- if ( gridIsRotated(gridID) )
- {
- ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000);
- ISEC2_LonSP = (int)lround((gridInqXpole(gridID) + 180) * 1000);
- double angle = gridInqAngle(gridID);
- if ( fabs(angle) > 0 ) angle = -angle;
- FSEC2_RotAngle = angle;
- }
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
- /* East -> West */
- if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ nlevs = zaxisInqSize(zaxisID);
- /* South -> North */
- if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- break;
- }
- case GRID_LCC:
- {
- double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
- int xsize, ysize;
- int projflag, scanflag;
+ cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ header[0] = streamptr->tsteps[tsID].taxis.vdate;
+ header[1] = pnum;
+ header[3] = gridInqSize(gridID);
- gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
- &projflag, &scanflag);
+ extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
- ISEC2_GridType = GRIB1_GTYPE_LCC;
- ISEC2_NumLon = xsize;
- ISEC2_NumLat = ysize;
- ISEC2_FirstLon = (int)lround(originLon * 1000);
- ISEC2_FirstLat = (int)lround(originLat * 1000);
- ISEC2_Lambert_Lov = (int)lround(lonParY * 1000);
- ISEC2_Lambert_LatS1 = (int)lround(lat1 * 1000);
- ISEC2_Lambert_LatS2 = (int)lround(lat2 * 1000);
- ISEC2_Lambert_dx = (int)lround(xincm);
- ISEC2_Lambert_dy = (int)lround(yincm);
- ISEC2_Lambert_LatSP = 0;
- ISEC2_Lambert_LatSP = 0;
- ISEC2_Lambert_ProjFlag = projflag;
- ISEC2_ScanFlag = scanflag;
+ for ( levID = 0; levID < nlevs; levID++ )
+ {
+ level = zaxisInqLevel(zaxisID, levID);
- break;
- }
- case GRID_SPECTRAL:
- {
- ISEC2_GridType = GRIB1_GTYPE_SPECTRAL;
- ISEC2_PentaJ = gridInqTrunc(gridID);
- ISEC2_PentaK = ISEC2_PentaJ;
- ISEC2_PentaM = ISEC2_PentaJ;
- ISEC2_RepType = 1;
- isec4[2] = 128;
- if ( gridInqComplexPacking(gridID) && ISEC2_PentaJ >= 21 )
- {
- ISEC2_RepMode = 2;
- isec4[3] = 64;
- isec4[16] = 0;
- isec4[17] = 20;
- isec4[18] = 20;
- isec4[19] = 20;
- }
- else
- {
- ISEC2_RepMode = 1;
- isec4[3] = 0;
- }
- break;
- }
- case GRID_GME:
- {
- ISEC2_GridType = GRIB1_GTYPE_GME;
- ISEC2_GME_ND = gridInqGMEnd(gridID);
- ISEC2_GME_NI = gridInqGMEni(gridID);
- ISEC2_GME_NI2 = gridInqGMEni2(gridID);
- ISEC2_GME_NI3 = gridInqGMEni3(gridID);
- ISEC2_GME_AFlag = 0;
- ISEC2_GME_LatPP = 90000;
- ISEC2_GME_LonPP = 0;
- ISEC2_GME_LonMPL = 0;
- ISEC2_GME_BFlag = 0;
- break;
- }
- default:
- {
- Warning("The CGRIBEX library can not store fields on the used grid!");
- Error("Unsupported grid type: %s", gridNamePtr(gridtype));
- break;
- }
+ header[2] = (int) level;
+ extDefHeader(extp, header);
+ extDefDataDP(extp, &data[levID*gridsize]);
+ extWrite(fileID, extp);
}
}
-static
-void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int levelID)
+
+void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
{
+ int fileID;
+ int gridID;
+ int zaxisID;
double level;
- int ilevel, zaxistype, ltype;
- static bool lwarning = true;
- static bool lwarning_vct = true;
+ int header[4];
+ int tsID;
+ int vlistID;
+ int pdis, pcat, pnum;
+ extrec_t *extp = (extrec_t*) streamptr->record->exsep;
- zaxistype = zaxisInqType(zaxisID);
- ltype = zaxisInqLtype(zaxisID);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ level = zaxisInqLevel(zaxisID, levID);
- if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
- {
- Message("Changed zaxis type from %s to %s",
- zaxisNamePtr(zaxistype),
- zaxisNamePtr(ZAXIS_PRESSURE));
- zaxistype = ZAXIS_PRESSURE;
- zaxisChangeType(zaxisID, zaxistype);
- zaxisDefUnits(zaxisID, "Pa");
- }
+ if ( CDI_Debug )
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
- ISEC2_NumVCP = 0;
+ cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
- switch (zaxistype)
- {
- case ZAXIS_SURFACE:
- {
- ISEC1_LevelType = GRIB1_LTYPE_SURFACE;
- ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_CLOUD_BASE:
- {
- ISEC1_LevelType = GRIB1_LTYPE_CLOUD_BASE;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_CLOUD_TOP:
- {
- ISEC1_LevelType = GRIB1_LTYPE_CLOUD_TOP;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_ISOTHERM_ZERO:
- {
- ISEC1_LevelType = GRIB1_LTYPE_ISOTHERM0;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_TOA:
- {
- ISEC1_LevelType = GRIB1_LTYPE_TOA;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_SEA_BOTTOM:
- {
- ISEC1_LevelType = GRIB1_LTYPE_SEA_BOTTOM;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_ATMOSPHERE:
- {
- ISEC1_LevelType = GRIB1_LTYPE_ATMOSPHERE;
- ISEC1_Level1 = 0;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_MEANSEA:
- {
- ISEC1_LevelType = GRIB1_LTYPE_MEANSEA;
- ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_HYBRID:
- case ZAXIS_HYBRID_HALF:
- {
- int vctsize;
+ header[0] = streamptr->tsteps[tsID].taxis.vdate;
+ header[1] = pnum;
+ header[2] = (int) level;
+ header[3] = gridInqSize(gridID);
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- ISEC1_LevelType = GRIB1_LTYPE_HYBRID_LAYER;
- ISEC1_Level1 = (int)(zaxisInqLbound(zaxisID, levelID));
- ISEC1_Level2 = (int)(zaxisInqUbound(zaxisID, levelID));
- }
- else
- {
- ISEC1_LevelType = GRIB1_LTYPE_HYBRID;
- ISEC1_Level1 = (int)(zaxisInqLevel(zaxisID, levelID));
- ISEC1_Level2 = 0;
- }
+ extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
- vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && lwarning )
- {
- Warning("VCT missing. ( param = %d, zaxisID = %d )", ISEC1_Parameter, zaxisID);
- lwarning = false;
- }
- if ( vctsize > 255 )
- {
- ISEC2_NumVCP = 0;
- if ( lwarning_vct )
- {
- Warning("VCT size of %d is too large (maximum is 255). Set to 0!", vctsize);
- lwarning_vct = false;
- }
- }
- else
- {
- ISEC2_NumVCP = vctsize;
- zaxisInqVct(zaxisID, &fsec2[10]);
- }
- break;
- }
- case ZAXIS_PRESSURE:
- {
- double dum;
- char units[128];
+ extDefHeader(extp, header);
+ extDefDataDP(extp, data);
+ extWrite(fileID, extp);
+}
- level = zaxisInqLevel(zaxisID, levelID);
- if ( level < 0 )
- Warning("Pressure level of %f Pa is below zero!", level);
+#endif /* HAVE_LIBEXTRA */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#include <stdlib.h>
- zaxisInqUnits(zaxisID, units);
- if ( (units[0] != 'P') | (units[1] != 'a') ) level *= 100;
- ilevel = (int) level;
- if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
- {
- ISEC1_LevelType = GRIB1_LTYPE_99;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
- }
- else
- {
- ISEC1_LevelType = GRIB1_LTYPE_ISOBARIC;
- ISEC1_Level1 = ilevel/100;
- ISEC1_Level2 = 0;
- }
- break;
- }
- case ZAXIS_HEIGHT:
- {
- level = zaxisInqLevel(zaxisID, levelID);
- ilevel = (int) level;
- ISEC1_LevelType = GRIB1_LTYPE_HEIGHT;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
+void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name)
+{
+ int fileID1 = streamptr1->fileID;
+ int fileID2 = streamptr2->fileID;
- break;
- }
- case ZAXIS_ALTITUDE:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+ int tsID = streamptr1->curTsID;
+ int vrecID = streamptr1->tsteps[tsID].curRecID;
+ int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
- ilevel = (int) level;
- ISEC1_LevelType = GRIB1_LTYPE_ALTITUDE;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
+ if (fileSetPos(fileID1, recpos, SEEK_SET) != 0)
+ Error("Cannot seek input file for %s record copy!", container_name);
- break;
- }
- case ZAXIS_SIGMA:
- {
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- ISEC1_LevelType = GRIB1_LTYPE_SIGMA_LAYER;
- ISEC1_Level1 = (int)(zaxisInqLbound(zaxisID, levelID));
- ISEC1_Level2 = (int)(zaxisInqUbound(zaxisID, levelID));
- }
- else
- {
- level = zaxisInqLevel(zaxisID, levelID);
+ char *buffer = (char *) Malloc(recsize);
- ilevel = (int) level;
- ISEC1_LevelType = GRIB1_LTYPE_SIGMA;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
- }
+ if (fileRead(fileID1, buffer, recsize) != recsize)
+ Error("Failed to read record from %s file for copying!", container_name);
- break;
- }
- case ZAXIS_DEPTH_BELOW_LAND:
- {
- char units[128];
- double factor;
+ if (fileWrite(fileID2, buffer, recsize) != recsize)
+ Error("Failed to write record to %s file when copying!", container_name);
- zaxisInqUnits(zaxisID, units);
+ Free(buffer);
+}
- if ( units[0] == 'm' && units[1] == 'm' ) factor = 0.1;
- else if ( units[0] == 'c' && units[1] == 'm' ) factor = 1;
- else if ( units[0] == 'd' && units[1] == 'm' ) factor = 10;
- else factor = 100; // meter
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#ifndef _STREAM_GRIBAPI_H
+#define _STREAM_GRIBAPI_H
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- double level1, level2;
- level1 = zaxisInqLbound(zaxisID, levelID);
- level2 = zaxisInqUbound(zaxisID, levelID);
- ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH_LAYER;
- ISEC1_Level1 = (int) (level1*factor);
- ISEC1_Level2 = (int) (level2*factor);
- }
- else
- {
- level = zaxisInqLevel(zaxisID, levelID);
+int gribapiScanTimestep1(stream_t * streamptr);
+int gribapiScanTimestep2(stream_t * streamptr);
+int gribapiScanTimestep(stream_t * streamptr);
- ilevel = (int) (level*factor);
- ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
- }
+int gribapiDecode(void *gribbuffer, int gribsize, double *data, long datasize,
+ int unreduced, int *nmiss, double missval, int vlistID, int varID);
- break;
- }
- case ZAXIS_DEPTH_BELOW_SEA:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const double *data, int nmiss, void **gribbuffer, size_t *gribbuffersize,
+ int ljpeg, void *gribContainer);
- ilevel = (int) level;
- ISEC1_LevelType = GRIB1_LTYPE_SEADEPTH;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
+#endif /* _STREAM_GRIBAPI_H */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#ifdef HAVE_CONFIG_H
+#endif
- break;
- }
- case ZAXIS_ISENTROPIC:
- {
- level = zaxisInqLevel(zaxisID, levelID);
- ilevel = (int) level;
- ISEC1_LevelType = GRIB1_LTYPE_ISENTROPIC;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
- break;
- }
- case ZAXIS_GENERIC:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+int grib1ltypeToZaxisType(int grib_ltype)
+{
+ int zaxistype = ZAXIS_GENERIC;
- ilevel = (int) level;
- ISEC1_LevelType = ltype;
- ISEC1_Level1 = ilevel;
- ISEC1_Level2 = 0;
+ switch ( grib_ltype )
+ {
+ case GRIB1_LTYPE_SURFACE: zaxistype = ZAXIS_SURFACE; break;
+ case GRIB1_LTYPE_CLOUD_BASE: zaxistype = ZAXIS_CLOUD_BASE; break;
+ case GRIB1_LTYPE_CLOUD_TOP: zaxistype = ZAXIS_CLOUD_TOP; break;
+ case GRIB1_LTYPE_ISOTHERM0: zaxistype = ZAXIS_ISOTHERM_ZERO; break;
+ case GRIB1_LTYPE_TOA: zaxistype = ZAXIS_TOA; break;
+ case GRIB1_LTYPE_SEA_BOTTOM: zaxistype = ZAXIS_SEA_BOTTOM; break;
+ case GRIB1_LTYPE_ATMOSPHERE: zaxistype = ZAXIS_ATMOSPHERE; break;
+ case GRIB1_LTYPE_MEANSEA: zaxistype = ZAXIS_MEANSEA; break;
+ case GRIB1_LTYPE_99:
+ case GRIB1_LTYPE_ISOBARIC: zaxistype = ZAXIS_PRESSURE; break;
+ case GRIB1_LTYPE_HEIGHT: zaxistype = ZAXIS_HEIGHT; break;
+ case GRIB1_LTYPE_ALTITUDE: zaxistype = ZAXIS_ALTITUDE; break;
+ case GRIB1_LTYPE_SIGMA:
+ case GRIB1_LTYPE_SIGMA_LAYER: zaxistype = ZAXIS_SIGMA; break;
+ case GRIB1_LTYPE_HYBRID:
+ case GRIB1_LTYPE_HYBRID_LAYER: zaxistype = ZAXIS_HYBRID; break;
+ case GRIB1_LTYPE_LANDDEPTH:
+ case GRIB1_LTYPE_LANDDEPTH_LAYER: zaxistype = ZAXIS_DEPTH_BELOW_LAND; break;
+ case GRIB1_LTYPE_ISENTROPIC: zaxistype = ZAXIS_ISENTROPIC; break;
+ case GRIB1_LTYPE_SEADEPTH: zaxistype = ZAXIS_DEPTH_BELOW_SEA; break;
+ case GRIB1_LTYPE_LAKE_BOTTOM: zaxistype = ZAXIS_LAKE_BOTTOM; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM: zaxistype = ZAXIS_SEDIMENT_BOTTOM; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM_TA: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM_TW: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break;
+ case GRIB1_LTYPE_MIX_LAYER: zaxistype = ZAXIS_MIX_LAYER; break;
+ }
- break;
- }
- default:
- {
- Error("Unsupported zaxis type: %s", zaxisNamePtr(zaxistype));
- break;
- }
+ return zaxistype;
+}
+
+
+int grib2ltypeToZaxisType(int grib_ltype)
+{
+ int zaxistype = ZAXIS_GENERIC;
+
+ switch ( grib_ltype )
+ {
+ case GRIB2_LTYPE_SURFACE: zaxistype = ZAXIS_SURFACE; break;
+ case GRIB2_LTYPE_CLOUD_BASE: zaxistype = ZAXIS_CLOUD_BASE; break;
+ case GRIB2_LTYPE_CLOUD_TOP: zaxistype = ZAXIS_CLOUD_TOP; break;
+ case GRIB2_LTYPE_ISOTHERM0: zaxistype = ZAXIS_ISOTHERM_ZERO; break;
+ case GRIB2_LTYPE_TOA: zaxistype = ZAXIS_TOA; break;
+ case GRIB2_LTYPE_SEA_BOTTOM: zaxistype = ZAXIS_SEA_BOTTOM; break;
+ case GRIB2_LTYPE_ATMOSPHERE: zaxistype = ZAXIS_ATMOSPHERE; break;
+ case GRIB2_LTYPE_MEANSEA: zaxistype = ZAXIS_MEANSEA; break;
+ case GRIB2_LTYPE_ISOBARIC: zaxistype = ZAXIS_PRESSURE; break;
+ case GRIB2_LTYPE_HEIGHT: zaxistype = ZAXIS_HEIGHT; break;
+ case GRIB2_LTYPE_ALTITUDE: zaxistype = ZAXIS_ALTITUDE; break;
+ case GRIB2_LTYPE_SIGMA: zaxistype = ZAXIS_SIGMA; break;
+ case GRIB2_LTYPE_HYBRID:
+ /* case GRIB2_LTYPE_HYBRID_LAYER: */ zaxistype = ZAXIS_HYBRID; break;
+ case GRIB2_LTYPE_LANDDEPTH:
+ /* case GRIB2_LTYPE_LANDDEPTH_LAYER: */ zaxistype = ZAXIS_DEPTH_BELOW_LAND; break;
+ case GRIB2_LTYPE_ISENTROPIC: zaxistype = ZAXIS_ISENTROPIC; break;
+ case GRIB2_LTYPE_SNOW: zaxistype = ZAXIS_SNOW; break;
+ case GRIB2_LTYPE_SEADEPTH: zaxistype = ZAXIS_DEPTH_BELOW_SEA; break;
+ case GRIB2_LTYPE_LAKE_BOTTOM: zaxistype = ZAXIS_LAKE_BOTTOM; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM: zaxistype = ZAXIS_SEDIMENT_BOTTOM; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM_TA: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM_TW: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break;
+ case GRIB2_LTYPE_MIX_LAYER: zaxistype = ZAXIS_MIX_LAYER; break;
+ case GRIB2_LTYPE_REFERENCE: zaxistype = ZAXIS_REFERENCE; break;
+ }
+
+ return zaxistype;
+}
+
+
+int zaxisTypeToGrib1ltype(int zaxistype)
+{
+ int grib_ltype = -1;
+
+ switch (zaxistype)
+ {
+ case ZAXIS_SURFACE: grib_ltype = GRIB1_LTYPE_SURFACE; break;
+ case ZAXIS_MEANSEA: grib_ltype = GRIB1_LTYPE_MEANSEA; break;
+ case ZAXIS_HEIGHT: grib_ltype = GRIB1_LTYPE_HEIGHT; break;
+ case ZAXIS_ALTITUDE: grib_ltype = GRIB1_LTYPE_ALTITUDE; break;
+ case ZAXIS_SIGMA: grib_ltype = GRIB1_LTYPE_SIGMA; break;
+ case ZAXIS_DEPTH_BELOW_SEA: grib_ltype = GRIB1_LTYPE_SEADEPTH; break;
+ case ZAXIS_ISENTROPIC: grib_ltype = GRIB1_LTYPE_ISENTROPIC; break;
+ case ZAXIS_CLOUD_BASE: grib_ltype = GRIB1_LTYPE_CLOUD_BASE; break;
+ case ZAXIS_CLOUD_TOP: grib_ltype = GRIB1_LTYPE_CLOUD_TOP; break;
+ case ZAXIS_ISOTHERM_ZERO: grib_ltype = GRIB1_LTYPE_ISOTHERM0; break;
+ case ZAXIS_TOA: grib_ltype = GRIB1_LTYPE_TOA; break;
+ case ZAXIS_SEA_BOTTOM: grib_ltype = GRIB1_LTYPE_SEA_BOTTOM; break;
+ case ZAXIS_LAKE_BOTTOM: grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TA: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TW: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break;
+ case ZAXIS_MIX_LAYER: grib_ltype = GRIB1_LTYPE_MIX_LAYER; break;
+ case ZAXIS_ATMOSPHERE: grib_ltype = GRIB1_LTYPE_ATMOSPHERE; break;
+ }
+
+ return grib_ltype;
+}
+
+
+int zaxisTypeToGrib2ltype(int zaxistype)
+{
+ int grib_ltype = -1;
+
+ switch (zaxistype)
+ {
+ case ZAXIS_SURFACE: grib_ltype = GRIB2_LTYPE_SURFACE; break;
+ case ZAXIS_MEANSEA: grib_ltype = GRIB2_LTYPE_MEANSEA; break;
+ case ZAXIS_HEIGHT: grib_ltype = GRIB2_LTYPE_HEIGHT; break;
+ case ZAXIS_ALTITUDE: grib_ltype = GRIB2_LTYPE_ALTITUDE; break;
+ case ZAXIS_SIGMA: grib_ltype = GRIB2_LTYPE_SIGMA; break;
+ case ZAXIS_DEPTH_BELOW_SEA: grib_ltype = GRIB2_LTYPE_SEADEPTH; break;
+ case ZAXIS_ISENTROPIC: grib_ltype = GRIB2_LTYPE_ISENTROPIC; break;
+ case ZAXIS_CLOUD_BASE: grib_ltype = GRIB2_LTYPE_CLOUD_BASE; break;
+ case ZAXIS_CLOUD_TOP: grib_ltype = GRIB2_LTYPE_CLOUD_TOP; break;
+ case ZAXIS_ISOTHERM_ZERO: grib_ltype = GRIB2_LTYPE_ISOTHERM0; break;
+ case ZAXIS_TOA: grib_ltype = GRIB2_LTYPE_TOA; break;
+ case ZAXIS_SEA_BOTTOM: grib_ltype = GRIB2_LTYPE_SEA_BOTTOM; break;
+ case ZAXIS_LAKE_BOTTOM: grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TA: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TW: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break;
+ case ZAXIS_MIX_LAYER: grib_ltype = GRIB2_LTYPE_MIX_LAYER; break;
+ case ZAXIS_ATMOSPHERE: grib_ltype = GRIB2_LTYPE_ATMOSPHERE; break;
+ }
+
+ return grib_ltype;
+}
+
+
+int grbBitsPerValue(int datatype)
+{
+ int bitsPerValue = 16;
+
+ if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
+ Error("CDI/GRIB library does not support complex numbers!");
+
+ if ( datatype != CDI_UNDEFID )
+ {
+ if ( datatype > 0 && datatype <= 32 )
+ bitsPerValue = datatype;
+ else if ( datatype == DATATYPE_FLT64 )
+ bitsPerValue = 24;
+ else
+ bitsPerValue = 16;
}
+
+ return bitsPerValue;
+}
+
+
+/*
+int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
+{
+ int status;
+
+ status = cgribexInqRecord(streamptr, varID, levelID);
+
+ return (status);
}
+*/
-static
-void cgribexDefaultSec0(int *isec0)
+void grbDefRecord(stream_t * streamptr)
{
- ISEC0_GRIB_Len = 0;
- ISEC0_GRIB_Version = 0;
+ UNUSED(streamptr);
}
static
-void cgribexDefaultSec1(int *isec1)
+int grbScanTimestep1(stream_t * streamptr)
{
- ISEC1_CenterID = 0;
- ISEC1_SubCenterID = 0;
- ISEC1_LocalFLag = 0;
+ int status = CDI_EUFTYPE;
+
+#if defined (HAVE_LIBCGRIBEX)
+ int filetype = streamptr->filetype;
+
+ if ( filetype == FILETYPE_GRB )
+ status = cgribexScanTimestep1(streamptr);
+#endif
+#if defined(HAVE_LIBCGRIBEX) && defined (HAVE_LIBGRIB_API)
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ status = gribapiScanTimestep1(streamptr);
+#endif
+
+ return status;
}
static
-void cgribexDefaultSec4(int *isec4)
+int grbScanTimestep2(stream_t * streamptr)
{
- long i;
+ int status = CDI_EUFTYPE;
+
+#if defined (HAVE_LIBCGRIBEX)
+ int filetype = streamptr->filetype;
+
+ if ( filetype == FILETYPE_GRB )
+ {
+ status = cgribexScanTimestep2(streamptr);
+ }
+#endif
+#if defined(HAVE_LIBCGRIBEX) && defined (HAVE_LIBGRIB_API)
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ status = gribapiScanTimestep2(streamptr);
+#endif
- for ( i = 2; i <= 10; ++i ) isec4[i] = 0;
+ return status;
}
static
-void cgribexDefEnsembleVar(int *isec1, int vlistID, int varID)
+int grbScanTimestep(stream_t * streamptr)
{
- int ensID, ensCount, forecast_type;
-
- /* For Ensemble info */
+ int status = CDI_EUFTYPE;
+ int filetype;
- //Put1Byte(isec1[36]); /* MPIM local GRIB use definition identifier */
- /* (extension identifier) */
- //Put1Byte(isec1[37]); /* type of ensemble forecast */
- //Put2Byte(isec1[38]); /* individual ensemble member */
- //Put2Byte(isec1[39]); /* number of forecasts in ensemble */
+ filetype = streamptr->filetype;
- if ( vlistInqVarEnsemble(vlistID, varID, &ensID, &ensCount, &forecast_type) )
+#if defined (HAVE_LIBCGRIBEX)
+ if ( filetype == FILETYPE_GRB )
{
- if ( ISEC1_CenterID == 252 )
- {
- ISEC1_LocalFLag = 1;
- isec1[36] = 1;
-
- isec1[37] = forecast_type;
- isec1[38] = ensID;
- isec1[39] = ensCount;
- }
+ status = cgribexScanTimestep(streamptr);
}
-}
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ status = gribapiScanTimestep(streamptr);
+#else
+ Error("Sufficient GRIB support unavailable!");
#endif
+ return status;
+}
-#if defined (HAVE_LIBCGRIBEX)
-size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize)
+
+#if defined (HAVE_LIBGRIB)
+int grbInqContents(stream_t * streamptr)
{
- size_t nbytes = 0;
- int gribsize;
- int iret = 0, iword = 0;
- int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
- float fsec2f[512], fsec3f[2];
- double fsec2[512], fsec3[2];
- int datatype;
- int param;
+ int fileID;
+ int status = 0;
- memset(isec1, 0, 256*sizeof(int));
- fsec2[0] = 0; fsec2[1] = 0;
- fsec2f[0] = 0; fsec2f[1] = 0;
+ fileID = streamptr->fileID;
- gribsize = (int)(gribbuffersize / sizeof(int));
- param = vlistInqVarParam(vlistID, varID);
+ streamptr->curTsID = 0;
- cgribexDefaultSec0(isec0);
- cgribexDefaultSec1(isec1);
- cgribexDefaultSec4(isec4);
+ status = grbScanTimestep1(streamptr);
- cgribexDefInstitut(isec1, vlistID, varID);
- cgribexDefModel(isec1, vlistID, varID);
+ if ( status == 0 && streamptr->ntsteps == -1 ) status = grbScanTimestep2(streamptr);
- datatype = vlistInqVarDatatype(vlistID, varID);
+ fileSetPos(fileID, 0, SEEK_SET);
- cgribexDefParam(isec1, param);
- cgribexDefTime(isec1, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID));
- cgribexDefGrid(isec1, isec2, fsec2, isec4, gridID);
- cgribexDefLevel(isec1, isec2, fsec2, zaxisID, levelID);
+ return status;
+}
+#endif
- cgribexDefEnsembleVar(isec1, vlistID, varID);
+int grbInqTimestep(stream_t * streamptr, int tsID)
+{
+ int ntsteps, nrecs;
- ISEC4_NumValues = gridInqSize(gridID);
- ISEC4_NumBits = grbBitsPerValue(datatype);
+ if ( tsID == 0 && streamptr->rtsteps == 0 )
+ Error("Call to cdiInqContents missing!");
- if ( nmiss > 0 )
+ if ( CDI_Debug )
+ Message("tsid = %d rtsteps = %d", tsID, streamptr->rtsteps);
+
+ ntsteps = CDI_UNDEFID;
+ while ( (tsID + 1) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
{
- FSEC3_MissVal = vlistInqVarMissval(vlistID, varID);
- ISEC1_Sec2Or3Flag |= 64;
+ ntsteps = grbScanTimestep(streamptr);
+ if ( ntsteps == CDI_EUFSTRUCT )
+ {
+ streamptr->ntsteps = streamptr->rtsteps;
+ break;
+ }
}
- if ( isec4[2] == 128 && isec4[3] == 64 )
+ if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
{
- isec4[16] = (int) (1000*calculate_pfactor(data, ISEC2_PentaJ, isec4[17]));
- if ( isec4[16] < -10000 ) isec4[16] = -10000;
- if ( isec4[16] > 10000 ) isec4[16] = 10000;
+ nrecs = 0;
}
- //printf("isec4[16] %d\n", isec4[16]);
-
- if ( memtype == MEMTYPE_FLOAT )
+ else
{
- size_t numVCP = ISEC2_NumVCP > 0 ? (size_t)ISEC2_NumVCP : (size_t)0;
- for ( size_t i = 0; i < numVCP; ++i ) fsec2f[10+i] = (float)fsec2[10+i];
- fsec3f[ 1] = (float)fsec3[ 1];
+ streamptr->curTsID = tsID;
+ nrecs = streamptr->tsteps[tsID].nrecs;
}
- if ( memtype == MEMTYPE_FLOAT )
- gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
- (int)datasize, (int *)(void *)gribbuffer, gribsize, &iword, "C", &iret);
- else
- gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
- (int)datasize, (int *)(void *)gribbuffer, gribsize, &iword, "C", &iret);
+ return nrecs;
+}
- if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
- nbytes = (size_t)iword * sizeof (int);
- return (nbytes);
+void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
+{
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ int filetype = streamptr->filetype;
+
+ if ( filetype == FILETYPE_GRB )
+ {
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ int zip = streamptr->tsteps[tsID].records[recID].zip;
+
+ void *gribbuffer = streamptr->record->buffer;
+ size_t gribbuffersize = streamptr->record->buffersize;
+
+ if ( zip > 0 )
+ Error("Compressed GRIB records unsupported!");
+ else
+ grib_info_for_grads(recpos, (long)gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
+ }
}
-#endif
/*
* Local Variables:
* c-file-style: "Java"
@@ -48094,16 +48605,102 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
* require-trailing-newline: t
* End:
*/
-#ifndef STREAM_FCOMMON_H
-#define STREAM_FCOMMON_H
+#ifndef _SUBTYPE_H
+#define _SUBTYPE_H
-#ifndef _CDI_INT_H
-#endif
-void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
- const char *container_name);
+enum {
+ /* subtype attributes wrt. TILES */
+ SUBTYPE_ATT_TILEINDEX = 0,
+ SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS = 1,
+ SUBTYPE_ATT_TILE_CLASSIFICATION = 2,
+ SUBTYPE_ATT_NUMBER_OF_TILES = 3,
+ SUBTYPE_ATT_NUMBER_OF_ATTR = 4,
+ SUBTYPE_ATT_TILEATTRIBUTE = 5,
+/* No. of different constants in the enumeration
+ "subtype_attributes" */
+ nSubtypeAttributes
+};
+
+
+/* Literal constants corresponding to the different constants of the
+ enumeration "subtype_attributes". */
+extern const char * const cdiSubtypeAttributeName[];
+
+/* Data type specifying an attribute of a subtype (for example an
+ attribute of a set of TILES) or an attribute of a subtype entry
+ (for example an attribute of a single TILE). This data type is part
+ of a linked list. */
+struct subtype_attr_t {
+ int key, val; /* key/value pair */
+ struct subtype_attr_t* next; /* next element in linked list */
+};
+
+
+/* Data type specifying a single entry of a subtype, for example a
+ single TILE in a set of TILES. */
+struct subtype_entry_t {
+ int self; /* list entry index (0,...,nentries-1) */
+ struct subtype_entry_t *next; /* next node in linked list */
+
+ /* linked list with attributes for this subtype entry, ordered by its key values*/
+ struct subtype_attr_t *atts;
+};
+
+
+/* Data type specifying a variable subtype, for example a list of
+ TILES. This can be interpreted as an additional axis like the
+ vertical axis. */
+typedef struct {
+ int self; /* resource handler ID */
+ int subtype; /* subtype kind: TILES, ... */
+ int nentries; /* counter: total no. of entries in list */
+
+ struct subtype_entry_t globals; /* global attributes */
+
+ /* list of subtype entries, e.g. the list of tiles, ordered by entry->self. */
+ struct subtype_entry_t *entries;
+ /* currently active subtype, e.g. GRIB2 tile index (for example for
+ stream/vlist accesses): */
+ int active_subtype_index;
+} subtype_t;
+
+
+
+
+/* prototypes: allocation and destruction */
+void subtypeAllocate(subtype_t **subtype_ptr2, int subtype);
+int subtypePush(subtype_t *subtype_ptr);
+void subtypeDestroyPtr(void *ptr);
+void subtypeDuplicate(subtype_t *subtype_ptr, subtype_t **dst);
+struct subtype_entry_t* subtypeEntryInsert(subtype_t* head);
+
+/* prototypes: accessing global attributes */
+void subtypePrint(int subtypeID);
+void subtypePrintPtr(subtype_t* subtype_ptr);
+void subtypeDefGlobalDataP(subtype_t *subtype_ptr, int key, int val);
+void subtypeDefGlobalData(int subtypeID, int key, int val);
+int subtypeGetGlobalData(int subtypeID, int key);
+int subtypeGetGlobalDataP(subtype_t *subtype_ptr, int key);
+int subtypeComparePtr(int s1_ID, subtype_t *s2);
+
+/* prototypes: accessing subtype entries */
+void subtypeDefEntryDataP(struct subtype_entry_t *subtype_entry_ptr, int key, int val);
+
+
+/* prototypes: tile implementations */
+void tilesetInsertP(subtype_t *s1, subtype_t *s2);
+
+/* Construct a new subtype for a tile set. If a corresponding subtype
+ * already exists, then we return this subtype ID instead. */
+int vlistDefTileSubtype(int vlistID, subtype_t *tiles);
+
+/* Insert a trivial one-tile-subtype */
+int vlistInsertTrivialTileSubtype(int vlistID);
+
#endif
+
/*
* Local Variables:
* c-file-style: "Java"
@@ -48116,4647 +48713,4615 @@ void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
#if defined (HAVE_CONFIG_H)
#endif
+#if defined (HAVE_LIBGRIB_API)
#include <limits.h>
#include <stdio.h>
-#include <string.h>
-#undef UNDEFID
-#define UNDEFID CDI_UNDEFID
-
-#define SINGLE_PRECISION 4
-#define DOUBLE_PRECISION 8
+# include <grib_api.h>
-#if defined (HAVE_LIBEXTRA)
+extern int cdiInventoryMode;
+static const var_tile_t dummy_tiles = { 0, -1, -1, -1, -1, -1 };
typedef struct {
int param;
- int level;
-} extcompvar_t;
+ int level1;
+ int level2;
+ int ltype;
+ int tsteptype;
+ char name[32];
+
+ var_tile_t tiles;
+
+} compvar2_t;
+
static
-int extInqDatatype(int prec, int number)
+int gribapiGetZaxisType(long editionNumber, int grib_ltype)
{
- int datatype;
+ int zaxistype = ZAXIS_GENERIC;
- if ( number == 2 )
+ if ( editionNumber <= 1 )
{
- if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_CPX64;
- else datatype = DATATYPE_CPX32;
+ zaxistype = grib1ltypeToZaxisType(grib_ltype);
}
else
{
- if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
- else datatype = DATATYPE_FLT32;
+ zaxistype = grib2ltypeToZaxisType(grib_ltype);
}
- return (datatype);
+ return (zaxistype);
}
static
-void extDefDatatype(int datatype, int *prec, int *number)
+int getTimeunits(long unitsOfTime)
{
+ int timeunits = -1;
- if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 &&
- datatype != DATATYPE_CPX32 && datatype != DATATYPE_CPX64 )
- datatype = DATATYPE_FLT32;
-
- if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- *number = 2;
- else
- *number = 1;
+ switch (unitsOfTime)
+ {
+ case 13: timeunits = TUNIT_SECOND; break;
+ case 0: timeunits = TUNIT_MINUTE; break;
+ case 1: timeunits = TUNIT_HOUR; break;
+ case 10: timeunits = TUNIT_3HOURS; break;
+ case 11: timeunits = TUNIT_6HOURS; break;
+ case 12: timeunits = TUNIT_12HOURS; break;
+ case 2: timeunits = TUNIT_DAY; break;
+ default: timeunits = TUNIT_HOUR; break;
+ }
- if ( datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64 )
- *prec = DOUBLE_PRECISION;
- else
- *prec = SINGLE_PRECISION;
+ return (timeunits);
}
-/* not used
-int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
+static
+double timeunit_factor(int tu1, int tu2)
{
- int status;
- int fileID;
- int icode, ilevel;
- int zaxisID = -1;
- int header[4];
- int vlistID;
- void *extp = streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
-
- *varID = -1;
- *levelID = -1;
-
- status = extRead(fileID, extp);
- if ( status != 0 ) return (0);
+ double factor = 1;
- extInqHeader(extp, header);
+ if ( tu2 == TUNIT_HOUR )
+ {
+ switch (tu1)
+ {
+ case TUNIT_SECOND: factor = 3600; break;
+ case TUNIT_MINUTE: factor = 60; break;
+ case TUNIT_HOUR: factor = 1; break;
+ case TUNIT_3HOURS: factor = 1./3; break;
+ case TUNIT_6HOURS: factor = 1./6; break;
+ case TUNIT_12HOURS: factor = 1./12; break;
+ case TUNIT_DAY: factor = 1./24; break;
+ }
+ }
- icode = header[1];
- ilevel = header[2];
+ return (factor);
+}
- *varID = vlistInqVarID(vlistID, icode);
+static
+int gribapiGetTimeUnits(grib_handle *gh)
+{
+ int timeunits = -1;
+ long unitsOfTime = -1;
- if ( *varID == UNDEFID ) Error("Code %d undefined", icode);
+ grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
- zaxisID = vlistInqVarZaxis(vlistID, *varID);
+ GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
- *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
+ timeunits = getTimeunits(unitsOfTime);
- return (1);
+ return (timeunits);
}
-*/
-void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
+static
+void gribapiGetSteps(grib_handle *gh, int timeunits, int *startStep, int *endStep)
{
- int vlistID, fileID;
- int status;
- int recID, vrecID, tsID;
- off_t recpos;
- int header[4];
- int varID, gridID;
- int i, size;
- double missval;
- void *extp = streamptr->record->exsep;
+ int timeunits2 = timeunits;
+ long unitsOfTime;
+ int status = grib_get_long(gh, "stepUnits", &unitsOfTime);
+ if ( status == 0 ) timeunits2 = getTimeunits(unitsOfTime);
+ //timeunits2 = gribapiGetTimeUnits(gh);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- vrecID = streamptr->tsteps[tsID].curRecID;
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- recpos = streamptr->tsteps[tsID].records[recID].position;
- varID = streamptr->tsteps[tsID].records[recID].varID;
+ long lpar;
+ status = grib_get_long(gh, "forecastTime", &lpar);
+ if ( status == 0 ) *startStep = (int) lpar;
+ else
+ {
+ status = grib_get_long(gh, "startStep", &lpar);
+ if ( status == 0 )
+ *startStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
+ }
- fileSetPos(fileID, recpos, SEEK_SET);
+ *endStep = *startStep;
+ status = grib_get_long(gh, "endStep", &lpar);
+ if ( status == 0 )
+ *endStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
+ // printf("%d %d %d %d %d %g\n", *startStep, *endStep, lpar, timeunits, timeunits2, timeunit_factor(timeunits, timeunits2));
+}
- status = extRead(fileID, extp);
- if ( status != 0 )
- Error("Failed to read EXTRA record");
+static
+void gribapiGetDataDateTime(grib_handle *gh, int *datadate, int *datatime)
+{
+ long lpar;
- extInqHeader(extp, header);
- extInqDataDP(extp, data);
+ GRIB_CHECK(grib_get_long(gh, "dataDate", &lpar), 0);
+ *datadate = (int) lpar;
+ GRIB_CHECK(grib_get_long(gh, "dataTime", &lpar), 0); //FIXME: This looses the seconds in GRIB2 files.
+ *datatime = (int) lpar*100;
+}
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- size = gridInqSize(gridID);
+static
+void gribapiSetDataDateTime(grib_handle *gh, int datadate, int datatime)
+{
+ GRIB_CHECK(my_grib_set_long(gh, "dataDate", datadate), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "dataTime", datatime/100), 0);
+}
- streamptr->numvals += size;
+static
+int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
+{
+ int rdate, rtime;
+ int timeUnits, startStep = 0, endStep;
+ int tstepRange = 0;
+ int range;
+ long sigofrtime = 3;
- *nmiss = 0;
- if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
+ if ( gribEditionNumber(gh) > 1 )
{
- for ( i = 0; i < size; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ GRIB_CHECK(grib_get_long(gh, "significanceOfReferenceTime", &sigofrtime), 0);
}
else
{
- for ( i = 0; i < 2*size; i+=2 )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ GRIB_CHECK(grib_get_long(gh, "timeRangeIndicator", &sigofrtime), 0);
}
-}
+ if ( sigofrtime == 3 ) //XXX: This looks like a bug to me, because timeRangeIndicator == 3 does not seem to have the same meaning as significanceOfReferenceTime == 3. I would recommend replacing this condition with `if(!gribapiTimeIsFC())`.
+ {
+ gribapiGetDataDateTime(gh, vdate, vtime);
+ }
+ else
+ {
+ gribapiGetDataDateTime(gh, &rdate, &rtime);
-void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
-{
- streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
-}
+ timeUnits = gribapiGetTimeUnits(gh);
+ gribapiGetSteps(gh, timeUnits, &startStep, &endStep);
+ range = endStep - startStep;
-void extDefRecord(stream_t *streamptr)
-{
- int gridID;
- int header[4];
- int pdis, pcat, pnum;
- extrec_t *extp = (extrec_t*) streamptr->record->exsep;
+ if ( range > 0 )
+ {
+ if ( startStep == 0 ) tstepRange = -1;
+ else tstepRange = 1;
+ }
- gridID = streamptr->record->gridID;
+ {
+ static int lprint = TRUE;
+ extern int grib_calendar;
+ int ryear, rmonth, rday, rhour, rminute, rsecond;
+ int julday, secofday;
+ int64_t time_period = endStep;
+ int64_t addsec;
- cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
- header[0] = streamptr->record->date;
- header[1] = pnum;
- header[2] = streamptr->record->level;
- header[3] = gridInqSize(gridID);
+ cdiDecodeDate(rdate, &ryear, &rmonth, &rday);
+ cdiDecodeTime(rtime, &rhour, &rminute, &rsecond);
- extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
+ if ( rday > 0 )
+ {
+ encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
- extDefHeader(extp, header);
-}
+ addsec = 0;
+ switch ( timeUnits )
+ {
+ case TUNIT_SECOND: addsec = time_period; break;
+ case TUNIT_MINUTE: addsec = 60 * time_period; break;
+ case TUNIT_HOUR: addsec = 3600 * time_period; break;
+ case TUNIT_3HOURS: addsec = 10800 * time_period; break;
+ case TUNIT_6HOURS: addsec = 21600 * time_period; break;
+ case TUNIT_12HOURS: addsec = 43200 * time_period; break;
+ case TUNIT_DAY: addsec = 86400 * time_period; break;
+ default:
+ if ( lprint )
+ {
+ Warning("Time unit %d unsupported", timeUnits);
+ lprint = FALSE;
+ }
+ break;
+ }
+ julday_add_seconds(addsec, &julday, &secofday);
-void extWriteRecord(stream_t *streamptr, const double *data)
-{
- int fileID = streamptr->fileID;
- void *extp = streamptr->record->exsep;
+ decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
+ }
- extDefDataDP(extp, data);
- extWrite(fileID, extp);
+ *vdate = cdiEncodeDate(ryear, rmonth, rday);
+ *vtime = cdiEncodeTime(rhour, rminute, rsecond);
+ }
+ }
+
+ return (tstepRange);
}
static
-void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
- size_t recsize, off_t position, int prec, int number)
+void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2)
{
- int leveltype;
- int gridID = CDI_UNDEFID;
- int levelID = 0;
- int tsID, recID, varID;
- record_t *record;
- grid_t grid;
- int vlistID;
+ *leveltype = 0;
+ *lbounds = 0;
+ *level1 = 0;
+ *level2 = 0;
- vlistID = streamptr->vlistID;
- tsID = streamptr->curTsID;
- recID = recordNewEntry(streamptr, tsID);
- record = &streamptr->tsteps[tsID].records[recID];
+ long lpar;
+ if(!grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar)) //1 byte
+ {
+ *leveltype = (int) lpar;
- (*record).size = recsize;
- (*record).position = position;
- (*record).param = param;
- (*record).ilevel = level;
-
- memset(&grid, 0, sizeof(grid_t));
- grid.type = GRID_GENERIC;
- grid.size = xysize;
- grid.xsize = xysize;
- grid.ysize = 0;
- grid.xvals = NULL;
- grid.yvals = NULL;
- gridID = varDefGrid(vlistID, &grid, 0);
- /*
- if ( level == 0 ) leveltype = ZAXIS_SURFACE;
- else leveltype = ZAXIS_GENERIC;
- */
- leveltype = ZAXIS_GENERIC;
+ switch (*leveltype)
+ {
+ case GRIB1_LTYPE_SIGMA_LAYER:
+ case GRIB1_LTYPE_HYBRID_LAYER:
+ case GRIB1_LTYPE_LANDDEPTH_LAYER:
+ { *lbounds = 1; break; }
+ }
- varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
- extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ if ( *lbounds )
+ {
+ GRIB_CHECK(grib_get_long(gh, "topLevel", &lpar), 0); //1 byte
+ *level1 = (int)lpar;
+ GRIB_CHECK(grib_get_long(gh, "bottomLevel", &lpar), 0); //1 byte
+ *level2 = (int)lpar;
+ }
+ else
+ {
+ double dlevel;
+ GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0); //2 byte
+ if ( *leveltype == 100 ) dlevel *= 100;
+ if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;
+ if ( *leveltype == GRIB1_LTYPE_99 ) *leveltype = 100;
- (*record).varID = (short)varID;
- (*record).levelID = (short)levelID;
+ *level1 = (int) dlevel;
+ *level2 = 0;
+ }
+ }
+}
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
+static
+double grib2ScaleFactor(long factor)
+{
+ switch(factor)
+ {
+ case GRIB_MISSING_LONG: return 1;
+ case 0: return 1;
+ case 1: return 0.1;
+ case 2: return 0.01;
+ case 3: return 0.001;
+ case 4: return 0.0001;
+ case 5: return 0.00001;
+ case 6: return 0.000001;
+ case 7: return 0.0000001;
+ case 8: return 0.00000001;
+ case 9: return 0.000000001;
+ default: return 0;
+ }
+}
- if ( CDI_Debug )
- Message("varID = %d gridID = %d levelID = %d",
- varID, gridID, levelID);
+static
+int calcLevel(int level_sf, long factor, long level)
+{
+ double result = 0;
+ if(level != GRIB_MISSING_LONG) result = (double)level*grib2ScaleFactor(factor);
+ if(level_sf) result *= level_sf;
+ return (int)result;
}
static
-void extScanTimestep1(stream_t *streamptr)
+void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1,
+ int *level2, int *level_sf, int *level_unit)
{
- int header[4];
int status;
- int fileID;
- int rxysize = 0;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- DateTime datetime0 = { LONG_MIN, LONG_MIN };
- int tsID;
- int varID;
- long recsize;
- off_t recpos;
- int nrecords, nrecs, recID;
- int taxisID = -1;
- taxis_t *taxis;
- int vlistID;
- extcompvar_t compVar, compVar0;
- extrec_t *extp = (extrec_t*) streamptr->record->exsep;
-
- streamptr->curTsID = 0;
-
- tsID = tstepsNewEntry(streamptr);
- taxis = &streamptr->tsteps[tsID].taxis;
-
- if ( tsID != 0 )
- Error("Internal problem! tstepsNewEntry returns %d", tsID);
+ long lpar;
+ long factor;
- fileID = streamptr->fileID;
+ *leveltype1 = 0;
+ *leveltype2 = -1;
+ *lbounds = 0;
+ *level1 = 0;
+ *level2 = 0;
+ *level_sf = 0;
+ *level_unit = 0;
- nrecs = 0;
- while ( TRUE )
+ status = grib_get_long(gh, "typeOfFirstFixedSurface", &lpar); //1 byte
+ if ( status == 0 )
{
- recpos = fileGetPos(fileID);
- status = extRead(fileID, extp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 1;
- break;
- }
- recsize = fileGetPos(fileID) - recpos;
+ long llevel;
- extInqHeader(extp, header);
+ *leveltype1 = (int) lpar;
- vdate = header[0];
- vtime = 0;
- rcode = header[1];
- rlevel = header[2];
- rxysize = header[3];
+ status = grib_get_long(gh, "typeOfSecondFixedSurface", &lpar); //1 byte
+ /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
+ if ( status == 0 ) *leveltype2 = (int)lpar;
- param = cdiEncodeParam(rcode, 255, 255);
+ if ( *leveltype1 != 255 && *leveltype2 != 255 && *leveltype2 > 0 ) *lbounds = 1;
+ switch(*leveltype1)
+ {
+ case GRIB2_LTYPE_REFERENCE:
+ if(*leveltype2 == 1) *lbounds = 0;
+ break;
- if ( nrecs == 0 )
- {
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
- else
- {
- compVar.param = param;
- compVar.level = rlevel;
- for ( recID = 0; recID < nrecs; recID++ )
- {
- compVar0.param = streamptr->tsteps[0].records[recID].param;
- compVar0.level = streamptr->tsteps[0].records[recID].ilevel;
+ case GRIB2_LTYPE_LANDDEPTH:
+ *level_sf = 1000;
+ *level_unit = CDI_UNIT_M;
+ break;
- if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 ) break;
- }
- if ( recID < nrecs ) break;
- DateTime datetime = { .date = vdate, .time = vtime};
- if ( datetimeCmp(datetime, datetime0) )
- Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
- }
+ case GRIB2_LTYPE_ISOBARIC:
+ *level_sf = 1000;
+ *level_unit = CDI_UNIT_PA;
+ break;
- nrecs++;
+ case GRIB2_LTYPE_SIGMA:
+ *level_sf = 1000;
+ *level_unit = 0;
+ break;
+ }
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
+ GRIB_CHECK(grib_get_long(gh, "scaleFactorOfFirstFixedSurface", &factor), 0); //1 byte
+ GRIB_CHECK(grib_get_long(gh, "scaledValueOfFirstFixedSurface", &llevel), 0); //4 byte
+ *level1 = calcLevel(*level_sf, factor, llevel);
- extAddRecord(streamptr, param, rlevel, rxysize, (size_t)recsize, recpos, extp->prec, extp->number);
+ if ( *lbounds )
+ {
+ GRIB_CHECK(grib_get_long(gh, "scaleFactorOfSecondFixedSurface", &factor), 0); //1 byte
+ GRIB_CHECK(grib_get_long(gh, "scaledValueOfSecondFixedSurface", &llevel), 0); //4 byte
+ *level2 = calcLevel(*level_sf, factor, llevel);
+ }
}
+}
- streamptr->rtsteps = 1;
-
- cdi_generate_vars(streamptr);
-
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = (int)datetime0.date;
- taxis->vtime = (int)datetime0.time;
-
- vlistID = streamptr->vlistID;
- vlistDefTaxis(vlistID, taxisID);
-
- vlist_check_contents(vlistID);
-
- nrecords = streamptr->tsteps[0].nallrecs;
- if ( nrecords < streamptr->tsteps[0].recordSize )
+static
+void gribGetLevel(grib_handle *gh, int* leveltype1, int* leveltype2, int* lbounds, int* level1, int* level2, int* level_sf, int* level_unit, var_tile_t* tiles)
+{
+ if ( gribEditionNumber(gh) <= 1 )
{
- streamptr->tsteps[0].recordSize = nrecords;
- streamptr->tsteps[0].records =
- (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
+ grib1GetLevel(gh, leveltype1, lbounds, level1, level2);
+ *leveltype2 = -1;
+ *level_sf = 0;
+ *level_unit = 0;
}
-
- streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
- streamptr->tsteps[0].nrecs = nrecords;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[0].recIDs[recID] = recID;
-
- if ( streamptr->ntsteps == -1 )
+ else
{
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ grib2GetLevel(gh, leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit);
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ /* read in tiles attributes (if there are any) */
+ tiles->tileindex = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], -1);
+ tiles->totalno_of_tileattr_pairs = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS], -1);
+ tiles->tileClassification = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILE_CLASSIFICATION], -1);
+ tiles->numberOfTiles = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_NUMBER_OF_TILES], -1);
+ tiles->numberOfAttributes = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_NUMBER_OF_ATTR], -1);
+ tiles->attribute = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], -1);
}
+}
- if ( streamptr->ntsteps == 1 )
+static
+void gribapiGetString(grib_handle *gh, const char *key, char *string, size_t length)
+{
+ string[0] = 0;
+
+ int ret = grib_get_string(gh, key, string, &length);
+ if (ret != 0)
{
- if ( taxis->vdate == 0 && taxis->vtime == 0 )
- {
- streamptr->ntsteps = 0;
- for ( varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- }
+ fprintf(stderr, "grib_get_string(gh, \"%s\", ...) failed!\n", key);
+ GRIB_CHECK(ret, 0);
}
+ if ( length == 8 && memcmp(string, "unknown", length) == 0 ) string[0] = 0;
+ else if ( length == 2 && memcmp(string, "~", length) == 0 ) string[0] = 0;
}
static
-int extScanTimestep2(stream_t *streamptr)
+void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
+ size_t recsize, off_t position, int datatype, int comptype, const char *varname,
+ int leveltype1, int leveltype2, int lbounds, int level1, int level2, int level_sf, int level_unit,
+ const var_tile_t *tiles, int lread_additional_keys)
{
- int header[4];
- int status;
- int fileID;
- // int rxysize = 0;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- int tsID;
- int varID;
- off_t recpos = 0;
- int nrecords, nrecs, recID, rindex;
- int nextstep;
- taxis_t *taxis;
- int vlistID;
- extcompvar_t compVar, compVar0;
- void *extp = streamptr->record->exsep;
+ int levelID = 0;
+ char stdname[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
+ long ens_index = 0, ens_count = 0, ens_forecast_type = 0;
- streamptr->curTsID = 1;
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
- fileID = streamptr->fileID;
- vlistID = streamptr->vlistID;
+ int tsteptype = gribapiGetTsteptype(gh);
+ // numavg = ISEC1_AvgNum;
+ int numavg = 0;
- tsID = streamptr->rtsteps;
- if ( tsID != 1 )
- Error("Internal problem! unexpected timestep %d", tsID+1);
+ // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype1);
- taxis = &streamptr->tsteps[tsID].taxis;
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level1;
+ record->ilevel2 = level2;
+ record->ltype = leveltype1;
+ record->tsteptype = (short)tsteptype;
+ record->tiles = tiles ? *tiles : dummy_tiles;
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ //FIXME: This may leave the variable name unterminated (which is the behavior that I found in the code).
+ // I don't know precisely how this field is used, so I did not change this behavior to avoid regressions,
+ // but I think that it would be better to at least add a line
+ //
+ // record->varname[sizeof(record->varname) - 1] = 0;`
+ //
+ // after the `strncpy()` call.
+ //
+ // I would consider using strdup() (that requires POSIX-2008 compliance, though), or a similar homebrew approach.
+ // I. e. kick the fixed size array and allocate enough space, whatever that may be.
+ strncpy(record->varname, varname, sizeof(record->varname));
- cdi_create_records(streamptr, tsID);
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ gribapiGetGrid(gh, grid);
- nrecords = streamptr->tsteps[0].nallrecs;
- streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
- streamptr->tsteps[1].nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[1].recIDs[recID] = -1;
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
- for ( recID = 0; recID < nrecords; recID++ )
+ int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1);
+
+ switch (zaxistype)
{
- varID = streamptr->tsteps[0].records[recID].varID;
- streamptr->tsteps[tsID].records[recID].position =
- streamptr->tsteps[0].records[recID].position;
- streamptr->tsteps[tsID].records[recID].size =
- streamptr->tsteps[0].records[recID].size;
+ case ZAXIS_HYBRID:
+ case ZAXIS_HYBRID_HALF:
+ {
+ long lpar;
+ GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
+ /* FIXME: assert(lpar >= 0) */
+ size_t vctsize = (size_t)lpar;
+ if ( vctsize > 0 )
+ {
+ double *vctptr = (double *) Malloc(vctsize*sizeof(double));
+ size_t dummy = vctsize;
+ GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
+ varDefVCT(vctsize, vctptr);
+ Free(vctptr);
+ }
+ break;
+ }
+ case ZAXIS_REFERENCE:
+ {
+ unsigned char uuid[CDI_UUID_SIZE];
+ long lpar;
+ GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
+ if ( lpar != 6 )
+ {
+ fprintf(stderr, "Warning ...\n");
+ }
+ GRIB_CHECK(grib_get_long(gh, "nlev", &lpar), 0);
+ int nhlev = (int)lpar;
+ GRIB_CHECK(grib_get_long(gh, "numberOfVGridUsed", &lpar), 0);
+ int nvgrid = (int)lpar;
+ size_t len = (size_t)CDI_UUID_SIZE;
+ memset(uuid, 0, CDI_UUID_SIZE);
+ GRIB_CHECK(grib_get_bytes(gh, "uuidOfVGrid", uuid, &len), 0);
+ varDefZAxisReference(nhlev, nvgrid, uuid);
+ break;
+ }
}
- for ( rindex = 0; rindex <= nrecords; rindex++ )
- {
- recpos = fileGetPos(fileID);
- status = extRead(fileID, extp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 2;
- break;
- }
- size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
+ // if ( datatype > 32 ) datatype = DATATYPE_PACK32;
+ if ( datatype < 0 ) datatype = DATATYPE_PACK;
- extInqHeader(extp, header);
+ stdname[0] = 0;
+ longname[0] = 0;
+ units[0] = 0;
- vdate = header[0];
- vtime = 0;
- rcode = header[1];
- rlevel = header[2];
- // rxysize = header[3];
+ if ( varname[0] != 0 )
+ {
+ size_t vlen = CDI_MAX_NAME;
+ gribapiGetString(gh, "name", longname, vlen);
+ vlen = CDI_MAX_NAME;
+ gribapiGetString(gh, "units", units, vlen);
+ vlen = CDI_MAX_NAME;
+ int status = grib_get_string(gh, "cfName", stdname, &vlen);
+ if ( status != 0 || vlen <= 1 || strncmp(stdname, "unknown", 7) == 0 )
+ stdname[0] = 0;
+ }
+ // fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units);
- param = cdiEncodeParam(rcode, 255, 255);
+ /* add the previously read record data to the (intermediate) list of records */
+ int tile_index = 0, varID;
+ varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, level_sf, level_unit,
+ datatype, &varID, &levelID, tsteptype, numavg, leveltype1, leveltype2,
+ varname, stdname, longname, units, tiles, &tile_index);
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
- compVar.param = param;
- compVar.level = rlevel;
- nextstep = FALSE;
- for ( recID = 0; recID < nrecords; recID++ )
- {
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ varDefCompType(varID, comptype);
- if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
- {
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- nextstep = TRUE;
- }
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
- break;
- }
- }
- if ( recID == nrecords )
- {
- Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
- return (CDI_EUFSTRUCT);
- }
+ /*
+ Get the ensemble Info from the grib-2 Tables and update the intermediate datastructure.
+ Further update to the "vlist" is handled in the same way as for GRIB-1 by "cdi_generate_vars"
+ */
+ if ( grib_get_long(gh, "typeOfEnsembleForecast", &ens_forecast_type) == 0 )
+ {
+ GRIB_CHECK(grib_get_long(gh, "numberOfForecastsInEnsemble", &ens_count ), 0);
+ GRIB_CHECK(grib_get_long(gh, "perturbationNumber", &ens_index ), 0);
+ }
- if ( nextstep ) break;
+ if ( ens_index > 0 )
+ varDefEnsembleInfo(varID, (int)ens_index, (int)ens_count, (int)ens_forecast_type);
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
+ long typeOfGeneratingProcess = 0;
+ if ( grib_get_long(gh, "typeOfGeneratingProcess", &typeOfGeneratingProcess) == 0 )
+ varDefTypeOfGeneratingProcess(varID, (int) typeOfGeneratingProcess);
- streamptr->tsteps[tsID].records[recID].size = recsize;
+ long productDefinitionTemplate = 0;
+ if ( grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate) == 0 )
+ varDefProductDefinitionTemplate(varID, (int) productDefinitionTemplate);
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ int i;
+ long lval;
+ double dval;
- if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- return (CDI_EUFSTRUCT);
- }
+ if (lread_additional_keys)
+ for ( i = 0; i < cdiNAdditionalGRIBKeys; i++ )
+ {
+ /* note: if the key is not defined, we do not throw an error! */
+ if ( grib_get_long(gh, cdiAdditionalGRIBKeys[i], &lval) == 0 )
+ varDefOptGribInt(varID, tile_index, lval, cdiAdditionalGRIBKeys[i]);
+ if ( grib_get_double(gh, cdiAdditionalGRIBKeys[i], &dval) == 0 )
+ varDefOptGribDbl(varID, tile_index, dval, cdiAdditionalGRIBKeys[i]);
+ }
- streamptr->tsteps[1].records[recID].position = recpos;
+ if ( varInqInst(varID) == CDI_UNDEFID )
+ {
+ long center, subcenter;
+ int instID;
+ GRIB_CHECK(grib_get_long(gh, "centre", ¢er), 0);
+ GRIB_CHECK(grib_get_long(gh, "subCentre", &subcenter), 0);
+ instID = institutInq((int)center, (int)subcenter, NULL, NULL);
+ if ( instID == CDI_UNDEFID )
+ instID = institutDef((int)center, (int)subcenter, NULL, NULL);
+ varDefInst(varID, instID);
}
- nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
+ if ( varInqModel(varID) == CDI_UNDEFID )
{
- if ( ! streamptr->tsteps[tsID].records[recID].used )
- {
- varID = streamptr->tsteps[tsID].records[recID].varID;
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- else
+ int modelID;
+ long processID;
+ if ( grib_get_long(gh, "generatingProcessIdentifier", &processID) == 0 )
{
- nrecs++;
+ /* FIXME: assert(processID >= INT_MIN && processID <= INT_MAX) */
+ modelID = modelInq(varInqInst(varID), (int)processID, NULL);
+ if ( modelID == CDI_UNDEFID )
+ modelID = modelDef(varInqInst(varID), (int)processID, NULL);
+ varDefModel(varID, modelID);
}
}
- streamptr->tsteps[tsID].nrecs = nrecs;
- streamptr->rtsteps = 2;
-
- if ( streamptr->ntsteps == -1 )
+ if ( varInqTable(varID) == CDI_UNDEFID )
{
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ int pdis, pcat, pnum;
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+
+ if ( pdis == 255 )
+ {
+ int tableID;
+ int tabnum = pcat;
+
+ tableID = tableInq(varInqModel(varID), tabnum, NULL);
+
+ if ( tableID == CDI_UNDEFID )
+ tableID = tableDef(varInqModel(varID), tabnum, NULL);
+ varDefTable(varID, tableID);
+ }
}
- return (0);
-}
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
+ if ( CDI_Debug )
+ Message("varID = %d param = %d zaxistype = %d gridID = %d levelID = %d",
+ varID, param, zaxistype, gridID, levelID);
+}
-int extInqContents(stream_t *streamptr)
+static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype,
+ int tsteptype, char *name, var_tile_t tiles_data)
{
- int fileID;
- int status = 0;
+ compvar2_t compVar;
+ size_t maxlen = sizeof(compVar.name);
+ size_t len = strlen(name);
+ if ( len > maxlen ) len = maxlen;
- fileID = streamptr->fileID;
+ compVar.param = param;
+ compVar.level1 = level1;
+ compVar.level2 = level2;
+ compVar.ltype = leveltype;
+ compVar.tsteptype = tsteptype;
+ memset(compVar.name, 0, maxlen);
+ memcpy(compVar.name, name, len);
+ compVar.tiles = tiles_data;
- streamptr->curTsID = 0;
+ return (compVar);
+}
- extScanTimestep1(streamptr);
+static
+int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
+{
+ compvar2_t compVar0;
+ compVar0.param = record.param;
+ compVar0.level1 = record.ilevel;
+ compVar0.level2 = record.ilevel2;
+ compVar0.ltype = record.ltype;
+ compVar0.tsteptype = record.tsteptype;
+ memcpy(compVar0.name, record.varname, sizeof(compVar.name));
- if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamptr);
+ if ( flag == 0 )
+ {
+ if ( compVar0.tsteptype == TSTEP_INSTANT && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
+ if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT ) compVar0.tsteptype = TSTEP_INSTANT;
+ }
- fileSetPos(fileID, 0, SEEK_SET);
+ compVar0.tiles = record.tiles;
- return (status);
+ return memcmp(&compVar0, &compVar, sizeof(compvar2_t));
}
static
-long extScanTimestep(stream_t *streamptr)
+void ensureBufferSize(size_t requiredSize, size_t *curSize, void **buffer)
{
- int header[4];
- int status;
- int fileID;
- // int rxysize = 0;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- off_t recpos = 0;
- int recID;
- int rindex, nrecs = 0;
- extcompvar_t compVar, compVar0;
- void *extp = streamptr->record->exsep;
- /*
- if ( CDI_Debug )
+ if ( *curSize < requiredSize )
{
- Message("streamID = %d", streamptr->self);
- Message("cts = %d", streamptr->curTsID);
- Message("rts = %d", streamptr->rtsteps);
- Message("nts = %d", streamptr->ntsteps);
+ *curSize = requiredSize;
+ *buffer = Realloc(*buffer, *curSize);
}
- */
+}
- int tsID = streamptr->rtsteps;
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+static
+grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, void **gribbuffer, int *outDatatype, int *outCompressionType, long *outUnzipsize)
+{
+ int lieee = FALSE;
- if ( streamptr->tsteps[tsID].recordSize == 0 )
+ grib_handle *gh = grib_handle_new_from_message(NULL, *gribbuffer, recsize);
+ if(gribEditionNumber(gh) > 1)
{
- cdi_create_records(streamptr, tsID);
-
- nrecs = streamptr->tsteps[1].nrecs;
-
- streamptr->tsteps[tsID].nrecs = nrecs;
- streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
- for ( recID = 0; recID < nrecs; recID++ )
- streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
-
- fileID = streamptr->fileID;
-
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
-
- for ( rindex = 0; rindex <= nrecs; rindex++ )
- {
- recpos = fileGetPos(fileID);
- status = extRead(fileID, extp);
- if ( status != 0 )
- {
- streamptr->ntsteps = streamptr->rtsteps + 1;
- break;
- }
- size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
-
- extInqHeader(extp, header);
+ size_t len = 256;
+ char typeOfPacking[256];
- vdate = header[0];
- vtime = 0;
- rcode = header[1];
- rlevel = header[2];
- // rxysize = header[3];
+ if ( grib_get_string(gh, "packingType", typeOfPacking, &len) == 0 )
+ {
+ // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking);
+ if ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = COMPRESS_JPEG;
+ else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = COMPRESS_SZIP;
+ else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = TRUE;
+ }
+ }
+ else
+ {
+ if( gribGetZip((long)recsize, *gribbuffer, outUnzipsize) > 0 )
+ {
+ *outCompressionType = COMPRESS_SZIP;
+ ensureBufferSize((size_t)*outUnzipsize + 100, buffersize, gribbuffer);
+ }
+ else
+ {
+ *outCompressionType = COMPRESS_NONE;
+ }
+ }
- param = cdiEncodeParam(rcode, 255, 255);
+ if ( lieee )
+ {
+ *outDatatype = DATATYPE_FLT64;
+ long precision;
+ int status = grib_get_long(gh, "precision", &precision);
+ if ( status == 0 && precision == 1 ) *outDatatype = DATATYPE_FLT32;
+ }
+ else
+ {
+ *outDatatype = DATATYPE_PACK;
+ long bitsPerValue;
+ if ( grib_get_long(gh, "bitsPerValue", &bitsPerValue) == 0 )
+ {
+ if ( bitsPerValue > 0 && bitsPerValue <= 32 ) *outDatatype = (int)bitsPerValue;
+ }
+ }
+ return gh;
+}
- // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
- if ( rindex == nrecs ) continue;
- recID = streamptr->tsteps[tsID].recIDs[rindex];
+typedef enum { CHECKTIME_OK, CHECKTIME_SKIP, CHECKTIME_STOP, CHECKTIME_INCONSISTENT } checkTimeResult;
+static checkTimeResult checkTime(stream_t* streamptr, compvar2_t compVar, const DateTime* verificationTime, const DateTime* expectedVTime) {
+ // First determine whether the current record exists already.
+ int recID = 0;
+ for ( ; recID < streamptr->nrecs; recID++ )
+ {
+ if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
+ }
+ int recordExists = recID < streamptr->nrecs;
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
+ // Then we need to know whether the verification time is consistent.
+ int consistentTime = !memcmp(verificationTime, expectedVTime, sizeof(*verificationTime));
- compVar.param = param;
- compVar.level = rlevel;
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ // Finally, we make a decision.
+ if ( cdiInventoryMode == 1 )
+ {
+ if ( recordExists ) return CHECKTIME_STOP;
+ if ( !consistentTime ) return CHECKTIME_INCONSISTENT;
+ }
+ else
+ {
+ if ( !consistentTime ) return CHECKTIME_STOP;
+ if ( recordExists ) return CHECKTIME_SKIP;
+ }
- if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- Error("Invalid, unsupported or inconsistent record structure!");
- }
+ return CHECKTIME_OK;
+}
- streamptr->tsteps[tsID].records[recID].position = recpos;
- streamptr->tsteps[tsID].records[recID].size = recsize;
+#define gribWarning(text, nrecs, timestep, varname, param, level1, level2) do \
+ { \
+ char paramstr[32]; \
+ cdiParamToString(param, paramstr, sizeof(paramstr)); \
+ Warning("Record %2d (name=%s id=%s lev1=%d lev2=%d) timestep %d: %s", nrecs, varname, paramstr, level1, level2, timestep, text); \
+ } \
+while(0)
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
- }
+int gribapiScanTimestep1(stream_t * streamptr)
+{
+ off_t recpos = 0;
+ void *gribbuffer = NULL;
+ size_t buffersize = 0;
+ DateTime datetime0 = { .date = 10101, .time = 0 };
+ int nrecs_scanned = 0; //Only used for debug output.
+ int warn_time = TRUE;
+ // int warn_numavg = TRUE;
+ int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
+ grib_handle *gh = NULL;
- streamptr->rtsteps++;
+ streamptr->curTsID = 0;
- if ( streamptr->ntsteps != streamptr->rtsteps )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ int tsID = tstepsNewEntry(streamptr);
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
- streamptr->tsteps[tsID-1].next = 1;
- streamptr->tsteps[tsID].position = recpos;
- }
+ if ( tsID != 0 )
+ Error("Internal problem! tstepsNewEntry returns %d", tsID);
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- streamptr->tsteps[tsID].position = recpos;
- }
+ int fileID = streamptr->fileID;
- if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
+ unsigned nrecs = 0;
+ while ( TRUE )
{
- Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
- streamptr->ntsteps = tsID;
- }
+ int level1 = 0, level2 = 0;
+ size_t recsize = (size_t)gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
- return (streamptr->ntsteps);
-}
+ if ( recsize == 0 )
+ {
+ streamptr->ntsteps = 1;
+ break;
+ }
+ ensureBufferSize(recsize, &buffersize, &gribbuffer);
+ size_t readsize = recsize;
+ int rstatus = gribRead(fileID, gribbuffer, &readsize); //Search for next 'GRIB', read the following record, and position file offset after it.
+ if ( rstatus ) break;
-int extInqTimestep(stream_t *streamptr, int tsID)
-{
- int nrecs;
- long ntsteps;
+ int datatype, comptype = 0;
+ long unzipsize;
+ gh = gribapiGetDiskRepresentation(recsize, &buffersize, &gribbuffer, &datatype, &comptype, &unzipsize);
- if ( tsID == 0 && streamptr->rtsteps == 0 )
- Error("Call to cdiInqContents missing!");
+ nrecs_scanned++;
+ GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
- if ( CDI_Debug )
- Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
+ int param = gribapiGetParam(gh);
+ int leveltype1 = -1, leveltype2 = -1, lbounds, level_sf, level_unit;
+ var_tile_t tiles = dummy_tiles;
+ gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
- ntsteps = UNDEFID;
- while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
- ntsteps = extScanTimestep(streamptr);
+ char varname[256];
+ varname[0] = 0;
+ gribapiGetString(gh, "shortName", varname, sizeof(varname));
- if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
- {
- nrecs = 0;
- }
- else
- {
- streamptr->curTsID = tsID;
- nrecs = streamptr->tsteps[tsID].nrecs;
- }
+ int tsteptype = gribapiGetTsteptype(gh);
- return (nrecs);
-}
+ int vdate = 0, vtime = 0;
+ gribapiGetValidityDateTime(gh, &vdate, &vtime);
+ DateTime datetime = { .date = vdate, .time = vtime };
+ /*
+ printf("%d %d %d\n", vdate, vtime, leveltype1);
+ */
+ if ( datetime0.date == 10101 && datetime0.time == 0 )
+ {
+ if( datetimeCmp(datetime, datetime0) || !nrecs ) //Do we really need this condition? I have included it in order not to change the number of times gribapiGetDataDateTime() etc. get called. But if those are sideeffect-free, this condition should be removed.
+ {
+ datetime0 = datetime;
-void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
-{
- int vlistID, fileID;
- int levID, nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int header[4];
- int tsid;
- int recID;
- int i;
- double missval;
- void *extp = streamptr->record->exsep;
+ gribapiGetDataDateTime(gh, &rdate, &rtime);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
+ fcast = gribapiTimeIsFC(gh);
+ if ( fcast ) tunit = gribapiGetTimeUnits(gh);
+ }
+ }
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ if ( nrecs )
+ {
+ checkTimeResult result = checkTime(streamptr, gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles), &datetime, &datetime0);
+ if ( result == CHECKTIME_STOP )
+ {
+ break;
+ }
+ else if ( result == CHECKTIME_SKIP )
+ {
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
+ continue;
+ }
+ else if ( result == CHECKTIME_INCONSISTENT && warn_time )
+ {
+ gribWarning("Inconsistent verification time!", nrecs_scanned, tsID+1, varname, param, level1, level2);
+ warn_time = FALSE;
+ }
+ assert(result == CHECKTIME_OK || result == CHECKTIME_INCONSISTENT);
+ }
+ /*
+ if ( ISEC1_AvgNum )
+ {
+ if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
+ {
+ Message("Change numavg from %d to %d not allowed!",
+ taxis->numavg, ISEC1_AvgNum);
+ warn_numavg = FALSE;
+ }
+ else
+ {
+ taxis->numavg = ISEC1_AvgNum;
+ }
+ }
+ */
+ nrecs++;
- currentfilepos = fileGetPos(fileID);
+ if ( CDI_Debug )
+ {
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ Message("%4u %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
+ nrecs, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
+ }
- for (levID = 0; levID < nlevs; levID++)
- {
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- extRead(fileID, extp);
- extInqHeader(extp, header);
- extInqDataDP(extp, &data[levID*gridsize]);
- }
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ var_tile_t *ptiles = NULL;
+ if ( memcmp(&tiles, &dummy_tiles, sizeof(var_tile_t)) != 0 ) ptiles = &tiles;
+ gribapiAddRecord(streamptr, param, gh, recsize, recpos, datatype, comptype, varname,
+ leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit, ptiles, 1);
- *nmiss = 0;
- if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
- {
- for ( i = 0; i < nlevs*gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
- }
- else
- {
- for ( i = 0; i < 2*nlevs*gridsize; i+=2 )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ grib_handle_delete(gh);
+ gh = NULL;
}
-}
-
-
-void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
-{
- int vlistID, fileID;
- int nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int header[4];
- int tsid;
- int recID;
- int i;
- double missval;
- void *extp = streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d",
- nlevs, gridID, gridsize);
+ if ( gh ) grib_handle_delete(gh);
- currentfilepos = fileGetPos(fileID);
+ streamptr->rtsteps = 1;
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- extRead(fileID, extp);
- extInqHeader(extp, header);
- extInqDataDP(extp, data);
+ if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ cdi_generate_vars(streamptr);
- *nmiss = 0;
- if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
+ int taxisID = -1;
+ if ( fcast )
{
- for ( i = 0; i < gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ taxisID = taxisCreate(TAXIS_RELATIVE);
+ taxis->type = TAXIS_RELATIVE;
+ taxis->rdate = rdate;
+ taxis->rtime = rtime;
+ taxis->unit = tunit;
}
else
{
- for ( i = 0; i < 2*gridsize; i+=2 )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ taxis->type = TAXIS_ABSOLUTE;
}
-}
-
-void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
-{
- int fileID;
- int levID, nlevs, gridID, gridsize;
- int zaxisID;
- double level;
- int header[4];
- int tsID;
- int vlistID;
- int pdis, pcat, pnum;
- extrec_t *extp = (extrec_t*) streamptr->record->exsep;
+ taxis->vdate = (int)datetime0.date;
+ taxis->vtime = (int)datetime0.time;
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
+ int vlistID = streamptr->vlistID;
+ vlistDefTaxis(vlistID, taxisID);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlevs = zaxisInqSize(zaxisID);
+ int nrecords = streamptr->tsteps[0].nallrecs;
+ if ( nrecords < streamptr->tsteps[0].recordSize )
+ {
+ streamptr->tsteps[0].recordSize = nrecords;
+ streamptr->tsteps[0].records =
+ (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords*sizeof(record_t));
+ }
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords*sizeof(int));
+ streamptr->tsteps[0].nrecs = nrecords;
+ for ( int recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[0].recIDs[recID] = recID;
- cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = buffersize;
- header[0] = streamptr->tsteps[tsID].taxis.vdate;
- header[1] = pnum;
- header[3] = gridInqSize(gridID);
+ if ( streamptr->ntsteps == -1 )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
- for ( levID = 0; levID < nlevs; levID++ )
+ if ( streamptr->ntsteps == 1 )
{
- level = zaxisInqLevel(zaxisID, levID);
-
- header[2] = (int) level;
- extDefHeader(extp, header);
- extDefDataDP(extp, &data[levID*gridsize]);
- extWrite(fileID, extp);
+ if ( taxis->vdate == 0 && taxis->vtime == 0 )
+ {
+ streamptr->ntsteps = 0;
+ for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ }
}
+
+ return (0);
}
-void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
+int gribapiScanTimestep2(stream_t * streamptr)
{
- int fileID;
- int gridID;
- int zaxisID;
- double level;
- int header[4];
- int tsID;
- int vlistID;
- int pdis, pcat, pnum;
- extrec_t *extp = (extrec_t*) streamptr->record->exsep;
+ int rstatus = 0;
+ off_t recpos = 0;
+ DateTime datetime0 = { LONG_MIN, LONG_MIN };
+ // int gridID;
+ int recID;
+ // int warn_numavg = TRUE;
+ grib_handle *gh = NULL;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- level = zaxisInqLevel(zaxisID, levID);
+ streamptr->curTsID = 1;
- if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+ int fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int taxisID = vlistInqTaxis(vlistID);
- cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
+ void *gribbuffer = streamptr->record->buffer;
+ size_t buffersize = streamptr->record->buffersize;
- header[0] = streamptr->tsteps[tsID].taxis.vdate;
- header[1] = pnum;
- header[2] = (int) level;
- header[3] = gridInqSize(gridID);
+ int tsID = streamptr->rtsteps;
+ if ( tsID != 1 )
+ Error("Internal problem! unexpected timestep %d", tsID+1);
- extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
- extDefHeader(extp, header);
- extDefDataDP(extp, data);
- extWrite(fileID, extp);
-}
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
-#endif /* HAVE_LIBEXTRA */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#include <stdlib.h>
+ cdi_create_records(streamptr, tsID);
+ int nrecords = streamptr->tsteps[tsID].nallrecs;
+ streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords*sizeof(int));
+ streamptr->tsteps[1].nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[1].recIDs[recID] = -1;
-void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
- const char *container_name)
-{
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position;
+ streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size;
+ }
- int fileID1 = streamptr1->fileID;
- int fileID2 = streamptr2->fileID;
+ int nrecs_scanned = nrecords; //Only used for debug output
+ int rindex = 0;
+ while ( TRUE )
+ {
+ if ( rindex > nrecords ) break;
- int tsID = streamptr1->curTsID;
- int vrecID = streamptr1->tsteps[tsID].curRecID;
- int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
+ size_t recsize = (size_t)gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
+ if ( recsize == 0 )
+ {
+ streamptr->ntsteps = 2;
+ break;
+ }
+ ensureBufferSize(recsize, &buffersize, &gribbuffer);
- if (fileSetPos(fileID1, recpos, SEEK_SET) != 0)
- Error("Cannot seek input file for %s record copy!", container_name);
+ size_t readsize = recsize;
+ rstatus = gribRead(fileID, gribbuffer, &readsize);
+ if ( rstatus ) break;
- char *buffer = (char *) Malloc(recsize);
+ long unzipsize;
+ if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
+ ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
- if (fileRead(fileID1, buffer, recsize) != recsize)
- Error("Failed to read record from %s file for copying!", container_name);
+ nrecs_scanned++;
+ gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
+ GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
- if (fileWrite(fileID2, buffer, recsize) != recsize)
- Error("Failed to write record to %s file when copying!", container_name);
+ int param = gribapiGetParam(gh);
+ int level1 = 0, level2 = 0, leveltype1, leveltype2, lbounds, level_sf, level_unit;
+ var_tile_t tiles = dummy_tiles;
+ gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
- Free(buffer);
-}
+ char varname[256];
+ varname[0] = 0;
+ gribapiGetString(gh, "shortName", varname, sizeof(varname));
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#ifndef _STREAM_GRIBAPI_H
-#define _STREAM_GRIBAPI_H
+ int vdate = 0, vtime = 0;
+ gribapiGetValidityDateTime(gh, &vdate, &vtime);
-int gribapiScanTimestep1(stream_t * streamptr);
-int gribapiScanTimestep2(stream_t * streamptr);
-int gribapiScanTimestep(stream_t * streamptr);
+ if ( rindex == 0 )
+ {
+ if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
+ {
+ taxis->type = TAXIS_RELATIVE;
-int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval, int vlistID, int varID);
+ gribapiGetDataDateTime(gh, &(taxis->rdate), &(taxis->rtime));
-size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
- int ljpeg, void *gribContainer);
+ taxis->unit = gribapiGetTimeUnits(gh);
+ }
+ else
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ }
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
-#endif /* _STREAM_GRIBAPI_H */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
-#endif
+ datetime0.date = vdate;
+ datetime0.time = vtime;
+ }
-#include <stdio.h>
-#include <string.h>
+ int tsteptype = gribapiGetTsteptype(gh);
+ /*
+ if ( ISEC1_AvgNum )
+ {
+ if ( taxis->numavg && warn_numavg &&
+ (taxis->numavg != ISEC1_AvgNum) )
+ {
+ warn_numavg = FALSE;
+ }
+ else
+ {
+ taxis->numavg = ISEC1_AvgNum;
+ }
+ }
+ */
+ DateTime datetime = {
+ .date = vdate,
+ .time = vtime
+ };
+ compvar2_t compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles);
+ for ( recID = 0; recID < nrecords; recID++ )
+ if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
+ if ( recID == nrecords )
+ {
+ gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
+ return (CDI_EUFSTRUCT);
+ }
-int grib1ltypeToZaxisType(int grib_ltype)
-{
- int zaxistype = ZAXIS_GENERIC;
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ if ( cdiInventoryMode == 1 ) break;
+ else
+ {
+ if ( datetimeCmp(datetime, datetime0) != 0 ) break;
- switch ( grib_ltype )
- {
- case GRIB1_LTYPE_SURFACE: { zaxistype = ZAXIS_SURFACE; break; }
- case GRIB1_LTYPE_CLOUD_BASE: { zaxistype = ZAXIS_CLOUD_BASE; break; }
- case GRIB1_LTYPE_CLOUD_TOP: { zaxistype = ZAXIS_CLOUD_TOP; break; }
- case GRIB1_LTYPE_ISOTHERM0: { zaxistype = ZAXIS_ISOTHERM_ZERO; break; }
- case GRIB1_LTYPE_TOA: { zaxistype = ZAXIS_TOA; break; }
- case GRIB1_LTYPE_SEA_BOTTOM: { zaxistype = ZAXIS_SEA_BOTTOM; break; }
- case GRIB1_LTYPE_ATMOSPHERE: { zaxistype = ZAXIS_ATMOSPHERE; break; }
- case GRIB1_LTYPE_MEANSEA: { zaxistype = ZAXIS_MEANSEA; break; }
- case GRIB1_LTYPE_99:
- case GRIB1_LTYPE_ISOBARIC: { zaxistype = ZAXIS_PRESSURE; break; }
- case GRIB1_LTYPE_HEIGHT: { zaxistype = ZAXIS_HEIGHT; break; }
- case GRIB1_LTYPE_ALTITUDE: { zaxistype = ZAXIS_ALTITUDE; break; }
- case GRIB1_LTYPE_SIGMA:
- case GRIB1_LTYPE_SIGMA_LAYER: { zaxistype = ZAXIS_SIGMA; break; }
- case GRIB1_LTYPE_HYBRID:
- case GRIB1_LTYPE_HYBRID_LAYER: { zaxistype = ZAXIS_HYBRID; break; }
- case GRIB1_LTYPE_LANDDEPTH:
- case GRIB1_LTYPE_LANDDEPTH_LAYER: { zaxistype = ZAXIS_DEPTH_BELOW_LAND; break; }
- case GRIB1_LTYPE_ISENTROPIC: { zaxistype = ZAXIS_ISENTROPIC; break; }
- case GRIB1_LTYPE_SEADEPTH: { zaxistype = ZAXIS_DEPTH_BELOW_SEA; break; }
- case GRIB1_LTYPE_LAKE_BOTTOM: { zaxistype = ZAXIS_LAKE_BOTTOM; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM: { zaxistype = ZAXIS_SEDIMENT_BOTTOM; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break; }
- case GRIB1_LTYPE_MIX_LAYER: { zaxistype = ZAXIS_MIX_LAYER; break; }
- }
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
+ continue;
+ }
+ }
- return (zaxistype);
-}
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ if ( CDI_Debug )
+ {
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
+ nrecs_scanned, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
+ }
-int grib2ltypeToZaxisType(int grib_ltype)
-{
- int zaxistype = ZAXIS_GENERIC;
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- switch ( grib_ltype )
- {
- case GRIB2_LTYPE_SURFACE: { zaxistype = ZAXIS_SURFACE; break; }
- case GRIB2_LTYPE_CLOUD_BASE: { zaxistype = ZAXIS_CLOUD_BASE; break; }
- case GRIB2_LTYPE_CLOUD_TOP: { zaxistype = ZAXIS_CLOUD_TOP; break; }
- case GRIB2_LTYPE_ISOTHERM0: { zaxistype = ZAXIS_ISOTHERM_ZERO; break; }
- case GRIB2_LTYPE_TOA: { zaxistype = ZAXIS_TOA; break; }
- case GRIB2_LTYPE_SEA_BOTTOM: { zaxistype = ZAXIS_SEA_BOTTOM; break; }
- case GRIB2_LTYPE_ATMOSPHERE: { zaxistype = ZAXIS_ATMOSPHERE; break; }
- case GRIB2_LTYPE_MEANSEA: { zaxistype = ZAXIS_MEANSEA; break; }
- case GRIB2_LTYPE_ISOBARIC: { zaxistype = ZAXIS_PRESSURE; break; }
- case GRIB2_LTYPE_HEIGHT: { zaxistype = ZAXIS_HEIGHT; break; }
- case GRIB2_LTYPE_ALTITUDE: { zaxistype = ZAXIS_ALTITUDE; break; }
- case GRIB2_LTYPE_SIGMA: { zaxistype = ZAXIS_SIGMA; break; }
- case GRIB2_LTYPE_HYBRID:
- /* case GRIB2_LTYPE_HYBRID_LAYER: */ { zaxistype = ZAXIS_HYBRID; break; }
- case GRIB2_LTYPE_LANDDEPTH:
- /* case GRIB2_LTYPE_LANDDEPTH_LAYER: */ { zaxistype = ZAXIS_DEPTH_BELOW_LAND; break; }
- case GRIB2_LTYPE_ISENTROPIC: { zaxistype = ZAXIS_ISENTROPIC; break; }
- case GRIB2_LTYPE_SNOW: { zaxistype = ZAXIS_SNOW; break; }
- case GRIB2_LTYPE_SEADEPTH: { zaxistype = ZAXIS_DEPTH_BELOW_SEA; break; }
- case GRIB2_LTYPE_LAKE_BOTTOM: { zaxistype = ZAXIS_LAKE_BOTTOM; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM: { zaxistype = ZAXIS_SEDIMENT_BOTTOM; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break; }
- case GRIB2_LTYPE_MIX_LAYER: { zaxistype = ZAXIS_MIX_LAYER; break; }
- case GRIB2_LTYPE_REFERENCE: { zaxistype = ZAXIS_REFERENCE; break; }
+ if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, level1);
+ return (CDI_EUFSTRUCT);
+ }
+
+ streamptr->tsteps[1].records[recID].position = recpos;
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ /*
+ gridID = vlistInqVarGrid(vlistID, varID);
+ if ( gridInqSize(gridID) == 1 && gridInqType(gridID) == GRID_LONLAT )
+ {
+ if ( IS_NOT_EQUAL(gridInqXval(gridID, 0),ISEC2_FirstLon*0.001) ||
+ IS_NOT_EQUAL(gridInqYval(gridID, 0),ISEC2_FirstLat*0.001) )
+ gridChangeType(gridID, GRID_TRAJECTORY);
+ }
+ */
+ if ( tsteptype != vlistInqVarTsteptype(vlistID, varID) )
+ vlistDefVarTsteptype(vlistID, varID, tsteptype);
+
+ grib_handle_delete(gh);
+ gh = NULL;
+
+ rindex++;
}
- return (zaxistype);
-}
+ if ( gh ) grib_handle_delete(gh);
+ int nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ if ( ! streamptr->tsteps[tsID].records[recID].used )
+ {
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ else
+ {
+ nrecs++;
+ }
+ }
+ streamptr->tsteps[tsID].nrecs = nrecs;
-int zaxisTypeToGrib1ltype(int zaxistype)
-{
- int grib_ltype = -1;
+ streamptr->rtsteps = 2;
- switch (zaxistype)
+ if ( streamptr->ntsteps == -1 )
{
- case ZAXIS_SURFACE: { grib_ltype = GRIB1_LTYPE_SURFACE; break; }
- case ZAXIS_MEANSEA: { grib_ltype = GRIB1_LTYPE_MEANSEA; break; }
- case ZAXIS_HEIGHT: { grib_ltype = GRIB1_LTYPE_HEIGHT; break; }
- case ZAXIS_ALTITUDE: { grib_ltype = GRIB1_LTYPE_ALTITUDE; break; }
- case ZAXIS_SIGMA: { grib_ltype = GRIB1_LTYPE_SIGMA; break; }
- case ZAXIS_DEPTH_BELOW_SEA: { grib_ltype = GRIB1_LTYPE_SEADEPTH; break; }
- case ZAXIS_ISENTROPIC: { grib_ltype = GRIB1_LTYPE_ISENTROPIC; break; }
- case ZAXIS_CLOUD_BASE: { grib_ltype = GRIB1_LTYPE_CLOUD_BASE; break; }
- case ZAXIS_CLOUD_TOP: { grib_ltype = GRIB1_LTYPE_CLOUD_TOP; break; }
- case ZAXIS_ISOTHERM_ZERO: { grib_ltype = GRIB1_LTYPE_ISOTHERM0; break; }
- case ZAXIS_TOA: { grib_ltype = GRIB1_LTYPE_TOA; break; }
- case ZAXIS_SEA_BOTTOM: { grib_ltype = GRIB1_LTYPE_SEA_BOTTOM; break; }
- case ZAXIS_LAKE_BOTTOM: { grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TA: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TW: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break; }
- case ZAXIS_MIX_LAYER: { grib_ltype = GRIB1_LTYPE_MIX_LAYER; break; }
- case ZAXIS_ATMOSPHERE: { grib_ltype = GRIB1_LTYPE_ATMOSPHERE; break; }
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
+
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
}
- return (grib_ltype);
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = buffersize;
+
+ return (rstatus);
}
-int zaxisTypeToGrib2ltype(int zaxistype)
+int gribapiScanTimestep(stream_t * streamptr)
{
- int grib_ltype = -1;
+ int vrecID, recID;
+ //int warn_numavg = TRUE;
+ int nrecs = 0;
+ int vlistID = streamptr->vlistID;
- switch (zaxistype)
+ if ( CDI_Debug )
{
- case ZAXIS_SURFACE: { grib_ltype = GRIB2_LTYPE_SURFACE; break; }
- case ZAXIS_MEANSEA: { grib_ltype = GRIB2_LTYPE_MEANSEA; break; }
- case ZAXIS_HEIGHT: { grib_ltype = GRIB2_LTYPE_HEIGHT; break; }
- case ZAXIS_ALTITUDE: { grib_ltype = GRIB2_LTYPE_ALTITUDE; break; }
- case ZAXIS_SIGMA: { grib_ltype = GRIB2_LTYPE_SIGMA; break; }
- case ZAXIS_DEPTH_BELOW_SEA: { grib_ltype = GRIB2_LTYPE_SEADEPTH; break; }
- case ZAXIS_ISENTROPIC: { grib_ltype = GRIB2_LTYPE_ISENTROPIC; break; }
- case ZAXIS_CLOUD_BASE: { grib_ltype = GRIB2_LTYPE_CLOUD_BASE; break; }
- case ZAXIS_CLOUD_TOP: { grib_ltype = GRIB2_LTYPE_CLOUD_TOP; break; }
- case ZAXIS_ISOTHERM_ZERO: { grib_ltype = GRIB2_LTYPE_ISOTHERM0; break; }
- case ZAXIS_TOA: { grib_ltype = GRIB2_LTYPE_TOA; break; }
- case ZAXIS_SEA_BOTTOM: { grib_ltype = GRIB2_LTYPE_SEA_BOTTOM; break; }
- case ZAXIS_LAKE_BOTTOM: { grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TA: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TW: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break; }
- case ZAXIS_MIX_LAYER: { grib_ltype = GRIB2_LTYPE_MIX_LAYER; break; }
- case ZAXIS_ATMOSPHERE: { grib_ltype = GRIB2_LTYPE_ATMOSPHERE; break; }
+ Message("streamID = %d", streamptr->self);
+ Message("cts = %d", streamptr->curTsID);
+ Message("rts = %d", streamptr->rtsteps);
+ Message("nts = %d", streamptr->ntsteps);
}
- return (grib_ltype);
-}
+ int tsID = streamptr->rtsteps;
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ if ( streamptr->tsteps[tsID].recordSize == 0 )
+ {
+ void *gribbuffer = streamptr->record->buffer;
+ size_t buffersize = streamptr->record->buffersize;
-int grbBitsPerValue(int datatype)
-{
- int bitsPerValue = 16;
+ cdi_create_records(streamptr, tsID);
- if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- Error("CDI/GRIB library does not support complex numbers!");
+ nrecs = streamptr->tsteps[1].nrecs;
- if ( datatype != CDI_UNDEFID )
- {
- if ( datatype > 0 && datatype <= 32 )
- bitsPerValue = datatype;
- else if ( datatype == DATATYPE_FLT64 )
- bitsPerValue = 24;
- else
- bitsPerValue = 16;
- }
+ streamptr->tsteps[tsID].nrecs = nrecs;
+ streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs*sizeof(int));
+ for ( recID = 0; recID < nrecs; recID++ )
+ streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
- return (bitsPerValue);
-}
+ int fileID = streamptr->fileID;
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
-/*
-int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
-{
- int status;
+ int nrecs_scanned = streamptr->tsteps[0].nallrecs + streamptr->tsteps[1].nrecs*(tsID-1); //Only used for debug output.
+ int rindex = 0;
+ off_t recpos = 0;
+ DateTime datetime0 = { LONG_MIN, LONG_MIN };
+ grib_handle *gh = NULL;
+ char varname[256];
+ while ( TRUE )
+ {
+ if ( rindex > nrecs ) break;
- status = cgribexInqRecord(streamptr, varID, levelID);
+ size_t recsize = (size_t)gribGetSize(fileID);
+ recpos = fileGetPos(fileID);
+ if ( recsize == 0 )
+ {
+ streamptr->ntsteps = streamptr->rtsteps + 1;
+ break;
+ }
- return (status);
-}
-*/
+ if ( rindex >= nrecs ) break;
-void grbDefRecord(stream_t * streamptr)
-{
- UNUSED(streamptr);
-}
+ ensureBufferSize(recsize, &buffersize, &gribbuffer);
-static
-int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval, int vlistID, int varID)
-{
- int status = 0;
+ size_t readsize = recsize;
+ if (gribRead(fileID, gribbuffer, &readsize))
+ {
+ Warning("Inconsistent timestep %d (GRIB record %d/%d)!", tsID+1, rindex+1,
+ streamptr->tsteps[tsID].recordSize);
+ break;
+ }
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
- {
-#if defined (HAVE_LIBGRIB_API)
- extern int cdiNAdditionalGRIBKeys;
- if ( cdiNAdditionalGRIBKeys > 0 )
- Error("CGRIBEX decode does not support reading of additional GRIB keys!");
-#endif
- status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval);
- }
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval, vlistID, varID);
-#else
- {
- (void)vlistID; (void)varID;
- Error("GRIB_API support not compiled in!");
- }
-#endif
+ long unzipsize;
+ if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
+ ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
+
+ nrecs_scanned++;
+ gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
+ GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
+
+ int param = gribapiGetParam(gh);
+ int level1 = 0, level2 = 0, leveltype1, leveltype2 = -1, lbounds, level_sf, level_unit;
+ var_tile_t tiles = dummy_tiles;
+ gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
+
+ varname[0] = 0;
+ gribapiGetString(gh, "shortName", varname, sizeof(varname));
- return (status);
-}
+ int vdate = 0, vtime = 0;
+ gribapiGetValidityDateTime(gh, &vdate, &vtime);
+ if ( rindex == nrecs ) break;
-static int grbUnzipRecord(unsigned char *gribbuffer, size_t *gribsize)
-{
- int zip = 0;
- int izip;
- size_t igribsize;
- size_t ogribsize;
- long unzipsize;
+ if ( rindex == 0 )
+ {
+ int taxisID = vlistInqTaxis(vlistID);
+ if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
+ {
+ taxis->type = TAXIS_RELATIVE;
- igribsize = *gribsize;
- ogribsize = *gribsize;
+ gribapiGetDataDateTime(gh, &(taxis->rdate), &(taxis->rtime));
- if ( (izip = gribGetZip((long)igribsize, gribbuffer, &unzipsize)) > 0 )
- {
- zip = izip;
- if ( izip == 128 ) /* szip */
- {
- unsigned char *itmpbuffer = NULL;
- size_t itmpbuffersize = 0;
+ taxis->unit = gribapiGetTimeUnits(gh);
+ }
+ else
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ }
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
- if ( unzipsize < (long) igribsize )
- {
- fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
- return (0);
+ datetime0.date = vdate;
+ datetime0.time = vtime;
}
-
- if ( itmpbuffersize < igribsize )
+ /*
+ if ( ISEC1_AvgNum )
{
- itmpbuffersize = igribsize;
- itmpbuffer = (unsigned char *) Realloc(itmpbuffer, itmpbuffersize);
+ if ( taxis->numavg && warn_numavg &&
+ (taxis->numavg != ISEC1_AvgNum) )
+ {
+ warn_numavg = FALSE;
+ }
+ else
+ {
+ taxis->numavg = ISEC1_AvgNum;
+ }
}
+ */
+ DateTime datetime = {
+ .date = vdate,
+ .time = vtime
+ };
- memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
-
- unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-
- ogribsize = (size_t)gribUnzip(gribbuffer, unzipsize, itmpbuffer, (long)igribsize);
+ int tsteptype = gribapiGetTsteptype(gh);
- Free(itmpbuffer);
+ compvar2_t compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles);
- if ( ogribsize <= 0 ) Error("Decompression problem!");
- }
- else
- {
- Error("Decompression for %d not implemented!", izip);
- }
- }
+ for ( vrecID = 0; vrecID < nrecs; vrecID++ )
+ {
+ recID = streamptr->tsteps[1].recIDs[vrecID];
+ if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
+ }
- *gribsize = ogribsize;
+ if ( vrecID == nrecs )
+ {
+ gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- return zip;
-}
+ if ( cdiInventoryMode == 1 )
+ return (CDI_EUFSTRUCT);
+ else
+ continue;
+ }
+ if ( cdiInventoryMode != 1 )
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-void grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
-{
- int filetype = streamptr->filetype;
+ if ( CDI_Debug )
+ gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
+ continue;
+ }
+ }
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int tsID = streamptr->curTsID;
- int vrecID = streamptr->tsteps[tsID].curRecID;
- int recID = streamptr->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
- int varID = streamptr->tsteps[tsID].records[recID].varID;
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
+ if ( CDI_Debug )
+ Message("%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
- streamptr->numvals += gridsize;
+ if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, level1);
+ Error("Invalid, unsupported or inconsistent record structure");
+ }
- fileSetPos(fileID, recpos, SEEK_SET);
+ streamptr->tsteps[tsID].records[recID].position = recpos;
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- if (fileRead(fileID, gribbuffer, recsize) != recsize)
- Error("Failed to read GRIB record");
+ if ( CDI_Debug )
+ Message("%4d %8d %4d %8d %8d %6d", rindex, (int)recpos, param, level1, vdate, vtime);
- double missval = vlistInqVarMissval(vlistID, varID);
+ grib_handle_delete(gh);
+ gh = NULL;
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+ rindex++;
+ }
- grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
-}
+ if ( gh ) grib_handle_delete(gh);
-static
-int grbScanTimestep1(stream_t * streamptr)
-{
- int status = CDI_EUFTYPE;
+ for ( vrecID = 0; vrecID < nrecs; vrecID++ )
+ {
+ recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ if ( ! streamptr->tsteps[tsID].records[recID].used ) break;
+ }
-#if defined (HAVE_LIBCGRIBEX)
- int filetype = streamptr->filetype;
+ if ( vrecID < nrecs )
+ {
+ gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, varname, streamptr->tsteps[tsID].records[recID].param,
+ streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
+ return (CDI_EUFSTRUCT);
+ }
- if ( filetype == FILETYPE_GRB )
- status = cgribexScanTimestep1(streamptr);
-#endif
-#if defined(HAVE_LIBCGRIBEX) && defined (HAVE_LIBGRIB_API)
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- status = gribapiScanTimestep1(streamptr);
-#endif
+ streamptr->rtsteps++;
- return (status);
-}
+ if ( streamptr->ntsteps != streamptr->rtsteps )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
-static
-int grbScanTimestep2(stream_t * streamptr)
-{
- int status = CDI_EUFTYPE;
+ streamptr->tsteps[tsID-1].next = 1;
+ streamptr->tsteps[tsID].position = recpos;
+ }
-#if defined (HAVE_LIBCGRIBEX)
- int filetype = streamptr->filetype;
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ streamptr->tsteps[tsID].position = recpos;
- if ( filetype == FILETYPE_GRB )
- {
- status = cgribexScanTimestep2(streamptr);
+ streamptr->record->buffer = gribbuffer;
+ streamptr->record->buffersize = buffersize;
}
-#endif
-#if defined(HAVE_LIBCGRIBEX) && defined (HAVE_LIBGRIB_API)
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- status = gribapiScanTimestep2(streamptr);
-#endif
-
- return (status);
-}
-
-static
-int grbScanTimestep(stream_t * streamptr)
-{
- int status = CDI_EUFTYPE;
- int filetype;
-
- filetype = streamptr->filetype;
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
+ if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
{
- status = cgribexScanTimestep(streamptr);
+ Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
+ streamptr->ntsteps = tsID;
}
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- status = gribapiScanTimestep(streamptr);
-#else
- Error("Sufficient GRIB support unavailable!");
-#endif
- return (status);
+ return (int)streamptr->ntsteps;
}
+#ifdef gribWarning
+#undef gribWarning
+#endif
-#if defined (HAVE_LIBGRIB)
-int grbInqContents(stream_t * streamptr)
+int gribapiDecode(void *gribbuffer, int gribsize, double *data, long gridsize,
+ int unreduced, int *nmiss, double missval, int vlistID, int varID)
{
- int fileID;
int status = 0;
+ long lpar;
+ long numberOfPoints;
+ size_t datasize;
- fileID = streamptr->fileID;
-
- streamptr->curTsID = 0;
+ UNUSED(vlistID);
+ UNUSED(varID);
- status = grbScanTimestep1(streamptr);
+ if ( unreduced )
+ {
+ static int lwarn = 1;
- if ( status == 0 && streamptr->ntsteps == -1 ) status = grbScanTimestep2(streamptr);
+ if ( lwarn )
+ {
+ lwarn = 0;
+ Warning("Conversion of gaussian reduced grids unsupported!");
+ }
+ }
- fileSetPos(fileID, 0, SEEK_SET);
+ size_t recsize = (size_t)gribsize;
+ grib_handle *gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
+ GRIB_CHECK(my_grib_set_double(gh, "missingValue", missval), 0);
- return (status);
-}
-#endif
+ /* get the size of the values array*/
+ GRIB_CHECK(grib_get_size(gh, "values", &datasize), 0);
+ GRIB_CHECK(grib_get_long(gh, "numberOfPoints", &numberOfPoints), 0);
-int grbInqTimestep(stream_t * streamptr, int tsID)
-{
- int ntsteps, nrecs;
+ // printf("values_size = %d numberOfPoints = %ld\n", datasize, numberOfPoints);
- if ( tsID == 0 && streamptr->rtsteps == 0 )
- Error("Call to cdiInqContents missing!");
+ if ( gridsize != (long) datasize )
+ Error("Internal problem: gridsize(%ld) != datasize(%zu)!", gridsize, datasize);
+ size_t dummy = datasize;
+ GRIB_CHECK(grib_get_double_array(gh, "values", data, &dummy), 0);
- if ( CDI_Debug )
- Message("tsid = %d rtsteps = %d", tsID, streamptr->rtsteps);
+ GRIB_CHECK(grib_get_long(gh, "gridDefinitionTemplateNumber", &lpar), 0);
+ int gridtype = (int) lpar;
- ntsteps = CDI_UNDEFID;
- while ( (tsID + 1) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
+ *nmiss = 0;
+ if ( gridtype < 50 || gridtype > 53 )
{
- ntsteps = grbScanTimestep(streamptr);
- if ( ntsteps == CDI_EUFSTRUCT )
- {
- streamptr->ntsteps = streamptr->rtsteps;
- break;
- }
+ GRIB_CHECK(grib_get_long(gh, "numberOfMissing", &lpar), 0);
+ *nmiss = (int) lpar;
+ // printf("gridtype %d, nmiss %d\n", gridtype, nmiss);
}
- if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
- {
- nrecs = 0;
- }
- else
- {
- streamptr->curTsID = tsID;
- nrecs = streamptr->tsteps[tsID].nrecs;
- }
+ grib_handle_delete(gh);
- return (nrecs);
+ return status;
}
-void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
+static
+void gribapiDefInstitut(grib_handle *gh, int vlistID, int varID)
{
- int filetype = streamptr->filetype;
-
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int tsID = streamptr->curTsID;
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
-
- off_t currentfilepos = fileGetPos(fileID);
+ int instID;
+ if ( vlistInqInstitut(vlistID) != CDI_UNDEFID )
+ instID = vlistInqInstitut(vlistID);
+ else
+ instID = vlistInqVarInstitut(vlistID, varID);
- int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
- int nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- *nmiss = 0;
- for (int levelID = 0; levelID < nlevs; levelID++ )
+ if ( instID != CDI_UNDEFID )
{
- int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
-
- fileSetPos(fileID, recpos, SEEK_SET);
-
- fileRead(fileID, gribbuffer, recsize);
+ long center, subcenter;
+ long center0, subcenter0;
- double missval = vlistInqVarMissval(vlistID, varID);
+ center = institutInqCenter(instID);
+ subcenter = institutInqSubcenter(instID);
- int imiss;
+ GRIB_CHECK(grib_get_long(gh, "centre", ¢er0), 0);
+ GRIB_CHECK(grib_get_long(gh, "subCentre", &subcenter0), 0);
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+ if ( center != center0 )
+ GRIB_CHECK(my_grib_set_long(gh, "centre", center), 0);
+ if ( subcenter != subcenter0 )
+ GRIB_CHECK(my_grib_set_long(gh, "subCentre", subcenter), 0);
+ }
+}
- grbDecode(filetype, gribbuffer, (int)recsize, &data[levelID*gridsize], gridsize,
- streamptr->unreduced, &imiss, missval, vlistID, varID);
+static
+void gribapiDefModel(grib_handle *gh, int vlistID, int varID)
+{
+ int modelID;
- *nmiss += imiss;
- }
+ if ( vlistInqModel(vlistID) != CDI_UNDEFID )
+ modelID = vlistInqModel(vlistID);
+ else
+ modelID = vlistInqVarModel(vlistID, varID);
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ if ( modelID != CDI_UNDEFID )
+ GRIB_CHECK(my_grib_set_long(gh, "generatingProcessIdentifier", modelInqGribID(modelID)), 0);
}
-
-void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss)
+static
+void gribapiDefParam(int editionNumber, grib_handle *gh, int param, const char *name, const char *stdname)
{
- int filetype = streamptr->filetype;
-
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
+ bool ldefined = false;
- int vlistID = streamptr->vlistID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
- int tsID = streamptr->curTsID;
+ int pdis, pcat, pnum;
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
- if ( CDI_Debug )
- Message("gridID = %d gridsize = %d", gridID, gridsize);
+ if ( pnum < 0 )
+ {
+ size_t len;
+ len = strlen(stdname);
+ if ( len )
+ {
+ int status = my_grib_set_string(gh, "cfName", stdname, &len);
+ if ( status == 0 ) ldefined = true;
+ else Warning("grib_api: No match for cfName=%s", stdname);
+ }
- int fileID = streamptr->fileID;
+ if ( ldefined == false )
+ {
+ len = strlen(name);
+ int status = my_grib_set_string(gh, "shortName", name, &len);
+ if ( status == 0 ) ldefined = true;
+ else Warning("grib_api: No match for shortName=%s", name);
+ }
+ }
- off_t currentfilepos = fileGetPos(fileID);
+ if ( ldefined == false )
+ {
+ if ( pnum < 0 ) pnum = -pnum;
- int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
+ static bool lwarn_pnum = true;
+ if ( pnum > 255 && lwarn_pnum )
+ {
+ Warning("Parameter number %d out of range (1-255), set to %d!", pnum, pnum%256);
+ lwarn_pnum = false;
+ pnum = pnum%256;
+ }
+ if ( editionNumber <= 1 )
+ {
+ static bool lwarn_pdis = true;
+ if ( pdis != 255 && lwarn_pdis )
+ {
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ Warning("Can't convert GRIB2 parameter ID (%s) to GRIB1, set to %d.%d!", paramstr, pnum, pcat);
+ lwarn_pdis = false;
+ }
- int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+ GRIB_CHECK(my_grib_set_long(gh, "table2Version", pcat), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "indicatorOfParameter", pnum), 0);
+ }
+ else
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "discipline", pdis), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "parameterCategory", pcat), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "parameterNumber", pnum), 0);
+ }
+ }
- if ( recsize == 0 )
- Error("Internal problem! Recordsize is zero for record %d at timestep %d",
- recID+1, tsID+1);
+ // printf("param: %d.%d.%d %s\n", pnum, pcat, pdis, name);
+}
- fileSetPos(fileID, recpos, SEEK_SET);
+static
+int getTimeunitFactor(int timeunit)
+{
+ int factor = 1;
- fileRead(fileID, gribbuffer, recsize);
+ switch (timeunit)
+ {
+ case TUNIT_SECOND: factor = 1; break;
+ case TUNIT_MINUTE: factor = 60; break;
+ case TUNIT_HOUR: factor = 3600; break;
+ case TUNIT_3HOURS: factor = 10800; break;
+ case TUNIT_6HOURS: factor = 21600; break;
+ case TUNIT_12HOURS: factor = 43200; break;
+ case TUNIT_DAY: factor = 86400; break;
+ default: factor = 3600; break;
+ }
- double missval = vlistInqVarMissval(vlistID, varID);
+ return (factor);
+}
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+static
+void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
+{
+ long unitsOfTime;
- grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
+ switch (timeunit)
+ {
+ case TUNIT_SECOND: unitsOfTime = 13; break;
+ case TUNIT_MINUTE: unitsOfTime = 0; break;
+ case TUNIT_HOUR: unitsOfTime = 1; break;
+ case TUNIT_3HOURS: unitsOfTime = 10; break;
+ case TUNIT_6HOURS: unitsOfTime = 11; break;
+ case TUNIT_12HOURS: unitsOfTime = 12; break;
+ case TUNIT_DAY: unitsOfTime = 2; break;
+ default: unitsOfTime = 1; break;
+ }
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ if ( !gcinit )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
+ if ( proDefTempNum == 8 || proDefTempNum == 11 )
+ GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+ }
}
static
-size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int date, int time, int tsteptype, int numavg,
- size_t datasize, const double *data, int nmiss, unsigned char **gribbuffer,
- int comptype, void *gribContainer)
+int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
{
- size_t nbytes = 0;
+ long proDefTempNum = 0;
+ size_t len = 64;
+ const char *stepType;
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
+ static struct {
+ long productionTemplate;
+ const char sname[8];
+ } ts_tab[] = {
+ [TSTEP_INSTANT] = { 0, "instant" },
+ [TSTEP_AVG] = { 8, "avg" },
+ [TSTEP_ACCUM] = { 8, "accum" },
+ [TSTEP_MAX] = { 8, "max" },
+ [TSTEP_MIN] = { 8, "min" },
+ [TSTEP_DIFF] = { 8, "diff" },
+ [TSTEP_RMS] = { 8, "rms" },
+ [TSTEP_SD] = { 8, "sd" },
+ [TSTEP_COV] = { 8, "cov" },
+ [TSTEP_RATIO] = { 8, "ratio" }
+ };
+ if (tsteptype >= TSTEP_INSTANT && tsteptype <= TSTEP_RATIO)
{
- size_t gribbuffersize = datasize*4+3000;
- *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
-
- nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
- date, time, tsteptype, numavg,
- (long)datasize, data, nmiss, *gribbuffer, gribbuffersize);
+ stepType = ts_tab[tsteptype].sname;
+ proDefTempNum = ts_tab[tsteptype].productionTemplate;
}
else
-#endif
-#ifdef HAVE_LIBGRIB_API
{
- if ( memtype == MEMTYPE_FLOAT ) Error("gribapiEncode() not implemented for memtype float!");
+ stepType = "instant";
+ proDefTempNum = 0;
+ }
- size_t gribbuffersize;
- nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
- date, time, tsteptype, numavg,
- (long)datasize, data, nmiss, gribbuffer, &gribbuffersize,
- comptype, gribContainer);
+ if ( typeOfGeneratingProcess == 4 )
+ {
+ if ( proDefTempNum == 8 ) proDefTempNum = 11;
+ else proDefTempNum = 1;
}
-#else
- Error("GRIB_API support not compiled in!");
- (void)gribContainer;
- (void)comptype;
-#endif
+ if ( productDefinitionTemplate != -1 ) proDefTempNum = productDefinitionTemplate;
+
+ if ( !gcinit )
+ {
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "productDefinitionTemplateNumber", proDefTempNum), 0);
+ len = strlen(stepType);
+ GRIB_CHECK(my_grib_set_string(gh, "stepType", stepType, &len), 0);
+ }
- return (nbytes);
+ return ((int)proDefTempNum);
}
static
-size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
+void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
{
- size_t nbytes = 0;
- unsigned char *buffer;
- size_t buffersize;
- static int lszip_warn = 1;
-
- buffersize = gribbuffersize + 1000; /* compressed record can be greater than source record */
- buffer = (unsigned char *) Malloc(buffersize);
-
- /* memcpy(buffer, gribbuffer, gribbuffersize); */
-
- if ( filetype == FILETYPE_GRB )
- {
- nbytes = (size_t)gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
- }
- else
- {
- if ( lszip_warn ) Warning("Szip compression of GRIB2 records not implemented!");
- lszip_warn = 0;
- nbytes = gribbuffersize;
- }
+ (void ) gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
- Free(buffer);
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 0), 0);
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
- return (nbytes);
+ if ( date == 0 ) date = 10101;
+ gribapiSetDataDateTime(gh, date, time);
}
-
-void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+static
+int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rtime, int vdate, int vtime,
+ int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int timeunit, int calendar, int gcinit)
{
- size_t nwrite;
- int fileID;
- int gridID;
- int zaxisID;
- unsigned char *gribbuffer = NULL;
- int tsID;
- int vlistID;
- int date, time;
- int tsteptype;
- int numavg = 0;
- size_t nbytes;
- int filetype;
- void *gc = NULL;
-
- filetype = streamptr->filetype;
- fileID = streamptr->fileID;
- vlistID = streamptr->vlistID;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int status = -1;
+ int year, month, day, hour, minute, second;
+ int julday1, secofday1, julday2, secofday2, days, secs;
+ long startStep = 0, endStep;
- int comptype = streamptr->comptype;
+ cdiDecodeDate(rdate, &year, &month, &day);
+ cdiDecodeTime(rtime, &hour, &minute, &second);
+ encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday1, &secofday1);
- tsID = streamptr->curTsID;
- date = streamptr->tsteps[tsID].taxis.vdate;
- time = streamptr->tsteps[tsID].taxis.vtime;
- if ( vlistInqVarTimave(vlistID, varID) )
- numavg = streamptr->tsteps[tsID].taxis.numavg;
+ if ( vdate == 0 && vtime == 0 ) { vdate = rdate; vtime = rtime; }
- if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+ cdiDecodeDate(vdate, &year, &month, &day);
+ cdiDecodeTime(vtime, &hour, &minute, &second);
+ encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
- size_t datasize = (size_t)gridInqSize(gridID);
- /*
- gribbuffersize = datasize*4+3000;
- gribbuffer = (unsigned char *) Malloc(gribbuffersize);
- */
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
- {
- }
- else
-#endif
- {
-#if defined (GRIBCONTAINER2D)
- gribContainer_t **gribContainers = (gribContainer_t **) streamptr->gribContainers;
- gc = (void *) &gribContainers[varID][levelID];
-#else
- gribContainer_t *gribContainers = (gribContainer_t *) streamptr->gribContainers;
- gc = (void *) &gribContainers[varID];
-#endif
- }
+ (void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
- if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
+ int factor = getTimeunitFactor(timeunit);
- if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
+ if ( !(int) fmod(days*86400.0 + secs, factor) )
{
- static int ljpeg_warn = 1;
- if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
- ljpeg_warn = 0;
- }
-
- nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
- datasize, (const double*) data, nmiss, &gribbuffer, comptype, gc);
+ int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
- if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
- nbytes = grbSzip(filetype, gribbuffer, nbytes);
+ gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
- {
- size_t (*myFileWrite)(int fileID, const void *restrict buffer,
- size_t len, int tsID)
- = (size_t (*)(int, const void *restrict, size_t, int))
- namespaceSwitchGet(NSSWITCH_FILE_WRITE).func;
- nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
- }
+ endStep = (int) ((days*86400.0 + secs)/factor);
- if ( nwrite != nbytes )
- {
- perror(__func__);
- Error("Failed to write GRIB slice!");
- }
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 1), 0);
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
- if ( gribbuffer ) Free(gribbuffer);
-}
+ if ( rdate == 0 ) rdate = 10101;
+ gribapiSetDataDateTime(gh, rdate, rtime);
+ // printf(">>>>> tsteptype %d startStep %ld endStep %ld\n", tsteptype, startStep, endStep);
-void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
-{
- int vlistID, gridID, zaxisID, levelID, nlevs;
- int gridsize;
+ // Product Definition Template Number: defined in GRIB_API file 4.0.table
+ // point in time products:
+ if ( (proDefTempNum >= 0 && proDefTempNum <= 7) ||
+ proDefTempNum == 55 || proDefTempNum == 40055 ) // Tile
+ startStep = endStep;
- vlistID = streamptr->vlistID;
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlevs = zaxisInqSize(zaxisID);
+ if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "forecastTime", startStep), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "endStep", endStep), 0);
- for ( levelID = 0; levelID < nlevs; levelID++ )
- {
- if ( memtype == MEMTYPE_FLOAT )
- grb_write_var_slice(streamptr, varID, levelID, memtype, ((float*)data)+levelID*gridsize, nmiss);
- else
- grb_write_var_slice(streamptr, varID, levelID, memtype, ((double*)data)+levelID*gridsize, nmiss);
+ status = 0;
}
-}
+ return (status);
+}
-void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
+static
+void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOfGeneratingProcess, grib_handle *gh,
+ int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
{
- int filetype = streamptr1->filetype;
-
- int fileID1 = streamptr1->fileID;
- int fileID2 = streamptr2->fileID;
-
- int tsID = streamptr1->curTsID;
- int vrecID = streamptr1->tsteps[tsID].curRecID;
- int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
-
- fileSetPos(fileID1, recpos, SEEK_SET);
-
- /* round up recsize to next multiple of 8 */
- size_t gribbuffersize = ((recsize + 7U) & ~7U);
+ int taxistype = -1;
- unsigned char *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
+ UNUSED(numavg);
- if (fileRead(fileID1, gribbuffer, recsize) != recsize)
- Error("Could not read GRIB record for copying!");
+ if ( taxisID != -1 ) taxistype = taxisInqType(taxisID);
- size_t nbytes = recsize;
+ if ( typeOfGeneratingProcess == 196 )
+ {
+ vdate = 10101;
+ vtime = 0;
+ taxistype = TAXIS_ABSOLUTE;
+ }
+ /*
+ else if ( typeOfGeneratingProcess == 9 )
+ {
+ }
+ */
- if ( filetype == FILETYPE_GRB )
+ if ( taxistype == TAXIS_RELATIVE )
{
- long unzipsize;
- int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
+ int status;
+ int calendar = taxisInqCalendar(taxisID);
+ int rdate = taxisInqRdate(taxisID);
+ int rtime = taxisInqRtime(taxisID);
+ int timeunit = taxisInqTunit(taxisID);
- if ( izip == 0 )
- if ( streamptr2->comptype == COMPRESS_SZIP )
- nbytes = grbSzip(filetype, gribbuffer, nbytes);
- }
+ status = gribapiDefDateTimeRel(editionNumber, gh, rdate, rtime, vdate, vtime,
+ productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, timeunit, calendar, gcinit);
- while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
+ if ( status != 0 ) taxistype = TAXIS_ABSOLUTE;
+ }
- size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
- if ( nwrite != nbytes )
+ if ( taxistype == TAXIS_ABSOLUTE )
{
- perror(__func__);
- Error("Could not write record for copying!");
+ gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
}
-
- Free(gribbuffer);
}
-
-void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
+static
+void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
{
- int varID, levelID;
-
- varID = streamptr->record->varID;
- levelID = streamptr->record->levelID;
-
- grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-}
+ int status;
+ static short lwarn = TRUE;
+ UNUSED(nmiss);
-void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
+ int gridtype = gridInqType(gridID);
+ int gridsize = gridInqSize(gridID);
- stream_check_ptr(__func__, streamptr);
+ if ( editionNumber <= 1 )
+ if ( gridtype == GRID_GME || gridtype == GRID_UNSTRUCTURED )
+ gridtype = -1;
- int filetype = streamptr->filetype;
+ if ( gridtype == GRID_GENERIC )
+ {
+ int xsize = gridInqXsize(gridID);
+ int ysize = gridInqYsize(gridID);
- if ( filetype == FILETYPE_GRB )
+ if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
+ ysize == 96 || ysize == 160 || ysize == 192 ||
+ ysize == 240 || ysize == 320 || ysize == 384 ||
+ ysize == 480 || ysize == 768 ) &&
+ (xsize == 2*ysize || xsize == 1) )
+ {
+ gridtype = GRID_GAUSSIAN;
+ gridChangeType(gridID, gridtype);
+ }
+ else if ( gridsize == 1 )
+ {
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
+ }
+ else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+ {
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
+ }
+ }
+ else if ( gridtype == GRID_CURVILINEAR )
{
- int tsID = streamptr->curTsID;
- int vrecID = streamptr->tsteps[tsID].curRecID;
- int recID = streamptr->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- int zip = streamptr->tsteps[tsID].records[recID].zip;
+ if ( lwarn && gridsize > 1 )
+ {
+ lwarn = FALSE;
+ Warning("Curvilinear grids are unsupported in GRIB format! Created wrong GDS!");
+ }
+ gridtype = GRID_LONLAT;
+ }
- void *gribbuffer = streamptr->record->buffer;
- size_t gribbuffersize = streamptr->record->buffersize;
+ if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+ {
+ if ( editionNumber != 2 || lieee ) { comptype = 0; }
- if ( zip > 0 )
- Error("Compressed GRIB records unsupported!");
- else
- grib_info_for_grads(recpos, (long)gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
+ if ( comptype )
+ {
+ if ( comptype == COMPRESS_JPEG && gridsize > 1 )
+ {
+ static const char mesg[] = "grid_jpeg";
+ size_t len = sizeof (mesg) - 1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
+ {
+ static const char mesg[] = "grid_ccsds";
+ size_t len = sizeof (mesg) - 1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ else
+ {
+ static const char mesg[] = "grid_simple";
+ size_t len = sizeof (mesg) - 1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ }
}
-}
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#ifndef _SUBTYPE_H
-#define _SUBTYPE_H
+ if ( gcinit ) return;
-enum {
- /* subtype attributes wrt. TILES */
- SUBTYPE_ATT_TILEINDEX = 0,
- SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS = 1,
- SUBTYPE_ATT_TILE_CLASSIFICATION = 2,
- SUBTYPE_ATT_NUMBER_OF_TILES = 3,
- SUBTYPE_ATT_NUMBER_OF_ATTR = 4,
- SUBTYPE_ATT_TILEATTRIBUTE = 5,
-/* No. of different constants in the enumeration
- "subtype_attributes" */
- nSubtypeAttributes
-};
+ switch (gridtype)
+ {
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ case GRID_GAUSSIAN_REDUCED:
+ case GRID_TRAJECTORY:
+ {
+ double xfirst = 0, xlast = 0, xinc = 0;
+ double yfirst = 0, ylast = 0, yinc = 0;
+ double latIncr;
+
+ if ( gridtype == GRID_GAUSSIAN )
+ {
+ static const char mesg[] = "regular_gg";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ }
+ else if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ static const char mesg[] = "reduced_gg";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ }
+ else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+ {
+ static const char mesg[] = "rotated_ll";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ }
+ else
+ {
+ static const char mesg[] = "regular_ll";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ }
+ int nlon = gridInqXsize(gridID);
+ int nlat = gridInqYsize(gridID);
-/* Literal constants corresponding to the different constants of the
- enumeration "subtype_attributes". */
-extern const char * const cdiSubtypeAttributeName[];
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ int *rowlon, i;
+ long *pl = NULL;
-/* Data type specifying an attribute of a subtype (for example an
- attribute of a set of TILES) or an attribute of a subtype entry
- (for example an attribute of a single TILE). This data type is part
- of a linked list. */
-struct subtype_attr_t {
- int key, val; /* key/value pair */
- struct subtype_attr_t* next; /* next element in linked list */
-};
+ nlon = 0;
+ rowlon = (int *) Malloc((size_t)nlat*sizeof(int));
+ pl = (long *) Malloc((size_t)nlat*sizeof(long));
+ gridInqRowlon(gridID, rowlon);
+ for ( i = 0; i < nlat; ++i ) pl[i] = rowlon[i];
-/* Data type specifying a single entry of a subtype, for example a
- single TILE in a set of TILES. */
-struct subtype_entry_t {
- int self; /* list entry index (0,...,nentries-1) */
- struct subtype_entry_t *next; /* next node in linked list */
+ // GRIB_CHECK(my_grib_set_long_array(gh, "pl", pl, nlat), 0);
- /* linked list with attributes for this subtype entry, ordered by its key values*/
- struct subtype_attr_t *atts;
-};
+ Free(pl);
+ Free(rowlon);
+ }
+ else
+ {
+ if ( nlon == 0 )
+ {
+ nlon = 1;
+ }
+ else
+ {
+ xfirst = gridInqXval(gridID, 0);
+ xlast = gridInqXval(gridID, nlon-1);
+ xinc = gridInqXinc(gridID);
+ }
+ }
+ if ( nlat == 0 )
+ {
+ nlat = 1;
+ }
+ else
+ {
+ yfirst = gridInqYval(gridID, 0);
+ ylast = gridInqYval(gridID, nlat-1);
+ yinc = gridInqYinc(gridID);
+ }
-/* Data type specifying a variable subtype, for example a list of
- TILES. This can be interpreted as an additional axis like the
- vertical axis. */
-typedef struct {
- int self; /* resource handler ID */
- int subtype; /* subtype kind: TILES, ... */
- int nentries; /* counter: total no. of entries in list */
+ GRIB_CHECK(my_grib_set_long(gh, "Ni", nlon), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "Nj", nlat), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", xfirst), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "longitudeOfLastGridPointInDegrees", xlast), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", yfirst), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "latitudeOfLastGridPointInDegrees", ylast), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "iDirectionIncrementInDegrees", xinc), 0);
- struct subtype_entry_t globals; /* global attributes */
+ {
+ long jscan = 0;
+ if ( yfirst < ylast ) jscan = 1;
+ GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jscan), 0);
+ }
+ /*
+ if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON )
+ ISEC2_LonIncr = 0;
+ */
+ if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
+ {
+ int np = gridInqNP(gridID);
+ if ( np == 0 ) np = nlat/2;
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", np), 0);
+ }
+ else
+ {
+ latIncr = yinc;
+ if ( latIncr < 0 ) latIncr = -latIncr;
+ GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", latIncr), 0);
+ /*
+ if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON )
+ ISEC2_LatIncr = 0;
+ */
+ }
+ /*
+ if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
+ if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr;
- /* list of subtype entries, e.g. the list of tiles, ordered by entry->self. */
- struct subtype_entry_t *entries;
- /* currently active subtype, e.g. GRIB2 tile index (for example for
- stream/vlist accesses): */
- int active_subtype_index;
-} subtype_t;
+ if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
+ if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
+ if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
+ ISEC2_ResFlag = 0;
+ else
+ ISEC2_ResFlag = 128;
+ */
+ if ( gridIsRotated(gridID) )
+ {
+ double xpole = gridInqXpole(gridID);
+ double ypole = gridInqYpole(gridID);
+ double angle = gridInqAngle(gridID);
+ /* change from north to south pole */
+ if ( fabs(ypole) > 0 ) ypole = -ypole;
+ xpole = xpole + 180;
+ if ( fabs(angle) > 0 ) angle = -angle;
+ GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees", ypole), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0);
+ }
+ /* East -> West */
+ //if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
+ /* South -> North */
+ //if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
-/* prototypes: allocation and destruction */
-void subtypeAllocate(subtype_t **subtype_ptr2, int subtype);
-int subtypePush(subtype_t *subtype_ptr);
-void subtypeDestroyPtr(void *ptr);
-void subtypeDuplicate(subtype_t *subtype_ptr, subtype_t **dst);
-struct subtype_entry_t* subtypeEntryInsert(subtype_t* head);
+ if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
-/* prototypes: accessing global attributes */
-void subtypePrint(int subtypeID);
-void subtypePrintPtr(subtype_t* subtype_ptr);
-void subtypeDefGlobalDataP(subtype_t *subtype_ptr, int key, int val);
-void subtypeDefGlobalData(int subtypeID, int key, int val);
-int subtypeGetGlobalData(int subtypeID, int key);
-int subtypeGetGlobalDataP(subtype_t *subtype_ptr, int key);
-int subtypeComparePtr(int s1_ID, subtype_t *s2);
+ if ( lieee )
+ {
+ static const char mesg[] = "grid_ieee";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-/* prototypes: accessing subtype entries */
-void subtypeDefEntryDataP(struct subtype_entry_t *subtype_entry_ptr, int key, int val);
+ if ( datatype == DATATYPE_FLT64 )
+ GRIB_CHECK(my_grib_set_long(gh, "precision", 2), 0);
+ else
+ GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
+ }
+ else
+ {
+ if ( comptype == COMPRESS_JPEG && gridsize > 1 )
+ {
+ static const char mesg[] = "grid_jpeg";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
+ {
+ static const char mesg[] = "grid_ccsds";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ else
+ {
+ static const char mesg[] = "grid_simple";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ }
+ break;
+ }
+ case GRID_LCC:
+ {
+ double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
+ int projflag, scanflag;
-/* prototypes: tile implementations */
-void tilesetInsertP(subtype_t *s1, subtype_t *s2);
+ int xsize = gridInqXsize(gridID);
+ int ysize = gridInqYsize(gridID);
-/* Construct a new subtype for a tile set. If a corresponding subtype
- * already exists, then we return this subtype ID instead. */
-int vlistDefTileSubtype(int vlistID, subtype_t *tiles);
+ gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
+ &projflag, &scanflag);
-/* Insert a trivial one-tile-subtype */
-int vlistInsertTrivialTileSubtype(int vlistID);
+ static const char mesg[] = "lambert";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "Nx", xsize), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "Ny", ysize), 0);
-#endif
+ /* FIXME: lround should probably be round here */
+ GRIB_CHECK(my_grib_set_double(gh, "DxInMetres", (double)lround(xincm)), 0);
+ /* FIXME: lround should probably be round here */
+ GRIB_CHECK(my_grib_set_double(gh, "DyInMetres", (double)lround(yincm)), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", originLon), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", originLat), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "LoVInDegrees", lonParY), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "Latin1InDegrees", lat1), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "Latin2InDegrees", lat2), 0);
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
-#endif
+ if ( editionNumber <= 1 )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "projectionCenterFlag", projflag), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "scanningMode", scanflag), 0);
+ }
-#include <limits.h>
-#include <stdio.h>
+ break;
+ }
+ case GRID_SPECTRAL:
+ {
+ int trunc = gridInqTrunc(gridID);
+ static const char mesg[] = "sh";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "J", trunc), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "K", trunc), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "M", trunc), 0);
-#if defined (HAVE_LIBGRIB_API)
+ // GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
+ /*
+ if ( lieee )
+ {
+ printf("spectral_ieee\n");
+ if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize, 0);
+ static const char mesg[] = "spectral_ieee";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
+ else */ if ( gridInqComplexPacking(gridID) )
+ {
+ if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize), 0);
+ static const char mesg[] = "spectral_complex";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-# include <grib_api.h>
-#endif
+ GRIB_CHECK(my_grib_set_long(gh, "JS", 20), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "KS", 20), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "MS", 20), 0);
+ }
+ else
+ {
+ static const char mesg[] = "spectral_simple";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
-extern int cdiInventoryMode;
+ break;
+ }
+ case GRID_GME:
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_GME), 0);
-#if defined (HAVE_LIBGRIB_API)
-static const var_tile_t dummy_tiles = { -1, -1, -1, -1, -1, -1 };
-#endif
+ GRIB_CHECK(my_grib_set_long(gh, "nd", gridInqGMEnd(gridID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "Ni", gridInqGMEni(gridID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "n2", gridInqGMEni2(gridID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "n3", gridInqGMEni3(gridID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "latitudeOfThePolePoint", 90000000), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "longitudeOfThePolePoint", 0), 0);
-typedef struct {
- int param;
- int level1;
- int level2;
- int ltype;
- int tsteptype;
- char name[32];
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridsize), 0);
- var_tile_t tiles;
+ if ( comptype == COMPRESS_SZIP )
+ {
+ static const char mesg[] = "grid_ccsds";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
-} compvar2_t;
+ break;
+ }
+ case GRID_UNSTRUCTURED:
+ {
+ static int warning = 1;
+ status = my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_UNSTRUCTURED);
+ if ( status != 0 && warning )
+ {
+ warning = 0;
+ Warning("Can't write reference grid!");
+ Warning("gridDefinitionTemplateNumber %d not found (grib2/template.3.%d.def)!",
+ GRIB2_GTYPE_UNSTRUCTURED, GRIB2_GTYPE_UNSTRUCTURED);
+ }
+ else
+ {
+ unsigned char uuid[CDI_UUID_SIZE];
+ int position = gridInqPosition(gridID);
+ int number = gridInqNumber(gridID);
+ if ( position < 0 ) position = 0;
+ if ( number < 0 ) number = 0;
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfGridUsed", number), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfGridInReference", position), 0);
+ size_t len = CDI_UUID_SIZE;
+ gridInqUUID(gridID, uuid);
+ if (grib_set_bytes(gh, "uuidOfHGrid", uuid, &len) != 0)
+ Warning("Can't write UUID!");
+ }
-#if defined (HAVE_LIBGRIB_API)
-static
-int gribapiGetZaxisType(long editionNumber, int grib_ltype)
-{
- int zaxistype = ZAXIS_GENERIC;
+ if ( comptype == COMPRESS_SZIP )
+ {
+ static const char mesg[] = "grid_ccsds";
+ size_t len = sizeof (mesg) -1;
+ GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ }
- if ( editionNumber <= 1 )
- {
- zaxistype = grib1ltypeToZaxisType(grib_ltype);
- }
- else
- {
- zaxistype = grib2ltypeToZaxisType(grib_ltype);
+ break;
+ }
+ default:
+ {
+ Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+ break;
+ }
}
-
- return (zaxistype);
}
static
-int getTimeunits(long unitsOfTime)
+void getLevelFactor(double level, long *factor, long *out_scaled_value)
{
- int timeunits = -1;
+ double scaled_value = level;
+ /* FIXME: lround might be better here */
+ long iscaled_value = (long) round(scaled_value);
+ long i;
- switch (unitsOfTime)
+ const double eps = 1.e-8;
+ for ( i=0; (fabs(scaled_value - (double) iscaled_value) >= eps) && i < 7; i++ )
{
- case 13: timeunits = TUNIT_SECOND; break;
- case 0: timeunits = TUNIT_MINUTE; break;
- case 1: timeunits = TUNIT_HOUR; break;
- case 10: timeunits = TUNIT_3HOURS; break;
- case 11: timeunits = TUNIT_6HOURS; break;
- case 12: timeunits = TUNIT_12HOURS; break;
- case 2: timeunits = TUNIT_DAY; break;
- default: timeunits = TUNIT_HOUR; break;
+ scaled_value *= 10.;
+ /* FIXME: lround might be better here */
+ iscaled_value = (long)round(scaled_value);
}
- return (timeunits);
+ (*factor) = i;
+ (*out_scaled_value) = iscaled_value;
}
static
-double timeunit_factor(int tu1, int tu2)
+void gribapiDefLevelType(grib_handle *gh, int gcinit, const char *keyname, long leveltype)
{
- double factor = 1;
-
- if ( tu2 == TUNIT_HOUR )
- {
- switch (tu1)
- {
- case TUNIT_SECOND: factor = 3600; break;
- case TUNIT_MINUTE: factor = 60; break;
- case TUNIT_HOUR: factor = 1; break;
- case TUNIT_3HOURS: factor = 1./3; break;
- case TUNIT_6HOURS: factor = 1./6; break;
- case TUNIT_12HOURS: factor = 1./12; break;
- case TUNIT_DAY: factor = 1./24; break;
- }
- }
-
- return (factor);
+ if ( !gcinit ) GRIB_CHECK(my_grib_set_long(gh, keyname, leveltype), 0);
}
static
-int gribapiGetTimeUnits(grib_handle *gh)
+void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, int lbounds, double level, double dlevel1, double dlevel2)
{
- int timeunits = -1;
- long unitsOfTime = -1;
-
- grib_get_long(gh, "indicatorOfUnitOfTimeRange", &unitsOfTime);
-
- GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
+ long scaled_level;
+ long factor;
- timeunits = getTimeunits(unitsOfTime);
+ gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype1);
+ if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype2);
- return (timeunits);
-}
+ if ( !lbounds ) dlevel1 = level;
-static
-void gribapiGetSteps(grib_handle *gh, int timeunits, int *startStep, int *endStep)
-{
- int timeunits2 = timeunits;
- long unitsOfTime;
- int status = grib_get_long(gh, "stepUnits", &unitsOfTime);
- if ( status == 0 ) timeunits2 = getTimeunits(unitsOfTime);
- //timeunits2 = gribapiGetTimeUnits(gh);
+ getLevelFactor(dlevel1, &factor, &scaled_level);
+ GRIB_CHECK(my_grib_set_long(gh, "scaleFactorOfFirstFixedSurface", factor), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "scaledValueOfFirstFixedSurface", scaled_level), 0);
- long lpar;
- status = grib_get_long(gh, "forecastTime", &lpar);
- if ( status == 0 ) *startStep = (int) lpar;
- else
+ if ( lbounds )
{
- status = grib_get_long(gh, "startStep", &lpar);
- if ( status == 0 )
- *startStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
+ getLevelFactor(dlevel2, &factor, &scaled_level);
+ GRIB_CHECK(my_grib_set_long(gh, "scaleFactorOfSecondFixedSurface", factor), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "scaledValueOfSecondFixedSurface", scaled_level), 0);
}
-
- *endStep = *startStep;
- status = grib_get_long(gh, "endStep", &lpar);
- if ( status == 0 )
- *endStep = (int) (((double)lpar * timeunit_factor(timeunits, timeunits2)) + 0.5);
- // printf("%d %d %d %d %d %g\n", *startStep, *endStep, lpar, timeunits, timeunits2, timeunit_factor(timeunits, timeunits2));
}
static
-void gribapiGetDataDateTime(grib_handle *gh, int *datadate, int *datatime)
-{
- long lpar;
-
- GRIB_CHECK(grib_get_long(gh, "dataDate", &lpar), 0);
- *datadate = (int) lpar;
- GRIB_CHECK(grib_get_long(gh, "dataTime", &lpar), 0); //FIXME: This looses the seconds in GRIB2 files.
- *datatime = (int) lpar*100;
-}
-
-static
-void gribapiSetDataDateTime(grib_handle *gh, int datadate, int datatime)
+void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit, int proddef_template_num)
{
- GRIB_CHECK(my_grib_set_long(gh, "dataDate", datadate), 0);
- GRIB_CHECK(my_grib_set_long(gh, "dataTime", datatime/100), 0);
-}
+ int lbounds = 0;
+ double dlevel1 = 0, dlevel2 = 0;
-static
-int gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
-{
- int rdate, rtime;
- int timeUnits, startStep = 0, endStep;
- int tstepRange = 0;
- int range;
- long sigofrtime = 3;
+ int zaxistype = zaxisInqType(zaxisID);
+ int ltype = zaxisInqLtype(zaxisID);
+ int ltype2 = zaxisInqLtype2(zaxisID);
+ double level = zaxisInqLevel(zaxisID, levelID);
- if ( gribEditionNumber(gh) > 1 )
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
{
- GRIB_CHECK(grib_get_long(gh, "significanceOfReferenceTime", &sigofrtime), 0);
+ lbounds = 1;
+ dlevel1 = zaxisInqLbound(zaxisID, levelID);
+ dlevel2 = zaxisInqUbound(zaxisID, levelID);
}
else
{
- GRIB_CHECK(grib_get_long(gh, "timeRangeIndicator", &sigofrtime), 0);
+ dlevel1 = level;
+ dlevel2 = 0;
}
- if ( sigofrtime == 3 ) //XXX: This looks like a bug to me, because timeRangeIndicator == 3 does not seem to have the same meaning as significanceOfReferenceTime == 3. I would recommend replacing this condition with `if(!gribapiTimeIsFC())`.
+ if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
{
- gribapiGetDataDateTime(gh, vdate, vtime);
+ Message("Changed zaxis type from %s to %s", zaxisNamePtr(zaxistype), zaxisNamePtr(ZAXIS_PRESSURE));
+ zaxistype = ZAXIS_PRESSURE;
+ zaxisChangeType(zaxisID, zaxistype);
+ zaxisDefUnits(zaxisID, "Pa");
}
- else
- {
- gribapiGetDataDateTime(gh, &rdate, &rtime);
-
- timeUnits = gribapiGetTimeUnits(gh);
- gribapiGetSteps(gh, timeUnits, &startStep, &endStep);
- range = endStep - startStep;
-
- if ( range > 0 )
- {
- if ( startStep == 0 ) tstepRange = -1;
- else tstepRange = 1;
- }
+ int grib2ltype = zaxisTypeToGrib2ltype(zaxistype);
+ switch (zaxistype)
+ {
+ case ZAXIS_SURFACE:
+ case ZAXIS_MEANSEA:
+ case ZAXIS_HEIGHT:
+ case ZAXIS_ALTITUDE:
+ case ZAXIS_SIGMA:
+ case ZAXIS_DEPTH_BELOW_SEA:
+ case ZAXIS_ISENTROPIC:
{
- static int lprint = TRUE;
- extern int grib_calendar;
- int ryear, rmonth, rday, rhour, rminute, rsecond;
- int julday, secofday;
- int64_t time_period = endStep;
- int64_t addsec;
-
- cdiDecodeDate(rdate, &ryear, &rmonth, &rday);
- cdiDecodeTime(rtime, &rhour, &rminute, &rsecond);
-
- if ( rday > 0 )
+ if ( zaxistype == ZAXIS_HEIGHT )
{
- encode_caldaysec(grib_calendar, ryear, rmonth, rday, rhour, rminute, rsecond, &julday, &secofday);
-
- addsec = 0;
- switch ( timeUnits )
+ double sf = 1;
+ char units[128];
+ zaxisInqUnits(zaxisID, units);
+ if ( units[1] == 'm' && !units[2] )
{
- case TUNIT_SECOND: addsec = time_period; break;
- case TUNIT_MINUTE: addsec = 60 * time_period; break;
- case TUNIT_HOUR: addsec = 3600 * time_period; break;
- case TUNIT_3HOURS: addsec = 10800 * time_period; break;
- case TUNIT_6HOURS: addsec = 21600 * time_period; break;
- case TUNIT_12HOURS: addsec = 43200 * time_period; break;
- case TUNIT_DAY: addsec = 86400 * time_period; break;
- default:
- if ( lprint )
- {
- Warning("Time unit %d unsupported", timeUnits);
- lprint = FALSE;
- }
- break;
+ if ( units[0] == 'c' ) sf = 0.01;
+ else if ( units[0] == 'd' ) sf = 0.1;
+ else if ( units[0] == 'k' ) sf = 1000;
+ }
+ if ( IS_NOT_EQUAL(sf, 1) )
+ {
+ level *= sf;
+ dlevel1 *= sf;
+ dlevel2 *= sf;
}
-
- julday_add_seconds(addsec, &julday, &secofday);
-
- decode_caldaysec(grib_calendar, julday, secofday, &ryear, &rmonth, &rday, &rhour, &rminute, &rsecond);
}
- *vdate = cdiEncodeDate(ryear, rmonth, rday);
- *vtime = cdiEncodeTime(rhour, rminute, rsecond);
- }
- }
-
- return (tstepRange);
-}
-
-static
-void grib1GetLevel(grib_handle *gh, int *leveltype, int *lbounds, int *level1, int *level2)
-{
- *leveltype = 0;
- *lbounds = 0;
- *level1 = 0;
- *level2 = 0;
-
- long lpar;
- if(!grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar)) //1 byte
- {
- *leveltype = (int) lpar;
-
- switch (*leveltype)
- {
- case GRIB1_LTYPE_SIGMA_LAYER:
- case GRIB1_LTYPE_HYBRID_LAYER:
- case GRIB1_LTYPE_LANDDEPTH_LAYER:
- { *lbounds = 1; break; }
- }
-
- if ( *lbounds )
- {
- GRIB_CHECK(grib_get_long(gh, "topLevel", &lpar), 0); //1 byte
- *level1 = (int)lpar;
- GRIB_CHECK(grib_get_long(gh, "bottomLevel", &lpar), 0); //1 byte
- *level2 = (int)lpar;
- }
- else
- {
- double dlevel;
- GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0); //2 byte
- if ( *leveltype == 100 ) dlevel *= 100;
- if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;
- if ( *leveltype == GRIB1_LTYPE_99 ) *leveltype = 100;
-
- *level1 = (int) dlevel;
- *level2 = 0;
- }
- }
-}
-
-static
-double grib2ScaleFactor(long factor)
-{
- switch(factor)
- {
- case GRIB_MISSING_LONG: return 1;
- case 0: return 1;
- case 1: return 0.1;
- case 2: return 0.01;
- case 3: return 0.001;
- case 4: return 0.0001;
- case 5: return 0.00001;
- case 6: return 0.000001;
- case 7: return 0.0000001;
- case 8: return 0.00000001;
- case 9: return 0.000000001;
- default: return 0;
- }
-}
-
-static
-int calcLevel(int level_sf, long factor, long level)
-{
- double result = 0;
- if(level != GRIB_MISSING_LONG) result = (double)level*grib2ScaleFactor(factor);
- if(level_sf) result *= level_sf;
- return (int)result;
-}
-
-static
-void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1,
- int *level2, int *level_sf, int *level_unit)
-{
- int status;
- long lpar;
- long factor;
-
- *leveltype1 = 0;
- *leveltype2 = -1;
- *lbounds = 0;
- *level1 = 0;
- *level2 = 0;
- *level_sf = 0;
- *level_unit = 0;
-
- status = grib_get_long(gh, "typeOfFirstFixedSurface", &lpar); //1 byte
- if ( status == 0 )
- {
- long llevel;
-
- *leveltype1 = (int) lpar;
-
- status = grib_get_long(gh, "typeOfSecondFixedSurface", &lpar); //1 byte
- /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */
- if ( status == 0 ) *leveltype2 = (int)lpar;
-
- if ( *leveltype1 != 255 && *leveltype2 != 255 && *leveltype2 > 0 ) *lbounds = 1;
- switch(*leveltype1)
- {
- case GRIB2_LTYPE_REFERENCE:
- if(*leveltype2 == 1) *lbounds = 0;
- break;
-
- case GRIB2_LTYPE_LANDDEPTH:
- *level_sf = 1000;
- *level_unit = CDI_UNIT_M;
- break;
+ if ( editionNumber <= 1 )
+ {
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
+ GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
+ }
+ else
+ {
+ /* PRODUCT DEFINITION TEMPLATE NUMBER 32:
- case GRIB2_LTYPE_ISOBARIC:
- *level_sf = 1000;
- *level_unit = CDI_UNIT_PA;
- break;
+ "Analysis or forecast at a horizontal level or in a horizontal layer at a point
+ in time for simulate (synthetic) satellite data"
- case GRIB2_LTYPE_SIGMA:
- *level_sf = 1000;
- *level_unit = 0;
- break;
- }
+ The key/value pairs that are set in "grib2DefLevel" do not exist for this template.
+ */
+ if ( proddef_template_num != 32 )
+ grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
+ }
- GRIB_CHECK(grib_get_long(gh, "scaleFactorOfFirstFixedSurface", &factor), 0); //1 byte
- GRIB_CHECK(grib_get_long(gh, "scaledValueOfFirstFixedSurface", &llevel), 0); //4 byte
- *level1 = calcLevel(*level_sf, factor, llevel);
+ break;
+ }
+ case ZAXIS_CLOUD_BASE:
+ case ZAXIS_CLOUD_TOP:
+ case ZAXIS_ISOTHERM_ZERO:
+ case ZAXIS_TOA:
+ case ZAXIS_SEA_BOTTOM:
+ case ZAXIS_LAKE_BOTTOM:
+ case ZAXIS_SEDIMENT_BOTTOM:
+ case ZAXIS_SEDIMENT_BOTTOM_TA:
+ case ZAXIS_SEDIMENT_BOTTOM_TW:
+ case ZAXIS_MIX_LAYER:
+ case ZAXIS_ATMOSPHERE:
+ {
+ if ( editionNumber <= 1 )
+ {
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
+ if ( lbounds )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
+ }
+ else
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
+ }
+ }
+ else
+ {
+ grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
+ }
- if ( *lbounds )
- {
- GRIB_CHECK(grib_get_long(gh, "scaleFactorOfSecondFixedSurface", &factor), 0); //1 byte
- GRIB_CHECK(grib_get_long(gh, "scaledValueOfSecondFixedSurface", &llevel), 0); //4 byte
- *level2 = calcLevel(*level_sf, factor, llevel);
- }
- }
-}
+ break;
+ }
+ case ZAXIS_HYBRID:
+ case ZAXIS_HYBRID_HALF:
+ {
+ if ( editionNumber <= 1 )
+ {
+ if ( lbounds )
+ {
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID_LAYER);
+ GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
+ }
+ else
+ {
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID);
+ GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
+ }
+ }
+ else
+ {
+ grib2DefLevel(gh, gcinit, GRIB2_LTYPE_HYBRID, GRIB2_LTYPE_HYBRID, lbounds, level, dlevel1, dlevel2);
+ }
-static
-void gribGetLevel(grib_handle *gh, int* leveltype1, int* leveltype2, int* lbounds, int* level1, int* level2, int* level_sf, int* level_unit, var_tile_t* tiles)
-{
- if ( gribEditionNumber(gh) <= 1 )
- {
- grib1GetLevel(gh, leveltype1, lbounds, level1, level2);
- *leveltype2 = -1;
- *level_sf = 0;
- *level_unit = 0;
- }
- else
- {
- grib2GetLevel(gh, leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit);
+ if ( !gcinit )
+ {
+ int vctsize = zaxisInqVctSize(zaxisID);
+ if ( vctsize > 0 )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
+ GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
+ }
+ }
- /* read in tiles attributes (if there are any) */
- tiles->tileindex = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], -1);
- tiles->totalno_of_tileattr_pairs = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS], -1);
- tiles->tileClassification = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILE_CLASSIFICATION], -1);
- tiles->numberOfTiles = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_NUMBER_OF_TILES], -1);
- tiles->numberOfAttributes = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_NUMBER_OF_ATTR], -1);
- tiles->attribute = (int)gribGetLongDefault(gh, cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], -1);
- }
-}
+ break;
+ }
+ case ZAXIS_PRESSURE:
+ {
+ double dum;
+ char units[128];
-static
-void gribapiGetString(grib_handle *gh, const char *key, char *string, size_t length)
-{
- string[0] = 0;
+ if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level);
- int ret = grib_get_string(gh, key, string, &length);
- if (ret != 0)
- {
- fprintf(stderr, "grib_get_string(gh, \"%s\", ...) failed!\n", key);
- GRIB_CHECK(ret, 0);
- }
- if ( length == 8 && memcmp(string, "unknown", length) == 0 ) string[0] = 0;
- else if ( length == 2 && memcmp(string, "~", length) == 0 ) string[0] = 0;
-}
+ zaxisInqUnits(zaxisID, units);
+ if ( memcmp(units, "Pa", 2) != 0 )
+ {
+ level *= 100;
+ dlevel1 *= 100;
+ dlevel2 *= 100;
+ }
-#if defined (HAVE_LIBGRIB_API)
-static
-void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
- size_t recsize, off_t position, int datatype, int comptype, const char *varname,
- int leveltype1, int leveltype2, int lbounds, int level1, int level2, int level_sf, int level_unit,
- const var_tile_t *tiles, int lread_additional_keys)
-{
- int varID;
- int levelID = 0;
- grid_t grid;
- long lpar;
- int status;
- char stdname[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
- size_t vlen;
- long ens_index = 0, ens_count = 0, ens_forecast_type = 0;
+ if ( editionNumber <= 1 )
+ {
+ long leveltype = GRIB1_LTYPE_ISOBARIC;
- int vlistID = streamptr->vlistID;
- int tsID = streamptr->curTsID;
- int recID = recordNewEntry(streamptr, tsID);
- record_t *record = &streamptr->tsteps[tsID].records[recID];
+ if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
+ leveltype = GRIB1_LTYPE_99;
+ else
+ level /= 100;
- int tsteptype = gribapiGetTsteptype(gh);
- // numavg = ISEC1_AvgNum;
- int numavg = 0;
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", leveltype);
+ GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+ }
+ else
+ {
+ if ( ltype2 == -1 ) ltype2 = GRIB2_LTYPE_ISOBARIC;
+ grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, ltype2, lbounds, level, dlevel1, dlevel2);
+ }
- // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype1);
+ break;
+ }
+ case ZAXIS_SNOW:
+ {
+ if ( editionNumber <= 1 )
+ ; // not available
+ else
+ {
+ grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
+ }
- (*record).size = recsize;
- (*record).position = position;
- (*record).param = param;
- (*record).ilevel = level1;
- (*record).ilevel2 = level2;
- (*record).ltype = leveltype1;
- (*record).tsteptype = tsteptype;
- if ( tiles ) (*record).tiles = *tiles;
- else (*record).tiles = dummy_tiles;
+ break;
+ }
+ case ZAXIS_DEPTH_BELOW_LAND:
+ {
+ char units[128];
- //FIXME: This may leave the variable name unterminated (which is the behavior that I found in the code).
- // I don't know precisely how this field is used, so I did not change this behavior to avoid regressions,
- // but I think that it would be better to at least add a line
- //
- // record->varname[sizeof(record->varname) - 1] = 0;`
- //
- // after the `strncpy()` call.
- //
- // I would consider using strdup() (that requires POSIX-2008 compliance, though), or a similar homebrew approach.
- // I. e. kick the fixed size array and allocate enough space, whatever that may be.
- strncpy(record->varname, varname, sizeof(record->varname));
+ zaxisInqUnits(zaxisID, units);
- gribapiGetGrid(gh, &grid);
+ if ( editionNumber <= 1 )
+ {
+ double scalefactor;
+ if ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.1;
+ else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 1; // cm
+ else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 10;
+ else scalefactor = 100;
- int gridID = varDefGrid(vlistID, &grid, 0);
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_LANDDEPTH);
+ GRIB_CHECK(my_grib_set_double(gh, "level", level*scalefactor), 0);
+ }
+ else
+ {
+ double scalefactor;
+ if ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.001;
+ else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 0.01;
+ else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 0.1;
+ else scalefactor = 1; // meter
- int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1);
+ level *= scalefactor;
+ dlevel1 *= scalefactor;
+ dlevel2 *= scalefactor;
- switch (zaxistype)
- {
- case ZAXIS_HYBRID:
- case ZAXIS_HYBRID_HALF:
- {
- size_t vctsize;
- size_t dummy;
- double *vctptr;
+ grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
+ }
- GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
- /* FIXME: assert(lpar >= 0) */
- vctsize = (size_t)lpar;
- if ( vctsize > 0 )
- {
- vctptr = (double *) Malloc(vctsize*sizeof(double));
- dummy = vctsize;
- GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
- varDefVCT(vctsize, vctptr);
- Free(vctptr);
- }
- break;
+ break;
}
case ZAXIS_REFERENCE:
{
unsigned char uuid[CDI_UUID_SIZE];
- long ltmp;
- long nhlev, nvgrid;
- GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
- if ( lpar != 6 )
+ if ( !gcinit )
{
- fprintf(stderr, "Warning ...\n");
+ GRIB_CHECK(my_grib_set_long(gh, "genVertHeightCoords", 1), 0);
}
- GRIB_CHECK(grib_get_long(gh, "nlev", <mp), 0);
- nhlev = ltmp;
- GRIB_CHECK(grib_get_long(gh, "numberOfVGridUsed", <mp), 0);
- nvgrid = ltmp;
- size_t len = (size_t)CDI_UUID_SIZE;
- memset(uuid, 0, CDI_UUID_SIZE);
- GRIB_CHECK(grib_get_bytes(gh, "uuidOfVGrid", uuid, &len), 0);
- varDefZAxisReference((int) nhlev, (int) nvgrid, uuid);
- break;
- }
- }
- // if ( datatype > 32 ) datatype = DATATYPE_PACK32;
- if ( datatype < 0 ) datatype = DATATYPE_PACK;
+ if ( lbounds )
+ {
+ if ( editionNumber <= 1 )
+ ; // not available
+ else
+ {
+ int number = zaxisInqNumber(zaxisID);
+ gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
+ gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", GRIB2_LTYPE_REFERENCE);
+ GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
+ size_t len = CDI_UUID_SIZE;
+ zaxisInqUUID(zaxisID, uuid);
+ if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
+ {
+ Warning("Can't write UUID!");
+ }
+ GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
+ }
+ }
+ else
+ {
+ if ( editionNumber <= 1 )
+ ; // not available
+ else
+ {
+ int number = zaxisInqNumber(zaxisID);
+ gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
+ GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
+ size_t len = CDI_UUID_SIZE;
+ zaxisInqUUID(zaxisID, uuid);
+ if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
+ {
+ Warning("Can't write UUID!");
+ }
+ GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+ }
+ }
- stdname[0] = 0;
- longname[0] = 0;
- units[0] = 0;
+ break;
+ }
+ case ZAXIS_GENERIC:
+ {
+ if ( editionNumber <= 1 )
+ gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", ltype);
+ else
+ gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", ltype);
- if ( varname[0] != 0 )
- {
- vlen = CDI_MAX_NAME;
- gribapiGetString(gh, "name", longname, vlen);
- vlen = CDI_MAX_NAME;
- gribapiGetString(gh, "units", units, vlen);
+ GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+ break;
+ }
+ default:
{
- vlen = CDI_MAX_NAME;
- status = grib_get_string(gh, "cfName", stdname, &vlen);
- if ( status != 0 || vlen <= 1 ) stdname[0] = 0;
- else if ( strncmp(stdname, "unknown", 7) == 0 ) stdname[0] = 0;
+ Error("Unsupported zaxis type: %s", zaxisNamePtr(zaxistype));
+ break;
}
}
- // fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units);
+}
- /* add the previously read record data to the (intermediate) list of records */
- int tile_index = -1;
- varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, level_sf, level_unit,
- datatype, &varID, &levelID, tsteptype, numavg, leveltype1, leveltype2,
- varname, stdname, longname, units, tiles, &tile_index);
+/* #define GRIBAPIENCODETEST 1 */
- record->varID = (short)varID;
- record->levelID = (short)levelID;
+size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const double *data, int nmiss, void **gribbuffer, size_t *gribbuffersize,
+ int comptype, void *gribContainer)
+{
+ size_t recsize = 0;
+ void *dummy = NULL;
+ int lieee = FALSE;
+ /* int ensID, ensCount, forecast_type; *//* Ensemble Data */
+ int typeOfGeneratingProcess;
+ int productDefinitionTemplate;
+ long bitsPerValue;
+ long editionNumber = 2;
+ char name[256];
+ char stdname[256];
+ gribContainer_t *gc = (gribContainer_t *) gribContainer;
+ // extern unsigned char _grib_template_GRIB2[];
- varDefCompType(varID, comptype);
+ int param = vlistInqVarParam(vlistID, varID);
+ int datatype = vlistInqVarDatatype(vlistID, varID);
+ typeOfGeneratingProcess = vlistInqVarTypeOfGeneratingProcess(vlistID, varID);
+ productDefinitionTemplate = vlistInqVarProductDefinitionTemplate(vlistID, varID);
- /*
- Get the ensemble Info from the grib-2 Tables and update the intermediate datastructure.
- Further update to the "vlist" is handled in the same way as for GRIB-1 by "cdi_generate_vars"
- */
- status = grib_get_long(gh, "typeOfEnsembleForecast", &ens_forecast_type );
- if ( status == 0 )
+ vlistInqVarName(vlistID, varID, name);
+ vlistInqVarStdname(vlistID, varID, stdname);
+
+#if defined(GRIBAPIENCODETEST)
+ grib_handle *gh = (grib_handle *) gribHandleNew(editionNumber);
+#else
+ grib_handle *gh = (struct grib_handle *)gc->gribHandle;
+#endif
+ GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
+
+ if ( editionNumber == 2 )
{
- GRIB_CHECK(grib_get_long(gh, "numberOfForecastsInEnsemble", &ens_count ), 0);
- GRIB_CHECK(grib_get_long(gh, "perturbationNumber", &ens_index ), 0);
+ if ( typeOfGeneratingProcess == -1 ) typeOfGeneratingProcess = 0;
+ if ( ! gc->init ) GRIB_CHECK(my_grib_set_long(gh, "typeOfGeneratingProcess", typeOfGeneratingProcess), 0);
}
- if ( ens_index > 0 )
- varDefEnsembleInfo(varID, (int)ens_index, (int)ens_count, (int)ens_forecast_type);
+ /*
+ if( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "typeOfEnsembleForecast", forecast_type ), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfForecastsInEnsemble", ensCount ), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "perturbationNumber", ensID ), 0);
+ }
+ */
- long typeOfGeneratingProcess = 0;
- status = grib_get_long(gh, "typeOfGeneratingProcess", &typeOfGeneratingProcess);
- if ( status == 0 )
- varDefTypeOfGeneratingProcess(varID, (int) typeOfGeneratingProcess);
+ gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
- long productDefinitionTemplate = 0;
- status = grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate);
- if ( status == 0 )
- varDefProductDefinitionTemplate(varID, (int) productDefinitionTemplate);
+ if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
+ if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
- int i;
- long lval;
- double dval;
+ if ( ! gc->init ) gribapiDefParam((int)editionNumber, gh, param, name, stdname);
- if (lread_additional_keys)
- for ( i = 0; i < cdiNAdditionalGRIBKeys; i++ )
- {
- /* note: if the key is not defined, we do not throw an error! */
- if ( grib_get_long(gh, cdiAdditionalGRIBKeys[i], &lval) == 0 )
- varDefOptGribInt(varID, tile_index, lval, cdiAdditionalGRIBKeys[i]);
- if ( grib_get_double(gh, cdiAdditionalGRIBKeys[i], &dval) == 0 )
- varDefOptGribDbl(varID, tile_index, dval, cdiAdditionalGRIBKeys[i]);
- }
+ if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = TRUE;
- if ( varInqInst(varID) == CDI_UNDEFID )
+ /* bitsPerValue have to be defined before call to DefGrid (complex packing) */
+ // if ( lieee == FALSE )
{
- long center, subcenter;
- int instID;
- GRIB_CHECK(grib_get_long(gh, "centre", ¢er), 0);
- GRIB_CHECK(grib_get_long(gh, "subCentre", &subcenter), 0);
- instID = institutInq((int)center, (int)subcenter, NULL, NULL);
- if ( instID == CDI_UNDEFID )
- instID = institutDef((int)center, (int)subcenter, NULL, NULL);
- varDefInst(varID, instID);
+ bitsPerValue = grbBitsPerValue(datatype);
+ GRIB_CHECK(my_grib_set_long(gh, "bitsPerValue", bitsPerValue), 0);
}
- if ( varInqModel(varID) == CDI_UNDEFID )
- {
- int modelID;
- long processID;
- status = grib_get_long(gh, "generatingProcessIdentifier", &processID);
- if ( status == 0 )
- {
- /* FIXME: assert(processID >= INT_MIN && processID <= INT_MAX) */
- modelID = modelInq(varInqInst(varID), (int)processID, NULL);
- if ( modelID == CDI_UNDEFID )
- modelID = modelDef(varInqInst(varID), (int)processID, NULL);
- varDefModel(varID, modelID);
- }
- }
+ gribapiDefGrid((int)editionNumber, gh, gridID, comptype, lieee, datatype, nmiss, gc->init);
- if ( varInqTable(varID) == CDI_UNDEFID )
- {
- int pdis, pcat, pnum;
+ gribapiDefLevel((int)editionNumber, gh, param, zaxisID, levelID, gc->init, productDefinitionTemplate);
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ vlist_t *vlistptr = vlist_to_pointer(vlistID);
+ //if (!gc->init)
+ {
+ int ret = 0;
- if ( pdis == 255 )
- {
- int tableID;
- int tabnum = pcat;
+ /* NOTE: Optional key/value pairs: Note that we do not distinguish
+ * between tiles here! */
- tableID = tableInq(varInqModel(varID), tabnum, NULL);
+ for ( int i=0; i<vlistptr->vars[varID].opt_grib_nentries; i++ )
+ {
+ if ( vlistptr->vars[varID].opt_grib_kvpair[i].update )
+ {
+ //DR: Fix for multi-level fields (otherwise only the 1st level is correct)
+ if ( zaxisInqSize(zaxisID)==(levelID+1) )
+ vlistptr->vars[varID].opt_grib_kvpair[i].update = FALSE;
- if ( tableID == CDI_UNDEFID )
- tableID = tableDef(varInqModel(varID), tabnum, NULL);
- varDefTable(varID, tableID);
- }
+ if (vlistptr->vars[varID].opt_grib_kvpair[i].data_type == t_double)
+ {
+ if ( CDI_Debug )
+ Message("key \"%s\" : double value = %g\n",
+ vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
+ vlistptr->vars[varID].opt_grib_kvpair[i].dbl_val);
+ my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
+ vlistptr->vars[varID].opt_grib_kvpair[i].dbl_val);
+ GRIB_CHECK(ret, 0);
+ }
+ if (vlistptr->vars[varID].opt_grib_kvpair[i].data_type == t_int)
+ {
+ if ( CDI_Debug )
+ Message("key \"%s\" : integer value = %d\n",
+ vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
+ vlistptr->vars[varID].opt_grib_kvpair[i].int_val);
+ my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
+ (long) vlistptr->vars[varID].opt_grib_kvpair[i].int_val);
+ GRIB_CHECK(ret, 0);
+ }
+ }
+ }
+ }
+
+ if ( nmiss > 0 )
+ {
+ GRIB_CHECK(my_grib_set_long(gh, "bitmapPresent", 1), 0);
+ GRIB_CHECK(my_grib_set_double(gh, "missingValue", vlistInqVarMissval(vlistID, varID)), 0);
}
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
+ GRIB_CHECK(grib_set_double_array(gh, "values", data, (size_t)datasize), 0);
- if ( CDI_Debug )
- Message("varID = %d param = %d zaxistype = %d gridID = %d levelID = %d",
- varID, param, zaxistype, gridID, levelID);
-}
-#endif
+ /* get the size of coded message */
+ GRIB_CHECK(grib_get_message(gh, (const void **)&dummy, &recsize), 0);
+ recsize += 512; /* add some space for possible filling */
+ *gribbuffersize = recsize;
+ *gribbuffer = Malloc(*gribbuffersize);
-static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype,
- int tsteptype, char *name, var_tile_t tiles_data)
-{
- compvar2_t compVar;
- size_t maxlen = sizeof(compVar.name);
- size_t len = strlen(name);
- if ( len > maxlen ) len = maxlen;
+ /* get a copy of the coded message */
+ GRIB_CHECK(grib_get_message_copy(gh, *gribbuffer, &recsize), 0);
- compVar.param = param;
- compVar.level1 = level1;
- compVar.level2 = level2;
- compVar.ltype = leveltype;
- compVar.tsteptype = tsteptype;
- memset(compVar.name, 0, maxlen);
- memcpy(compVar.name, name, len);
- compVar.tiles = tiles_data;
+#if defined(GRIBAPIENCODETEST)
+ gribHandleDelete(gh);
+#endif
- return (compVar);
+ gc->init = TRUE;
+
+ return recsize;
}
#endif
-#ifdef HAVE_LIBGRIB_API
-static
-int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
-{
- compvar2_t compVar0;
- compVar0.param = record.param;
- compVar0.level1 = record.ilevel;
- compVar0.level2 = record.ilevel2;
- compVar0.ltype = record.ltype;
- compVar0.tsteptype = record.tsteptype;
- memcpy(compVar0.name, record.varname, sizeof(compVar.name));
-
- if ( flag == 0 )
- {
- if ( compVar0.tsteptype == TSTEP_INSTANT && compVar.tsteptype == TSTEP_INSTANT3 ) compVar0.tsteptype = TSTEP_INSTANT3;
- if ( compVar0.tsteptype == TSTEP_INSTANT3 && compVar.tsteptype == TSTEP_INSTANT ) compVar0.tsteptype = TSTEP_INSTANT;
- }
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
+#endif
- compVar0.tiles = record.tiles;
- int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
- return (rstatus);
-}
+void streamDefHistory(int streamID, int length, const char *history)
+{
+#ifdef HAVE_LIBNETCDF
+ stream_t *streamptr = stream_to_pointer(streamID);
-static void ensureBufferSize(size_t requiredSize, size_t* curSize, unsigned char **buffer) {
- if ( *curSize < requiredSize )
+ if ( streamptr->filetype == FILETYPE_NC ||
+ streamptr->filetype == FILETYPE_NC2 ||
+ streamptr->filetype == FILETYPE_NC4 ||
+ streamptr->filetype == FILETYPE_NC4C )
{
- *curSize = requiredSize;
- *buffer = (unsigned char *) Realloc(*buffer, *curSize);
+ char *histstring;
+ size_t len;
+ if ( history )
+ {
+ len = strlen(history);
+ if ( len )
+ {
+ /* FIXME: what's the point of strdupx? Why not use
+ * history argument directly? */
+ histstring = strdupx(history);
+ cdfDefHistory(streamptr, length, histstring);
+ Free(histstring);
+ }
+ }
}
+#else
+ (void)streamID; (void)length; (void)history;
+#endif
}
-static
-grib_handle* gribapiGetDiskRepresentation(size_t recsize, size_t* buffersize, unsigned char** gribbuffer, int* outDatatype, int* outCompressionType, long* outUnzipsize)
-{
- int lieee = FALSE;
-
- grib_handle* gh = grib_handle_new_from_message(NULL, (void *) *gribbuffer, recsize);
- if(gribEditionNumber(gh) > 1)
- {
- size_t len = 256;
- char typeOfPacking[256];
- if ( grib_get_string(gh, "packingType", typeOfPacking, &len) == 0 )
- {
- // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking);
- if ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = COMPRESS_JPEG;
- else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = COMPRESS_SZIP;
- else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = TRUE;
- }
- }
- else
- {
- if( gribGetZip((long)recsize, *gribbuffer, outUnzipsize) > 0 )
- {
- *outCompressionType = COMPRESS_SZIP;
- ensureBufferSize((size_t)*outUnzipsize + 100, buffersize, gribbuffer);
- }
- else
- {
- *outCompressionType = COMPRESS_NONE;
- }
- }
+int streamInqHistorySize(int streamID)
+{
+ int size = 0;
+#ifdef HAVE_LIBNETCDF
+ stream_t *streamptr = stream_to_pointer(streamID);
- if ( lieee )
- {
- *outDatatype = DATATYPE_FLT64;
- long precision;
- int status = grib_get_long(gh, "precision", &precision);
- if ( status == 0 && precision == 1 ) *outDatatype = DATATYPE_FLT32;
- }
- else
+ if ( streamptr->filetype == FILETYPE_NC ||
+ streamptr->filetype == FILETYPE_NC2 ||
+ streamptr->filetype == FILETYPE_NC4 ||
+ streamptr->filetype == FILETYPE_NC4C )
{
- *outDatatype = DATATYPE_PACK;
- long bitsPerValue;
- if ( grib_get_long(gh, "bitsPerValue", &bitsPerValue) == 0 )
- {
- if ( bitsPerValue > 0 && bitsPerValue <= 32 ) *outDatatype = (int)bitsPerValue;
- }
+ size = cdfInqHistorySize(streamptr);
}
- return gh;
-}
+#else
+ (void)streamID;
#endif
+ return (size);
+}
-#if defined (HAVE_LIBGRIB_API)
-typedef enum { CHECKTIME_OK, CHECKTIME_SKIP, CHECKTIME_STOP, CHECKTIME_INCONSISTENT } checkTimeResult;
-static checkTimeResult checkTime(stream_t* streamptr, compvar2_t compVar, const DateTime* verificationTime, const DateTime* expectedVTime) {
- // First determine whether the current record exists already.
- int recID = 0;
- for ( ; recID < streamptr->nrecs; recID++ )
- {
- if ( gribapiVarCompare(compVar, streamptr->tsteps[0].records[recID], 1) == 0 ) break;
- }
- int recordExists = recID < streamptr->nrecs;
- // Then we need to know whether the verification time is consistent.
- int consistentTime = !memcmp(verificationTime, expectedVTime, sizeof(*verificationTime));
+void streamInqHistoryString(int streamID, char *history)
+{
+#ifdef HAVE_LIBNETCDF
+ stream_t *streamptr = stream_to_pointer(streamID);
- // Finally, we make a decision.
- if ( cdiInventoryMode == 1 )
- {
- if ( recordExists ) return CHECKTIME_STOP;
- if ( !consistentTime ) return CHECKTIME_INCONSISTENT;
- }
- else
+ if ( streamptr->filetype == FILETYPE_NC ||
+ streamptr->filetype == FILETYPE_NC2 ||
+ streamptr->filetype == FILETYPE_NC4 ||
+ streamptr->filetype == FILETYPE_NC4C )
{
- if ( !consistentTime ) return CHECKTIME_STOP;
- if ( recordExists ) return CHECKTIME_SKIP;
+ cdfInqHistoryString(streamptr, history);
}
-
- return CHECKTIME_OK;
+#else
+ (void)streamID; (void)history;
+#endif
}
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
#endif
-#define gribWarning(text, nrecs, timestep, varname, param, level1, level2) do \
- { \
- char paramstr[32]; \
- cdiParamToString(param, paramstr, sizeof(paramstr)); \
- Warning("Record %2d (name=%s id=%s lev1=%d lev2=%d) timestep %d: %s", nrecs, varname, paramstr, level1, level2, timestep, text); \
- } \
-while(0)
-
-#if defined (HAVE_LIBGRIB_API)
-int gribapiScanTimestep1(stream_t * streamptr)
-{
- off_t recpos = 0;
- unsigned char *gribbuffer = NULL;
- size_t buffersize = 0;
- DateTime datetime0 = { .date = 10101, .time = 0 };
- int nrecs_scanned = 0; //Only used for debug output.
- int warn_time = TRUE;
- // int warn_numavg = TRUE;
- int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
- grib_handle *gh = NULL;
-
- streamptr->curTsID = 0;
-
- int tsID = tstepsNewEntry(streamptr);
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
- if ( tsID != 0 )
- Error("Internal problem! tstepsNewEntry returns %d", tsID);
- int fileID = streamptr->fileID;
- unsigned nrecs = 0;
- while ( TRUE )
- {
- int level1 = 0, level2 = 0;
- size_t recsize = (size_t)gribGetSize(fileID);
- recpos = fileGetPos(fileID);
- if ( recsize == 0 )
- {
- streamptr->ntsteps = 1;
- break;
- }
- ensureBufferSize(recsize, &buffersize, &gribbuffer);
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
- size_t readsize = recsize;
- int rstatus = gribRead(fileID, gribbuffer, &readsize); //Search for next 'GRIB', read the following record, and position file offset after it.
- if ( rstatus ) break;
+#define SINGLE_PRECISION 4
+#define DOUBLE_PRECISION 8
- int datatype, comptype = 0;
- long unzipsize;
- gh = gribapiGetDiskRepresentation(recsize, &buffersize, &gribbuffer, &datatype, &comptype, &unzipsize);
+#if defined (HAVE_LIBIEG)
- nrecs_scanned++;
- GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
- int param = gribapiGetParam(gh);
- int leveltype1 = -1, leveltype2 = -1, lbounds, level_sf, level_unit;
- var_tile_t tiles = dummy_tiles;
- gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
+typedef struct {
+ int param;
+ int level;
+} IEGCOMPVAR;
- char varname[256];
- varname[0] = 0;
- gribapiGetString(gh, "shortName", varname, sizeof(varname));
- int tsteptype = gribapiGetTsteptype(gh);
+static int iegInqDatatype(int prec)
+{
+ int datatype;
- int vdate = 0, vtime = 0;
- gribapiGetValidityDateTime(gh, &vdate, &vtime);
- DateTime datetime = { .date = vdate, .time = vtime };
- /*
- printf("%d %d %d\n", vdate, vtime, leveltype1);
- */
+ if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
+ else datatype = DATATYPE_FLT32;
- if ( datetime0.date == 10101 && datetime0.time == 0 )
- {
- if( datetimeCmp(datetime, datetime0) || !nrecs ) //Do we really need this condition? I have included it in order not to change the number of times gribapiGetDataDateTime() etc. get called. But if those are sideeffect-free, this condition should be removed.
- {
- datetime0 = datetime;
+ return (datatype);
+}
- gribapiGetDataDateTime(gh, &rdate, &rtime);
- fcast = gribapiTimeIsFC(gh);
- if ( fcast ) tunit = gribapiGetTimeUnits(gh);
- }
- }
+static int iegDefDatatype(int datatype)
+{
+ int prec;
- if ( nrecs )
- {
- checkTimeResult result = checkTime(streamptr, gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles), &datetime, &datetime0);
- if ( result == CHECKTIME_STOP )
- {
- break;
- }
- else if ( result == CHECKTIME_SKIP )
- {
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- continue;
- }
- else if ( result == CHECKTIME_INCONSISTENT && warn_time )
- {
- gribWarning("Inconsistent verification time!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- warn_time = FALSE;
- }
- assert(result == CHECKTIME_OK || result == CHECKTIME_INCONSISTENT);
- }
- /*
- if ( ISEC1_AvgNum )
- {
- if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
- {
- Message("Change numavg from %d to %d not allowed!",
- taxis->numavg, ISEC1_AvgNum);
- warn_numavg = FALSE;
- }
- else
- {
- taxis->numavg = ISEC1_AvgNum;
- }
- }
- */
- nrecs++;
+ if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
+ Error("CDI/IEG library does not support complex numbers!");
- if ( CDI_Debug )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Message("%4u %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
- nrecs, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
- }
+ if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
+ datatype = DATATYPE_FLT32;
- var_tile_t *ptiles = NULL;
- if ( memcmp(&tiles, &dummy_tiles, sizeof(var_tile_t)) != 0 ) ptiles = &tiles;
- gribapiAddRecord(streamptr, param, gh, recsize, recpos, datatype, comptype, varname,
- leveltype1, leveltype2, lbounds, level1, level2, level_sf, level_unit, ptiles, 1);
+ if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION;
+ else prec = SINGLE_PRECISION;
- grib_handle_delete(gh);
- gh = NULL;
- }
+ return (prec);
+}
- if ( gh ) grib_handle_delete(gh);
+/* not used
+int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
+{
+ int status;
+ int fileID;
+ int icode, ilevel;
+ int zaxisID = -1;
+ int vlistID;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- streamptr->rtsteps = 1;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
- if ( nrecs == 0 ) return (CDI_EUFSTRUCT);
+ *varID = -1;
+ *levelID = -1;
- cdi_generate_vars(streamptr);
+ status = iegRead(fileID, iegp);
+ if ( status != 0 ) return (0);
- int taxisID = -1;
- if ( fcast )
- {
- taxisID = taxisCreate(TAXIS_RELATIVE);
- taxis->type = TAXIS_RELATIVE;
- taxis->rdate = rdate;
- taxis->rtime = rtime;
- taxis->unit = tunit;
- }
+ icode = IEG_P_Parameter(iegp->ipdb);
+ if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
+ ilevel = IEG_P_Level1(iegp->ipdb);
else
- {
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- taxis->type = TAXIS_ABSOLUTE;
- }
-
- taxis->vdate = (int)datetime0.date;
- taxis->vtime = (int)datetime0.time;
-
- int vlistID = streamptr->vlistID;
- vlistDefTaxis(vlistID, taxisID);
-
- int nrecords = streamptr->tsteps[0].nallrecs;
- if ( nrecords < streamptr->tsteps[0].recordSize )
- {
- streamptr->tsteps[0].recordSize = nrecords;
- streamptr->tsteps[0].records =
- (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords*sizeof(record_t));
- }
-
- streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords*sizeof(int));
- streamptr->tsteps[0].nrecs = nrecords;
- for ( int recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[0].recIDs[recID] = recID;
+ ilevel = IEG_P_Level2(iegp->ipdb);
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = buffersize;
+ *varID = vlistInqVarID(vlistID, icode);
- if ( streamptr->ntsteps == -1 )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ if ( *varID == UNDEFID ) Error("Code %d undefined", icode);
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
- }
+ zaxisID = vlistInqVarZaxis(vlistID, *varID);
- if ( streamptr->ntsteps == 1 )
- {
- if ( taxis->vdate == 0 && taxis->vtime == 0 )
- {
- streamptr->ntsteps = 0;
- for ( int varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- }
- }
+ *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
- return (0);
+ return (1);
}
-#endif
-
+*/
-#ifdef HAVE_LIBGRIB_API
-int gribapiScanTimestep2(stream_t * streamptr)
+void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
{
- int rstatus = 0;
- off_t recpos = 0;
- DateTime datetime0 = { LONG_MIN, LONG_MIN };
- // int gridID;
- int recID;
- // int warn_numavg = TRUE;
- grib_handle *gh = NULL;
+ int vlistID, fileID;
+ int status;
+ int recID, vrecID, tsID;
+ off_t recpos;
+ int varID, gridID;
+ int i, size;
+ double missval;
+ void *iegp = streamptr->record->exsep;
- streamptr->curTsID = 1;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ vrecID = streamptr->tsteps[tsID].curRecID;
+ recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ recpos = streamptr->tsteps[tsID].records[recID].position;
+ varID = streamptr->tsteps[tsID].records[recID].varID;
- int fileID = streamptr->fileID;
- int vlistID = streamptr->vlistID;
- int taxisID = vlistInqTaxis(vlistID);
+ fileSetPos(fileID, recpos, SEEK_SET);
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
- size_t buffersize = streamptr->record->buffersize;
+ status = iegRead(fileID, iegp);
+ if ( status != 0 )
+ Error("Could not read IEG record!");
- int tsID = streamptr->rtsteps;
- if ( tsID != 1 )
- Error("Internal problem! unexpected timestep %d", tsID+1);
+ iegInqDataDP(iegp, data);
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ size = gridInqSize(gridID);
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ streamptr->numvals += size;
- cdi_create_records(streamptr, tsID);
+ *nmiss = 0;
+ for ( i = 0; i < size; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
+}
- int nrecords = streamptr->tsteps[tsID].nallrecs;
- streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords*sizeof(int));
- streamptr->tsteps[1].nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[1].recIDs[recID] = -1;
+static
+int iegGetZaxisType(int iegleveltype)
+{
+ int leveltype = 0;
- for ( recID = 0; recID < nrecords; recID++ )
+ switch ( iegleveltype )
{
- streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position;
- streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size;
+ case IEG_LTYPE_SURFACE:
+ {
+ leveltype = ZAXIS_SURFACE;
+ break;
+ }
+ case IEG_LTYPE_99:
+ case IEG_LTYPE_ISOBARIC:
+ {
+ leveltype = ZAXIS_PRESSURE;
+ break;
+ }
+ case IEG_LTYPE_HEIGHT:
+ {
+ leveltype = ZAXIS_HEIGHT;
+ break;
+ }
+ case IEG_LTYPE_ALTITUDE:
+ {
+ leveltype = ZAXIS_ALTITUDE;
+ break;
+ }
+ case IEG_LTYPE_HYBRID:
+ case IEG_LTYPE_HYBRID_LAYER:
+ {
+ leveltype = ZAXIS_HYBRID;
+ break;
+ }
+ case IEG_LTYPE_LANDDEPTH:
+ case IEG_LTYPE_LANDDEPTH_LAYER:
+ {
+ leveltype = ZAXIS_DEPTH_BELOW_LAND;
+ break;
+ }
+ case IEG_LTYPE_SEADEPTH:
+ {
+ leveltype = ZAXIS_DEPTH_BELOW_SEA;
+ break;
+ }
+ default:
+ {
+ leveltype = ZAXIS_GENERIC;
+ break;
+ }
}
- int nrecs_scanned = nrecords; //Only used for debug output
- int rindex = 0;
- while ( TRUE )
- {
- if ( rindex > nrecords ) break;
+ return (leveltype);
+}
- size_t recsize = (size_t)gribGetSize(fileID);
- recpos = fileGetPos(fileID);
- if ( recsize == 0 )
- {
- streamptr->ntsteps = 2;
- break;
- }
- ensureBufferSize(recsize, &buffersize, &gribbuffer);
- size_t readsize = recsize;
- rstatus = gribRead(fileID, gribbuffer, &readsize);
- if ( rstatus ) break;
+static void iegDefTime(int *pdb, int date, int time, int taxisID)
+{
+ int year, month, day, hour, minute, second;
+ int timetype = -1;
+
+ if ( taxisID != -1 ) timetype = taxisInqType(taxisID);
+
+ if ( timetype == TAXIS_ABSOLUTE || timetype == TAXIS_RELATIVE )
+ {
+ cdiDecodeDate(date, &year, &month, &day);
+ cdiDecodeTime(time, &hour, &minute, &second);
+
+ IEG_P_Year(pdb) = year;
+ IEG_P_Month(pdb) = month;
+ IEG_P_Day(pdb) = day;
+ IEG_P_Hour(pdb) = hour;
+ IEG_P_Minute(pdb) = minute;
- long unzipsize;
- if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
- ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
+ pdb[15] = 1;
+ pdb[16] = 0;
+ pdb[17] = 0;
+ pdb[18] = 10;
+ pdb[36] = 1;
+ }
- nrecs_scanned++;
- gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
- GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
+ pdb[5] = 128;
+}
- int param = gribapiGetParam(gh);
- int level1 = 0, level2 = 0, leveltype1, leveltype2, lbounds, level_sf, level_unit;
- var_tile_t tiles = dummy_tiles;
- gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
+/* find smallest power of 10 in [1000,10000000] that upon
+ * multiplication results in fractional part close to zero for all
+ * arguments */
+static double
+calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylast, double yinc)
+{
+ double resfac = 1000.0;
+ enum {
+ nPwrOf10 = 5,
+ nMultTests = 6,
+ };
+ static const double scaleFactors[nPwrOf10]
+ = { 1000, 10000, 100000, 1000000, 10000000 };
+ double vals[nMultTests] = { xfirst, xlast, xinc, yfirst, ylast, yinc };
- char varname[256];
- varname[0] = 0;
- gribapiGetString(gh, "shortName", varname, sizeof(varname));
+ for (size_t j = 0; j < nPwrOf10; ++j )
+ {
+ double scaleBy = scaleFactors[j];
+ bool fractionalScale = false;
+ for (size_t i = 0; i < nMultTests; ++i )
+ {
+ fractionalScale = fractionalScale
+ || fabs(vals[i]*scaleBy - round(vals[i]*scaleBy)) > FLT_EPSILON;
+ }
+ if ( !fractionalScale )
+ {
+ resfac = scaleBy;
+ break;
+ }
+ }
- int vdate = 0, vtime = 0;
- gribapiGetValidityDateTime(gh, &vdate, &vtime);
+ return (resfac);
+}
- if ( rindex == 0 )
- {
- if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
- {
- taxis->type = TAXIS_RELATIVE;
+static
+void iegDefGrid(int *gdb, int gridID)
+{
+ int gridtype = gridInqType(gridID);
- gribapiGetDataDateTime(gh, &(taxis->rdate), &(taxis->rtime));
+ if ( gridtype == GRID_GENERIC )
+ {
+ int xsize, ysize;
- taxis->unit = gribapiGetTimeUnits(gh);
- }
- else
- {
- taxis->type = TAXIS_ABSOLUTE;
- }
- taxis->vdate = vdate;
- taxis->vtime = vtime;
+ xsize = gridInqXsize(gridID);
+ ysize = gridInqYsize(gridID);
- datetime0.date = vdate;
- datetime0.time = vtime;
+ if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
+ ysize == 96 || ysize == 160) &&
+ (xsize == 2*ysize || xsize == 1) )
+ {
+ gridtype = GRID_GAUSSIAN;
+ gridChangeType(gridID, gridtype);
}
-
- int tsteptype = gribapiGetTsteptype(gh);
- /*
- if ( ISEC1_AvgNum )
+ else if ( (xsize == 1 && ysize == 1) || (xsize == 0 && ysize == 0) )
{
- if ( taxis->numavg && warn_numavg &&
- (taxis->numavg != ISEC1_AvgNum) )
- {
- warn_numavg = FALSE;
- }
- else
- {
- taxis->numavg = ISEC1_AvgNum;
- }
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
}
- */
- DateTime datetime = {
- .date = vdate,
- .time = vtime
- };
+ else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+ {
+ gridtype = GRID_LONLAT;
+ gridChangeType(gridID, gridtype);
+ }
+ }
+ else if ( gridtype == GRID_CURVILINEAR )
+ {
+ gridtype = GRID_LONLAT;
+ }
- compvar2_t compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles);
+ if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+ {
+ double xfirst = 0, xlast = 0, xinc = 0;
+ double yfirst = 0, ylast = 0, yinc = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
+ int nlon = gridInqXsize(gridID),
+ nlat = gridInqYsize(gridID);
- if ( recID == nrecords )
+ if ( nlon == 0 )
{
- gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- return (CDI_EUFSTRUCT);
+ nlon = 1;
+ }
+ else
+ {
+ xfirst = gridInqXval(gridID, 0);
+ xlast = gridInqXval(gridID, nlon-1);
+ xinc = gridInqXinc(gridID);
}
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- if ( cdiInventoryMode == 1 ) break;
- else
- {
- if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
- continue;
- }
+ if ( nlat == 0 )
+ {
+ nlat = 1;
+ }
+ else
+ {
+ yfirst = gridInqYval(gridID, 0);
+ ylast = gridInqYval(gridID, nlat-1);
+ yinc = gridInqYinc(gridID);
}
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ if ( gridtype == GRID_GAUSSIAN )
+ IEG_G_GridType(gdb) = 4;
+ else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
+ IEG_G_GridType(gdb) = 10;
+ else
+ IEG_G_GridType(gdb) = 0;
- if ( CDI_Debug )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Message("%4d %8d name=%s id=%s ltype=%d lev1=%d lev2=%d vdate=%d vtime=%d",
- nrecs_scanned, (int)recpos, varname, paramstr, leveltype1, level1, level2, vdate, vtime);
- }
+ double resfac = calc_resfac(xfirst, xlast, xinc, yfirst, ylast, yinc);
+ int iresfac = (int)resfac;
+ if ( iresfac == 1000 ) iresfac = 0;
- streamptr->tsteps[tsID].records[recID].size = recsize;
+ IEG_G_ResFac(gdb) = iresfac;
- if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, level1);
- return (CDI_EUFSTRUCT);
- }
+ IEG_G_NumLon(gdb) = nlon;
+ IEG_G_NumLat(gdb) = nlat;
+ IEG_G_FirstLat(gdb) = (int)lround(yfirst*resfac);
+ IEG_G_LastLat(gdb) = (int)lround(ylast*resfac);
+ IEG_G_FirstLon(gdb) = (int)lround(xfirst*resfac);
+ IEG_G_LastLon(gdb) = (int)lround(xlast*resfac);
+ IEG_G_LonIncr(gdb) = (int)lround(xinc*resfac);
+ if ( fabs(xinc*resfac - IEG_G_LonIncr(gdb)) > FLT_EPSILON )
+ IEG_G_LonIncr(gdb) = 0;
- streamptr->tsteps[1].records[recID].position = recpos;
- int varID = streamptr->tsteps[tsID].records[recID].varID;
- /*
- gridID = vlistInqVarGrid(vlistID, varID);
- if ( gridInqSize(gridID) == 1 && gridInqType(gridID) == GRID_LONLAT )
+ if ( gridtype == GRID_GAUSSIAN )
+ IEG_G_LatIncr(gdb) = nlat/2;
+ else
{
- if ( IS_NOT_EQUAL(gridInqXval(gridID, 0),ISEC2_FirstLon*0.001) ||
- IS_NOT_EQUAL(gridInqYval(gridID, 0),ISEC2_FirstLat*0.001) )
- gridChangeType(gridID, GRID_TRAJECTORY);
+ IEG_G_LatIncr(gdb) = (int)lround(yinc*resfac);
+ if ( fabs(yinc*resfac - IEG_G_LatIncr(gdb)) > FLT_EPSILON )
+ IEG_G_LatIncr(gdb) = 0;
+
+ if ( IEG_G_LatIncr(gdb) < 0 ) IEG_G_LatIncr(gdb) = -IEG_G_LatIncr(gdb);
}
- */
- if ( tsteptype != vlistInqVarTsteptype(vlistID, varID) )
- vlistDefVarTsteptype(vlistID, varID, tsteptype);
- grib_handle_delete(gh);
- gh = NULL;
+ if ( IEG_G_NumLon(gdb) > 1 && IEG_G_NumLat(gdb) == 1 )
+ if ( IEG_G_LonIncr(gdb) != 0 && IEG_G_LatIncr(gdb) == 0 ) IEG_G_LatIncr(gdb) = IEG_G_LonIncr(gdb);
- rindex++;
- }
+ if ( IEG_G_NumLon(gdb) == 1 && IEG_G_NumLat(gdb) > 1 )
+ if ( IEG_G_LonIncr(gdb) == 0 && IEG_G_LatIncr(gdb) != 0 ) IEG_G_LonIncr(gdb) = IEG_G_LatIncr(gdb);
- if ( gh ) grib_handle_delete(gh);
+ if ( IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0 )
+ IEG_G_ResFlag(gdb) = 0;
+ else
+ IEG_G_ResFlag(gdb) = 128;
- int nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- {
- if ( ! streamptr->tsteps[tsID].records[recID].used )
+ if ( gridIsRotated(gridID) )
{
- int varID = streamptr->tsteps[tsID].records[recID].varID;
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ IEG_G_LatSP(gdb) = - (int)lround(gridInqYpole(gridID) * resfac);
+ IEG_G_LonSP(gdb) = (int)lround((gridInqXpole(gridID) + 180) * resfac);
+ IEG_G_Size(gdb) = 42;
}
else
{
- nrecs++;
+ IEG_G_Size(gdb) = 32;
}
}
- streamptr->tsteps[tsID].nrecs = nrecs;
-
- streamptr->rtsteps = 2;
-
- if ( streamptr->ntsteps == -1 )
+ else
{
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
-
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ Error("Unsupported grid type: %s", gridNamePtr(gridtype));
}
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = buffersize;
-
- return (rstatus);
+ IEG_G_ScanFlag(gdb) = 64;
}
-#endif
-
-#if defined (HAVE_LIBGRIB_API)
-int gribapiScanTimestep(stream_t * streamptr)
+static
+void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
{
- int vrecID, recID;
- //int warn_numavg = TRUE;
- int nrecs = 0;
- int vlistID = streamptr->vlistID;
+ double level;
+ int ilevel, leveltype;
+ static int vct_warning = 1;
- if ( CDI_Debug )
+ leveltype = zaxisInqType(zaxisID);
+
+ if ( leveltype == ZAXIS_GENERIC )
{
- Message("streamID = %d", streamptr->self);
- Message("cts = %d", streamptr->curTsID);
- Message("rts = %d", streamptr->rtsteps);
- Message("nts = %d", streamptr->ntsteps);
+ Message("Changed zaxis type from %s to %s",
+ zaxisNamePtr(leveltype),
+ zaxisNamePtr(ZAXIS_PRESSURE));
+ leveltype = ZAXIS_PRESSURE;
+ zaxisChangeType(zaxisID, leveltype);
+ zaxisDefUnits(zaxisID, "Pa");
}
- int tsID = streamptr->rtsteps;
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+ /* IEG_G_NumVCP(gdb) = 0; */
- if ( streamptr->tsteps[tsID].recordSize == 0 )
+ switch (leveltype)
{
- unsigned char* gribbuffer = (unsigned char *) streamptr->record->buffer;
- size_t buffersize = streamptr->record->buffersize;
-
- cdi_create_records(streamptr, tsID);
-
- nrecs = streamptr->tsteps[1].nrecs;
-
- streamptr->tsteps[tsID].nrecs = nrecs;
- streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs*sizeof(int));
- for ( recID = 0; recID < nrecs; recID++ )
- streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
-
- int fileID = streamptr->fileID;
-
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
-
- int nrecs_scanned = streamptr->tsteps[0].nallrecs + streamptr->tsteps[1].nrecs*(tsID-1); //Only used for debug output.
- int rindex = 0;
- off_t recpos = 0;
- DateTime datetime0 = { LONG_MIN, LONG_MIN };
- grib_handle *gh = NULL;
- char varname[256];
- while ( TRUE )
- {
- if ( rindex > nrecs ) break;
-
- size_t recsize = (size_t)gribGetSize(fileID);
- recpos = fileGetPos(fileID);
- if ( recsize == 0 )
- {
- streamptr->ntsteps = streamptr->rtsteps + 1;
- break;
- }
-
- if ( rindex >= nrecs ) break;
-
- ensureBufferSize(recsize, &buffersize, &gribbuffer);
-
- size_t readsize = recsize;
- if (gribRead(fileID, gribbuffer, &readsize))
- {
- Warning("Inconsistent timestep %d (GRIB record %d/%d)!", tsID+1, rindex+1,
- streamptr->tsteps[tsID].recordSize);
- break;
- }
-
- long unzipsize;
- if ( gribGetZip((long)recsize, gribbuffer, &unzipsize) > 0 )
- ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
-
- nrecs_scanned++;
- gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
- GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
-
- int param = gribapiGetParam(gh);
- int level1 = 0, level2 = 0, leveltype1, leveltype2 = -1, lbounds, level_sf, level_unit;
- var_tile_t tiles = dummy_tiles;
- gribGetLevel(gh, &leveltype1, &leveltype2, &lbounds, &level1, &level2, &level_sf, &level_unit, &tiles);
-
- varname[0] = 0;
- gribapiGetString(gh, "shortName", varname, sizeof(varname));
-
- int vdate = 0, vtime = 0;
- gribapiGetValidityDateTime(gh, &vdate, &vtime);
-
- if ( rindex == nrecs ) break;
-
- if ( rindex == 0 )
- {
- int taxisID = vlistInqTaxis(vlistID);
- if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
- {
- taxis->type = TAXIS_RELATIVE;
-
- gribapiGetDataDateTime(gh, &(taxis->rdate), &(taxis->rtime));
-
- taxis->unit = gribapiGetTimeUnits(gh);
- }
- else
- {
- taxis->type = TAXIS_ABSOLUTE;
- }
- taxis->vdate = vdate;
- taxis->vtime = vtime;
-
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
- /*
- if ( ISEC1_AvgNum )
- {
- if ( taxis->numavg && warn_numavg &&
- (taxis->numavg != ISEC1_AvgNum) )
- {
- warn_numavg = FALSE;
- }
- else
- {
- taxis->numavg = ISEC1_AvgNum;
- }
- }
- */
- DateTime datetime = {
- .date = vdate,
- .time = vtime
- };
-
- int tsteptype = gribapiGetTsteptype(gh);
-
- compvar2_t compVar = gribapiVarSet(param, level1, level2, leveltype1, tsteptype, varname, tiles);
-
- for ( vrecID = 0; vrecID < nrecs; vrecID++ )
- {
- recID = streamptr->tsteps[1].recIDs[vrecID];
- if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) == 0 ) break;
- }
-
- if ( vrecID == nrecs )
- {
- gribWarning("Parameter not defined at timestep 1!", nrecs_scanned, tsID+1, varname, param, level1, level2);
-
- if ( cdiInventoryMode == 1 )
- return (CDI_EUFSTRUCT);
- else
- continue;
- }
-
- if ( cdiInventoryMode != 1 )
- {
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- if ( datetimeCmp(datetime, datetime0) != 0 ) break;
-
- if ( CDI_Debug )
- gribWarning("Parameter already exist, skipped!", nrecs_scanned, tsID+1, varname, param, level1, level2);
-
- continue;
- }
- }
-
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ case ZAXIS_SURFACE:
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_SURFACE;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID));
+ break;
+ }
+ case ZAXIS_HYBRID:
+ {
+ int vctsize;
- if ( CDI_Debug )
- Message("%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID_LAYER;
+ IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID));
+ IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID));
+ }
+ else
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID));
+ }
- if ( gribapiVarCompare(compVar, streamptr->tsteps[tsID].records[recID], 0) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, level1);
- Error("Invalid, unsupported or inconsistent record structure");
- }
+ vctsize = zaxisInqVctSize(zaxisID);
+ if ( vctsize > 100 )
+ {
+ /* IEG_G_NumVCP(gdb) = 0; */
+ if ( vct_warning )
+ {
+ Warning("VCT size of %d is too large (maximum is 100). Set to 0!", vctsize);
+ vct_warning = 0;
+ }
+ }
+ else
+ {
+ IEG_G_Size(gdb) += (vctsize*4);
+ memcpy(vct, zaxisInqVctPtr(zaxisID), (size_t)vctsize/2*sizeof(double));
+ memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, (size_t)vctsize/2*sizeof(double));
+ }
+ break;
+ }
+ case ZAXIS_PRESSURE:
+ {
+ double dum;
+ char units[128];
- streamptr->tsteps[tsID].records[recID].position = recpos;
- streamptr->tsteps[tsID].records[recID].size = recsize;
+ level = zaxisInqLevel(zaxisID, levelID);
+ if ( level < 0 )
+ Warning("pressure level of %f Pa is below 0.", level);
- if ( CDI_Debug )
- Message("%4d %8d %4d %8d %8d %6d", rindex, (int)recpos, param, level1, vdate, vtime);
+ zaxisInqUnits(zaxisID, units);
+ if ( memcmp(units, "hPa", 3) == 0 || memcmp(units, "mb",2 ) == 0 )
+ level = level*100;
- grib_handle_delete(gh);
- gh = NULL;
+ ilevel = (int) level;
+ if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_99;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
+ }
+ else
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_ISOBARIC;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel/100;
+ }
+ break;
+ }
+ case ZAXIS_HEIGHT:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- rindex++;
- }
+ ilevel = (int) level;
+ IEG_P_LevelType(pdb) = IEG_LTYPE_HEIGHT;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
- if ( gh ) grib_handle_delete(gh);
+ break;
+ }
+ case ZAXIS_ALTITUDE:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- for ( vrecID = 0; vrecID < nrecs; vrecID++ )
- {
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- if ( ! streamptr->tsteps[tsID].records[recID].used ) break;
- }
+ ilevel = (int) level;
+ IEG_P_LevelType(pdb) = IEG_LTYPE_ALTITUDE;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
- if ( vrecID < nrecs )
- {
- gribWarning("Paramameter not found!", nrecs_scanned, tsID+1, varname, streamptr->tsteps[tsID].records[recID].param,
- streamptr->tsteps[tsID].records[recID].ilevel, streamptr->tsteps[tsID].records[recID].ilevel2);
- return (CDI_EUFSTRUCT);
- }
+ break;
+ }
+ case ZAXIS_DEPTH_BELOW_LAND:
+ {
+ if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
+ {
+ IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH_LAYER;
+ IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID));
+ IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID));
+ }
+ else
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- streamptr->rtsteps++;
+ ilevel = (int) level;
+ IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
+ }
- if ( streamptr->ntsteps != streamptr->rtsteps )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ break;
+ }
+ case ZAXIS_DEPTH_BELOW_SEA:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- streamptr->tsteps[tsID-1].next = 1;
- streamptr->tsteps[tsID].position = recpos;
- }
+ ilevel = (int) level;
+ IEG_P_LevelType(pdb) = IEG_LTYPE_SEADEPTH;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- streamptr->tsteps[tsID].position = recpos;
+ break;
+ }
+ case ZAXIS_ISENTROPIC:
+ {
+ level = zaxisInqLevel(zaxisID, levelID);
- streamptr->record->buffer = gribbuffer;
- streamptr->record->buffersize = buffersize;
- }
+ ilevel = (int) level;
+ IEG_P_LevelType(pdb) = 113;
+ IEG_P_Level1(pdb) = 0;
+ IEG_P_Level2(pdb) = ilevel;
- if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
- {
- Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
- streamptr->ntsteps = tsID;
+ break;
+ }
+ default:
+ {
+ Error("Unsupported zaxis type: %s", zaxisNamePtr(leveltype));
+ break;
+ }
}
-
- return (int)streamptr->ntsteps;
}
-#endif
-#ifdef gribWarning
-#undef gribWarning
-#endif
-#ifdef HAVE_LIBGRIB_API
-int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval, int vlistID, int varID)
+void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
{
- int status = 0;
- long lpar;
- long numberOfPoints;
- size_t datasize;
+ streamFCopyRecord(streamptr2, streamptr1, "IEG");
+}
- UNUSED(vlistID);
- UNUSED(varID);
- if ( unreduced )
- {
- static int lwarn = 1;
+void iegDefRecord(stream_t *streamptr)
+{
+ int vlistID;
+ int gridID;
+ int date, time;
+ int datatype;
+ int i;
+ int param, pdis, pcat, pnum;
+ int varID, levelID, tsID, zaxisID;
+ int byteorder;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- if ( lwarn )
- {
- lwarn = 0;
- Warning("Conversion of gaussian reduced grids unsupported!");
- }
- }
+ vlistID = streamptr->vlistID;
+ byteorder = streamptr->byteorder;
- size_t recsize = (size_t)gribsize;
- grib_handle *gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
- GRIB_CHECK(my_grib_set_double(gh, "missingValue", missval), 0);
+ varID = streamptr->record->varID;
+ levelID = streamptr->record->levelID;
+ tsID = streamptr->curTsID;
- /* get the size of the values array*/
- GRIB_CHECK(grib_get_size(gh, "values", &datasize), 0);
- GRIB_CHECK(grib_get_long(gh, "numberOfPoints", &numberOfPoints), 0);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
- // printf("values_size = %d numberOfPoints = %ld\n", datasize, numberOfPoints);
+ iegInitMem(iegp);
+ for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
- if ( gridsize != (int) datasize )
- Error("Internal problem: gridsize(%d) != datasize(%d)!", gridsize, datasize);
- size_t dummy = datasize;
- GRIB_CHECK(grib_get_double_array(gh, "values", data, &dummy), 0);
+ iegp->byteswap = getByteswap(byteorder);
- GRIB_CHECK(grib_get_long(gh, "gridDefinitionTemplateNumber", &lpar), 0);
- int gridtype = (int) lpar;
+ param = vlistInqVarParam(vlistID, varID);
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ IEG_P_Parameter(iegp->ipdb) = pnum;
+ if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
+ date = streamptr->tsteps[tsID].taxis.vdate;
+ time = streamptr->tsteps[tsID].taxis.vtime;
- *nmiss = 0;
- if ( gridtype < 50 || gridtype > 53 )
- {
- GRIB_CHECK(grib_get_long(gh, "numberOfMissing", &lpar), 0);
- *nmiss = (int) lpar;
- // printf("gridtype %d, nmiss %d\n", gridtype, nmiss);
- }
+ iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
+ iegDefGrid(iegp->igdb, gridID);
+ iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levelID);
- grib_handle_delete(gh);
+ datatype = streamptr->record->prec;
- return (status);
+ iegp->dprec = iegDefDatatype(datatype);
}
-#endif
-#if defined (HAVE_LIBGRIB_API)
-static
-void gribapiDefInstitut(grib_handle *gh, int vlistID, int varID)
+void iegWriteRecord(stream_t *streamptr, const double *data)
{
- int instID;
-
- if ( vlistInqInstitut(vlistID) != CDI_UNDEFID )
- instID = vlistInqInstitut(vlistID);
- else
- instID = vlistInqVarInstitut(vlistID, varID);
-
- if ( instID != CDI_UNDEFID )
- {
- long center, subcenter;
- long center0, subcenter0;
+ int fileID;
+ int i, gridsize, gridID;
+ double refval;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- center = institutInqCenter(instID);
- subcenter = institutInqSubcenter(instID);
+ fileID = streamptr->fileID;
+ gridID = streamptr->record->gridID;
- GRIB_CHECK(grib_get_long(gh, "centre", ¢er0), 0);
- GRIB_CHECK(grib_get_long(gh, "subCentre", &subcenter0), 0);
+ gridsize = gridInqSize(gridID);
- if ( center != center0 )
- GRIB_CHECK(my_grib_set_long(gh, "centre", center), 0);
- if ( subcenter != subcenter0 )
- GRIB_CHECK(my_grib_set_long(gh, "subCentre", subcenter), 0);
- }
-}
+ refval = data[0];
+ for ( i = 1; i < gridsize; i++ )
+ if ( data[i] < refval ) refval = data[i];
-static
-void gribapiDefModel(grib_handle *gh, int vlistID, int varID)
-{
- int modelID;
+ iegp->refval = refval;
- if ( vlistInqModel(vlistID) != CDI_UNDEFID )
- modelID = vlistInqModel(vlistID);
- else
- modelID = vlistInqVarModel(vlistID, varID);
+ iegDefDataDP(iegp, data);
- if ( modelID != CDI_UNDEFID )
- GRIB_CHECK(my_grib_set_long(gh, "generatingProcessIdentifier", modelInqGribID(modelID)), 0);
+ iegWrite(fileID, iegp);
}
static
-void gribapiDefParam(int editionNumber, grib_handle *gh, int param, const char *name, const char *stdname)
+void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
+ size_t recsize, off_t position, int prec)
{
- bool ldefined = false;
-
- int pdis, pcat, pnum;
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ int levelID = 0;
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
- if ( pnum < 0 )
+ int level1, level2;
+ if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER )
{
- size_t len;
- len = strlen(stdname);
- if ( len )
- {
- int status = my_grib_set_string(gh, "cfName", stdname, &len);
- if ( status == 0 ) ldefined = true;
- else Warning("grib_api: No match for cfName=%s", stdname);
- }
-
- if ( ldefined == false )
- {
- len = strlen(name);
- int status = my_grib_set_string(gh, "shortName", name, &len);
- if ( status == 0 ) ldefined = true;
- else Warning("grib_api: No match for shortName=%s", name);
- }
+ level1 = IEG_P_Level1(pdb);
+ level2 = IEG_P_Level2(pdb);
}
-
- if ( ldefined == false )
+ else
{
- if ( pnum < 0 ) pnum = -pnum;
+ level1 = IEG_P_Level2(pdb);
+ level2 = 0;
+ if ( IEG_P_LevelType(pdb) == 100 ) level1 *= 100;
+ }
- static bool lwarn_pnum = true;
- if ( pnum > 255 && lwarn_pnum )
- {
- Warning("Parameter number %d out of range (1-255), set to %d!", pnum, pnum%256);
- lwarn_pnum = false;
- pnum = pnum%256;
- }
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level1;
+ record->ilevel2 = level2;
+ record->ltype = IEG_P_LevelType(pdb);
- if ( editionNumber <= 1 )
- {
- static bool lwarn_pdis = true;
- if ( pdis != 255 && lwarn_pdis )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Warning("Can't convert GRIB2 parameter ID (%s) to GRIB1, set to %d.%d!", paramstr, pnum, pcat);
- lwarn_pdis = false;
- }
+ int gridtype =
+ ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 ) ? GRID_LONLAT :
+ ( IEG_G_GridType(gdb) == 4 ) ? GRID_GAUSSIAN : GRID_GENERIC;
- GRIB_CHECK(my_grib_set_long(gh, "table2Version", pcat), 0);
- GRIB_CHECK(my_grib_set_long(gh, "indicatorOfParameter", pnum), 0);
- }
- else
- {
- GRIB_CHECK(my_grib_set_long(gh, "discipline", pdis), 0);
- GRIB_CHECK(my_grib_set_long(gh, "parameterCategory", pcat), 0);
- GRIB_CHECK(my_grib_set_long(gh, "parameterNumber", pnum), 0);
- }
- }
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb));
+ grid->xsize = IEG_G_NumLon(gdb);
+ grid->ysize = IEG_G_NumLat(gdb);
+ grid->xinc = 0;
+ grid->yinc = 0;
+ grid->xdef = 0;
- // printf("param: %d.%d.%d %s\n", pnum, pcat, pdis, name);
-}
+ int iresfac = IEG_G_ResFac(gdb);
+ if ( iresfac == 0 ) iresfac = 1000;
+ double resfac = 1./(double) iresfac;
-static
-int getTimeunitFactor(int timeunit)
-{
- int factor = 1;
+ /* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */
+ {
+ if ( grid->xsize > 1 )
+ {
+ if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 )
+ grid->xinc = IEG_G_LonIncr(gdb) * resfac;
+ else
+ grid->xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid->xsize - 1);
- switch (timeunit)
+ /* correct xinc if necessary */
+ if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 )
+ {
+ double xinc = 360. / grid->xsize;
+ /* FIXME: why not use grid->xinc != xinc as condition? */
+ if ( fabs(grid->xinc-xinc) > 0.0 )
+ {
+ grid->xinc = xinc;
+ if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
+ }
+ }
+ }
+ grid->xfirst = IEG_G_FirstLon(gdb) * resfac;
+ grid->xlast = IEG_G_LastLon(gdb) * resfac;
+ grid->xdef = 2;
+ }
+ grid->ydef = 0;
+ /* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */
+ {
+ if ( grid->ysize > 1 )
+ {
+ if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 )
+ grid->yinc = IEG_G_LatIncr(gdb) * resfac;
+ else
+ grid->yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid->ysize - 1);
+ }
+ grid->yfirst = IEG_G_FirstLat(gdb) * resfac;
+ grid->ylast = IEG_G_LastLat(gdb) * resfac;
+ grid->ydef = 2;
+ }
+ /*
+ grid->xfirst= IEG_G_FirstLon(gdb) * resfac;
+ grid->xlast = IEG_G_LastLon(gdb) * resfac;
+ grid->xinc = IEG_G_LonIncr(gdb) * resfac;
+ grid->xdef = 2;
+ grid->yfirst= IEG_G_FirstLat(gdb) * resfac;
+ grid->ylast = IEG_G_LastLat(gdb) * resfac;
+ grid->yinc = IEG_G_LatIncr(gdb) * resfac;
+ grid->ydef = 2;
+ */
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+
+ grid->isRotated = FALSE;
+ if ( IEG_G_GridType(gdb) == 10 )
{
- case TUNIT_SECOND: factor = 1; break;
- case TUNIT_MINUTE: factor = 60; break;
- case TUNIT_HOUR: factor = 3600; break;
- case TUNIT_3HOURS: factor = 10800; break;
- case TUNIT_6HOURS: factor = 21600; break;
- case TUNIT_12HOURS: factor = 43200; break;
- case TUNIT_DAY: factor = 86400; break;
- default: factor = 3600; break;
+ grid->isRotated = TRUE;
+ grid->ypole = - IEG_G_LatSP(gdb) * resfac;
+ grid->xpole = IEG_G_LonSP(gdb) * resfac - 180;
+ grid->angle = 0;
}
- return (factor);
-}
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
-static
-void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int gcinit)
-{
- long unitsOfTime;
+ int leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
- switch (timeunit)
+ if ( leveltype == ZAXIS_HYBRID )
{
- case TUNIT_SECOND: unitsOfTime = 13; break;
- case TUNIT_MINUTE: unitsOfTime = 0; break;
- case TUNIT_HOUR: unitsOfTime = 1; break;
- case TUNIT_3HOURS: unitsOfTime = 10; break;
- case TUNIT_6HOURS: unitsOfTime = 11; break;
- case TUNIT_12HOURS: unitsOfTime = 12; break;
- case TUNIT_DAY: unitsOfTime = 2; break;
- default: unitsOfTime = 1; break;
- }
+ double tmpvct[100];
+ size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
- if ( !gcinit )
- {
- GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
- if ( proDefTempNum == 8 || proDefTempNum == 11 )
- GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
- GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+ for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
+ for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50];
+
+ varDefVCT(vctsize, tmpvct);
}
+
+ int lbounds = IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER ? 1 : 0;
+
+ int datatype = iegInqDatatype(prec);
+
+ int varID;
+ varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
+ datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
+
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
+
+ if ( CDI_Debug )
+ Message("varID = %d gridID = %d levelID = %d",
+ varID, gridID, levelID);
}
+#if 0
static
-int gribapiDefSteptype(int editionNumber, grib_handle *gh, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
+void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
+ int level, int xsize, int ysize)
{
- long proDefTempNum = 0;
- size_t len = 64;
- const char *stepType;
+ int varID = 0;
+ int levelID = 0;
+ record_t *record;
- static struct {
- long productionTemplate;
- const char sname[8];
- } ts_tab[] = {
- [TSTEP_INSTANT] = { 0, "instant" },
- [TSTEP_AVG] = { 8, "avg" },
- [TSTEP_ACCUM] = { 8, "accum" },
- [TSTEP_MAX] = { 8, "max" },
- [TSTEP_MIN] = { 8, "min" },
- [TSTEP_DIFF] = { 8, "diff" },
- [TSTEP_RMS] = { 8, "rms" },
- [TSTEP_SD] = { 8, "sd" },
- [TSTEP_COV] = { 8, "cov" },
- [TSTEP_RATIO] = { 8, "ratio" }
- };
- if (tsteptype >= TSTEP_INSTANT && tsteptype <= TSTEP_RATIO)
- {
- stepType = ts_tab[tsteptype].sname;
- proDefTempNum = ts_tab[tsteptype].productionTemplate;
- }
- else
- {
- stepType = "instant";
- proDefTempNum = 0;
- }
+ record = &streamptr->tsteps[tsID].records[recID];
- if ( typeOfGeneratingProcess == 4 )
- {
- if ( proDefTempNum == 8 ) proDefTempNum = 11;
- else proDefTempNum = 1;
- }
+ if ( param != (*record).param || level != (*record).ilevel )
+ Error("inconsistent timestep");
- if ( productDefinitionTemplate != -1 ) proDefTempNum = productDefinitionTemplate;
+ (*record).position = position;
+ /*
+ varID = (*record).varID;
+ levelID = (*record).levelID;
- if ( !gcinit )
- {
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "productDefinitionTemplateNumber", proDefTempNum), 0);
- len = strlen(stepType);
- GRIB_CHECK(my_grib_set_string(gh, "stepType", stepType, &len), 0);
- }
+ streamptr->vars[varID].level[levelID] = recID;
- return ((int)proDefTempNum);
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
+ */
+ if ( CDI_Debug )
+ Message("varID = %d levelID = %d", varID, levelID);
}
+#endif
-static
-void gribapiDefDateTimeAbs(int editionNumber, grib_handle *gh, int date, int time, int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int gcinit)
+static void iegDateTime(int *pdb, int *date, int *time)
{
- (void ) gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
+ int ryear, rmonth, rday, rhour, rminute;
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 0), 0);
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
+ ryear = IEG_P_Year(pdb);
- if ( date == 0 ) date = 10101;
- gribapiSetDataDateTime(gh, date, time);
+ rmonth = IEG_P_Month(pdb);
+ rday = IEG_P_Day(pdb);
+
+ rhour = IEG_P_Hour(pdb);
+ rminute = IEG_P_Minute(pdb);
+
+ if ( rminute == -1 ) rminute = 0;
+
+ *date = cdiEncodeDate(ryear, rmonth, rday);
+ *time = cdiEncodeTime(rhour, rminute, 0);
}
static
-int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rtime, int vdate, int vtime,
- int productDefinitionTemplate, int typeOfGeneratingProcess, int tsteptype, int timeunit, int calendar, int gcinit)
+void iegScanTimestep1(stream_t *streamptr)
{
- int status = -1;
- int year, month, day, hour, minute, second;
- int julday1, secofday1, julday2, secofday2, days, secs;
- long startStep = 0, endStep;
+ int prec = 0;
+ int status;
+ int fileID;
+ int tabnum;
+ int param = 0;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ DateTime datetime0 = { LONG_MIN, LONG_MIN };
+ int tsID;
+ int varID;
+ size_t recsize;
+ off_t recpos;
+ int nrecords, nrecs, recID;
+ int taxisID = -1;
+ taxis_t *taxis;
+ int vlistID;
+ IEGCOMPVAR compVar, compVar0;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- cdiDecodeDate(rdate, &year, &month, &day);
- cdiDecodeTime(rtime, &hour, &minute, &second);
- encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday1, &secofday1);
+ streamptr->curTsID = 0;
- if ( vdate == 0 && vtime == 0 ) { vdate = rdate; vtime = rtime; }
+ tsID = tstepsNewEntry(streamptr);
+ taxis = &streamptr->tsteps[tsID].taxis;
- cdiDecodeDate(vdate, &year, &month, &day);
- cdiDecodeTime(vtime, &hour, &minute, &second);
- encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
+ if ( tsID != 0 )
+ Error("Internal problem! tstepsNewEntry returns %d", tsID);
- (void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
+ fileID = streamptr->fileID;
- int factor = getTimeunitFactor(timeunit);
+ nrecs = 0;
+ while ( TRUE )
+ {
+ recpos = fileGetPos(fileID);
+ status = iegRead(fileID, iegp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = 1;
+ break;
+ }
+ recsize = (size_t)(fileGetPos(fileID) - recpos);
- if ( !(int) fmod(days*86400.0 + secs, factor) )
- {
- int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
+ prec = iegp->dprec;
+ rcode = IEG_P_Parameter(iegp->ipdb);
+ tabnum = IEG_P_CodeTable(iegp->ipdb);
+ param = cdiEncodeParam(rcode, tabnum, 255);
- gribapiDefStepUnits(gh, timeunit, proDefTempNum, gcinit);
+ if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
+ rlevel = IEG_P_Level1(iegp->ipdb);
+ else
+ rlevel = IEG_P_Level2(iegp->ipdb);
- endStep = (int) ((days*86400.0 + secs)/factor);
+ if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "significanceOfReferenceTime", 1), 0);
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "stepRange", 0), 0);
+ iegDateTime(iegp->ipdb, &vdate, &vtime);
- if ( rdate == 0 ) rdate = 10101;
- gribapiSetDataDateTime(gh, rdate, rtime);
+ if ( nrecs == 0 )
+ {
+ datetime0.date = vdate;
+ datetime0.time = vtime;
+ }
+ else
+ {
+ compVar.param = param;
+ compVar.level = rlevel;
+ for ( recID = 0; recID < nrecs; recID++ )
+ {
+ compVar0.param = streamptr->tsteps[0].records[recID].param;
+ compVar0.level = streamptr->tsteps[0].records[recID].ilevel;
- // printf(">>>>> tsteptype %d startStep %ld endStep %ld\n", tsteptype, startStep, endStep);
+ if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 ) break;
+ }
+ if ( recID < nrecs ) break;
+ DateTime datetime = { .date = vdate, .time = vtime};
+ if ( datetimeCmp(datetime, datetime0) )
+ Warning("Inconsistent verification time for param %d level %d", param, rlevel);
+ }
- // Product Definition Template Number: defined in GRIB_API file 4.0.table
- // point in time products:
- if ( (proDefTempNum >= 0 && proDefTempNum <= 7) ||
- proDefTempNum == 55 || proDefTempNum == 40055 ) // Tile
- startStep = endStep;
+ nrecs++;
- if ( editionNumber > 1 ) GRIB_CHECK(my_grib_set_long(gh, "forecastTime", startStep), 0);
- GRIB_CHECK(my_grib_set_long(gh, "endStep", endStep), 0);
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, param, rlevel, vdate, vtime);
- status = 0;
+ iegAddRecord(streamptr, param, iegp->ipdb, iegp->igdb, iegp->vct, recsize, recpos, prec);
}
- return (status);
-}
+ streamptr->rtsteps = 1;
-static
-void gribapiDefTime(int editionNumber, int productDefinitionTemplate, int typeOfGeneratingProcess, grib_handle *gh,
- int vdate, int vtime, int tsteptype, int numavg, int taxisID, int gcinit)
-{
- int taxistype = -1;
+ cdi_generate_vars(streamptr);
- UNUSED(numavg);
+ taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = (int)datetime0.date;
+ taxis->vtime = (int)datetime0.time;
- if ( taxisID != -1 ) taxistype = taxisInqType(taxisID);
+ vlistID = streamptr->vlistID;
+ vlistDefTaxis(vlistID, taxisID);
- if ( typeOfGeneratingProcess == 196 )
- {
- vdate = 10101;
- vtime = 0;
- taxistype = TAXIS_ABSOLUTE;
- }
- /*
- else if ( typeOfGeneratingProcess == 9 )
+ vlist_check_contents(vlistID);
+
+ nrecords = streamptr->tsteps[0].nallrecs;
+ if ( nrecords < streamptr->tsteps[0].recordSize )
{
+ streamptr->tsteps[0].recordSize = nrecords;
+ streamptr->tsteps[0].records =
+ (record_t *) Realloc(streamptr->tsteps[0].records,
+ (size_t)nrecords * sizeof (record_t));
}
- */
- if ( taxistype == TAXIS_RELATIVE )
- {
- int status;
- int calendar = taxisInqCalendar(taxisID);
- int rdate = taxisInqRdate(taxisID);
- int rtime = taxisInqRtime(taxisID);
- int timeunit = taxisInqTunit(taxisID);
+ streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
+ streamptr->tsteps[0].nrecs = nrecords;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[0].recIDs[recID] = recID;
- status = gribapiDefDateTimeRel(editionNumber, gh, rdate, rtime, vdate, vtime,
- productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, timeunit, calendar, gcinit);
+ if ( streamptr->ntsteps == -1 )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- if ( status != 0 ) taxistype = TAXIS_ABSOLUTE;
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
}
- if ( taxistype == TAXIS_ABSOLUTE )
+ if ( streamptr->ntsteps == 1 )
{
- gribapiDefDateTimeAbs(editionNumber, gh, vdate, vtime, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
+ if ( taxis->vdate == 0 && taxis->vtime == 0 )
+ {
+ streamptr->ntsteps = 0;
+ for ( varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ }
}
}
static
-void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, int lieee, int datatype, int nmiss, int gcinit)
+int iegScanTimestep2(stream_t *streamptr)
{
int status;
- static short lwarn = TRUE;
+ int fileID;
+ int tabnum;
+ int param = 0;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ int tsID;
+ int varID;
+ size_t recsize;
+ off_t recpos = 0;
+ int nrecords, nrecs, recID, rindex;
+ int nextstep;
+ taxis_t *taxis;
+ int vlistID;
+ IEGCOMPVAR compVar, compVar0;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- UNUSED(nmiss);
+ streamptr->curTsID = 1;
- int gridtype = gridInqType(gridID);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
- if ( editionNumber <= 1 )
- if ( gridtype == GRID_GME || gridtype == GRID_UNSTRUCTURED )
- gridtype = -1;
+ tsID = streamptr->rtsteps;
+ if ( tsID != 1 )
+ Error("Internal problem! unexpected timestep %d", tsID+1);
- if ( gridtype == GRID_GENERIC )
+ taxis = &streamptr->tsteps[tsID].taxis;
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+
+ cdi_create_records(streamptr, tsID);
+
+ nrecords = streamptr->tsteps[0].nallrecs;
+ streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
+ streamptr->tsteps[1].nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[1].recIDs[recID] = -1;
+
+ for ( recID = 0; recID < nrecords; recID++ )
{
- int xsize, ysize, gridsize;
+ varID = streamptr->tsteps[0].records[recID].varID;
+ streamptr->tsteps[tsID].records[recID].position =
+ streamptr->tsteps[0].records[recID].position;
+ streamptr->tsteps[tsID].records[recID].size =
+ streamptr->tsteps[0].records[recID].size;
+ }
- gridsize = gridInqSize(gridID);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ for ( rindex = 0; rindex <= nrecords; rindex++ )
+ {
+ recpos = fileGetPos(fileID);
+ status = iegRead(fileID, iegp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = 2;
+ break;
+ }
+ recsize = (size_t)(fileGetPos(fileID) - recpos);
- if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
- ysize == 96 || ysize == 160 || ysize == 192 ||
- ysize == 240 || ysize == 320 || ysize == 384 ||
- ysize == 480 || ysize == 768 ) &&
- (xsize == 2*ysize || xsize == 1) )
+ rcode = IEG_P_Parameter(iegp->ipdb);
+ tabnum = IEG_P_CodeTable(iegp->ipdb);
+ param = cdiEncodeParam(rcode, tabnum, 255);
+
+ if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
+ rlevel = IEG_P_Level1(iegp->ipdb);
+ else
+ rlevel = IEG_P_Level2(iegp->ipdb);
+
+ if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
+
+ iegDateTime(iegp->ipdb, &vdate, &vtime);
+
+ if ( rindex == 0 )
{
- gridtype = GRID_GAUSSIAN;
- gridChangeType(gridID, gridtype);
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
}
- else if ( gridsize == 1 )
+
+ compVar.param = param;
+ compVar.level = rlevel;
+ nextstep = FALSE;
+ for ( recID = 0; recID < nrecords; recID++ )
{
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 )
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ nextstep = TRUE;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ break;
+ }
}
- else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
+ if ( recID == nrecords )
{
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ Warning("param %s level %d not defined at timestep 1", paramstr, rlevel);
+ return (CDI_EUFSTRUCT);
}
- }
- else if ( gridtype == GRID_CURVILINEAR )
- {
- if ( lwarn && gridInqSize(gridID) > 1 )
+
+ if ( nextstep ) break;
+
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, param, rlevel, vdate, vtime);
+
+ streamptr->tsteps[tsID].records[recID].size = recsize;
+
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
{
- lwarn = FALSE;
- Warning("Curvilinear grids are unsupported in GRIB format! Created wrong GDS!");
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
+ return (CDI_EUFSTRUCT);
}
- gridtype = GRID_LONLAT;
+
+ streamptr->tsteps[1].records[recID].position = recpos;
}
- if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+ nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
{
- if ( editionNumber != 2 || lieee ) { comptype = 0; }
-
- if ( comptype )
- {
- if ( comptype == COMPRESS_JPEG )
- {
- static const char mesg[] = "grid_jpeg";
- size_t len = sizeof (mesg) - 1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- else if ( comptype == COMPRESS_SZIP )
- {
- static const char mesg[] = "grid_ccsds";
- size_t len = sizeof (mesg) - 1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- else
- {
- static const char mesg[] = "grid_simple";
- size_t len = sizeof (mesg) - 1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- }
+ if ( ! streamptr->tsteps[tsID].records[recID].used )
+ {
+ varID = streamptr->tsteps[tsID].records[recID].varID;
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ else
+ {
+ nrecs++;
+ }
}
+ streamptr->tsteps[tsID].nrecs = nrecs;
- if ( gcinit ) return;
+ streamptr->rtsteps = 2;
- switch (gridtype)
+ if ( streamptr->ntsteps == -1 )
{
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- case GRID_GAUSSIAN_REDUCED:
- case GRID_TRAJECTORY:
- {
- int nlon = 0, nlat;
- double xfirst = 0, xlast = 0, xinc = 0;
- double yfirst = 0, ylast = 0, yinc = 0;
- double latIncr;
-
- if ( gridtype == GRID_GAUSSIAN )
- {
- static const char mesg[] = "regular_gg";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
- }
- else if ( gridtype == GRID_GAUSSIAN_REDUCED )
- {
- static const char mesg[] = "reduced_gg";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
- }
- else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
- {
- static const char mesg[] = "rotated_ll";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
- }
- else
- {
- static const char mesg[] = "regular_ll";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
- }
-
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- if ( gridtype == GRID_GAUSSIAN_REDUCED )
- {
- int *rowlon, i;
- long *pl = NULL;
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
- nlon = 0;
+ return (0);
+}
- rowlon = (int *) Malloc((size_t)nlat*sizeof(int));
- pl = (long *) Malloc((size_t)nlat*sizeof(long));
- gridInqRowlon(gridID, rowlon);
- for ( i = 0; i < nlat; ++i ) pl[i] = rowlon[i];
- // GRIB_CHECK(my_grib_set_long_array(gh, "pl", pl, nlat), 0);
+int iegInqContents(stream_t *streamptr)
+{
+ int fileID;
+ int status = 0;
- Free(pl);
- Free(rowlon);
- }
- else
- {
- if ( nlon == 0 )
- {
- nlon = 1;
- }
- else
- {
- xfirst = gridInqXval(gridID, 0);
- xlast = gridInqXval(gridID, nlon-1);
- xinc = gridInqXinc(gridID);
- }
- }
+ fileID = streamptr->fileID;
- if ( nlat == 0 )
- {
- nlat = 1;
- }
- else
- {
- yfirst = gridInqYval(gridID, 0);
- ylast = gridInqYval(gridID, nlat-1);
- yinc = gridInqYinc(gridID);
- }
+ streamptr->curTsID = 0;
- GRIB_CHECK(my_grib_set_long(gh, "Ni", nlon), 0);
- GRIB_CHECK(my_grib_set_long(gh, "Nj", nlat), 0);
- GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", xfirst), 0);
- GRIB_CHECK(my_grib_set_double(gh, "longitudeOfLastGridPointInDegrees", xlast), 0);
- GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", yfirst), 0);
- GRIB_CHECK(my_grib_set_double(gh, "latitudeOfLastGridPointInDegrees", ylast), 0);
- GRIB_CHECK(my_grib_set_double(gh, "iDirectionIncrementInDegrees", xinc), 0);
+ iegScanTimestep1(streamptr);
- {
- long jscan = 0;
- if ( yfirst < ylast ) jscan = 1;
- GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jscan), 0);
- }
- /*
- if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON )
- ISEC2_LonIncr = 0;
- */
- if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
- {
- int np = gridInqNP(gridID);
- if ( np == 0 ) np = nlat/2;
- GRIB_CHECK(my_grib_set_long(gh, "numberOfParallelsBetweenAPoleAndTheEquator", np), 0);
- }
- else
- {
- latIncr = yinc;
- if ( latIncr < 0 ) latIncr = -latIncr;
- GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", latIncr), 0);
- /*
- if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON )
- ISEC2_LatIncr = 0;
- */
- }
- /*
- if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
- if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr;
+ if ( streamptr->ntsteps == -1 ) status = iegScanTimestep2(streamptr);
- if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
- if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
+ fileSetPos(fileID, 0, SEEK_SET);
- if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 )
- ISEC2_ResFlag = 0;
- else
- ISEC2_ResFlag = 128;
- */
- if ( gridIsRotated(gridID) )
- {
- double xpole, ypole, angle;
- xpole = gridInqXpole(gridID);
- ypole = gridInqYpole(gridID);
- angle = gridInqAngle(gridID);
- /* change from north to south pole */
- if ( fabs(ypole) > 0 ) ypole = -ypole;
- xpole = xpole + 180;
- if ( fabs(angle) > 0 ) angle = -angle;
- GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees", ypole), 0);
- GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0);
- GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0);
- }
+ return (status);
+}
- /* East -> West */
- //if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
+static
+long iegScanTimestep(stream_t *streamptr)
+{
+ int status;
+ int fileID;
+ int tsID;
+ int tabnum;
+ int param = 0;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ size_t recsize = 0;
+ off_t recpos = 0;
+ int recID;
+ taxis_t *taxis;
+ int rindex, nrecs = 0;
+ IEGCOMPVAR compVar, compVar0;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- /* South -> North */
- //if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
+ if ( CDI_Debug )
+ {
+ Message("streamID = %d", streamptr->self);
+ Message("cts = %d", streamptr->curTsID);
+ Message("rts = %d", streamptr->rtsteps);
+ Message("nts = %d", streamptr->ntsteps);
+ }
- if ( editionNumber != 2 ) { lieee = 0; comptype = 0; }
+ if ( streamptr->rtsteps == 0 )
+ Error("Internal problem! Missing contents.");
- if ( lieee )
- {
- static const char mesg[] = "grid_ieee";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ tsID = streamptr->rtsteps;
+ taxis = &streamptr->tsteps[tsID].taxis;
- if ( datatype == DATATYPE_FLT64 )
- GRIB_CHECK(my_grib_set_long(gh, "precision", 2), 0);
- else
- GRIB_CHECK(my_grib_set_long(gh, "precision", 1), 0);
- }
- else
- {
- if ( comptype == COMPRESS_JPEG )
- {
- static const char mesg[] = "grid_jpeg";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- else if ( comptype == COMPRESS_SZIP )
- {
- static const char mesg[] = "grid_ccsds";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- else
- {
- static const char mesg[] = "grid_simple";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- }
+ if ( streamptr->tsteps[tsID].recordSize == 0 )
+ {
+ cdi_create_records(streamptr, tsID);
- break;
- }
- case GRID_LCC:
- {
- double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
- int xsize, ysize;
- int projflag, scanflag;
+ nrecs = streamptr->tsteps[1].nrecs;
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ streamptr->tsteps[tsID].nrecs = nrecs;
+ streamptr->tsteps[tsID].recIDs
+ = (int *) Malloc((size_t)nrecs * sizeof (int));
+ for ( recID = 0; recID < nrecs; recID++ )
+ streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
- gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
- &projflag, &scanflag);
+ fileID = streamptr->fileID;
- static const char mesg[] = "lambert";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- GRIB_CHECK(my_grib_set_long(gh, "Nx", xsize), 0);
- GRIB_CHECK(my_grib_set_long(gh, "Ny", ysize), 0);
+ for ( rindex = 0; rindex <= nrecs; rindex++ )
+ {
+ recpos = fileGetPos(fileID);
+ status = iegRead(fileID, iegp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = streamptr->rtsteps + 1;
+ break;
+ }
+ recsize = (size_t)(fileGetPos(fileID) - recpos);
- /* FIXME: lround should probably be round here */
- GRIB_CHECK(my_grib_set_double(gh, "DxInMetres", (double)lround(xincm)), 0);
- /* FIXME: lround should probably be round here */
- GRIB_CHECK(my_grib_set_double(gh, "DyInMetres", (double)lround(yincm)), 0);
- GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", originLon), 0);
- GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", originLat), 0);
- GRIB_CHECK(my_grib_set_double(gh, "LoVInDegrees", lonParY), 0);
- GRIB_CHECK(my_grib_set_double(gh, "Latin1InDegrees", lat1), 0);
- GRIB_CHECK(my_grib_set_double(gh, "Latin2InDegrees", lat2), 0);
+ rcode = IEG_P_Parameter(iegp->ipdb);
+ tabnum = IEG_P_CodeTable(iegp->ipdb);
+ param = cdiEncodeParam(rcode, tabnum, 255);
- if ( editionNumber <= 1 )
- {
- GRIB_CHECK(my_grib_set_long(gh, "projectionCenterFlag", projflag), 0);
- GRIB_CHECK(my_grib_set_long(gh, "scanningMode", scanflag), 0);
- }
- /*
- ISEC2_Lambert_LatSP = 0;
- ISEC2_Lambert_LatSP = 0;
- */
- break;
- }
- case GRID_SPECTRAL:
- {
- int trunc = gridInqTrunc(gridID);
+ if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
+ rlevel = IEG_P_Level1(iegp->ipdb);
+ else
+ rlevel = IEG_P_Level2(iegp->ipdb);
- static const char mesg[] = "sh";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+ if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
- GRIB_CHECK(my_grib_set_long(gh, "J", trunc), 0);
- GRIB_CHECK(my_grib_set_long(gh, "K", trunc), 0);
- GRIB_CHECK(my_grib_set_long(gh, "M", trunc), 0);
+ iegDateTime(iegp->ipdb, &vdate, &vtime);
- // GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridInqSize(gridID)), 0);
- /*
- if ( lieee )
- {
- printf("spectral_ieee\n");
- if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridInqSize(gridID)), 0);
- static const char mesg[] = "spectral_ieee";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
- else */ if ( gridInqComplexPacking(gridID) )
- {
- if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridInqSize(gridID)), 0);
- static const char mesg[] = "spectral_complex";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
+ // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
+ if ( rindex == nrecs ) continue;
+ recID = streamptr->tsteps[tsID].recIDs[rindex];
- GRIB_CHECK(my_grib_set_long(gh, "JS", 20), 0);
- GRIB_CHECK(my_grib_set_long(gh, "KS", 20), 0);
- GRIB_CHECK(my_grib_set_long(gh, "MS", 20), 0);
- }
- else
- {
- static const char mesg[] = "spectral_simple";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
+ if ( rindex == 0 )
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
+ }
- break;
- }
- case GRID_GME:
- {
- GRIB_CHECK(my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_GME), 0);
+ compVar.param = param;
+ compVar.level = rlevel;
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
- GRIB_CHECK(my_grib_set_long(gh, "nd", gridInqGMEnd(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "Ni", gridInqGMEni(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "n2", gridInqGMEni2(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "n3", gridInqGMEni3(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "latitudeOfThePolePoint", 90000000), 0);
- GRIB_CHECK(my_grib_set_long(gh, "longitudeOfThePolePoint", 0), 0);
+ if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
+ Error("Invalid, unsupported or inconsistent record structure");
+ }
- GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridInqSize(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridInqSize(gridID)), 0);
+ streamptr->tsteps[tsID].records[recID].position = recpos;
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- if ( comptype == COMPRESS_SZIP )
- {
- static const char mesg[] = "grid_ccsds";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, param, rlevel, vdate, vtime);
+ }
- break;
- }
- case GRID_UNSTRUCTURED:
- {
- static int warning = 1;
+ streamptr->rtsteps++;
- status = my_grib_set_long(gh, "gridDefinitionTemplateNumber", GRIB2_GTYPE_UNSTRUCTURED);
- if ( status != 0 && warning )
- {
- warning = 0;
- Warning("Can't write reference grid!");
- Warning("gridDefinitionTemplateNumber %d not found (grib2/template.3.%d.def)!",
- GRIB2_GTYPE_UNSTRUCTURED, GRIB2_GTYPE_UNSTRUCTURED);
- }
- else
- {
- unsigned char uuid[CDI_UUID_SIZE];
- int position = gridInqPosition(gridID);
- int number = gridInqNumber(gridID);
- if ( position < 0 ) position = 0;
- if ( number < 0 ) number = 0;
- GRIB_CHECK(my_grib_set_long(gh, "numberOfGridUsed", number), 0);
- GRIB_CHECK(my_grib_set_long(gh, "numberOfGridInReference", position), 0);
- size_t len = CDI_UUID_SIZE;
- gridInqUUID(gridID, uuid);
- if (grib_set_bytes(gh, "uuidOfHGrid", uuid, &len) != 0)
- Warning("Can't write UUID!");
- }
+ if ( streamptr->ntsteps != streamptr->rtsteps )
+ {
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- if ( comptype == COMPRESS_SZIP )
- {
- static const char mesg[] = "grid_ccsds";
- size_t len = sizeof (mesg) -1;
- GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
- }
+ streamptr->tsteps[tsID-1].next = 1;
+ streamptr->tsteps[tsID].position = recpos;
+ }
- break;
- }
- default:
- {
- Error("Unsupported grid type: %s", gridNamePtr(gridtype));
- break;
- }
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ streamptr->tsteps[tsID].position = recpos;
+ }
+
+ if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
+ {
+ Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
+ streamptr->ntsteps = tsID;
}
+
+ return (streamptr->ntsteps);
}
-static
-void getLevelFactor(double level, long *factor, long *out_scaled_value)
+
+int iegInqTimestep(stream_t *streamptr, int tsID)
{
- double scaled_value = level;
- /* FIXME: lround might be better here */
- long iscaled_value = (long) round(scaled_value);
- long i;
+ int nrecs;
- const double eps = 1.e-8;
- for ( i=0; (fabs(scaled_value - (double) iscaled_value) >= eps) && i < 7; i++ )
+ if ( tsID == 0 && streamptr->rtsteps == 0 )
+ Error("Call to cdiInqContents missing!");
+
+ if ( CDI_Debug )
+ Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
+
+ long ntsteps = UNDEFID;
+ while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
+ ntsteps = iegScanTimestep(streamptr);
+
+ if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
{
- scaled_value *= 10.;
- /* FIXME: lround might be better here */
- iscaled_value = (long)round(scaled_value);
+ nrecs = 0;
+ }
+ else
+ {
+ streamptr->curTsID = tsID;
+ nrecs = streamptr->tsteps[tsID].nrecs;
}
- (*factor) = i;
- (*out_scaled_value) = iscaled_value;
+ return (nrecs);
}
-static
-void gribapiDefLevelType(grib_handle *gh, int gcinit, const char *keyname, long leveltype)
-{
- if ( !gcinit ) GRIB_CHECK(my_grib_set_long(gh, keyname, leveltype), 0);
-}
-static
-void grib2DefLevel(grib_handle *gh, int gcinit, long leveltype1, long leveltype2, int lbounds, double level, double dlevel1, double dlevel2)
+void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
{
- long scaled_level;
- long factor;
+ int vlistID, fileID;
+ int levID, nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *iegp = streamptr->record->exsep;
- gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", leveltype1);
- if ( lbounds ) gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", leveltype2);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
- if ( !lbounds ) dlevel1 = level;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- getLevelFactor(dlevel1, &factor, &scaled_level);
- GRIB_CHECK(my_grib_set_long(gh, "scaleFactorOfFirstFixedSurface", factor), 0);
- GRIB_CHECK(my_grib_set_long(gh, "scaledValueOfFirstFixedSurface", scaled_level), 0);
+ currentfilepos = fileGetPos(fileID);
- if ( lbounds )
+ for (levID = 0; levID < nlevs; levID++)
{
- getLevelFactor(dlevel2, &factor, &scaled_level);
- GRIB_CHECK(my_grib_set_long(gh, "scaleFactorOfSecondFixedSurface", factor), 0);
- GRIB_CHECK(my_grib_set_long(gh, "scaledValueOfSecondFixedSurface", scaled_level), 0);
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ iegRead(fileID, iegp);
+ iegInqDataDP(iegp, &data[levID*gridsize]);
}
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+
+ *nmiss = 0;
+ for ( i = 0; i < nlevs*gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
+ {
+ data[i] = missval;
+ (*nmiss)++;
+ }
}
-static
-void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit, int proddef_template_num)
+
+void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
{
- int lbounds = 0;
- static int warning = 1;
- double dlevel1 = 0, dlevel2 = 0;
+ int vlistID, fileID;
+ int nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *iegp = streamptr->record->exsep;
- int zaxistype = zaxisInqType(zaxisID);
- int ltype = zaxisInqLtype(zaxisID);
- int ltype2 = zaxisInqLtype2(zaxisID);
- double level = zaxisInqLevel(zaxisID, levelID);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- lbounds = 1;
- dlevel1 = zaxisInqLbound(zaxisID, levelID);
- dlevel2 = zaxisInqUbound(zaxisID, levelID);
- }
- else
- {
- dlevel1 = level;
- dlevel2 = 0;
- }
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d",
+ nlevs, gridID, gridsize);
- if ( zaxistype == ZAXIS_GENERIC && ltype == 0 )
- {
- Message("Changed zaxis type from %s to %s", zaxisNamePtr(zaxistype), zaxisNamePtr(ZAXIS_PRESSURE));
- zaxistype = ZAXIS_PRESSURE;
- zaxisChangeType(zaxisID, zaxistype);
- zaxisDefUnits(zaxisID, "Pa");
- }
+ currentfilepos = fileGetPos(fileID);
- int grib2ltype = zaxisTypeToGrib2ltype(zaxistype);
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ iegRead(fileID, iegp);
+ iegInqDataDP(iegp, data);
- switch (zaxistype)
- {
- case ZAXIS_SURFACE:
- case ZAXIS_MEANSEA:
- case ZAXIS_HEIGHT:
- case ZAXIS_ALTITUDE:
- case ZAXIS_SIGMA:
- case ZAXIS_DEPTH_BELOW_SEA:
- case ZAXIS_ISENTROPIC:
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+
+ *nmiss = 0;
+ for ( i = 0; i < gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
{
- if ( editionNumber <= 1 )
- {
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
- GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
- }
- else
- {
- /* PRODUCT DEFINITION TEMPLATE NUMBER 32:
+ data[i] = missval;
+ (*nmiss)++;
+ }
+}
- "Analysis or forecast at a horizontal level or in a horizontal layer at a point
- in time for simulate (synthetic) satellite data"
- The key/value pairs that are set in "grib2DefLevel" do not exist for this template.
- */
- if ( proddef_template_num != 32 )
- grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
- }
+void iegWriteVarDP(stream_t *streamptr, int varID, const double *data)
+{
+ int fileID;
+ int levID, nlevs, gridID, gridsize;
+ int zaxisID;
+ int datatype;
+ int tsID;
+ int vlistID;
+ int i;
+ int date, time;
+ int param, pdis, pcat, pnum;
+ double refval;
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
- break;
- }
- case ZAXIS_CLOUD_BASE:
- case ZAXIS_CLOUD_TOP:
- case ZAXIS_ISOTHERM_ZERO:
- case ZAXIS_TOA:
- case ZAXIS_SEA_BOTTOM:
- case ZAXIS_LAKE_BOTTOM:
- case ZAXIS_SEDIMENT_BOTTOM:
- case ZAXIS_SEDIMENT_BOTTOM_TA:
- case ZAXIS_SEDIMENT_BOTTOM_TW:
- case ZAXIS_MIX_LAYER:
- case ZAXIS_ATMOSPHERE:
- {
- if ( editionNumber <= 1 )
- {
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
- if ( lbounds )
- {
- GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
- GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
- }
- else
- {
- GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
- }
- }
- else
- {
- grib2DefLevel(gh, gcinit, grib2ltype, grib2ltype, lbounds, level, dlevel1, dlevel2);
- }
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d", streamptr->self, varID);
- break;
- }
- case ZAXIS_HYBRID:
- case ZAXIS_HYBRID_HALF:
- {
- if ( editionNumber <= 1 )
- {
- if ( lbounds )
- {
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID_LAYER);
- GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
- GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
- }
- else
- {
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_HYBRID);
- GRIB_CHECK(my_grib_set_long(gh, "level", (long) level), 0);
- }
- }
- else
- {
- grib2DefLevel(gh, gcinit, GRIB2_LTYPE_HYBRID, GRIB2_LTYPE_HYBRID, lbounds, level, dlevel1, dlevel2);
- }
+ iegInitMem(iegp);
+ for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
- if ( !gcinit )
- {
- int vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && warning )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Warning("VCT missing ( param = %s, zaxisID = %d )", paramstr, zaxisID);
- warning = 0;
- }
- GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
- GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
- }
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ nlevs = zaxisInqSize(zaxisID);
+
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+
+ param = vlistInqVarParam(vlistID, varID);
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ IEG_P_Parameter(iegp->ipdb) = pnum;
+ if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
+ date = streamptr->tsteps[tsID].taxis.vdate;
+ time = streamptr->tsteps[tsID].taxis.vtime;
+
+ iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
+ iegDefGrid(iegp->igdb, gridID);
+
+ datatype = vlistInqVarDatatype(vlistID, varID);
+
+ iegp->dprec = iegDefDatatype(datatype);
+
+ for ( levID = 0; levID < nlevs; levID++ )
+ {
+ iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID);
+
+ refval = data[0];
+ for ( i = 1; i < gridsize; i++ )
+ if ( data[levID*gridsize+i] < refval ) refval = data[levID*gridsize+i];
+
+ iegp->refval = refval;
+
+ iegDefDataDP(iegp, &data[levID*gridsize]);
+ iegWrite(fileID, iegp);
+ }
+}
+
+
+void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
+{
+ int fileID;
+ int gridID;
+ int zaxisID;
+ /* double level; */
+ int datatype;
+ /* int tsID; */
+ int vlistID;
+ /* int param, date, time, datasize; */
+ iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* tsID = streamptr->curTsID; */
+ gridID = vlistInqVarGrid(vlistID, varID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ (void)levID;
+ /* level = zaxisInqLevel(zaxisID, levID); */
+
+ if ( CDI_Debug )
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+
+ /* param = vlistInqVarParam(vlistID, varID); */
+ /* date = streamptr->tsteps[tsID].taxis.vdate; */
+ /* time = streamptr->tsteps[tsID].taxis.vtime; */
+ /* datasize = gridInqSize(gridID); */
- break;
- }
- case ZAXIS_PRESSURE:
- {
- double dum;
- char units[128];
+ datatype = vlistInqVarDatatype(vlistID, varID);
- if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level);
+ iegp->dprec = iegDefDatatype(datatype);
- zaxisInqUnits(zaxisID, units);
- if ( memcmp(units, "Pa", 2) != 0 )
- {
- level *= 100;
- dlevel1 *= 100;
- dlevel2 *= 100;
- }
+ iegDefDataDP(iegp, data);
+ iegWrite(fileID, iegp);
+}
- if ( editionNumber <= 1 )
- {
- long leveltype = GRIB1_LTYPE_ISOBARIC;
+#endif /* HAVE_LIBIEG */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
+#endif
- if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
- leveltype = GRIB1_LTYPE_99;
- else
- level /= 100;
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", leveltype);
- GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
- }
- else
- {
- if ( ltype2 == -1 ) ltype2 = GRIB2_LTYPE_ISOBARIC;
- grib2DefLevel(gh, gcinit, GRIB2_LTYPE_ISOBARIC, ltype2, lbounds, level, dlevel1, dlevel2);
- }
- break;
- }
- case ZAXIS_SNOW:
- {
- if ( editionNumber <= 1 )
- ; // not available
- else
- {
- grib2DefLevel(gh, gcinit, GRIB2_LTYPE_SNOW, GRIB2_LTYPE_SNOW, lbounds, level, dlevel1, dlevel2);
- }
- break;
- }
- case ZAXIS_DEPTH_BELOW_LAND:
- {
- char units[128];
- zaxisInqUnits(zaxisID, units);
+void recordInitEntry(record_t *record)
+{
+ record->position = CDI_UNDEFID;
+ record->size = 0;
+ record->param = 0;
+ record->ilevel = CDI_UNDEFID;
+ record->used = FALSE;
+ record->varID = CDI_UNDEFID;
+ record->levelID = CDI_UNDEFID;
+ memset(record->varname, 0, sizeof(record->varname));
+ memset(&record->tiles, 0, sizeof(record->tiles));
+}
- if ( editionNumber <= 1 )
- {
- double scalefactor;
- if ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.1;
- else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 1; // cm
- else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 10;
- else scalefactor = 100;
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", GRIB1_LTYPE_LANDDEPTH);
- GRIB_CHECK(my_grib_set_double(gh, "level", level*scalefactor), 0);
- }
- else
- {
- double scalefactor;
- if ( memcmp(units, "mm", 2) == 0 ) scalefactor = 0.001;
- else if ( memcmp(units, "cm", 2) == 0 ) scalefactor = 0.01;
- else if ( memcmp(units, "dm", 2) == 0 ) scalefactor = 0.1;
- else scalefactor = 1; // meter
+int recordNewEntry(stream_t *streamptr, int tsID)
+{
+ size_t recordID = 0;
+ size_t recordSize = (size_t)streamptr->tsteps[tsID].recordSize;
+ record_t *records = streamptr->tsteps[tsID].records;
+ /*
+ Look for a free slot in record.
+ (Create the table the first time through).
+ */
+ if ( ! recordSize )
+ {
+ recordSize = 1; /* <<<<---- */
+ records = (record_t *) Malloc(recordSize * sizeof (record_t));
- level *= scalefactor;
- dlevel1 *= scalefactor;
- dlevel2 *= scalefactor;
+ for ( size_t i = 0; i < recordSize; i++ )
+ records[i].used = CDI_UNDEFID;
+ }
+ else
+ {
+ while ( recordID < recordSize
+ && records[recordID].used != CDI_UNDEFID )
+ ++recordID;
+ }
+ /*
+ If the table overflows, double its size.
+ */
+ if ( recordID == recordSize )
+ {
+ if (recordSize <= INT_MAX / 2)
+ recordSize *= 2;
+ else if (recordSize < INT_MAX)
+ recordSize = INT_MAX;
+ else
+ Error("Cannot handle this many records!\n");
+ records = (record_t *) Realloc(records,
+ recordSize * sizeof (record_t));
- grib2DefLevel(gh, gcinit, GRIB2_LTYPE_LANDDEPTH, GRIB2_LTYPE_LANDDEPTH, lbounds, level, dlevel1, dlevel2);
- }
+ for ( size_t i = recordID; i < recordSize; i++ )
+ records[i].used = CDI_UNDEFID;
+ }
- break;
- }
- case ZAXIS_REFERENCE:
- {
- unsigned char uuid[CDI_UUID_SIZE];
+ recordInitEntry(&records[recordID]);
- if ( !gcinit )
- {
- GRIB_CHECK(my_grib_set_long(gh, "genVertHeightCoords", 1), 0);
- }
+ records[recordID].used = 1;
- if ( lbounds )
- {
- if ( editionNumber <= 1 )
- ; // not available
- else
- {
- int number = zaxisInqNumber(zaxisID);
- gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
- gribapiDefLevelType(gh, gcinit, "typeOfSecondFixedSurface", GRIB2_LTYPE_REFERENCE);
- GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
- GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
- size_t len = CDI_UUID_SIZE;
- zaxisInqUUID(zaxisID, uuid);
- if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
- {
- Warning("Can't write UUID!");
- }
- GRIB_CHECK(my_grib_set_long(gh, "topLevel", (long) dlevel1), 0);
- GRIB_CHECK(my_grib_set_long(gh, "bottomLevel", (long) dlevel2), 0);
- }
- }
- else
- {
- if ( editionNumber <= 1 )
- ; // not available
- else
- {
- int number = zaxisInqNumber(zaxisID);
- gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", GRIB2_LTYPE_REFERENCE);
- GRIB_CHECK(my_grib_set_long(gh, "NV", 6), 0);
- GRIB_CHECK(my_grib_set_long(gh, "nlev", zaxisInqNlevRef(zaxisID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "numberOfVGridUsed", number), 0);
- size_t len = CDI_UUID_SIZE;
- zaxisInqUUID(zaxisID, uuid);
- if (grib_set_bytes(gh, "uuidOfVGrid", uuid, &len) != 0)
- {
- Warning("Can't write UUID!");
- }
- GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
- }
- }
+ streamptr->tsteps[tsID].recordSize = (int)recordSize;
+ streamptr->tsteps[tsID].records = records;
- break;
- }
- case ZAXIS_GENERIC:
- {
- if ( editionNumber <= 1 )
- gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", ltype);
- else
- gribapiDefLevelType(gh, gcinit, "typeOfFirstFixedSurface", ltype);
+ return (int)recordID;
+}
- GRIB_CHECK(my_grib_set_double(gh, "level", level), 0);
+static
+void cdiInitRecord(stream_t *streamptr)
+{
+ streamptr->record = (Record *) Malloc(sizeof(Record));
- break;
- }
- default:
- {
- Error("Unsupported zaxis type: %s", zaxisNamePtr(zaxistype));
- break;
- }
- }
+ streamptr->record->param = 0;
+ streamptr->record->level = 0;
+ streamptr->record->date = 0;
+ streamptr->record->time = 0;
+ streamptr->record->gridID = 0;
+ streamptr->record->buffer = NULL;
+ streamptr->record->buffersize = 0;
+ streamptr->record->position = 0;
+ streamptr->record->varID = 0;
+ streamptr->record->levelID = CDI_UNDEFID;
}
-#endif
-/* #define GRIBAPIENCODETEST 1 */
-#ifdef HAVE_LIBGRIB_API
-size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
- int comptype, void *gribContainer)
+void streamInqRecord(int streamID, int *varID, int *levelID)
{
- size_t recsize = 0;
- void *dummy = NULL;
- int lieee = FALSE;
- /* int ensID, ensCount, forecast_type; *//* Ensemble Data */
- int typeOfGeneratingProcess;
- int productDefinitionTemplate;
- long bitsPerValue;
- long editionNumber = 2;
- char name[256];
- char stdname[256];
- gribContainer_t *gc = (gribContainer_t *) gribContainer;
- // extern unsigned char _grib_template_GRIB2[];
-
- int param = vlistInqVarParam(vlistID, varID);
- int datatype = vlistInqVarDatatype(vlistID, varID);
- typeOfGeneratingProcess = vlistInqVarTypeOfGeneratingProcess(vlistID, varID);
- productDefinitionTemplate = vlistInqVarProductDefinitionTemplate(vlistID, varID);
+ check_parg(varID);
+ check_parg(levelID);
- vlistInqVarName(vlistID, varID, name);
- vlistInqVarStdname(vlistID, varID, stdname);
+ stream_t *streamptr = stream_to_pointer(streamID);
-#if defined(GRIBAPIENCODETEST)
- grib_handle *gh = (grib_handle *) gribHandleNew(editionNumber);
-#else
- grib_handle *gh = (struct grib_handle *)gc->gribHandle;
-#endif
- GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
+ cdiDefAccesstype(streamID, TYPE_REC);
- if ( editionNumber == 2 )
- {
- if ( typeOfGeneratingProcess == -1 ) typeOfGeneratingProcess = 0;
- if ( ! gc->init ) GRIB_CHECK(my_grib_set_long(gh, "typeOfGeneratingProcess", typeOfGeneratingProcess), 0);
- }
+ if ( ! streamptr->record ) cdiInitRecord(streamptr);
- /*
- if( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
- {
- GRIB_CHECK(my_grib_set_long(gh, "typeOfEnsembleForecast", forecast_type ), 0);
- GRIB_CHECK(my_grib_set_long(gh, "numberOfForecastsInEnsemble", ensCount ), 0);
- GRIB_CHECK(my_grib_set_long(gh, "perturbationNumber", ensID ), 0);
- }
- */
+ int tsID = streamptr->curTsID;
+ int rindex = streamptr->tsteps[tsID].curRecID + 1;
- gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+ if ( rindex >= streamptr->tsteps[tsID].nrecs )
+ Error("record %d not available at timestep %d", rindex+1, tsID+1);
- if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
- if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
+ int recID = streamptr->tsteps[tsID].recIDs[rindex];
- if ( ! gc->init ) gribapiDefParam((int)editionNumber, gh, param, name, stdname);
+ if ( recID == -1 || recID >= streamptr->tsteps[tsID].nallrecs )
+ Error("Internal problem! tsID = %d recID = %d", tsID, recID);
- if ( editionNumber == 2 && (datatype == DATATYPE_FLT32 || datatype == DATATYPE_FLT64) ) lieee = TRUE;
+ *varID = streamptr->tsteps[tsID].records[recID].varID;
+ int lindex = streamptr->tsteps[tsID].records[recID].levelID;
- /* bitsPerValue have to be defined before call to DefGrid (complex packing) */
- // if ( lieee == FALSE )
- {
- bitsPerValue = grbBitsPerValue(datatype);
- GRIB_CHECK(my_grib_set_long(gh, "bitsPerValue", bitsPerValue), 0);
- }
+ int isub = subtypeInqActiveIndex(streamptr->vars[*varID].subtypeID);
+ *levelID = streamptr->vars[*varID].recordTable[isub].lindex[lindex];
- gribapiDefGrid((int)editionNumber, gh, gridID, comptype, lieee, datatype, nmiss, gc->init);
+ if ( CDI_Debug )
+ Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n", tsID, recID, *varID, *levelID);
- gribapiDefLevel((int)editionNumber, gh, param, zaxisID, levelID, gc->init, productDefinitionTemplate);
+ streamptr->curTsID = tsID;
+ streamptr->tsteps[tsID].curRecID = rindex;
+}
- vlist_t *vlistptr = vlist_to_pointer(vlistID);
- //if (!gc->init)
- {
- int ret = 0;
+/*
+ at Function streamDefRecord
+ at Title Define the next record
- /* NOTE: Optional key/value pairs: Note that we do not distinguish
- * between tiles here! */
+ at Prototype void streamDefRecord(int streamID, int varID, int levelID)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
- for ( int i=0; i<vlistptr->vars[varID].opt_grib_nentries; i++ )
- {
- if ( vlistptr->vars[varID].opt_grib_kvpair[i].update )
- {
- //DR: Fix for multi-level fields (otherwise only the 1st level is correct)
- if ( zaxisInqSize(zaxisID)==(levelID+1) )
- vlistptr->vars[varID].opt_grib_kvpair[i].update = FALSE;
+ at Description
+The function streamDefRecord defines the meta-data of the next record.
+ at EndFunction
+*/
+void streamDefRecord(int streamID, int varID, int levelID)
+{
+ stream_t *streamptr = stream_to_pointer(streamID);
- if (vlistptr->vars[varID].opt_grib_kvpair[i].data_type == t_double)
- {
- if ( CDI_Debug )
- Message("key \"%s\" : double value = %g\n",
- vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
- vlistptr->vars[varID].opt_grib_kvpair[i].dbl_val);
- my_grib_set_double(gh, vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
- vlistptr->vars[varID].opt_grib_kvpair[i].dbl_val);
- GRIB_CHECK(ret, 0);
- }
- if (vlistptr->vars[varID].opt_grib_kvpair[i].data_type == t_int)
- {
- if ( CDI_Debug )
- Message("key \"%s\" : integer value = %d\n",
- vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
- vlistptr->vars[varID].opt_grib_kvpair[i].int_val);
- my_grib_set_long(gh, vlistptr->vars[varID].opt_grib_kvpair[i].keyword,
- (long) vlistptr->vars[varID].opt_grib_kvpair[i].int_val);
- GRIB_CHECK(ret, 0);
- }
- }
- }
- }
+ int tsID = streamptr->curTsID;
- if ( nmiss > 0 )
+ if ( tsID == CDI_UNDEFID )
{
- GRIB_CHECK(my_grib_set_long(gh, "bitmapPresent", 1), 0);
- GRIB_CHECK(my_grib_set_double(gh, "missingValue", vlistInqVarMissval(vlistID, varID)), 0);
+ tsID++;
+ streamDefTimestep(streamID, tsID);
}
- GRIB_CHECK(grib_set_double_array(gh, "values", data, (size_t)datasize), 0);
+ if ( ! streamptr->record ) cdiInitRecord(streamptr);
- /* get the size of coded message */
- GRIB_CHECK(grib_get_message(gh, (const void **)&dummy, &recsize), 0);
- recsize += 512; /* add some space for possible filling */
- *gribbuffersize = recsize;
- *gribbuffer = (unsigned char *) Malloc(*gribbuffersize);
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int param = vlistInqVarParam(vlistID, varID);
+ int level = (int)(zaxisInqLevel(zaxisID, levelID));
- /* get a copy of the coded message */
- GRIB_CHECK(grib_get_message_copy(gh, *gribbuffer, &recsize), 0);
+ streamptr->record->varID = varID;
+ streamptr->record->levelID = levelID;
+ streamptr->record->param = param;
+ streamptr->record->level = level;
+ streamptr->record->date = streamptr->tsteps[tsID].taxis.vdate;
+ streamptr->record->time = streamptr->tsteps[tsID].taxis.vtime;
+ streamptr->record->gridID = gridID;
+ streamptr->record->prec = vlistInqVarDatatype(vlistID, varID);
-#if defined(GRIBAPIENCODETEST)
- gribHandleDelete(gh);
+ switch (streamptr->filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grbDefRecord(streamptr);
+ break;
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ srvDefRecord(streamptr);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ extDefRecord(streamptr);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ iegDefRecord(streamptr);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
+ cdfDefRecord(streamptr);
+ break;
#endif
+ default:
+ Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+ break;
+ }
+}
- gc->init = TRUE;
- return (recsize);
-}
-#endif
+void streamCopyRecord(int streamID2, int streamID1)
+{
+ stream_t *streamptr1 = stream_to_pointer(streamID1),
+ *streamptr2 = stream_to_pointer(streamID2);
+ int filetype1 = streamptr1->filetype,
+ filetype2 = streamptr2->filetype,
+ filetype = FILETYPE_UNDEF;
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
+ if ( filetype1 == filetype2 ) filetype = filetype2;
+ else
+ {
+ switch (filetype1)
+ {
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ switch (filetype2)
+ {
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ Warning("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
+ filetype = filetype2;
+ break;
+ }
+ break;
+ }
+ }
+
+ if ( filetype == FILETYPE_UNDEF )
+ Error("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grbCopyRecord(streamptr2, streamptr1);
+ break;
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ srvCopyRecord(streamptr2, streamptr1);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ extCopyRecord(streamptr2, streamptr1);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ iegCopyRecord(streamptr2, streamptr1);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdfCopyRecord(streamptr2, streamptr1);
+ break;
#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+ }
+}
+
+
+void cdi_create_records(stream_t *streamptr, int tsID)
+{
+ unsigned nrecords, maxrecords;
+ record_t *records;
+
+ tsteps_t *sourceTstep = streamptr->tsteps;
+ tsteps_t *destTstep = sourceTstep + tsID;
+ if ( destTstep->records ) return;
+ int vlistID = streamptr->vlistID;
-void streamDefHistory(int streamID, int length, const char *history)
-{
-#ifdef HAVE_LIBNETCDF
- stream_t *streamptr = stream_to_pointer(streamID);
+ if ( tsID == 0 )
+ {
+ maxrecords = 0;
+ int nvars = streamptr->nvars;
+ for ( int varID = 0; varID < nvars; varID++)
+ for (int isub=0; isub<streamptr->vars[varID].subtypeSize; isub++)
+ maxrecords += (unsigned)streamptr->vars[varID].recordTable[isub].nlevs;
+ }
+ else
+ {
+ maxrecords = (unsigned)sourceTstep->recordSize;
+ }
- if ( streamptr->filetype == FILETYPE_NC ||
- streamptr->filetype == FILETYPE_NC2 ||
- streamptr->filetype == FILETYPE_NC4 ||
- streamptr->filetype == FILETYPE_NC4C )
+ if ( tsID == 0 )
{
- char *histstring;
- size_t len;
- if ( history )
+ nrecords = maxrecords;
+ }
+ else if ( tsID == 1 )
+ {
+ nrecords = 0;
+ maxrecords = (unsigned)sourceTstep->recordSize;
+ for ( unsigned recID = 0; recID < maxrecords; recID++ )
{
- len = strlen(history);
- if ( len )
- {
- /* FIXME: what's the point of strdupx? Why not use
- * history argument directly? */
- histstring = strdupx(history);
- cdfDefHistory(streamptr, length, histstring);
- Free(histstring);
- }
+ int varID = sourceTstep->records[recID].varID;
+ nrecords += (varID == CDI_UNDEFID /* varID = CDI_UNDEFID for write mode !!! */
+ || vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT);
+ // printf("varID nrecords %d %d %d \n", varID, nrecords, vlistInqVarTsteptype(vlistID, varID));
}
}
-#else
- (void)streamID; (void)length; (void)history;
-#endif
-}
-
-
-int streamInqHistorySize(int streamID)
-{
- int size = 0;
-#ifdef HAVE_LIBNETCDF
- stream_t *streamptr = stream_to_pointer(streamID);
-
- if ( streamptr->filetype == FILETYPE_NC ||
- streamptr->filetype == FILETYPE_NC2 ||
- streamptr->filetype == FILETYPE_NC4 ||
- streamptr->filetype == FILETYPE_NC4C )
+ else
{
- size = cdfInqHistorySize(streamptr);
+ nrecords = (unsigned)streamptr->tsteps[1].nallrecs;
}
-#else
- (void)streamID;
-#endif
- return (size);
-}
+ // printf("tsID, nrecords %d %d\n", tsID, nrecords);
+ if ( maxrecords > 0 )
+ records = (record_t *) Malloc(maxrecords*sizeof(record_t));
+ else
+ records = NULL;
-void streamInqHistoryString(int streamID, char *history)
-{
-#ifdef HAVE_LIBNETCDF
- stream_t *streamptr = stream_to_pointer(streamID);
+ destTstep->records = records;
+ destTstep->recordSize = (int)maxrecords;
+ destTstep->nallrecs = (int)nrecords;
- if ( streamptr->filetype == FILETYPE_NC ||
- streamptr->filetype == FILETYPE_NC2 ||
- streamptr->filetype == FILETYPE_NC4 ||
- streamptr->filetype == FILETYPE_NC4C )
+ if ( tsID == 0 )
{
- cdfInqHistoryString(streamptr, history);
+ for ( unsigned recID = 0; recID < maxrecords; recID++ )
+ recordInitEntry(&destTstep->records[recID]);
+ }
+ else
+ {
+ memcpy(destTstep->records, sourceTstep->records, (size_t)maxrecords*sizeof(record_t));
+
+ for ( unsigned recID = 0; recID < maxrecords; recID++ )
+ {
+ record_t *curRecord = &sourceTstep->records[recID];
+ destTstep->records[recID].used = curRecord->used;
+ if ( curRecord->used != CDI_UNDEFID && curRecord->varID != -1 ) /* curRecord->varID = -1 for write mode !!! */
+ {
+ if ( vlistInqVarTsteptype(vlistID, curRecord->varID) != TSTEP_CONSTANT )
+ {
+ destTstep->records[recID].position = CDI_UNDEFID;
+ destTstep->records[recID].size = 0;
+ destTstep->records[recID].used = FALSE;
+ }
+ }
+ }
}
-#else
- (void)streamID; (void)history;
-#endif
}
/*
* Local Variables:
@@ -52771,12 +53336,9 @@ void streamInqHistoryString(int streamID, char *history)
#endif
#include <limits.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <float.h>
-#include <math.h>
@@ -52787,16 +53349,16 @@ void streamInqHistoryString(int streamID, char *history)
#define SINGLE_PRECISION 4
#define DOUBLE_PRECISION 8
-#if defined (HAVE_LIBIEG)
+#if defined (HAVE_LIBSERVICE)
typedef struct {
int param;
int level;
-} IEGCOMPVAR;
+} SRVCOMPVAR;
-static int iegInqDatatype(int prec)
+static int srvInqDatatype(int prec)
{
int datatype;
@@ -52807,12 +53369,12 @@ static int iegInqDatatype(int prec)
}
-static int iegDefDatatype(int datatype)
+static int srvDefDatatype(int datatype)
{
int prec;
if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- Error("CDI/IEG library does not support complex numbers!");
+ Error("CDI/SERVICE library does not support complex numbers!");
if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
datatype = DATATYPE_FLT32;
@@ -52824,14 +53386,15 @@ static int iegDefDatatype(int datatype)
}
/* not used
-int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
+int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
{
int status;
int fileID;
int icode, ilevel;
int zaxisID = -1;
+ int header[8];
int vlistID;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ void *srvp = streamptr->record->exsep;
vlistID = streamptr->vlistID;
fileID = streamptr->fileID;
@@ -52839,14 +53402,13 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
*varID = -1;
*levelID = -1;
- status = iegRead(fileID, iegp);
+ status = srvRead(fileID, srvp);
if ( status != 0 ) return (0);
- icode = IEG_P_Parameter(iegp->ipdb);
- if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
- ilevel = IEG_P_Level1(iegp->ipdb);
- else
- ilevel = IEG_P_Level2(iegp->ipdb);
+ srvInqHeader(srvp, header);
+
+ icode = header[0];
+ ilevel = header[1];
*varID = vlistInqVarID(vlistID, icode);
@@ -52860,32 +53422,31 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID)
}
*/
-void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
+void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
{
- int vlistID, fileID;
int status;
- int recID, vrecID, tsID;
- off_t recpos;
- int varID, gridID;
+ int header[8];
+ int gridID;
int i, size;
double missval;
- void *iegp = streamptr->record->exsep;
+ void *srvp = streamptr->record->exsep;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- vrecID = streamptr->tsteps[tsID].curRecID;
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- recpos = streamptr->tsteps[tsID].records[recID].position;
- varID = streamptr->tsteps[tsID].records[recID].varID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
fileSetPos(fileID, recpos, SEEK_SET);
- status = iegRead(fileID, iegp);
+ status = srvRead(fileID, srvp);
if ( status != 0 )
- Error("Could not read IEG record!");
+ Error("Failed to read record from SRV file");
- iegInqDataDP(iegp, data);
+ srvInqHeader(srvp, header);
+ srvInqDataDP(srvp, data);
missval = vlistInqVarMissval(vlistID, varID);
gridID = vlistInqVarGrid(vlistID, varID);
@@ -52902,2965 +53463,3390 @@ void iegReadRecord(stream_t *streamptr, double *data, int *nmiss)
}
}
+
+void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+{
+ streamFCopyRecord(streamptr2, streamptr1, "SRV");
+}
+
+
+void srvDefRecord(stream_t *streamptr)
+{
+ int header[8];
+ Record *restrict record = streamptr->record;
+ srvrec_t *restrict srvp = (srvrec_t*) record->exsep;
+ int gridID = record->gridID;
+
+ int pdis, pcat, pnum;
+ cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
+ header[0] = pnum;
+ header[1] = record->level;
+ header[2] = record->date;
+ header[3] = record->time;
+
+ int xsize = gridInqXsize(gridID),
+ ysize = gridInqYsize(gridID);
+ if ( xsize == 0 || ysize == 0 )
+ {
+ xsize = gridInqSize(gridID);
+ ysize = 1;
+ }
+ if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
+ if ( gridInqSize(gridID) != xsize*ysize )
+ Error("Internal problem with gridsize!");
+
+ header[4] = xsize;
+ header[5] = ysize;
+ header[6] = 0;
+ header[7] = 0;
+
+ int datatype = record->prec;
+
+ srvp->dprec = srvDefDatatype(datatype);
+
+ srvDefHeader(srvp, header);
+}
+
+
+void srvWriteRecord(stream_t *streamptr, const double *data)
+{
+ int fileID = streamptr->fileID;
+ void *srvp = streamptr->record->exsep;
+
+ srvDefDataDP(srvp, data);
+ srvWrite(fileID, srvp);
+}
+
static
-int iegGetZaxisType(int iegleveltype)
+void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ysize,
+ size_t recsize, off_t position, int prec)
{
- int leveltype = 0;
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
- switch ( iegleveltype )
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level;
+
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize);
+ grid->xsize = xsize;
+ grid->ysize = ysize;
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
+ /*
+ if ( level == 0 ) leveltype = ZAXIS_SURFACE;
+ else leveltype = ZAXIS_GENERIC;
+ */
+ int leveltype = ZAXIS_GENERIC;
+
+ int datatype = srvInqDatatype(prec);
+
+ int levelID = 0;
+ int varID;
+ varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
+ datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+
+ xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
+
+ streamptr->tsteps[tsID].nallrecs++;
+ streamptr->nrecs++;
+
+ if ( CDI_Debug )
+ Message("varID = %d gridID = %d levelID = %d",
+ varID, gridID, levelID);
+}
+
+static
+void srvScanTimestep1(stream_t *streamptr)
+{
+ DateTime datetime0 = { LONG_MIN, LONG_MIN };
+ off_t recpos;
+ taxis_t *taxis;
+ srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+
+ streamptr->curTsID = 0;
+
+ {
+ int tsID = tstepsNewEntry(streamptr);
+ if ( tsID != 0 )
+ Error("Internal problem! tstepsNewEntry returns %d", tsID);
+ taxis = &streamptr->tsteps[tsID].taxis;
+ }
+
+
+ int fileID = streamptr->fileID;
+
+ int nrecs = 0;
+ while ( TRUE )
{
- case IEG_LTYPE_SURFACE:
- {
- leveltype = ZAXIS_SURFACE;
- break;
- }
- case IEG_LTYPE_99:
- case IEG_LTYPE_ISOBARIC:
- {
- leveltype = ZAXIS_PRESSURE;
- break;
- }
- case IEG_LTYPE_HEIGHT:
- {
- leveltype = ZAXIS_HEIGHT;
- break;
- }
- case IEG_LTYPE_ALTITUDE:
- {
- leveltype = ZAXIS_ALTITUDE;
- break;
- }
- case IEG_LTYPE_HYBRID:
- case IEG_LTYPE_HYBRID_LAYER:
- {
- leveltype = ZAXIS_HYBRID;
- break;
- }
- case IEG_LTYPE_LANDDEPTH:
- case IEG_LTYPE_LANDDEPTH_LAYER:
- {
- leveltype = ZAXIS_DEPTH_BELOW_LAND;
- break;
- }
- case IEG_LTYPE_SEADEPTH:
- {
- leveltype = ZAXIS_DEPTH_BELOW_SEA;
- break;
- }
- default:
- {
- leveltype = ZAXIS_GENERIC;
- break;
- }
+ int header[8];
+ recpos = fileGetPos(fileID);
+ int status = srvRead(fileID, srvp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = 1;
+ break;
+ }
+ size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
+
+ srvInqHeader(srvp, header);
+
+ int prec = srvp->dprec;
+ int rcode = header[0];
+ int rlevel = header[1];
+ int vdate = header[2];
+ int vtime = header[3];
+ int rxsize = header[4];
+ int rysize = header[5];
+
+ int param = cdiEncodeParam(rcode, 255, 255);
+
+ if ( nrecs == 0 )
+ {
+ datetime0.date = vdate;
+ datetime0.time = vtime;
+ }
+ else
+ {
+ for ( int recID = 0; recID < nrecs; recID++ )
+ if ( streamptr->tsteps[0].records[recID].param == param
+ && streamptr->tsteps[0].records[recID].ilevel == rlevel )
+ goto tstepScanLoopFinished;
+ DateTime datetime = { .date = vdate, .time = vtime };
+ if ( datetimeCmp(datetime, datetime0) )
+ Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
+ }
+
+ nrecs++;
+
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
+
+ srv_add_record(streamptr, param, rlevel, rxsize, rysize, recsize, recpos, prec);
}
- return (leveltype);
+ tstepScanLoopFinished:
+ streamptr->rtsteps = 1;
+
+ cdi_generate_vars(streamptr);
+
+ int taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = (int)datetime0.date;
+ taxis->vtime = (int)datetime0.time;
+
+ int vlistID = streamptr->vlistID;
+ vlistDefTaxis(vlistID, taxisID);
+
+ vlist_check_contents(vlistID);
+
+ int nrecords = streamptr->tsteps[0].nallrecs;
+ if ( nrecords < streamptr->tsteps[0].recordSize )
+ {
+ streamptr->tsteps[0].recordSize = nrecords;
+ streamptr->tsteps[0].records =
+ (record_t *) Realloc(streamptr->tsteps[0].records,
+ (size_t)nrecords * sizeof(record_t));
+ }
+
+ streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
+ streamptr->tsteps[0].nrecs = nrecords;
+ for ( int recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[0].recIDs[recID] = recID;
+
+ if ( streamptr->ntsteps == -1 )
+ {
+ int tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
+
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
+ }
+
+ if ( streamptr->ntsteps == 1 )
+ {
+ if ( taxis->vdate == 0 && taxis->vtime == 0 )
+ {
+ streamptr->ntsteps = 0;
+ for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ }
}
+static
+int srvScanTimestep2(stream_t *streamptr)
+{
+ int header[8];
+ int status;
+ int fileID;
+ int param = 0;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ int tsID;
+ int varID;
+ off_t recpos = 0;
+ int nrecords, nrecs, recID, rindex;
+ int nextstep;
+ taxis_t *taxis;
+ int vlistID;
+ SRVCOMPVAR compVar, compVar0;
+ void *srvp = streamptr->record->exsep;
+
+ streamptr->curTsID = 1;
+
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+
+ tsID = streamptr->rtsteps;
+ if ( tsID != 1 )
+ Error("Internal problem! unexpected timestep %d", tsID+1);
+
+ taxis = &streamptr->tsteps[tsID].taxis;
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+
+ cdi_create_records(streamptr, tsID);
+
+ nrecords = streamptr->tsteps[0].nallrecs;
+ streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
+ streamptr->tsteps[1].nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ streamptr->tsteps[1].recIDs[recID] = -1;
+
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ varID = streamptr->tsteps[0].records[recID].varID;
+ streamptr->tsteps[tsID].records[recID].position =
+ streamptr->tsteps[0].records[recID].position;
+ streamptr->tsteps[tsID].records[recID].size =
+ streamptr->tsteps[0].records[recID].size;
+ }
+
+ for ( rindex = 0; rindex <= nrecords; rindex++ )
+ {
+ recpos = fileGetPos(fileID);
+ status = srvRead(fileID, srvp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = 2;
+ break;
+ }
+ size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
+
+ srvInqHeader(srvp, header);
+
+ rcode = header[0];
+ rlevel = header[1];
+ vdate = header[2];
+ vtime = header[3];
+
+ param = cdiEncodeParam(rcode, 255, 255);
+
+ if ( rindex == 0 )
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
+ }
+
+ compVar.param = param;
+ compVar.level = rlevel;
+ nextstep = FALSE;
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) == 0 )
+ {
+ if ( streamptr->tsteps[tsID].records[recID].used )
+ {
+ nextstep = TRUE;
+ }
+ else
+ {
+ streamptr->tsteps[tsID].records[recID].used = TRUE;
+ streamptr->tsteps[tsID].recIDs[rindex] = recID;
+ }
+ break;
+ }
+ }
+ if ( recID == nrecords )
+ {
+ Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
+ return (CDI_EUFSTRUCT);
+ }
+
+ if ( nextstep ) break;
+
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
+
+ streamptr->tsteps[tsID].records[recID].size = recsize;
+
+ compVar0.param = streamptr->tsteps[tsID].records[recID].param;
+ compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+
+ if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) != 0 )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
+ return (CDI_EUFSTRUCT);
+ }
+
+ streamptr->tsteps[1].records[recID].position = recpos;
+ }
-static void iegDefTime(int *pdb, int date, int time, int taxisID)
-{
- int year, month, day, hour, minute, second;
- int timetype = -1;
+ nrecs = 0;
+ for ( recID = 0; recID < nrecords; recID++ )
+ {
+ if ( ! streamptr->tsteps[tsID].records[recID].used )
+ {
+ varID = streamptr->tsteps[tsID].records[recID].varID;
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ }
+ else
+ {
+ nrecs++;
+ }
+ }
+ streamptr->tsteps[tsID].nrecs = nrecs;
- if ( taxisID != -1 ) timetype = taxisInqType(taxisID);
+ streamptr->rtsteps = 2;
- if ( timetype == TAXIS_ABSOLUTE || timetype == TAXIS_RELATIVE )
+ if ( streamptr->ntsteps == -1 )
{
- cdiDecodeDate(date, &year, &month, &day);
- cdiDecodeTime(time, &hour, &minute, &second);
-
- IEG_P_Year(pdb) = year;
- IEG_P_Month(pdb) = month;
- IEG_P_Day(pdb) = day;
- IEG_P_Hour(pdb) = hour;
- IEG_P_Minute(pdb) = minute;
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
- pdb[15] = 1;
- pdb[16] = 0;
- pdb[17] = 0;
- pdb[18] = 10;
- pdb[36] = 1;
+ streamptr->tsteps[tsID-1].next = TRUE;
+ streamptr->tsteps[tsID].position = recpos;
}
- pdb[5] = 128;
+ return (0);
}
-/* find smallest power of 10 in [1000,10000000] that upon
- * multiplication results in fractional part close to zero for all
- * arguments */
-static double
-calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylast, double yinc)
+
+int srvInqContents(stream_t *streamptr)
{
- double resfac = 1000.0;
- enum {
- nPwrOf10 = 5,
- nMultTests = 6,
- };
- static const double scaleFactors[nPwrOf10]
- = { 1000, 10000, 100000, 1000000, 10000000 };
- double vals[nMultTests] = { xfirst, xlast, xinc, yfirst, ylast, yinc };
+ int fileID;
+ int status = 0;
- for (size_t j = 0; j < nPwrOf10; ++j )
- {
- double scaleBy = scaleFactors[j];
- bool fractionalScale = false;
- for (size_t i = 0; i < nMultTests; ++i )
- {
- fractionalScale = fractionalScale
- || fabs(vals[i]*scaleBy - round(vals[i]*scaleBy)) > FLT_EPSILON;
- }
- if ( !fractionalScale )
- {
- resfac = scaleBy;
- break;
- }
- }
+ fileID = streamptr->fileID;
- return (resfac);
-}
+ streamptr->curTsID = 0;
-static
-void iegDefGrid(int *gdb, int gridID)
-{
- int gridtype;
+ srvScanTimestep1(streamptr);
- gridtype = gridInqType(gridID);
+ if ( streamptr->ntsteps == -1 ) status = srvScanTimestep2(streamptr);
- if ( gridtype == GRID_GENERIC )
- {
- int xsize, ysize;
+ fileSetPos(fileID, 0, SEEK_SET);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ return (status);
+}
- if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
- ysize == 96 || ysize == 160) &&
- (xsize == 2*ysize || xsize == 1) )
- {
- gridtype = GRID_GAUSSIAN;
- gridChangeType(gridID, gridtype);
- }
- else if ( (xsize == 1 && ysize == 1) || (xsize == 0 && ysize == 0) )
- {
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
- }
- else if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) )
- {
- gridtype = GRID_LONLAT;
- gridChangeType(gridID, gridtype);
- }
- }
- else if ( gridtype == GRID_CURVILINEAR )
+static
+long srvScanTimestep(stream_t *streamptr)
+{
+ int header[8];
+ int status;
+ int fileID;
+ /* int rxsize = 0, rysize = 0; */
+ int param = 0;
+ int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
+ off_t recpos = 0;
+ int recID;
+ int rindex, nrecs = 0;
+ void *srvp = streamptr->record->exsep;
+ /*
+ if ( CDI_Debug )
{
- gridtype = GRID_LONLAT;
+ Message("streamID = %d", streamptr->self);
+ Message("cts = %d", streamptr->curTsID);
+ Message("rts = %d", streamptr->rtsteps);
+ Message("nts = %d", streamptr->ntsteps);
}
+ */
- if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+ int tsID = streamptr->rtsteps;
+ taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
+
+ if ( streamptr->tsteps[tsID].recordSize == 0 )
{
- double xfirst = 0, xlast = 0, xinc = 0;
- double yfirst = 0, ylast = 0, yinc = 0;
+ cdi_create_records(streamptr, tsID);
- int nlon = gridInqXsize(gridID),
- nlat = gridInqYsize(gridID);
+ nrecs = streamptr->tsteps[1].nrecs;
- if ( nlon == 0 )
- {
- nlon = 1;
- }
- else
- {
- xfirst = gridInqXval(gridID, 0);
- xlast = gridInqXval(gridID, nlon-1);
- xinc = gridInqXinc(gridID);
- }
+ streamptr->tsteps[tsID].nrecs = nrecs;
+ streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
+ for ( recID = 0; recID < nrecs; recID++ )
+ streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
- if ( nlat == 0 )
- {
- nlat = 1;
- }
- else
- {
- yfirst = gridInqYval(gridID, 0);
- ylast = gridInqYval(gridID, nlat-1);
- yinc = gridInqYinc(gridID);
- }
+ fileID = streamptr->fileID;
- if ( gridtype == GRID_GAUSSIAN )
- IEG_G_GridType(gdb) = 4;
- else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) )
- IEG_G_GridType(gdb) = 10;
- else
- IEG_G_GridType(gdb) = 0;
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- double resfac = calc_resfac(xfirst, xlast, xinc, yfirst, ylast, yinc);
- int iresfac = (int)resfac;
- if ( iresfac == 1000 ) iresfac = 0;
+ for ( rindex = 0; rindex <= nrecs; rindex++ )
+ {
+ recpos = fileGetPos(fileID);
+ status = srvRead(fileID, srvp);
+ if ( status != 0 )
+ {
+ streamptr->ntsteps = streamptr->rtsteps + 1;
+ break;
+ }
+ size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
- IEG_G_ResFac(gdb) = iresfac;
+ srvInqHeader(srvp, header);
- IEG_G_NumLon(gdb) = nlon;
- IEG_G_NumLat(gdb) = nlat;
- IEG_G_FirstLat(gdb) = (int)lround(yfirst*resfac);
- IEG_G_LastLat(gdb) = (int)lround(ylast*resfac);
- IEG_G_FirstLon(gdb) = (int)lround(xfirst*resfac);
- IEG_G_LastLon(gdb) = (int)lround(xlast*resfac);
- IEG_G_LonIncr(gdb) = (int)lround(xinc*resfac);
- if ( fabs(xinc*resfac - IEG_G_LonIncr(gdb)) > FLT_EPSILON )
- IEG_G_LonIncr(gdb) = 0;
+ rcode = header[0];
+ rlevel = header[1];
+ vdate = header[2];
+ vtime = header[3];
+ /* rxsize = header[4]; */
+ /* rysize = header[5]; */
- if ( gridtype == GRID_GAUSSIAN )
- IEG_G_LatIncr(gdb) = nlat/2;
- else
- {
- IEG_G_LatIncr(gdb) = (int)lround(yinc*resfac);
- if ( fabs(yinc*resfac - IEG_G_LatIncr(gdb)) > FLT_EPSILON )
- IEG_G_LatIncr(gdb) = 0;
+ param = cdiEncodeParam(rcode, 255, 255);
- if ( IEG_G_LatIncr(gdb) < 0 ) IEG_G_LatIncr(gdb) = -IEG_G_LatIncr(gdb);
- }
+ // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
+ if ( rindex == nrecs ) continue;
+ recID = streamptr->tsteps[tsID].recIDs[rindex];
- if ( IEG_G_NumLon(gdb) > 1 && IEG_G_NumLat(gdb) == 1 )
- if ( IEG_G_LonIncr(gdb) != 0 && IEG_G_LatIncr(gdb) == 0 ) IEG_G_LatIncr(gdb) = IEG_G_LonIncr(gdb);
+ if ( rindex == 0 )
+ {
+ taxis->type = TAXIS_ABSOLUTE;
+ taxis->vdate = vdate;
+ taxis->vtime = vtime;
+ }
- if ( IEG_G_NumLon(gdb) == 1 && IEG_G_NumLat(gdb) > 1 )
- if ( IEG_G_LonIncr(gdb) == 0 && IEG_G_LatIncr(gdb) != 0 ) IEG_G_LonIncr(gdb) = IEG_G_LatIncr(gdb);
+ if ( param != streamptr->tsteps[tsID].records[recID].param
+ || rlevel != streamptr->tsteps[tsID].records[recID].ilevel )
+ {
+ Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
+ tsID, recID,
+ streamptr->tsteps[tsID].records[recID].param, param,
+ streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
+ Error("Invalid, unsupported or inconsistent record structure!");
+ }
- if ( IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0 )
- IEG_G_ResFlag(gdb) = 0;
- else
- IEG_G_ResFlag(gdb) = 128;
+ streamptr->tsteps[tsID].records[recID].position = recpos;
+ streamptr->tsteps[tsID].records[recID].size = recsize;
- if ( gridIsRotated(gridID) )
- {
- IEG_G_LatSP(gdb) = - (int)lround(gridInqYpole(gridID) * resfac);
- IEG_G_LonSP(gdb) = (int)lround((gridInqXpole(gridID) + 180) * resfac);
- IEG_G_Size(gdb) = 42;
+ if ( CDI_Debug )
+ Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
}
- else
+
+ streamptr->rtsteps++;
+
+ if ( streamptr->ntsteps != streamptr->rtsteps )
{
- IEG_G_Size(gdb) = 32;
+ tsID = tstepsNewEntry(streamptr);
+ if ( tsID != streamptr->rtsteps )
+ Error("Internal error. tsID = %d", tsID);
+
+ streamptr->tsteps[tsID-1].next = 1;
+ streamptr->tsteps[tsID].position = recpos;
}
+
+ fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ streamptr->tsteps[tsID].position = recpos;
}
- else
+
+ if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
{
- Error("Unsupported grid type: %s", gridNamePtr(gridtype));
+ Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
+ streamptr->ntsteps = tsID;
}
- IEG_G_ScanFlag(gdb) = 64;
+ return (streamptr->ntsteps);
}
-static
-void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
+
+int srvInqTimestep(stream_t *streamptr, int tsID)
{
- double level;
- int ilevel, leveltype;
- static int warning = 1;
- static int vct_warning = 1;
+ long ntsteps;
+ int nrecs;
- leveltype = zaxisInqType(zaxisID);
+ if ( tsID == 0 && streamptr->rtsteps == 0 )
+ Error("Call to cdiInqContents missing!");
- if ( leveltype == ZAXIS_GENERIC )
+ if ( CDI_Debug )
+ Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
+
+ ntsteps = UNDEFID;
+ while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
+ ntsteps = srvScanTimestep(streamptr);
+
+ if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID )
{
- Message("Changed zaxis type from %s to %s",
- zaxisNamePtr(leveltype),
- zaxisNamePtr(ZAXIS_PRESSURE));
- leveltype = ZAXIS_PRESSURE;
- zaxisChangeType(zaxisID, leveltype);
- zaxisDefUnits(zaxisID, "Pa");
+ nrecs = 0;
+ }
+ else
+ {
+ streamptr->curTsID = tsID;
+ nrecs = streamptr->tsteps[tsID].nrecs;
}
- /* IEG_G_NumVCP(gdb) = 0; */
+ return (nrecs);
+}
- switch (leveltype)
+
+void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+{
+ int vlistID, fileID;
+ int levID, nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int header[8];
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *srvp = streamptr->record->exsep;
+
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
+
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+
+ currentfilepos = fileGetPos(fileID);
+
+ for (levID = 0; levID < nlevs; levID++)
{
- case ZAXIS_SURFACE:
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ if (srvRead(fileID, srvp) < 0)
+ abort();
+ srvInqHeader(srvp, header);
+ srvInqDataDP(srvp, &data[levID*gridsize]);
+ }
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+
+ *nmiss = 0;
+ for ( i = 0; i < nlevs*gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
{
- IEG_P_LevelType(pdb) = IEG_LTYPE_SURFACE;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID));
- break;
+ data[i] = missval;
+ (*nmiss)++;
}
- case ZAXIS_HYBRID:
- {
- int vctsize;
+}
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID_LAYER;
- IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID));
- IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID));
- }
- else
- {
- IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID));
- }
- vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && warning )
- {
- Warning("VCT missing. ( code = %d, zaxisID = %d )",
- IEG_P_Parameter(pdb), zaxisID);
- warning = 0;
- }
- if ( vctsize > 100 )
- {
- /* IEG_G_NumVCP(gdb) = 0; */
- if ( vct_warning )
- {
- Warning("VCT size of %d is too large (maximum is 100). Set to 0!", vctsize);
- vct_warning = 0;
- }
- }
- else
- {
- IEG_G_Size(gdb) += (vctsize*4);
- memcpy(vct, zaxisInqVctPtr(zaxisID), (size_t)vctsize/2*sizeof(double));
- memcpy(vct+50, zaxisInqVctPtr(zaxisID)+vctsize/2, (size_t)vctsize/2*sizeof(double));
- }
- break;
- }
- case ZAXIS_PRESSURE:
- {
- double dum;
- char units[128];
+void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
+{
+ int vlistID, fileID;
+ int nlevs, gridID, gridsize;
+ off_t recpos, currentfilepos;
+ int header[8];
+ int tsid;
+ int recID;
+ int i;
+ double missval;
+ void *srvp = streamptr->record->exsep;
- level = zaxisInqLevel(zaxisID, levelID);
- if ( level < 0 )
- Warning("pressure level of %f Pa is below 0.", level);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ /* NOTE: tiles are not supported here! */
+ nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ missval = vlistInqVarMissval(vlistID, varID);
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ tsid = streamptr->curTsID;
- zaxisInqUnits(zaxisID, units);
- if ( memcmp(units, "hPa", 3) == 0 || memcmp(units, "mb",2 ) == 0 )
- level = level*100;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d",
+ nlevs, gridID, gridsize);
- ilevel = (int) level;
- if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) )
- {
- IEG_P_LevelType(pdb) = IEG_LTYPE_99;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
- }
- else
- {
- IEG_P_LevelType(pdb) = IEG_LTYPE_ISOBARIC;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel/100;
- }
- break;
- }
- case ZAXIS_HEIGHT:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+ currentfilepos = fileGetPos(fileID);
- ilevel = (int) level;
- IEG_P_LevelType(pdb) = IEG_LTYPE_HEIGHT;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
+ /* NOTE: tiles are not supported here! */
+ recID = streamptr->vars[varID].recordTable[0].recordID[levID];
+ recpos = streamptr->tsteps[tsid].records[recID].position;
+ fileSetPos(fileID, recpos, SEEK_SET);
+ if (srvRead(fileID, srvp) < 0)
+ abort();
+ srvInqHeader(srvp, header);
+ srvInqDataDP(srvp, data);
- break;
- }
- case ZAXIS_ALTITUDE:
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+
+ *nmiss = 0;
+ for ( i = 0; i < gridsize; i++ )
+ if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
{
- level = zaxisInqLevel(zaxisID, levelID);
+ data[i] = missval;
+ (*nmiss)++;
+ }
+}
- ilevel = (int) level;
- IEG_P_LevelType(pdb) = IEG_LTYPE_ALTITUDE;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
- break;
- }
- case ZAXIS_DEPTH_BELOW_LAND:
- {
- if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
- {
- IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH_LAYER;
- IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID));
- IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID));
- }
- else
- {
- level = zaxisInqLevel(zaxisID, levelID);
+void srvWriteVarDP(stream_t *streamptr, int varID, const double *data)
+{
+ int fileID;
+ int levID, nlevs, gridID, gridsize;
+ int zaxisID;
+ double level;
+ int header[8];
+ int xsize, ysize;
+ int datatype;
+ int tsID;
+ int vlistID;
+ int pdis, pcat, pnum;
+ srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
- ilevel = (int) level;
- IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
- }
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d", streamptr->self, varID);
- break;
- }
- case ZAXIS_DEPTH_BELOW_SEA:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ gridsize = gridInqSize(gridID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ nlevs = zaxisInqSize(zaxisID);
- ilevel = (int) level;
- IEG_P_LevelType(pdb) = IEG_LTYPE_SEADEPTH;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- break;
- }
- case ZAXIS_ISENTROPIC:
- {
- level = zaxisInqLevel(zaxisID, levelID);
+ cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
- ilevel = (int) level;
- IEG_P_LevelType(pdb) = 113;
- IEG_P_Level1(pdb) = 0;
- IEG_P_Level2(pdb) = ilevel;
+ header[0] = pnum;
+ header[2] = streamptr->tsteps[tsID].taxis.vdate;
+ header[3] = streamptr->tsteps[tsID].taxis.vtime;
- break;
- }
- default:
- {
- Error("Unsupported zaxis type: %s", zaxisNamePtr(leveltype));
- break;
- }
+ xsize = gridInqXsize(gridID);
+ ysize = gridInqYsize(gridID);
+ if ( xsize == 0 || ysize == 0 )
+ {
+ xsize = gridInqSize(gridID);
+ ysize = 1;
}
-}
+ if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
+ if ( gridInqSize(gridID) != xsize*ysize )
+ Error("Internal problem with gridsize!");
+ header[4] = xsize;
+ header[5] = ysize;
+ header[6] = 0;
+ header[7] = 0;
-void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
-{
- streamFCopyRecord(streamptr2, streamptr1, "IEG");
+ datatype = vlistInqVarDatatype(vlistID, varID);
+
+ srvp->dprec = srvDefDatatype(datatype);
+
+ for ( levID = 0; levID < nlevs; levID++ )
+ {
+ level = zaxisInqLevel(zaxisID, levID);
+
+ header[1] = (int) level;
+ srvDefHeader(srvp, header);
+ srvDefDataDP(srvp, &data[levID*gridsize]);
+ srvWrite(fileID, srvp);
+ }
}
-void iegDefRecord(stream_t *streamptr)
+void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
{
- int vlistID;
+ int fileID;
int gridID;
- int date, time;
+ int zaxisID;
+ double level;
+ int header[8];
+ int xsize, ysize;
int datatype;
- int i;
- int param, pdis, pcat, pnum;
- int varID, levelID, tsID, zaxisID;
- int byteorder;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ int tsID;
+ int vlistID;
+ int pdis, pcat, pnum;
+ srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
- vlistID = streamptr->vlistID;
- byteorder = streamptr->byteorder;
+ vlistID = streamptr->vlistID;
+ fileID = streamptr->fileID;
+ tsID = streamptr->curTsID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ zaxisID = vlistInqVarZaxis(vlistID, varID);
+ level = zaxisInqLevel(zaxisID, levID);
- varID = streamptr->record->varID;
- levelID = streamptr->record->levelID;
- tsID = streamptr->curTsID;
+ if ( CDI_Debug )
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
+ cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
- iegInitMem(iegp);
- for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
+ header[0] = pnum;
+ header[1] = (int) level;
+ header[2] = streamptr->tsteps[tsID].taxis.vdate;
+ header[3] = streamptr->tsteps[tsID].taxis.vtime;
- iegp->byteswap = getByteswap(byteorder);
+ xsize = gridInqXsize(gridID);
+ ysize = gridInqYsize(gridID);
+ if ( xsize == 0 || ysize == 0 )
+ {
+ xsize = gridInqSize(gridID);
+ ysize = 1;
+ }
+ if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
+ if ( gridInqSize(gridID) != xsize*ysize )
+ Error("Internal problem with gridsize!");
- param = vlistInqVarParam(vlistID, varID);
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
- IEG_P_Parameter(iegp->ipdb) = pnum;
- if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
- date = streamptr->tsteps[tsID].taxis.vdate;
- time = streamptr->tsteps[tsID].taxis.vtime;
+ header[4] = xsize;
+ header[5] = ysize;
+ header[6] = 0;
+ header[7] = 0;
- iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
- iegDefGrid(iegp->igdb, gridID);
- iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levelID);
+ datatype = vlistInqVarDatatype(vlistID, varID);
- datatype = streamptr->record->prec;
+ srvp->dprec = srvDefDatatype(datatype);
- iegp->dprec = iegDefDatatype(datatype);
+ srvDefHeader(srvp, header);
+ srvDefDataDP(srvp, data);
+ srvWrite(fileID, srvp);
}
+#endif /* HAVE_LIBSERVICE */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#if defined (HAVE_CONFIG_H)
+#endif
-void iegWriteRecord(stream_t *streamptr, const double *data)
-{
- int fileID;
- int i, gridsize, gridID;
- double refval;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+#include <string.h>
- fileID = streamptr->fileID;
- gridID = streamptr->record->gridID;
- gridsize = gridInqSize(gridID);
- refval = data[0];
- for ( i = 1; i < gridsize; i++ )
- if ( data[i] < refval ) refval = data[i];
- iegp->refval = refval;
+static void streamvar_init_recordtable(stream_t *streamptr, int varID, int isub)
+{
+ streamptr->vars[varID].recordTable[isub].nlevs = 0;
+ streamptr->vars[varID].recordTable[isub].recordID = NULL;
+ streamptr->vars[varID].recordTable[isub].lindex = NULL;
+}
- iegDefDataDP(iegp, data);
- iegWrite(fileID, iegp);
+static
+void streamvar_init_entry(stream_t *streamptr, int varID)
+{
+ streamptr->vars[varID].ncvarid = CDI_UNDEFID;
+ streamptr->vars[varID].defmiss = 0;
+
+ streamptr->vars[varID].subtypeSize = 0;
+ streamptr->vars[varID].recordTable = NULL;
+
+ streamptr->vars[varID].gridID = CDI_UNDEFID;
+ streamptr->vars[varID].zaxisID = CDI_UNDEFID;
+ streamptr->vars[varID].tsteptype = CDI_UNDEFID;
+ streamptr->vars[varID].subtypeID = CDI_UNDEFID;
}
static
-void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
- size_t recsize, off_t position, int prec)
+int streamvar_new_entry(stream_t *streamptr)
{
- int leveltype;
- int gridID = UNDEFID;
- int levelID = 0;
- int tsID, recID, varID;
- int datatype;
- int level1, level2;
- int gridtype;
- int lbounds = 0;
- record_t *record;
- grid_t grid;
- int vlistID;
-
- vlistID = streamptr->vlistID;
- tsID = streamptr->curTsID;
- recID = recordNewEntry(streamptr, tsID);
- record = &streamptr->tsteps[tsID].records[recID];
+ int varID = 0;
+ int streamvarSize;
+ svarinfo_t *streamvar;
- if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER )
+ streamvarSize = streamptr->varsAllocated;
+ streamvar = streamptr->vars;
+ /*
+ Look for a free slot in streamvar.
+ (Create the table the first time through).
+ */
+ if ( ! streamvarSize )
{
- level1 = IEG_P_Level1(pdb);
- level2 = IEG_P_Level2(pdb);
+ int i;
+
+ streamvarSize = 2;
+ streamvar
+ = (svarinfo_t *) Malloc((size_t)streamvarSize * sizeof(svarinfo_t));
+ if ( streamvar == NULL )
+ {
+ Message("streamvarSize = %d", streamvarSize);
+ SysError("Allocation of svarinfo_t failed");
+ }
+
+ for ( i = 0; i < streamvarSize; i++ )
+ streamvar[i].isUsed = FALSE;
}
else
{
- level1 = IEG_P_Level2(pdb);
- level2 = 0;
- if ( IEG_P_LevelType(pdb) == 100 ) level1 *= 100;
+ while ( varID < streamvarSize )
+ {
+ if ( ! streamvar[varID].isUsed ) break;
+ varID++;
+ }
}
-
- record->size = recsize;
- record->position = position;
- record->param = param;
- record->ilevel = level1;
- record->ilevel2 = level2;
- record->ltype = IEG_P_LevelType(pdb);
-
- if ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 )
- gridtype = GRID_LONLAT;
- else if ( IEG_G_GridType(gdb) == 4 )
- gridtype = GRID_GAUSSIAN;
- else
- gridtype = GRID_GENERIC;
-
- memset(&grid, 0, sizeof(grid_t));
- grid.type = gridtype;
- grid.size = IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb);
- grid.xsize = IEG_G_NumLon(gdb);
- grid.ysize = IEG_G_NumLat(gdb);
- grid.xinc = 0;
- grid.yinc = 0;
- grid.xdef = 0;
-
- int iresfac = IEG_G_ResFac(gdb);
- if ( iresfac == 0 ) iresfac = 1000;
- double resfac = 1./(double) iresfac;
-
- /* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */
- {
- if ( grid.xsize > 1 )
- {
- if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 )
- grid.xinc = IEG_G_LonIncr(gdb) * resfac;
- else
- grid.xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid.xsize - 1);
-
- /* correct xinc if necessary */
- if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 )
- {
- double xinc = 360. / grid.xsize;
- /* FIXME: why not use grid.xinc != xinc as condition? */
- if ( fabs(grid.xinc-xinc) > 0.0 )
- {
- grid.xinc = xinc;
- if ( CDI_Debug ) Message("set xinc to %g", grid.xinc);
- }
- }
- }
- grid.xfirst = IEG_G_FirstLon(gdb) * resfac;
- grid.xlast = IEG_G_LastLon(gdb) * resfac;
- grid.xdef = 2;
- }
- grid.ydef = 0;
- /* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */
- {
- if ( grid.ysize > 1 )
- {
- if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 )
- grid.yinc = IEG_G_LatIncr(gdb) * resfac;
- else
- grid.yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid.ysize - 1);
- }
- grid.yfirst = IEG_G_FirstLat(gdb) * resfac;
- grid.ylast = IEG_G_LastLat(gdb) * resfac;
- grid.ydef = 2;
- }
/*
- grid.xfirst= IEG_G_FirstLon(gdb) * resfac;
- grid.xlast = IEG_G_LastLon(gdb) * resfac;
- grid.xinc = IEG_G_LonIncr(gdb) * resfac;
- grid.xdef = 2;
- grid.yfirst= IEG_G_FirstLat(gdb) * resfac;
- grid.ylast = IEG_G_LastLat(gdb) * resfac;
- grid.yinc = IEG_G_LatIncr(gdb) * resfac;
- grid.ydef = 2;
+ If the table overflows, double its size.
*/
- grid.xvals = NULL;
- grid.yvals = NULL;
-
- grid.isRotated = FALSE;
- if ( IEG_G_GridType(gdb) == 10 )
+ if ( varID == streamvarSize )
{
- grid.isRotated = TRUE;
- grid.ypole = - IEG_G_LatSP(gdb) * resfac;
- grid.xpole = IEG_G_LonSP(gdb) * resfac - 180;
- grid.angle = 0;
- }
+ int i;
- gridID = varDefGrid(vlistID, &grid, 0);
+ streamvarSize = 2*streamvarSize;
+ streamvar
+ = (svarinfo_t *) Realloc(streamvar,
+ (size_t)streamvarSize * sizeof (svarinfo_t));
+ if ( streamvar == NULL )
+ {
+ Message("streamvarSize = %d", streamvarSize);
+ SysError("Reallocation of svarinfo_t failed");
+ }
+ varID = streamvarSize/2;
- leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
+ for ( i = varID; i < streamvarSize; i++ )
+ streamvar[i].isUsed = FALSE;
+ }
- if ( leveltype == ZAXIS_HYBRID )
- {
- double tmpvct[100];
- size_t vctsize = (size_t)IEG_G_NumVCP(gdb);
+ streamptr->varsAllocated = streamvarSize;
+ streamptr->vars = streamvar;
- for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i];
- for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50];
+ streamvar_init_entry(streamptr, varID);
- varDefVCT(vctsize, tmpvct);
- }
+ streamptr->vars[varID].isUsed = TRUE;
+ return (varID);
+}
- if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER ) lbounds = 1;
- datatype = iegInqDatatype(prec);
+static void
+allocate_record_table_entry(stream_t *streamptr, int varID, int subID, int nlevs)
+{
+ int *level = (int *) Malloc((size_t)nlevs * sizeof (int));
+ int *lindex = (int *) Malloc((size_t)nlevs * sizeof (int));
- varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
- datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ for (int levID = 0; levID < nlevs; levID++ )
+ {
+ level[levID] = CDI_UNDEFID;
+ lindex[levID] = levID;
+ }
- record->varID = (short)varID;
- record->levelID = (short)levelID;
+ streamptr->vars[varID].recordTable[subID].nlevs = nlevs;
+ streamptr->vars[varID].recordTable[subID].recordID = level;
+ streamptr->vars[varID].recordTable[subID].lindex = lindex;
+}
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
+int stream_new_var(stream_t *streamptr, int gridID, int zaxisID, int tilesetID)
+{
if ( CDI_Debug )
- Message("varID = %d gridID = %d levelID = %d",
- varID, gridID, levelID);
-}
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
-#if 0
-static
-void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int param,
- int level, int xsize, int ysize)
-{
- int varID = 0;
- int levelID = 0;
- record_t *record;
+ int varID = streamvar_new_entry(streamptr);
+ int nlevs = zaxisInqSize(zaxisID);
- record = &streamptr->tsteps[tsID].records[recID];
+ streamptr->nvars++;
- if ( param != (*record).param || level != (*record).ilevel )
- Error("inconsistent timestep");
+ streamptr->vars[varID].gridID = gridID;
+ streamptr->vars[varID].zaxisID = zaxisID;
- (*record).position = position;
- /*
- varID = (*record).varID;
- levelID = (*record).levelID;
+ int nsub = 1;
+ if (tilesetID != CDI_UNDEFID)
+ nsub = subtypeInqSize(tilesetID); /* e.g. no of tiles */
+ if ( CDI_Debug )
+ Message("varID %d: create %d tiles with %d level(s), zaxisID=%d", varID, nsub, nlevs,zaxisID);
+ streamptr->vars[varID].recordTable = (sleveltable_t *) Malloc((size_t)nsub * sizeof (sleveltable_t));
+ if( streamptr->vars[varID].recordTable == NULL )
+ SysError("Allocation of leveltable failed!");
+ streamptr->vars[varID].subtypeSize = nsub;
- streamptr->vars[varID].level[levelID] = recID;
+ for (int isub=0; isub<nsub; isub++) {
+ streamvar_init_recordtable(streamptr, varID, isub);
+ allocate_record_table_entry(streamptr, varID, isub, nlevs);
+ if ( CDI_Debug )
+ Message("streamptr->vars[varID].recordTable[isub].recordID[0]=%d",
+ streamptr->vars[varID].recordTable[isub].recordID[0]);
+ }
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
- */
- if ( CDI_Debug )
- Message("varID = %d levelID = %d", varID, levelID);
+ streamptr->vars[varID].subtypeID = tilesetID;
+
+ return (varID);
}
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
+#ifdef HAVE_CONFIG_H
#endif
-static void iegDateTime(int *pdb, int *date, int *time)
-{
- int ryear, rmonth, rday, rhour, rminute;
+#ifdef HAVE_LIBGRIB
- ryear = IEG_P_Year(pdb);
- rmonth = IEG_P_Month(pdb);
- rday = IEG_P_Day(pdb);
- rhour = IEG_P_Hour(pdb);
- rminute = IEG_P_Minute(pdb);
+static
+size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int date, int time, int tsteptype, int numavg,
+ size_t datasize, const void *data, int nmiss, void **gribbuffer,
+ int comptype, void *gribContainer)
+{
+ size_t nbytes = 0;
- if ( rminute == -1 ) rminute = 0;
+#ifdef HAVE_LIBCGRIBEX
+ if ( filetype == FILETYPE_GRB )
+ {
+ size_t gribbuffersize = datasize*4+3000;
+ *gribbuffer = Malloc(gribbuffersize);
- *date = cdiEncodeDate(ryear, rmonth, rday);
- *time = cdiEncodeTime(rhour, rminute, 0);
+ nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
+ date, time, tsteptype, numavg,
+ (long) datasize, data, nmiss, *gribbuffer, gribbuffersize);
+ }
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ {
+ const void *datap = data;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ const float *dataf = (const float*) data;
+ double *datad = (double*) Malloc(datasize*sizeof(double));
+ for ( size_t i = 0; i < datasize; ++i ) datad[i] = (double) dataf[i];
+ datap = (const void*) datad;
+ }
+
+ size_t gribbuffersize;
+ nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
+ date, time, tsteptype, numavg,
+ (long) datasize, datap, nmiss, gribbuffer, &gribbuffersize,
+ comptype, gribContainer);
+
+ if ( memtype == MEMTYPE_FLOAT ) free((void*)datap);
+ }
+#else
+ {
+ Error("GRIB_API support not compiled in!");
+ (void)gribContainer;
+ (void)comptype;
+ }
+#endif
+
+ return nbytes;
}
static
-void iegScanTimestep1(stream_t *streamptr)
+size_t grbSzip(int filetype, void *gribbuffer, size_t gribbuffersize)
{
- int prec = 0;
- int status;
- int fileID;
- int tabnum;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- DateTime datetime0 = { LONG_MIN, LONG_MIN };
- int tsID;
- int varID;
- size_t recsize;
- off_t recpos;
- int nrecords, nrecs, recID;
- int taxisID = -1;
- taxis_t *taxis;
- int vlistID;
- IEGCOMPVAR compVar, compVar0;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ size_t buffersize = gribbuffersize + 1000; /* compressed record can be greater than source record */
+ void *buffer = Malloc(buffersize);
- streamptr->curTsID = 0;
-
- tsID = tstepsNewEntry(streamptr);
- taxis = &streamptr->tsteps[tsID].taxis;
-
- if ( tsID != 0 )
- Error("Internal problem! tstepsNewEntry returns %d", tsID);
-
- fileID = streamptr->fileID;
+ /* memcpy(buffer, gribbuffer, gribbuffersize); */
- nrecs = 0;
- while ( TRUE )
+ size_t nbytes = 0;
+ if ( filetype == FILETYPE_GRB )
{
- recpos = fileGetPos(fileID);
- status = iegRead(fileID, iegp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 1;
- break;
- }
- recsize = (size_t)(fileGetPos(fileID) - recpos);
+ nbytes = (size_t)gribZip((unsigned char *)gribbuffer, (long) gribbuffersize, (unsigned char *)buffer, (long) buffersize);
+ }
+ else
+ {
+ static int lszip_warn = 1;
+ if ( lszip_warn ) Warning("Szip compression of GRIB2 records not implemented!");
+ lszip_warn = 0;
+ nbytes = gribbuffersize;
+ }
- prec = iegp->dprec;
- rcode = IEG_P_Parameter(iegp->ipdb);
- tabnum = IEG_P_CodeTable(iegp->ipdb);
- param = cdiEncodeParam(rcode, tabnum, 255);
+ Free(buffer);
- if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
- rlevel = IEG_P_Level1(iegp->ipdb);
- else
- rlevel = IEG_P_Level2(iegp->ipdb);
+ return nbytes;
+}
- if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
- iegDateTime(iegp->ipdb, &vdate, &vtime);
+void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
+{
+ int filetype = streamptr1->filetype;
+ int fileID1 = streamptr1->fileID;
+ int fileID2 = streamptr2->fileID;
+ int tsID = streamptr1->curTsID;
+ int vrecID = streamptr1->tsteps[tsID].curRecID;
+ int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
- if ( nrecs == 0 )
- {
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
- else
- {
- compVar.param = param;
- compVar.level = rlevel;
- for ( recID = 0; recID < nrecs; recID++ )
- {
- compVar0.param = streamptr->tsteps[0].records[recID].param;
- compVar0.level = streamptr->tsteps[0].records[recID].ilevel;
+ fileSetPos(fileID1, recpos, SEEK_SET);
- if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 ) break;
- }
- if ( recID < nrecs ) break;
- DateTime datetime = { .date = vdate, .time = vtime};
- if ( datetimeCmp(datetime, datetime0) )
- Warning("Inconsistent verification time for param %d level %d", param, rlevel);
- }
+ /* round up recsize to next multiple of 8 */
+ size_t gribbuffersize = ((recsize + 7U) & ~7U);
- nrecs++;
+ unsigned char *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, param, rlevel, vdate, vtime);
+ if (fileRead(fileID1, gribbuffer, recsize) != recsize)
+ Error("Could not read GRIB record for copying!");
- iegAddRecord(streamptr, param, iegp->ipdb, iegp->igdb, iegp->vct, recsize, recpos, prec);
+ size_t nbytes = recsize;
+
+ if ( filetype == FILETYPE_GRB )
+ {
+ long unzipsize;
+ int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
+
+ if ( izip == 0 && streamptr2->comptype == COMPRESS_SZIP )
+ nbytes = grbSzip(filetype, gribbuffer, nbytes);
}
- streamptr->rtsteps = 1;
+ while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
- cdi_generate_vars(streamptr);
+ size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
+ if ( nwrite != nbytes )
+ {
+ perror(__func__);
+ Error("Could not write record for copying!");
+ }
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = (int)datetime0.date;
- taxis->vtime = (int)datetime0.time;
+ Free(gribbuffer);
+}
- vlistID = streamptr->vlistID;
- vlistDefTaxis(vlistID, taxisID);
- vlist_check_contents(vlistID);
+void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+{
+ void *gribbuffer = NULL;
+ void *gc = NULL;
- nrecords = streamptr->tsteps[0].nallrecs;
- if ( nrecords < streamptr->tsteps[0].recordSize )
+ int filetype = streamptr->filetype;
+ int fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int comptype = streamptr->comptype;
+ int tsID = streamptr->curTsID;
+ int date = streamptr->tsteps[tsID].taxis.vdate;
+ int time = streamptr->tsteps[tsID].taxis.vtime;
+ int numavg = 0;
+ if ( vlistInqVarTimave(vlistID, varID) )
+ numavg = streamptr->tsteps[tsID].taxis.numavg;
+
+ if ( CDI_Debug )
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+
+ size_t datasize = (size_t)gridInqSize(gridID);
+
+#ifdef HAVE_LIBCGRIBEX
+ if ( filetype == FILETYPE_GRB )
{
- streamptr->tsteps[0].recordSize = nrecords;
- streamptr->tsteps[0].records =
- (record_t *) Realloc(streamptr->tsteps[0].records,
- (size_t)nrecords * sizeof (record_t));
+ }
+ else
+#endif
+ {
+#ifdef GRIBCONTAINER2D
+ gribContainer_t **gribContainers = (gribContainer_t **) streamptr->gribContainers;
+ gc = (void *) &gribContainers[varID][levelID];
+#else
+ gribContainer_t *gribContainers = (gribContainer_t *) streamptr->gribContainers;
+ gc = (void *) &gribContainers[varID];
+#endif
}
- streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
- streamptr->tsteps[0].nrecs = nrecords;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[0].recIDs[recID] = recID;
+ if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
- if ( streamptr->ntsteps == -1 )
+ if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
{
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
-
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ static int ljpeg_warn = 1;
+ if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
+ ljpeg_warn = 0;
}
- if ( streamptr->ntsteps == 1 )
+ size_t nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
+ datasize, data, nmiss, &gribbuffer, comptype, gc);
+
+ if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
+ nbytes = grbSzip(filetype, gribbuffer, nbytes);
+
+ size_t (*myFileWrite)(int fileID, const void *restrict buffer,
+ size_t len, int tsID)
+ = (size_t (*)(int, const void *restrict, size_t, int))
+ namespaceSwitchGet(NSSWITCH_FILE_WRITE).func;
+ size_t nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
+
+ if ( nwrite != nbytes )
{
- if ( taxis->vdate == 0 && taxis->vtime == 0 )
- {
- streamptr->ntsteps = 0;
- for ( varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- }
+ perror(__func__);
+ Error("Failed to write GRIB slice!");
}
+
+ if ( gribbuffer ) Free(gribbuffer);
}
-static
-int iegScanTimestep2(stream_t *streamptr)
+
+void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
{
- int status;
- int fileID;
- int tabnum;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- int tsID;
- int varID;
- size_t recsize;
- off_t recpos = 0;
- int nrecords, nrecs, recID, rindex;
- int nextstep;
- taxis_t *taxis;
- int vlistID;
- IEGCOMPVAR compVar, compVar0;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ int vlistID = streamptr->vlistID,
+ gridID = vlistInqVarGrid(vlistID, varID),
+ gridsize = gridInqSize(gridID),
+ zaxisID = vlistInqVarZaxis(vlistID, varID),
+ nlevs = zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
- streamptr->curTsID = 1;
+ size_t chunkLen = (size_t)gridsize;
+ if ( memtype == MEMTYPE_FLOAT )
+ for ( int levelID = 0; levelID < nlevs; levelID++ )
+ {
+ const float *restrict fdata = ((const float *)data)+levelID*gridsize;
+
+ int nmiss_slice = 0;
+ if ( nmiss )
+ for ( size_t i = 0; i < chunkLen; ++i )
+ nmiss_slice += DBL_IS_EQUAL(fdata[i], missval);
+
+ grb_write_var_slice(streamptr, varID, levelID, memtype, fdata, nmiss_slice);
+ }
+ else
+ for ( int levelID = 0; levelID < nlevs; levelID++ )
+ {
+ const double *restrict ddata = ((const double *)data)+levelID*gridsize;
+
+ int nmiss_slice = 0;
+ if ( nmiss )
+ for ( size_t i = 0; i < chunkLen; ++i )
+ nmiss_slice += DBL_IS_EQUAL(ddata[i], missval);
+
+ grb_write_var_slice(streamptr, varID, levelID, memtype, ddata, nmiss_slice);
+ }
+}
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->rtsteps;
- if ( tsID != 1 )
- Error("Internal problem! unexpected timestep %d", tsID+1);
+void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
+{
+ int varID = streamptr->record->varID;
+ int levelID = streamptr->record->levelID;
- taxis = &streamptr->tsteps[tsID].taxis;
+ grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+}
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+#endif
+#ifdef HAVE_CONFIG_H
+#endif
- cdi_create_records(streamptr, tsID);
+#ifdef HAVE_LIBGRIB
- nrecords = streamptr->tsteps[0].nallrecs;
- streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int));
- streamptr->tsteps[1].nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[1].recIDs[recID] = -1;
- for ( recID = 0; recID < nrecords; recID++ )
+
+static
+int grbDecode(int filetype, int memtype, void *gribbuffer, int gribsize, void *data, size_t datasize,
+ int unreduced, int *nmiss, double missval, int vlistID, int varID)
+{
+ int status = 0;
+
+#if defined (HAVE_LIBCGRIBEX)
+ if ( filetype == FILETYPE_GRB )
{
- varID = streamptr->tsteps[0].records[recID].varID;
- streamptr->tsteps[tsID].records[recID].position =
- streamptr->tsteps[0].records[recID].position;
- streamptr->tsteps[tsID].records[recID].size =
- streamptr->tsteps[0].records[recID].size;
+#if defined (HAVE_LIBGRIB_API)
+ extern int cdiNAdditionalGRIBKeys;
+ if ( cdiNAdditionalGRIBKeys > 0 )
+ Error("CGRIBEX decode does not support reading of additional GRIB keys!");
+#endif
+ status = cgribexDecode(memtype, gribbuffer, gribsize, data, (long) datasize, unreduced, nmiss, missval);
}
-
- for ( rindex = 0; rindex <= nrecords; rindex++ )
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
{
- recpos = fileGetPos(fileID);
- status = iegRead(fileID, iegp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 2;
- break;
- }
- recsize = (size_t)(fileGetPos(fileID) - recpos);
+ void *datap = data;
+ if ( memtype == MEMTYPE_FLOAT )
+ datap = Malloc(datasize*sizeof(double));
- rcode = IEG_P_Parameter(iegp->ipdb);
- tabnum = IEG_P_CodeTable(iegp->ipdb);
- param = cdiEncodeParam(rcode, tabnum, 255);
+ status = gribapiDecode(gribbuffer, gribsize, datap, (long) datasize, unreduced, nmiss, missval, vlistID, varID);
- if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
- rlevel = IEG_P_Level1(iegp->ipdb);
- else
- rlevel = IEG_P_Level2(iegp->ipdb);
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ float *dataf = (float*) data;
+ double *datad = (double*) datap;
+ for ( size_t i = 0; i < datasize; ++i ) dataf[i] = (float) datad[i];
+ free((void*)datap);
+ }
+ }
+#else
+ {
+ (void)vlistID; (void)varID;
+ Error("GRIB_API support not compiled in!");
+ }
+#endif
- if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
+ return status;
+}
- iegDateTime(iegp->ipdb, &vdate, &vtime);
+static
+int grbUnzipRecord(void *gribbuffer, size_t *gribsize)
+{
+ int zip = 0;
+ int izip;
+ long unzipsize;
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
+ size_t igribsize = *gribsize;
+ size_t ogribsize = *gribsize;
- compVar.param = param;
- compVar.level = rlevel;
- nextstep = FALSE;
- for ( recID = 0; recID < nrecords; recID++ )
+ if ( (izip = gribGetZip((long)igribsize, (unsigned char *)gribbuffer, &unzipsize)) > 0 )
+ {
+ zip = izip;
+ if ( izip == 128 ) /* szip */
{
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ unsigned char *itmpbuffer = NULL;
+ size_t itmpbuffersize = 0;
- if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 )
+ if ( unzipsize < (long) igribsize )
{
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- nextstep = TRUE;
- }
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
- break;
+ fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
+ return (0);
}
- }
- if ( recID == nrecords )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Warning("param %s level %d not defined at timestep 1", paramstr, rlevel);
- return (CDI_EUFSTRUCT);
- }
-
- if ( nextstep ) break;
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, param, rlevel, vdate, vtime);
+ if ( itmpbuffersize < igribsize )
+ {
+ itmpbuffersize = igribsize;
+ itmpbuffer = (unsigned char *) Realloc(itmpbuffer, itmpbuffersize);
+ }
- streamptr->tsteps[tsID].records[recID].size = recsize;
+ memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
- if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- return (CDI_EUFSTRUCT);
- }
+ ogribsize = (size_t)gribUnzip((unsigned char *)gribbuffer, unzipsize, itmpbuffer, (long)igribsize);
- streamptr->tsteps[1].records[recID].position = recpos;
- }
+ Free(itmpbuffer);
- nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- {
- if ( ! streamptr->tsteps[tsID].records[recID].used )
- {
- varID = streamptr->tsteps[tsID].records[recID].varID;
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
+ if ( ogribsize <= 0 ) Error("Decompression problem!");
}
else
{
- nrecs++;
+ Error("Decompression for %d not implemented!", izip);
}
}
- streamptr->tsteps[tsID].nrecs = nrecs;
-
- streamptr->rtsteps = 2;
-
- if ( streamptr->ntsteps == -1 )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
- }
+ *gribsize = ogribsize;
- return (0);
+ return zip;
}
-int iegInqContents(stream_t *streamptr)
+void grb_read_record(stream_t * streamptr, int memtype, void *data, int *nmiss)
{
- int fileID;
- int status = 0;
+ int filetype = streamptr->filetype;
- fileID = streamptr->fileID;
+ void *gribbuffer = streamptr->record->buffer;
- streamptr->curTsID = 0;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
- iegScanTimestep1(streamptr);
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
- if ( streamptr->ntsteps == -1 ) status = iegScanTimestep2(streamptr);
+ streamptr->numvals += gridsize;
- fileSetPos(fileID, 0, SEEK_SET);
+ fileSetPos(fileID, recpos, SEEK_SET);
- return (status);
+ if (fileRead(fileID, gribbuffer, recsize) != recsize)
+ Error("Failed to read GRIB record");
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, data, (size_t)gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
}
-static
-long iegScanTimestep(stream_t *streamptr)
+
+void grb_read_var(stream_t * streamptr, int varID, int memtype, void *data, int *nmiss)
{
- int status;
- int fileID;
- int tsID;
- int tabnum;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- size_t recsize = 0;
- off_t recpos = 0;
- int recID;
- taxis_t *taxis;
- int rindex, nrecs = 0;
- IEGCOMPVAR compVar, compVar0;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ int filetype = streamptr->filetype;
+
+ void *gribbuffer = streamptr->record->buffer;
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
+
+ off_t currentfilepos = fileGetPos(fileID);
+ int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
+ int nlevs = streamptr->vars[varID].recordTable[0].nlevs;
if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ *nmiss = 0;
+ for (int levelID = 0; levelID < nlevs; levelID++ )
{
- Message("streamID = %d", streamptr->self);
- Message("cts = %d", streamptr->curTsID);
- Message("rts = %d", streamptr->rtsteps);
- Message("nts = %d", streamptr->ntsteps);
+ int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+
+ fileSetPos(fileID, recpos, SEEK_SET);
+
+ fileRead(fileID, gribbuffer, recsize);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ int imiss;
+
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+ void *datap = NULL;
+ if ( memtype == MEMTYPE_FLOAT )
+ datap = (float*)data + levelID*gridsize;
+ else
+ datap = (double*)data + levelID*gridsize;
+
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, datap, (size_t)gridsize,
+ streamptr->unreduced, &imiss, missval, vlistID, varID);
+
+ *nmiss += imiss;
}
- if ( streamptr->rtsteps == 0 )
- Error("Internal problem! Missing contents.");
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+}
- tsID = streamptr->rtsteps;
- taxis = &streamptr->tsteps[tsID].taxis;
- if ( streamptr->tsteps[tsID].recordSize == 0 )
- {
- cdi_create_records(streamptr, tsID);
+void grb_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss)
+{
+ int filetype = streamptr->filetype;
- nrecs = streamptr->tsteps[1].nrecs;
+ void *gribbuffer = streamptr->record->buffer;
- streamptr->tsteps[tsID].nrecs = nrecs;
- streamptr->tsteps[tsID].recIDs
- = (int *) Malloc((size_t)nrecs * sizeof (int));
- for ( recID = 0; recID < nrecs; recID++ )
- streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
+ int tsID = streamptr->curTsID;
- fileID = streamptr->fileID;
+ if ( CDI_Debug )
+ Message("gridID = %d gridsize = %d", gridID, gridsize);
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
+ int fileID = streamptr->fileID;
- for ( rindex = 0; rindex <= nrecs; rindex++ )
- {
- recpos = fileGetPos(fileID);
- status = iegRead(fileID, iegp);
- if ( status != 0 )
- {
- streamptr->ntsteps = streamptr->rtsteps + 1;
- break;
- }
- recsize = (size_t)(fileGetPos(fileID) - recpos);
+ off_t currentfilepos = fileGetPos(fileID);
- rcode = IEG_P_Parameter(iegp->ipdb);
- tabnum = IEG_P_CodeTable(iegp->ipdb);
- param = cdiEncodeParam(rcode, tabnum, 255);
+ int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
- if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER )
- rlevel = IEG_P_Level1(iegp->ipdb);
- else
- rlevel = IEG_P_Level2(iegp->ipdb);
+ int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
- if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100;
+ if ( recsize == 0 )
+ Error("Internal problem! Recordsize is zero for record %d at timestep %d",
+ recID+1, tsID+1);
- iegDateTime(iegp->ipdb, &vdate, &vtime);
+ fileSetPos(fileID, recpos, SEEK_SET);
+ fileRead(fileID, gribbuffer, recsize);
- // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
- if ( rindex == nrecs ) continue;
- recID = streamptr->tsteps[tsID].recIDs[rindex];
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
+ double missval = vlistInqVarMissval(vlistID, varID);
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, data, (size_t)gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
- compVar.param = param;
- compVar.level = rlevel;
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+}
- if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- Error("Invalid, unsupported or inconsistent record structure");
- }
+#endif
+#ifdef HAVE_CONFIG_H
+#endif
- streamptr->tsteps[tsID].records[recID].position = recpos;
- streamptr->tsteps[tsID].records[recID].size = recsize;
+#ifdef HAVE_LIBNETCDF
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, param, rlevel, vdate, vtime);
- }
- streamptr->rtsteps++;
- if ( streamptr->ntsteps != streamptr->rtsteps )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
- streamptr->tsteps[tsID-1].next = 1;
- streamptr->tsteps[tsID].position = recpos;
- }
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- streamptr->tsteps[tsID].position = recpos;
+void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
+{
+#if defined (HAVE_NETCDF4)
+ int retval;
+ /* Set chunking, shuffle, and deflate. */
+ int shuffle = 1;
+ int deflate = 1;
+
+ if ( deflate_level < 1 || deflate_level > 9 ) deflate_level = 1;
+
+ if ((retval = nc_def_var_deflate(ncid, ncvarid, shuffle, deflate, deflate_level)))
+ {
+ Error("nc_def_var_deflate failed, status = %d", retval);
}
-
- if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
+#else
+
+ static int lwarn = TRUE;
+ if ( lwarn )
{
- Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
- streamptr->ntsteps = tsID;
+ lwarn = FALSE;
+ Warning("Deflate compression failed, NetCDF4 not available!");
}
-
- return (streamptr->ntsteps);
+#endif
}
-
-int iegInqTimestep(stream_t *streamptr, int tsID)
+static
+int cdfDefDatatype(int datatype, int filetype)
{
- int nrecs;
-
- if ( tsID == 0 && streamptr->rtsteps == 0 )
- Error("Call to cdiInqContents missing!");
+ int xtype = NC_FLOAT;
- if ( CDI_Debug )
- Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
-
- long ntsteps = UNDEFID;
- while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
- ntsteps = iegScanTimestep(streamptr);
+ if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
+ Error("CDI/NetCDF library does not support complex numbers!");
- if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
+ if ( filetype == FILETYPE_NC4 )
{
- nrecs = 0;
+ if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
+ else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
+#if defined (HAVE_NETCDF4)
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_UBYTE;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
+#else
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
+#endif
+ else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
+ else xtype = NC_FLOAT;
}
else
{
- streamptr->curTsID = tsID;
- nrecs = streamptr->tsteps[tsID].nrecs;
+ if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
+ else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
+ else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
+ else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
+ else xtype = NC_FLOAT;
}
- return (nrecs);
+ return xtype;
}
-
-void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+static
+void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
{
- int vlistID, fileID;
- int levID, nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int tsid;
- int recID;
- int i;
- double missval;
- void *iegp = streamptr->record->exsep;
+ if ( streamptr->vars[varID].defmiss == FALSE )
+ {
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ double missval = vlistInqVarMissval(vlistID, varID);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
+ if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ int xtype = cdfDefDatatype(dtype, streamptr->filetype);
- currentfilepos = fileGetPos(fileID);
+ if ( xtype == NC_BYTE && missval > 127 && missval < 256 ) xtype = NC_INT;
- for (levID = 0; levID < nlevs; levID++)
- {
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- iegRead(fileID, iegp);
- iegInqDataDP(iegp, &data[levID*gridsize]);
- }
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
+ cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
- *nmiss = 0;
- for ( i = 0; i < nlevs*gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
-}
+ if ( lcheck && streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ streamptr->vars[varID].defmiss = TRUE;
+ }
+}
-void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
+static
+void cdfDefInstitut(stream_t *streamptr)
{
- int vlistID, fileID;
- int nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int tsid;
- int recID;
- int i;
- double missval;
- void *iegp = streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
-
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d",
- nlevs, gridID, gridsize);
-
- currentfilepos = fileGetPos(fileID);
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int instID = vlistInqInstitut(vlistID);
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- iegRead(fileID, iegp);
- iegInqDataDP(iegp, data);
+ if ( instID != UNDEFID )
+ {
+ const char *longname = institutInqLongnamePtr(instID);
+ if ( longname )
+ {
+ size_t len = strlen(longname);
+ if ( len > 0 )
+ {
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ cdf_put_att_text(fileID, NC_GLOBAL, "institution", len, longname);
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ }
+ }
+ }
+}
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+static
+void cdfDefSource(stream_t *streamptr)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int modelID = vlistInqModel(vlistID);
- *nmiss = 0;
- for ( i = 0; i < gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ if ( modelID != UNDEFID )
+ {
+ const char *longname = modelInqNamePtr(modelID);
+ if ( longname )
+ {
+ size_t len = strlen(longname);
+ if ( len > 0 )
+ {
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
+ cdf_put_att_text(fileID, NC_GLOBAL, "source", len, longname);
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
+ }
+ }
+ }
}
+static inline
+void *resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
+{
+ if (reqSize > *bufSize)
+ {
+ *buf = Realloc(*buf, reqSize);
+ *bufSize = reqSize;
+ }
+ return *buf;
+}
-void iegWriteVarDP(stream_t *streamptr, int varID, const double *data)
+static
+void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
- int fileID;
- int levID, nlevs, gridID, gridsize;
- int zaxisID;
- int datatype;
- int tsID;
- int vlistID;
- int i;
- int date, time;
- int param, pdis, pcat, pnum;
- double refval;
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
+ int atttype, attlen;
+ size_t len;
+ char attname[CDI_MAX_NAME+1];
+ void *attBuf = NULL;
+ size_t attBufSize = 0;
- if ( CDI_Debug )
- Message("streamID = %d varID = %d", streamptr->self, varID);
+ int natts;
+ vlistInqNatts(vlistID, varID, &natts);
- iegInitMem(iegp);
- for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1;
+ for ( int iatt = 0; iatt < natts; iatt++ )
+ {
+ vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlevs = zaxisInqSize(zaxisID);
+ if ( attlen == 0 ) continue;
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ if ( atttype == DATATYPE_TXT )
+ {
+ size_t attSize = (size_t)attlen*sizeof(char);
+ char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
+ len = (size_t)attlen;
+ cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
+ }
+ else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
+ {
+ size_t attSize = (size_t)attlen*sizeof(int);
+ int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
+ len = (size_t)attlen;
+ cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
+ }
+ else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
+ {
+ size_t attSize = (size_t)attlen * sizeof(double);
+ double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
+ vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
+ len = (size_t)attlen;
+ if ( atttype == DATATYPE_FLT32 )
+ {
+ float attflt_sp[len];
+ for ( size_t i = 0; i < len; ++i ) attflt_sp[i] = (float)attflt[i];
+ cdf_put_att_float(fileID, ncvarID, attname, NC_FLOAT, len, attflt_sp);
+ }
+ else
+ cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
+ }
+ }
+
+ Free(attBuf);
+}
- param = vlistInqVarParam(vlistID, varID);
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
- IEG_P_Parameter(iegp->ipdb) = pnum;
- if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat;
- date = streamptr->tsteps[tsID].taxis.vdate;
- time = streamptr->tsteps[tsID].taxis.vtime;
+static
+void cdfDefGlobalAtts(stream_t *streamptr)
+{
+ if ( streamptr->globalatts ) return;
- iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID));
- iegDefGrid(iegp->igdb, gridID);
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- datatype = vlistInqVarDatatype(vlistID, varID);
+ cdfDefSource(streamptr);
+ cdfDefInstitut(streamptr);
- iegp->dprec = iegDefDatatype(datatype);
+ int natts;
+ vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
- for ( levID = 0; levID < nlevs; levID++ )
- {
- iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID);
+ if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID);
- refval = data[0];
- for ( i = 1; i < gridsize; i++ )
- if ( data[levID*gridsize+i] < refval ) refval = data[levID*gridsize+i];
+ cdfDefineAttributes(vlistID, CDI_GLOBAL, fileID, NC_GLOBAL);
- iegp->refval = refval;
+ if ( natts > 0 && streamptr->ncmode == 2 ) cdf_enddef(fileID);
- iegDefDataDP(iegp, &data[levID*gridsize]);
- iegWrite(fileID, iegp);
- }
+ streamptr->globalatts = 1;
}
-
-void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
+static
+void cdfDefLocalAtts(stream_t *streamptr)
{
- int fileID;
- int gridID;
- int zaxisID;
- /* double level; */
- int datatype;
- /* int tsID; */
- int vlistID;
- /* int param, date, time, datasize; */
- iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* tsID = streamptr->curTsID; */
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- (void)levID;
- /* level = zaxisInqLevel(zaxisID, levID); */
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+ if ( streamptr->localatts ) return;
+ if ( vlistInqInstitut(vlistID) != UNDEFID ) return;
- /* param = vlistInqVarParam(vlistID, varID); */
- /* date = streamptr->tsteps[tsID].taxis.vdate; */
- /* time = streamptr->tsteps[tsID].taxis.vtime; */
- /* datasize = gridInqSize(gridID); */
+ streamptr->localatts = 1;
- datatype = vlistInqVarDatatype(vlistID, varID);
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- iegp->dprec = iegDefDatatype(datatype);
+ for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ {
+ int instID = vlistInqVarInstitut(vlistID, varID);
+ if ( instID != UNDEFID )
+ {
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ const char *name = institutInqNamePtr(instID);
+ if ( name )
+ {
+ size_t len = strlen(name);
+ cdf_put_att_text(fileID, ncvarid, "institution", len, name);
+ }
+ }
+ }
- iegDefDataDP(iegp, data);
- iegWrite(fileID, iegp);
+ if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
}
-#endif /* HAVE_LIBIEG */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
-#endif
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
+static
+int cdfDefVar(stream_t *streamptr, int varID)
+{
+ int ncvarid = -1;
+ int xid = UNDEFID, yid = UNDEFID;
+ size_t xsize = 0, ysize = 0;
+ char varname[CDI_MAX_NAME];
+ int dims[4];
+ int lchunk = FALSE;
+ size_t chunks[4] = {0,0,0,0};
+ int ndims = 0;
+ int tablenum;
+ int dimorder[3];
+ size_t iax = 0;
+ char axis[5];
+ int ensID, ensCount, forecast_type;
+ int retval;
+ int fileID = streamptr->fileID;
+ if ( CDI_Debug )
+ Message("streamID = %d, fileID = %d, varID = %d", streamptr->self, fileID, varID);
+ if ( streamptr->vars[varID].ncvarid != UNDEFID )
+ return streamptr->vars[varID].ncvarid;
-void recordInitEntry(record_t *record)
-{
- record->position = CDI_UNDEFID;
- record->size = 0;
- record->param = 0;
- record->ilevel = CDI_UNDEFID;
- record->used = FALSE;
- record->varID = CDI_UNDEFID;
- record->levelID = CDI_UNDEFID;
- memset(record->varname, 0, sizeof(record->varname));
- memset(&record->tiles, 0, sizeof(record->tiles));
-}
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int code = vlistInqVarCode(vlistID, varID);
+ int param = vlistInqVarParam(vlistID, varID);
+ int pnum, pcat, pdis;
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ int chunktype = vlistInqVarChunkType(vlistID, varID);
-int recordNewEntry(stream_t *streamptr, int tsID)
-{
- size_t recordID = 0;
- size_t recordSize = (size_t)streamptr->tsteps[tsID].recordSize;
- record_t *records = streamptr->tsteps[tsID].records;
- /*
- Look for a free slot in record.
- (Create the table the first time through).
- */
- if ( ! recordSize )
- {
- recordSize = 1; /* <<<<---- */
- records = (record_t *) Malloc(recordSize * sizeof (record_t));
+ vlistInqVarDimorder(vlistID, varID, &dimorder);
- for ( size_t i = 0; i < recordSize; i++ )
- records[i].used = CDI_UNDEFID;
- }
- else
- {
- while ( recordID < recordSize
- && records[recordID].used != CDI_UNDEFID )
- ++recordID;
- }
- /*
- If the table overflows, double its size.
- */
- if ( recordID == recordSize )
+ int gridsize = gridInqSize(gridID);
+ if ( gridsize > 1 ) lchunk = TRUE;
+ int gridtype = gridInqType(gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ if ( gridtype != GRID_TRAJECTORY )
{
- if (recordSize <= INT_MAX / 2)
- recordSize *= 2;
- else if (recordSize < INT_MAX)
- recordSize = INT_MAX;
- else
- Error("Cannot handle this many records!\n");
- records = (record_t *) Realloc(records,
- recordSize * sizeof (record_t));
-
- for ( size_t i = recordID; i < recordSize; i++ )
- records[i].used = CDI_UNDEFID;
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize);
+ if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize);
}
- recordInitEntry(&records[recordID]);
-
- records[recordID].used = 1;
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
+ int zaxis_is_scalar = FALSE;
+ if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID);
- streamptr->tsteps[tsID].recordSize = (int)recordSize;
- streamptr->tsteps[tsID].records = records;
+ if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
- return (int)recordID;
-}
+ if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
+ {
+ printf("zid=%d yid=%d xid=%d\n", zid, yid, xid);
+ Error("Internal problem, dimension order missing!");
+ }
-static
-void cdiInitRecord(stream_t *streamptr)
-{
- streamptr->record = (Record *) Malloc(sizeof(Record));
+ int tid = streamptr->basetime.ncdimid;
- streamptr->record->param = 0;
- streamptr->record->level = 0;
- streamptr->record->date = 0;
- streamptr->record->time = 0;
- streamptr->record->gridID = 0;
- streamptr->record->buffer = NULL;
- streamptr->record->buffersize = 0;
- streamptr->record->position = 0;
- streamptr->record->varID = 0;
- streamptr->record->levelID = CDI_UNDEFID;
-}
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ if ( tid == UNDEFID ) Error("Internal problem, time undefined!");
+ chunks[ndims] = 1;
+ dims[ndims++] = tid;
+ axis[iax++] = 'T';
+ }
+ /*
+ if ( zid != UNDEFID ) axis[iax++] = 'Z';
+ if ( zid != UNDEFID ) chunks[ndims] = 1;
+ if ( zid != UNDEFID ) dims[ndims++] = zid;
+ if ( yid != UNDEFID ) chunks[ndims] = ysize;
+ if ( yid != UNDEFID ) dims[ndims++] = yid;
-void streamInqRecord(int streamID, int *varID, int *levelID)
-{
- check_parg(varID);
- check_parg(levelID);
+ if ( xid != UNDEFID ) chunks[ndims] = xsize;
+ if ( xid != UNDEFID ) dims[ndims++] = xid;
+ */
+ for ( int id = 0; id < 3; ++id )
+ {
+ if ( dimorder[id] == 3 && zid != UNDEFID )
+ {
+ axis[iax++] = 'Z';
+ chunks[ndims] = 1;
+ dims[ndims] = zid;
+ ndims++;
+ }
+ else if ( dimorder[id] == 2 && yid != UNDEFID )
+ {
+ if ( chunktype == CHUNK_LINES )
+ chunks[ndims] = 1;
+ else
+ chunks[ndims] = ysize;
+ dims[ndims] = yid;
+ ndims++;
+ }
+ else if ( dimorder[id] == 1 && xid != UNDEFID )
+ {
+ chunks[ndims] = xsize;
+ dims[ndims] = xid;
+ ndims++;
+ }
+ }
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
+ if ( CDI_Debug )
+ fprintf(stderr, "chunktype %d chunks %d %d %d %d\n", chunktype, (int)chunks[0], (int)chunks[1], (int)chunks[2], (int)chunks[3]);
- cdiDefAccesstype(streamID, TYPE_REC);
+ int tableID = vlistInqVarTable(vlistID, varID);
- if ( ! streamptr->record ) cdiInitRecord(streamptr);
+ const char *name = vlistInqVarNamePtr(vlistID, varID);
+ const char *longname = vlistInqVarLongnamePtr(vlistID, varID);
+ const char *stdname = vlistInqVarStdnamePtr(vlistID, varID);
+ const char *units = vlistInqVarUnitsPtr(vlistID, varID);
- int tsID = streamptr->curTsID;
- int rindex = streamptr->tsteps[tsID].curRecID + 1;
+ if ( name == NULL ) name = tableInqParNamePtr(tableID, code);
+ if ( longname == NULL ) longname = tableInqParLongnamePtr(tableID, code);
+ if ( units == NULL ) units = tableInqParUnitsPtr(tableID, code);
+ if ( name )
+ {
+ int checkname;
+ int iz;
+ int status;
- if ( rindex >= streamptr->tsteps[tsID].nrecs )
- Error("record %d not available at timestep %d", rindex+1, tsID+1);
+ sprintf(varname, "%s", name);
- int recID = streamptr->tsteps[tsID].recIDs[rindex];
+ checkname = TRUE;
+ iz = 0;
- if ( recID == -1 || recID >= streamptr->tsteps[tsID].nallrecs )
- Error("Internal problem! tsID = %d recID = %d", tsID, recID);
+ while ( checkname )
+ {
+ if ( iz ) sprintf(varname, "%s_%d", name, iz+1);
- *varID = streamptr->tsteps[tsID].records[recID].varID;
- int lindex = streamptr->tsteps[tsID].records[recID].levelID;
+ status = nc_inq_varid(fileID, varname, &ncvarid);
+ if ( status != NC_NOERR )
+ {
+ checkname = FALSE;
+ }
- int isub = subtypeInqActiveIndex(streamptr->vars[*varID].subtypeID);
- *levelID = streamptr->vars[*varID].recordTable[isub].lindex[lindex];
+ if ( checkname ) iz++;
- if ( CDI_Debug )
- Message("tsID = %d, recID = %d, varID = %d, levelID = %d\n", tsID, recID, *varID, *levelID);
+ if ( iz >= CDI_MAX_NAME ) Error("Double entry of variable name '%s'!", name);
+ }
- streamptr->curTsID = tsID;
- streamptr->tsteps[tsID].curRecID = rindex;
-}
+ if ( strcmp(name, varname) != 0 )
+ {
+ if ( iz == 1 )
+ Warning("Changed double entry of variable name '%s' to '%s'!", name, varname);
+ else
+ Warning("Changed multiple entry of variable name '%s' to '%s'!", name, varname);
+ }
-/*
- at Function streamDefRecord
- at Title Define the next record
+ name = varname;
+ }
+ else
+ {
+ if ( code < 0 ) code = -code;
+ if ( pnum < 0 ) pnum = -pnum;
- at Prototype void streamDefRecord(int streamID, int varID, int levelID)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
+ if ( pdis == 255 )
+ sprintf(varname, "var%d", code);
+ else
+ sprintf(varname, "param%d.%d.%d", pnum, pcat, pdis);
- at Description
-The function streamDefRecord defines the meta-data of the next record.
- at EndFunction
-*/
-void streamDefRecord(int streamID, int varID, int levelID)
-{
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
+ char *varname2 = varname+strlen(varname);
- int tsID = streamptr->curTsID;
+ int checkname = TRUE;
+ int iz = 0;
- if ( tsID == CDI_UNDEFID )
- {
- tsID++;
- streamDefTimestep(streamID, tsID);
- }
+ while ( checkname )
+ {
+ if ( iz ) sprintf(varname2, "_%d", iz+1);
- if ( ! streamptr->record ) cdiInitRecord(streamptr);
+ int status = nc_inq_varid(fileID, varname, &ncvarid);
+ if ( status != NC_NOERR ) checkname = FALSE;
- int vlistID = streamptr->vlistID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int param = vlistInqVarParam(vlistID, varID);
- int level = (int)(zaxisInqLevel(zaxisID, levelID));
+ if ( checkname ) iz++;
- streamptr->record->varID = varID;
- streamptr->record->levelID = levelID;
- streamptr->record->param = param;
- streamptr->record->level = level;
- streamptr->record->date = streamptr->tsteps[tsID].taxis.vdate;
- streamptr->record->time = streamptr->tsteps[tsID].taxis.vtime;
- streamptr->record->gridID = gridID;
- streamptr->record->prec = vlistInqVarDatatype(vlistID, varID);
+ if ( iz >= CDI_MAX_NAME ) break;
+ }
- switch (streamptr->filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grbDefRecord(streamptr);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- srvDefRecord(streamptr);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- extDefRecord(streamptr);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- iegDefRecord(streamptr);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdfDefRecord(streamptr);
- break;
-#endif
- default:
- Error("%s support not compiled in!", strfiletype(streamptr->filetype));
- break;
+ name = varname;
+ code = 0;
+ pdis = 255;
}
-}
+ /* if ( streamptr->ncmode == 2 ) cdf_redef(fileID); */
-void streamReadRecord(int streamID, double *data, int *nmiss)
-{
- check_parg(data);
- check_parg(nmiss);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
+ int dtype = vlistInqVarDatatype(vlistID, varID);
+ int xtype = cdfDefDatatype(dtype, streamptr->filetype);
- *nmiss = 0;
+ cdf_def_var(fileID, name, (nc_type) xtype, ndims, dims, &ncvarid);
- switch (streamptr->filetype)
+#if defined (HAVE_NETCDF4)
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
{
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grbReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- srvReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- extReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- iegReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- cdfReadRecord(streamptr, data, nmiss);
- break;
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(streamptr->filetype));
- break;
- }
+ if ( chunktype == CHUNK_AUTO )
+ retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
+ else
+ retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
+
+ if ( retval ) Error("nc_def_var_chunking failed, status = %d", retval);
}
-}
+#endif
-static void
-stream_write_record(int streamID, int memtype, const void *data, int nmiss)
-{
- check_parg(data);
+ if ( streamptr->comptype == COMPRESS_ZIP )
+ {
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+ {
+ cdfDefVarDeflate(fileID, ncvarid, streamptr->complevel);
+ }
+ else
+ {
+ if ( lchunk )
+ {
+ static int lwarn = TRUE;
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("Deflate compression is only available for NetCDF4!");
+ }
+ }
+ }
+ }
- switch (streamptr->filetype)
+ if ( streamptr->comptype == COMPRESS_SZIP )
{
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grb_write_record(streamptr, memtype, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
- srvWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
- extWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
- iegWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- cdf_write_record(streamptr, memtype, data, nmiss);
- break;
- }
+ if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
+ {
+#if defined (NC_SZIP_NN_OPTION_MASK)
+ cdfDefVarSzip(fileID, ncvarid);
+#else
+ static int lwarn = TRUE;
+
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("NetCDF4/SZIP compression not available!");
+ }
#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(streamptr->filetype));
- break;
- }
- }
-}
+ }
+ else
+ {
+ static int lwarn = TRUE;
-/*
- at Function streamWriteRecord
- at Title Write a horizontal slice of a variable
+ if ( lwarn )
+ {
+ lwarn = FALSE;
+ Warning("SZIP compression is only available for NetCDF4!");
+ }
+ }
+ }
- at Prototype void streamWriteRecord(int streamID, const double *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
+ if ( stdname && *stdname )
+ cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(stdname), stdname);
- at Description
-The function streamWriteRecord writes the values of a horizontal slice (record) of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteRecord(int streamID, const double *data, int nmiss)
-{
- stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
-}
+ if ( longname && *longname )
+ cdf_put_att_text(fileID, ncvarid, "long_name", strlen(longname), longname);
-void streamWriteRecordF(int streamID, const float *data, int nmiss)
-{
- stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, nmiss);
-}
+ if ( units && *units )
+ cdf_put_att_text(fileID, ncvarid, "units", strlen(units), units);
+ if ( code > 0 && pdis == 255 )
+ cdf_put_att_int(fileID, ncvarid, "code", NC_INT, 1, &code);
-void streamCopyRecord(int streamID2, int streamID1)
-{
- stream_t *streamptr1 = stream_to_pointer(streamID1);
- stream_t *streamptr2 = stream_to_pointer(streamID2);
+ if ( pdis != 255 )
+ {
+ char paramstr[32];
+ cdiParamToString(param, paramstr, sizeof(paramstr));
+ cdf_put_att_text(fileID, ncvarid, "param", strlen(paramstr), paramstr);
+ }
- stream_check_ptr(__func__, streamptr1);
- stream_check_ptr(__func__, streamptr2);
+ if ( tableID != UNDEFID )
+ {
+ tablenum = tableInqNum(tableID);
+ if ( tablenum > 0 )
+ cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum);
+ }
- int filetype1 = streamptr1->filetype;
- int filetype2 = streamptr2->filetype;
- int filetype = FILETYPE_UNDEF;
+ char coordinates[CDI_MAX_NAME];
+ coordinates[0] = 0;
- if ( filetype1 == filetype2 ) filetype = filetype2;
- else
+ if ( zaxis_is_scalar )
{
- switch (filetype1)
+ int nczvarID = streamptr->nczvarID[zaxisindex];
+ if ( nczvarID != CDI_UNDEFID )
{
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- switch (filetype2)
- {
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- Warning("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
- filetype = filetype2;
- break;
- }
- break;
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, nczvarID, coordinates+len);
}
}
- if ( filetype == FILETYPE_UNDEF )
- Error("Streams have different file types (%s -> %s)!", strfiletype(filetype1), strfiletype(filetype2));
-
- switch (filetype)
+ if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR )
{
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grbCopyRecord(streamptr2, streamptr1);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- srvCopyRecord(streamptr2, streamptr1);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- extCopyRecord(streamptr2, streamptr1);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- iegCopyRecord(streamptr2, streamptr1);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- cdfCopyRecord(streamptr2, streamptr1);
- break;
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
+ size_t len = strlen(gridNamePtr(gridtype));
+ if ( len > 0 )
+ cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
}
-}
-
-
-void cdi_create_records(stream_t *streamptr, int tsID)
-{
- unsigned nrecords, maxrecords;
- record_t *records;
-
- tsteps_t *sourceTstep = streamptr->tsteps;
- tsteps_t *destTstep = sourceTstep + tsID;
-
- if ( destTstep->records ) return;
- int vlistID = streamptr->vlistID;
+ if ( gridIsRotated(gridID) )
+ {
+ char mapping[] = "rotated_pole";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
+ }
- if ( tsID == 0 )
+ if ( gridtype == GRID_SINUSOIDAL )
{
- maxrecords = 0;
- int nvars = streamptr->nvars;
- for ( int varID = 0; varID < nvars; varID++)
- for (int isub=0; isub<streamptr->vars[varID].subtypeSize; isub++)
- maxrecords += (unsigned)streamptr->vars[varID].recordTable[isub].nlevs;
+ char mapping[] = "sinusoidal";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
}
- else
+ else if ( gridtype == GRID_LAEA )
{
- maxrecords = (unsigned)sourceTstep->recordSize;
+ char mapping[] = "laea";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
}
-
- if ( tsID == 0 )
+ else if ( gridtype == GRID_LCC2 )
{
- nrecords = maxrecords;
+ char mapping[] = "Lambert_Conformal";
+ cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
}
- else if ( tsID == 1 )
+ else if ( gridtype == GRID_TRAJECTORY )
{
- nrecords = 0;
- maxrecords = (unsigned)sourceTstep->recordSize;
- for ( unsigned recID = 0; recID < maxrecords; recID++ )
- {
- int varID = sourceTstep->records[recID].varID;
- nrecords += (varID == CDI_UNDEFID /* varID = CDI_UNDEFID for write mode !!! */
- || vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT);
- // printf("varID nrecords %d %d %d \n", varID, nrecords, vlistInqVarTsteptype(vlistID, varID));
- }
+ cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" );
+ }
+ else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 )
+ {
+ int ncxvarID = streamptr->ncxvarID[gridindex];
+ int ncyvarID = streamptr->ncyvarID[gridindex];
+ if ( ncyvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncyvarID, coordinates+len);
+ }
+ if ( ncxvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncxvarID, coordinates+len);
+ }
+ }
+ else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
+ {
+ char cellarea[CDI_MAX_NAME] = "area: ";
+ int ncxvarID = streamptr->ncxvarID[gridindex];
+ int ncyvarID = streamptr->ncyvarID[gridindex];
+ int ncavarID = streamptr->ncavarID[gridindex];
+ if ( ncyvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncyvarID, coordinates+len);
+ }
+ if ( ncxvarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(coordinates);
+ if ( len ) coordinates[len++] = ' ';
+ cdf_inq_varname(fileID, ncxvarID, coordinates+len);
+ }
+
+ if ( ncavarID != CDI_UNDEFID )
+ {
+ size_t len = strlen(cellarea);
+ cdf_inq_varname(fileID, ncavarID, cellarea+len);
+ len = strlen(cellarea);
+ cdf_put_att_text(fileID, ncvarid, "cell_measures", len, cellarea);
+ }
+
+ if ( gridtype == GRID_UNSTRUCTURED )
+ {
+ int position = gridInqPosition(gridID);
+ if ( position > 0 )
+ cdf_put_att_int(fileID, ncvarid, "number_of_grid_in_reference", NC_INT, 1, &position);
+ }
}
- else
+ else if ( gridtype == GRID_SPECTRAL || gridtype == GRID_FOURIER )
{
- nrecords = (unsigned)streamptr->tsteps[1].nallrecs;
+ int gridTruncation = gridInqTrunc(gridID);
+ axis[iax++] = '-';
+ axis[iax++] = '-';
+ cdf_put_att_text(fileID, ncvarid, "axis", iax, axis);
+ cdf_put_att_int(fileID, ncvarid, "truncation", NC_INT, 1, &gridTruncation);
}
- // printf("tsID, nrecords %d %d\n", tsID, nrecords);
-
- if ( maxrecords > 0 )
- records = (record_t *) Malloc(maxrecords*sizeof(record_t));
- else
- records = NULL;
- destTstep->records = records;
- destTstep->recordSize = (int)maxrecords;
- destTstep->nallrecs = (int)nrecords;
+ size_t len = strlen(coordinates);
+ if ( len ) cdf_put_att_text(fileID, ncvarid, "coordinates", len, coordinates);
- if ( tsID == 0 )
- {
- for ( unsigned recID = 0; recID < maxrecords; recID++ )
- recordInitEntry(&destTstep->records[recID]);
- }
- else
+ /* if ( xtype == NC_BYTE || xtype == NC_SHORT || xtype == NC_INT ) */
{
- memcpy(destTstep->records, sourceTstep->records, (size_t)maxrecords*sizeof(record_t));
+ int laddoffset, lscalefactor;
+ double addoffset, scalefactor;
+ int astype = NC_DOUBLE;
- for ( unsigned recID = 0; recID < maxrecords; recID++ )
- {
- record_t *curRecord = &sourceTstep->records[recID];
- destTstep->records[recID].used = curRecord->used;
- if ( curRecord->used != CDI_UNDEFID && curRecord->varID != -1 ) /* curRecord->varID = -1 for write mode !!! */
+ addoffset = vlistInqVarAddoffset(vlistID, varID);
+ scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+ if ( laddoffset || lscalefactor )
+ {
+ if ( IS_EQUAL(addoffset, (double) ((float) addoffset)) &&
+ IS_EQUAL(scalefactor, (double) ((float) scalefactor)) )
{
- if ( vlistInqVarTsteptype(vlistID, curRecord->varID) != TSTEP_CONSTANT )
- {
- destTstep->records[recID].position = CDI_UNDEFID;
- destTstep->records[recID].size = 0;
- destTstep->records[recID].used = FALSE;
- }
+ astype = NC_FLOAT;
}
- }
+
+ if ( xtype == (int) NC_FLOAT ) astype = NC_FLOAT;
+
+ cdf_put_att_double(fileID, ncvarid, "add_offset", (nc_type) astype, 1, &addoffset);
+ cdf_put_att_double(fileID, ncvarid, "scale_factor", (nc_type) astype, 1, &scalefactor);
+ }
}
-}
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
-#endif
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+ if ( dtype == DATATYPE_UINT8 && xtype == NC_BYTE )
+ {
+ int validrange[2] = {0, 255};
+ cdf_put_att_int(fileID, ncvarid, "valid_range", NC_SHORT, 2, validrange);
+ cdf_put_att_text(fileID, ncvarid, "_Unsigned", 4, "true");
+ }
+ streamptr->vars[varID].ncvarid = ncvarid;
+ if ( vlistInqVarMissvalUsed(vlistID, varID) )
+ cdfDefVarMissval(streamptr, varID, vlistInqVarDatatype(vlistID, varID), 0);
+ if ( zid == -1 )
+ {
+ if ( zaxisInqType(zaxisID) == ZAXIS_CLOUD_BASE ||
+ zaxisInqType(zaxisID) == ZAXIS_CLOUD_TOP ||
+ zaxisInqType(zaxisID) == ZAXIS_ISOTHERM_ZERO ||
+ zaxisInqType(zaxisID) == ZAXIS_TOA ||
+ zaxisInqType(zaxisID) == ZAXIS_SEA_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_LAKE_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TA ||
+ zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TW ||
+ zaxisInqType(zaxisID) == ZAXIS_MIX_LAYER ||
+ zaxisInqType(zaxisID) == ZAXIS_ATMOSPHERE )
+ {
+ zaxisInqName(zaxisID, varname);
+ cdf_put_att_text(fileID, ncvarid, "level_type", strlen(varname), varname);
+ }
+ }
-#undef UNDEFID
-#define UNDEFID CDI_UNDEFID
+ if ( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
+ {
+ /* void cdf_put_att_int( int ncid, int varid, const char *name, nc_type xtype,
+ size_t len, const int *ip )
+ */
+ cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID);
+ cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount);
+ cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type);
-#define SINGLE_PRECISION 4
-#define DOUBLE_PRECISION 8
+#ifdef DBG
+ if( DBG )
+ {
+ fprintf( stderr, "cdfDefVar :\n EnsID %d\n Enscount %d\n Forecast init type %d\n", ensID,
+ ensCount, forecast_type );
+ }
+#endif
+ }
-#if defined (HAVE_LIBSERVICE)
+ /* Attributes */
+ cdfDefineAttributes(vlistID, varID, fileID, ncvarid);
+ /* if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); */
-typedef struct {
- int param;
- int level;
-} SRVCOMPVAR;
+ return ncvarid;
+}
-static int srvInqDatatype(int prec)
+void cdfEndDef(stream_t *streamptr)
{
- int datatype;
+ cdfDefGlobalAtts(streamptr);
+ cdfDefLocalAtts(streamptr);
- if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
- else datatype = DATATYPE_FLT32;
+ if ( streamptr->accessmode == 0 )
+ {
+ int fileID = streamptr->fileID;
+ if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- return (datatype);
-}
+ int nvars = streamptr->nvars;
+ for ( int varID = 0; varID < nvars; varID++ )
+ cdfDefVar(streamptr, varID);
+ if ( streamptr->ncmode == 2 )
+ {
+ if ( CDI_netcdf_hdr_pad == 0UL )
+ cdf_enddef(fileID);
+ else
+ cdf__enddef(fileID, CDI_netcdf_hdr_pad);
+ }
-static int srvDefDatatype(int datatype)
-{
- int prec;
+ streamptr->accessmode = 1;
+ }
+}
- if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- Error("CDI/SERVICE library does not support complex numbers!");
+static
+void cdfWriteGridTraj(stream_t *streamptr, int gridID)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
- datatype = DATATYPE_FLT32;
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int lonID = streamptr->xdimID[gridindex];
+ int latID = streamptr->ydimID[gridindex];
- if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION;
- else prec = SINGLE_PRECISION;
+ double xlon = gridInqXval(gridID, 0);
+ double xlat = gridInqYval(gridID, 0);
+ int tsID = streamptr->curTsID;
+ size_t index = (size_t)tsID;
- return (prec);
+ cdf_put_var1_double(fileID, lonID, &index, &xlon);
+ cdf_put_var1_double(fileID, latID, &index, &xlat);
}
-/* not used
-int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
+static
+void cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, size_t nvals, size_t xsize, size_t ysize,
+ int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
{
- int status;
- int fileID;
- int icode, ilevel;
- int zaxisID = -1;
- int header[8];
- int vlistID;
- void *srvp = streamptr->record->exsep;
+ const double *pdata_dp = (const double *) data;
+ double *mdata_dp = NULL;
+ double *sdata_dp = NULL;
+ const float *pdata_sp = (const float *) data;
+ float *mdata_sp = NULL;
+ float *sdata_sp = NULL;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ /* if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
+ {
+ double missval = vlistInqVarMissval(vlistID, varID);
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ bool laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ bool lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
- *varID = -1;
- *levelID = -1;
+ if ( laddoffset || lscalefactor )
+ {
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ mdata_sp = (float *) Malloc(nvals*sizeof(float));
+ memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+ pdata_sp = mdata_sp;
- status = srvRead(fileID, srvp);
- if ( status != 0 ) return (0);
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ double temp = mdata_sp[i];
+ if ( !DBL_IS_EQUAL(temp, missval) )
+ {
+ if ( laddoffset ) temp -= addoffset;
+ if ( lscalefactor ) temp /= scalefactor;
+ mdata_sp[i] = (float)temp;
+ }
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ double temp = mdata_sp[i];
+ if ( laddoffset ) temp -= addoffset;
+ if ( lscalefactor ) temp /= scalefactor;
+ mdata_sp[i] = (float)temp;
+ }
+ }
+ }
+ else
+ {
+ mdata_dp = (double *) Malloc(nvals*sizeof(double));
+ memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+ pdata_dp = mdata_dp;
- srvInqHeader(srvp, header);
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
+ {
+ if ( laddoffset ) mdata_dp[i] -= addoffset;
+ if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+ }
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nvals; i++ )
+ {
+ if ( laddoffset ) mdata_dp[i] -= addoffset;
+ if ( lscalefactor ) mdata_dp[i] /= scalefactor;
+ }
+ }
+ }
+ }
- icode = header[0];
- ilevel = header[1];
+ if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
+ dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
+ {
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ if ( mdata_sp == NULL )
+ {
+ mdata_sp = (float *) Malloc(nvals*sizeof(float));
+ memcpy(mdata_sp, pdata_sp, nvals*sizeof(float));
+ pdata_sp = mdata_sp;
+ }
- *varID = vlistInqVarID(vlistID, icode);
+ for ( size_t i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
- if ( *varID == UNDEFID ) Error("Code %d undefined", icode);
+ if ( dtype == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < nvals; ++i )
+ if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
+ }
+ }
+ }
+ else
+ {
+ if ( mdata_dp == NULL )
+ {
+ mdata_dp = (double *) Malloc(nvals*sizeof(double));
+ memcpy(mdata_dp, pdata_dp, nvals*sizeof(double));
+ pdata_dp = mdata_dp;
+ }
- zaxisID = vlistInqVarZaxis(vlistID, *varID);
+ for ( size_t i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
- *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
+ if ( dtype == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < nvals; ++i )
+ if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
+ }
+ }
+ }
+ }
- return (1);
-}
-*/
+ if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
+ {
+ double fmin, fmax;
+ fmin = 1.0e200;
+ fmax = -1.0e200;
+ for ( size_t i = 0; i < nvals; ++i )
+ {
+ if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
+ {
+ if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
+ if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
+ }
+ }
+ Message("nvals = %zu, nmiss = %d, missval = %g, minval = %g, maxval = %g",
+ nvals, nmiss, missval, fmin, fmax);
+ }
+ }
-void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
-{
- int vlistID, fileID;
- int status;
- int recID, vrecID, tsID;
- off_t recpos;
- int header[8];
- int varID, gridID;
- int i, size;
- double missval;
- void *srvp = streamptr->record->exsep;
+ if ( swapxy ) // implemented only for cdf_write_var_slice()
+ {
+ size_t gridsize = xsize*ysize;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ sdata_sp = (float *) Malloc(gridsize*sizeof(float));
+ for ( size_t j = 0; j < ysize; ++j )
+ for ( size_t i = 0; i < xsize; ++i )
+ sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
+ pdata_sp = sdata_sp;
+ }
+ else
+ {
+ sdata_dp = (double *) Malloc(gridsize*sizeof (double));
+ for ( size_t j = 0; j < ysize; ++j )
+ for ( size_t i = 0; i < xsize; ++i )
+ sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
+ pdata_dp = sdata_dp;
+ }
+ }
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- vrecID = streamptr->tsteps[tsID].curRecID;
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- recpos = streamptr->tsteps[tsID].records[recID].position;
- varID = streamptr->tsteps[tsID].records[recID].varID;
+ if ( memtype == MEMTYPE_FLOAT )
+ cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
+ else
+ cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
- fileSetPos(fileID, recpos, SEEK_SET);
+ if ( mdata_dp ) Free(mdata_dp);
+ if ( sdata_dp ) Free(sdata_dp);
+ if ( mdata_sp ) Free(mdata_sp);
+ if ( sdata_sp ) Free(sdata_sp);
+}
- status = srvRead(fileID, srvp);
- if ( status != 0 )
- Error("Failed to read record from SRV file");
- srvInqHeader(srvp, header);
- srvInqDataDP(srvp, data);
+void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- size = gridInqSize(gridID);
+ size_t xsize = 0, ysize = 0;
+ size_t size;
+ size_t start[5];
+ size_t count[5];
+ int swapxy = FALSE;
+ int ndims = 0;
+ int idim;
- streamptr->numvals += size;
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
- *nmiss = 0;
- for ( i = 0; i < size; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
-}
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ long ntsteps = streamptr->ntsteps;
+ if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
-void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
-{
- streamFCopyRecord(streamptr2, streamptr1, "SRV");
-}
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+ int ncvarid = cdfDefVar(streamptr, varID);
-void srvDefRecord(stream_t *streamptr)
-{
- int gridID;
- int header[8];
- int xsize, ysize;
- int datatype;
- int pdis, pcat, pnum;
- srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- gridID = streamptr->record->gridID;
+ int xid = UNDEFID, yid = UNDEFID;
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
- cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
- header[0] = pnum;
- header[1] = streamptr->record->level;
- header[2] = streamptr->record->date;
- header[3] = streamptr->record->time;
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
- if ( xsize == 0 || ysize == 0 )
+ if ( tsteptype != TSTEP_CONSTANT )
{
- xsize = gridInqSize(gridID);
- ysize = 1;
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
}
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
- if ( gridInqSize(gridID) != xsize*ysize )
- Error("Internal problem with gridsize!");
- header[4] = xsize;
- header[5] = ysize;
- header[6] = 0;
- header[7] = 0;
+ if ( zid != UNDEFID )
+ {
+ start[ndims] = 0;
+ count[ndims] = (size_t)zaxisInqSize(zaxisID);
+ ndims++;
+ }
- datatype = streamptr->record->prec;
+ if ( yid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, yid, &size);
+ /* count[ndims] = gridInqYsize(gridID); */
+ count[ndims] = size;
+ ndims++;
+ }
- srvp->dprec = srvDefDatatype(datatype);
+ if ( xid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, xid, &size);
+ /* count[ndims] = gridInqXsize(gridID); */
+ count[ndims] = size;
+ ndims++;
+ }
- srvDefHeader(srvp, header);
-}
+ if ( CDI_Debug )
+ for (idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+ if ( streamptr->ncmode == 1 )
+ {
+ cdf_enddef(fileID);
+ streamptr->ncmode = 2;
+ }
-void srvWriteRecord(stream_t *streamptr, const double *data)
-{
- int fileID = streamptr->fileID;
- void *srvp = streamptr->record->exsep;
+ int dtype = vlistInqVarDatatype(vlistID, varID);
- srvDefDataDP(srvp, data);
- srvWrite(fileID, srvp);
-}
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-static
-void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ysize,
- size_t recsize, off_t position, int prec)
-{
- int vlistID = streamptr->vlistID;
- int tsID = streamptr->curTsID;
- int recID = recordNewEntry(streamptr, tsID);
- record_t *record = &streamptr->tsteps[tsID].records[recID];
+ size_t nvals = (size_t)(gridInqSize(gridID)) * (size_t)(zaxisInqSize(zaxisID));
- record->size = recsize;
- record->position = position;
- record->param = param;
- record->ilevel = level;
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
- grid_t grid;
- memset(&grid, 0, sizeof(grid_t));
- grid.type = GRID_GENERIC;
- grid.size = xsize*ysize;
- grid.xsize = xsize;
- grid.ysize = ysize;
- grid.xvals = NULL;
- grid.yvals = NULL;
- int gridID = varDefGrid(vlistID, &grid, 0);
- /*
- if ( level == 0 ) leveltype = ZAXIS_SURFACE;
- else leveltype = ZAXIS_GENERIC;
- */
- int leveltype = ZAXIS_GENERIC;
- int datatype = srvInqDatatype(prec);
+void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
+ const int rect[][2], const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- int levelID = 0;
- int varID;
- varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
- datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ int xid = UNDEFID, yid = UNDEFID;
+ size_t xsize = 0, ysize = 0;
+ size_t start[5];
+ size_t count[5];
+ int swapxy = FALSE;
+ int ndims = 0;
+ int idim;
+ int streamID = streamptr->self;
- xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
- record->varID = (short)varID;
- record->levelID = (short)levelID;
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d", streamID, varID);
- streamptr->tsteps[tsID].nallrecs++;
- streamptr->nrecs++;
+ int vlistID = streamInqVlist(streamID);
+ int fileID = streamInqFileID(streamID);
+ long ntsteps = streamptr->ntsteps;
if ( CDI_Debug )
- Message("varID = %d gridID = %d levelID = %d",
- varID, gridID, levelID);
-}
+ Message("ntsteps = %ld", ntsteps);
-static
-void srvScanTimestep1(stream_t *streamptr)
-{
- int header[8];
- int prec = 0;
- int status;
- int fileID;
- int rxsize = 0, rysize = 0;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- DateTime datetime0 = { LONG_MIN, LONG_MIN };
- int tsID;
- int varID;
- off_t recpos;
- int nrecords, nrecs, recID;
- int taxisID = -1;
- taxis_t *taxis;
- int vlistID;
- srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
- streamptr->curTsID = 0;
+ int ncvarid = cdfDefVar(streamptr, varID);
- tsID = tstepsNewEntry(streamptr);
- taxis = &streamptr->tsteps[tsID].taxis;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- if ( tsID != 0 )
- Error("Internal problem! tstepsNewEntry returns %d", tsID);
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ {
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
- fileID = streamptr->fileID;
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
- nrecs = 0;
- while ( TRUE )
+ if ( tsteptype != TSTEP_CONSTANT )
{
- recpos = fileGetPos(fileID);
- status = srvRead(fileID, srvp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 1;
- break;
- }
- size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
+ }
+ if ( zid != UNDEFID )
+ {
+ int size = zaxisInqSize(zaxisID);
+ xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
+ && rect[2][1] <= size);
+ start[ndims] = (size_t)rect[2][0];
+ count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
+ ndims++;
+ }
+ if ( yid != UNDEFID )
+ {
+ size_t size;
+ cdf_inq_dimlen(fileID, yid, &size);
+ xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
+ && (size_t)rect[1][1] <= size);
+ start[ndims] = (size_t)rect[1][0];
+ count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
+ ndims++;
+ }
+ if ( xid != UNDEFID )
+ {
+ size_t size;
+ cdf_inq_dimlen(fileID, xid, &size);
+ xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
+ && (size_t)rect[0][1] <= size);
+ start[ndims] = (size_t)rect[0][0];
+ count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
+ ndims++;
+ }
- srvInqHeader(srvp, header);
+ if ( CDI_Debug )
+ for (idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
- prec = srvp->dprec;
- rcode = header[0];
- rlevel = header[1];
- vdate = header[2];
- vtime = header[3];
- rxsize = header[4];
- rysize = header[5];
+ if ( streamptr->ncmode == 1 )
+ {
+ cdf_enddef(fileID);
+ streamptr->ncmode = 2;
+ }
- param = cdiEncodeParam(rcode, 255, 255);
+ int dtype = vlistInqVarDatatype(vlistID, varID);
- if ( nrecs == 0 )
- {
- datetime0.date = vdate;
- datetime0.time = vtime;
- }
- else
- {
- for ( recID = 0; recID < nrecs; recID++ )
- if ( streamptr->tsteps[0].records[recID].param == param
- && streamptr->tsteps[0].records[recID].ilevel == rlevel )
- break;
- if ( recID < nrecs ) break;
- DateTime datetime = { .date = vdate, .time = vtime };
- if ( datetimeCmp(datetime, datetime0) )
- Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
- }
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
- nrecs++;
+ size_t nvals = (size_t)(gridInqSize(gridID)) * (size_t)(zaxisInqSize(zaxisID));
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals,
+ xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
- srv_add_record(streamptr, param, rlevel, rxsize, rysize, recsize, recpos, prec);
- }
- streamptr->rtsteps = 1;
+void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+{
+ if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdi_generate_vars(streamptr);
+ size_t xsize = 0, ysize = 0;
+ size_t start[5];
+ size_t count[5];
+ int dimorder[3];
+ int xid = UNDEFID, yid = UNDEFID;
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = (int)datetime0.date;
- taxis->vtime = (int)datetime0.time;
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
- vlistID = streamptr->vlistID;
- vlistDefTaxis(vlistID, taxisID);
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- vlist_check_contents(vlistID);
+ long ntsteps = streamptr->ntsteps;
+ if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
- nrecords = streamptr->tsteps[0].nallrecs;
- if ( nrecords < streamptr->tsteps[0].recordSize )
+ if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
+
+ int ncvarid = cdfDefVar(streamptr, varID);
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ vlistInqVarDimorder(vlistID, varID, &dimorder);
+
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
{
- streamptr->tsteps[0].recordSize = nrecords;
- streamptr->tsteps[0].records =
- (record_t *) Realloc(streamptr->tsteps[0].records,
- (size_t)nrecords * sizeof(record_t));
+ cdfWriteGridTraj(streamptr, gridID);
+ }
+ else
+ {
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
}
- streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
- streamptr->tsteps[0].nrecs = nrecords;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[0].recIDs[recID] = recID;
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
- if ( streamptr->ntsteps == -1 )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ int swapxy = (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID;
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ size_t ndims = 0;
+ if ( tsteptype != TSTEP_CONSTANT )
+ {
+ start[ndims] = (size_t)ntsteps - 1;
+ count[ndims] = 1;
+ ndims++;
}
- if ( streamptr->ntsteps == 1 )
+ for ( int id = 0; id < 3; ++id )
{
- if ( taxis->vdate == 0 && taxis->vtime == 0 )
- {
- streamptr->ntsteps = 0;
- for ( varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- }
+ if ( dimorder[id] == 3 && zid != UNDEFID )
+ {
+ start[ndims] = (size_t)levelID;
+ count[ndims] = 1;
+ ndims++;
+ }
+ else if ( dimorder[id] == 2 && yid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, yid, &ysize);
+ count[ndims] = ysize;
+ ndims++;
+ }
+ else if ( dimorder[id] == 1 && xid != UNDEFID )
+ {
+ start[ndims] = 0;
+ cdf_inq_dimlen(fileID, xid, &xsize);
+ count[ndims] = xsize;
+ ndims++;
+ }
}
-}
-static
-int srvScanTimestep2(stream_t *streamptr)
-{
- int header[8];
- int status;
- int fileID;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- int tsID;
- int varID;
- off_t recpos = 0;
- int nrecords, nrecs, recID, rindex;
- int nextstep;
- taxis_t *taxis;
- int vlistID;
- SRVCOMPVAR compVar, compVar0;
- void *srvp = streamptr->record->exsep;
+ if ( CDI_Debug )
+ for (size_t idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
- streamptr->curTsID = 1;
+ int dtype = vlistInqVarDatatype(vlistID, varID);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
- tsID = streamptr->rtsteps;
- if ( tsID != 1 )
- Error("Internal problem! unexpected timestep %d", tsID+1);
+ size_t nvals = (size_t)(gridInqSize(gridID));
- taxis = &streamptr->tsteps[tsID].taxis;
+ cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
+}
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- cdi_create_records(streamptr, tsID);
+void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
+{
+ int varID = streamptr->record->varID;
+ int levelID = streamptr->record->levelID;
- nrecords = streamptr->tsteps[0].nallrecs;
- streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
- streamptr->tsteps[1].nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
- streamptr->tsteps[1].recIDs[recID] = -1;
+ cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+}
- for ( recID = 0; recID < nrecords; recID++ )
- {
- varID = streamptr->tsteps[0].records[recID].varID;
- streamptr->tsteps[tsID].records[recID].position =
- streamptr->tsteps[0].records[recID].position;
- streamptr->tsteps[tsID].records[recID].size =
- streamptr->tsteps[0].records[recID].size;
- }
+#endif
+#ifdef HAVE_CONFIG_H
+#endif
- for ( rindex = 0; rindex <= nrecords; rindex++ )
- {
- recpos = fileGetPos(fileID);
- status = srvRead(fileID, srvp);
- if ( status != 0 )
- {
- streamptr->ntsteps = 2;
- break;
- }
- size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
+#ifdef HAVE_LIBNETCDF
- srvInqHeader(srvp, header);
+#include <limits.h>
+#include <float.h>
- rcode = header[0];
- rlevel = header[1];
- vdate = header[2];
- vtime = header[3];
- param = cdiEncodeParam(rcode, 255, 255);
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
+#undef UNDEFID
+#define UNDEFID CDI_UNDEFID
- compVar.param = param;
- compVar.level = rlevel;
- nextstep = FALSE;
- for ( recID = 0; recID < nrecords; recID++ )
- {
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
- if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) == 0 )
- {
- if ( streamptr->tsteps[tsID].records[recID].used )
- {
- nextstep = TRUE;
- }
- else
- {
- streamptr->tsteps[tsID].records[recID].used = TRUE;
- streamptr->tsteps[tsID].recIDs[rindex] = recID;
- }
- break;
- }
- }
- if ( recID == nrecords )
- {
- Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
- return (CDI_EUFSTRUCT);
- }
+static
+void cdfReadGridTraj(stream_t *streamptr, int gridID)
+{
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- if ( nextstep ) break;
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int lonID = streamptr->xdimID[gridindex];
+ int latID = streamptr->ydimID[gridindex];
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
+ int tsID = streamptr->curTsID;
+ size_t index = (size_t)tsID;
- streamptr->tsteps[tsID].records[recID].size = recsize;
+ double xlon, xlat;
+ cdf_get_var1_double(fileID, lonID, &index, &xlon);
+ cdf_get_var1_double(fileID, latID, &index, &xlat);
- compVar0.param = streamptr->tsteps[tsID].records[recID].param;
- compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
+ gridDefXvals(gridID, &xlon);
+ gridDefYvals(gridID, &xlat);
+}
- if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) != 0 )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- return (CDI_EUFSTRUCT);
- }
+static
+void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
+{
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
- streamptr->tsteps[1].records[recID].position = recpos;
- }
+ if ( CDI_Debug ) Message("tsID = %d", tsID);
- nrecs = 0;
- for ( recID = 0; recID < nrecords; recID++ )
+ int xid = UNDEFID, yid = UNDEFID;
+ if ( gridInqType(gridID) == GRID_TRAJECTORY )
{
- if ( ! streamptr->tsteps[tsID].records[recID].used )
- {
- varID = streamptr->tsteps[tsID].records[recID].varID;
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
- else
- {
- nrecs++;
- }
+ cdfReadGridTraj(streamptr, gridID);
}
- streamptr->tsteps[tsID].nrecs = nrecs;
+ else
+ {
+ xid = streamptr->xdimID[gridindex];
+ yid = streamptr->ydimID[gridindex];
+ }
+ int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
+ int zid = streamptr->zaxisID[zaxisindex];
- streamptr->rtsteps = 2;
+ int ndims = 0;
+#define addDimension(startCoord, length) do \
+ { \
+ (*start)[ndims] = startCoord; \
+ (*count)[ndims] = length; \
+ ndims++; \
+ } while(0)
+ if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+ if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
+ if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
+ if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
+#undef addDimension
- if ( streamptr->ntsteps == -1 )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+ assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
- streamptr->tsteps[tsID-1].next = TRUE;
- streamptr->tsteps[tsID].position = recpos;
+ if ( CDI_Debug )
+ for (int idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
+}
+
+//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
+//Returns the number of missing + out-of-range values encountered.
+static
+size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
+ {
+ const bool haveOffset = IS_NOT_EQUAL(offset, 0);
+ const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+ size_t missValCount = 0;
+
+ if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
+ if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
+
+ bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
+ assert(!haveRangeCheck || haveMissVal);
+
+ switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
+ | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ {
+ case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] * scaleFactor + offset;
+ }
+ break;
+ case 13: /* haveRangeCheck & haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] + offset;
+ }
+ break;
+ case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal
+ : isMissVal ? data[i] : data[i] * scaleFactor;
+ }
+ break;
+ case 9: /* haveRangeCheck & haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? missVal : data[i];
+ }
+ break;
+ case 7: /* haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = data[i] * scaleFactor + offset;
+ break;
+ case 6: /* haveOffset & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = data[i] * scaleFactor + offset;
+ break;
+ case 5: /* haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] += offset;
+ break;
+ case 4: /* haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] += offset;
+ break;
+ case 3: /* haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] *= scaleFactor;
+ break;
+ case 2: /* haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] *= scaleFactor;
+ break;
+ case 1: /* haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
+ break;
}
- return (0);
+ return missValCount;
}
+static
+size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
+ {
+ const bool haveOffset = IS_NOT_EQUAL(offset, 0);
+ const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
+ size_t missValCount = 0;
-int srvInqContents(stream_t *streamptr)
-{
- int fileID;
- int status = 0;
-
- fileID = streamptr->fileID;
-
- streamptr->curTsID = 0;
+ if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
+ if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
- srvScanTimestep1(streamptr);
+ bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
+ assert(!haveRangeCheck || haveMissVal);
- if ( streamptr->ntsteps == -1 ) status = srvScanTimestep2(streamptr);
+ switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
+ | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
+ {
+ case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] * scaleFactor + offset);
+ }
+ break;
+ case 13: /* haveRangeCheck & haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] + offset);
+ }
+ break;
+ case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal
+ : isMissVal ? data[i] : (float)(data[i] * scaleFactor);
+ }
+ break;
+ case 9: /* haveRangeCheck & haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ {
+ int outOfRange = data[i] < validMin || data[i] > validMax;
+ int isMissVal = DBL_IS_EQUAL(data[i], missVal);
+ missValCount += (size_t)(outOfRange | isMissVal);
+ data[i] = outOfRange ? (float)missVal : data[i];
+ }
+ break;
+ case 7: /* haveMissVal & haveScaleFactor & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] * scaleFactor + offset);
+ break;
+ case 6: /* haveOffset & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] * scaleFactor + offset);
+ break;
+ case 5: /* haveMissVal & haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] + offset);
+ break;
+ case 4: /* haveOffset */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] + offset);
+ break;
+ case 3: /* haveMissVal & haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ if ( DBL_IS_EQUAL(data[i], missVal) )
+ missValCount++;
+ else
+ data[i] = (float)(data[i] * scaleFactor);
+ break;
+ case 2: /* haveScaleFactor */
+ for ( size_t i = 0; i < valueCount; i++ )
+ data[i] = (float)(data[i] * scaleFactor);
+ break;
+ case 1: /* haveMissVal */
+ for ( size_t i = 0; i < valueCount; i++ )
+ missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
+ break;
+ }
- fileSetPos(fileID, 0, SEEK_SET);
+ return missValCount;
+}
- return (status);
+static
+size_t min_size(size_t a, size_t b)
+{
+ return a < b ? a : b;
}
static
-long srvScanTimestep(stream_t *streamptr)
+void transpose2dArrayDP(size_t inWidth, size_t inHeight, double *data)
{
- int header[8];
- int status;
- int fileID;
- /* int rxsize = 0, rysize = 0; */
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
- off_t recpos = 0;
- int recID;
- int rindex, nrecs = 0;
- void *srvp = streamptr->record->exsep;
+ const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+ // which should be a decent compromise on many architectures.
+#ifdef __cplusplus
+ double *out[inHeight];
+ double *temp[inWidth];
+ temp[0] = (double *) Malloc(inHeight*inWidth*sizeof(double));
+ memcpy(temp[0], data, inHeight*inWidth*sizeof(double));
+ for(int i = 0; i < inHeight; i++) out[i] = data + (inWidth*i);
+ for(int i = 1; i < inWidth; i++) temp[i] = temp[0] + (inHeight*i);
+#else
+ double (*out)[inHeight] = (double (*)[inHeight])data;
+ double (*temp)[inWidth] = (double (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
+ memcpy(temp, data, inHeight*sizeof(*temp));
+#endif
+
/*
- if ( CDI_Debug )
- {
- Message("streamID = %d", streamptr->self);
- Message("cts = %d", streamptr->curTsID);
- Message("rts = %d", streamptr->rtsteps);
- Message("nts = %d", streamptr->ntsteps);
- }
+ for ( size_t y = 0; y < inHeight; ++y )
+ for ( size_t x = 0; x < inWidth; ++x )
+ out[x][y] = temp[y][x];
*/
- int tsID = streamptr->rtsteps;
- taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
-
- if ( streamptr->tsteps[tsID].recordSize == 0 )
+ for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
{
- cdi_create_records(streamptr, tsID);
-
- nrecs = streamptr->tsteps[1].nrecs;
-
- streamptr->tsteps[tsID].nrecs = nrecs;
- streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
- for ( recID = 0; recID < nrecs; recID++ )
- streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
-
- fileID = streamptr->fileID;
-
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
-
- for ( rindex = 0; rindex <= nrecs; rindex++ )
- {
- recpos = fileGetPos(fileID);
- status = srvRead(fileID, srvp);
- if ( status != 0 )
- {
- streamptr->ntsteps = streamptr->rtsteps + 1;
- break;
- }
- size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
-
- srvInqHeader(srvp, header);
-
- rcode = header[0];
- rlevel = header[1];
- vdate = header[2];
- vtime = header[3];
- /* rxsize = header[4]; */
- /* rysize = header[5]; */
-
- param = cdiEncodeParam(rcode, 255, 255);
-
- // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
- if ( rindex == nrecs ) continue;
- recID = streamptr->tsteps[tsID].recIDs[rindex];
-
- if ( rindex == 0 )
- {
- taxis->type = TAXIS_ABSOLUTE;
- taxis->vdate = vdate;
- taxis->vtime = vtime;
- }
-
- if ( param != streamptr->tsteps[tsID].records[recID].param
- || rlevel != streamptr->tsteps[tsID].records[recID].ilevel )
- {
- Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d",
- tsID, recID,
- streamptr->tsteps[tsID].records[recID].param, param,
- streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
- Error("Invalid, unsupported or inconsistent record structure!");
- }
-
- streamptr->tsteps[tsID].records[recID].position = recpos;
- streamptr->tsteps[tsID].records[recID].size = recsize;
-
- if ( CDI_Debug )
- Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
- }
-
- streamptr->rtsteps++;
+ for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
+ {
+ for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+ {
+ for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+ {
+ out[x][y] = temp[y][x];
+ }
+ }
+ }
+ }
- if ( streamptr->ntsteps != streamptr->rtsteps )
- {
- tsID = tstepsNewEntry(streamptr);
- if ( tsID != streamptr->rtsteps )
- Error("Internal error. tsID = %d", tsID);
+ Free(temp[0]);
+}
- streamptr->tsteps[tsID-1].next = 1;
- streamptr->tsteps[tsID].position = recpos;
- }
+static
+void transpose2dArraySP(size_t inWidth, size_t inHeight, float *data)
+{
+ const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
+ // which should be a decent compromise on many architectures.
+#ifdef __cplusplus
+ float *out[inHeight];
+ float *temp[inWidth];
+ temp[0] = (float *) Malloc(inHeight*inWidth*sizeof(float));
+ memcpy(temp[0], data, inHeight*inWidth*sizeof(float));
+ for(int i = 0; i < inHeight; i++) out[i] = data + (inWidth*i);
+ for(int i = 1; i < inWidth; i++) temp[i] = temp[0] + (inHeight*i);
+#else
+ float (*out)[inHeight] = (float (*)[inHeight])data;
+ float (*temp)[inWidth] = (float (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
+ memcpy(temp, data, inHeight*sizeof(*temp));
+#endif
- fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
- streamptr->tsteps[tsID].position = recpos;
- }
+ /*
+ for ( size_t y = 0; y < inHeight; ++y )
+ for ( size_t x = 0; x < inWidth; ++x )
+ out[x][y] = temp[y][x];
+ */
- if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
+ for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
{
- Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
- streamptr->ntsteps = tsID;
+ for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
+ {
+ for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
+ {
+ for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
+ {
+ out[x][y] = temp[y][x];
+ }
+ }
+ }
}
- return (streamptr->ntsteps);
+ Free(temp);
}
-
-int srvInqTimestep(stream_t *streamptr, int tsID)
+static
+void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
{
- long ntsteps;
- int nrecs;
-
- if ( tsID == 0 && streamptr->rtsteps == 0 )
- Error("Call to cdiInqContents missing!");
+ int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
+ int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
- if ( CDI_Debug )
- Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
+ (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
+ switch ( gridInqType(gridId) )
+ {
+ case GRID_TRAJECTORY:
+ cdfReadGridTraj(streamptr, gridId);
+ break;
- ntsteps = UNDEFID;
- while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
- ntsteps = srvScanTimestep(streamptr);
+ case GRID_UNSTRUCTURED:
+ (*outDimIds)[0] = streamptr->xdimID[gridindex];
+ break;
- if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID )
- {
- nrecs = 0;
- }
- else
- {
- streamptr->curTsID = tsID;
- nrecs = streamptr->tsteps[tsID].nrecs;
+ default:
+ (*outDimIds)[0] = streamptr->xdimID[gridindex];
+ (*outDimIds)[1] = streamptr->ydimID[gridindex];
+ break;
}
- return (nrecs);
+ int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
+ int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
+ (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
}
-
-void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+static
+int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
{
- int vlistID, fileID;
- int levID, nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int header[8];
- int tsid;
- int recID;
- int i;
- double missval;
- void *srvp = streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
-
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
-
- currentfilepos = fileGetPos(fileID);
+ if((*dimIds)[0] != UNDEFID) return 0;
+ if((*dimIds)[1] != UNDEFID) return 0;
+ int nvdims;
+ cdf_inq_varndims(fileId, ncvarid, &nvdims);
+ if(nvdims != 3) return 0;
- for (levID = 0; levID < nlevs; levID++)
+ int varDimIds[3];
+ cdf_inq_vardimid(fileId, ncvarid, varDimIds);
+ size_t size = 0;
+ if ( (*dimIds)[2] == varDimIds[2] )
{
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- if (srvRead(fileID, srvp) < 0)
- abort();
- srvInqHeader(srvp, header);
- srvInqDataDP(srvp, &data[levID*gridsize]);
+ cdf_inq_dimlen(fileId, varDimIds[1], &size);
+ if ( size == 1 ) return 1;
}
- fileSetPos(fileID, currentfilepos, SEEK_SET);
-
- *nmiss = 0;
- for ( i = 0; i < nlevs*gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
+ else if ( (*dimIds)[2] == varDimIds[1] )
+ {
+ cdf_inq_dimlen(fileId, varDimIds[2], &size);
+ if ( size == 1 ) return 2;
+ }
+ return 0;
}
-
-void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
+static
+void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
{
- int vlistID, fileID;
- int nlevs, gridID, gridsize;
- off_t recpos, currentfilepos;
- int header[8];
- int tsid;
- int recID;
- int i;
- double missval;
- void *srvp = streamptr->record->exsep;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- /* NOTE: tiles are not supported here! */
- nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- missval = vlistInqVarMissval(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- tsid = streamptr->curTsID;
-
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d",
- nlevs, gridID, gridsize);
-
- currentfilepos = fileGetPos(fileID);
+ int tsID = streamptr->curTsID;
+ if ( CDI_Debug ) Message("tsID = %d", tsID);
- /* NOTE: tiles are not supported here! */
- recID = streamptr->vars[varID].recordTable[0].recordID[levID];
- recpos = streamptr->tsteps[tsid].records[recID].position;
- fileSetPos(fileID, recpos, SEEK_SET);
- if (srvRead(fileID, srvp) < 0)
- abort();
- srvInqHeader(srvp, header);
- srvInqDataDP(srvp, data);
+ int fileId = streamptr->fileID;
+ int vlistId = streamptr->vlistID;
+ int ncvarid = streamptr->vars[varId].ncvarid;
- fileSetPos(fileID, currentfilepos, SEEK_SET);
+ int gridId = vlistInqVarGrid(vlistId, varId);
+ int tsteptype = vlistInqVarTsteptype(vlistId, varId);
+ int gridsize = gridInqSize(gridId);
- *nmiss = 0;
- for ( i = 0; i < gridsize; i++ )
- if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
- {
- data[i] = missval;
- (*nmiss)++;
- }
-}
+ streamptr->numvals += gridsize;
+ int dimIds[3]; //this array joins the old variables xid, yid, and zid
+ cdfInqDimIds(streamptr, varId, &dimIds);
-void srvWriteVarDP(stream_t *streamptr, int varID, const double *data)
-{
- int fileID;
- int levID, nlevs, gridID, gridsize;
- int zaxisID;
- double level;
- int header[8];
- int xsize, ysize;
- int datatype;
- int tsID;
- int vlistID;
- int pdis, pcat, pnum;
- srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+ int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
- if ( CDI_Debug )
- Message("streamID = %d varID = %d", streamptr->self, varID);
+ int dimorder[3];
+ vlistInqVarDimorder(vlistId, varId, &dimorder);
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlevs = zaxisInqSize(zaxisID);
+ *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ int ndims = 0;
- cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
+#define addDimension(startIndex, extent) do { \
+ (*start)[ndims] = startIndex; \
+ (*count)[ndims] = extent; \
+ ndims++; \
+ } while(0)
- header[0] = pnum;
- header[2] = streamptr->tsteps[tsID].taxis.vdate;
- header[3] = streamptr->tsteps[tsID].taxis.vtime;
+ if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
+ if ( skipdim == 1 ) addDimension(0, 1);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
- if ( xsize == 0 || ysize == 0 )
+ for ( int id = 0; id < 3; ++id )
{
- xsize = gridInqSize(gridID);
- ysize = 1;
- }
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
- if ( gridInqSize(gridID) != xsize*ysize )
- Error("Internal problem with gridsize!");
-
- header[4] = xsize;
- header[5] = ysize;
- header[6] = 0;
- header[7] = 0;
-
- datatype = vlistInqVarDatatype(vlistID, varID);
-
- srvp->dprec = srvDefDatatype(datatype);
+ size_t size;
+ int curDimId = dimIds[dimorder[id]-1];
+ if ( curDimId == UNDEFID ) continue;
+ switch ( dimorder[id] )
+ {
+ Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+ case 1:
+ case 2:
+ cdf_inq_dimlen(fileId, curDimId, &size);
+ addDimension(0, size);
+ break;
- for ( levID = 0; levID < nlevs; levID++ )
- {
- level = zaxisInqLevel(zaxisID, levID);
+ case 3:
+ addDimension((size_t)levelId, 1);
+ break;
- header[1] = (int) level;
- srvDefHeader(srvp, header);
- srvDefDataDP(srvp, &data[levID*gridsize]);
- srvWrite(fileID, srvp);
+ default:
+ Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
+ }
}
-}
+ if ( skipdim == 2 ) addDimension(0, 1);
-void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
-{
- int fileID;
- int gridID;
- int zaxisID;
- double level;
- int header[8];
- int xsize, ysize;
- int datatype;
- int tsID;
- int vlistID;
- int pdis, pcat, pnum;
- srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+ assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
+ assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- level = zaxisInqLevel(zaxisID, levID);
+#undef addDimension
if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+ for (int idim = 0; idim < ndims; idim++)
+ Message("dim = %d start = %d count = %d", idim, (*start)[idim], (*count)[idim]);
- cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
+ int nvdims;
+ cdf_inq_varndims(fileId, ncvarid, &nvdims);
- header[0] = pnum;
- header[1] = (int) level;
- header[2] = streamptr->tsteps[tsID].taxis.vdate;
- header[3] = streamptr->tsteps[tsID].taxis.vtime;
+ if ( nvdims != ndims )
+ Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
+}
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
- if ( xsize == 0 || ysize == 0 )
- {
- xsize = gridInqSize(gridID);
- ysize = 1;
- }
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
- if ( gridInqSize(gridID) != xsize*ysize )
- Error("Internal problem with gridsize!");
+static
+void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
- header[4] = xsize;
- header[5] = ysize;
- header[6] = 0;
- header[7] = 0;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- datatype = vlistInqVarDatatype(vlistID, varID);
+ int ncvarid = streamptr->vars[varID].ncvarid;
- srvp->dprec = srvDefDatatype(datatype);
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
- srvDefHeader(srvp, header);
- srvDefDataDP(srvp, data);
- srvWrite(fileID, srvp);
+ size_t start[4];
+ size_t count[4];
+ cdfGetSlapDescription(streamptr, varID, &start, &count);
+
+ cdf_get_vara_double(fileID, ncvarid, start, count, data);
+
+ size_t size = (size_t)gridInqSize(gridID)*(size_t)zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationDP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
}
-#endif /* HAVE_LIBSERVICE */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
-#if defined (HAVE_CONFIG_H)
-#endif
+static
+void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-#include <string.h>
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int ncvarid = streamptr->vars[varID].ncvarid;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ size_t start[4];
+ size_t count[4];
+ cdfGetSlapDescription(streamptr, varID, &start, &count);
+ cdf_get_vara_float(fileID, ncvarid, start, count, data);
-static void streamvar_init_recordtable(stream_t *streamptr, int varID, int isub)
-{
- streamptr->vars[varID].recordTable[isub].nlevs = 0;
- streamptr->vars[varID].recordTable[isub].recordID = NULL;
- streamptr->vars[varID].recordTable[isub].lindex = NULL;
+ size_t size = (size_t)gridInqSize(gridID) * (size_t)zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationSP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
}
-static
-void streamvar_init_entry(stream_t *streamptr, int varID)
+void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss)
{
- streamptr->vars[varID].ncvarid = CDI_UNDEFID;
- streamptr->vars[varID].defmiss = 0;
-
- streamptr->vars[varID].subtypeSize = 0;
- streamptr->vars[varID].recordTable = NULL;
-
- streamptr->vars[varID].gridID = CDI_UNDEFID;
- streamptr->vars[varID].zaxisID = CDI_UNDEFID;
- streamptr->vars[varID].tsteptype = CDI_UNDEFID;
- streamptr->vars[varID].subtypeID = CDI_UNDEFID;
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarDP(streamptr, varID, (double*) data, nmiss);
+ else
+ cdfReadVarSP(streamptr, varID, (float*) data, nmiss);
}
static
-int streamvar_new_entry(stream_t *streamptr)
+void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
{
- int varID = 0;
- int streamvarSize;
- svarinfo_t *streamvar;
+ size_t start[4];
+ size_t count[4];
- streamvarSize = streamptr->varsAllocated;
- streamvar = streamptr->vars;
- /*
- Look for a free slot in streamvar.
- (Create the table the first time through).
- */
- if ( ! streamvarSize )
- {
- int i;
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
- streamvarSize = 2;
- streamvar
- = (svarinfo_t *) Malloc((size_t)streamvarSize * sizeof(svarinfo_t));
- if ( streamvar == NULL )
- {
- Message("streamvarSize = %d", streamvarSize);
- SysError("Allocation of svarinfo_t failed");
- }
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- for ( i = 0; i < streamvarSize; i++ )
- streamvar[i].isUsed = FALSE;
+ bool swapxy;
+ cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
+
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ int gridId = vlistInqVarGrid(vlistID, varID);
+ size_t gridsize = (size_t)gridInqSize(gridId);
+ size_t xsize = (size_t)gridInqXsize(gridId);
+ size_t ysize = (size_t)gridInqYsize(gridId);
+
+ if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+ {
+ float *data_fp = (float *) Malloc(gridsize*sizeof(*data_fp));
+ cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
+ for ( size_t i = 0; i < gridsize; i++ )
+ data[i] = (double) data_fp[i];
+ Free(data_fp);
}
- else
+ else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
{
- while ( varID < streamvarSize )
- {
- if ( ! streamvar[varID].isUsed ) break;
- varID++;
- }
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < gridsize; i++ )
+ if ( data[i] < 0 ) data[i] += 256;
+ }
}
- /*
- If the table overflows, double its size.
- */
- if ( varID == streamvarSize )
+ else
{
- int i;
+ cdf_get_vara_double(fileID, ncvarid, start, count, data);
+ }
- streamvarSize = 2*streamvarSize;
- streamvar
- = (svarinfo_t *) Realloc(streamvar,
- (size_t)streamvarSize * sizeof (svarinfo_t));
- if ( streamvar == NULL )
- {
- Message("streamvarSize = %d", streamvarSize);
- SysError("Reallocation of svarinfo_t failed");
- }
- varID = streamvarSize/2;
+ if ( swapxy ) transpose2dArrayDP(ysize, xsize, data);
- for ( i = varID; i < streamvarSize; i++ )
- streamvar[i].isUsed = FALSE;
- }
+ double missval = vlistInqVarMissval(vlistID, varID);
+ const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationDP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
+}
- streamptr->varsAllocated = streamvarSize;
- streamptr->vars = streamvar;
+static
+void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
+{
+ size_t start[4];
+ size_t count[4];
- streamvar_init_entry(streamptr, varID);
+ if ( CDI_Debug )
+ Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
- streamptr->vars[varID].isUsed = TRUE;
- return (varID);
-}
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ bool swapxy;
+ cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
-static void
-allocate_record_table_entry(stream_t *streamptr, int varID, int subID, int nlevs)
-{
- int *level = (int *) Malloc((size_t)nlevs * sizeof (int));
- int *lindex = (int *) Malloc((size_t)nlevs * sizeof (int));
+ int ncvarid = streamptr->vars[varID].ncvarid;
+ int gridId = vlistInqVarGrid(vlistID, varID);
+ size_t gridsize = (size_t)gridInqSize(gridId);
+ size_t xsize = (size_t)gridInqXsize(gridId);
+ size_t ysize = (size_t)gridInqYsize(gridId);
- for (int levID = 0; levID < nlevs; levID++ )
+ if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
{
- level[levID] = CDI_UNDEFID;
- lindex[levID] = levID;
+ double *data_dp = (double *) Malloc(gridsize*sizeof(*data_dp));
+ cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
+ for ( size_t i = 0; i < gridsize; i++ )
+ data[i] = (float) data_dp[i];
+ Free(data_dp);
+ }
+ else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
+ {
+ nc_type xtype;
+ cdf_inq_vartype(fileID, ncvarid, &xtype);
+ if ( xtype == NC_BYTE )
+ {
+ for ( size_t i = 0; i < gridsize; i++ )
+ if ( data[i] < 0 ) data[i] += 256;
+ }
+ }
+ else
+ {
+ cdf_get_vara_float(fileID, ncvarid, start, count, data);
}
- streamptr->vars[varID].recordTable[subID].nlevs = nlevs;
- streamptr->vars[varID].recordTable[subID].recordID = level;
- streamptr->vars[varID].recordTable[subID].lindex = lindex;
+ if ( swapxy ) transpose2dArraySP(ysize, xsize, data);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+ bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
+ double validRange[2];
+ if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
+ validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
+ double addoffset = vlistInqVarAddoffset(vlistID, varID);
+ double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+ size_t nmiss_ = cdfDoInputDataTransformationSP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
+ assert(nmiss_ <= INT_MAX);
+ *nmiss = (int)nmiss_;
}
-int stream_new_var(stream_t *streamptr, int gridID, int zaxisID, int tilesetID)
+void cdf_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss)
{
- if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
-
- int varID = streamvar_new_entry(streamptr);
- int nlevs = zaxisInqSize(zaxisID);
-
- streamptr->nvars++;
-
- streamptr->vars[varID].gridID = gridID;
- streamptr->vars[varID].zaxisID = zaxisID;
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarSliceDP(streamptr, varID, levelID, (double*) data, nmiss);
+ else
+ cdfReadVarSliceSP(streamptr, varID, levelID, (float*) data, nmiss);
+}
- int nsub = 1;
- if (tilesetID != CDI_UNDEFID)
- nsub = subtypeInqSize(tilesetID); /* e.g. no of tiles */
- if ( CDI_Debug )
- Message("varID %d: create %d tiles with %d level(s), zaxisID=%d", varID, nsub, nlevs,zaxisID);
- streamptr->vars[varID].recordTable = (sleveltable_t *) Malloc((size_t)nsub * sizeof (sleveltable_t));
- if( streamptr->vars[varID].recordTable == NULL )
- SysError("Allocation of leveltable failed!");
- streamptr->vars[varID].subtypeSize = nsub;
- for (int isub=0; isub<nsub; isub++) {
- streamvar_init_recordtable(streamptr, varID, isub);
- allocate_record_table_entry(streamptr, varID, isub, nlevs);
- if ( CDI_Debug )
- Message("streamptr->vars[varID].recordTable[isub].recordID[0]=%d",
- streamptr->vars[varID].recordTable[isub].recordID[0]);
- }
+void cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
- streamptr->vars[varID].subtypeID = tilesetID;
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ int levelID = streamptr->tsteps[tsID].records[recID].levelID;
- return (varID);
+ if ( memtype == MEMTYPE_DOUBLE )
+ cdfReadVarSliceDP(streamptr, varID, levelID, (double*) data, nmiss);
+ else
+ cdfReadVarSliceSP(streamptr, varID, levelID, (float*) data, nmiss);
}
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
+
+#endif
/* Subroutines and data structures for storing "subtypes". */
/* */
/* A subtype is, for example, a list of TILES. This can be interpreted */
@@ -55936,7 +56922,7 @@ enum {
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR ATTRIBUTE LISTS */
+/* SUBROUTINES FOR ATTRIBUTE LISTS */
/* ------------------------------------------------------------------- */
@@ -56068,7 +57054,7 @@ static void subtypeAttsDuplicate(struct subtype_attr_t *a1, struct subtype_entry
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR LIST OF ENTRIES */
+/* SUBROUTINES FOR LIST OF ENTRIES */
/* ------------------------------------------------------------------- */
@@ -56192,7 +57178,7 @@ static void subtypeEntryDuplicate(struct subtype_entry_t *a1, subtype_t* dst)
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR THE SUBTYPE ITSELF */
+/* SUBROUTINES FOR THE SUBTYPE ITSELF */
/* ------------------------------------------------------------------- */
/* Print-out subtype data structure together with its attributes. */
@@ -56403,7 +57389,7 @@ void subtypeDefEntryDataP(struct subtype_entry_t *subtype_entry_ptr, int key, in
/* ------------------------------------------------------------------- */
-/* IMPLEMENTATIONS FOR KEY-VALUE-PAIR QUERIES */
+/* IMPLEMENTATIONS FOR KEY-VALUE-PAIR QUERIES */
/* ------------------------------------------------------------------- */
@@ -56452,7 +57438,7 @@ subtype_query_t matchAND(subtype_query_t q1, subtype_query_t q2)
/* ------------------------------------------------------------------- */
-/* SPECIFIC IMPLEMENTATIONS FOR TILE SETS */
+/* SPECIFIC IMPLEMENTATIONS FOR TILE SETS */
/* ------------------------------------------------------------------- */
@@ -56464,39 +57450,39 @@ void tilesetInsertP(subtype_t *s1, subtype_t *s2)
{
if (s1 == NULL) Error("Internal error!");
if (s2 == NULL) Error("Internal error!");
- struct subtype_entry_t
+ struct subtype_entry_t
*entry1 = s1->entries,
*entry2 = s2->entries;
struct subtype_attr_t *att_ptr2;
/* test all entries of set 2 against set 1, to check if entry
already exists: */
- if (subtypeAttsCompare(s1->globals.atts, s2->globals.atts) != differ)
+ if (subtypeAttsCompare(s1->globals.atts, s2->globals.atts) != differ)
{
while (entry1 != NULL) {
- int found = 1;
- entry2 = s2->entries;
- while (entry2 != NULL) {
- found &= (subtypeAttsCompare(entry1->atts, entry2->atts) != differ);
- entry2 = entry2->next;
- }
- if (found)
- {
- return;
- }
- entry1 = entry1->next;
+ int found = 1;
+ entry2 = s2->entries;
+ while (entry2 != NULL) {
+ found &= (subtypeAttsCompare(entry1->atts, entry2->atts) != differ);
+ entry2 = entry2->next;
+ }
+ if (found)
+ {
+ return;
+ }
+ entry1 = entry1->next;
}
-
+
entry2 = s2->entries;
while (entry2 != NULL) {
- entry1 = subtypeEntryInsert(s1);
-
- att_ptr2 = entry2->atts;
- while (att_ptr2 != NULL) {
- (void) subtypeAttrInsert(entry1, att_ptr2->key, att_ptr2->val);
- att_ptr2 = att_ptr2->next;
- }
- entry2 = entry2->next;
+ entry1 = subtypeEntryInsert(s1);
+
+ att_ptr2 = entry2->atts;
+ while (att_ptr2 != NULL) {
+ (void) subtypeAttrInsert(entry1, att_ptr2->key, att_ptr2->val);
+ att_ptr2 = att_ptr2->next;
+ }
+ entry2 = entry2->next;
}
}
else
@@ -56512,7 +57498,7 @@ void tilesetInsertP(subtype_t *s1, subtype_t *s2)
/* ------------------------------------------------------------------- */
-/* IMPLEMENTATIONS FOR ROUTINES VISIBLE THROUGH CDI.H */
+/* IMPLEMENTATIONS FOR ROUTINES VISIBLE THROUGH CDI.H */
/* ------------------------------------------------------------------- */
@@ -56607,22 +57593,22 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion)
int match = 1;
/* test if this entry matches ALL criteria. */
for (int j=0; (j<criterion.nAND) && (match); j++)
- {
- if (CDI_Debug) Message("check criterion %d : %d --?-- %d", j,
- criterion.key_value_pairs[0][j], criterion.key_value_pairs[1][j]);
- struct subtype_attr_t* att_ptr =
- subtypeAttrFind(entry->atts, criterion.key_value_pairs[0][j]);
- if (att_ptr == NULL)
- {
- match = 0;
- if (CDI_Debug) Message("did not find %d", criterion.key_value_pairs[0][j]);
- }
- else
- {
- if (CDI_Debug) Message("found %d", criterion.key_value_pairs[0][j]);
- match &= (att_ptr->val == criterion.key_value_pairs[1][j]);
- }
- }
+ {
+ if (CDI_Debug) Message("check criterion %d : %d --?-- %d", j,
+ criterion.key_value_pairs[0][j], criterion.key_value_pairs[1][j]);
+ struct subtype_attr_t* att_ptr =
+ subtypeAttrFind(entry->atts, criterion.key_value_pairs[0][j]);
+ if (att_ptr == NULL)
+ {
+ match = 0;
+ if (CDI_Debug) Message("did not find %d", criterion.key_value_pairs[0][j]);
+ }
+ else
+ {
+ if (CDI_Debug) Message("found %d", criterion.key_value_pairs[0][j]);
+ match &= (att_ptr->val == criterion.key_value_pairs[1][j]);
+ }
+ }
if (match) return entry->self;
}
entry = entry->next;
@@ -56634,10 +57620,50 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion)
int subtypeInqTile(int subtypeID, int tileindex, int attribute)
{
return subtypeInqSubEntry(subtypeID,
- matchAND(keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], tileindex),
- keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], attribute)));
+ matchAND(keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], tileindex),
+ keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], attribute)));
}
+int subtypeInqAttribute(int subtypeID, int index, const char* key, int* outValue)
+{
+ //Validate input params.
+ if(subtypeID == CDI_UNDEFID) xabort("CDI_UNDEFID was passed to %s() as a subtypeID. Please check the origin of that ID.", __func__);
+ subtype_t *subtype_ptr = (subtype_t *)reshGetVal(subtypeID, &subtypeOps);
+ if(!subtype_ptr) xabort("Internal error: subtypeID %d resolved to NULL.", subtypeID);
+
+ if((unsigned)index >= (unsigned)subtype_ptr->nentries)
+ {
+ xabort("index argument of %s() is out of range. Expected 0 <= index < %d, but got index = %d.", __func__, subtype_ptr->nentries, index);
+ }
+
+#ifndef __cplusplus
+ if(!outValue) outValue = &(int){0};
+#else
+ int dummy = 0;
+ if(!outValue) outValue = &dummy;
+#endif
+
+ if(!key) return CDI_EINVAL;
+ int iKey = attribute_to_index(key);
+ if(iKey < 0) return CDI_EINVAL;
+
+ //Find the entry.
+ struct subtype_entry_t* entry = subtype_ptr->entries;
+ for(; index--; entry = entry->next) if(!entry) xabort("internal error: preliminary end of subtype entry list");
+
+ //Find the attribute.
+ for(struct subtype_attr_t* attribute = entry->atts; attribute; attribute = attribute->next)
+ {
+ if(attribute->key == iKey)
+ {
+ *outValue = attribute->val;
+ return CDI_NOERR;
+ }
+ }
+
+ //Failed to find the attribute if this point is reached.
+ return CDI_EINVAL;
+}
/* Construct a new subtype for a tile set. If a corresponding subtype
* already exists, then we return this subtype ID instead.
@@ -56694,7 +57720,7 @@ int vlistInsertTrivialTileSubtype(int vlistID)
/* ------------------------------------------------------------------- */
-/* NOT YET IMPLEMENTED */
+/* NOT YET IMPLEMENTED */
/* ------------------------------------------------------------------- */
static int subtypeGetPackSize( void * subtype_ptr, void *context)
@@ -56791,6 +57817,7 @@ int tableDef(int modelID, int tablegribID, const char *tablename);
* require-trailing-newline: t
* End:
*/
+/* Automatically generated, do not edit! */
#ifndef _TABLE_H
#define _TABLE_H
@@ -57345,177 +58372,177 @@ static const PAR mpiom1[] = {
};
static const PAR ecmwf[] = {
- { 1, 0, "STRF", "Stream function", "m**2 s**-1" },
- { 2, 0, "VPOT", "Velocity potential", "m**2 s**-1" },
- { 3, 0, "PT", "Potential temperature", "K" },
- { 4, 0, "EQPT", "Equivalent potential temperature", "K" },
- { 5, 0, "SEPT", "Saturated equivalent potential temperature", "K" },
- { 11, 0, "UDVW", "U component of divergent wind", "m s**-1" },
- { 12, 0, "VDVW", "V component of divergent wind", "m s**-1" },
- { 13, 0, "URTW", "U component of rotational wind", "m s**-1" },
- { 14, 0, "VRTW", "V component of rotational wind", "m s**-1" },
- { 21, 0, "UCTP", "Unbalanced component of temperature", "K" },
- { 22, 0, "UCLN", "Unbalanced component of logarithm of surface pressure", NULL },
- { 23, 0, "UCDV", "Unbalanced component of divergence", "s**-1" },
- { 26, 0, "CL", "Lake cover", NULL },
- { 27, 0, "CVL", "Low vegetation cover", NULL },
- { 28, 0, "CVH", "High vegetation cover", NULL },
- { 29, 0, "TVL", "Type of low vegetation", NULL },
- { 30, 0, "TVH", "Type of high vegetation", NULL },
- { 31, 0, "CI", "Sea-ice cover", NULL },
- { 32, 0, "ASN", "Snow albedo", NULL },
- { 33, 0, "RSN", "Snow density kg", "m**-3" },
- { 34, 0, "SSTK", "Sea surface temperature", "K" },
- { 35, 0, "ISTL1", "Ice surface temperature layer 1", "K" },
- { 36, 0, "ISTL2", "Ice surface temperature layer 2", "K" },
- { 37, 0, "ISTL3", "Ice surface temperature layer 3", "K" },
- { 38, 0, "ISTL4", "Ice surface temperature layer 4", "K" },
- { 39, 0, "SWVL1", "Volumetric soil water layer 1", "m**3 m**-3" },
- { 40, 0, "SWVL2", "Volumetric soil water layer 2", "m**3 m**-3" },
- { 41, 0, "SWVL3", "Volumetric soil water layer 3", "m**3 m**-3" },
- { 42, 0, "SWVL4", "Volumetric soil water layer 4", "m**3 m**-3" },
- { 43, 0, "SLT", "Soil type", NULL },
- { 44, 0, "ES", "Snow evaporation m of water", NULL },
- { 45, 0, "SMLT", "Snowmelt m of water", NULL },
- { 46, 0, "SDUR", "Solar duration", "s" },
- { 47, 0, "DSRP", "Direct solar radiation", "w m**-2" },
- { 48, 0, "MAGSS", "Magnitude of surface stress", "N m**-2 s" },
- { 49, 0, "WG10", "Wind gust at 10 metres", "m s**-1" },
- { 50, 0, "LSPF", "Large-scale precipitation fraction", "s" },
- { 51, 0, "MX2T24", "Maximum 2 metre temperature", "K" },
- { 52, 0, "MN2T24", "Minimum 2 metre temperature", "K" },
- { 53, 0, "MONT", "Montgomery potential", "m**2 s**-2" },
- { 54, 0, "PRES", "Pressure", "Pa" },
- { 55, 0, "MN2T24", "Mean 2 metre temperature past 24 hours", "K" },
- { 56, 0, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours", "K" },
- { 60, 0, "PV", "Potential vorticity", "K m**2 kg**-1 s**-1" },
- { 127, 0, "AT", "Atmospheric tide", NULL },
- { 128, 0, "BV", "Budget values", NULL },
- { 129, 0, "Z", "Geopotential", "m**2 s**-2" },
- { 130, 0, "T", "Temperature", "K" },
- { 131, 0, "U", "U velocity", "m s**-1" },
- { 132, 0, "V", "V velocity", "m s**-1" },
- { 133, 0, "Q", "Specific humidity", "kg kg**-1" },
- { 134, 0, "SP", "Surface pressure", "Pa" },
- { 135, 0, "W", "Vertical velocity", "Pa s**-1" },
- { 136, 0, "TCW", "Total column water", "kg m**-2" },
- { 137, 0, "TCWV", "Total column water vapour", "kg m**-2" },
- { 138, 0, "VO", "Vorticity (relative)", "s**-1" },
- { 139, 0, "STL1", "Soil temperature level 1", "K" },
- { 140, 0, "SWL1", "Soil wetness level 1 m of water", NULL },
- { 141, 0, "SD", "Snow depth 1 m of water equivalent", NULL },
- { 142, 0, "LSP", "Stratiform precipitation (Large scale precipitation)", "m" },
- { 143, 0, "CP", "Convective precipitation", "m" },
- { 144, 0, "SF", "Snowfall (convective + stratiform)", "m" },
- { 145, 0, "BLD", "Boundary layer dissipation", "W m**-2 s" },
- { 146, 0, "SSHF", "Surface sensible heat flux", "W m**-2 s" },
- { 147, 0, "SLHF", "Surface latent heat flux", "W m**-2 s" },
- { 148, 0, "CHNK", "Charnock", NULL },
- { 149, 0, "SNR", "Surface net radiation", "W m**-2 s" },
- { 150, 0, "TNR", "Top net radiation", NULL },
- { 151, 0, "MSL", "Mean sea-level pressure", "Pa" },
- { 152, 0, "LNSP", "Logarithm of surface pressure", NULL },
- { 153, 0, "SWHR", "Short-wave heating rate", "K" },
- { 154, 0, "LWHR", "Long-wave heating rate", "K" },
- { 155, 0, "D", "Divergence", "s**-1" },
- { 156, 0, "GH", "Height m Geopotential height", NULL },
- { 157, 0, "R", "Relative humidity", "%" },
- { 158, 0, "TSP", "Tendency of surface pressure", "Pa s**-1" },
- { 159, 0, "BLH", "Boundary layer height", "m" },
- { 160, 0, "SDOR", "Standard deviation of orography", NULL },
- { 161, 0, "ISOR", "Anisotropy of sub-gridscale orography", NULL },
- { 162, 0, "ANOR", "Angle of sub-gridscale orography", "rad" },
- { 163, 0, "SLOR", "Slope of sub-gridscale orography", NULL },
- { 164, 0, "TCC", "Total cloud cover", NULL },
- { 165, 0, "U10M", "10 metre U wind component", "m s**-1" },
- { 166, 0, "V10M", "10 metre V wind component", "m s**-1" },
- { 167, 0, "T2M", "2 metre temperature", "K" },
- { 168, 0, "D2M", "2 metre dewpoint temperature", "K" },
- { 169, 0, "SSRD", "Surface solar radiation downwards", "W m**-2 s" },
- { 170, 0, "STL2", "Soil temperature level 2", "K" },
- { 171, 0, "SWL2", "Soil wetness level 2", "m of water" },
- { 172, 0, "LSM", "Land/sea mask", NULL },
- { 173, 0, "SR", "Surface roughness", "m" },
- { 174, 0, "AL", "Albedo", NULL },
- { 175, 0, "STRD", "Surface thermal radiation downwards", "W m**-2 s" },
- { 176, 0, "SSR", "Surface solar radiation", "W m**-2 s" },
- { 177, 0, "STR", "Surface thermal radiation", "W m**-2 s" },
- { 178, 0, "TSR", "Top solar radiation", "W m**-2 s" },
- { 179, 0, "TTR", "Top thermal radiation", "W m**-2 s" },
- { 180, 0, "EWSS", "East/West surface stress", "N m**-2 s" },
- { 181, 0, "NSSS", "North/South surface stress", "N m**-2 s" },
- { 182, 0, "E", "Evaporation", "m of water" },
- { 183, 0, "STL3", "Soil temperature level 3", "K" },
- { 184, 0, "SWL3", "Soil wetness level 3", "m of water" },
- { 185, 0, "CCC", "Convective cloud cover", NULL },
- { 186, 0, "LCC", "Low cloud cover", NULL },
- { 187, 0, "MCC", "Medium cloud cover", NULL },
- { 188, 0, "HCC", "High cloud cover", NULL },
- { 189, 0, "SUND", "Sunshine duration", "s" },
- { 190, 0, "EWOV", "EW component of subgrid orographic variance", "m**2" },
- { 191, 0, "NSOV", "NS component of subgrid orographic variance", "m**2" },
- { 192, 0, "NWOV", "NWSE component of subgrid orographic variance", "m**2" },
- { 193, 0, "NEOV", "NESW component of subgrid orographic variance", "m**2" },
- { 194, 0, "BTMP", "Brightness temperature", "K" },
- { 195, 0, "LGWS", "Lat. component of gravity wave stress", "N m**-2 s" },
- { 196, 0, "MGWS", "Meridional component of gravity wave stress", "N m**-2 s" },
- { 197, 0, "GWD", "Gravity wave dissipation", "W m**-2 s" },
- { 198, 0, "SRC", "Skin reservoir content", "m of water" },
- { 199, 0, "VEG", "Vegetation fraction", NULL },
- { 200, 0, "VSO", "Variance of sub-gridscale orography", "m**2" },
- { 201, 0, "MX2T", "Maximum 2 metre temperature since previous post-processing", "K" },
- { 202, 0, "MN2T", "Minimum 2 metre temperature since previous post-processing", "K" },
- { 203, 0, "O3", "Ozone mass mixing ratio", "kg kg**-1" },
- { 204, 0, "PAW", "Precipiation analysis weights", NULL },
- { 205, 0, "RO", "Runoff", "m" },
- { 206, 0, "TCO3", "Total column ozone", "kg m**-2" },
- { 207, 0, "WS10", "10 meter windspeed", "m s**-1" },
- { 208, 0, "TSRC", "Top net solar radiation, clear sky", "W m**-2" },
- { 209, 0, "TTRC", "Top net thermal radiation, clear sky", "W m**-2" },
- { 210, 0, "SSRC", "Surface net solar radiation, clear sky", "W m**-2" },
- { 211, 0, "STRC", "Surface net thermal radiation, clear sky", "W m**-2" },
- { 212, 0, "SI", "Solar insolation", "W m**-2" },
- { 214, 0, "DHR", "Diabatic heating by radiation", "K" },
- { 215, 0, "DHVD", "Diabatic heating by vertical diffusion", "K" },
- { 216, 0, "DHCC", "Diabatic heating by cumulus convection", "K" },
- { 217, 0, "DHLC", "Diabatic heating large-scale condensation", "K" },
- { 218, 0, "VDZW", "Vertical diffusion of zonal wind", "m s**-1" },
- { 219, 0, "VDMW", "Vertical diffusion of meridional wind", "m s**-1" },
- { 220, 0, "EWGD", "EW gravity wave drag tendency", "m s**-1" },
- { 221, 0, "NSGD", "NS gravity wave drag tendency", "m s**-1" },
- { 222, 0, "CTZW", "Convective tendency of zonal wind", "m s**-1" },
- { 223, 0, "CTMW", "Convective tendency of meridional wind", "m s**-1" },
- { 224, 0, "VDH", "Vertical diffusion of humidity", "kg kg**-1" },
- { 225, 0, "HTCC", "Humidity tendency by cumulus convection", "kg kg**-1" },
- { 226, 0, "HTLC", "Humidity tendency large-scale condensation", "kg kg**-1" },
- { 227, 0, "CRNH", "Change from removing negative humidity", "kg kg**-1" },
- { 228, 0, "TP", "Total precipitation", "m" },
- { 229, 0, "IEWS", "Instantaneous X surface stress", "N m**-2" },
- { 230, 0, "INSS", "Instantaneous Y surface stress", "N m**-2" },
- { 231, 0, "ISHF", "Instantaneous surface heat flux", "W m**-2" },
- { 232, 0, "IE", "Instantaneous moisture flux", "kg m**-2 s" },
- { 233, 0, "ASQ", "Apparent surface humidity", "kg kg**-1" },
- { 234, 0, "LSRH", "Logarithm of surface roughness length for heat", NULL },
- { 235, 0, "SKT", "Skin temperature", "K" },
- { 236, 0, "STL4", "Soil temperature level 4", "K" },
- { 237, 0, "SWL4", "Soil wetness level 4", "m" },
- { 238, 0, "TSN", "Temperature of snow layer", "K" },
- { 239, 0, "CSF", "Convective snowfall", "m of water equivalent" },
- { 240, 0, "LSF", "Large-scale snowfall", "m of water equivalent" },
- { 241, 0, "ACF", "Accumulated cloud fraction tendency", NULL },
- { 242, 0, "ALW", "Accumulated liquid water tendency", NULL },
- { 243, 0, "FAL", "Forecast albedo", NULL },
- { 244, 0, "FSR", "Forecast surface roughness", "m" },
- { 245, 0, "FLSR", "Forecast log of surface roughness for heat", NULL },
- { 246, 0, "CLWC", "Cloud liquid water content", "kg kg**-1" },
- { 247, 0, "CIWC", "Cloud ice water content", "kg kg**-1" },
- { 248, 0, "CC", "Cloud cover", NULL },
- { 249, 0, "AIW", "Accumulated ice water tendency", NULL },
- { 250, 0, "ICE", "Ice age", NULL },
- { 251, 0, "ATTE", "Adiabatic tendency of temperature", "K" },
- { 252, 0, "ATHE", "Adiabatic tendency of humidity", "kg kg**-1" },
- { 253, 0, "ATZE", "Adiabatic tendency of zonal wind", "m s**-1" },
- { 254, 0, "ATMW", "Adiabatic tendency of meridional wind", "m s**-1" },
+ { 1, 0, "STRF", "Stream function", "m**2 s**-1" },
+ { 2, 0, "VPOT", "Velocity potential", "m**2 s**-1" },
+ { 3, 0, "PT", "Potential temperature", "K" },
+ { 4, 0, "EQPT", "Equivalent potential temperature", "K" },
+ { 5, 0, "SEPT", "Saturated equivalent potential temperature", "K" },
+ { 11, 0, "UDVW", "U component of divergent wind", "m s**-1" },
+ { 12, 0, "VDVW", "V component of divergent wind", "m s**-1" },
+ { 13, 0, "URTW", "U component of rotational wind", "m s**-1" },
+ { 14, 0, "VRTW", "V component of rotational wind", "m s**-1" },
+ { 21, 0, "UCTP", "Unbalanced component of temperature", "K" },
+ { 22, 0, "UCLN", "Unbalanced component of logarithm of surface pressure", NULL },
+ { 23, 0, "UCDV", "Unbalanced component of divergence", "s**-1" },
+ { 26, 0, "CL", "Lake cover", NULL },
+ { 27, 0, "CVL", "Low vegetation cover", NULL },
+ { 28, 0, "CVH", "High vegetation cover", NULL },
+ { 29, 0, "TVL", "Type of low vegetation", NULL },
+ { 30, 0, "TVH", "Type of high vegetation", NULL },
+ { 31, 0, "CI", "Sea-ice cover", NULL },
+ { 32, 0, "ASN", "Snow albedo", NULL },
+ { 33, 0, "RSN", "Snow density kg", "m**-3" },
+ { 34, 0, "SSTK", "Sea surface temperature", "K" },
+ { 35, 0, "ISTL1", "Ice surface temperature layer 1", "K" },
+ { 36, 0, "ISTL2", "Ice surface temperature layer 2", "K" },
+ { 37, 0, "ISTL3", "Ice surface temperature layer 3", "K" },
+ { 38, 0, "ISTL4", "Ice surface temperature layer 4", "K" },
+ { 39, 0, "SWVL1", "Volumetric soil water layer 1", "m**3 m**-3" },
+ { 40, 0, "SWVL2", "Volumetric soil water layer 2", "m**3 m**-3" },
+ { 41, 0, "SWVL3", "Volumetric soil water layer 3", "m**3 m**-3" },
+ { 42, 0, "SWVL4", "Volumetric soil water layer 4", "m**3 m**-3" },
+ { 43, 0, "SLT", "Soil type", NULL },
+ { 44, 0, "ES", "Snow evaporation m of water", NULL },
+ { 45, 0, "SMLT", "Snowmelt m of water", NULL },
+ { 46, 0, "SDUR", "Solar duration", "s" },
+ { 47, 0, "DSRP", "Direct solar radiation", "w m**-2" },
+ { 48, 0, "MAGSS", "Magnitude of surface stress", "N m**-2 s" },
+ { 49, 0, "WG10", "Wind gust at 10 metres", "m s**-1" },
+ { 50, 0, "LSPF", "Large-scale precipitation fraction", "s" },
+ { 51, 0, "MX2T24", "Maximum 2 metre temperature", "K" },
+ { 52, 0, "MN2T24", "Minimum 2 metre temperature", "K" },
+ { 53, 0, "MONT", "Montgomery potential", "m**2 s**-2" },
+ { 54, 0, "PRES", "Pressure", "Pa" },
+ { 55, 0, "MEAN2T24", "Mean 2 metre temperature past 24 hours", "K" },
+ { 56, 0, "MEAN2D24", "Mean 2 metre dewpoint temperature past 24 hours", "K" },
+ { 60, 0, "PV", "Potential vorticity", "K m**2 kg**-1 s**-1" },
+ { 127, 0, "AT", "Atmospheric tide", NULL },
+ { 128, 0, "BV", "Budget values", NULL },
+ { 129, 0, "Z", "Geopotential", "m**2 s**-2" },
+ { 130, 0, "T", "Temperature", "K" },
+ { 131, 0, "U", "U velocity", "m s**-1" },
+ { 132, 0, "V", "V velocity", "m s**-1" },
+ { 133, 0, "Q", "Specific humidity", "kg kg**-1" },
+ { 134, 0, "SP", "Surface pressure", "Pa" },
+ { 135, 0, "W", "Vertical velocity", "Pa s**-1" },
+ { 136, 0, "TCW", "Total column water", "kg m**-2" },
+ { 137, 0, "TCWV", "Total column water vapour", "kg m**-2" },
+ { 138, 0, "VO", "Vorticity (relative)", "s**-1" },
+ { 139, 0, "STL1", "Soil temperature level 1", "K" },
+ { 140, 0, "SWL1", "Soil wetness level 1 m of water", NULL },
+ { 141, 0, "SD", "Snow depth 1 m of water equivalent", NULL },
+ { 142, 0, "LSP", "Stratiform precipitation (Large scale precipitation)", "m" },
+ { 143, 0, "CP", "Convective precipitation", "m" },
+ { 144, 0, "SF", "Snowfall (convective + stratiform)", "m" },
+ { 145, 0, "BLD", "Boundary layer dissipation", "W m**-2 s" },
+ { 146, 0, "SSHF", "Surface sensible heat flux", "W m**-2 s" },
+ { 147, 0, "SLHF", "Surface latent heat flux", "W m**-2 s" },
+ { 148, 0, "CHNK", "Charnock", NULL },
+ { 149, 0, "SNR", "Surface net radiation", "W m**-2 s" },
+ { 150, 0, "TNR", "Top net radiation", NULL },
+ { 151, 0, "MSL", "Mean sea-level pressure", "Pa" },
+ { 152, 0, "LNSP", "Logarithm of surface pressure", NULL },
+ { 153, 0, "SWHR", "Short-wave heating rate", "K" },
+ { 154, 0, "LWHR", "Long-wave heating rate", "K" },
+ { 155, 0, "D", "Divergence", "s**-1" },
+ { 156, 0, "GH", "Height m Geopotential height", NULL },
+ { 157, 0, "R", "Relative humidity", "%" },
+ { 158, 0, "TSP", "Tendency of surface pressure", "Pa s**-1" },
+ { 159, 0, "BLH", "Boundary layer height", "m" },
+ { 160, 0, "SDOR", "Standard deviation of orography", NULL },
+ { 161, 0, "ISOR", "Anisotropy of sub-gridscale orography", NULL },
+ { 162, 0, "ANOR", "Angle of sub-gridscale orography", "rad" },
+ { 163, 0, "SLOR", "Slope of sub-gridscale orography", NULL },
+ { 164, 0, "TCC", "Total cloud cover", NULL },
+ { 165, 0, "U10M", "10 metre U wind component", "m s**-1" },
+ { 166, 0, "V10M", "10 metre V wind component", "m s**-1" },
+ { 167, 0, "T2M", "2 metre temperature", "K" },
+ { 168, 0, "D2M", "2 metre dewpoint temperature", "K" },
+ { 169, 0, "SSRD", "Surface solar radiation downwards", "W m**-2 s" },
+ { 170, 0, "STL2", "Soil temperature level 2", "K" },
+ { 171, 0, "SWL2", "Soil wetness level 2", "m of water" },
+ { 172, 0, "LSM", "Land/sea mask", NULL },
+ { 173, 0, "SR", "Surface roughness", "m" },
+ { 174, 0, "AL", "Albedo", NULL },
+ { 175, 0, "STRD", "Surface thermal radiation downwards", "W m**-2 s" },
+ { 176, 0, "SSR", "Surface solar radiation", "W m**-2 s" },
+ { 177, 0, "STR", "Surface thermal radiation", "W m**-2 s" },
+ { 178, 0, "TSR", "Top solar radiation", "W m**-2 s" },
+ { 179, 0, "TTR", "Top thermal radiation", "W m**-2 s" },
+ { 180, 0, "EWSS", "East/West surface stress", "N m**-2 s" },
+ { 181, 0, "NSSS", "North/South surface stress", "N m**-2 s" },
+ { 182, 0, "E", "Evaporation", "m of water" },
+ { 183, 0, "STL3", "Soil temperature level 3", "K" },
+ { 184, 0, "SWL3", "Soil wetness level 3", "m of water" },
+ { 185, 0, "CCC", "Convective cloud cover", NULL },
+ { 186, 0, "LCC", "Low cloud cover", NULL },
+ { 187, 0, "MCC", "Medium cloud cover", NULL },
+ { 188, 0, "HCC", "High cloud cover", NULL },
+ { 189, 0, "SUND", "Sunshine duration", "s" },
+ { 190, 0, "EWOV", "EW component of subgrid orographic variance", "m**2" },
+ { 191, 0, "NSOV", "NS component of subgrid orographic variance", "m**2" },
+ { 192, 0, "NWOV", "NWSE component of subgrid orographic variance", "m**2" },
+ { 193, 0, "NEOV", "NESW component of subgrid orographic variance", "m**2" },
+ { 194, 0, "BTMP", "Brightness temperature", "K" },
+ { 195, 0, "LGWS", "Lat. component of gravity wave stress", "N m**-2 s" },
+ { 196, 0, "MGWS", "Meridional component of gravity wave stress", "N m**-2 s" },
+ { 197, 0, "GWD", "Gravity wave dissipation", "W m**-2 s" },
+ { 198, 0, "SRC", "Skin reservoir content", "m of water" },
+ { 199, 0, "VEG", "Vegetation fraction", NULL },
+ { 200, 0, "VSO", "Variance of sub-gridscale orography", "m**2" },
+ { 201, 0, "MX2T", "Maximum 2 metre temperature since previous post-processing", "K" },
+ { 202, 0, "MN2T", "Minimum 2 metre temperature since previous post-processing", "K" },
+ { 203, 0, "O3", "Ozone mass mixing ratio", "kg kg**-1" },
+ { 204, 0, "PAW", "Precipiation analysis weights", NULL },
+ { 205, 0, "RO", "Runoff", "m" },
+ { 206, 0, "TCO3", "Total column ozone", "kg m**-2" },
+ { 207, 0, "WS10", "10 meter windspeed", "m s**-1" },
+ { 208, 0, "TSRC", "Top net solar radiation, clear sky", "W m**-2" },
+ { 209, 0, "TTRC", "Top net thermal radiation, clear sky", "W m**-2" },
+ { 210, 0, "SSRC", "Surface net solar radiation, clear sky", "W m**-2" },
+ { 211, 0, "STRC", "Surface net thermal radiation, clear sky", "W m**-2" },
+ { 212, 0, "SI", "Solar insolation", "W m**-2" },
+ { 214, 0, "DHR", "Diabatic heating by radiation", "K" },
+ { 215, 0, "DHVD", "Diabatic heating by vertical diffusion", "K" },
+ { 216, 0, "DHCC", "Diabatic heating by cumulus convection", "K" },
+ { 217, 0, "DHLC", "Diabatic heating large-scale condensation", "K" },
+ { 218, 0, "VDZW", "Vertical diffusion of zonal wind", "m s**-1" },
+ { 219, 0, "VDMW", "Vertical diffusion of meridional wind", "m s**-1" },
+ { 220, 0, "EWGD", "EW gravity wave drag tendency", "m s**-1" },
+ { 221, 0, "NSGD", "NS gravity wave drag tendency", "m s**-1" },
+ { 222, 0, "CTZW", "Convective tendency of zonal wind", "m s**-1" },
+ { 223, 0, "CTMW", "Convective tendency of meridional wind", "m s**-1" },
+ { 224, 0, "VDH", "Vertical diffusion of humidity", "kg kg**-1" },
+ { 225, 0, "HTCC", "Humidity tendency by cumulus convection", "kg kg**-1" },
+ { 226, 0, "HTLC", "Humidity tendency large-scale condensation", "kg kg**-1" },
+ { 227, 0, "CRNH", "Change from removing negative humidity", "kg kg**-1" },
+ { 228, 0, "TP", "Total precipitation", "m" },
+ { 229, 0, "IEWS", "Instantaneous X surface stress", "N m**-2" },
+ { 230, 0, "INSS", "Instantaneous Y surface stress", "N m**-2" },
+ { 231, 0, "ISHF", "Instantaneous surface heat flux", "W m**-2" },
+ { 232, 0, "IE", "Instantaneous moisture flux", "kg m**-2 s" },
+ { 233, 0, "ASQ", "Apparent surface humidity", "kg kg**-1" },
+ { 234, 0, "LSRH", "Logarithm of surface roughness length for heat", NULL },
+ { 235, 0, "SKT", "Skin temperature", "K" },
+ { 236, 0, "STL4", "Soil temperature level 4", "K" },
+ { 237, 0, "SWL4", "Soil wetness level 4", "m" },
+ { 238, 0, "TSN", "Temperature of snow layer", "K" },
+ { 239, 0, "CSF", "Convective snowfall", "m of water equivalent" },
+ { 240, 0, "LSF", "Large-scale snowfall", "m of water equivalent" },
+ { 241, 0, "ACF", "Accumulated cloud fraction tendency", NULL },
+ { 242, 0, "ALW", "Accumulated liquid water tendency", NULL },
+ { 243, 0, "FAL", "Forecast albedo", NULL },
+ { 244, 0, "FSR", "Forecast surface roughness", "m" },
+ { 245, 0, "FLSR", "Forecast log of surface roughness for heat", NULL },
+ { 246, 0, "CLWC", "Cloud liquid water content", "kg kg**-1" },
+ { 247, 0, "CIWC", "Cloud ice water content", "kg kg**-1" },
+ { 248, 0, "CC", "Cloud cover", NULL },
+ { 249, 0, "AIW", "Accumulated ice water tendency", NULL },
+ { 250, 0, "ICE", "Ice age", NULL },
+ { 251, 0, "ATTE", "Adiabatic tendency of temperature", "K" },
+ { 252, 0, "ATHE", "Adiabatic tendency of humidity", "kg kg**-1" },
+ { 253, 0, "ATZE", "Adiabatic tendency of zonal wind", "m s**-1" },
+ { 254, 0, "ATMW", "Adiabatic tendency of meridional wind", "m s**-1" },
};
static const PAR remo[] = {
@@ -58017,7 +59044,8 @@ static const PAR cosmo250[] = {
};
-static void tableDefault(void)
+static
+void tableDefault(void)
{
int tableID, instID, modelID;
@@ -58216,15 +59244,6 @@ static void tableDefault(void)
}
#endif /* _TABLE_H */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
#if defined (HAVE_CONFIG_H)
#endif
@@ -58581,7 +59600,7 @@ int tableRead(const char *tablefile)
*/
if ( id == 0 ) continue;
- while ( isdigit((int) *pline) ) pline++;
+ while ( isdigit((int) *pline) ) pline++;
if ( strchr(pline, '|') )
err = decodeForm2(pline, name, longname, units);
@@ -58590,7 +59609,7 @@ int tableRead(const char *tablefile)
if ( err ) continue;
- if ( name[0] ) sprintf(name, "var%d", id);
+ if ( name[0] == 0 ) sprintf(name, "var%d", id);
tableDefEntry(tableID, id, name, longname, units);
}
@@ -60216,28 +61235,26 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
}
}
+
void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
{
- int year, month, day, hour, minute, second;
- int rdate, rtime;
- int timeunit;
- int calendar;
- int julday, secofday, days, secs;
-
- *vdate = 0;
- *vtime = 0;
-
- timeunit = (*taxis).unit;
- calendar = (*taxis).calendar;
-
- rdate = (*taxis).rdate;
- rtime = (*taxis).rtime;
+ int rdate = taxis->rdate;
+ int rtime = taxis->rtime;
- if ( rdate == 0 && rtime == 0 && DBL_IS_EQUAL(timevalue, 0.) ) return;
+ if ( DBL_IS_EQUAL(timevalue, 0.) )
+ {
+ *vdate = rdate;
+ *vtime = rtime;
+ return;
+ }
+ int year, month, day, hour, minute, second;
cdiDecodeDate(rdate, &year, &month, &day);
cdiDecodeTime(rtime, &hour, &minute, &second);
+ int timeunit = taxis->unit;
+ int calendar = taxis->calendar;
+
if ( timeunit == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
{
timeunit = TUNIT_DAY;
@@ -60246,24 +61263,22 @@ void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
{
- int nmon, dpm;
- double fmon;
-
if ( timeunit == TUNIT_YEAR ) timevalue *= 12;
- nmon = (int) timevalue;
- fmon = timevalue - nmon;
+ int nmon = (int) timevalue;
+ double fmon = timevalue - nmon;
month += nmon;
while ( month > 12 ) { month -= 12; year++; }
while ( month < 1 ) { month += 12; year--; }
- dpm = days_per_month(calendar, year, month);
+ int dpm = days_per_month(calendar, year, month);
timeunit = TUNIT_DAY;
timevalue = fmon*dpm;
}
+ int julday, secofday, days, secs;
encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday, &secofday);
cdiDecodeTimevalue(timeunit, timevalue, &days, &secs);
@@ -60622,50 +61637,49 @@ taxisPrintKernel(taxis_t * taxisptr, FILE * fp)
taxisInqVdateBounds ( taxisptr->self, &vdate_lb, &vdate_ub);
taxisInqVtimeBounds ( taxisptr->self, &vtime_lb, &vtime_ub);
- fprintf ( fp, "#\n");
- fprintf ( fp, "# taxisID %d\n", taxisptr->self);
- fprintf ( fp, "#\n");
- fprintf ( fp, "self = %d\n", taxisptr->self );
- fprintf ( fp, "used = %d\n", taxisptr->used );
- fprintf ( fp, "type = %d\n", taxisptr->type );
- fprintf ( fp, "vdate = %d\n", taxisptr->vdate );
- fprintf ( fp, "vtime = %d\n", taxisptr->vtime );
- fprintf ( fp, "rdate = %d\n", taxisptr->rdate );
- fprintf ( fp, "rtime = %d\n", taxisptr->rtime );
- fprintf ( fp, "fdate = %d\n", taxisptr->fdate );
- fprintf ( fp, "ftime = %d\n", taxisptr->ftime );
- fprintf ( fp, "calendar = %d\n", taxisptr->calendar );
- fprintf ( fp, "unit = %d\n", taxisptr->unit );
- fprintf ( fp, "numavg = %d\n", taxisptr->numavg );
- fprintf ( fp, "climatology = %d\n", taxisptr->climatology );
- fprintf ( fp, "has_bounds = %d\n", taxisptr->has_bounds );
- fprintf ( fp, "vdate_lb = %d\n", vdate_lb );
- fprintf ( fp, "vtime_lb = %d\n", vtime_lb );
- fprintf ( fp, "vdate_ub = %d\n", vdate_ub );
- fprintf ( fp, "vtime_ub = %d\n", vtime_ub );
- fprintf ( fp, "fc_unit = %d\n", taxisptr->fc_unit );
- fprintf ( fp, "fc_period = %g\n", taxisptr->fc_period );
- fprintf ( fp, "\n");
-}
-
-static void taxisPrint ( int taxisID )
-{
- taxis_t * taxisptr;
-
- taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
- taxisPrintKernel ( taxisptr, stdout );
+ fprintf(fp,
+ "#\n"
+ "# taxisID %d\n"
+ "#\n"
+ "self = %d\n"
+ "used = %d\n"
+ "type = %d\n"
+ "vdate = %d\n"
+ "vtime = %d\n"
+ "rdate = %d\n"
+ "rtime = %d\n"
+ "fdate = %d\n"
+ "ftime = %d\n"
+ "calendar = %d\n"
+ "unit = %d\n"
+ "numavg = %d\n"
+ "climatology = %d\n"
+ "has_bounds = %d\n"
+ "vdate_lb = %d\n"
+ "vtime_lb = %d\n"
+ "vdate_ub = %d\n"
+ "vtime_ub = %d\n"
+ "fc_unit = %d\n"
+ "fc_period = %g\n"
+ "\n", taxisptr->self, taxisptr->self,
+ taxisptr->used, taxisptr->type,
+ taxisptr->vdate, taxisptr->vtime,
+ taxisptr->rdate, taxisptr->rtime,
+ taxisptr->fdate, taxisptr->ftime,
+ taxisptr->calendar, taxisptr->unit,
+ taxisptr->numavg, taxisptr->climatology,
+ taxisptr->has_bounds,
+ vdate_lb, vtime_lb, vdate_ub, vtime_ub,
+ taxisptr->fc_unit, taxisptr->fc_period );
}
static int
taxisCompareP(void *taxisptr1, void *taxisptr2)
{
- taxis_t * t1, * t2;
+ const taxis_t *t1 = ( const taxis_t * ) taxisptr1,
+ *t2 = ( const taxis_t * ) taxisptr2;
- t1 = ( taxis_t * ) taxisptr1;
- t2 = ( taxis_t * ) taxisptr2;
-
- xassert ( t1 );
- xassert ( t2 );
+ xassert ( t1 && t2 );
return ! ( t1->used == t2->used &&
t1->type == t2->type &&
@@ -61274,27 +62288,6 @@ void cdiCreateTimesteps(stream_t *streamptr)
* require-trailing-newline: t
* End:
*/
-#ifndef CREATE_UUID_H
-#define CREATE_UUID_H
-
-#if defined (HAVE_CONFIG_H)
-#endif
-
-
-void
-create_uuid(unsigned char uuid[CDI_UUID_SIZE]);
-
-#endif
-
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
#if defined (HAVE_CONFIG_H)
#endif
@@ -61358,7 +62351,8 @@ enum {
uuidNumHexChars = 36,
};
-void uuid2str(const unsigned char *uuid, char *uuidstr)
+
+void cdiUUID2Str(const unsigned char *uuid, char *uuidstr)
{
if ( uuid == NULL || uuidstr == NULL ) return;
@@ -61373,7 +62367,7 @@ void uuid2str(const unsigned char *uuid, char *uuidstr)
}
-int str2uuid(const char *uuidstr, unsigned char *uuid)
+int cdiStr2UUID(const char *uuidstr, unsigned char *uuid)
{
if ( uuid == NULL || uuidstr == NULL || strlen(uuidstr) != uuidNumHexChars)
return -1;
@@ -61442,8 +62436,7 @@ char* cdiUnescapeSpaces(const char* string, const char** outStringEnd)
#ifdef HAVE_DECL_UUID_GENERATE
#include <sys/time.h>
#include <uuid/uuid.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
static int uuid_seeded = 0;
static char uuid_rand_state[31 * sizeof (long)];
@@ -61472,8 +62465,7 @@ typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
#include <uuid.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
uint32_t status;
uuid_create((uuid_t *)(void *)uuid, &status);
@@ -61485,8 +62477,7 @@ create_uuid(unsigned char *uuid)
}
#else
#include <sys/time.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
static int uuid_seeded = 0;
static char uuid_rand_state[31 * sizeof (long)];
@@ -61913,39 +62904,22 @@ int varInsertTileSubtype(vartable_t *vptr, const var_tile_t *tiles)
{
if ( tiles == NULL ) return -1;
- int totalno_of_tileattr_pairs = -1;
- int tileClassification = -1;
- int numberOfTiles = -1;
- int numberOfAttributes = -1;
- int tileindex = -1;
- int attribute = -1;
-
- if ( tiles )
- {
- totalno_of_tileattr_pairs = tiles->totalno_of_tileattr_pairs;
- tileClassification = tiles->tileClassification;
- numberOfTiles = tiles->numberOfTiles;
- numberOfAttributes = tiles->numberOfAttributes;
- tileindex = tiles->tileindex;
- attribute = tiles->attribute;
- }
-
/* first, generate a subtype based on the info in "tiles". */
subtype_t *subtype_ptr;
subtypeAllocate(&subtype_ptr, SUBTYPE_TILES);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS, totalno_of_tileattr_pairs);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TILE_CLASSIFICATION , tileClassification);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_NUMBER_OF_TILES , numberOfTiles);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS, tiles->totalno_of_tileattr_pairs);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TILE_CLASSIFICATION , tiles->tileClassification);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_NUMBER_OF_TILES , tiles->numberOfTiles);
/*
* Here, we create a tile set for comparison that contains only one
* tile/attribute pair (based on "tiles").
*/
struct subtype_entry_t *entry = subtypeEntryInsert(subtype_ptr);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_NUMBER_OF_ATTR, numberOfAttributes);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEINDEX, tileindex);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEATTRIBUTE, attribute);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_NUMBER_OF_ATTR, tiles->numberOfAttributes);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEINDEX, tiles->tileindex);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEATTRIBUTE, tiles->attribute);
if (vptr->tiles == NULL) {
vptr->tiles = subtype_ptr;
@@ -62475,7 +63449,7 @@ struct varDefZAxisSearchState
int zaxistype;
int nlevels;
int lbounds;
- double *levels;
+ const double *levels;
const char *longname;
const char *units;
int ltype;
@@ -62498,23 +63472,19 @@ varDefZAxisSearch(int id, void *res, void *data)
}
-int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
- double *levels1, double *levels2, int vctsize, double *vct, char *name,
- char *longname, const char *units, int prec, int mode, int ltype1)
+int varDefZaxis(int vlistID, int zaxistype, int nlevels, const double *levels, int lbounds,
+ const double *levels1, const double *levels2, int vctsize, const double *vct, char *name,
+ const char *longname, const char *units, int prec, int mode, int ltype1)
{
/*
mode: 0 search in vlist and zaxis table
1 search in zaxis table
*/
int zaxisdefined = 0;
- int nzaxis;
int zaxisID = UNDEFID;
int zaxisglobdefined = 0;
- vlist_t *vlistptr;
-
- vlistptr = vlist_to_pointer(vlistID);
-
- nzaxis = vlistptr->nzaxis;
+ vlist_t *vlistptr = vlist_to_pointer(vlistID);
+ int nzaxis = vlistptr->nzaxis;
if ( mode == 0 )
for ( int index = 0; index < nzaxis; index++ )
@@ -62565,15 +63535,8 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
zaxisDefUbounds(zaxisID, levels2);
}
- if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
- {
- /* if ( vctsize > 0 && vctsize >= 2*(nlevels+1)) */
- /* if ( vctsize > 0 && vctsize >= 2*(nlevels)) */
- if ( vctsize > 0 )
- zaxisDefVct(zaxisID, vctsize, vct);
- else
- Warning("VCT missing");
- }
+ if ( (zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF) && vctsize > 0 )
+ zaxisDefVct(zaxisID, vctsize, vct);
zaxisDefName(zaxisID, name);
zaxisDefLongname(zaxisID, longname);
@@ -62923,7 +63886,8 @@ vlist_t *vlist_to_pointer(int vlistID)
static
void vlist_init_entry(vlist_t *vlistptr)
{
- vlistptr->locked = 0;
+ vlistptr->immutable = 0;
+ vlistptr->internal = 0;
vlistptr->self = CDI_UNDEFID;
vlistptr->nvars = 0;
vlistptr->vars = NULL;
@@ -62988,32 +63952,22 @@ static
void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
{
int vlistID2 = vlistptr2->self;
+ int vlist2internal = vlistptr2->internal;
memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
+ vlistptr2->internal = vlist2internal; //the question who's responsible to destroy the vlist is tied to its containing memory region, so we retain this flag
+ vlistptr2->immutable = 0; //this is a copy, so it's mutable, independent of whether the original is mutable or not
vlistptr2->atts.nelems = 0;
vlistptr2->self = vlistID2;
}
-void vlist_lock(int vlistID)
+void cdiVlistMakeInternal(int vlistID)
{
- vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
- if ( !vlistptr->locked )
- {
- vlistptr->locked += 1;
- reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
- }
+ vlist_to_pointer(vlistID)->internal = 1;
}
-
-void vlist_unlock(int vlistID)
+void cdiVlistMakeImmutable(int vlistID)
{
- vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
- if ( vlistptr->locked )
- {
- vlistptr->locked -= 1;
- reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
- }
+ vlist_to_pointer(vlistID)->immutable = 1;
}
/*
@@ -63106,12 +64060,25 @@ void vlistDestroy(int vlistID)
{
vlist_t *vlistptr = vlist_to_pointer(vlistID);
- if ( vlistptr->locked != 0 )
- Warning("Destroying of a locked object (vlistID=%d) failed!", vlistID);
+ if ( vlistptr->internal )
+ Warning("Attempt to destroy an internal vlist object by the user (vlistID=%d).", vlistID);
else
vlist_delete(vlistptr);
}
+// destroy an internal vlist object
+void cdiVlistDestroy_(int vlistID)
+{
+ vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+ if(!vlistptr->internal)
+ Warning("Destroying a vlist object that is owned by the user.\n"
+ "This is most likely because of a missing vlistDestroy() in the application code.\n"
+ "If that's not the case, and you are absolutely certain about it, please report the bug.");
+
+ vlist_delete(vlistptr);
+}
+
static
void var_copy_entries(var_t *var2, var_t *var1)
{
@@ -63322,13 +64289,8 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, const double *
zaxisDefUbounds(zaxisID, ubounds);
}
- if ( zaxistype == ZAXIS_HYBRID )
- {
- if ( vctsize > 0 )
- zaxisDefVct(zaxisID, vctsize, vct);
- else
- Warning("VCT missing");
- }
+ if ( zaxistype == ZAXIS_HYBRID && vctsize > 0 )
+ zaxisDefVct(zaxisID, vctsize, vct);
}
nzaxis = vlistptr->nzaxis;
@@ -63559,12 +64521,12 @@ void vlistCat(int vlistID2, int vlistID1)
var_copy_entries(&vars2[varID2], &vars1[varID]);
- int nlevs = zaxisInqSize(vars1[varID].zaxisID);
if ( vars1[varID].levinfo )
{
- vars2[varID2].levinfo = (levinfo_t *) Malloc((size_t)nlevs * sizeof(levinfo_t));
+ size_t nlevs = (size_t)zaxisInqSize(vars1[varID].zaxisID);
+ vars2[varID2].levinfo = (levinfo_t *) Malloc(nlevs * sizeof(levinfo_t));
memcpy(vars2[varID2].levinfo, vars1[varID].levinfo,
- (size_t)nlevs * sizeof(levinfo_t));
+ nlevs * sizeof(levinfo_t));
}
vars2[varID2].atts.nelems = 0;
@@ -64266,12 +65228,10 @@ int vlistSubtypeIndex(int vlistID, int subtypeID)
vlist_t *vlistptr = vlist_to_pointer(vlistID);
int index;
- for ( index = 0 ; index < vlistptr->nsubtypes ; index++ )
+ for(index = vlistptr->nsubtypes; index--; )
if ( subtypeID == vlistptr->subtypeIDs[index] ) break;
- if ( index == vlistptr->nsubtypes ) index = -1;
-
- return (index);
+ return index;
}
@@ -64348,6 +65308,7 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
xassert(!force_id || p->self == targetID);
if (!force_id)
targetID = p->self;
+ cdiVlistMakeInternal(p->self);
p->taxisID = namespaceAdaptKey(tempbuf[2], originNamespace);
p->tableID = tempbuf[3];
p->instID = namespaceAdaptKey(tempbuf[4], originNamespace);
@@ -65659,7 +66620,7 @@ The function @func{vlistInqVarStdname} returns the standard name of a variable i
otherwise the result is an empty string.
@Result
- at func{vlistInqVarName} returns the standard name of the variable to the parameter stdname.
+ at func{vlistInqVarStdname} returns the standard name of the variable to the parameter stdname.
@EndFunction
*/
@@ -66790,9 +67751,10 @@ void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
if (vlistptr == NULL) Error("Internal error!");
int idx;
- if ( vlistptr->locked != 0 )
- Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
- "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+ if ( vlistptr->immutable )
+ Error("vlistDefVarIntKey() was called on an immutable vlist object (vlistID = %d)\n"
+ "Either call vlistDefVarIntKey() before passing the vlist object to streamDefVlist(),\n"
+ "or use the stream-internal vlist by calling streamInqVlist().", vlistID);
for ( idx=0; idx<vlistptr->vars[varID].opt_grib_nentries; idx++)
if ( (strcmp(name, vlistptr->vars[varID].opt_grib_kvpair[idx].keyword) == 0 ) &&
@@ -66852,9 +67814,10 @@ void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
if (vlistptr == NULL) Error("Internal error!");
int idx;
- if ( vlistptr->locked != 0 )
- Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
- "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+ if ( vlistptr->immutable )
+ Error("vlistDefVarDblKey() was called on an immutable vlist object (vlistID = %d)\n"
+ "Either call vlistDefVarIntKey() before passing the vlist object to streamDefVlist(),\n"
+ "or use the stream-internal vlist by calling streamInqVlist().", vlistID);
for ( idx=0; idx<vlistptr->vars[varID].opt_grib_nentries; idx++)
if ( (strcmp(name, vlistptr->vars[varID].opt_grib_kvpair[idx].keyword) == 0 ) &&
@@ -67048,6 +68011,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
| FCMPFLT(validrange[0]) | FCMPFLT(validrange[1]);
#undef FCMP
#undef FCMPFLT
+#undef FCMPSTR
#undef FCMP2
if ((diff |= ((pva->levinfo == NULL) ^ (pvb->levinfo == NULL))))
return 1;
@@ -68470,7 +69434,6 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
unsigned char uuid[CDI_UUID_SIZE];
int levelID;
int nbyte;
- double level;
xassert ( zaxisptr );
@@ -68499,16 +69462,28 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
fprintf(fp, "%*s", nbyte0, "");
nbyte = nbyte0;
}
- level = zaxisInqLevel(zaxisID, levelID);
- nbyte += fprintf(fp, "%.9g ", level);
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->vals[levelID]);
}
fprintf(fp, "\n");
if ( zaxisptr->lbounds && zaxisptr->ubounds )
{
- double level1, level2;
+ nbyte0 = fprintf(fp, "lbounds = ");
+ nbyte = nbyte0;
+ for ( levelID = 0; levelID < nlevels; levelID++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n");
+ fprintf(fp, "%*s", nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->lbounds[levelID]);
+ }
+ fprintf(fp, "\n");
+
+ nbyte0 = fprintf(fp, "ubounds = ");
nbyte = nbyte0;
- nbyte0 = fprintf(fp, "bounds = ");
for ( levelID = 0; levelID < nlevels; levelID++ )
{
if ( nbyte > 80 )
@@ -68517,27 +69492,21 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
fprintf(fp, "%*s", nbyte0, "");
nbyte = nbyte0;
}
- level1 = zaxisInqLbound(zaxisID, levelID);
- level2 = zaxisInqUbound(zaxisID, levelID);
- nbyte += fprintf(fp, "%.9g-%.9g ", level1, level2);
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->ubounds[levelID]);
}
fprintf(fp, "\n");
}
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
- int i;
- int vctsize;
- const double *vct;
-
- vctsize = zaxisptr->vctsize;
- vct = zaxisptr->vct;
+ int vctsize = zaxisptr->vctsize;
+ const double *vct = zaxisptr->vct;
fprintf(fp, "vctsize = %d\n", vctsize);
if ( vctsize )
{
nbyte0 = fprintf(fp, "vct = ");
nbyte = nbyte0;
- for ( i = 0; i < vctsize; i++ )
+ for ( int i = 0; i < vctsize; i++ )
{
if ( nbyte > 70 || i == vctsize/2 )
{
@@ -68985,7 +69954,7 @@ void cdiZaxisGetIndexList(unsigned nzaxis, int *zaxisResHs)
* require-trailing-newline: t
* End:
*/
- static const char cdi_libvers[] = "1.7.0" " of " "Oct 25 2015"" " "12:56:26";
+ static const char cdi_libvers[] = "1.7.1" " of " "Feb 19 2016"" " "11:18:00";
const char *cdiLibraryVersion(void)
{
return (cdi_libvers);
@@ -71712,6 +72681,7 @@ FCALLSCSUB3 (streamInqRecord, STREAMINQRECORD, streaminqrecord, INT, PINT, PINT)
FCALLSCSUB3 (streamWriteRecord, STREAMWRITERECORD, streamwriterecord, INT, DOUBLEV, INT)
FCALLSCSUB3 (streamWriteRecordF, STREAMWRITERECORDF, streamwriterecordf, INT, FLOATV, INT)
FCALLSCSUB3 (streamReadRecord, STREAMREADRECORD, streamreadrecord, INT, DOUBLEV, PINT)
+FCALLSCSUB3 (streamReadRecordF, STREAMREADRECORDF, streamreadrecordf, INT, FLOATV, PINT)
FCALLSCSUB2 (streamCopyRecord, STREAMCOPYRECORD, streamcopyrecord, INT, INT)
/* File driven I/O (may yield better performance than using the streamXXX functions) */
@@ -71839,6 +72809,12 @@ FCALLSCFUN3 (INT, vlistHasVarKey, VLISTHASVARKEY, vlisthasvarkey, INT, INT, STRI
FCALLSCFUN3 (DOUBLE, vlistInqVarDblKey, VLISTINQVARDBLKEY, vlistinqvardblkey, INT, INT, STRING)
FCALLSCFUN3 (INT, vlistInqVarIntKey, VLISTINQVARINTKEY, vlistinqvarintkey, INT, INT, STRING)
+/* needed only for CDO operator after */
+
+FCALLSCFUN2 (STRING, vlistInqVarNamePtr, VLISTINQVARNAMEPTR, vlistinqvarnameptr, INT, INT)
+FCALLSCFUN2 (STRING, vlistInqVarLongnamePtr, VLISTINQVARLONGNAMEPTR, vlistinqvarlongnameptr, INT, INT)
+FCALLSCFUN2 (STRING, vlistInqVarUnitsPtr, VLISTINQVARUNITSPTR, vlistinqvarunitsptr, INT, INT)
+
/* VLIST attributes */
FCALLSCFUN3 (INT, vlistInqNatts, VLISTINQNATTS, vlistinqnatts, INT, INT, PINT)
@@ -72081,6 +73057,9 @@ FCALLSCFUN3 (INT, tableInqParCode, TABLEINQPARCODE, tableinqparcode, INT, PSTRIN
FCALLSCFUN3 (INT, tableInqParName, TABLEINQPARNAME, tableinqparname, INT, INT, PSTRING)
FCALLSCFUN3 (INT, tableInqParLongname, TABLEINQPARLONGNAME, tableinqparlongname, INT, INT, PSTRING)
FCALLSCFUN3 (INT, tableInqParUnits, TABLEINQPARUNITS, tableinqparunits, INT, INT, PSTRING)
+
+/* needed only for CDO operator after */
+
FCALLSCFUN2 (STRING, tableInqParNamePtr, TABLEINQPARNAMEPTR, tableinqparnameptr, INT, INT)
FCALLSCFUN2 (STRING, tableInqParLongnamePtr, TABLEINQPARLONGNAMEPTR, tableinqparlongnameptr, INT, INT)
FCALLSCFUN2 (STRING, tableInqParUnitsPtr, TABLEINQPARUNITSPTR, tableinqparunitsptr, INT, INT)
@@ -72113,6 +73092,7 @@ FCALLSCSUB2 (subtypeDefActiveIndex, SUBTYPEDEFACTIVEINDEX, subtypedefactiveindex
query objects. */
FCALLSCFUN3 (INT, subtypeInqTile, SUBTYPEINQTILE, subtypeinqtile, INT, INT, INT)
+FCALLSCFUN4 (INT, subtypeInqAttribute, SUBTYPEINQATTRIBUTE, subtypeinqattribute, INT, INT, STRING, PINT)
FCALLSCFUN2 (INT, vlistInqVarSubtype, VLISTINQVARSUBTYPE, vlistinqvarsubtype, INT, INT)
FCALLSCSUB3 (gribapiLibraryVersion, GRIBAPILIBRARYVERSION, gribapilibraryversion, PINT, PINT, PINT)
diff --git a/libcdi/src/cdipio.inc b/libcdi/src/cdipio.inc
index d6afa53..ab4eba3 100644
--- a/libcdi/src/cdipio.inc
+++ b/libcdi/src/cdipio.inc
@@ -4,7 +4,7 @@
!
! Author:
! -------
-! Uwe Schulzweida, MPI-MET, Hamburg, October 2015
+! Uwe Schulzweida, MPI-MET, Hamburg, February 2016
!
!
diff --git a/libcdi/src/cgribex.h b/libcdi/src/cgribex.h
index 43385aa..0f0f713 100644
--- a/libcdi/src/cgribex.h
+++ b/libcdi/src/cgribex.h
@@ -175,6 +175,9 @@
#define ISEC4_NumNonMissValues (isec4[20]) /* Number of non-missing values */
+#ifdef __cplusplus
+extern "C" {
+#endif
void gribFixZSE(int flag); /* 1: Fix ZeroShiftError of simple packed spherical harmonics */
@@ -188,11 +191,11 @@ void gribSetValueCheck(int vcheck);
void gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret);
+ int kleng, int *kword, const char *hoper, int *kret);
void gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret);
+ int kleng, int *kword, const char *hoper, int *kret);
const char *cgribexLibraryVersion(void);
@@ -243,7 +246,13 @@ int gribVersion(unsigned char *buffer, size_t buffersize);
int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer, int *intnum, float *fltnum, off_t *bignum);
-double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation);
+double calculate_pfactor_float(const float* spectralField, long fieldTruncation, long subsetTruncation);
+double calculate_pfactor_double(const double* spectralField, long fieldTruncation, long subsetTruncation);
+
+
+#if defined (__cplusplus)
+}
+#endif
#endif /* _CGRIBEX_H */
diff --git a/libcdi/src/cgribexlib.c b/libcdi/src/cgribexlib.c
index 62a26c5..e824767 100644
--- a/libcdi/src/cgribexlib.c
+++ b/libcdi/src/cgribexlib.c
@@ -1,7 +1,7 @@
-/* Automatically generated by m214003 at 2015-09-14, do not edit */
+/* Automatically generated by m214003 at 2016-02-19, do not edit */
-/* CGRIBEXLIB_VERSION="1.7.3" */
+/* CGRIBEXLIB_VERSION="1.7.4" */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined (__clang__)
#pragma GCC diagnostic push
@@ -38,8 +38,8 @@
#define TEMPLATE(X,Y) CAT(X,Y)
#endif
-#ifndef _GRIB_INT_H
-#define _GRIB_INT_H
+#ifndef GRIB_INT_H
+#define GRIB_INT_H
#if defined (HAVE_CONFIG_H)
# include "config.h"
@@ -112,24 +112,25 @@
#endif
#endif
-#ifndef DBL_IS_EQUAL
-/*#define DBL_IS_EQUAL(x,y) (!(x < y || y < x)) */
-# define DBL_IS_EQUAL(x,y) (DBL_IS_NAN(x)||DBL_IS_NAN(y)?(DBL_IS_NAN(x)&&DBL_IS_NAN(y)?1:0):!(x < y || y < x))
-#endif
-
#ifndef IS_EQUAL
# define IS_NOT_EQUAL(x,y) (x < y || y < x)
# define IS_EQUAL(x,y) (!IS_NOT_EQUAL(x,y))
#endif
/* dummy use of unused parameters to silence compiler warnings */
-#define UNUSED(x) (void)x
+#ifndef UNUSED
+# define UNUSED(x) (void)(x)
+#endif
#define JP23SET 0x7FFFFF /* 2**23 - 1 (---> 8388607) */
#define POW_2_M24 0.000000059604644775390625 /* pow(2.0, -24.0) */
-double intpow2(int x);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define intpow2(x) (ldexp(1.0, (x)))
int gribrec_len(unsigned b1, unsigned b2, unsigned b3);
int correct_bdslen(int bdslen, long recsize, long gribpos);
@@ -176,8 +177,8 @@ void scale_complex_double(double *fpdata, int pcStart, int pcScale, int trunc,
void scale_complex_float(float *fpdata, int pcStart, int pcScale, int trunc, int inv);
void scatter_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
void scatter_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
-void gather_complex_double(double *fpdata, int pcStart, int trunc, int nsp);
-void gather_complex_float(float *fpdata, int pcStart, int trunc, int nsp);
+void gather_complex_double(double *fpdata, size_t pcStart, size_t trunc, size_t nsp);
+void gather_complex_float(float *fpdata, size_t pcStart, size_t trunc, size_t nsp);
void scm0_double(double *pdl, double *pdr, double *pfl, double *pfr, int klg);
int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
@@ -217,7 +218,11 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
unsigned char **lusp, unsigned char **gdsp, unsigned char **pdsp,
unsigned char **drsp, unsigned char **bmsp, unsigned char **bdsp);
-#endif /* _GRIB_INT_H */
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* GRIB_INT_H */
#ifndef _GRIBDECODE_H
#define _GRIBDECODE_H
@@ -319,7 +324,7 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define GDS_ScanFlag GET_UINT1(gds[27])
#define GDS_LatSP GET_INT3(gds[32], gds[33], gds[34])
#define GDS_LonSP GET_INT3(gds[35], gds[36], gds[37])
-#define GDS_RotAngle GET_Real(&(gds[38]))
+#define GDS_RotAngle (GET_Real(&(gds[38])))
/* GRIB1 Lambert */
#define GDS_Lambert_Lov GET_INT3(gds[17], gds[18], gds[19])
@@ -344,9 +349,9 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define BDS_Len ((int) ((bds[0]<<16)+(bds[1]<<8)+bds[2]))
#define BDS_Flag (bds[3])
#define BDS_BinScale GET_INT2(bds[ 4], bds[ 5])
-#define BDS_RefValue decfp2((int)bds[ 6], GET_UINT3(bds[ 7], bds[ 8], bds[ 9]))
+#define BDS_RefValue (decfp2((int)bds[ 6], GET_UINT3(bds[ 7], bds[ 8], bds[ 9])))
#define BDS_NumBits ((int) bds[10])
-#define BDS_RealCoef decfp2((int)bds[zoff+11], GET_UINT3(bds[zoff+12], bds[zoff+13], bds[zoff+14]))
+#define BDS_RealCoef (decfp2((int)bds[zoff+11], GET_UINT3(bds[zoff+12], bds[zoff+13], bds[zoff+14])))
#define BDS_PackData ((int) ((bds[zoff+11]<<8) + bds[zoff+12]))
#define BDS_Power GET_INT2(bds[zoff+13], bds[zoff+14])
#define BDS_Z (bds[13])
@@ -365,21 +370,20 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
#define PutnZero(n) \
{ \
- int i; \
- for ( i = z; i < z+n; i++ ) lGrib[i] = 0; \
+ for ( size_t i = z >= 0 ? (size_t)z : 0; i < (size_t)(z+n); i++ ) lGrib[i] = 0; \
z += n; \
}
-#define Put1Byte(Value) (lGrib[z++] = (Value))
-#define Put2Byte(Value) ((lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
-#define Put3Byte(Value) ((lGrib[z++] = (Value) >> 16), \
- (lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
-#define Put4Byte(Value) ((lGrib[z++] = (Value) >> 24), \
- (lGrib[z++] = (Value) >> 16), \
- (lGrib[z++] = (Value) >> 8), \
- (lGrib[z++] = (Value)))
+#define Put1Byte(Value) (lGrib[z++] = (GRIBPACK)(Value))
+#define Put2Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
+#define Put3Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
+#define Put4Byte(Value) ((lGrib[z++] = (GRIBPACK)((Value) >> 24)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 16)), \
+ (lGrib[z++] = (GRIBPACK)((Value) >> 8)), \
+ (lGrib[z++] = (GRIBPACK)(Value)))
#define Put1Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x80 - ival; Put1Byte(ival);}
#define Put2Int(Value) {ival = Value; if ( ival < 0 ) ival = 0x8000 - ival; Put2Byte(ival);}
@@ -393,278 +397,21 @@ int grib2Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **i
}
#endif /* _GRIB_ENCODE_H */
-#include <stdio.h>
-#include <math.h>
-
-
-const double _pow2tab[158] = {
- /* pow(2.0, 0.0) */ 1.0,
- /* pow(2.0, 1.0) */ 2.0,
- /* pow(2.0, 2.0) */ 4.0,
- /* pow(2.0, 3.0) */ 8.0,
- /* pow(2.0, 4.0) */ 16.0,
- /* pow(2.0, 5.0) */ 32.0,
- /* pow(2.0, 6.0) */ 64.0,
- /* pow(2.0, 7.0) */ 128.0,
- /* pow(2.0, 8.0) */ 256.0,
- /* pow(2.0, 9.0) */ 512.0,
- /* pow(2.0, 10.0) */ 1024.0,
- /* pow(2.0, 11.0) */ 2048.0,
- /* pow(2.0, 12.0) */ 4096.0,
- /* pow(2.0, 13.0) */ 8192.0,
- /* pow(2.0, 14.0) */ 16384.0,
- /* pow(2.0, 15.0) */ 32768.0,
- /* pow(2.0, 16.0) */ 65536.0,
- /* pow(2.0, 17.0) */ 131072.0,
- /* pow(2.0, 18.0) */ 262144.0,
- /* pow(2.0, 19.0) */ 524288.0,
- /* pow(2.0, 20.0) */ 1048576.0,
- /* pow(2.0, 21.0) */ 2097152.0,
- /* pow(2.0, 22.0) */ 4194304.0,
- /* pow(2.0, 23.0) */ 8388608.0,
- /* pow(2.0, 24.0) */ 16777216.0,
- /* pow(2.0, 25.0) */ 33554432.0,
- /* pow(2.0, 26.0) */ 67108864.0,
- /* pow(2.0, 27.0) */ 134217728.0,
- /* pow(2.0, 28.0) */ 268435456.0,
- /* pow(2.0, 29.0) */ 536870912.0,
- /* pow(2.0, 30.0) */ 1073741824.0,
- /* pow(2.0, 31.0) */ 2147483648.0,
- /* pow(2.0, 32.0) */ 4294967296.0,
- /* pow(2.0, 33.0) */ 8589934592.0,
- /* pow(2.0, 34.0) */ 17179869184.0,
- /* pow(2.0, 35.0) */ 34359738368.0,
- /* pow(2.0, 36.0) */ 68719476736.0,
- /* pow(2.0, 37.0) */ 137438953472.0,
- /* pow(2.0, 38.0) */ 274877906944.0,
- /* pow(2.0, 39.0) */ 549755813888.0,
- /* pow(2.0, 40.0) */ 1099511627776.0,
- /* pow(2.0, 41.0) */ 2199023255552.0,
- /* pow(2.0, 42.0) */ 4398046511104.0,
- /* pow(2.0, 43.0) */ 8796093022208.0,
- /* pow(2.0, 44.0) */ 17592186044416.0,
- /* pow(2.0, 45.0) */ 35184372088832.0,
- /* pow(2.0, 46.0) */ 70368744177664.0,
- /* pow(2.0, 47.0) */ 140737488355328.0,
- /* pow(2.0, 48.0) */ 281474976710656.0,
- /* pow(2.0, 49.0) */ 562949953421312.0,
- /* pow(2.0, 50.0) */ 1125899906842624.0,
- /* pow(2.0, 51.0) */ 2251799813685248.0,
- /* pow(2.0, 52.0) */ 4503599627370496.0,
- /* pow(2.0, 53.0) */ 9007199254740992.0,
- /* pow(2.0, 54.0) */ 18014398509481984.0,
- /* pow(2.0, 55.0) */ 36028797018963968.0,
- /* pow(2.0, 56.0) */ 72057594037927936.0,
- /* pow(2.0, 57.0) */ 144115188075855872.0,
- /* pow(2.0, 58.0) */ 288230376151711744.0,
- /* pow(2.0, 59.0) */ 576460752303423488.0,
- /* pow(2.0, 60.0) */ 1152921504606846976.0,
- /* pow(2.0, 61.0) */ 2305843009213693952.0,
- /* pow(2.0, 62.0) */ 4611686018427387904.0,
- /* pow(2.0, 63.0) */ 9223372036854775808.0,
- /* pow(2.0, 64.0) */ 18446744073709551616.0,
- /* pow(2.0, 65.0) */ 36893488147419103232.0,
- /* pow(2.0, 66.0) */ 73786976294838206464.0,
- /* pow(2.0, 67.0) */ 147573952589676412928.0,
- /* pow(2.0, 68.0) */ 295147905179352825856.0,
- /* pow(2.0, 69.0) */ 590295810358705651712.0,
- /* pow(2.0, 70.0) */ 1180591620717411303424.0,
- /* pow(2.0, 71.0) */ 2361183241434822606848.0,
- /* pow(2.0, 72.0) */ 4722366482869645213696.0,
- /* pow(2.0, 73.0) */ 9444732965739290427392.0,
- /* pow(2.0, 74.0) */ 18889465931478580854784.0,
- /* pow(2.0, 75.0) */ 37778931862957161709568.0,
- /* pow(2.0, 76.0) */ 75557863725914323419136.0,
- /* pow(2.0, 77.0) */ 151115727451828646838272.0,
- /* pow(2.0, 78.0) */ 302231454903657293676544.0,
- /* pow(2.0, 79.0) */ 604462909807314587353088.0,
- /* pow(2.0, 80.0) */ 1208925819614629174706176.0,
- /* pow(2.0, 81.0) */ 2417851639229258349412352.0,
- /* pow(2.0, 82.0) */ 4835703278458516698824704.0,
- /* pow(2.0, 83.0) */ 9671406556917033397649408.0,
- /* pow(2.0, 84.0) */ 19342813113834066795298816.0,
- /* pow(2.0, 85.0) */ 38685626227668133590597632.0,
- /* pow(2.0, 86.0) */ 77371252455336267181195264.0,
- /* pow(2.0, 87.0) */ 154742504910672534362390528.0,
- /* pow(2.0, 88.0) */ 309485009821345068724781056.0,
- /* pow(2.0, 89.0) */ 618970019642690137449562112.0,
- /* pow(2.0, 90.0) */ 1237940039285380274899124224.0,
- /* pow(2.0, 91.0) */ 2475880078570760549798248448.0,
- /* pow(2.0, 92.0) */ 4951760157141521099596496896.0,
- /* pow(2.0, 93.0) */ 9903520314283042199192993792.0,
- /* pow(2.0, 94.0) */ 19807040628566084398385987584.0,
- /* pow(2.0, 95.0) */ 39614081257132168796771975168.0,
- /* pow(2.0, 96.0) */ 79228162514264337593543950336.0,
- /* pow(2.0, 97.0) */ 158456325028528675187087900672.0,
- /* pow(2.0, 98.0) */ 316912650057057350374175801344.0,
- /* pow(2.0, 99.0) */ 633825300114114700748351602688.0,
- /* pow(2.0, 100.0) */ 1267650600228229401496703205376.0,
- /* pow(2.0, 101.0) */ 2535301200456458802993406410752.0,
- /* pow(2.0, 102.0) */ 5070602400912917605986812821504.0,
- /* pow(2.0, 103.0) */ 10141204801825835211973625643008.0,
- /* pow(2.0, 104.0) */ 20282409603651670423947251286016.0,
- /* pow(2.0, 105.0) */ 40564819207303340847894502572032.0,
- /* pow(2.0, 106.0) */ 81129638414606681695789005144064.0,
- /* pow(2.0, 107.0) */ 162259276829213363391578010288128.0,
- /* pow(2.0, 108.0) */ 324518553658426726783156020576256.0,
- /* pow(2.0, 109.0) */ 649037107316853453566312041152512.0,
- /* pow(2.0, 110.0) */ 1298074214633706907132624082305024.0,
- /* pow(2.0, 111.0) */ 2596148429267413814265248164610048.0,
- /* pow(2.0, 112.0) */ 5192296858534827628530496329220096.0,
- /* pow(2.0, 113.0) */ 10384593717069655257060992658440192.0,
- /* pow(2.0, 114.0) */ 20769187434139310514121985316880384.0,
- /* pow(2.0, 115.0) */ 41538374868278621028243970633760768.0,
- /* pow(2.0, 116.0) */ 83076749736557242056487941267521536.0,
- /* pow(2.0, 117.0) */ 166153499473114484112975882535043072.0,
- /* pow(2.0, 118.0) */ 332306998946228968225951765070086144.0,
- /* pow(2.0, 119.0) */ 664613997892457936451903530140172288.0,
- /* pow(2.0, 120.0) */ 1329227995784915872903807060280344576.0,
- /* pow(2.0, 121.0) */ 2658455991569831745807614120560689152.0,
- /* pow(2.0, 122.0) */ 5316911983139663491615228241121378304.0,
- /* pow(2.0, 123.0) */ 10633823966279326983230456482242756608.0,
- /* pow(2.0, 124.0) */ 21267647932558653966460912964485513216.0,
- /* pow(2.0, 125.0) */ 42535295865117307932921825928971026432.0,
- /* pow(2.0, 126.0) */ 85070591730234615865843651857942052864.0,
- /* pow(2.0, 127.0) */ 170141183460469231731687303715884105728.0,
- /* pow(2.0, 128.0) */ 340282366920938463463374607431768211456.0,
- /* pow(2.0, 129.0) */ 680564733841876926926749214863536422912.0,
- /* pow(2.0, 130.0) */ 1361129467683753853853498429727072845824.0,
- /* pow(2.0, 131.0) */ 2722258935367507707706996859454145691648.0,
- /* pow(2.0, 132.0) */ 5444517870735015415413993718908291383296.0,
- /* pow(2.0, 133.0) */ 10889035741470030830827987437816582766592.0,
- /* pow(2.0, 134.0) */ 21778071482940061661655974875633165533184.0,
- /* pow(2.0, 135.0) */ 43556142965880123323311949751266331066368.0,
- /* pow(2.0, 136.0) */ 87112285931760246646623899502532662132736.0,
- /* pow(2.0, 137.0) */ 174224571863520493293247799005065324265472.0,
- /* pow(2.0, 138.0) */ 348449143727040986586495598010130648530944.0,
- /* pow(2.0, 139.0) */ 696898287454081973172991196020261297061888.0,
- /* pow(2.0, 140.0) */ 1393796574908163946345982392040522594123776.0,
- /* pow(2.0, 141.0) */ 2787593149816327892691964784081045188247552.0,
- /* pow(2.0, 142.0) */ 5575186299632655785383929568162090376495104.0,
- /* pow(2.0, 143.0) */ 11150372599265311570767859136324180752990208.0,
- /* pow(2.0, 144.0) */ 22300745198530623141535718272648361505980416.0,
- /* pow(2.0, 145.0) */ 44601490397061246283071436545296723011960832.0,
- /* pow(2.0, 146.0) */ 89202980794122492566142873090593446023921664.0,
- /* pow(2.0, 147.0) */ 178405961588244985132285746181186892047843328.0,
- /* pow(2.0, 148.0) */ 356811923176489970264571492362373784095686656.0,
- /* pow(2.0, 149.0) */ 713623846352979940529142984724747568191373312.0,
- /* pow(2.0, 150.0) */ 1427247692705959881058285969449495136382746624.0,
- /* pow(2.0, 151.0) */ 2854495385411919762116571938898990272765493248.0,
- /* pow(2.0, 152.0) */ 5708990770823839524233143877797980545530986496.0,
- /* pow(2.0, 153.0) */ 11417981541647679048466287755595961091061972992.0,
- /* pow(2.0, 154.0) */ 22835963083295358096932575511191922182123945984.0,
- /* pow(2.0, 155.0) */ 45671926166590716193865151022383844364247891968.0,
- /* pow(2.0, 156.0) */ 91343852333181432387730302044767688728495783936.0,
- /* pow(2.0, 157.0) */ 182687704666362864775460604089535377456991567872.0,
-};
-
-
-const double _pow16tab[71] = {
- /* pow(16.0, 0.0) */ 1.0,
- /* pow(16.0, 1.0) */ 16.0,
- /* pow(16.0, 2.0) */ 256.0,
- /* pow(16.0, 3.0) */ 4096.0,
- /* pow(16.0, 4.0) */ 65536.0,
- /* pow(16.0, 5.0) */ 1048576.0,
- /* pow(16.0, 6.0) */ 16777216.0,
- /* pow(16.0, 7.0) */ 268435456.0,
- /* pow(16.0, 8.0) */ 4294967296.0,
- /* pow(16.0, 9.0) */ 68719476736.0,
- /* pow(16.0, 10.0) */ 1099511627776.0,
- /* pow(16.0, 11.0) */ 17592186044416.0,
- /* pow(16.0, 12.0) */ 281474976710656.0,
- /* pow(16.0, 13.0) */ 4503599627370496.0,
- /* pow(16.0, 14.0) */ 72057594037927936.0,
- /* pow(16.0, 15.0) */ 1152921504606846976.0,
- /* pow(16.0, 16.0) */ 18446744073709551616.0,
- /* pow(16.0, 17.0) */ 295147905179352825856.0,
- /* pow(16.0, 18.0) */ 4722366482869645213696.0,
- /* pow(16.0, 19.0) */ 75557863725914323419136.0,
- /* pow(16.0, 20.0) */ 1208925819614629174706176.0,
- /* pow(16.0, 21.0) */ 19342813113834066795298816.0,
- /* pow(16.0, 22.0) */ 309485009821345068724781056.0,
- /* pow(16.0, 23.0) */ 4951760157141521099596496896.0,
- /* pow(16.0, 24.0) */ 79228162514264337593543950336.0,
- /* pow(16.0, 25.0) */ 1267650600228229401496703205376.0,
- /* pow(16.0, 26.0) */ 20282409603651670423947251286016.0,
- /* pow(16.0, 27.0) */ 324518553658426726783156020576256.0,
- /* pow(16.0, 28.0) */ 5192296858534827628530496329220096.0,
- /* pow(16.0, 29.0) */ 83076749736557242056487941267521536.0,
- /* pow(16.0, 30.0) */ 1329227995784915872903807060280344576.0,
- /* pow(16.0, 31.0) */ 21267647932558653966460912964485513216.0,
- /* pow(16.0, 32.0) */ 340282366920938463463374607431768211456.0,
- /* pow(16.0, 33.0) */ 5444517870735015415413993718908291383296.0,
- /* pow(16.0, 34.0) */ 87112285931760246646623899502532662132736.0,
- /* pow(16.0, 35.0) */ 1393796574908163946345982392040522594123776.0,
- /* pow(16.0, 36.0) */ 22300745198530623141535718272648361505980416.0,
- /* pow(16.0, 37.0) */ 356811923176489970264571492362373784095686656.0,
- /* pow(16.0, 38.0) */ 5708990770823839524233143877797980545530986496.0,
- /* pow(16.0, 39.0) */ 91343852333181432387730302044767688728495783936.0,
- /* pow(16.0, 40.0) */ 1461501637330902918203684832716283019655932542976.0,
- /* pow(16.0, 41.0) */ 23384026197294446691258957323460528314494920687616.0,
- /* pow(16.0, 42.0) */ 374144419156711147060143317175368453031918731001856.0,
- /* pow(16.0, 43.0) */ 5986310706507378352962293074805895248510699696029696.0,
- /* pow(16.0, 44.0) */ 95780971304118053647396689196894323976171195136475136.0,
- /* pow(16.0, 45.0) */ 1532495540865888858358347027150309183618739122183602176.0,
- /* pow(16.0, 46.0) */ 24519928653854221733733552434404946937899825954937634816.0,
- /* pow(16.0, 47.0) */ 392318858461667547739736838950479151006397215279002157056.0,
- /* pow(16.0, 48.0) */ 6277101735386680763835789423207666416102355444464034512896.0,
- /* pow(16.0, 49.0) */ 100433627766186892221372630771322662657637687111424552206336.0,
- /* pow(16.0, 50.0) */ 1606938044258990275541962092341162602522202993782792835301376.0,
- /* pow(16.0, 51.0) */ 25711008708143844408671393477458601640355247900524685364822016.0,
- /* pow(16.0, 52.0) */ 411376139330301510538742295639337626245683966408394965837152256.0,
- /* pow(16.0, 53.0) */ 6582018229284824168619876730229402019930943462534319453394436096.0,
- /* pow(16.0, 54.0) */ 105312291668557186697918027683670432318895095400549111254310977536.0,
- /* pow(16.0, 55.0) */ 1684996666696914987166688442938726917102321526408785780068975640576.0,
- /* pow(16.0, 56.0) */ 26959946667150639794667015087019630673637144422540572481103610249216.0,
- /* pow(16.0, 57.0) */ 431359146674410236714672241392314090778194310760649159697657763987456.0,
- /* pow(16.0, 58.0) */ 6901746346790563787434755862277025452451108972170386555162524223799296.0,
- /* pow(16.0, 59.0) */ 110427941548649020598956093796432407239217743554726184882600387580788736.0,
- /* pow(16.0, 60.0) */ 1766847064778384329583297500742918515827483896875618958121606201292619776.0,
- /* pow(16.0, 61.0) */ 28269553036454149273332760011886696253239742350009903329945699220681916416.0,
- /* pow(16.0, 62.0) */ 452312848583266388373324160190187140051835877600158453279131187530910662656.0,
- /* pow(16.0, 63.0) */ 7237005577332262213973186563042994240829374041602535252466099000494570602496.0,
- /* pow(16.0, 64.0) */ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
- /* pow(16.0, 65.0) */ 1852673427797059126777135760139006525652319754650249024631321344126610074238976.0,
- /* pow(16.0, 66.0) */ 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0,
- /* pow(16.0, 67.0) */ 474284397516047136454946754595585670566993857190463750305618264096412179005177856.0,
- /* pow(16.0, 68.0) */ 7588550360256754183279148073529370729071901715047420004889892225542594864082845696.0,
- /* pow(16.0, 69.0) */ 121416805764108066932466369176469931665150427440758720078238275608681517825325531136.0,
- /* pow(16.0, 70.0) */ 1942668892225729070919461906823518906642406839052139521251812409738904285205208498176.0,
-};
-
-static int _pow2tab_size = sizeof(_pow2tab)/sizeof(double);
-
-void gen_pow2tab(void)
-{
- int jloop;
-
- for ( jloop = 0; jloop < 158; jloop++ )
- printf(" /* pow(2.0, %2d.0) */ %.1f,\n", jloop, pow(2.0, (double) jloop));
-}
-
-
-void gen_pow16tab(void)
-{
- double pval;
- int iexp;
-
- for ( iexp = 0; iexp < 71; iexp++ )
- {
- pval = pow(16.0, (double)(iexp));
- printf(" /* pow(16.0, %2d.0) */ %.1f,\n", iexp, pval);
- }
-}
-
-
-double intpow2(int x)
-{
- if ( x < _pow2tab_size )
- return (_pow2tab[x]);
- else
- return (pow(2.0, (double) x));
-}
+#ifndef CODEC_COMMON_H
+#define CODEC_COMMON_H
+#define gribSwapByteOrder_uint16(ui16) ((uint16_t)((ui16<<8) | (ui16>>8)))
+#endif /* CODEC_COMMON_H */
/*
+icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
+ result on hama2 (icc 16.0.0):
+ float:
+minmax_val: fmin: -500000 fmax: 499999 time: 0.63s
+ double:
+minmax_val: fmin: -500000 fmax: 499999 time: 2.98s
+orig : fmin: -500000 fmax: 499999 time: 2.83s
+simd : fmin: -500000 fmax: 499999 time: 2.82s
+avx : fmin: -500000 fmax: 499999 time: 3.17s
+
gcc -g -Wall -O3 -march=native -std=c99 -DTEST_MINMAXVAL minmax_val.c
result on bailung (gcc 4.8.2):
orig : fmin: -500000 fmax: 499999 time: 4.82s
@@ -682,16 +429,6 @@ icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp
simd : fmin: -500000 fmax: 499999 time: 2.83s
avx : fmin: -500000 fmax: 499999 time: 2.92s
-icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_MINMAXVAL -openmp -DOMP_SIMD minmax_val.c
- result on hama (icc 15.0.1):
- float:
- minmax_val: fmin: -500000 fmax: 499999 time: 0.60s
- double:
- minmax_val: fmin: -500000 fmax: 499999 time: 3.06s
- orig : fmin: -500000 fmax: 499999 time: 2.66s
- simd : fmin: -500000 fmax: 499999 time: 6.65s
- avx : fmin: -500000 fmax: 499999 time: 3.11s
-
xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_MINMAXVAL minmax_val.c
result on blizzard (xlc 12):
orig : fmin: -500000 fmax: 499999 time: 7.26s
@@ -937,10 +674,9 @@ void sse2_minmax_val_double(const double *restrict buf, size_t nframes, double *
#if defined(_ARCH_PWR6)
static
-void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void pwr6_minmax_val_double_unrolled6(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
#define __UNROLL_DEPTH_1 6
- size_t datasize = idatasize;
// to allow pipelining we have to unroll
@@ -984,9 +720,9 @@ void pwr6_minmax_val_double_unrolled6(const double *restrict data, long idatasiz
#if defined(TEST_MINMAXVAL) && defined(__GNUC__)
static
-void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
static
-void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax) __attribute__ ((noinline));
+void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax) __attribute__ ((noinline));
#endif
#if defined(GNUC_PUSH_POP)
@@ -994,10 +730,8 @@ void minmax_val_double_simd(const double *restrict data, long idatasize, double
#pragma GCC optimize ("O3", "fast-math")
#endif
static
-void minmax_val_double_orig(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_orig(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
- size_t i;
- size_t datasize = idatasize;
double dmin = *fmin, dmax = *fmax;
#if defined(CRAY)
@@ -1009,7 +743,7 @@ void minmax_val_double_orig(const double *restrict data, long idatasize, double
#elif defined (__ICC)
#pragma ivdep
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -1022,8 +756,7 @@ void minmax_val_double_orig(const double *restrict data, long idatasize, double
static
void minmax_val_float(const float *restrict data, long idatasize, float *fmin, float *fmax)
{
- size_t i;
- size_t datasize = idatasize;
+ size_t datasize = (size_t)idatasize;
float dmin = *fmin, dmax = *fmax;
#if defined(CRAY)
@@ -1035,7 +768,7 @@ void minmax_val_float(const float *restrict data, long idatasize, float *fmin, f
#elif defined (__ICC)
#pragma ivdep
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -1051,25 +784,19 @@ void minmax_val_float(const float *restrict data, long idatasize, float *fmin, f
// TEST
#if defined(OMP_SIMD)
-//#pragma omp declare reduction(xmin : double : omp_out = omp_in > omp_out ? omp_out : omp_in) initializer( omp_priv = { 1.e300 })
-//#pragma omp declare reduction(xmax : double : omp_out = omp_in < omp_out ? omp_out : omp_in) initializer( omp_priv = { -1.e300 })
-
#if defined(GNUC_PUSH_POP)
#pragma GCC push_options
#pragma GCC optimize ("O3", "fast-math")
#endif
static
-void minmax_val_double_simd(const double *restrict data, long idatasize, double *fmin, double *fmax)
+void minmax_val_double_simd(const double *restrict data, size_t datasize, double *fmin, double *fmax)
{
- size_t i;
- size_t datasize = idatasize;
double dmin = *fmin, dmax = *fmax;
#if defined(_OPENMP)
- //#pragma omp simd reduction(xmin:dmin) reduction(xmax:dmax)
-#pragma omp simd
+#pragma omp simd reduction(min:dmin) reduction(max:dmax)
#endif
- for ( i = 0; i < datasize; ++i )
+ for ( size_t i = 0; i < datasize; ++i )
{
dmin = dmin < data[i] ? dmin : data[i];
dmax = dmax > data[i] ? dmax : data[i];
@@ -1089,9 +816,9 @@ void minmax_val_double(const double *restrict data, long idatasize, double *fmin
#if defined(_GET_X86_COUNTER) || defined(_GET_MACH_COUNTER)
uint64_t start_minmax, end_minmax;
#endif
- size_t datasize = idatasize;
+ size_t datasize = (size_t)idatasize;
- if ( idatasize < 1 ) return;
+ if ( idatasize >= 1 ) ; else return;
#if defined(_GET_X86_COUNTER)
start_minmax = _rdtsc();
@@ -1200,7 +927,7 @@ int main(void)
{
float fmin, fmax;
- float *data_sp = (float*) Malloc(datasize*sizeof(float));
+ float *data_sp = (float*) malloc(datasize*sizeof(float));
for ( long i = 0; i < datasize/2; i++ ) data_sp[i] = (float) (i);
for ( long i = datasize/2; i < datasize; i++ ) data_sp[i] = (float) (-datasize + i);
@@ -1215,12 +942,12 @@ int main(void)
}
t_end = dtime();
printf("minmax_val: fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
- Free(data_sp);
+ free(data_sp);
}
{
double fmin, fmax;
- double *data_dp = (double*) Malloc(datasize*sizeof(double));
+ double *data_dp = (double*) malloc(datasize*sizeof(double));
// for ( long i = datasize-1; i >= 0; i-- ) data[i] = (double) (-datasize/2 + i);
for ( long i = 0; i < datasize/2; i++ ) data_dp[i] = (double) (i);
@@ -1286,7 +1013,7 @@ int main(void)
t_end = dtime();
printf("pwr6u6 : fmin: %ld fmax: %ld time: %6.2fs\n", (long)fmin, (long) fmax, t_end-t_begin);
#endif
- Free(data_dp);
+ free(data_dp);
}
return (0);
@@ -1297,20 +1024,48 @@ int main(void)
#undef _ENABLE_AVX
#undef _ENABLE_SSE2
#undef GNUC_PUSH_POP
-/*
+/*
+### new version with gribSwapByteOrder_uint16()
icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
- result on hama (icc 15.0.1):
- float:
- orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.7936s
+ result on hama2 (icc 16.0.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 1.8731s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 2.0898s
double:
- orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 13.6093s
- avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.90009s
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.68089s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.30798s
+ avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.23864s
+
+gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama2 (gcc 5.2.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.96739s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 4.30871s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 6.24448s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.66679s
-gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
- result on hama (gcc 4.8.2):
- orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 16.0471s
- sse41 : val1: 1 val2: 1 val3: 2 valn: 66 time: 15.4391s
+###
+icc -g -Wall -O3 -march=native -std=c99 -qopt-report=5 -DTEST_ENCODE encode_array.c
+ result on hama2 (icc 16.0.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.10691s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 8.63584s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 13.5768s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 9.17742s
+ avx: val1: 1 val2: 1 val3: 2 valn: 66 time: 3.9488s
+
+gcc -g -Wall -O3 -std=c99 -DTEST_ENCODE encode_array.c
+ result on hama2 (gcc 5.2.0):
+ float:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 5.32775s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.87125s
+ double:
+ orig: val1: 1 val2: 1 val3: 2 valn: 66 time: 7.85873s
+unrolled: val1: 1 val2: 1 val3: 2 valn: 66 time: 12.9979s
+###
gcc -g -Wall -O3 -march=native -std=c99 -DTEST_ENCODE encode_array.c
result on bailung (gcc 4.7):
orig : val1: 1 val2: 1 val3: 2 valn: 66 time: 8.4166s
@@ -1675,14 +1430,11 @@ void pout(char *name, int s, unsigned char *lgrib, long datasize, double tt)
int main(void)
{
long datasize = 1000000;
- float *dataf = NULL;
- double *data = NULL;
double t_begin, t_end;
- unsigned char *lgrib;
- dataf = (float*) Malloc(datasize*sizeof(float));
- data = (double*) Malloc(datasize*sizeof(double));
- lgrib = (unsigned char*) Malloc(2*datasize*sizeof(unsigned char));
+ float *dataf = (float*) malloc(datasize*sizeof(float));
+ double *data = (double*) malloc(datasize*sizeof(double));
+ unsigned char *lgrib = (unsigned char*) malloc(2*datasize*sizeof(unsigned char));
for ( long i = 0; i < datasize; ++i ) dataf[i] = (float) (-datasize/2 + i);
for ( long i = 0; i < datasize; ++i ) data[i] = (double) (-datasize/2 + i);
@@ -1700,7 +1452,6 @@ int main(void)
encode_array_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
}
-
#if defined(__ICC)
printf("icc\n");
#elif defined(__clang__)
@@ -1776,240 +1527,6 @@ int main(void)
#undef DISABLE_SIMD
#undef _ENABLE_AVX
#undef _ENABLE_SSE4_1
-//#undef _GET_X86_COUNTER
-//#undef _GET_MACH_COUNTER
-//#undef _GET_IBM_COUNTER
-//#undef _ARCH_PWR6
-
-#if defined _GET_IBM_COUNTER
-#include <libhpc.h>
-#elif defined _GET_X86_COUNTER
-#include <x86intrin.h>
-#elif defined _GET_MACH_COUNTER
-#include <mach/mach_time.h>
-#endif
-
-#ifdef __cplusplus
-#define __STDC_FORMAT_MACROS
-#endif
-#include <inttypes.h>
-
-#if defined(__GNUC__) && (__GNUC__ >= 4)
-#elif defined(__ICC) && (__ICC >= 1100)
-#elif defined(__clang__)
-#else
-#define DISABLE_SIMD
-#endif
-
-#define DISABLE_SIMD
-
-#ifdef DISABLE_SIMD
-# ifdef ENABLE_AVX
-# define _ENABLE_AVX
-# endif
-# ifdef ENABLE_SSE4_1
-# define _ENABLE_SSE4_1
-# endif
-#endif
-
-#ifndef DISABLE_SIMD
-# ifdef __AVX__
-# define _ENABLE_AVX
-# endif
-# ifdef __SSE4_1__
-# define _ENABLE_SSE4_1
-# endif
-#endif
-
-#if defined _ENABLE_AVX
-#include <immintrin.h>
-#elif defined _ENABLE_SSE4_1
-#include <smmintrin.h>
-#endif
-
-#if defined _ENABLE_AVX
-
-static
-void avx_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
- double * restrict fpdata, double fmin, double zscale)
-{
- size_t i, j;
- size_t nframes = datasize;
- size_t residual;
- size_t ofs;
-
- double dval;
-
- double *data = fpdata;
- __m128i *sgrib;
-
- __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
-
- __m256d ymm0 = _mm256_set1_pd(fmin);
- __m256d ymm1 = _mm256_set1_pd(zscale);
-
- __m128i xmm0, xmm1, xmm2, xmm3;
- __m256d ymm2, ymm3;
-
- i = -1;
- while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
- {
- i++;
- dval = (((int)igrib[2*i] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- data++;
- nframes--;
- }
-
- if (i == -1) i = 0;
- sgrib = (__m128i *) (igrib+i);
-
- while (nframes >= 16)
- {
- xmm0 = _mm_loadu_si128((__m128i *) sgrib);
- xmm0 = _mm_shuffle_epi8(xmm0, mask);
- xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
- xmm2 = _mm_cvtepu16_epi32(xmm0);
- xmm3 = _mm_cvtepu16_epi32(xmm1);
-
- ymm2 = _mm256_cvtepi32_pd(xmm2);
- ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
- (void) _mm256_stream_pd(data, ymm2);
- ymm3 = _mm256_cvtepi32_pd(xmm3);
- ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
- (void) _mm256_stream_pd(data+4, ymm3);
-
- xmm0 = _mm_loadu_si128((__m128i *) sgrib + 1);
- xmm0 = _mm_shuffle_epi8(xmm0, mask);
- xmm1 = _mm_shuffle_epi32(xmm0, _MM_SHUFFLE(1, 0, 3, 2));
- xmm2 = _mm_cvtepu16_epi32(xmm0);
- xmm3 = _mm_cvtepu16_epi32(xmm1);
-
- ymm2 = _mm256_cvtepi32_pd(xmm2);
- ymm2 = _mm256_add_pd(_mm256_mul_pd(ymm2, ymm1), ymm0);
- (void) _mm256_stream_pd(data+8, ymm2);
- ymm3 = _mm256_cvtepi32_pd(xmm3);
- ymm3 = _mm256_add_pd(_mm256_mul_pd(ymm3, ymm1), ymm0);
- (void) _mm256_stream_pd(data+12, ymm3);
-
- data += 16;
- sgrib += 2;
- nframes -= 16;
- }
-
- residual = nframes;
- ofs = datasize - residual;
- for ( j = 0; j < residual; j++ )
- {
- dval = (((int)igrib[2*(ofs+j)] << 8) | (int)igrib[2*(ofs+j)+1]);
- fpdata[ofs+j] = fmin + zscale * dval;
- }
-
- return;
-}
-
-#elif defined _ENABLE_SSE4_1
-
-static
-void sse41_decode_array_2byte_double(size_t datasize, const unsigned char * restrict igrib,
- double * restrict fpdata, double fmin, double zscale)
-{
- size_t i, j;
- size_t nframes = datasize;
- size_t residual;
- size_t ofs;
-
- double dval;
-
- double *data = fpdata;
- __m128i *sgrib;
-
- __m128i mask = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
- __m128d dmm8 = _mm_set1_pd(fmin);
- __m128d dmm9 = _mm_set1_pd(zscale);
-
- __m128i xmm4, xmm5;
- __m128i xmm6, xmm7;
-
- __m128d dmm0, dmm1, dmm2, dmm3;
- __m128d dmm4, dmm5, dmm6, dmm7;
-
- i = -1;
- while ( ((unsigned long) data) % 32 != 0 && datasize > 0)
- {
- i++;
- dval = (((int)igrib[2*i] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- data++;
- nframes--;
- }
-
- if (i == -1) i = 0;
- sgrib = (__m128i *) (igrib+i);
-
- while (nframes >= 16)
- {
- xmm5 = _mm_loadu_si128((__m128i *) sgrib);
- xmm5 = _mm_shuffle_epi8(xmm5, mask);
- xmm4 = _mm_srli_si128(xmm5, 8);
- xmm6 = _mm_cvtepu16_epi32(xmm5);
- dmm0 = _mm_cvtepi32_pd(xmm6);
- dmm0 = _mm_add_pd(_mm_mul_pd(dmm0, dmm9), dmm8);
- (void) _mm_stream_pd(data, dmm0);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm1 = _mm_cvtepi32_pd(xmm7);
- dmm1 = _mm_add_pd(_mm_mul_pd(dmm1, dmm9), dmm8);
- (void) _mm_stream_pd(data+2, dmm1);
- xmm6 = _mm_cvtepu16_epi32(xmm4);
- dmm2 = _mm_cvtepi32_pd(xmm6);
- dmm2 = _mm_add_pd(_mm_mul_pd(dmm2, dmm9), dmm8);
- (void) _mm_stream_pd(data+4, dmm2);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm3 = _mm_cvtepi32_pd(xmm7);
- dmm3 = _mm_add_pd(_mm_mul_pd(dmm3, dmm9), dmm8);
- (void) _mm_stream_pd(data+6, dmm3);
-
- xmm5 = _mm_loadu_si128((__m128i *) sgrib+1);
- xmm5 = _mm_shuffle_epi8(xmm5, mask);
- xmm4 = _mm_srli_si128(xmm5, 8);
- xmm6 = _mm_cvtepu16_epi32(xmm5);
- dmm4 = _mm_cvtepi32_pd(xmm6);
- dmm4 = _mm_add_pd(_mm_mul_pd(dmm4, dmm9), dmm8);
- (void) _mm_stream_pd(data+8, dmm4);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm5 = _mm_cvtepi32_pd(xmm7);
- dmm5 = _mm_add_pd(_mm_mul_pd(dmm5, dmm9), dmm8);
- (void) _mm_stream_pd(data+10, dmm5);
- xmm6 = _mm_cvtepu16_epi32(xmm4);
- dmm6 = _mm_cvtepi32_pd(xmm6);
- dmm6 = _mm_add_pd(_mm_mul_pd(dmm6, dmm9), dmm8);
- (void) _mm_stream_pd(data+12, dmm6);
- xmm7 = _mm_srli_si128(xmm6, 8);
- dmm7 = _mm_cvtepi32_pd(xmm7);
- dmm7 = _mm_add_pd(_mm_mul_pd(dmm7, dmm9), dmm8);
- (void) _mm_stream_pd(data+14, dmm7);
-
- data += 16;
- sgrib += 2;
- nframes -= 16;
- }
-
- residual = nframes;
- ofs = datasize - residual;
- for ( j = 0; j < residual; j++ )
- {
- dval = (((int)igrib[2*(ofs+j)] << 8) | (int)igrib[2*(ofs+j)+1]);
- fpdata[ofs+j] = fmin + zscale * dval;
- }
-
- return;
-}
-
-#endif
-
-#undef DISABLE_SIMD
-#undef _ENABLE_AVX
-#undef _ENABLE_SSE4_1
void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
@@ -2080,12 +1597,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
- replace 1.0 / pow(16.0, (double)(iexp - 70)) by rpow16m70tab[iexp]
*/
- double rpowref;
- double zref, zeps;
- int iexp, isign;
- int iround;
// extern int CGRIBEX_Debug;
- extern const double _pow16tab[71];
/* ----------------------------------------------------------------- */
/* Section 1 . Initialise */
@@ -2093,7 +1605,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* Check conversion type parameter. */
- iround = kround;
+ int iround = kround;
if ( iround != 0 && iround != 1 )
{
Error("Invalid conversion type = %d", iround);
@@ -2118,42 +1630,35 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* ----------------------------------------------------------------- */
/* Section 3 . Convert other values. */
/* ----------------------------------------------------------------- */
+ {
+ double zeps = kbits != 32 ? 1.0e-12 : 1.0e-8;
+ double zref = pval;
- zeps = 1.0e-12;
- if ( kbits == 32 ) zeps = 1.0e-8;
- zref = pval;
-
- /* Sign of value. */
+ /* Sign of value. */
- isign = 0;
- if ( zref < 0.0 )
- {
- isign = 128;
- zref = - zref;
- }
+ int isign = zref >= 0.0 ? 0 : 128;
+ zref = fabs(zref);
- /* Exponent. */
+ /* Exponent. */
- iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
+ int iexp = (int) (log(zref)/log(16.0) + 65.0 + zeps);
- /* only ANSI C99 has log2 */
- /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
+ /* only ANSI C99 has log2 */
+ /* iexp = (int) (log2(zref) * 0.25 + 65.0 + zeps); */
- if ( iexp < 0 ) iexp = 0;
- if ( iexp > 127 ) iexp = 127;
+ if ( iexp < 0 ) iexp = 0;
+ if ( iexp > 127 ) iexp = 127;
- /*
- rpowref = zref / pow(16.0, (double)(iexp - 70));
- */
+ double rpowref;
+ /*
+ rpowref = zref / pow(16.0, (double)(iexp - 70));
+ */
- if ( (iexp - 70) < 0 )
- rpowref = zref * _pow16tab[-(iexp - 70)];
- else
- rpowref = zref / _pow16tab[(iexp - 70)];
+ rpowref = ldexp(zref, 4 * -(iexp - 70));
- /* Mantissa. */
+ /* Mantissa. */
- if ( iround == 0 )
+ if ( iround == 0 )
{
/* Closest number in GRIB format less than original number. */
/* Truncate for positive numbers. */
@@ -2164,7 +1669,7 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
else
*kmant = (int)lround(rpowref + 0.5);
}
- else
+ else
{
/* Closest number in GRIB format to the original number */
/* (equal to, greater than or less than original number). */
@@ -2172,12 +1677,12 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
*kmant = (int)lround(rpowref);
}
- /* Check that mantissa value does not exceed 24 bits. */
- /* If it does, adjust the exponent upwards and recalculate */
- /* the mantissa. */
- /* 16777215 = 2**24 - 1 */
+ /* Check that mantissa value does not exceed 24 bits. */
+ /* If it does, adjust the exponent upwards and recalculate */
+ /* the mantissa. */
+ /* 16777215 = 2**24 - 1 */
- if ( *kmant > 16777215 )
+ if ( *kmant > 16777215 )
{
LABEL350:
@@ -2187,47 +1692,44 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
/* Check for exponent overflow during adjustment */
if ( iexp > 127 )
- {
- Message("Exponent overflow");
- Message("Original number = %30.20f", pval);
- Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
- isign, iexp, *kmant);
+ {
+ Message("Exponent overflow");
+ Message("Original number = %30.20f", pval);
+ Message("Sign = %3d, Exponent = %3d, Mantissa = %12d",
+ isign, iexp, *kmant);
- Error("Exponent overflow");
+ Error("Exponent overflow");
- /* If not aborting, arbitrarily set value to zero */
+ /* If not aborting, arbitrarily set value to zero */
- Message("Value arbitrarily set to zero.");
- *kexp = 0;
- *kmant = 0;
- // iexp = 0;
- // isign = 0;
- goto LABEL900;
- }
+ Message("Value arbitrarily set to zero.");
+ *kexp = 0;
+ *kmant = 0;
+ // iexp = 0;
+ // isign = 0;
+ goto LABEL900;
+ }
- if ( (iexp - 70) < 0 )
- rpowref = zref * _pow16tab[-(iexp - 70)];
- else
- rpowref = zref / _pow16tab[(iexp - 70)];
+ rpowref = ldexp(zref, 4 * -(iexp - 70));
if ( iround == 0 )
- {
- /* Closest number in GRIB format less than original number. */
- /* Truncate for positive numbers. */
- /* Round up for negative numbers. */
+ {
+ /* Closest number in GRIB format less than original number. */
+ /* Truncate for positive numbers. */
+ /* Round up for negative numbers. */
- if ( isign == 0 )
- *kmant = (int)rpowref;
- else
- *kmant = (int)lround(rpowref + 0.5);
- }
+ if ( isign == 0 )
+ *kmant = (int)rpowref;
+ else
+ *kmant = (int)lround(rpowref + 0.5);
+ }
else
- {
- /* Closest number in GRIB format to the original number */
- /* (equal to, greater or less than original number). */
+ {
+ /* Closest number in GRIB format to the original number */
+ /* (equal to, greater or less than original number). */
- *kmant = (int)lround(rpowref);
- }
+ *kmant = (int)lround(rpowref);
+ }
/* Repeat calculation (with modified exponent) if still have */
/* mantissa overflow. */
@@ -2235,9 +1737,10 @@ void confp3(double pval, int *kexp, int *kmant, int kbits, int kround)
if ( *kmant > 16777215 ) goto LABEL350;
}
- /* Add sign bit to exponent. */
+ /* Add sign bit to exponent. */
- *kexp = iexp + isign;
+ *kexp = iexp + isign;
+ }
/* ----------------------------------------------------------------- */
/* Section 9. Return */
@@ -2260,6 +1763,7 @@ LABEL900:
*/
return;
} /* confp3 */
+#include <math.h>
double decfp2(int kexp, int kmant)
@@ -2321,7 +1825,7 @@ double decfp2(int kexp, int kmant)
Uwe Schulzweida MPIfM 01/04/2001
- Convert to C from EMOS library version 130
-
+
Uwe Schulzweida MPIfM 02/08/2002
- speed up by factor 2 on NEC SX6
@@ -2330,10 +1834,7 @@ double decfp2(int kexp, int kmant)
*/
double pval;
- int iexp, isign;
//extern int CGRIBEX_Debug;
- extern const double _pow16tab[71];
-
/* ----------------------------------------------------------------- */
/* Section 1 . Convert value of 0.0. Ignore sign bit. */
/* ----------------------------------------------------------------- */
@@ -2354,14 +1855,10 @@ double decfp2(int kexp, int kmant)
/* Sign of value. */
- iexp = kexp;
- isign = 1;
+ int iexp = kexp,
+ isign = (iexp < 128) * 2 - 1;
- if ( iexp >= 128 )
- {
- iexp -= 128;
- isign = -1;
- }
+ iexp -= iexp < 128 ? 0 : 128;
/* Decode value. */
@@ -2369,12 +1866,7 @@ double decfp2(int kexp, int kmant)
iexp -= 64;
- if ( iexp < 0 )
- pval = 1./_pow16tab[-iexp];
- else
- pval = _pow16tab[iexp];
-
- pval *= isign * POW_2_M24 * kmant;
+ pval = ldexp(1.0, 4 * iexp) * isign * POW_2_M24 * kmant;
/* ----------------------------------------------------------------- */
/* Section 9. Return to calling routine. */
@@ -2574,7 +2066,7 @@ void gprintf(const char *caller, const char *fmt, ...)
void
gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
double *fsec3, int *isec4, double *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
+ int kleng, int *kword, const char *hoper, int *kret)
{
int yfunc = *hoper;
@@ -2605,7 +2097,7 @@ gribExDP(int *isec0, int *isec1, int *isec2, double *fsec2, int *isec3,
void
gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
float *fsec3, int *isec4, float *fsec4, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
+ int kleng, int *kword, const char *hoper, int *kret)
{
int yfunc = *hoper;
@@ -2632,86 +2124,6 @@ gribExSP(int *isec0, int *isec1, int *isec2, float *fsec2, int *isec3,
}
}
-
-void
-gribExSP_old(int *isec0, int *isec1, int *isec2, float *fsec2sp, int *isec3,
- float *fsec3sp, int *isec4, float *fsec4sp, int klenp, int *kgrib,
- int kleng, int *kword, char *hoper, int *kret)
-{
- int inum, j;
- double fsec2dp[1024];
- double fsec3dp[2];
- double *fsec4dp = NULL;
- int yfunc = *hoper;
-
- if ( yfunc == 'C' )
- {
- inum = 10 + isec2[11];
- for ( j = 0; j < inum; j++ ) fsec2dp[j] = fsec2sp[j];
-
- fsec3dp[0] = fsec3sp[0];
- fsec3dp[1] = fsec3sp[1];
-
- inum = isec4[0];
- fsec4dp = (double*) Malloc(inum*sizeof(double));
- if ( fsec4dp == NULL ) SysError("No Memory!");
-
- for ( j = 0; j < inum; j++ ) fsec4dp[j] = fsec4sp[j];
-
- gribExDP(isec0, isec1, isec2, fsec2dp, isec3,
- fsec3dp, isec4, fsec4dp, klenp, kgrib,
- kleng, kword, hoper, kret);
-
- Free(fsec4dp);
- }
- else if ( yfunc == 'D' || yfunc == 'J' || yfunc == 'R' )
- {
- if ( yfunc == 'D' || yfunc == 'R' )
- {
- fsec4dp = (double*) Malloc(klenp*sizeof(double));
- if ( fsec4dp == NULL ) SysError("No Memory!");
- }
-
- for ( j = 0; j < 10; j++ ) fsec2dp[j] = 0.0;
- for ( j = 0; j < 2; j++ ) fsec3dp[j] = 0.0;
-
- gribExDP(isec0, isec1, isec2, fsec2dp, isec3,
- fsec3dp, isec4, fsec4dp, klenp, kgrib,
- kleng, kword, hoper, kret);
-
- inum = 10 + isec2[11];
- for ( j = 0; j < inum; j++ ) fsec2sp[j] = fsec2dp[j];
-
- fsec3sp[0] = fsec3dp[0];
- fsec3sp[1] = fsec3dp[1];
-
- if ( yfunc == 'D' || yfunc == 'R' )
- {
- inum = isec4[0];
- for ( j = 0; j < inum; j++ )
- {
- if ( fsec4dp[j] > -FLT_MIN && fsec4dp[j] < FLT_MIN )
- fsec4sp[j] = 0;
- else if ( fsec4dp[j] > FLT_MAX )
- fsec4sp[j] = FLT_MAX;
- else if ( fsec4dp[j] < -FLT_MAX )
- fsec4sp[j] = -FLT_MAX;
- else
- fsec4sp[j] = fsec4dp[j];
- }
-
- Free(fsec4dp);
- }
- }
- else if ( yfunc == 'V' )
- fprintf(stderr, " c-gribex: Version is %s\n", cgribexLibraryVersion());
- else
- {
- Error("oper %c unsupported!", yfunc);
- *kret=-9;
- }
-}
-
int CGRIBEX_Fix_ZSE = 0; /* 1: Fix ZeroShiftError of simple packed spherical harmonics */
int CGRIBEX_Const = 0; /* 1: Don't pack constant fields on regular grids */
int CGRIBEX_Debug = 0; /* 1: Debugging */
@@ -3992,7 +3404,7 @@ void gribPrintSec2SP(int *isec0, int *isec2, float *fsec2sp)
inum = 10 + isec2[11];
- fsec2 = (double*) Malloc(inum*sizeof(double));
+ fsec2 = (double*) Malloc((size_t)inum*sizeof(double));
if ( fsec2 == NULL ) SysError("No Memory!");
for ( j = 0; j < inum; j++ )
@@ -4340,29 +3752,30 @@ int gribCheckSeek(int fileID, long *offset, int *version)
int gribFileSeekOld(int fileID, long *offset)
{
/* position file pointer after GRIB */
- int ch;
- int buffersize = 4096;
- unsigned char buffer[4096];
+ enum { buffersize = 4096 };
+ unsigned char buffer[buffersize];
int retry = 4096;
- int i;
*offset = 0;
void *fileptr = filePtr(fileID);
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[0] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[1] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[2] = ch;
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[3] = ch;
+ for ( size_t i = 0; i < 4; ++i)
+ {
+ int ch = filePtrGetc(fileptr);
+ if ( ch == EOF ) return (-1);
+ buffer[i] = (unsigned char)ch;
+ }
/*
fileRead(fileID, buffer, 4);
*/
while ( retry-- )
{
+ size_t i;
for ( i = 0; i < buffersize-4; ++i )
{
- if (buffer[i ] == 'G' &&
+ if (buffer[i ] == 'G' &&
buffer[i+1] == 'R' &&
buffer[i+2] == 'I' &&
buffer[i+3] == 'B')
@@ -4373,7 +3786,7 @@ int gribFileSeekOld(int fileID, long *offset)
}
else
{
- ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = ch;
+ int ch = filePtrGetc(fileptr); if ( ch == EOF ) return (-1); buffer[i+4] = (unsigned char)ch;
(*offset)++;
}
}
@@ -4427,13 +3840,13 @@ int gribFileSeek(int fileID, long *offset)
int gribFileSeekTest(int fileID, long *offset)
{
/* position file pointer after GRIB */
- const long GRIB = 0x47524942;
+ const long GRIB = 0x47524942L;
long code = 0;
int ch;
int i = 0;
- const int buffersize = 8;
- unsigned char buffer[8];
- int retry = 4096*4096;
+ enum { buffersize = 8 };
+ unsigned char buffer[buffersize];
+ unsigned long retry = 4096L*4096L;
int nread = 0;
*offset = 0;
@@ -4450,7 +3863,7 @@ int gribFileSeekTest(int fileID, long *offset)
}
ch = buffer[i++];
- code = ( (code << 8) + ch ) & 0xFFFFFFFF;
+ code = ( (code << 8) + ch ) & 0xFFFFFFFFL;
if ( code == GRIB )
{
@@ -4471,6 +3884,14 @@ int gribFileSeekTest(int fileID, long *offset)
return 1;
}
+static inline int
+read3ByteMSBFirst(void *fileptr)
+{
+ unsigned b1 = (unsigned)(filePtrGetc(fileptr));
+ unsigned b2 = (unsigned)(filePtrGetc(fileptr));
+ unsigned b3 = (unsigned)(filePtrGetc(fileptr));
+ return (int)((b1 << 16) + (b2 << 8) + b3);
+}
int gribReadSize(int fileID)
{
@@ -4496,7 +3917,7 @@ int gribReadSize(int fileID)
{
int pdssize = 0, gdssize = 0, bmssize = 0, bdssize = 0;
int issize = 4, essize = 4;
- int flag;
+ int flag = 0;
pdssize = gribsize;
fileSetPos(fileID, (off_t) 3, SEEK_CUR);
@@ -4508,22 +3929,19 @@ int gribReadSize(int fileID)
if ( flag & 128 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- gdssize = (b1 << 16) + (b2 << 8) + b3;
+ gdssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("gdssize = %d", gdssize);
}
if ( flag & 64 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bmssize = (b1 << 16) + (b2 << 8) + b3;
+ bmssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("bmssize = %d", bmssize);
}
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bdssize = (b1 << 16) + (b2 << 8) + b3;
+ bdssize = read3ByteMSBFirst(fileptr);
if ( CGRIBEX_Debug ) Message("bdssize = %d", bdssize);
gribsize = issize + pdssize + gdssize + bmssize + bdssize + essize;
@@ -4536,8 +3954,7 @@ int gribReadSize(int fileID)
int issize = 4, essize = 4;
int flag;
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- pdssize = (b1 << 16) + (b2 << 8) + b3;
+ pdssize = read3ByteMSBFirst(fileptr);
if ( CGRIBEX_Debug ) Message("pdssize = %d", pdssize);
for ( int i = 0; i < 5; ++i ) flag = filePtrGetc(fileptr);
@@ -4547,22 +3964,19 @@ int gribReadSize(int fileID)
if ( flag & 128 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- gdssize = (b1 << 16) + (b2 << 8) + b3;
+ gdssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) gdssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("gdssize = %d", gdssize);
}
if ( flag & 64 )
{
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bmssize = (b1 << 16) + (b2 << 8) + b3;
+ bmssize = read3ByteMSBFirst(fileptr);
fileSetPos(fileID, (off_t) bmssize-3, SEEK_CUR);
if ( CGRIBEX_Debug ) Message("bmssize = %d", bmssize);
}
- b1 = filePtrGetc(fileptr); b2 = filePtrGetc(fileptr); b3 = filePtrGetc(fileptr);
- bdssize = (b1 << 16) + (b2 << 8) + b3;
+ bdssize = read3ByteMSBFirst(fileptr);
bdssize = correct_bdslen(bdssize, gribsize, issize+pdssize+gdssize+bmssize);
if ( CGRIBEX_Debug ) Message("bdssize = %d", bdssize);
@@ -4631,7 +4045,7 @@ int gribRead(int fileID, unsigned char *buffer, size_t *buffersize)
if ( ierr == -1 ) { *buffersize = 0; return -1; }
else if ( ierr == 1 ) { *buffersize = 0; return -2; }
- size_t recSize = gribReadSize(fileID);
+ size_t recSize = (size_t)gribReadSize(fileID);
size_t readSize = recSize;
if ( readSize > *buffersize )
@@ -4662,7 +4076,7 @@ int gribWrite(int fileID, unsigned char *buffer, size_t buffersize)
{
int nwrite = 0;
- if ( (nwrite = fileWrite(fileID, buffer, buffersize)) != (int) buffersize )
+ if ( (nwrite = (int)(fileWrite(fileID, buffer, buffersize))) != (int) buffersize )
{
perror(__func__);
nwrite = -1;
@@ -4682,7 +4096,7 @@ int gribrec_len(unsigned b1, unsigned b2, unsigned b3)
*/
int needRescaling = b1 & (1 << 7);
- int gribsize = (((b1&127) << 16)+(b2<<8) + b3);
+ int gribsize = (int)((((b1&127) << 16)+(b2<<8) + b3));
if ( needRescaling ) gribsize *= 120;
@@ -5547,6 +4961,7 @@ void ref2ibm(double *pref, int kbits)
return;
} /* ref2ibm */
+#include <math.h>
#include <string.h>
@@ -5560,7 +4975,7 @@ int correct_bdslen(int bdslen, long recsize, long gribpos)
due to the count being only 24 bits. It is only possible because
the (default) rounding for GRIB products is 120 bytes.
*/
- if ( recsize > JP23SET ) bdslen = recsize - gribpos - bdslen;
+ if ( recsize > JP23SET ) bdslen = (int)(recsize - gribpos - bdslen);
return (bdslen);
}
@@ -5924,19 +5339,20 @@ int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
bufpointer[0], bufpointer[1], bufpointer[2], bufpointer[3]);
}
- bsf = BDS_BinScale;
- if ( bsf > 32767 ) bsf = 32768-bsf;
- bsf = pow(2.0,(double)bsf);
+ {
+ int bs = BDS_BinScale;
+ if ( bs > 32767 ) bs = 32768-bs;
+ bsf = ldexpf(1.0f, bs);
+ }
bignum[0] = dpos;
- if ( bms ) bignum[1] = bpos;
- else bignum[1] = -999;
+ bignum[1] = bms ? bpos : -999;
intnum[0] = BDS_NumBits;
/* fltnum[0] = 1.0; */
- fltnum[0] = pow(10.0, (double)PDS_DecimalScale);
+ fltnum[0] = powf(10.0f, (float)PDS_DecimalScale);
fltnum[1] = bsf;
- fltnum[2] = BDS_RefValue;
+ fltnum[2] = (float)BDS_RefValue;
/*
printf("intnum %d %d %d\n", intnum[0], intnum[1], intnum[2]);
printf("fltnum %g %g %g\n", fltnum[0], fltnum[1], fltnum[2]);
@@ -6077,7 +5493,7 @@ void gribPrintALL(int nrec, long offset, long recpos, long recsize, unsigned cha
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintALL(nrec, offset, recpos, recsize, gribbuffer);
@@ -6169,7 +5585,7 @@ void gribPrintPDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintPDS(nrec, recpos, recsize, gribbuffer);
@@ -6230,7 +5646,7 @@ void gribPrintGDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintGDS(nrec, recpos, recsize, gribbuffer);
@@ -6295,7 +5711,7 @@ void gribPrintBMS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintBMS(nrec, recpos, recsize, gribbuffer);
@@ -6385,7 +5801,7 @@ void gribPrintBDS(int nrec, long recpos, long recsize, unsigned char *gribbuffer
{
int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 0 || gribversion == 1 )
grib1PrintBDS(nrec, recpos, recsize, gribbuffer);
@@ -6448,7 +5864,6 @@ void gribCheck1(int nrec, long recpos, long recsize, unsigned char *gribbuffer)
static
void repair1(unsigned char *gbuf, long gbufsize)
{
- long i;
int nerr;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
/* int recLen; */
@@ -6504,15 +5919,13 @@ void repair1(unsigned char *gbuf, long gbufsize)
source = bds + datstart;
- sourceLen = ((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8;
+ sourceLen = (size_t)(((((bds_len - datstart)*8-bds_ubits)/bds_nbits)*bds_nbits)/8);
if ( bds_nbits == 24 )
{
- long nelem;
- unsigned char *pbuf;
- nelem = sourceLen/3;
- pbuf = (unsigned char*) Malloc(sourceLen);
- for ( i = 0; i < nelem; i++ )
+ unsigned char *pbuf = (unsigned char*) Malloc(sourceLen);;
+ size_t nelem = sourceLen/3;
+ for ( size_t i = 0; i < nelem; i++ )
{
pbuf[3*i ] = source[ i];
pbuf[3*i+1] = source[ nelem+i];
@@ -6620,9 +6033,8 @@ int gribGetZip(long recsize, unsigned char *gribbuffer, long *urecsize)
int bds_flag, lcompress;
long gribsize = 0;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
- int gribversion;
- gribversion = gribVersion(gribbuffer, recsize);
+ int gribversion = gribVersion(gribbuffer, (size_t)recsize);
if ( gribversion == 2 ) return (compress);
@@ -6977,22 +6389,20 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
#if ! (defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC))
static int libszwarn = 1;
#endif
- int nerr;
unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
- int bdsLen, recLen, gribLen = 0;
+ size_t gribLen = 0;
unsigned char *dest, *source;
size_t destLen, sourceLen;
int /* bds_len, */ bds_nbits, bds_flag, lspherc, lcomplex /*, lcompress*/;
- int bds_head = 11;
+ enum { bds_head = 11 };
int bds_ext = 0;
int bds_zoffset, bds_zstart;
- int datstart = 0;
int llarge = FALSE;
UNUSED(dbufsize);
long gribrecsize;
- nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
+ int nerr = grib1Sections(sbuf, sbufsize, &pds, &gds, &bms, &bds, &gribrecsize);
if ( nerr < 0 )
{
fprintf(stdout, "GRIB message error\n");
@@ -7007,7 +6417,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
bds_zstart = 14;
- recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
+ int recLen = gribrec_len(bds[bds_zstart], bds[bds_zstart+1], bds[bds_zstart+2]);
if ( recLen > JP23SET ) llarge = TRUE;
bds_zoffset = 12;
@@ -7035,7 +6445,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
}
- datstart = bds_head + bds_ext;
+ size_t datstart = bds_head + (size_t)bds_ext;
source = bds + datstart + bds_zoffset;
if ( llarge )
@@ -7057,14 +6467,14 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
dest = bds + datstart;
- if ( llarge )
+ if ( llarge )
destLen = ((size_t) ((bds[17]<<24)+(bds[18]<<16)+(bds[19]<<8)+bds[20]));
else
destLen = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- BDS_Flag -= 16;
+ BDS_Flag = (unsigned char)(BDS_Flag - 16);
- bdsLen = datstart + destLen;
+ size_t bdsLen = datstart + destLen;
#if defined (HAVE_LIBSZ) || defined (HAVE_LIBAEC)
{
@@ -7159,7 +6569,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
pbuf[3*i+2] = dest[2*nelem+i];
}
memcpy(dest, pbuf, tmpLen);
- Free(pbuf);
+ Free(pbuf);
}
#endif
@@ -7195,7 +6605,7 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
*/
while ( gribLen%120 ) dbuf[gribLen++] = 0;
- if ( gribLen != recLen )
+ if ( gribLen != (size_t)recLen )
fprintf(stderr, "Internal problem, recLen and gribLen differ!\n");
itemp = gribLen / (-120);
@@ -7236,126 +6646,19 @@ int gribUnzip(unsigned char *dbuf, long dbufsize, unsigned char *sbuf, long sbu
}
#endif
- return (gribLen);
+ return (int)gribLen;
}
#include <stdio.h>
#include <math.h>
-/* calculate_pfactor: source code from grib_api-1.8.0 */
-double calculate_pfactor(const double* spectralField, long fieldTruncation, long subsetTruncation)
+
+static
+int rowina2(double *p, int ko, int ki, double *pw,
+ int kcode, double msval, int *kret)
{
- /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
- long loop, index, m, n = 0;
- double pFactor, zeps = 1.0e-15;
- long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
- double* weights, range, * norms;
- double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
- double numerator = 0.0, denominator = 0.0, slope;
-
- /*
- // Setup the weights
- */
-
- range = (double) (ismax - ismin +1);
-
- weights = (double*) Malloc((ismax+1)*sizeof(double));
- for( loop = ismin; loop <= ismax; loop++ )
- weights[loop] = range / (double) (loop-ismin+1);
- /*
- // Compute norms
- // Handle values 2 at a time (real and imaginary parts).
- */
- norms = (double*) Malloc((ismax+1)*sizeof(double));
-
- for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
- /*
- // Form norms for the rows which contain part of the unscaled subset.
- */
-
- index = -2;
- for( m = 0; m < subsetTruncation; m++ )
- for( n = m; n <= fieldTruncation; n++ ) {
- index += 2;
- if( n >= subsetTruncation ) {
- double tval = spectralField[index];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- tval = spectralField[index+1];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- }
- }
- /*
- // Form norms for the rows which do not contain part of the unscaled subset.
- */
-
- for( m = subsetTruncation; m <= fieldTruncation; m++ )
- for( n = m; n <= fieldTruncation; n++ ) {
- double tval = spectralField[index];
- index += 2;
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- tval = spectralField[index+1];
- tval=tval<0?-tval:tval;
- norms[n] = norms[n] > tval ? norms[n] : tval;
- }
-
- /*
- // Ensure the norms have a value which is not too small in case of
- // problems with math functions (e.g. LOG).
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
- norms[n] = norms[n] > zeps ? norms[n] : zeps;
- if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
- }
-
- /*
- // Do linear fit to find the slope
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
- x = log( (double) (loop*(loop+1)) );
- y = log( norms[loop] );
- weightedSumOverX = weightedSumOverX + x * weights[loop];
- weightedSumOverY = weightedSumOverY + y * weights[loop];
- sumOfWeights = sumOfWeights + weights[loop];
- }
- weightedSumOverX = weightedSumOverX / sumOfWeights;
- weightedSumOverY = weightedSumOverY / sumOfWeights;
-
- /*
- // Perform a least square fit for the equation
- */
-
- for( loop = ismin; loop <= ismax; loop++ ) {
-
- x = log( (double)(loop*(loop+1)) );
- y = log( norms[loop] );
- numerator =
- numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
- denominator =
- denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
- }
- slope = numerator / denominator;
-
- Free(weights);
- Free(norms);
-
- pFactor = -slope;
- if( pFactor < -9999.9 ) pFactor = -9999.9;
- if( pFactor > 9999.9 ) pFactor = 9999.9;
-
- return pFactor;
-}
-
-static
-int rowina2(double *p, int ko, int ki, double *pw,
- int kcode, double msval, int *kret)
-{
- /* System generated locals */
- int pw_dim1, pw_offset, i_1;
+ /* System generated locals */
+ int pw_dim1, pw_offset, i_1;
/* Local variables */
double zwt1, zrdi, zpos;
@@ -7535,10 +6838,10 @@ int qu2reg2(double *pfield, int *kpoint, int klat, int klon,
int iregno, iquano, j210, j220, j230, j240, j225;
- zline = (double*) Malloc(2*klon*sizeof(double));
+ zline = (double*) Malloc(2*(size_t)klon*sizeof(double));
if ( zline == NULL ) SysError("No Memory!");
- zwork = (double*) Malloc(3*(2*klon+3)*sizeof(double));
+ zwork = (double*) Malloc(3*(2*(size_t)klon+3)*sizeof(double));
if ( zwork == NULL ) SysError("No Memory!");
/* Parameter adjustments */
@@ -7689,12 +6992,118 @@ L900:
#define T double
#ifdef T
+/* calculate_pfactor: source code from grib_api-1.8.0 */
+double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
+{
+ /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
+ long loop, index, m, n = 0;
+ double pFactor, zeps = 1.0e-15;
+ long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
+ double* weights, range, * norms;
+ double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
+ double numerator = 0.0, denominator = 0.0, slope;
+
+ /*
+ // Setup the weights
+ */
+
+ range = (double) (ismax - ismin +1);
+
+ weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+ for( loop = ismin; loop <= ismax; loop++ )
+ weights[loop] = range / (double) (loop-ismin+1);
+ /*
+ // Compute norms
+ // Handle values 2 at a time (real and imaginary parts).
+ */
+ norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+
+ for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
+ /*
+ // Form norms for the rows which contain part of the unscaled subset.
+ */
+
+ index = -2;
+ for( m = 0; m < subsetTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ index += 2;
+ if( n >= subsetTruncation ) {
+ double tval = spectralField[index];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+ }
+ /*
+ // Form norms for the rows which do not contain part of the unscaled subset.
+ */
+
+ for( m = subsetTruncation; m <= fieldTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ double tval = spectralField[index];
+ index += 2;
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+
+ /*
+ // Ensure the norms have a value which is not too small in case of
+ // problems with math functions (e.g. LOG).
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ norms[n] = norms[n] > zeps ? norms[n] : zeps;
+ if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
+ }
+
+ /*
+ // Do linear fit to find the slope
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ x = log( (double) (loop*(loop+1)) );
+ y = log( norms[loop] );
+ weightedSumOverX = weightedSumOverX + x * weights[loop];
+ weightedSumOverY = weightedSumOverY + y * weights[loop];
+ sumOfWeights = sumOfWeights + weights[loop];
+ }
+ weightedSumOverX = weightedSumOverX / sumOfWeights;
+ weightedSumOverY = weightedSumOverY / sumOfWeights;
+
+ /*
+ // Perform a least square fit for the equation
+ */
+
+ for( loop = ismin; loop <= ismax; loop++ ) {
+
+ x = log( (double)(loop*(loop+1)) );
+ y = log( norms[loop] );
+ numerator =
+ numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
+ denominator =
+ denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
+ }
+ slope = numerator / denominator;
+
+ Free(weights);
+ Free(norms);
+
+ pFactor = -slope;
+ if( pFactor < -9999.9 ) pFactor = -9999.9;
+ if( pFactor > 9999.9 ) pFactor = 9999.9;
+
+ return pFactor;
+}
+
void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
{
double power;
- double *scale = (double*) Malloc((trunc+1)*sizeof(double));
- int n, m;
- int index;
+ double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
if ( scale == NULL ) SysError("No Memory!");
@@ -7711,38 +7120,33 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
power = (double) pcScale / 1000.;
scale[0] = 1.0;
- for ( n = 1; n <= trunc; n++ )
- {
- if (pcScale != 1000)
- scale[n] = pow((double) (n*(n+1)), power);
- else
- scale[n] = (double) (n*(n+1));
- }
+ if (pcScale != 1000)
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = pow((double) (n*(n+1)), power);
+ else
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = (double) (n*(n+1));
if ( inv )
- for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+ for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
/* Scale the values */
- index = 0;
+ size_t index = 0;
- for ( m = 0; m < pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
- {
- if ( n >= pcStart )
- {
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- }
- index += 2;
- }
+ for ( int m = 0; m < pcStart; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
+ if ( n >= pcStart )
+ {
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
+ }
- for ( m = pcStart; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( int m = pcStart; m <= trunc; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
{
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- index += 2;
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
}
Free(scale);
@@ -7751,7 +7155,7 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
+ T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
int m, n;
int index, inext;
@@ -7788,18 +7192,13 @@ void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
}
-void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
- int m, n;
- int index, inext;
-
- if ( fphelp == NULL ) SysError("No Memory!");
+ T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
+ size_t inext = 0;
- index = inext = 0;
-
- for ( m = 0; m <= pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= pcStart; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( pcStart >= n )
{
@@ -7809,9 +7208,8 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- index = 0;
- for ( m = 0; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= trunc; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( n > pcStart )
{
@@ -7821,7 +7219,7 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+ for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
Free(fphelp);
}
@@ -8042,8 +7440,8 @@ C -----------------------------------------------------------------
{
/* Interpolate using the weighted values on either side */
/* of the output point position */
- p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
- zwt * pw[ip+2 + pw_dim1];
+ p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
+ + zwt * pw[ip+2 + pw_dim1]);
}
}
}
@@ -8073,14 +7471,14 @@ C -----------------------------------------------------------------
for ( jl = 1; jl <= i_1; ++jl )
{
pw[jl + (pw_dim1 << 1)] =
- - pw[jl - 1 + pw_dim1] / 3.0 -
- pw[jl + pw_dim1] * 0.5 +
- pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+ (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
+ pw[jl + pw_dim1] * 0.5 +
+ pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
pw[jl + 1 + pw_dim1 * 3] =
- pw[jl - 1 + pw_dim1] / 6.0 -
- pw[jl + pw_dim1] +
- pw[jl + 1 + pw_dim1] * 0.5 +
- pw[jl + 2 + pw_dim1] / 3.0;
+ (T)(pw[jl - 1 + pw_dim1] / 6.0 -
+ pw[jl + pw_dim1] +
+ pw[jl + 1 + pw_dim1] * 0.5 +
+ pw[jl + 2 + pw_dim1] / 3.0);
}
TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
@@ -8095,10 +7493,10 @@ C -----------------------------------------------------------------
ip = (int) zwt + 1;
zwt = zwt + 1.0 - ip;
zwt1 = 1.0 - zwt;
- p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
- zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
- ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
- zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+ p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+ zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+ ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+ zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
}
}
@@ -8227,14 +7625,11 @@ C
T *zline = NULL;
T *zwork = NULL;
- ztemp = (T*) Malloc(klon*klat*sizeof(T));
- if ( ztemp == NULL ) SysError("No Memory!");
+ ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
- zline = (T*) Malloc(2*klon*sizeof(T));
- if ( zline == NULL ) SysError("No Memory!");
+ zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
- zwork = (T*) Malloc(3*(2*klon+3)*sizeof(T));
- if ( zwork == NULL ) SysError("No Memory!");
+ zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
/* Parameter adjustments */
--pfield;
@@ -8310,54 +7705,166 @@ C
ztemp[ilio - 1] = zline[j220 - 1];
}
- } else {
+ } else {
+
+/* Line contains the required number of values, so add */
+/* this line to the temporary array. */
+
+ i_2 = iregno;
+ for (j225 = 1; j225 <= i_2; ++j225) {
+ ++ilio;
+ ++ilii;
+ ztemp[ilio - 1] = pfield[ilii];
+ }
+ }
+ }
+
+/* Copy temporary array to user array. */
+
+ i_1 = klon * klat;
+ for (j240 = 1; j240 <= i_1; ++j240) {
+ pfield[j240] = ztemp[j240 - 1];
+ }
+
+/* -------------------------------------------------------- */
+/* Section 9. Return to calling routine. Format statements. */
+/* -------------------------------------------------------- */
+
+L900:
+
+ Free(zwork);
+ Free(zline);
+ Free(ztemp);
+
+ return 0;
+} /* qu2reg3 */
+
+#endif /* T */
+
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#ifdef T
+#undef T
+#endif
+#define T float
+#ifdef T
+
+/* calculate_pfactor: source code from grib_api-1.8.0 */
+double TEMPLATE(calculate_pfactor,T)(const T *spectralField, long fieldTruncation, long subsetTruncation)
+{
+ /*long n_vals = ((fieldTruncation+1)*(fieldTruncation+2));*/
+ long loop, index, m, n = 0;
+ double pFactor, zeps = 1.0e-15;
+ long ismin = (subsetTruncation+1), ismax = (fieldTruncation+1);
+ double* weights, range, * norms;
+ double weightedSumOverX = 0.0, weightedSumOverY = 0.0, sumOfWeights = 0.0, x, y;
+ double numerator = 0.0, denominator = 0.0, slope;
+
+ /*
+ // Setup the weights
+ */
+
+ range = (double) (ismax - ismin +1);
+
+ weights = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+ for( loop = ismin; loop <= ismax; loop++ )
+ weights[loop] = range / (double) (loop-ismin+1);
+ /*
+ // Compute norms
+ // Handle values 2 at a time (real and imaginary parts).
+ */
+ norms = (double*) Malloc(((size_t)ismax+1)*sizeof(double));
+
+ for( loop = 0; loop < ismax+1; loop++ ) norms[loop] = 0.0;
+ /*
+ // Form norms for the rows which contain part of the unscaled subset.
+ */
+
+ index = -2;
+ for( m = 0; m < subsetTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ index += 2;
+ if( n >= subsetTruncation ) {
+ double tval = spectralField[index];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
+ }
+ /*
+ // Form norms for the rows which do not contain part of the unscaled subset.
+ */
+
+ for( m = subsetTruncation; m <= fieldTruncation; m++ )
+ for( n = m; n <= fieldTruncation; n++ ) {
+ double tval = spectralField[index];
+ index += 2;
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ tval = spectralField[index+1];
+ tval=tval<0?-tval:tval;
+ norms[n] = norms[n] > tval ? norms[n] : tval;
+ }
-/* Line contains the required number of values, so add */
-/* this line to the temporary array. */
+ /*
+ // Ensure the norms have a value which is not too small in case of
+ // problems with math functions (e.g. LOG).
+ */
- i_2 = iregno;
- for (j225 = 1; j225 <= i_2; ++j225) {
- ++ilio;
- ++ilii;
- ztemp[ilio - 1] = pfield[ilii];
- }
- }
- }
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ norms[n] = norms[n] > zeps ? norms[n] : zeps;
+ if( IS_EQUAL(norms[n], zeps) ) weights[n] = 100.0 * zeps;
+ }
-/* Copy temporary array to user array. */
+ /*
+ // Do linear fit to find the slope
+ */
- i_1 = klon * klat;
- for (j240 = 1; j240 <= i_1; ++j240) {
- pfield[j240] = ztemp[j240 - 1];
- }
+ for( loop = ismin; loop <= ismax; loop++ ) {
+ x = log( (double) (loop*(loop+1)) );
+ y = log( norms[loop] );
+ weightedSumOverX = weightedSumOverX + x * weights[loop];
+ weightedSumOverY = weightedSumOverY + y * weights[loop];
+ sumOfWeights = sumOfWeights + weights[loop];
+ }
+ weightedSumOverX = weightedSumOverX / sumOfWeights;
+ weightedSumOverY = weightedSumOverY / sumOfWeights;
-/* -------------------------------------------------------- */
-/* Section 9. Return to calling routine. Format statements. */
-/* -------------------------------------------------------- */
+ /*
+ // Perform a least square fit for the equation
+ */
-L900:
+ for( loop = ismin; loop <= ismax; loop++ ) {
- Free(zwork);
- Free(zline);
- Free(ztemp);
+ x = log( (double)(loop*(loop+1)) );
+ y = log( norms[loop] );
+ numerator =
+ numerator + weights[loop] * (y-weightedSumOverY) * (x-weightedSumOverX);
+ denominator =
+ denominator + weights[loop] * ((x-weightedSumOverX) * (x-weightedSumOverX));
+ }
+ slope = numerator / denominator;
- return 0;
-} /* qu2reg3 */
+ Free(weights);
+ Free(norms);
-#endif /* T */
+ pFactor = -slope;
+ if( pFactor < -9999.9 ) pFactor = -9999.9;
+ if( pFactor > 9999.9 ) pFactor = 9999.9;
-#ifdef T
-#undef T
-#endif
-#define T float
-#ifdef T
+ return pFactor;
+}
void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, int inv)
{
double power;
- double *scale = (double*) Malloc((trunc+1)*sizeof(double));
- int n, m;
- int index;
+ double *scale = (double*) Malloc(((size_t)trunc+1)*sizeof(double));
if ( scale == NULL ) SysError("No Memory!");
@@ -8374,38 +7881,33 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
power = (double) pcScale / 1000.;
scale[0] = 1.0;
- for ( n = 1; n <= trunc; n++ )
- {
- if (pcScale != 1000)
- scale[n] = pow((double) (n*(n+1)), power);
- else
- scale[n] = (double) (n*(n+1));
- }
+ if (pcScale != 1000)
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = pow((double) (n*(n+1)), power);
+ else
+ for ( int n = 1; n <= trunc; n++ )
+ scale[n] = (double) (n*(n+1));
if ( inv )
- for ( n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
+ for ( int n = 1; n <= trunc; n++ ) scale[n] = 1.0 / scale[n];
/* Scale the values */
- index = 0;
+ size_t index = 0;
- for ( m = 0; m < pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
- {
- if ( n >= pcStart )
- {
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- }
- index += 2;
- }
+ for ( int m = 0; m < pcStart; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
+ if ( n >= pcStart )
+ {
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
+ }
- for ( m = pcStart; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( int m = pcStart; m <= trunc; m++ )
+ for ( int n = m; n <= trunc; n++, index += 2 )
{
- fpdata[index ] *= scale[n];
- fpdata[index+1] *= scale[n];
- index += 2;
+ fpdata[index ] = (T)(fpdata[index ] * scale[n]);
+ fpdata[index+1] = (T)(fpdata[index+1] * scale[n]);
}
Free(scale);
@@ -8414,7 +7916,7 @@ void TEMPLATE(scale_complex,T)(T *fpdata, int pcStart, int pcScale, int trunc, i
void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
+ T *fphelp = (T*) Malloc((size_t)nsp*sizeof(T));
int m, n;
int index, inext;
@@ -8451,18 +7953,13 @@ void TEMPLATE(scatter_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
}
-void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
+void TEMPLATE(gather_complex,T)(T *fpdata, size_t pcStart, size_t trunc, size_t nsp)
{
- T *fphelp = (T*) Malloc(nsp*sizeof(T));
- int m, n;
- int index, inext;
-
- if ( fphelp == NULL ) SysError("No Memory!");
-
- index = inext = 0;
+ T *restrict fphelp = (T*) Malloc(nsp*sizeof(T));
+ size_t inext = 0;
- for ( m = 0; m <= pcStart; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= pcStart; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( pcStart >= n )
{
@@ -8472,9 +7969,8 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- index = 0;
- for ( m = 0; m <= trunc; m++ )
- for ( n = m; n <= trunc; n++ )
+ for ( size_t m = 0, index = 0; m <= trunc; m++ )
+ for ( size_t n = m; n <= trunc; n++ )
{
if ( n > pcStart )
{
@@ -8484,7 +7980,7 @@ void TEMPLATE(gather_complex,T)(T *fpdata, int pcStart, int trunc, int nsp)
index += 2;
}
- for ( m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
+ for ( size_t m = 0; m < nsp; m++ ) fpdata[m] = fphelp[m];
Free(fphelp);
}
@@ -8705,8 +8201,8 @@ C -----------------------------------------------------------------
{
/* Interpolate using the weighted values on either side */
/* of the output point position */
- p[jl] = (1.0 - zwt) * pw[ip+1 + pw_dim1] +
- zwt * pw[ip+2 + pw_dim1];
+ p[jl] = (T)((1.0 - zwt) * pw[ip+1 + pw_dim1]
+ + zwt * pw[ip+2 + pw_dim1]);
}
}
}
@@ -8736,14 +8232,14 @@ C -----------------------------------------------------------------
for ( jl = 1; jl <= i_1; ++jl )
{
pw[jl + (pw_dim1 << 1)] =
- - pw[jl - 1 + pw_dim1] / 3.0 -
- pw[jl + pw_dim1] * 0.5 +
- pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0;
+ (T)(- pw[jl - 1 + pw_dim1] / 3.0 -
+ pw[jl + pw_dim1] * 0.5 +
+ pw[jl + 1 + pw_dim1] - pw[jl + 2 + pw_dim1] / 6.0);
pw[jl + 1 + pw_dim1 * 3] =
- pw[jl - 1 + pw_dim1] / 6.0 -
- pw[jl + pw_dim1] +
- pw[jl + 1 + pw_dim1] * 0.5 +
- pw[jl + 2 + pw_dim1] / 3.0;
+ (T)(pw[jl - 1 + pw_dim1] / 6.0 -
+ pw[jl + pw_dim1] +
+ pw[jl + 1 + pw_dim1] * 0.5 +
+ pw[jl + 2 + pw_dim1] / 3.0);
}
TEMPLATE(scm0,T)(&pw[(pw_dim1 << 1) + 1], &pw[pw_dim1 * 3 + 2],
@@ -8758,10 +8254,10 @@ C -----------------------------------------------------------------
ip = (int) zwt + 1;
zwt = zwt + 1.0 - ip;
zwt1 = 1.0 - zwt;
- p[jl] = ((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
- zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
- ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
- zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt;
+ p[jl] = (T)(((3.0 - zwt1 * 2.0) * pw[ip + pw_dim1] +
+ zwt * pw[ip + (pw_dim1 << 1)]) * zwt1 * zwt1 +
+ ((3.0 - zwt * 2.0) * pw[ip + 1 + pw_dim1] -
+ zwt1 * pw[ip + 1 + pw_dim1 * 3]) * zwt * zwt);
}
}
@@ -8890,14 +8386,11 @@ C
T *zline = NULL;
T *zwork = NULL;
- ztemp = (T*) Malloc(klon*klat*sizeof(T));
- if ( ztemp == NULL ) SysError("No Memory!");
+ ztemp = (T*) Malloc((size_t)klon*(size_t)klat*sizeof(T));
- zline = (T*) Malloc(2*klon*sizeof(T));
- if ( zline == NULL ) SysError("No Memory!");
+ zline = (T*) Malloc(2*(size_t)klon*sizeof(T));
- zwork = (T*) Malloc(3*(2*klon+3)*sizeof(T));
- if ( zwork == NULL ) SysError("No Memory!");
+ zwork = (T*) Malloc(3*(2*(size_t)klon+3)*sizeof(T));
/* Parameter adjustments */
--pfield;
@@ -9008,6 +8501,12 @@ L900:
} /* qu2reg3 */
#endif /* T */
+
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
#include <string.h>
@@ -9301,31 +8800,31 @@ void gribPrintSec3_float(int *isec0, int *isec3, float *fsec3) {gribPrintSec3SP(
void gribPrintSec4_float(int *isec0, int *isec4, float *fsec4) {gribPrintSec4SP(isec0, isec4, fsec4);}
-
#ifdef T
#undef T
#endif
#define T double
#ifdef T
+#include <inttypes.h>
+
static
-void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
- unsigned int jmask;
long i;
unsigned int tbits = 0;
int n_bits = NumBits;
int t_bits = 0;
-
- jmask = (1 << n_bits) - 1;
+
+ unsigned jmask = (1U << n_bits) - 1U;
for ( i = 0; i < jlend; i++ )
{
if (n_bits - t_bits > 8)
{
- tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+ tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
bits += 2;
t_bits += 16;
}
@@ -9336,35 +8835,32 @@ void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long
t_bits += 8;
}
t_bits -= n_bits;
- fpdata[i] = (tbits >> t_bits) & jmask;
+ fpdata[i] = (float)((tbits >> t_bits) & jmask);
}
/* at least this vectorizes :) */
for ( i = 0; i < jlend; i++ )
fpdata[i] = fmin + zscale*fpdata[i];
}
-#if !defined(_MASK_AND_SHIFT_)
-#define _MASK_AND_SHIFT_
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
-#endif
-
-static
-void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+static
+void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
+ static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
+ static const double shift[9]
+ = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
long i;
int n_bits = NumBits;
int c_bits, j_bits;
- double jj;
/* older unoptimized code, not often used */
c_bits = 8;
for ( i = 0; i < jlend; i++ )
{
- jj = 0.0;
+ double jj = 0.0;
j_bits = n_bits;
while (c_bits <= j_bits)
{
@@ -9385,12 +8881,36 @@ void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long
if (j_bits)
{
c_bits -= j_bits;
- jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+ jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
}
-
- fpdata[i] = fmin + zscale*jj;
+ fpdata[i] = (T)(fmin + zscale*jj);
+ }
+}
+
+static
+void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
+ T *fpdata, T fmin, T zscale)
+{
+ U_BYTEORDER;
+ const uint16_t *restrict sgrib = (uint16_t *) (igrib);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ fpdata[i] = fmin + zscale * sgrib[i];
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ ui16 = gribSwapByteOrder_uint16(sgrib[i]);
+ fpdata[i] = fmin + zscale * ui16;
+ }
}
-}
+}
static
void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
@@ -9401,7 +8921,6 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif
long i;
- T dval;
#if defined (VECTORCODE)
GRIBPACK *lgrib = NULL;
@@ -9425,26 +8944,26 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)lgrib[i];
+ T dval = (int)lgrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
+ T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
+ T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
(int)lgrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+ T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
@@ -9472,75 +8991,25 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)igrib[i];
+ T dval = (int)igrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
{
-#ifdef _GET_IBM_COUNTER
- hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER
- start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- start_decode = mach_absolute_time();
-#endif
-
- if ( sizeof(T) == sizeof(double) )
- {
-#if defined _ENABLE_AVX
- printf("AVX selected ...\n");
- avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
- printf("SSE4 selected ...\n");
- sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
-#endif
- }
- else
- {
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
- }
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER
- end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
- printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
- printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
- printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif
-#endif
-
-#ifdef _GET_IBM_COUNTER
- hpmStop(6);
-#endif
+ TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
- (int)igrib[3*i+2]);
+ T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
+ (int)igrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
- ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
+ T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+ ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits <= 25 )
@@ -9560,30 +9029,37 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
#define T float
#ifdef T
+#include <inttypes.h>
+
static
-void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+void TEMPLATE(decode_array_common,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
- unsigned int jmask;
long i;
unsigned int tbits = 0;
int n_bits = NumBits;
int t_bits = 0;
-
- jmask = (1 << n_bits) - 1;
+
+ unsigned jmask = (1U << n_bits) - 1U;
for ( i = 0; i < jlend; i++ )
{
if (n_bits - t_bits > 8)
{
- tbits = (tbits << 16) | (bits[0] << 8) | (bits[1]);
+ tbits = (tbits << 16) | ((unsigned)bits[0] << 8) | ((unsigned)bits[1]);
bits += 2;
t_bits += 16;
}
@@ -9594,35 +9070,32 @@ void TEMPLATE(decode_array_common,T)(const unsigned char * restrict igrib, long
t_bits += 8;
}
t_bits -= n_bits;
- fpdata[i] = (tbits >> t_bits) & jmask;
+ fpdata[i] = (float)((tbits >> t_bits) & jmask);
}
/* at least this vectorizes :) */
for ( i = 0; i < jlend; i++ )
fpdata[i] = fmin + zscale*fpdata[i];
}
-#if !defined(_MASK_AND_SHIFT_)
-#define _MASK_AND_SHIFT_
-static unsigned int mask[] = {0,1,3,7,15,31,63,127,255};
-static double shift[9] = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
-#endif
-
-static
-void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long jlend, int NumBits,
- T fmin, T zscale, T * restrict fpdata)
+static
+void TEMPLATE(decode_array_common2,T)(const unsigned char *restrict igrib, long jlend, int NumBits,
+ T fmin, T zscale, T *restrict fpdata)
{
+ static const unsigned mask[] = {0,1,3,7,15,31,63,127,255};
+ static const double shift[9]
+ = {1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0};
+
/* code from wgrib routine BDS_unpack */
const unsigned char *bits = igrib;
long i;
int n_bits = NumBits;
int c_bits, j_bits;
- double jj;
/* older unoptimized code, not often used */
c_bits = 8;
for ( i = 0; i < jlend; i++ )
{
- jj = 0.0;
+ double jj = 0.0;
j_bits = n_bits;
while (c_bits <= j_bits)
{
@@ -9643,12 +9116,36 @@ void TEMPLATE(decode_array_common2,T)(const unsigned char * restrict igrib, long
if (j_bits)
{
c_bits -= j_bits;
- jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]);
+ jj = (jj * shift[j_bits]) + (double) (((unsigned)*bits >> c_bits) & mask[j_bits]);
}
-
- fpdata[i] = fmin + zscale*jj;
+ fpdata[i] = (T)(fmin + zscale*jj);
+ }
+}
+
+static
+void TEMPLATE(decode_array_2byte,T)(size_t jlend, const unsigned char *restrict igrib,
+ T *fpdata, T fmin, T zscale)
+{
+ U_BYTEORDER;
+ const uint16_t *restrict sgrib = (uint16_t *) (igrib);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ fpdata[i] = fmin + zscale * sgrib[i];
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < jlend; i++ )
+ {
+ ui16 = gribSwapByteOrder_uint16(sgrib[i]);
+ fpdata[i] = fmin + zscale * ui16;
+ }
}
-}
+}
static
void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, int numBits,
@@ -9659,7 +9156,6 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif
long i;
- T dval;
#if defined (VECTORCODE)
GRIBPACK *lgrib = NULL;
@@ -9683,26 +9179,26 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
else if ( numBits == 8 )
for ( i = 0; i < jlend; i++ )
{
- dval = (int)lgrib[i];
+ T dval = (int)lgrib[i];
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 16 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
+ T dval = (((int)lgrib[2*i ] << 8) + (int)lgrib[2*i+1]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
+ T dval = (((int)lgrib[3*i ] << 16) + ((int)lgrib[3*i+1] << 8) +
(int)lgrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
+ T dval = (((unsigned int)lgrib[4*i ] << 24) + ((unsigned int)lgrib[4*i+1] << 16) +
((unsigned int)lgrib[4*i+2] << 8) + (unsigned int)lgrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
@@ -9722,83 +9218,33 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
if ( lgrib ) Free(lgrib);
#else
- if ( numBits == 0 )
- {
- for ( i = 0; i < jlend; i++ )
- fpdata[i] = fmin;
- }
- else if ( numBits == 8 )
- for ( i = 0; i < jlend; i++ )
- {
- dval = (int)igrib[i];
- fpdata[i] = fmin + zscale * dval;
- }
- else if ( numBits == 16 )
- {
-#ifdef _GET_IBM_COUNTER
- hpmStart(6, "unpack 16 bit base");
-#elif defined _GET_X86_COUNTER
- start_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- start_decode = mach_absolute_time();
-#endif
-
- if ( sizeof(T) == sizeof(double) )
- {
-#if defined _ENABLE_AVX
- printf("AVX selected ...\n");
- avx_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#elif defined _ENABLE_SSE4_1
- printf("SSE4 selected ...\n");
- sse41_decode_array_2byte_double((size_t) jlend, igrib, fpdata, fmin, zscale);
-#else
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
-#endif
- }
- else
- {
- for ( i = 0; i < jlend; i++ )
- {
- dval = (((int)igrib[2*i ] << 8) | (int)igrib[2*i+1]);
- fpdata[i] = fmin + zscale * dval;
- }
- }
-
-#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
-#if defined _GET_X86_COUNTER
- end_decode = _rdtsc();
-#elif defined _GET_MACH_COUNTER
- end_decode = mach_absolute_time();
-#endif
-#if defined _ENABLE_AVX
- printf("AVX encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#elif defined _ENABLE_SSE4_1
- printf("SSE 4.1 encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#else
- printf("loop encoding cycles:: %" PRIu64 "\n", end_decode-start_decode);
-#endif
-#endif
-
-#ifdef _GET_IBM_COUNTER
- hpmStop(6);
-#endif
+ if ( numBits == 0 )
+ {
+ for ( i = 0; i < jlend; i++ )
+ fpdata[i] = fmin;
+ }
+ else if ( numBits == 8 )
+ for ( i = 0; i < jlend; i++ )
+ {
+ T dval = (int)igrib[i];
+ fpdata[i] = fmin + zscale * dval;
+ }
+ else if ( numBits == 16 )
+ {
+ TEMPLATE(decode_array_2byte,T)((size_t) jlend, igrib, fpdata, fmin, zscale);
}
else if ( numBits == 24 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
- (int)igrib[3*i+2]);
+ T dval = (T)(((int)igrib[3*i ] << 16) + ((int)igrib[3*i+1] << 8) +
+ (int)igrib[3*i+2]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits == 32 )
for ( i = 0; i < jlend; i++ )
{
- dval = (((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
- ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
+ T dval = (T)(((unsigned int)igrib[4*i ] << 24) + ((unsigned int)igrib[4*i+1] << 16) +
+ ((unsigned int)igrib[4*i+2] << 8) + (unsigned int)igrib[4*i+3]);
fpdata[i] = fmin + zscale * dval;
}
else if ( numBits <= 25 )
@@ -9818,6 +9264,12 @@ void TEMPLATE(decode_array,T)(const unsigned char *restrict igrib, long jlend, i
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
@@ -9832,7 +9284,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
int ReducedGrid = FALSE, VertCoorTab = FALSE;
int locnv = 0, locnl;
int jlenl;
- long i;
int iexp, imant;
int ipvpl, ipl;
int gdsLen = 0;
@@ -9884,7 +9335,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
*numGridVals = 0;
ISEC2_Reduced = TRUE;
- for ( i = 0; i < jlenl; i++ )
+ for ( int i = 0; i < jlenl; i++ )
{
ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
*numGridVals += ISEC2_RowLon(i);
@@ -9924,7 +9375,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
ISEC2_LatSP = GDS_LatSP;
ISEC2_LonSP = GDS_LonSP;
- FSEC2_RotAngle = GDS_RotAngle;
+ FSEC2_RotAngle = (T)GDS_RotAngle;
}
/*
if ( Lons != Longitudes || Lats != Latitudes )
@@ -10034,31 +9485,34 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
igrib = &gds[locnv];
if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (lgrib[4*i ]);
imant =((lgrib[4*i+1]) << 16) +
((lgrib[4*i+2]) << 8) +
(lgrib[4*i+3]);
- fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+ fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
}
Free(lgrib);
#else
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (gds[locnv+4*i ]);
imant =((gds[locnv+4*i+1]) << 16) +
((gds[locnv+4*i+2]) << 8) +
(gds[locnv+4*i+3]);
- fsec2[10+i] = decfp2(iexp,imant);
+ fsec2[10+i] = (T)decfp2(iexp,imant);
}
#endif
}
- return (gdsLen);
+ return gdsLen;
}
+#define ldexp_double ldexp
+#define ldexp_float ldexpf
+
static
int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
@@ -10068,15 +9522,13 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
int lcompress;
int jup, kup, mup;
int locnd;
- long jlend;
- long i;
int bds_flag, jscale, imiss;
int bds_ubits;
int ioff = 0;
int iexp, imant;
int zoff;
int bds_head = 11;
- double zscale = 0.;
+ T zscale = 0.;
T fmin = 0.;
T *fpdata = fsec4;
int bdsLen;
@@ -10147,16 +9599,11 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* convert reference value and scale factor. */
- if ( ! (dfunc == 'J') )
- if ( imiss == 0 )
- {
- fmin = BDS_RefValue;
-
- if ( jscale < 0 )
- zscale = 1.0/intpow2(-jscale);
- else
- zscale = intpow2(jscale);
- }
+ if ( ! (dfunc == 'J') && imiss == 0 )
+ {
+ fmin = BDS_RefValue;
+ zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
+ }
/* get number of bits in each data value. */
@@ -10190,7 +9637,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( dfunc != 'J' )
{
if ( imiss ) *fpdata++ = 0.0;
- else *fpdata++ = BDS_RealCoef;
+ else *fpdata++ = (T)BDS_RealCoef;
}
}
else /* complex packed spherical harmonics */
@@ -10217,7 +9664,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
ioff = (jup+1)*(jup+2);
if ( dfunc != 'J' )
- for ( i = 0; i < ioff; i++ )
+ for ( int i = 0; i < ioff; i++ )
{
if ( imiss )
*fpdata++ = 0.0;
@@ -10228,7 +9675,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
((bds[locnd+4*i+2]) << 8) +
(bds[locnd+4*i+3]);
- *fpdata++ = decfp2(iexp,imant);
+ *fpdata++ = (T)decfp2(iexp,imant);
}
}
@@ -10242,7 +9689,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 1999;
gprintf(__func__, " Second order packed grids unsupported!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
}
@@ -10251,7 +9698,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* Take into account that spherical harmonics can be packed */
/* simple (lcomplex = 0) or complex (lcomplex = 1) */
- jlend = bdsLen - locnd;
+ int jlend = bdsLen - locnd;
if ( ISEC4_NumBits == 0 )
{
@@ -10260,7 +9707,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2001;
gprintf(__func__, " Number of bits per data value = 0!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
if ( numGridVals == 0 )
@@ -10268,7 +9715,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2002;
gprintf(__func__, " Constant field unsupported for this grid type!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
jlend = numGridVals;
@@ -10291,7 +9738,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
else
len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- ISEC4_NumValues = len*8/ISEC4_NumBits;
+ ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
if ( lspherc )
{
@@ -10302,7 +9749,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
}
}
- if ( dfunc == 'J' ) return (bdsLen);
+ if ( dfunc == 'J' ) return bdsLen;
/* check length of output array. */
@@ -10312,10 +9759,10 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
gprintf(__func__, " Output array too small. Length = %d", fsec4len);
gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
- if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+ if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
else
{
igrib += locnd;
@@ -10325,9 +9772,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( lspherc && lcomplex )
{
- int pcStart, pcScale;
- pcStart = isec4[19];
- pcScale = isec4[16];
+ int pcStart = isec4[19], pcScale = isec4[16];
TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
}
@@ -10339,17 +9784,17 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
{
T zserr = fsec4[1];
- for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+ for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
}
}
if ( decscale )
{
T scale = (T) pow(10.0, (double)-decscale);
- for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+ for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
}
- return (bdsLen);
+ return bdsLen;
}
@@ -10359,7 +9804,6 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
{
UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
- int gribLen = 0;
int gdsIncluded = FALSE;
int bmsIncluded = FALSE;
int bitmapSize = 0;
@@ -10550,7 +9994,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
{
lmissvalinfo = 0;
- FSEC3_MissVal = GRIB_MISSVAL;
+ FSEC3_MissVal = (T)GRIB_MISSVAL;
Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
}
@@ -10559,16 +10003,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
{
- long i, j;
- GRIBPACK *pbitmap;
GRIBPACK bitmap;
- GRIBPACK *imask;
-
/*
unsigned char *bitmap;
bitmap = BMS_Bitmap;
- j = ISEC4_NumNonMissValues;
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ int j = ISEC4_NumNonMissValues;
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
{
if ( (bitmap[i/8]>>(7-(i&7)))&1 )
fsec4[i] = fsec4[--j];
@@ -10577,13 +10017,13 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
}
*/
- imask = (GRIBPACK*) Malloc(imaskSize*sizeof(GRIBPACK));
+ GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
#if defined (VECTORCODE)
(void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
- pbitmap = imask;
+ GRIBPACK *pbitmap = imask;
#else
- pbitmap = BMS_Bitmap;
+ GRIBPACK *pbitmap = BMS_Bitmap;
#endif
#if defined (CRAY)
@@ -10595,7 +10035,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = imaskSize/8-1; i >= 0; i-- )
+ for ( int i = imaskSize/8-1; i >= 0; i-- )
{
bitmap = pbitmap[i];
imask[i*8+0] = 1 & (bitmap >> 7);
@@ -10608,8 +10048,8 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
imask[i*8+7] = 1 & (bitmap);
}
- j = 0;
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( imask[i] ) j++;
if ( ISEC4_NumNonMissValues != j )
@@ -10632,7 +10072,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
}
@@ -10642,24 +10082,18 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC2_Reduced )
{
- int nlon, nlat;
- int lperio = 1, lveggy;
- int ilat;
int nvalues = 0;
-
- nlat = ISEC2_NumLat;
- nlon = ISEC2_RowLonPtr[0];
- for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
- for ( ilat = 1; ilat < nlat; ++ilat )
+ int nlat = ISEC2_NumLat;
+ int nlon = ISEC2_RowLonPtr[0];
+ for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+ for ( int ilat = 1; ilat < nlat; ++ilat )
if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
// int dlon = ISEC2_LastLon-ISEC2_FirstLon;
// if ( dlon < 0 ) dlon += 360000;
- if ( nvalues != ISEC4_NumValues )
- {
- *iret = -801;
- }
+ if ( nvalues != ISEC4_NumValues ) *iret = -801;
+
//printf("nlat %d nlon %d \n", nlat, nlon);
//printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
@@ -10674,18 +10108,20 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC4_NumValues = nlon*nlat;
lsect3 = bitmapSize > 0;
- lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
- ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
- (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+ int lperio = 1;
+ int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
+ ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
+ (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
+ (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
+ (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
+ (ISEC1_Parameter == 43));
(void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
if ( bitmapSize > 0 )
{
- long i;
- int j = 0;
-
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
ISEC4_NumNonMissValues = j;
@@ -10697,7 +10133,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
esLen = 4;
- gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+ int gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
if ( ISEC0_GRIB_Len )
if ( ISEC0_GRIB_Len < gribLen )
@@ -10705,8 +10141,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC0_GRIB_Len = gribLen;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
/*
----------------------------------------------------------------
@@ -10751,6 +10186,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
@@ -10764,7 +10205,6 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
int ReducedGrid = FALSE, VertCoorTab = FALSE;
int locnv = 0, locnl;
int jlenl;
- long i;
int iexp, imant;
int ipvpl, ipl;
int gdsLen = 0;
@@ -10816,7 +10256,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
*numGridVals = 0;
ISEC2_Reduced = TRUE;
- for ( i = 0; i < jlenl; i++ )
+ for ( int i = 0; i < jlenl; i++ )
{
ISEC2_RowLon(i) = GET_UINT2(gds[locnl+2*i], gds[locnl+2*i+1]);
*numGridVals += ISEC2_RowLon(i);
@@ -10856,7 +10296,7 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
{
ISEC2_LatSP = GDS_LatSP;
ISEC2_LonSP = GDS_LonSP;
- FSEC2_RotAngle = GDS_RotAngle;
+ FSEC2_RotAngle = (T)GDS_RotAngle;
}
/*
if ( Lons != Longitudes || Lats != Latitudes )
@@ -10966,31 +10406,34 @@ int TEMPLATE(decodeGDS,T)(unsigned char *gds, int *isec0, int *isec2, T *fsec2,
igrib = &gds[locnv];
if ( ISEC2_NumVCP > 0 ) (void) UNPACK_GRIB(igrib, lgrib, lGribLen, -1L);
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (lgrib[4*i ]);
imant =((lgrib[4*i+1]) << 16) +
((lgrib[4*i+2]) << 8) +
(lgrib[4*i+3]);
- fsec2[10+i] = POW_2_M24 * imant * pow(16.0, (double)(iexp - 64));
+ fsec2[10+i] = POW_2_M24 * imant * ldexp(1.0, 4 * (iexp - 64));
}
Free(lgrib);
#else
- for ( i = 0; i < ISEC2_NumVCP; i++ )
+ for ( int i = 0; i < ISEC2_NumVCP; i++ )
{
iexp = (gds[locnv+4*i ]);
imant =((gds[locnv+4*i+1]) << 16) +
((gds[locnv+4*i+2]) << 8) +
(gds[locnv+4*i+3]);
- fsec2[10+i] = decfp2(iexp,imant);
+ fsec2[10+i] = (T)decfp2(iexp,imant);
}
#endif
}
- return (gdsLen);
+ return gdsLen;
}
+#define ldexp_double ldexp
+#define ldexp_float ldexpf
+
static
int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *isec4,
T *fsec4, int fsec4len, int dfunc, int bdsLenIn, int numGridVals, int llarge, int *iret)
@@ -11000,15 +10443,13 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
int lcompress;
int jup, kup, mup;
int locnd;
- long jlend;
- long i;
int bds_flag, jscale, imiss;
int bds_ubits;
int ioff = 0;
int iexp, imant;
int zoff;
int bds_head = 11;
- double zscale = 0.;
+ T zscale = 0.;
T fmin = 0.;
T *fpdata = fsec4;
int bdsLen;
@@ -11079,16 +10520,11 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* convert reference value and scale factor. */
- if ( ! (dfunc == 'J') )
- if ( imiss == 0 )
- {
- fmin = BDS_RefValue;
-
- if ( jscale < 0 )
- zscale = 1.0/intpow2(-jscale);
- else
- zscale = intpow2(jscale);
- }
+ if ( ! (dfunc == 'J') && imiss == 0 )
+ {
+ fmin = BDS_RefValue;
+ zscale = TEMPLATE(ldexp,T)((T)1.0, jscale);
+ }
/* get number of bits in each data value. */
@@ -11122,7 +10558,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( dfunc != 'J' )
{
if ( imiss ) *fpdata++ = 0.0;
- else *fpdata++ = BDS_RealCoef;
+ else *fpdata++ = (T)BDS_RealCoef;
}
}
else /* complex packed spherical harmonics */
@@ -11149,7 +10585,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
ioff = (jup+1)*(jup+2);
if ( dfunc != 'J' )
- for ( i = 0; i < ioff; i++ )
+ for ( int i = 0; i < ioff; i++ )
{
if ( imiss )
*fpdata++ = 0.0;
@@ -11160,7 +10596,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
((bds[locnd+4*i+2]) << 8) +
(bds[locnd+4*i+3]);
- *fpdata++ = decfp2(iexp,imant);
+ *fpdata++ = (T)decfp2(iexp,imant);
}
}
@@ -11174,7 +10610,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 1999;
gprintf(__func__, " Second order packed grids unsupported!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
}
@@ -11183,7 +10619,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
/* Take into account that spherical harmonics can be packed */
/* simple (lcomplex = 0) or complex (lcomplex = 1) */
- jlend = bdsLen - locnd;
+ int jlend = bdsLen - locnd;
if ( ISEC4_NumBits == 0 )
{
@@ -11192,7 +10628,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2001;
gprintf(__func__, " Number of bits per data value = 0!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
if ( numGridVals == 0 )
@@ -11200,7 +10636,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
*iret = 2002;
gprintf(__func__, " Constant field unsupported for this grid type!");
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
jlend = numGridVals;
@@ -11223,7 +10659,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
else
len = ((size_t) ((bds[17]<<16)+(bds[18]<<8)+bds[19]));
- ISEC4_NumValues = len*8/ISEC4_NumBits;
+ ISEC4_NumValues = (int)(len*8/(size_t)ISEC4_NumBits);
if ( lspherc )
{
@@ -11234,7 +10670,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
}
}
- if ( dfunc == 'J' ) return (bdsLen);
+ if ( dfunc == 'J' ) return bdsLen;
/* check length of output array. */
@@ -11244,10 +10680,10 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
gprintf(__func__, " Output array too small. Length = %d", fsec4len);
gprintf(__func__, " Number of values = %d", ISEC4_NumValues);
gprintf(__func__, " Return code = %d", *iret);
- return (0);
+ return 0;
}
- if ( imiss ) memset((char *)fpdata, 0, jlend*sizeof(T));
+ if ( imiss ) memset((char *)fpdata, 0, (size_t)jlend*sizeof(T));
else
{
igrib += locnd;
@@ -11257,9 +10693,7 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( lspherc && lcomplex )
{
- int pcStart, pcScale;
- pcStart = isec4[19];
- pcScale = isec4[16];
+ int pcStart = isec4[19], pcScale = isec4[16];
TEMPLATE(scatter_complex,T)(fsec4, pcStart, ISEC2_PentaJ, ISEC4_NumValues);
TEMPLATE(scale_complex,T)(fsec4, pcStart, pcScale, ISEC2_PentaJ, 1);
}
@@ -11271,17 +10705,17 @@ int TEMPLATE(decodeBDS,T)(int decscale, unsigned char *bds, int *isec2, int *ise
if ( IS_NOT_EQUAL(fsec4[1], 0.0) )
{
T zserr = fsec4[1];
- for ( i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
+ for ( int i = 1; i < ISEC4_NumValues; i++ ) fsec4[i] -= zserr;
}
}
if ( decscale )
{
T scale = (T) pow(10.0, (double)-decscale);
- for ( i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
+ for ( int i = 0; i < ISEC4_NumValues; i++ ) fsec4[i] *= scale;
}
- return (bdsLen);
+ return bdsLen;
}
@@ -11291,7 +10725,6 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
{
UCHAR *is = NULL, *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
int isLen = 0, pdsLen = 0, gdsLen = 0, bmsLen = 0, bdsLen = 0, esLen = 0;
- int gribLen = 0;
int gdsIncluded = FALSE;
int bmsIncluded = FALSE;
int bitmapSize = 0;
@@ -11482,7 +10915,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( DBL_IS_NAN(FSEC3_MissVal) && lmissvalinfo )
{
lmissvalinfo = 0;
- FSEC3_MissVal = GRIB_MISSVAL;
+ FSEC3_MissVal = (T)GRIB_MISSVAL;
Message("Missing value = NaN is unsupported, set to %g!", GRIB_MISSVAL);
}
@@ -11491,16 +10924,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( dfunc != 'J' || bitmapSize == ISEC4_NumNonMissValues )
{
- long i, j;
- GRIBPACK *pbitmap;
GRIBPACK bitmap;
- GRIBPACK *imask;
-
/*
unsigned char *bitmap;
bitmap = BMS_Bitmap;
- j = ISEC4_NumNonMissValues;
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ int j = ISEC4_NumNonMissValues;
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
{
if ( (bitmap[i/8]>>(7-(i&7)))&1 )
fsec4[i] = fsec4[--j];
@@ -11509,13 +10938,13 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
}
*/
- imask = (GRIBPACK*) Malloc(imaskSize*sizeof(GRIBPACK));
+ GRIBPACK *imask = (GRIBPACK*) Malloc((size_t)imaskSize*sizeof(GRIBPACK));
#if defined (VECTORCODE)
(void) UNPACK_GRIB(BMS_Bitmap, imask, imaskSize/8, -1L);
- pbitmap = imask;
+ GRIBPACK *pbitmap = imask;
#else
- pbitmap = BMS_Bitmap;
+ GRIBPACK *pbitmap = BMS_Bitmap;
#endif
#if defined (CRAY)
@@ -11527,7 +10956,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = imaskSize/8-1; i >= 0; i-- )
+ for ( int i = imaskSize/8-1; i >= 0; i-- )
{
bitmap = pbitmap[i];
imask[i*8+0] = 1 & (bitmap >> 7);
@@ -11540,8 +10969,8 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
imask[i*8+7] = 1 & (bitmap);
}
- j = 0;
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( imask[i] ) j++;
if ( ISEC4_NumNonMissValues != j )
@@ -11564,7 +10993,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#ifdef __uxpch__
#pragma loop novrec
#endif
- for ( i = ISEC4_NumValues-1; i >= 0; i-- )
+ for ( int i = ISEC4_NumValues-1; i >= 0; i-- )
fsec4[i] = imask[i] ? fsec4[--j] : FSEC3_MissVal;
}
@@ -11574,24 +11003,18 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC2_Reduced )
{
- int nlon, nlat;
- int lperio = 1, lveggy;
- int ilat;
int nvalues = 0;
-
- nlat = ISEC2_NumLat;
- nlon = ISEC2_RowLonPtr[0];
- for ( ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
- for ( ilat = 1; ilat < nlat; ++ilat )
+ int nlat = ISEC2_NumLat;
+ int nlon = ISEC2_RowLonPtr[0];
+ for ( int ilat = 0; ilat < nlat; ++ilat ) nvalues += ISEC2_RowLon(ilat);
+ for ( int ilat = 1; ilat < nlat; ++ilat )
if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
// int dlon = ISEC2_LastLon-ISEC2_FirstLon;
// if ( dlon < 0 ) dlon += 360000;
- if ( nvalues != ISEC4_NumValues )
- {
- *iret = -801;
- }
+ if ( nvalues != ISEC4_NumValues ) *iret = -801;
+
//printf("nlat %d nlon %d \n", nlat, nlon);
//printf("nvalues %d %d\n", nvalues, ISEC4_NumValues);
@@ -11606,18 +11029,20 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC4_NumValues = nlon*nlat;
lsect3 = bitmapSize > 0;
- lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
- ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
- (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30));
+ int lperio = 1;
+ int lveggy = (ISEC1_CodeTable == 128) && (ISEC1_CenterID == 98) &&
+ ((ISEC1_Parameter == 27) || (ISEC1_Parameter == 28) ||
+ (ISEC1_Parameter == 29) || (ISEC1_Parameter == 30) ||
+ (ISEC1_Parameter == 39) || (ISEC1_Parameter == 40) ||
+ (ISEC1_Parameter == 41) || (ISEC1_Parameter == 42) ||
+ (ISEC1_Parameter == 43));
(void) TEMPLATE(qu2reg3,T)(fsec4, ISEC2_RowLonPtr, nlat, nlon, FSEC3_MissVal, iret, lsect3, lperio, lveggy);
if ( bitmapSize > 0 )
{
- long i;
- int j = 0;
-
- for ( i = 0; i < ISEC4_NumValues; i++ )
+ int j = 0;
+ for ( int i = 0; i < ISEC4_NumValues; i++ )
if ( IS_NOT_EQUAL(fsec4[i], FSEC3_MissVal) ) j++;
ISEC4_NumNonMissValues = j;
@@ -11629,7 +11054,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
if ( ISEC0_GRIB_Version == 1 ) isLen = 8;
esLen = 4;
- gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
+ int gribLen = isLen + pdsLen + gdsLen + bmsLen + bdsLen + esLen;
if ( ISEC0_GRIB_Len )
if ( ISEC0_GRIB_Len < gribLen )
@@ -11637,8 +11062,7 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
ISEC0_GRIB_Len = gribLen;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)(((size_t)gribLen + sizeof(int) - 1) / sizeof(int));
/*
----------------------------------------------------------------
@@ -11683,6 +11107,12 @@ void TEMPLATE(grib_decode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
/* GRIB block 0 - indicator block */
static
void encodeIS(GRIBPACK *lGrib, long *gribLen)
@@ -11745,20 +11175,20 @@ void encodeES(GRIBPACK *lGrib, long *gribLen, long bdsstart)
itemp = z / (-120);
itemp = JP23SET - itemp + 1;
- lGrib[4] = itemp >> 16;
- lGrib[5] = itemp >> 8;
- lGrib[6] = itemp;
+ lGrib[4] = (GRIBPACK)(itemp >> 16);
+ lGrib[5] = (GRIBPACK)(itemp >> 8);
+ lGrib[6] = (GRIBPACK)itemp;
bdslen = z - bdslen;
- lGrib[bdsstart ] = bdslen >> 16;
- lGrib[bdsstart+1] = bdslen >> 8;
- lGrib[bdsstart+2] = bdslen;
+ lGrib[bdsstart ] = (GRIBPACK)(bdslen >> 16);
+ lGrib[bdsstart+1] = (GRIBPACK)(bdslen >> 8);
+ lGrib[bdsstart+2] = (GRIBPACK)bdslen;
}
else
{
- lGrib[4] = z >> 16;
- lGrib[5] = z >> 8;
- lGrib[6] = z;
+ lGrib[4] = (GRIBPACK)(z >> 16);
+ lGrib[5] = (GRIBPACK)(z >> 8);
+ lGrib[6] = (GRIBPACK)z;
while ( z%8 ) lGrib[z++] = 0;
}
@@ -12030,6 +11460,7 @@ int BitsPerInt = (int) (sizeof(int) * 8);
#define T double
#ifdef T
+
static
void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
const T *data, T zref, T factor, size_t *gz)
@@ -12047,7 +11478,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
for ( i = packStart; i < datasize; i++ )
{
/* note float -> unsigned int .. truncate */
- ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+ ival = (unsigned int) ((data[i] - zref) * factor + (T)0.5);
/*
if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
if ( ival < 0 ) ival = 0;
@@ -12063,7 +11494,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
else
{
jbits -= cbits;
- lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+ lGrib[z++] = (GRIBPACK)((c << cbits) + ((ival >> jbits) & mask[cbits]));
cbits = 8;
c = 0;
}
@@ -12075,11 +11506,39 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
cbits -= jbits;
}
}
- if ( cbits != 8 ) lGrib[z++] = c << cbits;
+ if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
*gz = z;
}
+
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+ const T *restrict data, T zref, T factor, size_t *gz)
+{
+ U_BYTEORDER;
+ uint16_t *restrict sgrib = (uint16_t *) (lGrib+*gz);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ sgrib[i] = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ ui16 = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ sgrib[i] = gribSwapByteOrder_uint16(ui16);
+ }
+ }
+
+ *gz += 2*datasize;
+}
+/*
static
void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
const T *restrict data, T zref, T factor, size_t *gz)
@@ -12099,7 +11558,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui16 = (uint16_t) tmp;
lGrib[z ] = ui16 >> 8;
lGrib[z+1] = ui16;
@@ -12108,7 +11567,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
*gz = z;
}
-
+*/
static
void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
GRIBPACK *restrict lGrib,
@@ -12118,7 +11577,6 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
uint64_t start_minmax, end_minmax;
#endif
-
uint32_t ui32;
size_t i, z = *gz;
T tmp;
@@ -12143,8 +11601,8 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
- lGrib[z ] = (uint16_t) tmp;
+ tmp = ((data[i] - zref) * factor + (T)0.5);
+ lGrib[z ] = (GRIBPACK)tmp;
z++;
}
@@ -12161,10 +11619,9 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#elif defined _GET_MACH_COUNTER
start_minmax = mach_absolute_time();
#endif
-
if ( sizeof(T) == sizeof(double) )
{
- grib_encode_array_2byte_double(datasize, lGrib, (const double * restrict) data, zref, factor, &z);
+ grib_encode_array_2byte_double(datasize, lGrib, (const double *) data, zref, factor, &z);
}
else
{
@@ -12207,11 +11664,11 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 16;
- lGrib[z+1] = ui32 >> 8;
- lGrib[z+2] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+2] = (GRIBPACK)ui32;
z += 3;
}
@@ -12236,12 +11693,12 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 24;
- lGrib[z+1] = ui32 >> 16;
- lGrib[z+2] = ui32 >> 8;
- lGrib[z+3] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 24);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+3] = (GRIBPACK)ui32;
z += 4;
}
@@ -12275,12 +11732,11 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _ARCH_PWR6
#define __UNROLL_DEPTH_2 8
#else
-#define __UNROLL_DEPTH_2 8
+#define __UNROLL_DEPTH_2 128
#endif
size_t residual;
size_t ofs;
T dval[__UNROLL_DEPTH_2];
- unsigned long ival;
data += packStart;
datasize -= packStart;
@@ -12291,29 +11747,37 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
if ( numBits == 8 )
{
- unsigned char *cgrib = (unsigned char *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(2, "pack 8 bit unrolled");
#endif
+ unsigned char *cgrib = (unsigned char *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += __UNROLL_DEPTH_2;
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += residual;
@@ -12323,21 +11787,31 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
}
else if ( numBits == 16 )
{
- unsigned short *sgrib = (unsigned short *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(3, "pack 16 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint16_t ival;
+#endif
+ uint16_t *sgrib = (uint16_t *) (lGrib+z);
+
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*__UNROLL_DEPTH_2;
}
@@ -12345,22 +11819,25 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
- z += 2;
+ ival = (uint16_t) dval[j];
+ *sgrib++ = gribSwapByteOrder_uint16(ival);
}
+ z += 2*__UNROLL_DEPTH_2;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*residual;
}
@@ -12368,9 +11845,9 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
+ ival = (uint16_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 8);
+ lGrib[z+1] = (GRIBPACK)ival;
z += 2;
}
}
@@ -12383,31 +11860,40 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(4, "pack 24 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+#else
+ ival = (uint32_t) dval[j];
+#endif
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
#ifdef _GET_IBM_COUNTER
@@ -12419,18 +11905,27 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(5, "pack 32 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
unsigned int *igrib = (unsigned int *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
- {
+ {
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
@@ -12439,37 +11934,41 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
}
else
{
- for (j = 0; j < residual; j++)
+ for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
@@ -12495,12 +11994,19 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
#define T float
#ifdef T
+
static
void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datasize, GRIBPACK *lGrib,
const T *data, T zref, T factor, size_t *gz)
@@ -12518,7 +12024,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
for ( i = packStart; i < datasize; i++ )
{
/* note float -> unsigned int .. truncate */
- ival = (unsigned int) ((data[i] - zref) * factor + 0.5);
+ ival = (unsigned int) ((data[i] - zref) * factor + (T)0.5);
/*
if ( ival > max_nbpv_pow2 ) ival = max_nbpv_pow2;
if ( ival < 0 ) ival = 0;
@@ -12534,7 +12040,7 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
else
{
jbits -= cbits;
- lGrib[z++] = (c << cbits) + ((ival >> jbits) & mask[cbits]);
+ lGrib[z++] = (GRIBPACK)((c << cbits) + ((ival >> jbits) & mask[cbits]));
cbits = 8;
c = 0;
}
@@ -12546,11 +12052,39 @@ void TEMPLATE(encode_array_common,T)(int numBits, size_t packStart, size_t datas
cbits -= jbits;
}
}
- if ( cbits != 8 ) lGrib[z++] = c << cbits;
+ if ( cbits != 8 ) lGrib[z++] = (GRIBPACK)(c << cbits);
*gz = z;
}
+
+static
+void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
+ const T *restrict data, T zref, T factor, size_t *gz)
+{
+ U_BYTEORDER;
+ uint16_t *restrict sgrib = (uint16_t *) (lGrib+*gz);
+
+ if ( IS_BIGENDIAN() )
+ {
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ sgrib[i] = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ }
+ }
+ else
+ {
+ uint16_t ui16;
+ for ( size_t i = 0; i < datasize; i++ )
+ {
+ ui16 = (uint16_t) ((data[i] - zref) * factor + (T)0.5);
+ sgrib[i] = gribSwapByteOrder_uint16(ui16);
+ }
+ }
+
+ *gz += 2*datasize;
+}
+/*
static
void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
const T *restrict data, T zref, T factor, size_t *gz)
@@ -12570,7 +12104,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui16 = (uint16_t) tmp;
lGrib[z ] = ui16 >> 8;
lGrib[z+1] = ui16;
@@ -12579,7 +12113,7 @@ void TEMPLATE(encode_array_2byte,T)(size_t datasize, GRIBPACK *restrict lGrib,
*gz = z;
}
-
+*/
static
void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
GRIBPACK *restrict lGrib,
@@ -12589,7 +12123,6 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#if defined _GET_X86_COUNTER || defined _GET_MACH_COUNTER
uint64_t start_minmax, end_minmax;
#endif
-
uint32_t ui32;
size_t i, z = *gz;
T tmp;
@@ -12614,8 +12147,8 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
- lGrib[z ] = (uint16_t) tmp;
+ tmp = ((data[i] - zref) * factor + (T)0.5);
+ lGrib[z ] = (GRIBPACK)tmp;
z++;
}
@@ -12632,10 +12165,9 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#elif defined _GET_MACH_COUNTER
start_minmax = mach_absolute_time();
#endif
-
if ( sizeof(T) == sizeof(double) )
{
- grib_encode_array_2byte_double(datasize, lGrib, (const double * restrict) data, zref, factor, &z);
+ grib_encode_array_2byte_double(datasize, lGrib, (const double *) data, zref, factor, &z);
}
else
{
@@ -12678,11 +12210,11 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 16;
- lGrib[z+1] = ui32 >> 8;
- lGrib[z+2] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+2] = (GRIBPACK)ui32;
z += 3;
}
@@ -12707,12 +12239,12 @@ void TEMPLATE(encode_array,T)(int numBits, size_t packStart, size_t datasize,
#endif
for ( i = 0; i < datasize; i++ )
{
- tmp = ((data[i] - zref) * factor + 0.5);
+ tmp = ((data[i] - zref) * factor + (T)0.5);
ui32 = (uint32_t) tmp;
- lGrib[z ] = ui32 >> 24;
- lGrib[z+1] = ui32 >> 16;
- lGrib[z+2] = ui32 >> 8;
- lGrib[z+3] = ui32;
+ lGrib[z ] = (GRIBPACK)(ui32 >> 24);
+ lGrib[z+1] = (GRIBPACK)(ui32 >> 16);
+ lGrib[z+2] = (GRIBPACK)(ui32 >> 8);
+ lGrib[z+3] = (GRIBPACK)ui32;
z += 4;
}
@@ -12746,12 +12278,11 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _ARCH_PWR6
#define __UNROLL_DEPTH_2 8
#else
-#define __UNROLL_DEPTH_2 8
+#define __UNROLL_DEPTH_2 128
#endif
size_t residual;
size_t ofs;
T dval[__UNROLL_DEPTH_2];
- unsigned long ival;
data += packStart;
datasize -= packStart;
@@ -12762,29 +12293,37 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
if ( numBits == 8 )
{
- unsigned char *cgrib = (unsigned char *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(2, "pack 8 bit unrolled");
#endif
+ unsigned char *cgrib = (unsigned char *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += __UNROLL_DEPTH_2;
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*cgrib++ = (unsigned long) dval[j];
+#else
+ *cgrib++ = (unsigned char) dval[j];
+#endif
}
z += residual;
@@ -12794,21 +12333,31 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
}
else if ( numBits == 16 )
{
- unsigned short *sgrib = (unsigned short *) (lGrib + z);
#ifdef _GET_IBM_COUNTER
hpmStart(3, "pack 16 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint16_t ival;
+#endif
+ uint16_t *sgrib = (uint16_t *) (lGrib+z);
+
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*__UNROLL_DEPTH_2;
}
@@ -12816,22 +12365,25 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
- z += 2;
+ ival = (uint16_t) dval[j];
+ *sgrib++ = gribSwapByteOrder_uint16(ival);
}
+ z += 2*__UNROLL_DEPTH_2;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*sgrib++ = (unsigned long) dval[j];
+#else
+ *sgrib++ = (uint16_t) dval[j];
+#endif
}
z += 2*residual;
}
@@ -12839,9 +12391,9 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 8;
- lGrib[z+1] = ival;
+ ival = (uint16_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 8);
+ lGrib[z+1] = (GRIBPACK)ival;
z += 2;
}
}
@@ -12854,31 +12406,40 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(4, "pack 24 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+#else
+ ival = (uint32_t) dval[j];
+#endif
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 16;
- lGrib[z+1] = ival >> 8;
- lGrib[z+2] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 16);
+ lGrib[z+1] = (GRIBPACK)(ival >> 8);
+ lGrib[z+2] = (GRIBPACK)ival;
z += 3;
}
#ifdef _GET_IBM_COUNTER
@@ -12890,18 +12451,27 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#ifdef _GET_IBM_COUNTER
hpmStart(5, "pack 32 bit unrolled");
#endif
+#ifdef _ARCH_PWR6
+ unsigned long ival;
+#else
+ uint32_t ival;
+#endif
unsigned int *igrib = (unsigned int *) (lGrib + z);
for ( i = 0; i < datasize - residual; i += __UNROLL_DEPTH_2 )
- {
+ {
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- dval[j] = ((data[i+j] - zref) * factor + 0.5);
+ dval[j] = ((data[i+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
@@ -12910,37 +12480,41 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
{
for (j = 0; j < __UNROLL_DEPTH_2; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
}
for (j = 0; j < residual; j++)
{
- dval[j] = ((data[ofs+j] - zref) * factor + 0.5);
+ dval[j] = ((data[ofs+j] - zref) * factor + (T)0.5);
}
if ( IS_BIGENDIAN() )
{
for (j = 0; j < residual; j++)
{
+#ifdef _ARCH_PWR6
*igrib = (unsigned long) dval[j];
+#else
+ *igrib = (uint32_t) dval[j];
+#endif
igrib++;
z += 4;
}
}
else
{
- for (j = 0; j < residual; j++)
+ for (j = 0; j < residual; j++)
{
- ival = (unsigned long) dval[j];
- lGrib[z ] = ival >> 24;
- lGrib[z+1] = ival >> 16;
- lGrib[z+2] = ival >> 8;
- lGrib[z+3] = ival;
+ ival = (uint32_t) dval[j];
+ lGrib[z ] = (GRIBPACK)(ival >> 24);
+ lGrib[z+1] = (GRIBPACK)(ival >> 16);
+ lGrib[z+2] = (GRIBPACK)(ival >> 8);
+ lGrib[z+3] = (GRIBPACK)ival;
z += 4;
}
}
@@ -12966,6 +12540,12 @@ void TEMPLATE(encode_array_unrolled,T)(int numBits, size_t packStart, size_t dat
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
@@ -13066,8 +12646,8 @@ void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
}
else
{
- lonIncr = ISEC2_LonIncr;
- latIncr = ISEC2_LatIncr;
+ lonIncr = (unsigned)ISEC2_LonIncr;
+ latIncr = (unsigned)ISEC2_LatIncr;
}
Put2Byte(lonIncr); /* 23-24 i - direction increment */
if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
@@ -13180,7 +12760,7 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
{
data[fsec4size++] = data[i];
- bitmap[i/8] |= 1<<(7-(i&7));
+ bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
}
}
#endif
@@ -13206,36 +12786,33 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
/* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
/* Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow */
- size_t z = *gribLen;
- long i, jloop;
+ size_t z = (size_t)*gribLen;
+ long i;
int numBits;
int ival;
- int blockLength, PackStart = 0, Flag = 0;
+ long PackStart = 0, Flag = 0;
int binscale = 0;
int nbpv;
int bds_head = 11;
int bds_ext = 0;
/* ibits = BitsPerInt; */
- unsigned int max_nbpv_pow2;
int exponent, mantissa;
- int unused_bits = 0;
int lspherc = FALSE, lcomplex = FALSE;
int isubset = 0, itemp = 0, itrunc = 0;
T factor = 1, fmin, fmax;
double zref;
- double range, rangec;
+ double range;
double jpepsln = 1.0e-12; /* -----> tolerance used to check equality */
/* of floating point numbers - needed */
/* on some platforms (eg vpp700, linux) */
- extern const double _pow2tab[158];
extern int CGRIBEX_Const; /* 1: Don't pack constant fields on regular grids */
if ( isec2 )
{
/* If section 2 is present, it says if data is spherical harmonic */
- if ( isec2[0] == 50 || isec2[0] == 60 ||
- isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
+ lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
+ isec2[0] == 70 || isec2[0] == 80 );
if ( lspherc )
isec4[2] = 128;
@@ -13318,7 +12895,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
pcStart = isubset;
pcScale = isec4[16];
TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
- TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+ TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
}
fmin = fmax = data[PackStart];
@@ -13334,10 +12911,10 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
- blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
- if ( (blockLength%2) == 1 ) blockLength++;
+ long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+ blockLength += blockLength & 1;
- unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+ long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
Flag += unused_bits;
@@ -13375,57 +12952,54 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
else if ( range > 1.0 )
{
- rangec = range + jpepsln;
- for ( jloop = 1; jloop < 128; jloop++ )
- {
- if ( _pow2tab[jloop] > rangec ) break;
- }
- if ( jloop == 128 )
- {
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
- }
+ double rangec = range + jpepsln,
+ p2 = 2.0;
+ long jloop = 1;
+ while ( jloop < 128 && p2 <= rangec )
+ {
+ p2 *= 2.0;
+ ++jloop;
+ }
+ if (jloop < 128)
+ binscale = jloop - nbpv;
else
- {
- binscale = jloop - nbpv;
- }
+ {
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
+ }
}
else
{
- rangec = range - jpepsln;
- for ( jloop = 1; jloop < 127; jloop++ )
+ double rangec = range - jpepsln, p05 = 0.5;
+ long jloop = 1;
+ while ( jloop < 127 && p05 >= rangec )
{
- if ( 1.0/_pow2tab[jloop] < rangec ) break;
+ p05 *= 0.5;
+ jloop++;
}
- if ( jloop == 127 )
+ if ( jloop < 127 )
{
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
+ binscale = 1 - jloop - nbpv;
}
else
{
- binscale = 1 - jloop - nbpv;
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
}
}
- //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
- max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
+ uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
if ( binscale != 0 )
{
if ( binscale < 0 )
- {
- if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
else
- {
- if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- if ( binscale < 0 ) factor = intpow2(-binscale);
- else factor = 1.0/intpow2( binscale);
+ factor = intpow2(-binscale);
}
ref2ibm(&zref, BitsPerInt);
@@ -13442,7 +13016,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
if ( lcomplex )
{
int jup = isubset;
- int ioff = z + bds_ext;
+ int ioff = (int)z + bds_ext;
if ( ioff > 0xFFFF ) ioff = 0;
Put2Byte(ioff);
Put2Int(isec4[16]);
@@ -13460,14 +13034,14 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
*datsize = ((datasize-PackStart)*nbpv + 7)/8;
#if defined (_ARCH_PWR6)
- TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#else
- TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#endif
if ( unused_bits >= 8 ) Put1Byte(0); /* Fillbyte */
- *gribLen = z;
+ *gribLen = (long)z;
return (0);
}
@@ -13482,9 +13056,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
GRIBPACK *lpds;
unsigned char *CGrib;
long fsec4size = 0;
- int numBytes;
int bmsIncluded;
- size_t len;
GRIBPACK *lGrib;
long datstart, datsize, bdsstart;
int status = 0;
@@ -13499,15 +13071,15 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
bmsIncluded = ISEC1_Sec2Or3Flag & 64;
/* set max header len */
- len = 16384;
+ size_t len = 16384;
/* add data len */
- numBytes = (ISEC4_NumBits+7)>>3;
+ size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
- len += numBytes*klenp;
+ len += numBytes*(size_t)klenp;
/* add bitmap len */
- if ( bmsIncluded ) len += (klenp+7)>>3;
+ if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
#if defined (VECTORCODE)
lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
@@ -13563,7 +13135,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
encodeES(lGrib, &gribLen, bdsstart);
- if ( (size_t) gribLen > kleng*sizeof(int) )
+ if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
#if defined (VECTORCODE)
@@ -13575,17 +13147,22 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
Free(lGrib);
#endif
- ISEC0_GRIB_Len = gribLen;
+ ISEC0_GRIB_Len = (int)gribLen;
ISEC0_GRIB_Version = 1;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
*kret = status;
}
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
#ifdef T
#undef T
#endif
@@ -13685,8 +13262,8 @@ void TEMPLATE(encodeGDS,T)(GRIBPACK *lGrib, long *gribLen, int *isec2, T *fsec2)
}
else
{
- lonIncr = ISEC2_LonIncr;
- latIncr = ISEC2_LatIncr;
+ lonIncr = (unsigned)ISEC2_LonIncr;
+ latIncr = (unsigned)ISEC2_LatIncr;
}
Put2Byte(lonIncr); /* 23-24 i - direction increment */
if ( ISEC2_GridType == GRIB1_GTYPE_GAUSSIAN )
@@ -13799,7 +13376,7 @@ void TEMPLATE(encodeBMS,T)(GRIBPACK *lGrib, long *gribLen, T *fsec3, int *isec4,
if ( IS_NOT_EQUAL(data[i], FSEC3_MissVal) )
{
data[fsec4size++] = data[i];
- bitmap[i/8] |= 1<<(7-(i&7));
+ bitmap[i/8] |= (GRIBPACK)(1<<(7-(i&7)));
}
}
#endif
@@ -13825,36 +13402,33 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
/* Uwe Schulzweida, 11/04/2003 : Check that number of bits per value is not exceeded */
/* Uwe Schulzweida, 6/05/2003 : Copy result to fpval to prevent integer overflow */
- size_t z = *gribLen;
- long i, jloop;
+ size_t z = (size_t)*gribLen;
+ long i;
int numBits;
int ival;
- int blockLength, PackStart = 0, Flag = 0;
+ long PackStart = 0, Flag = 0;
int binscale = 0;
int nbpv;
int bds_head = 11;
int bds_ext = 0;
/* ibits = BitsPerInt; */
- unsigned int max_nbpv_pow2;
int exponent, mantissa;
- int unused_bits = 0;
int lspherc = FALSE, lcomplex = FALSE;
int isubset = 0, itemp = 0, itrunc = 0;
T factor = 1, fmin, fmax;
double zref;
- double range, rangec;
+ double range;
double jpepsln = 1.0e-12; /* -----> tolerance used to check equality */
/* of floating point numbers - needed */
/* on some platforms (eg vpp700, linux) */
- extern const double _pow2tab[158];
extern int CGRIBEX_Const; /* 1: Don't pack constant fields on regular grids */
if ( isec2 )
{
/* If section 2 is present, it says if data is spherical harmonic */
- if ( isec2[0] == 50 || isec2[0] == 60 ||
- isec2[0] == 70 || isec2[0] == 80 ) lspherc = TRUE;
+ lspherc = ( isec2[0] == 50 || isec2[0] == 60 ||
+ isec2[0] == 70 || isec2[0] == 80 );
if ( lspherc )
isec4[2] = 128;
@@ -13937,7 +13511,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
pcStart = isubset;
pcScale = isec4[16];
TEMPLATE(scale_complex,T)(data, pcStart, pcScale, itrunc, 0);
- TEMPLATE(gather_complex,T)(data, pcStart, itrunc, datasize);
+ TEMPLATE(gather_complex,T)(data, (size_t)pcStart, (size_t)itrunc, (size_t)datasize);
}
fmin = fmax = data[PackStart];
@@ -13953,10 +13527,10 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
- blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
- if ( (blockLength%2) == 1 ) blockLength++;
+ long blockLength = (*datstart) + (nbpv*(datasize - PackStart) + 7)/8;
+ blockLength += blockLength & 1;
- unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
+ long unused_bits = blockLength*8 - (*datstart)*8 - nbpv*(datasize - PackStart);
Flag += unused_bits;
@@ -13994,57 +13568,54 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
}
else if ( range > 1.0 )
{
- rangec = range + jpepsln;
- for ( jloop = 1; jloop < 128; jloop++ )
- {
- if ( _pow2tab[jloop] > rangec ) break;
- }
- if ( jloop == 128 )
- {
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
- }
+ double rangec = range + jpepsln,
+ p2 = 2.0;
+ long jloop = 1;
+ while ( jloop < 128 && p2 <= rangec )
+ {
+ p2 *= 2.0;
+ ++jloop;
+ }
+ if (jloop < 128)
+ binscale = jloop - nbpv;
else
- {
- binscale = jloop - nbpv;
- }
+ {
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "> range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
+ }
}
else
{
- rangec = range - jpepsln;
- for ( jloop = 1; jloop < 127; jloop++ )
+ double rangec = range - jpepsln, p05 = 0.5;
+ long jloop = 1;
+ while ( jloop < 127 && p05 >= rangec )
{
- if ( 1.0/_pow2tab[jloop] < rangec ) break;
+ p05 *= 0.5;
+ jloop++;
}
- if ( jloop == 127 )
+ if ( jloop < 127 )
{
- gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
- gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
- return (707);
+ binscale = 1 - jloop - nbpv;
}
else
{
- binscale = 1 - jloop - nbpv;
+ gprintf(__func__, "Problem calculating binary scale value for encode code %d!", code);
+ gprintf(__func__, "< range %g rangec %g fmin %g fmax %g", range, rangec, fmin, fmax);
+ return (707);
}
}
- //max_nbpv_pow2 = (unsigned) (intpow2(nbpv) - 1);
- max_nbpv_pow2 = (unsigned) ((1ULL << nbpv) - 1);
+ uint64_t max_nbpv_pow2 = (uint64_t) ((1ULL << nbpv) - 1);
if ( binscale != 0 )
{
if ( binscale < 0 )
- {
- if ( (unsigned)(range*intpow2(-binscale)+0.5) > max_nbpv_pow2 ) binscale++;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale++;
else
- {
- if ( (unsigned)(range/intpow2(binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- }
+ while ( (uint64_t)(ldexp(range, -binscale)+0.5) > max_nbpv_pow2 ) binscale--;
- if ( binscale < 0 ) factor = intpow2(-binscale);
- else factor = 1.0/intpow2( binscale);
+ factor = intpow2(-binscale);
}
ref2ibm(&zref, BitsPerInt);
@@ -14061,7 +13632,7 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
if ( lcomplex )
{
int jup = isubset;
- int ioff = z + bds_ext;
+ int ioff = (int)z + bds_ext;
if ( ioff > 0xFFFF ) ioff = 0;
Put2Byte(ioff);
Put2Int(isec4[16]);
@@ -14079,14 +13650,14 @@ int TEMPLATE(encodeBDS,T)(GRIBPACK *lGrib, long *gribLen, int decscale, int *ise
*datsize = ((datasize-PackStart)*nbpv + 7)/8;
#if defined (_ARCH_PWR6)
- TEMPLATE(encode_array_unrolled,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array_unrolled,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#else
- TEMPLATE(encode_array,T)(nbpv, PackStart, datasize, lGrib, data, (T)zref, factor, &z);
+ TEMPLATE(encode_array,T)(nbpv, (size_t)PackStart, (size_t)datasize, lGrib, data, (T)zref, factor, &z);
#endif
if ( unused_bits >= 8 ) Put1Byte(0); /* Fillbyte */
- *gribLen = z;
+ *gribLen = (long)z;
return (0);
}
@@ -14101,9 +13672,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
GRIBPACK *lpds;
unsigned char *CGrib;
long fsec4size = 0;
- int numBytes;
int bmsIncluded;
- size_t len;
GRIBPACK *lGrib;
long datstart, datsize, bdsstart;
int status = 0;
@@ -14118,15 +13687,15 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
bmsIncluded = ISEC1_Sec2Or3Flag & 64;
/* set max header len */
- len = 16384;
+ size_t len = 16384;
/* add data len */
- numBytes = (ISEC4_NumBits+7)>>3;
+ size_t numBytes = (size_t)((ISEC4_NumBits+7)>>3);
- len += numBytes*klenp;
+ len += numBytes*(size_t)klenp;
/* add bitmap len */
- if ( bmsIncluded ) len += (klenp+7)>>3;
+ if ( bmsIncluded ) len += (size_t)((klenp+7)>>3);
#if defined (VECTORCODE)
lGrib = (GRIBPACK*) Malloc(len*sizeof(GRIBPACK));
@@ -14182,7 +13751,7 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
encodeES(lGrib, &gribLen, bdsstart);
- if ( (size_t) gribLen > kleng*sizeof(int) )
+ if ( (size_t) gribLen > (size_t)kleng*sizeof(int) )
Error("kgrib buffer too small! kleng = %d gribLen = %d", kleng, gribLen);
#if defined (VECTORCODE)
@@ -14194,23 +13763,28 @@ void TEMPLATE(grib_encode,T)(int *isec0, int *isec1, int *isec2, T *fsec2, int *
Free(lGrib);
#endif
- ISEC0_GRIB_Len = gribLen;
+ ISEC0_GRIB_Len = (int)gribLen;
ISEC0_GRIB_Version = 1;
- *kword = gribLen / sizeof(int);
- if ( (size_t) gribLen != *kword * sizeof(int) ) *kword += 1;
+ *kword = (int)((gribLen + (long)sizeof(int) - 1) / (long)sizeof(int));
*kret = status;
}
#endif /* T */
+/*
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
void encode_dummy(void)
{
(void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
(void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
}
-static const char grb_libvers[] = "1.7.3" " of ""Sep 14 2015"" ""10:58:44";
+static const char grb_libvers[] = "1.7.4" " of ""Feb 19 2016"" ""11:03:41";
const char *
cgribexLibraryVersion(void)
{
diff --git a/libcdi/src/config.h.in b/libcdi/src/config.h.in
index 230bf53..f7ceef6 100644
--- a/libcdi/src/config.h.in
+++ b/libcdi/src/config.h.in
@@ -58,8 +58,7 @@
don't. */
#undef HAVE_DECL__SC_PAGE_SIZE
-/* Define to 1 if you have the declaration of `__builtin_ctz', and to 0 if you
- don't. */
+/* Define to 1 if __builtin_ctz is available, 0 if not */
#undef HAVE_DECL___BUILTIN_CTZ
/* Define to 1 if you have the <dlfcn.h> header file. */
diff --git a/libcdi/src/create_uuid.h b/libcdi/src/create_uuid.h
deleted file mode 100644
index 30566d2..0000000
--- a/libcdi/src/create_uuid.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef CREATE_UUID_H
-#define CREATE_UUID_H
-
-#if defined (HAVE_CONFIG_H)
-# include "config.h"
-#endif
-
-#include "cdi.h"
-
-void
-create_uuid(unsigned char uuid[CDI_UUID_SIZE]);
-
-#endif
-
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/libcdi/src/dmemory.h b/libcdi/src/dmemory.h
index d5f60a9..90ec1f0 100644
--- a/libcdi/src/dmemory.h
+++ b/libcdi/src/dmemory.h
@@ -10,6 +10,10 @@
#define WITH_FUNCTION_NAME
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern size_t memTotal(void);
extern void memDebug(int debug);
extern void memExitOnError(void);
@@ -21,6 +25,10 @@ extern void *memCalloc (size_t nmemb, size_t size, const char *file, const cha
extern void *memMalloc (size_t size, const char *file, const char *functionname, int line);
extern void memFree (void *ptr, const char *file, const char *functionname, int line);
+#if defined (__cplusplus)
+}
+#endif
+
#if defined WITH_FUNCTION_NAME
# define Realloc(p, s) memRealloc((p), (s), __FILE__, __func__, __LINE__)
# define Calloc(n, s) memCalloc((n), (s), __FILE__, __func__, __LINE__)
diff --git a/libcdi/src/error.c b/libcdi/src/error.c
index 7d488a9..5d1c345 100644
--- a/libcdi/src/error.c
+++ b/libcdi/src/error.c
@@ -27,6 +27,7 @@ void SysError_(const char *caller, const char *fmt, ...)
void SysError_(const char *caller, const char *fmt, ...)
{
va_list args;
+ int saved_errno = errno;
va_start(args, fmt);
@@ -37,8 +38,11 @@ void SysError_(const char *caller, const char *fmt, ...)
va_end(args);
- if ( errno )
- perror("System error message ");
+ if ( saved_errno )
+ {
+ errno = saved_errno;
+ perror("System error message");
+ }
exit(EXIT_FAILURE);
}
diff --git a/libcdi/src/error.h b/libcdi/src/error.h
index 77ea2b5..58b7288 100644
--- a/libcdi/src/error.h
+++ b/libcdi/src/error.h
@@ -8,9 +8,9 @@
#define WITH_CALLER_NAME
#endif
-#define _FATAL 1 /* Error flag: exit on error */
-#define _VERBOSE 2 /* Error flag: report errors */
-#define _DEBUG 4 /* Error flag: debug */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern int _ExitOnError; /* If set to 1, exit on error (default 1) */
extern int _Verbose; /* If set to 1, errors are reported (default 1) */
@@ -66,6 +66,10 @@ cdiAbortC_serial(const char *caller, const char *filename,
const char *errorString, va_list ap)
__attribute__((noreturn));
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _ERROR_H */
/*
* Local Variables:
diff --git a/libcdi/src/gaussgrid.h b/libcdi/src/gaussgrid.h
index c431324..e33df5e 100644
--- a/libcdi/src/gaussgrid.h
+++ b/libcdi/src/gaussgrid.h
@@ -1,7 +1,15 @@
#ifndef _GAUSSGRID_H
#define _GAUSSGRID_H
-void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+
+#if defined (__cplusplus)
+}
+#endif
#endif /* _GAUSSGRID_H */
/*
diff --git a/libcdi/src/grb_read.c b/libcdi/src/grb_read.c
new file mode 100644
index 0000000..4e52232
--- /dev/null
+++ b/libcdi/src/grb_read.c
@@ -0,0 +1,239 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBGRIB
+
+#include "dmemory.h"
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_cgribex.h"
+#include "stream_grb.h"
+#include "stream_gribapi.h"
+#include "file.h"
+#include "cgribex.h" /* gribZip gribGetZip gribGinfo */
+#include "gribapi.h"
+#include "namespace.h"
+
+
+static
+int grbDecode(int filetype, int memtype, void *gribbuffer, int gribsize, void *data, size_t datasize,
+ int unreduced, int *nmiss, double missval, int vlistID, int varID)
+{
+ int status = 0;
+
+#if defined (HAVE_LIBCGRIBEX)
+ if ( filetype == FILETYPE_GRB )
+ {
+#if defined (HAVE_LIBGRIB_API)
+ extern int cdiNAdditionalGRIBKeys;
+ if ( cdiNAdditionalGRIBKeys > 0 )
+ Error("CGRIBEX decode does not support reading of additional GRIB keys!");
+#endif
+ status = cgribexDecode(memtype, gribbuffer, gribsize, data, (long) datasize, unreduced, nmiss, missval);
+ }
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ {
+ void *datap = data;
+ if ( memtype == MEMTYPE_FLOAT )
+ datap = Malloc(datasize*sizeof(double));
+
+ status = gribapiDecode(gribbuffer, gribsize, datap, (long) datasize, unreduced, nmiss, missval, vlistID, varID);
+
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ float *dataf = (float*) data;
+ double *datad = (double*) datap;
+ for ( size_t i = 0; i < datasize; ++i ) dataf[i] = (float) datad[i];
+ free((void*)datap);
+ }
+ }
+#else
+ {
+ (void)vlistID; (void)varID;
+ Error("GRIB_API support not compiled in!");
+ }
+#endif
+
+ return status;
+}
+
+static
+int grbUnzipRecord(void *gribbuffer, size_t *gribsize)
+{
+ int zip = 0;
+ int izip;
+ long unzipsize;
+
+ size_t igribsize = *gribsize;
+ size_t ogribsize = *gribsize;
+
+ if ( (izip = gribGetZip((long)igribsize, (unsigned char *)gribbuffer, &unzipsize)) > 0 )
+ {
+ zip = izip;
+ if ( izip == 128 ) /* szip */
+ {
+ unsigned char *itmpbuffer = NULL;
+ size_t itmpbuffersize = 0;
+
+ if ( unzipsize < (long) igribsize )
+ {
+ fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
+ return (0);
+ }
+
+ if ( itmpbuffersize < igribsize )
+ {
+ itmpbuffersize = igribsize;
+ itmpbuffer = (unsigned char *) Realloc(itmpbuffer, itmpbuffersize);
+ }
+
+ memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
+
+ unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
+
+ ogribsize = (size_t)gribUnzip((unsigned char *)gribbuffer, unzipsize, itmpbuffer, (long)igribsize);
+
+ Free(itmpbuffer);
+
+ if ( ogribsize <= 0 ) Error("Decompression problem!");
+ }
+ else
+ {
+ Error("Decompression for %d not implemented!", izip);
+ }
+ }
+
+ *gribsize = ogribsize;
+
+ return zip;
+}
+
+
+void grb_read_record(stream_t * streamptr, int memtype, void *data, int *nmiss)
+{
+ int filetype = streamptr->filetype;
+
+ void *gribbuffer = streamptr->record->buffer;
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
+
+ streamptr->numvals += gridsize;
+
+ fileSetPos(fileID, recpos, SEEK_SET);
+
+ if (fileRead(fileID, gribbuffer, recsize) != recsize)
+ Error("Failed to read GRIB record");
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, data, (size_t)gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
+}
+
+
+void grb_read_var(stream_t * streamptr, int varID, int memtype, void *data, int *nmiss)
+{
+ int filetype = streamptr->filetype;
+
+ void *gribbuffer = streamptr->record->buffer;
+
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
+
+ off_t currentfilepos = fileGetPos(fileID);
+
+ int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
+ int nlevs = streamptr->vars[varID].recordTable[0].nlevs;
+ if ( CDI_Debug )
+ Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
+ *nmiss = 0;
+ for (int levelID = 0; levelID < nlevs; levelID++ )
+ {
+ int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+
+ fileSetPos(fileID, recpos, SEEK_SET);
+
+ fileRead(fileID, gribbuffer, recsize);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ int imiss;
+
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+ void *datap = NULL;
+ if ( memtype == MEMTYPE_FLOAT )
+ datap = (float*)data + levelID*gridsize;
+ else
+ datap = (double*)data + levelID*gridsize;
+
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, datap, (size_t)gridsize,
+ streamptr->unreduced, &imiss, missval, vlistID, varID);
+
+ *nmiss += imiss;
+ }
+
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+}
+
+
+void grb_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss)
+{
+ int filetype = streamptr->filetype;
+
+ void *gribbuffer = streamptr->record->buffer;
+
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int gridsize = gridInqSize(gridID);
+ int tsID = streamptr->curTsID;
+
+ if ( CDI_Debug )
+ Message("gridID = %d gridsize = %d", gridID, gridsize);
+
+ int fileID = streamptr->fileID;
+
+ off_t currentfilepos = fileGetPos(fileID);
+
+ int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
+
+ int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr->tsteps[tsID].records[recID].size;
+
+ if ( recsize == 0 )
+ Error("Internal problem! Recordsize is zero for record %d at timestep %d",
+ recID+1, tsID+1);
+
+ fileSetPos(fileID, recpos, SEEK_SET);
+ fileRead(fileID, gribbuffer, recsize);
+
+ streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
+
+ double missval = vlistInqVarMissval(vlistID, varID);
+ grbDecode(filetype, memtype, gribbuffer, (int)recsize, data, (size_t)gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
+
+ fileSetPos(fileID, currentfilepos, SEEK_SET);
+}
+
+#endif
diff --git a/libcdi/src/grb_write.c b/libcdi/src/grb_write.c
new file mode 100644
index 0000000..dd8cc9f
--- /dev/null
+++ b/libcdi/src/grb_write.c
@@ -0,0 +1,257 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_LIBGRIB
+
+#include "dmemory.h"
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_cgribex.h"
+#include "stream_grb.h"
+#include "stream_gribapi.h"
+#include "file.h"
+#include "cgribex.h" /* gribZip gribGetZip gribGinfo */
+#include "gribapi.h"
+#include "namespace.h"
+
+
+static
+size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
+ int date, int time, int tsteptype, int numavg,
+ size_t datasize, const void *data, int nmiss, void **gribbuffer,
+ int comptype, void *gribContainer)
+{
+ size_t nbytes = 0;
+
+#ifdef HAVE_LIBCGRIBEX
+ if ( filetype == FILETYPE_GRB )
+ {
+ size_t gribbuffersize = datasize*4+3000;
+ *gribbuffer = Malloc(gribbuffersize);
+
+ nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
+ date, time, tsteptype, numavg,
+ (long) datasize, data, nmiss, *gribbuffer, gribbuffersize);
+ }
+ else
+#endif
+#ifdef HAVE_LIBGRIB_API
+ {
+ const void *datap = data;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ const float *dataf = (const float*) data;
+ double *datad = (double*) Malloc(datasize*sizeof(double));
+ for ( size_t i = 0; i < datasize; ++i ) datad[i] = (double) dataf[i];
+ datap = (const void*) datad;
+ }
+
+ size_t gribbuffersize;
+ nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
+ date, time, tsteptype, numavg,
+ (long) datasize, datap, nmiss, gribbuffer, &gribbuffersize,
+ comptype, gribContainer);
+
+ if ( memtype == MEMTYPE_FLOAT ) free((void*)datap);
+ }
+#else
+ {
+ Error("GRIB_API support not compiled in!");
+ (void)gribContainer;
+ (void)comptype;
+ }
+#endif
+
+ return nbytes;
+}
+
+static
+size_t grbSzip(int filetype, void *gribbuffer, size_t gribbuffersize)
+{
+ size_t buffersize = gribbuffersize + 1000; /* compressed record can be greater than source record */
+ void *buffer = Malloc(buffersize);
+
+ /* memcpy(buffer, gribbuffer, gribbuffersize); */
+
+ size_t nbytes = 0;
+ if ( filetype == FILETYPE_GRB )
+ {
+ nbytes = (size_t)gribZip((unsigned char *)gribbuffer, (long) gribbuffersize, (unsigned char *)buffer, (long) buffersize);
+ }
+ else
+ {
+ static int lszip_warn = 1;
+ if ( lszip_warn ) Warning("Szip compression of GRIB2 records not implemented!");
+ lszip_warn = 0;
+ nbytes = gribbuffersize;
+ }
+
+ Free(buffer);
+
+ return nbytes;
+}
+
+
+void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
+{
+ int filetype = streamptr1->filetype;
+ int fileID1 = streamptr1->fileID;
+ int fileID2 = streamptr2->fileID;
+ int tsID = streamptr1->curTsID;
+ int vrecID = streamptr1->tsteps[tsID].curRecID;
+ int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
+ off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
+ size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
+
+ fileSetPos(fileID1, recpos, SEEK_SET);
+
+ /* round up recsize to next multiple of 8 */
+ size_t gribbuffersize = ((recsize + 7U) & ~7U);
+
+ unsigned char *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
+
+ if (fileRead(fileID1, gribbuffer, recsize) != recsize)
+ Error("Could not read GRIB record for copying!");
+
+ size_t nbytes = recsize;
+
+ if ( filetype == FILETYPE_GRB )
+ {
+ long unzipsize;
+ int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
+
+ if ( izip == 0 && streamptr2->comptype == COMPRESS_SZIP )
+ nbytes = grbSzip(filetype, gribbuffer, nbytes);
+ }
+
+ while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
+
+ size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
+ if ( nwrite != nbytes )
+ {
+ perror(__func__);
+ Error("Could not write record for copying!");
+ }
+
+ Free(gribbuffer);
+}
+
+
+void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
+{
+ void *gribbuffer = NULL;
+ void *gc = NULL;
+
+ int filetype = streamptr->filetype;
+ int fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int tsteptype = vlistInqVarTsteptype(vlistID, varID);
+ int comptype = streamptr->comptype;
+ int tsID = streamptr->curTsID;
+ int date = streamptr->tsteps[tsID].taxis.vdate;
+ int time = streamptr->tsteps[tsID].taxis.vtime;
+ int numavg = 0;
+ if ( vlistInqVarTimave(vlistID, varID) )
+ numavg = streamptr->tsteps[tsID].taxis.numavg;
+
+ if ( CDI_Debug )
+ Message("gridID = %d zaxisID = %d", gridID, zaxisID);
+
+ size_t datasize = (size_t)gridInqSize(gridID);
+
+#ifdef HAVE_LIBCGRIBEX
+ if ( filetype == FILETYPE_GRB )
+ {
+ }
+ else
+#endif
+ {
+#ifdef GRIBCONTAINER2D
+ gribContainer_t **gribContainers = (gribContainer_t **) streamptr->gribContainers;
+ gc = (void *) &gribContainers[varID][levelID];
+#else
+ gribContainer_t *gribContainers = (gribContainer_t *) streamptr->gribContainers;
+ gc = (void *) &gribContainers[varID];
+#endif
+ }
+
+ if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
+
+ if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
+ {
+ static int ljpeg_warn = 1;
+ if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
+ ljpeg_warn = 0;
+ }
+
+ size_t nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
+ datasize, data, nmiss, &gribbuffer, comptype, gc);
+
+ if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
+ nbytes = grbSzip(filetype, gribbuffer, nbytes);
+
+ size_t (*myFileWrite)(int fileID, const void *restrict buffer,
+ size_t len, int tsID)
+ = (size_t (*)(int, const void *restrict, size_t, int))
+ namespaceSwitchGet(NSSWITCH_FILE_WRITE).func;
+ size_t nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
+
+ if ( nwrite != nbytes )
+ {
+ perror(__func__);
+ Error("Failed to write GRIB slice!");
+ }
+
+ if ( gribbuffer ) Free(gribbuffer);
+}
+
+
+void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
+{
+ int vlistID = streamptr->vlistID,
+ gridID = vlistInqVarGrid(vlistID, varID),
+ gridsize = gridInqSize(gridID),
+ zaxisID = vlistInqVarZaxis(vlistID, varID),
+ nlevs = zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ size_t chunkLen = (size_t)gridsize;
+ if ( memtype == MEMTYPE_FLOAT )
+ for ( int levelID = 0; levelID < nlevs; levelID++ )
+ {
+ const float *restrict fdata = ((const float *)data)+levelID*gridsize;
+
+ int nmiss_slice = 0;
+ if ( nmiss )
+ for ( size_t i = 0; i < chunkLen; ++i )
+ nmiss_slice += DBL_IS_EQUAL(fdata[i], missval);
+
+ grb_write_var_slice(streamptr, varID, levelID, memtype, fdata, nmiss_slice);
+ }
+ else
+ for ( int levelID = 0; levelID < nlevs; levelID++ )
+ {
+ const double *restrict ddata = ((const double *)data)+levelID*gridsize;
+
+ int nmiss_slice = 0;
+ if ( nmiss )
+ for ( size_t i = 0; i < chunkLen; ++i )
+ nmiss_slice += DBL_IS_EQUAL(ddata[i], missval);
+
+ grb_write_var_slice(streamptr, varID, levelID, memtype, ddata, nmiss_slice);
+ }
+}
+
+
+void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
+{
+ int varID = streamptr->record->varID;
+ int levelID = streamptr->record->levelID;
+
+ grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+}
+
+#endif
diff --git a/libcdi/src/gribapi_utilities.c b/libcdi/src/gribapi_utilities.c
index a8907ec..90a2a98 100644
--- a/libcdi/src/gribapi_utilities.c
+++ b/libcdi/src/gribapi_utilities.c
@@ -10,6 +10,7 @@
#include "dmemory.h"
#include "error.h"
#include "gribapi.h"
+#include "grid.h"
#include <assert.h>
#include <time.h>
@@ -274,7 +275,8 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
*outHaveForecastTime = false, *outHaveTimeRange = false;
return 0;
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 60: case 1000: case 1002: case 1100: case 40033:
+ //case 55 and case 40455 are the same: 55 is the proposed standard value, 40455 is the value in the local use range that is used by the dwd until the standard is updated.
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 60: case 1000: case 1002: case 1100: case 40033: case 40455:
*outHaveForecastTime = true, *outHaveTimeRange = false;
return 0;
@@ -287,24 +289,15 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast
}
}
-char* gribMakeTimeString(grib_handle* gh, bool getEndTime)
+char* gribMakeTimeString(grib_handle* gh, CdiTimeType timeType)
{
//Get the parts of the reference date.
-#ifdef __cplusplus
- struct tm date;
- date.tm_mon = (int) gribGetLong(gh, "month") - 1; //months are zero based in struct tm and one based in GRIBy
+ struct tm date;
+ date.tm_mon = (int)gribGetLong(gh, "month") - 1; //months are zero based in struct tm and one based in GRIB
+ date.tm_mday = (int)gribGetLong(gh, "day");
+ date.tm_hour = (int)gribGetLong(gh, "hour");
+ date.tm_min = (int)gribGetLong(gh, "minute");
- date.tm_mday = (int)gribGetLong(gh, "day");
- date.tm_hour = (int)gribGetLong(gh, "hour");
- date.tm_min = (int)gribGetLong(gh, "minute");
-#else
- struct tm date = {
- .tm_mon = (int)gribGetLong(gh, "month") - 1, //months are zero based in struct tm and one based in GRIBy
- .tm_mday = (int)gribGetLong(gh, "day"),
- .tm_hour = (int)gribGetLong(gh, "hour"),
- .tm_min = (int)gribGetLong(gh, "minute")
- };
-#endif
if(gribEditionNumber(gh) == 1)
{
date.tm_year = (int)gribGetLong(gh, "yearOfCentury"); //years are -1900 based both in struct tm and GRIB1
@@ -314,23 +307,27 @@ char* gribMakeTimeString(grib_handle* gh, bool getEndTime)
date.tm_year = (int)gribGetLong(gh, "year") - 1900; //years are -1900 based in struct tm and zero based in GRIB2
date.tm_sec = (int)gribGetLong(gh, "second");
- //Determine whether we have a forecast time and a time range.
- bool haveForecastTime, haveTimeRange;
- if(getAvailabilityOfRelativeTimes(gh, &haveForecastTime, &haveTimeRange)) return NULL;
- if(getEndTime && !haveTimeRange) return NULL; //tell the caller that the requested time does not exist
-
- //If we have relative times, apply them to the date
- if(haveForecastTime)
+ //If the start or end time are requested, we need to take the relative times into account.
+ if(timeType != kCdiTimeType_referenceTime)
{
- long offset = gribGetLongDefault(gh, "forecastTime", 0); //if(stepUnits == indicatorOfUnitOfTimeRange) assert(startStep == forecastTime)
- long offsetUnit = gribGetLongDefault(gh, "indicatorOfUnitOfTimeRange", 255);
- if(addToDate(&date, offset, offsetUnit)) return NULL;
- if(getEndTime)
+ //Determine whether we have a forecast time and a time range.
+ bool haveForecastTime, haveTimeRange;
+ if(getAvailabilityOfRelativeTimes(gh, &haveForecastTime, &haveTimeRange)) return NULL;
+ if(timeType == kCdiTimeType_endTime && !haveTimeRange) return NULL; //tell the caller that the requested time does not exist
+
+ //If we have relative times, apply the relative times to the date
+ if(haveForecastTime)
{
- assert(haveTimeRange);
- long range = gribGetLongDefault(gh, "lengthOfTimeRange", 0); //if(stepUnits == indicatorOfUnitForTimeRange) assert(endStep == startStep + lengthOfTimeRange)
- long rangeUnit = gribGetLongDefault(gh, "indicatorOfUnitForTimeRange", 255);
- if(addToDate(&date, range, rangeUnit)) return NULL;
+ long offset = gribGetLongDefault(gh, "forecastTime", 0); //if(stepUnits == indicatorOfUnitOfTimeRange) assert(startStep == forecastTime)
+ long offsetUnit = gribGetLongDefault(gh, "indicatorOfUnitOfTimeRange", 255);
+ if(addToDate(&date, offset, offsetUnit)) return NULL;
+ if(timeType == kCdiTimeType_endTime)
+ {
+ assert(haveTimeRange);
+ long range = gribGetLongDefault(gh, "lengthOfTimeRange", 0); //if(stepUnits == indicatorOfUnitForTimeRange) assert(endStep == startStep + lengthOfTimeRange)
+ long rangeUnit = gribGetLongDefault(gh, "indicatorOfUnitForTimeRange", 255);
+ if(addToDate(&date, range, rangeUnit)) return NULL;
+ }
}
}
}
@@ -461,7 +458,8 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
ISEC4_NumValues = ISEC2_NumLon*ISEC2_NumLat;
}
*/
- memset(grid, 0, sizeof(grid_t));
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
size_t datasize;
FAIL_ON_GRIB_ERROR(grib_get_size, gh, "values", &datasize);
diff --git a/libcdi/src/gribapi_utilities.h b/libcdi/src/gribapi_utilities.h
index 0f8a12c..b9f2084 100644
--- a/libcdi/src/gribapi_utilities.h
+++ b/libcdi/src/gribapi_utilities.h
@@ -3,6 +3,7 @@
#ifdef HAVE_LIBGRIB_API
+#include "cdi_int.h"
#include "grid.h"
#include <grib_api.h>
@@ -24,7 +25,7 @@ void gribGetDoubleArray(grib_handle* gribHandle, const char* key, double* array)
void gribGetLongArray(grib_handle* gribHandle, const char* key, long* array); //The caller is responsible to ensure a sufficiently large buffer.
long gribEditionNumber(grib_handle* gh);
-char* gribMakeTimeString(grib_handle* gh, bool getEndTime); //For statistical fields, setting getEndTime produces the time of the end of the integration period, otherwise the time of the start of the integration period is returned. Returns NULL if getEndTime is set and the field does not have an integration period.
+char* gribMakeTimeString(grib_handle* gh, CdiTimeType timeType); //Returns NULL if timeType is kCdiTimeType_endTime and the field does not have an integration period (statistical data).
int gribapiTimeIsFC(grib_handle *gh);
int gribapiGetTsteptype(grib_handle *gh);
int gribGetDatatype(grib_handle* gribHandle);
diff --git a/libcdi/src/grid.c b/libcdi/src/grid.c
index a2ff574..64cc1df 100644
--- a/libcdi/src/grid.c
+++ b/libcdi/src/grid.c
@@ -2,6 +2,7 @@
# include "config.h"
#endif
+#include <assert.h>
#include <string.h>
#include <float.h> /* FLT_EPSILON */
#include <limits.h> /* INT_MAX */
@@ -10,6 +11,7 @@
#include "cdi.h"
#include "cdi_cksum.h"
#include "cdi_int.h"
+#include "cdi_uuid.h"
#include "grid.h"
#include "gaussgrid.h"
#include "resource_handle.h"
@@ -42,6 +44,23 @@ static const char Grids[][17] = {
/* 15 */ "projection",
};
+/* must match table below */
+enum xystdname_idx {
+ grid_xystdname_grid_latlon,
+ grid_xystdname_latlon,
+ grid_xystdname_projection,
+};
+static const char xystdname_tab[][2][24] = {
+ [grid_xystdname_grid_latlon] = { "grid_longitude",
+ "grid_latitude" },
+ [grid_xystdname_latlon] = { "longitude",
+ "latitude" },
+ [grid_xystdname_projection] = { "projection_x_coordinate",
+ "projection_y_coordinate" },
+
+};
+
+
static int gridCompareP ( void * gridptr1, void * gridptr2 );
static void gridDestroyP ( void * gridptr );
@@ -62,7 +81,13 @@ static const resOps gridOps = {
static int GRID_Debug = 0; /* If set to 1, debugging */
+grid_t *gridID2Ptr(int gridID)
+{
+ return (grid_t *)reshGetVal(gridID, &gridOps);
+}
#define gridID2Ptr(gridID) (grid_t *)reshGetVal(gridID, &gridOps)
+#define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
+
void grid_init(grid_t *gridptr)
{
@@ -125,7 +150,6 @@ void grid_init(grid_t *gridptr)
gridptr->xpole = 0.0;
gridptr->ypole = 0.0;
gridptr->angle = 0.0;
- gridptr->locked = FALSE;
gridptr->lcomplex = 0;
gridptr->hasdims = TRUE;
gridptr->xname[0] = 0;
@@ -134,26 +158,30 @@ void grid_init(grid_t *gridptr)
gridptr->ylongname[0] = 0;
gridptr->xunits[0] = 0;
gridptr->yunits[0] = 0;
- gridptr->xstdname[0] = 0;
- gridptr->ystdname[0] = 0;
+ gridptr->xstdname = NULL;
+ gridptr->ystdname = NULL;
memset(gridptr->uuid, 0, CDI_UUID_SIZE);
gridptr->name = NULL;
+ gridptr->vtable = &cdiGridVtable;
+ gridptr->extraData = NULL;
}
-void grid_free(grid_t *gridptr)
+static void
+grid_free_components(grid_t *gridptr)
{
- if ( gridptr->mask ) Free(gridptr->mask);
- if ( gridptr->mask_gme ) Free(gridptr->mask_gme);
- if ( gridptr->xvals ) Free(gridptr->xvals);
- if ( gridptr->yvals ) Free(gridptr->yvals);
- if ( gridptr->area ) Free(gridptr->area);
- if ( gridptr->xbounds ) Free(gridptr->xbounds);
- if ( gridptr->ybounds ) Free(gridptr->ybounds);
- if ( gridptr->rowlon ) Free(gridptr->rowlon);
- if ( gridptr->reference ) Free(gridptr->reference);
- if ( gridptr->name ) Free(gridptr->name);
+ void *p2free[] = { gridptr->mask, gridptr->mask_gme,
+ gridptr->xvals, gridptr->yvals,
+ gridptr->xbounds, gridptr->ybounds,
+ gridptr->rowlon, gridptr->area,
+ gridptr->reference, gridptr->name };
+ for (size_t i = 0; i < sizeof (p2free) / sizeof (p2free[0]); ++i)
+ if (p2free[i]) Free(p2free[i]);
+}
+void grid_free(grid_t *gridptr)
+{
+ grid_free_components(gridptr);
grid_init(gridptr);
}
@@ -186,14 +214,23 @@ void gridInit (void)
if ( env ) GRID_Debug = atoi(env);
}
-static
-void grid_copy(grid_t *gridptr2, grid_t *gridptr1)
+static void
+grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
{
- int gridID2;
+ memcpy(gridptrDup, gridptrOrig, sizeof(grid_t));
+ gridptrDup->self = CDI_UNDEFID;
+ if (gridptrOrig->reference)
+ gridptrDup->reference = strdupx(gridptrOrig->reference);
+}
- gridID2 = gridptr2->self;
- memcpy(gridptr2, gridptr1, sizeof(grid_t));
- gridptr2->self = gridID2;
+
+static grid_t *
+grid_copy_base(grid_t *gridptrOrig)
+{
+ grid_t *gridptrDup = (grid_t *)Malloc(sizeof (*gridptrDup));
+ gridptrOrig->vtable->copyScalarFields(gridptrOrig, gridptrDup);
+ gridptrOrig->vtable->copyArrayFields(gridptrOrig, gridptrDup);
+ return gridptrDup;
}
unsigned cdiGridCount(void)
@@ -201,8 +238,145 @@ unsigned cdiGridCount(void)
return reshCountType(&gridOps);
}
+static inline void
+gridSetXname(grid_t *gridptr, const char *xname)
+{
+ strncpy(gridptr->xname, xname, CDI_MAX_NAME);
+ gridptr->xname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetXlongname(grid_t *gridptr, const char *xlongname)
+{
+ strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
+ gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetXunits(grid_t *gridptr, const char *xunits)
+{
+ strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
+ gridptr->xunits[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYname(grid_t *gridptr, const char *yname)
+{
+ strncpy(gridptr->yname, yname, CDI_MAX_NAME);
+ gridptr->yname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYlongname(grid_t *gridptr, const char *ylongname)
+{
+ strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
+ gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
+}
+
+static inline void
+gridSetYunits(grid_t *gridptr, const char *yunits)
+{
+ strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
+ gridptr->yunits[CDI_MAX_NAME - 1] = 0;
+}
+
+void
+cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
+{
+
+ gridptr->type = gridtype;
+ gridptr->size = size;
+
+ switch (gridtype)
+ {
+ case GRID_CURVILINEAR:
+ gridptr->nvertex = 4;
+ /* Fall through */
+ case GRID_LONLAT:
+ case GRID_GAUSSIAN:
+ case GRID_GAUSSIAN_REDUCED:
+ case GRID_TRAJECTORY:
+ {
+ if ( gridtype == GRID_TRAJECTORY )
+ {
+ gridSetXname(gridptr, "tlon");
+ gridSetYname(gridptr, "tlat");
+ }
+ else
+ {
+ gridSetXname(gridptr, "lon");
+ gridSetYname(gridptr, "lat");
+ }
+ gridSetXlongname(gridptr, "longitude");
+ gridSetYlongname(gridptr, "latitude");
+
+ /*
+ if ( gridtype == GRID_CURVILINEAR )
+ {
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+ gridDefXunits(gridID, "degrees");
+ gridDefYunits(gridID, "degrees");
+ }
+ else
+ */
+ {
+ gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
+ gridSetXunits(gridptr, "degrees_east");
+ gridSetYunits(gridptr, "degrees_north");
+ }
+
+ break;
+ }
+ case GRID_UNSTRUCTURED:
+ gridptr->xsize = size;
+ /* Fall through */
+ case GRID_GME:
+ {
+ gridSetXname(gridptr, "lon");
+ gridSetYname(gridptr, "lat");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
+ gridSetXunits(gridptr, "degrees_east");
+ gridSetYunits(gridptr, "degrees_north");
+ break;
+ }
+ case GRID_GENERIC:
+ {
+
+ /* gridptr->xsize = size; */
+ gridSetXname(gridptr, "x");
+ gridSetYname(gridptr, "y");
+ /*
+ strcpy(gridptr->xstdname, "grid_longitude");
+ strcpy(gridptr->ystdname, "grid_latitude");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
+ gridDefXunits(gridID, "degrees");
+ gridDefYunits(gridID, "degrees");
+ */
+ break;
+ }
+ case GRID_LCC2:
+ case GRID_SINUSOIDAL:
+ case GRID_LAEA:
+ {
+ gridSetXname(gridptr, "x");
+ gridSetYname(gridptr, "y");
+ gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
+ gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
+ gridSetXunits(gridptr, "m");
+ gridSetYunits(gridptr, "m");
+ break;
+ }
+ }
+
+}
+
+
// used also in CDO
-void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
+void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *restrict xvals)
{
if ( (! (fabs(xinc) > 0)) && xsize > 1 )
{
@@ -222,7 +396,7 @@ void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *x
}
static
-void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
+void calc_gaussgrid(double *restrict yvals, int ysize, double yfirst, double ylast)
{
double *restrict yw = (double *) Malloc((size_t)ysize * sizeof(double));
gaussaw(yvals, yw, (size_t)ysize);
@@ -243,7 +417,7 @@ void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
}
// used also in CDO
-void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals)
+void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
{
const double deleps = 0.002;
@@ -258,7 +432,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
{
double *restrict ytmp = NULL;
int nstart, lfound = 0;
- int ny = (int) (180./fabs(ylast-yfirst)/(ysize-1) + 0.5);
+ int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
ny -= ny%2;
if ( ny > ysize && ny < 4096 )
{
@@ -388,89 +562,7 @@ int gridCreate(int gridtype, int size)
if ( CDI_Debug ) Message("gridID: %d", gridID);
- gridptr->type = gridtype;
- gridptr->size = size;
-
- /* if ( gridtype == GRID_GENERIC ) gridptr->xsize = size; */
- if ( gridtype == GRID_UNSTRUCTURED ) gridptr->xsize = size;
- if ( gridtype == GRID_CURVILINEAR ) gridptr->nvertex = 4;
-
- switch (gridtype)
- {
- case GRID_LONLAT:
- case GRID_GAUSSIAN:
- case GRID_GAUSSIAN_REDUCED:
- case GRID_CURVILINEAR:
- case GRID_TRAJECTORY:
- {
- if ( gridtype == GRID_TRAJECTORY )
- {
- gridDefXname(gridID, "tlon");
- gridDefYname(gridID, "tlat");
- }
- else
- {
- gridDefXname(gridID, "lon");
- gridDefYname(gridID, "lat");
- }
- gridDefXlongname(gridID, "longitude");
- gridDefYlongname(gridID, "latitude");
-
- /*
- if ( gridtype == GRID_CURVILINEAR )
- {
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
- gridDefXunits(gridID, "degrees");
- gridDefYunits(gridID, "degrees");
- }
- else
- */
- {
- strcpy(gridptr->xstdname, "longitude");
- strcpy(gridptr->ystdname, "latitude");
- gridDefXunits(gridID, "degrees_east");
- gridDefYunits(gridID, "degrees_north");
- }
-
- break;
- }
- case GRID_GME:
- case GRID_UNSTRUCTURED:
- {
- gridDefXname(gridID, "lon");
- gridDefYname(gridID, "lat");
- strcpy(gridptr->xstdname, "longitude");
- strcpy(gridptr->ystdname, "latitude");
- gridDefXunits(gridID, "degrees_east");
- gridDefYunits(gridID, "degrees_north");
- break;
- }
- case GRID_GENERIC:
- {
- gridDefXname(gridID, "x");
- gridDefYname(gridID, "y");
- /*
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
- gridDefXunits(gridID, "degrees");
- gridDefYunits(gridID, "degrees");
- */
- break;
- }
- case GRID_LCC2:
- case GRID_SINUSOIDAL:
- case GRID_LAEA:
- {
- gridDefXname(gridID, "x");
- gridDefYname(gridID, "y");
- strcpy(gridptr->xstdname, "projection_x_coordinate");
- strcpy(gridptr->ystdname, "projection_y_coordinate");
- gridDefXunits(gridID, "m");
- gridDefYunits(gridID, "m");
- break;
- }
- }
+ cdiGridTypeInit(gridptr, gridtype, size);
return (gridID);
}
@@ -484,16 +576,7 @@ void gridDestroyKernel( grid_t * gridptr )
id = gridptr->self;
- if ( gridptr->mask ) Free(gridptr->mask);
- if ( gridptr->mask_gme ) Free(gridptr->mask_gme);
- if ( gridptr->xvals ) Free(gridptr->xvals);
- if ( gridptr->yvals ) Free(gridptr->yvals);
- if ( gridptr->area ) Free(gridptr->area);
- if ( gridptr->xbounds ) Free(gridptr->xbounds);
- if ( gridptr->ybounds ) Free(gridptr->ybounds);
- if ( gridptr->rowlon ) Free(gridptr->rowlon);
- if ( gridptr->reference ) Free(gridptr->reference);
-
+ grid_free_components(gridptr);
Free( gridptr );
reshRemove ( id, &gridOps );
@@ -512,13 +595,12 @@ void gridDestroyKernel( grid_t * gridptr )
void gridDestroy(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- gridDestroyKernel ( gridptr );
+ gridptr->vtable->destroy(gridptr);
}
void gridDestroyP ( void * gridptr )
{
- gridDestroyKernel (( grid_t * ) gridptr );
+ ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
}
@@ -553,16 +635,15 @@ The function @func{gridDefXname} defines the name of a X-axis.
*/
void gridDefXname(int gridID, const char *xname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( xname )
+ if ( xname && *xname )
{
- strncpy(gridptr->xname, xname, CDI_MAX_NAME);
- gridptr->xname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXname(gridptr, xname);
+ gridMark4Update(gridID);
}
}
+
/*
@Function gridDefXlongname
@Title Define the longname of a X-axis
@@ -579,12 +660,11 @@ The function @func{gridDefXlongname} defines the longname of a X-axis.
*/
void gridDefXlongname(int gridID, const char *xlongname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
if ( xlongname )
{
- strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
- gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXlongname(gridptr, xlongname);
+ gridMark4Update(gridID);
}
}
@@ -604,13 +684,11 @@ The function @func{gridDefXunits} defines the units of a X-axis.
*/
void gridDefXunits(int gridID, const char *xunits)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( xunits )
{
- strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
- gridptr->xunits[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetXunits(gridptr, xunits);
+ gridMark4Update(gridID);
}
}
@@ -630,13 +708,11 @@ The function @func{gridDefYname} defines the name of a Y-axis.
*/
void gridDefYname(int gridID, const char *yname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( yname )
+ if ( yname && *yname )
{
- strncpy(gridptr->yname, yname, CDI_MAX_NAME);
- gridptr->yname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYname(gridptr, yname);
+ gridMark4Update(gridID);
}
}
@@ -656,13 +732,11 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis.
*/
void gridDefYlongname(int gridID, const char *ylongname)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( ylongname )
{
- strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
- gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYlongname(gridptr, ylongname);
+ gridMark4Update(gridID);
}
}
@@ -682,13 +756,11 @@ The function @func{gridDefYunits} defines the units of a Y-axis.
*/
void gridDefYunits(int gridID, const char *yunits)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
if ( yunits )
{
- strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
- gridptr->yunits[CDI_MAX_NAME - 1] = 0;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridSetYunits(gridptr, yunits);
+ gridMark4Update(gridID);
}
}
@@ -774,8 +846,10 @@ void gridInqXunits(int gridID, char *xunits)
void gridInqXstdname(int gridID, char *xstdname)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- strcpy(xstdname, gridptr->xstdname);
+ if ( gridptr->xstdname )
+ strcpy(xstdname, gridptr->xstdname);
+ else
+ xstdname[0] = 0;
}
/*
@@ -859,8 +933,10 @@ void gridInqYunits(int gridID, char *yunits)
void gridInqYstdname(int gridID, char *ystdname)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- strcpy(ystdname, gridptr->ystdname);
+ if ( gridptr->ystdname )
+ strcpy(ystdname, gridptr->ystdname);
+ else
+ ystdname[0] = 0;
}
/*
@@ -921,7 +997,7 @@ int gridInqSize(int gridID)
ysize = gridptr->ysize;
if ( ysize )
- size = xsize *ysize;
+ size = xsize * ysize;
else
size = xsize;
@@ -969,7 +1045,7 @@ void gridDefTrunc(int gridID, int trunc)
if (gridptr->trunc != trunc)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->trunc = trunc;
}
}
@@ -996,16 +1072,17 @@ void gridDefXsize(int gridID, int xsize)
if ( xsize > gridSize )
Error("xsize %d is greater then gridsize %d", xsize, gridSize);
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED && xsize != gridSize )
+ int gridType = gridInqType(gridID);
+ if ( gridType == GRID_UNSTRUCTURED && xsize != gridSize )
Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridSize);
if (gridptr->xsize != xsize)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->xsize = xsize;
}
- if ( gridInqType(gridID) != GRID_UNSTRUCTURED )
+ if ( gridType != GRID_UNSTRUCTURED )
{
long axisproduct = gridptr->xsize*gridptr->ysize;
if ( axisproduct > 0 && axisproduct != gridSize )
@@ -1030,7 +1107,7 @@ void gridDefPrec(int gridID, int prec)
if (gridptr->prec != prec)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->prec = prec;
}
}
@@ -1103,7 +1180,7 @@ void gridDefYsize(int gridID, int ysize)
if (gridptr->ysize != ysize)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->ysize = ysize;
}
@@ -1160,7 +1237,7 @@ void gridDefNP(int gridID, int np)
if (gridptr->np != np)
{
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
gridptr->np = np;
}
}
@@ -1206,7 +1283,7 @@ void gridDefRowlon(int gridID, int nrowlon, const int rowlon[])
gridptr->rowlon = (int *) Malloc((size_t)nrowlon * sizeof(int));
gridptr->nrowlon = nrowlon;
memcpy(gridptr->rowlon, rowlon, (size_t)nrowlon * sizeof(int));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
/*
@@ -1228,34 +1305,48 @@ void gridInqRowlon(int gridID, int *rowlon)
memcpy(rowlon, gridptr->rowlon, (size_t)gridptr->nrowlon * sizeof(int));
}
-
-int gridInqMask(int gridID, int *mask)
+static int
+gridInqMaskSerialGeneric(grid_t *gridptr, mask_t **internalMask,
+ int *restrict mask)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
long size = gridptr->size;
if ( CDI_Debug && size == 0 )
- Warning("Size undefined for gridID = %d", gridID);
+ Warning("Size undefined for gridID = %d", gridptr->self);
- if (mask && gridptr->mask)
- for (long i = 0; i < size; ++i)
- mask[i] = (int)gridptr->mask[i];
-
- if ( gridptr->mask == NULL ) size = 0;
+ const mask_t *restrict mask_src = *internalMask;
+ if (mask_src)
+ {
+ if (mask && size > 0)
+ for (size_t i = 0; i < (size_t)size; ++i)
+ mask[i] = (int)mask_src[i];
+ }
+ else
+ size = 0;
return (int)size;
}
+static int
+gridInqMaskSerial(grid_t *gridptr, int *mask)
+{
+ return gridInqMaskSerialGeneric(gridptr, &gridptr->mask, mask);
+}
+
-void gridDefMask(int gridID, const int *mask)
+int gridInqMask(int gridID, int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqMask(gridptr, mask);
+}
+static void
+gridDefMaskSerial(grid_t *gridptr, const int *mask)
+{
long size = gridptr->size;
if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
+ Error("Size undefined for gridID = %d", gridptr->self);
if ( mask == NULL )
{
@@ -1277,34 +1368,32 @@ void gridDefMask(int gridID, const int *mask)
}
}
-
-int gridInqMaskGME(int gridID, int *mask)
+void gridDefMask(int gridID, const int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- long size = gridptr->size;
-
- if ( CDI_Debug && size == 0 )
- Warning("Size undefined for gridID = %d", gridID);
-
- if ( mask && gridptr->mask_gme )
- for (long i = 0; i < size; ++i)
- mask[i] = (int)gridptr->mask_gme[i];
-
- if ( gridptr->mask_gme == NULL ) size = 0;
-
- return (int)size;
+ gridptr->vtable->defMask(gridptr, mask);
+ gridMark4Update(gridID);
}
+static int
+gridInqMaskGMESerial(grid_t *gridptr, int *mask_gme)
+{
+ return gridInqMaskSerialGeneric(gridptr, &gridptr->mask_gme, mask_gme);
+}
-void gridDefMaskGME(int gridID, const int *mask)
+int gridInqMaskGME(int gridID, int *mask)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqMaskGME(gridptr, mask);
+}
+static void
+gridDefMaskGMESerial(grid_t *gridptr, const int *mask)
+{
long size = gridptr->size;
if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
+ Error("Size undefined for gridID = %d", gridptr->self);
if ( gridptr->mask_gme == NULL )
gridptr->mask_gme = (mask_t *) Malloc((size_t)size * sizeof (mask_t));
@@ -1315,6 +1404,41 @@ void gridDefMaskGME(int gridID, const int *mask)
gridptr->mask_gme[i] = (mask_t)(mask[i] != 0);
}
+void gridDefMaskGME(int gridID, const int *mask)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defMaskGME(gridptr, mask);
+ gridMark4Update(gridID);
+}
+
+
+static int
+gridInqXValsSerial(grid_t *gridptr, double *xvals)
+{
+ long size;
+ if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
+ size = gridptr->size;
+ else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
+ size = 2;
+ else
+ size = gridptr->xsize;
+
+ if ( CDI_Debug && size == 0 )
+ Warning("size undefined for gridID = %d", gridptr->self);
+
+ if ( gridptr->xvals )
+ {
+ if ( size && xvals )
+ {
+ const double *gridptr_xvals = gridptr->vtable->inqXValsPtr(gridptr);
+ memcpy(xvals, gridptr_xvals, (size_t)size * sizeof (double));
+ }
+ }
+ else
+ size = 0;
+ return (int)size;
+}
+
/*
@Function gridInqXvals
@Title Get all values of a X-axis
@@ -1338,24 +1462,31 @@ Otherwise, 0 is returned and @func{xvals} is empty.
int gridInqXvals(int gridID, double *xvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXVals(gridptr, xvals);
+}
+
+
+static void
+gridDefXValsSerial(grid_t *gridptr, const double *xvals)
+{
+ int gridtype = gridptr->type;
long size;
- if ( gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED )
+ if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
size = gridptr->size;
- else if ( gridptr->type == GRID_GAUSSIAN_REDUCED )
+ else if ( gridtype == GRID_GAUSSIAN_REDUCED )
size = 2;
else
size = gridptr->xsize;
- if ( CDI_Debug && size == 0 )
- Warning("size undefined for gridID = %d", gridID);
-
- if ( size && xvals && gridptr->xvals )
- memcpy(xvals, gridptr->xvals, (size_t)size * sizeof (double));
-
- if ( gridptr->xvals == NULL ) size = 0;
+ if ( size == 0 )
+ Error("Size undefined for gridID = %d", gridptr->self);
- return (int)size;
+ if (gridptr->xvals && CDI_Debug)
+ Warning("values already defined!");
+ gridptr->xvals = (double *)Realloc(gridptr->xvals,
+ (size_t)size * sizeof(double));
+ memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
}
/*
@@ -1375,26 +1506,33 @@ The function @func{gridDefXvals} defines all values of the X-axis.
void gridDefXvals(int gridID, const double *xvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defXVals(gridptr, xvals);
+ gridMark4Update(gridID);
+}
+
+static int
+gridInqYValsSerial(grid_t *gridptr, double *yvals)
+{
int gridtype = gridptr->type;
+ long size
+ = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
+ ? gridptr->size : gridptr->ysize;
- long size;
+ if ( CDI_Debug && size == 0 )
+ Warning("size undefined for gridID = %d!", gridptr->self);
- if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
- size = gridptr->size;
- else if ( gridtype == GRID_GAUSSIAN_REDUCED )
- size = 2;
+ if ( gridptr->yvals )
+ {
+ if ( size && yvals )
+ {
+ const double *gridptr_yvals = gridptr->vtable->inqYValsPtr(gridptr);
+ memcpy(yvals, gridptr_yvals, (size_t)size * sizeof (double));
+ }
+ }
else
- size = gridptr->xsize;
-
- if ( size == 0 )
- Error("Size undefined for gridID = %d", gridID);
+ size = 0;
- if (gridptr->xvals && CDI_Debug)
- Warning("values already defined!");
- gridptr->xvals = (double *) Realloc(gridptr->xvals,
- (size_t)size * sizeof(double));
- memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return (int)size;
}
/*
@@ -1420,23 +1558,28 @@ Otherwise, 0 is returned and @func{yvals} is empty.
int gridInqYvals(int gridID, double *yvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYVals(gridptr, yvals);
+}
+static void
+gridDefYValsSerial(grid_t *gridptr, const double *yvals)
+{
int gridtype = gridptr->type;
long size
= (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
? gridptr->size : gridptr->ysize;
- if ( CDI_Debug && size == 0 )
- Warning("size undefined for gridID = %d!", gridID);
-
- if ( size && yvals && gridptr->yvals )
- memcpy(yvals, gridptr->yvals, (size_t)size * sizeof (double));
+ if ( size == 0 )
+ Error("Size undefined for gridID = %d!", gridptr->self);
- if ( gridptr->yvals == NULL ) size = 0;
+ if (gridptr->yvals && CDI_Debug)
+ Warning("Values already defined!");
- return (int)size;
+ gridptr->yvals = (double *)Realloc(gridptr->yvals, (size_t)size * sizeof (double));
+ memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
}
+
/*
@Function gridDefYvals
@Title Define the values of a Y-axis
@@ -1454,32 +1597,29 @@ The function @func{gridDefYvals} defines all values of the Y-axis.
void gridDefYvals(int gridID, const double *yvals)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defYVals(gridptr, yvals);
+ gridMark4Update(gridID);
+}
- int gridtype = gridptr->type;
- long size
- = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED)
- ? gridptr->size : gridptr->ysize;
-
- if ( size == 0 )
- Error("Size undefined for gridID = %d!", gridID);
-
- if (gridptr->yvals && CDI_Debug)
- Warning("Values already defined!");
-
- gridptr->yvals = (double *) Realloc(gridptr->yvals, (size_t)size * sizeof (double));
- memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+static double
+gridInqXValSerial(grid_t *gridptr, int index)
+{
+ double xval = gridptr->xvals ? gridptr->xvals[index] : 0;
+ return xval;
}
double gridInqXval(int gridID, int index)
{
- double xval = 0;
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXVal(gridptr, index);
+}
- if ( gridptr->xvals ) xval = gridptr->xvals[index];
-
- return xval;
+static double
+gridInqYValSerial(grid_t *gridptr, int index)
+{
+ double yval = gridptr->yvals ? gridptr->yvals[index] : 0;
+ return yval;
}
/*
@@ -1494,12 +1634,8 @@ double gridInqXval(int gridID, int index)
*/
double gridInqYval(int gridID, int index)
{
- double yval = 0;
grid_t *gridptr = gridID2Ptr(gridID);
-
- if ( gridptr->yvals ) yval = gridptr->yvals[index];
-
- return yval;
+ return gridptr->vtable->inqYVal(gridptr, index);
}
/*
@@ -1516,7 +1652,7 @@ double gridInqXinc(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
double xinc = gridptr->xinc;
- const double *restrict xvals = gridptr->xvals;
+ const double *restrict xvals = gridptr->vtable->inqXValsPtr(gridptr);
if ( (! (fabs(xinc) > 0)) && xvals )
{
@@ -1524,7 +1660,7 @@ double gridInqXinc(int gridID)
if ( xsize > 1 )
{
xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
- for ( size_t i = 2; i < (size_t)xsize; i++ )
+ for (size_t i = 2; i < (size_t)xsize; i++ )
if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc )
{
xinc = 0;
@@ -1552,7 +1688,7 @@ double gridInqYinc(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
double yinc = gridptr->yinc;
- const double *yvals = gridptr->yvals;
+ const double *yvals = gridptr->vtable->inqYValsPtr(gridptr);
if ( (! (fabs(yinc) > 0)) && yvals )
{
@@ -1561,8 +1697,8 @@ double gridInqYinc(int gridID)
{
yinc = yvals[1] - yvals[0];
double abs_yinc = fabs(yinc);
- for ( size_t i = 2; i < (size_t)ysize; i++ )
- if ( fabs(fabs(yvals[i] - yvals[i-1]) - abs_yinc) > (0.01*abs_yinc))
+ for (size_t i = 2; i < (size_t)ysize; i++ )
+ if ( fabs(fabs(yvals[i] - yvals[i-1]) - abs_yinc) > (0.01*abs_yinc) )
{
yinc = 0;
break;
@@ -1608,14 +1744,14 @@ void gridDefXpole(int gridID, double xpole)
// Xpole -> grid_north_pole_longitude
grid_t *gridptr = gridID2Ptr(gridID);
- if ( memcmp(gridptr->xstdname, "grid", 4) != 0 )
- strcpy(gridptr->xstdname, "grid_longitude");
+ if ( gridptr->xstdname && memcmp(gridptr->xstdname, "grid", 4) != 0 )
+ gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) )
{
gridptr->isRotated = TRUE;
gridptr->xpole = xpole;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1652,14 +1788,14 @@ void gridDefYpole(int gridID, double ypole)
// Ypole -> grid_north_pole_latitude
grid_t *gridptr = gridID2Ptr(gridID);
- if ( memcmp(gridptr->ystdname, "grid", 4) != 0 )
- strcpy(gridptr->ystdname, "grid_latitude");
+ if ( gridptr->ystdname && memcmp(gridptr->ystdname, "grid", 4) != 0 )
+ gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) )
{
gridptr->isRotated = TRUE;
gridptr->ypole = ypole;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1700,7 +1836,7 @@ void gridDefAngle(int gridID, double angle)
{
gridptr->isRotated = TRUE;
gridptr->angle = angle;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1738,7 +1874,7 @@ void gridDefGMEnd(int gridID, int nd)
if (gridptr->nd != nd)
{
gridptr->nd = nd;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1776,7 +1912,7 @@ void gridDefGMEni(int gridID, int ni)
if (gridptr->ni != ni)
{
gridptr->ni = ni;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1814,7 +1950,7 @@ void gridDefGMEni2(int gridID, int ni2)
if (gridptr->ni2 != ni2)
{
gridptr->ni2 = ni2;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1842,7 +1978,7 @@ void gridDefGMEni3(int gridID, int ni3)
if (gridptr->ni3 != ni3)
{
gridptr->ni3 = ni3;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1866,7 +2002,7 @@ void gridChangeType(int gridID, int gridtype)
if (gridptr->type != gridtype)
{
gridptr->type = gridtype;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -1874,18 +2010,20 @@ static
void grid_check_cyclic(grid_t *gridptr)
{
gridptr->isCyclic = FALSE;
-
- int xsize = gridptr->xsize,
- ysize = gridptr->ysize;
- const double *xvals = gridptr->xvals,
- *xbounds = gridptr->xbounds;
+ enum { numVertices = 4 };
+ size_t xsize = gridptr->xsize >= 0 ? (size_t)gridptr->xsize : 0,
+ ysize = gridptr->ysize >= 0 ? (size_t)gridptr->ysize : 0;
+ const double *xvals = gridptr->vtable->inqXValsPtr(gridptr),
+ (*xbounds)[numVertices]
+ = (const double (*)[numVertices])gridptr->vtable->inqXBoundsPtr(gridptr);
if ( gridptr->type == GRID_GAUSSIAN || gridptr->type == GRID_LONLAT )
{
if ( xvals && xsize > 1 )
{
double xinc = xvals[1] - xvals[0];
- if ( IS_EQUAL(xinc, 0) ) xinc = (xvals[xsize-1] - xvals[0])/(xsize-1);
+ if ( IS_EQUAL(xinc, 0) )
+ xinc = (xvals[xsize-1] - xvals[0])/(double)(xsize-1);
double x0 = 2*xvals[xsize-1]-xvals[xsize-2]-360;
@@ -1897,10 +2035,10 @@ void grid_check_cyclic(grid_t *gridptr)
{
if ( xvals && xsize > 1 )
{
- long nc = 0;
- for ( int j = 0; j < ysize; ++j )
+ size_t nc = 0;
+ for ( size_t j = 0; j < ysize; ++j )
{
- long i1 = j*xsize,
+ size_t i1 = j*xsize,
i2 = j*xsize+1,
in = j*xsize+(xsize-1);
double val1 = xvals[i1],
@@ -1919,23 +2057,22 @@ void grid_check_cyclic(grid_t *gridptr)
nc += fabs(x0-val1) < 0.5*xinc;
}
- gridptr->isCyclic = nc > 0.5*ysize ? TRUE : FALSE;
+ gridptr->isCyclic = nc > ysize/2 ? TRUE : FALSE;
}
if ( xbounds && xsize > 1 )
{
- gridptr->isCyclic = TRUE;
- for ( int j = 0; j < ysize; ++j )
+ short isCyclic = TRUE;
+ for ( size_t j = 0; j < ysize; ++j )
{
- long i1 = j*xsize*4,
- i2 = j*xsize*4+(xsize-1)*4;
- long nc = 0;
- for (unsigned k1 = 0; k1 < 4; ++k1 )
+ size_t i1 = j*xsize,
+ i2 = j*xsize+(xsize-1);
+ for (size_t k1 = 0; k1 < numVertices; ++k1 )
{
- double val1 = xbounds[i1+k1];
- for (unsigned k2 = 0; k2 < 4; ++k2 )
+ double val1 = xbounds[i1][k1];
+ for (size_t k2 = 0; k2 < numVertices; ++k2 )
{
- double val2 = xbounds[i2+k2];
+ double val2 = xbounds[i2][k2];
if ( val1 < 1 && val2 > 300 ) val1 += 360;
if ( val2 < 1 && val1 > 300 ) val2 += 360;
@@ -1944,19 +2081,16 @@ void grid_check_cyclic(grid_t *gridptr)
if ( fabs(val2-val1) > 180 ) val1 += 360;
if ( fabs(val1-val2) < 0.001 )
- {
- nc++;
- break;
- }
+ goto foundCloseVertices;
}
}
-
- if ( nc < 1 )
- {
- gridptr->isCyclic = FALSE;
- break;
- }
+ /* all vertices more than 0.001 degrees apart */
+ isCyclic = FALSE;
+ break;
+ foundCloseVertices:
+ ;
}
+ gridptr->isCyclic = isCyclic;
}
}
}
@@ -1980,67 +2114,60 @@ int gridIsRotated(int gridID)
}
static
-int compareXYvals(int gridID, long xsize, long ysize, double *xvals0, double *yvals0)
+int compareXYvals(grid_t *gridRef, grid_t *gridTest)
{
- long i;
int differ = 0;
- if ( !differ && xsize == gridInqXvals(gridID, NULL) )
+ int xsizeTest = gridTest->xsize, ysizeTest = gridTest->ysize;
+ if ( !differ && xsizeTest > 0 && xsizeTest == gridRef->vtable->inqXVals(gridRef, NULL) )
{
- double *xvals = (double *) Malloc((size_t)xsize * sizeof (double));
-
- gridInqXvals(gridID, xvals);
+ const double *restrict xvalsRef = gridRef->vtable->inqXValsPtr(gridRef),
+ *restrict xvalsTest = gridTest->vtable->inqXValsPtr(gridTest);
- for ( i = 0; i < xsize; ++i )
- if ( fabs(xvals0[i] - xvals[i]) > 1.e-10 )
+ for ( size_t i = 0; i < (size_t)xsizeTest; ++i )
+ if ( fabs(xvalsTest[i] - xvalsRef[i]) > 1.e-10 )
{
differ = 1;
break;
}
-
- Free(xvals);
}
- if ( !differ && ysize == gridInqYvals(gridID, NULL) )
+ if ( !differ && ysizeTest > 0 && ysizeTest == gridRef->vtable->inqYVals(gridRef, NULL) )
{
- double *yvals = (double *) Malloc((size_t)ysize * sizeof (double));
-
- gridInqYvals(gridID, yvals);
-
- for ( i = 0; i < ysize; ++i )
- if ( fabs(yvals0[i] - yvals[i]) > 1.e-10 )
+ const double *restrict yvalsRef = gridRef->vtable->inqYValsPtr(gridRef),
+ *restrict yvalsTest = gridTest->vtable->inqYValsPtr(gridTest);
+ for ( size_t i = 0; i < (size_t)ysizeTest; ++i )
+ if ( fabs(yvalsTest[i] - yvalsRef[i]) > 1.e-10 )
{
differ = 1;
break;
}
-
- Free(yvals);
}
return (differ);
}
static
-int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
+int compareXYvals2(grid_t *gridRef, grid_t *gridTest)
{
- int differ = 0;
+ int gridsize = gridTest->size;
+ int differ
+ = ((gridTest->xvals == NULL) ^ (gridRef->xvals == NULL))
+ || ((gridTest->yvals == NULL) ^ (gridRef->yvals == NULL));
- if ( !differ && ((xvals == NULL && gridInqXvalsPtr(gridID) != NULL) || (xvals != NULL && gridInqXvalsPtr(gridID) == NULL)) ) differ = 1;
- if ( !differ && ((yvals == NULL && gridInqYvalsPtr(gridID) != NULL) || (yvals != NULL && gridInqYvalsPtr(gridID) == NULL)) ) differ = 1;
+ typedef double (*inqVal)(grid_t *grid, int index);
+ inqVal inqXValRef = gridRef->vtable->inqXVal,
+ inqYValRef = gridRef->vtable->inqXVal,
+ inqXValTest = gridTest->vtable->inqXVal,
+ inqYValTest = gridTest->vtable->inqYVal;
- if ( !differ && xvals && gridInqXvalsPtr(gridID) )
- {
- if ( fabs(xvals[0] - gridInqXval(gridID, 0)) > 1.e-9 ||
- fabs(xvals[gridsize-1] - gridInqXval(gridID, gridsize-1)) > 1.e-9 )
- differ = 1;
- }
+ if ( !differ && gridTest->xvals )
+ differ = fabs(inqXValTest(gridTest, 0) - inqXValRef(gridRef, 0)) > 1.e-9
+ || fabs(inqXValTest(gridTest, gridsize-1) - inqXValRef(gridRef, gridsize-1)) > 1.e-9;
- if ( !differ && yvals && gridInqYvalsPtr(gridID) )
- {
- if ( fabs(yvals[0] - gridInqYval(gridID, 0)) > 1.e-9 ||
- fabs(yvals[gridsize-1] - gridInqYval(gridID, gridsize-1)) > 1.e-9 )
- differ = 1;
- }
+ if ( !differ && gridTest->yvals )
+ differ = fabs(inqYValTest(gridTest, 0) - inqYValRef(gridRef, 0)) > 1.e-9
+ || fabs(inqYValTest(gridTest, gridsize-1) - inqYValRef(gridRef, gridsize-1)) > 1.e-9;
return differ;
}
@@ -2049,10 +2176,11 @@ int compareXYvals2(int gridID, int gridsize, double *xvals, double *yvals)
int gridCompare(int gridID, const grid_t *grid)
{
int differ = 1;
+ grid_t *gridRef = gridID2Ptr(gridID);
- if ( grid->type == gridInqType(gridID) || grid->type == GRID_GENERIC )
+ if ( grid->type == gridRef->type || grid->type == GRID_GENERIC )
{
- if ( grid->size == gridInqSize(gridID) )
+ if ( grid->size == gridRef->size )
{
differ = 0;
if ( grid->type == GRID_LONLAT )
@@ -2072,7 +2200,7 @@ int gridCompare(int gridID, const grid_t *grid)
printf("grid.xinc %f\n", gridInqXinc(gridID));
printf("grid.yinc %f\n", gridInqYinc(gridID));
*/
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == grid->ysize )
{
if ( grid->xdef == 2 && grid->ydef == 2 )
{
@@ -2086,38 +2214,33 @@ int gridCompare(int gridID, const grid_t *grid)
differ = 1;
}
if ( !differ && fabs(grid->xinc) > 0 &&
- fabs(fabs(grid->xinc) - fabs(gridInqXinc(gridID))) > fabs(grid->xinc/1000))
+ fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000))
{
differ = 1;
}
if ( !differ && fabs(grid->yinc) > 0 &&
- fabs(fabs(grid->yinc) - fabs(gridInqYinc(gridID))) > fabs(grid->yinc/1000))
+ fabs(fabs(grid->yinc) - fabs(gridRef->yinc)) > fabs(grid->yinc/1000))
{
differ = 1;
}
}
}
- else
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ else if ( grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else
differ = 1;
}
else if ( grid->type == GRID_GENERIC )
{
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
{
- if ( grid->xdef == 1 && grid->ydef == 1 )
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ if ( grid->xdef == 1 && grid->ydef == 1
+ && grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else if ( (grid->ysize == 0 || grid->ysize == 1) &&
- grid->xsize == gridInqXsize(gridID)*gridInqYsize(gridID) )
+ grid->xsize == gridRef->xsize*gridRef->ysize )
{
}
else
@@ -2125,7 +2248,7 @@ int gridCompare(int gridID, const grid_t *grid)
}
else if ( grid->type == GRID_GAUSSIAN )
{
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
{
if ( grid->xdef == 2 && grid->ydef == 2 )
{
@@ -2133,16 +2256,13 @@ int gridCompare(int gridID, const grid_t *grid)
! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0)) )
if ( fabs(grid->xfirst - gridInqXval(gridID, 0)) > 0.0015 ||
fabs(grid->yfirst - gridInqYval(gridID, 0)) > 0.0015 ||
- (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridInqXinc(gridID))) > fabs(grid->xinc/1000)) )
+ (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) )
{
differ = 1;
}
}
- else
- {
- if ( grid->xvals && grid->yvals )
- differ = compareXYvals(gridID, grid->xsize, grid->ysize, grid->xvals, grid->yvals);
- }
+ else if ( grid->xvals && grid->yvals )
+ differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid);
}
else
differ = 1;
@@ -2164,31 +2284,36 @@ int gridCompare(int gridID, const grid_t *grid)
printf("grid.nv %d\n", grid->nvertex);
printf("grid nv %d\n", gridInqNvertex(gridID));
*/
- if ( grid->xsize == gridInqXsize(gridID) && grid->ysize == gridInqYsize(gridID) )
- differ = compareXYvals2(gridID, grid->size, grid->xvals, grid->yvals);
+ if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize )
+ differ = gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid);
}
else if ( grid->type == GRID_UNSTRUCTURED )
{
- unsigned char uuidOfHGrid[CDI_UUID_SIZE];
- gridInqUUID(gridID, uuidOfHGrid);
-
- if ( !differ && uuidOfHGrid[0] && grid->uuid[0] && memcmp(uuidOfHGrid, grid->uuid, CDI_UUID_SIZE) != 0 ) differ = 1;
+ /* FIXME: not octet 0 but octet 7 is guaranteed non-zero
+ * for any non-NULL UUID */
+ differ = differ || ( gridRef->uuid[0] && grid->uuid[0] && memcmp(gridRef->uuid, grid->uuid, CDI_UUID_SIZE) != 0 );
if ( !differ &&
- ((grid->xvals == NULL && gridInqXvalsPtr(gridID) != NULL) || (grid->xvals != NULL && gridInqXvalsPtr(gridID) == NULL)) &&
- ((grid->yvals == NULL && gridInqYvalsPtr(gridID) != NULL) || (grid->yvals != NULL && gridInqYvalsPtr(gridID) == NULL)) )
+ ((grid->xvals == NULL) ^ (gridRef->xvals == NULL)) &&
+ ((grid->yvals == NULL) ^ (gridRef->yvals == NULL)) )
{
- if ( !differ && grid->nvertex && gridInqNvertex(gridID) && grid->nvertex != gridInqNvertex(gridID) ) differ = 1;
- if ( !differ && grid->number && gridInqNumber(gridID) && grid->number != gridInqNumber(gridID) ) differ = 1;
- if ( !differ && grid->number && gridInqNumber(gridID) && grid->position != gridInqPosition(gridID) ) differ = 1;
+ int nvertexA, nvertexB, numberA, numberB;
+ differ = ( (nvertexA = grid->nvertex)
+ && (nvertexB = gridRef->nvertex)
+ && (nvertexA != nvertexB) )
+ || (numberA = grid->number, numberB = gridRef->number,
+ ( (numberA)
+ && numberB
+ && (numberA != numberB) )
+ || ( (numberA && numberB)
+ && (grid->position) != (gridRef->position) ) );
}
- else
+ else if ( !differ )
{
- if ( !differ && grid->nvertex != gridInqNvertex(gridID) ) differ = 1;
- if ( !differ && grid->number != gridInqNumber(gridID) ) differ = 1;
- if ( !differ && grid->number > 0 && grid->position != gridInqPosition(gridID) ) differ = 1;
- if ( !differ )
- differ = compareXYvals2(gridID, grid->size, grid->xvals, grid->yvals);
+ differ = grid->nvertex != gridRef->nvertex
+ || grid->number != gridRef->number
+ || (grid->number > 0 && grid->position != gridRef->position)
+ || gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid);
}
}
}
@@ -2232,7 +2357,6 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
if ( g1->size != g2->size ) return differ;
if ( g1->xsize != g2->xsize ) return differ;
if ( g1->ysize != g2->ysize ) return differ;
- if ( g1->locked != g2->locked ) return differ;
if ( g1->lcomplex != g2->lcomplex ) return differ;
if ( g1->rowlon )
@@ -2268,23 +2392,27 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
if ( IS_NOT_EQUAL(g1->ypole , g2->ypole) ) return differ;
if ( IS_NOT_EQUAL(g1->angle , g2->angle) ) return differ;
- if ( g1->xvals )
+ const double *restrict g1_xvals = g1->vtable->inqXValsPtr(g1),
+ *restrict g2_xvals = g2->vtable->inqXValsPtr(g2);
+ if ( g1_xvals )
{
if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
- size = g1->size;
+ size = g1->size;
else
- size = g1->xsize;
+ size = g1->xsize;
xassert ( size );
- if ( !g2->xvals ) return differ;
+ if ( !g2_xvals ) return differ;
for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->xvals[i], g2->xvals[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_xvals[i], g2_xvals[i]) ) return differ;
}
- else if ( g2->xvals )
+ else if ( g2_xvals )
return differ;
- if ( g1->yvals )
+ const double *restrict g1_yvals = g1->vtable->inqXValsPtr(g1),
+ *restrict g2_yvals = g2->vtable->inqXValsPtr(g2);
+ if ( g1_yvals )
{
if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR )
size = g1->size;
@@ -2292,66 +2420,74 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
size = g1->ysize;
xassert ( size );
- if ( !g2->yvals ) return differ;
+ if ( !g2_yvals ) return differ;
for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->yvals[i], g2->yvals[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_yvals[i], g2_yvals[i]) ) return differ;
}
- else if ( g2->yvals )
+ else if ( g2_yvals )
return differ;
- if ( g1->area )
+ const double *restrict g1_area = g1->vtable->inqAreaPtr(g1),
+ *restrict g2_area = g2->vtable->inqAreaPtr(g2);
+ if ( g1_area )
{
xassert ( g1->size );
- if ( !g2->area ) return differ;
+ if ( !g2_area ) return differ;
for ( i = 0; i < g1->size; i++ )
- if ( IS_NOT_EQUAL(g1->area[i], g2->area[i]) ) return differ;
+ if ( IS_NOT_EQUAL(g1_area[i], g2_area[i]) ) return differ;
}
- else if ( g2->area )
+ else if ( g2_area )
return differ;
- if ( g1->xbounds )
- {
- xassert ( g1->nvertex );
- if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
- size = g1->nvertex * g1->size;
- else
- size = g1->nvertex * g1->xsize;
- xassert ( size );
+ {
+ const double *restrict g1_xbounds, *restrict g2_xbounds;
+ if ( (g1_xbounds = g1->vtable->inqXBoundsPtr(g1)) )
+ {
+ xassert ( g1->nvertex );
+ if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
+ size = g1->nvertex * g1->size;
+ else
+ size = g1->nvertex * g1->xsize;
+ xassert ( size );
- if ( !g2->xbounds ) return differ;
+ if ( !(g2_xbounds = g2->vtable->inqXBoundsPtr(g2)) ) return differ;
- for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->xbounds[i], g2->xbounds[i]) ) return differ;
- }
- else if ( g2->xbounds )
- return differ;
+ for ( i = 0; i < size; i++ )
+ if ( IS_NOT_EQUAL(g1_xbounds[i], g2_xbounds[i]) ) return differ;
+ }
+ else if ( g2->vtable->inqXBoundsPtr(g2) )
+ return differ;
+ }
- if ( g1->ybounds )
- {
- xassert ( g1->nvertex );
- if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
- size = g1->nvertex * g1->size;
- else
- size = g1->nvertex * g1->ysize;
- xassert ( size );
+ {
+ const double *restrict g1_ybounds, *restrict g2_ybounds;
+ if ( (g1_ybounds = g1->vtable->inqYBoundsPtr(g1)) )
+ {
+ xassert ( g1->nvertex );
+ if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED )
+ size = g1->nvertex * g1->size;
+ else
+ size = g1->nvertex * g1->ysize;
+ xassert ( size );
- if ( !g2->ybounds ) return differ;
+ if ( ! (g2_ybounds = g2->vtable->inqYBoundsPtr(g2)) ) return differ;
- for ( i = 0; i < size; i++ )
- if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ;
- }
- else if ( g2->ybounds )
- return differ;
+ for ( i = 0; i < size; i++ )
+ if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ;
+ }
+ else if ( g2->vtable->inqYBoundsPtr(g2) )
+ return differ;
+ }
if (strcmp(g1->xname, g2->xname)) return differ;
if (strcmp(g1->yname, g2->yname)) return differ;
if (strcmp(g1->xlongname, g2->xlongname)) return differ;
if (strcmp(g1->ylongname, g2->ylongname)) return differ;
- if (strcmp(g1->xstdname, g2->xstdname)) return differ;
- if (strcmp(g1->ystdname, g2->ystdname)) return differ;
+ if (g1->xstdname != g2->xstdname) return differ;
+ if (g1->ystdname != g2->ystdname) return differ;
if (strcmp(g1->xunits, g2->xunits)) return differ;
if (strcmp(g1->yunits, g2->yunits)) return differ;
@@ -2387,16 +2523,13 @@ int gridCompareP ( void * gridptr1, void * gridptr2 )
return equal;
}
-
-int gridGenerate(const grid_t *grid)
+static void gridComplete(grid_t *grid)
{
- int gridID = gridCreate(grid->type, grid->size);
-
- grid_t *gridptr = gridID2Ptr(gridID);
-
+ int gridID = grid->self;
gridDefPrec(gridID, grid->prec);
- switch (grid->type)
+ int gridtype = grid->type;
+ switch (gridtype)
{
case GRID_LONLAT:
case GRID_GAUSSIAN:
@@ -2412,42 +2545,32 @@ int gridGenerate(const grid_t *grid)
if ( grid->xsize > 0 ) gridDefXsize(gridID, grid->xsize);
if ( grid->ysize > 0 ) gridDefYsize(gridID, grid->ysize);
- if ( grid->type == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np);
+ if ( gridtype == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np);
if ( grid->nvertex > 0 )
gridDefNvertex(gridID, grid->nvertex);
- if ( grid->xdef == 1 )
- {
- gridDefXvals(gridID, grid->xvals);
- if ( grid->xbounds )
- gridDefXbounds(gridID, grid->xbounds);
- }
- else if ( grid->xdef == 2 )
+ if ( grid->xdef == 2 )
{
+ assert(gridtype != GRID_UNSTRUCTURED
+ && gridtype != GRID_CURVILINEAR);
double *xvals
= (double *) Malloc((size_t)grid->xsize * sizeof (double));
gridGenXvals(grid->xsize, grid->xfirst, grid->xlast, grid->xinc, xvals);
- gridDefXvals(gridID, xvals);
- Free(xvals);
+ grid->xvals = xvals;
/*
gridDefXinc(gridID, grid->xinc);
*/
}
- if ( grid->ydef == 1 )
- {
- gridDefYvals(gridID, grid->yvals);
- if ( grid->ybounds && grid->nvertex )
- gridDefYbounds(gridID, grid->ybounds);
- }
- else if ( grid->ydef == 2 )
+ if ( grid->ydef == 2 )
{
+ assert(gridtype != GRID_UNSTRUCTURED
+ && gridtype != GRID_CURVILINEAR);
double *yvals
= (double *) Malloc((size_t)grid->ysize * sizeof (double));
- gridGenYvals(grid->type, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
- gridDefYvals(gridID, yvals);
- Free(yvals);
+ gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
+ grid->yvals = yvals;
/*
gridDefYinc(gridID, grid->yinc);
*/
@@ -2459,8 +2582,8 @@ int gridGenerate(const grid_t *grid)
gridDefYname(gridID, "rlat");
gridDefXlongname(gridID, "longitude in rotated pole grid");
gridDefYlongname(gridID, "latitude in rotated pole grid");
- strcpy(gridptr->xstdname, "grid_longitude");
- strcpy(gridptr->ystdname, "grid_latitude");
+ grid->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
+ grid->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
gridDefXunits(gridID, "degrees");
gridDefYunits(gridID, "degrees");
@@ -2469,39 +2592,30 @@ int gridGenerate(const grid_t *grid)
gridDefAngle(gridID, grid->angle);
}
- if ( grid->area )
- {
- gridDefArea(gridID, grid->area);
- }
-
- if ( grid->type == GRID_LAEA )
- gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0);
-
- if ( grid->type == GRID_LCC2 )
- gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2);
-
- if ( grid->type == GRID_LCC )
- gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY,
- grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc,
- grid->lcc_projflag, grid->lcc_scanflag);
-
- if ( grid->type == GRID_UNSTRUCTURED )
+ switch (gridtype)
{
- int number = grid->number;
- int position = grid->position;
- if ( position < 0 ) position = 0;
- if ( number > 0 )
- {
- gridDefNumber(gridID, number);
- gridDefPosition(gridID, position);
- }
- gridDefUUID(gridID, grid->uuid);
- if ( grid->reference ) gridDefReference(gridID, grid->reference);
- }
-
- if ( grid->type == GRID_PROJECTION )
- {
- gridptr->name = strdup(grid->name);
+ case GRID_LAEA:
+ gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0);
+ break;
+ case GRID_LCC2:
+ gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2);
+ break;
+ case GRID_LCC:
+ gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY,
+ grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc,
+ grid->lcc_projflag, grid->lcc_scanflag);
+ break;
+ case GRID_UNSTRUCTURED:
+ {
+ int number = grid->number;
+ int position = grid->position >= 0 ? grid->position : 0;
+ if ( number > 0 )
+ {
+ gridDefNumber(gridID, number);
+ gridDefPosition(gridID, position);
+ }
+ }
+ break;
}
break;
@@ -2510,29 +2624,19 @@ int gridGenerate(const grid_t *grid)
{
gridDefNP(gridID, grid->np);
gridDefYsize(gridID, grid->ysize);
- gridDefRowlon(gridID, grid->ysize, grid->rowlon);
if ( grid->xdef == 2 )
{
- double xvals[2];
- xvals[0] = grid->xfirst;
- xvals[1] = grid->xlast;
+ double xvals[2] = { grid->xfirst, grid->xlast };
gridDefXvals(gridID, xvals);
}
- if ( grid->ydef == 1 )
- {
- gridDefYvals(gridID, grid->yvals);
- if ( grid->ybounds && grid->nvertex )
- gridDefYbounds(gridID, grid->ybounds);
- }
- else if ( grid->ydef == 2 )
+ if ( grid->ydef == 2 )
{
double *yvals
= (double *) Malloc((size_t)grid->ysize * sizeof (double));
- gridGenYvals(grid->type, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
- gridDefYvals(gridID, yvals);
- Free(yvals);
+ gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals);
+ grid->yvals = yvals;
/*
gridDefYinc(gridID, grid->yinc);
*/
@@ -2579,127 +2683,209 @@ int gridGenerate(const grid_t *grid)
}
default:
{
- Error("Gridtype %s unsupported!", gridNamePtr(grid->type));
+ Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
break;
}
}
- if ( grid->xname[0] ) gridDefXname(gridID, grid->xname);
- if ( grid->xlongname[0] ) gridDefXlongname(gridID, grid->xlongname);
- if ( grid->xunits[0] ) gridDefXunits(gridID, grid->xunits);
- if ( grid->yname[0] ) gridDefYname(gridID, grid->yname);
- if ( grid->ylongname[0] ) gridDefYlongname(gridID, grid->ylongname);
- if ( grid->yunits[0] ) gridDefYunits(gridID, grid->yunits);
+ grid->xname[CDI_MAX_NAME - 1] = 0;
+ grid->xlongname[CDI_MAX_NAME - 1] = 0;
+ grid->xunits[CDI_MAX_NAME - 1] = 0;
+ grid->yname[CDI_MAX_NAME - 1] = 0;
+ grid->ylongname[CDI_MAX_NAME - 1] = 0;
+ grid->yunits[CDI_MAX_NAME - 1] = 0;
- return (gridID);
}
-/*
- at Function gridDuplicate
- at Title Duplicate a horizontal Grid
-
- at Prototype int gridDuplicate(int gridID)
- at Parameter
- @Item gridID Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
-
- at Description
-The function @func{gridDuplicate} duplicates a horizontal Grid.
-
- at Result
- at func{gridDuplicate} returns an identifier to the duplicated Grid.
+#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
+ gridP->xlongname, gridP->ylongname, \
+ gridP->xunits, gridP->yunits }
- at EndFunction
-*/
-int gridDuplicate(int gridID)
+int gridGenerate(const grid_t *grid)
{
- grid_t *gridptr = (grid_t *)reshGetVal(gridID, &gridOps);
-
- int gridtype = gridInqType(gridID);
- int gridsize = gridInqSize(gridID);
-
- int gridIDnew = gridCreate(gridtype, gridsize);
- grid_t *gridptrnew = (grid_t *)reshGetVal(gridIDnew, &gridOps);
-
- grid_copy(gridptrnew, gridptr);
-
- strcpy(gridptrnew->xname, gridptr->xname);
- strcpy(gridptrnew->yname, gridptr->yname);
- strcpy(gridptrnew->xlongname, gridptr->xlongname);
- strcpy(gridptrnew->ylongname, gridptr->ylongname);
- strcpy(gridptrnew->xunits, gridptr->xunits);
- strcpy(gridptrnew->yunits, gridptr->yunits);
- strcpy(gridptrnew->xstdname, gridptr->xstdname);
- strcpy(gridptrnew->ystdname, gridptr->ystdname);
-
- if (gridptr->reference)
- gridptrnew->reference = strdupx(gridptr->reference);
+ int gridtype = grid->type;
+ int gridID = gridCreate(gridtype, grid->size);
+ grid_t *restrict gridptr = gridID2Ptr(gridID);
+ gridptr->prec = grid->prec;
+ gridptr->xsize = grid->xsize;
+ gridptr->ysize = grid->ysize;
+ gridptr->np = grid->np;
+ gridptr->nvertex = grid->nvertex;
+ gridptr->xdef = grid->xdef;
+ int valdef_group1 = 0;
+ static const int valdef_group1_tab[] = {
+ GRID_LONLAT, GRID_GAUSSIAN, GRID_UNSTRUCTURED, GRID_CURVILINEAR,
+ GRID_GENERIC, GRID_LCC, GRID_LCC2, GRID_SINUSOIDAL, GRID_LAEA,
+ GRID_PROJECTION
+ };
+ for ( size_t i = 0; i < sizeof (valdef_group1_tab) / sizeof (valdef_group1_tab[0]); ++i)
+ valdef_group1 |= (gridtype == valdef_group1_tab[i]);
+ if ( valdef_group1 && grid->xdef == 1 )
+ {
+ gridDefXvals(gridID, grid->xvals);
+ if ( grid->xbounds )
+ gridDefXbounds(gridID, grid->xbounds);
+ }
+ gridptr->xfirst = grid->xfirst;
+ gridptr->xlast = grid->xlast;
+ gridptr->xinc = grid->xinc;
+ gridptr->ydef = grid->ydef;
+ if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->ydef == 1)
+ {
+ gridDefYvals(gridID, grid->yvals);
+ if ( grid->ybounds )
+ gridDefYbounds(gridID, grid->ybounds);
+ }
+ gridptr->yfirst = grid->yfirst;
+ gridptr->ylast = grid->ylast;
+ gridptr->yinc = grid->yinc;
+ gridptr->isRotated = grid->isRotated;
+ gridptr->xpole = grid->xpole;
+ gridptr->ypole = grid->ypole;
+ gridptr->angle = grid->angle;
+ if ( valdef_group1 && grid->area)
+ gridDefArea(gridID, grid->area);
+ gridptr->laea_a = grid->laea_a;
+ gridptr->laea_lon_0 = grid->laea_lon_0;
+ gridptr->laea_lat_0 = grid->laea_lat_0;
+ gridptr->lcc2_a = grid->lcc2_a;
+ gridptr->lcc2_lon_0 = grid->lcc2_lon_0;
+ gridptr->lcc2_lat_0 = grid->lcc2_lat_0;
+ gridptr->lcc2_lat_1 = grid->lcc2_lat_1;
+ gridptr->lcc2_lat_2 = grid->lcc2_lat_2;
+ gridptr->lcc_originLon = grid->lcc_originLon;
+ gridptr->lcc_originLat = grid->lcc_originLat;
+ gridptr->lcc_lonParY = grid->lcc_lonParY;
+ gridptr->lcc_lat1 = grid->lcc_lat1;
+ gridptr->lcc_lat2 = grid->lcc_lat2;
+ gridptr->lcc_xinc = grid->lcc_xinc;
+ gridptr->lcc_yinc = grid->lcc_yinc;
+ gridptr->lcc_projflag = grid->lcc_projflag;
+ gridptr->lcc_scanflag = grid->lcc_scanflag;
+ gridptr->number = grid->number;
+ gridptr->position = grid->position;
+ memcpy(gridptr->uuid, grid->uuid, CDI_UUID_SIZE);
+ if ( gridtype == GRID_UNSTRUCTURED && grid->reference )
+ gridDefReference(gridID, grid->reference);
+ if ( gridtype == GRID_PROJECTION )
+ gridptr->name = strdup(grid->name);
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ gridDefRowlon(gridID, grid->ysize, grid->rowlon);
+ gridptr->trunc = grid->trunc;
+ gridptr->lcomplex = grid->lcomplex;
+ gridptr->nd = grid->nd;
+ gridptr->ni = grid->ni;
+ gridptr->ni2 = grid->ni2;
+ gridptr->ni3 = grid->ni3;
+ const char *grid_str_tab[] = GRID_STR_SERIALIZE(grid);
+ char *gridptr_str_tab[] = GRID_STR_SERIALIZE(gridptr);
+ for (size_t i = 0; i < sizeof (grid_str_tab) / sizeof (grid_str_tab[0]); ++i)
+ if ( grid_str_tab[i][0] )
+ memcpy(gridptr_str_tab[i], grid_str_tab[i], CDI_MAX_NAME);
+ gridComplete(gridptr);
+ return (gridID);
+}
- size_t nrowlon = (size_t)gridptr->nrowlon;
+static void
+grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ size_t nrowlon = (size_t)gridptrOrig->nrowlon;
+ size_t gridsize = (size_t)gridptrOrig->size;
+ int gridtype = gridptrOrig->type;
int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
if ( nrowlon )
{
- gridptrnew->rowlon = (int *) Malloc(nrowlon * sizeof (int));
- memcpy(gridptrnew->rowlon, gridptr->rowlon, nrowlon * sizeof(int));
+ gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+ memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
}
- if ( gridptr->xvals != NULL )
+ if ( gridptrOrig->xvals != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->xsize);
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize;
- gridptrnew->xvals = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->xvals, gridptr->xvals, size * sizeof (double));
+ gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
}
- if ( gridptr->yvals != NULL )
+ if ( gridptrOrig->yvals != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->ysize);
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize;
- gridptrnew->yvals = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->yvals, gridptr->yvals, size * sizeof (double));
+ gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
}
- if ( gridptr->xbounds != NULL )
+ if ( gridptrOrig->xbounds != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->xsize)
- * (size_t)gridptr->nvertex;
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
+ * (size_t)gridptrOrig->nvertex;
- gridptrnew->xbounds = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->xbounds, gridptr->xbounds, size * sizeof (double));
+ gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
}
- if ( gridptr->ybounds != NULL )
+ if ( gridptrOrig->ybounds != NULL )
{
- size_t size = (size_t)(irregular ? gridsize : gridptr->ysize)
- * (size_t)gridptr->nvertex;
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
+ * (size_t)gridptrOrig->nvertex;
- gridptrnew->ybounds = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->ybounds, gridptr->ybounds, size * sizeof (double));
+ gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
}
- if ( gridptr->area != NULL )
- {
- size_t size = (size_t)gridsize;
+ {
+ const double *gridptrOrig_area
+ = gridptrOrig->vtable->inqAreaPtr(gridptrOrig);
+ if ( gridptrOrig_area != NULL )
+ {
+ size_t size = gridsize;
- gridptrnew->area = (double *) Malloc(size * sizeof (double));
- memcpy(gridptrnew->area, gridptr->area, size * sizeof (double));
- }
+ gridptrDup->area = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->area, gridptrOrig_area, size * sizeof (double));
+ }
+ }
- if ( gridptr->mask != NULL )
+ if ( gridptrOrig->mask != NULL )
{
- size_t size = (size_t)gridsize;
+ size_t size = gridsize;
- gridptrnew->mask = (mask_t *) Malloc(size * sizeof(mask_t));
- memcpy(gridptrnew->mask, gridptr->mask, size * sizeof (mask_t));
+ gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
+ memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
}
- if ( gridptr->mask_gme != NULL )
+ if ( gridptrOrig->mask_gme != NULL )
{
- size_t size = (size_t)gridsize;
+ size_t size = gridsize;
- gridptrnew->mask_gme = (mask_t *) Malloc(size * sizeof (mask_t));
- memcpy(gridptrnew->mask_gme, gridptr->mask_gme, size * sizeof(mask_t));
+ gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
+ memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
}
+}
+
+
+/*
+ at Function gridDuplicate
+ at Title Duplicate a horizontal Grid
+
+ at Prototype int gridDuplicate(int gridID)
+ at Parameter
+ @Item gridID Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
+
+ at Description
+The function @func{gridDuplicate} duplicates a horizontal Grid.
+
+ at Result
+ at func{gridDuplicate} returns an identifier to the duplicated Grid.
+
+ at EndFunction
+*/
+int gridDuplicate(int gridID)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ grid_t *gridptrnew = gridptr->vtable->copy(gridptr);
+ int gridIDnew = reshPut(gridptrnew, &gridOps);
+ gridptrnew->self = gridIDnew;
return (gridIDnew);
}
@@ -2715,71 +2901,72 @@ void gridCompress(int gridID)
{
size_t gridsize = (size_t)gridInqSize(gridID);
size_t nv = (size_t)gridptr->nvertex;
-
- size_t j = 0;
- double *area = gridptr->area,
- *xvals = gridptr->xvals,
- *yvals = gridptr->yvals,
- *xbounds = gridptr->xbounds,
- *ybounds = gridptr->ybounds;
- mask_t *mask_gme = gridptr->mask_gme;
- for (size_t i = 0; i < gridsize; i++ )
- {
- if (mask_gme[i])
- {
- if (xvals) xvals[j] = xvals[i];
- if (yvals) yvals[j] = yvals[i];
- if (area) area[j] = area[i];
- if (xbounds != NULL)
- for (size_t iv = 0; iv < nv; iv++)
- xbounds[j * nv + iv] = xbounds[i * nv + iv];
- if (ybounds != NULL)
- for (size_t iv = 0; iv < nv; iv++)
- ybounds[j * nv + iv] = ybounds[i * nv + iv];
-
- j++;
- }
- }
+ double *restrict area
+ = (double *)gridptr->vtable->inqAreaPtr(gridptr),
+ *restrict xvals = (double *)gridptr->vtable->inqXValsPtr((grid_t *)gridptr),
+ *restrict yvals = (double *)gridptr->vtable->inqYValsPtr((grid_t *)gridptr),
+ *restrict xbounds = (double *)gridptr->vtable->inqXBoundsPtr(gridptr),
+ *restrict ybounds = (double *)gridptr->vtable->inqYBoundsPtr(gridptr);
+ mask_t *restrict mask_gme = gridptr->mask_gme;
+ size_t *restrict selection = (size_t *)Malloc(gridsize * sizeof (selection[0]));
+ size_t nselect;
+ {
+ size_t j = 0;
+ for (size_t i = 0; i < gridsize; i++ )
+ selection[j] = i, j += (mask_gme[i] != 0);
+ nselect = j;
+ }
+ selection = (size_t *)Realloc(selection, nselect * sizeof (selection[0]));
+ if (xvals)
+ for (size_t i = 0; i < nselect; i++ )
+ xvals[i] = xvals[selection[i]];
+ if (yvals)
+ for (size_t i = 0; i < nselect; i++ )
+ yvals[i] = yvals[selection[i]];
+ if (area)
+ for (size_t i = 0; i < nselect; i++ )
+ area[i] = area[selection[i]];
+ if (xbounds)
+ for (size_t i = 0; i < nselect; i++ )
+ for (size_t iv = 0; iv < nv; iv++)
+ xbounds[i * nv + iv] = xbounds[selection[i] * nv + iv];
+ if (ybounds)
+ for (size_t i = 0; i < nselect; i++ )
+ for (size_t iv = 0; iv < nv; iv++)
+ ybounds[i * nv + iv] = ybounds[selection[i] * nv + iv];
+ Free(selection);
/* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */
- gridsize = j;
+ gridsize = nselect;
gridptr->size = (int)gridsize;
gridptr->xsize = (int)gridsize;
gridptr->ysize = (int)gridsize;
- if ( gridptr->xvals )
- gridptr->xvals = (double *) Realloc(gridptr->xvals, gridsize*sizeof(double));
-
- if ( gridptr->yvals )
- gridptr->yvals = (double *) Realloc(gridptr->yvals, gridsize*sizeof(double));
-
- if ( gridptr->area )
- gridptr->area = (double *) Realloc(gridptr->area, gridsize*sizeof(double));
-
- if ( gridptr->xbounds )
- gridptr->xbounds = (double *) Realloc(gridptr->xbounds, nv*gridsize*sizeof(double));
-
- if ( gridptr->ybounds )
- gridptr->ybounds = (double *) Realloc(gridptr->ybounds, nv*gridsize*sizeof(double));
+ double **resizeP[] = { &gridptr->xvals, &gridptr->yvals,
+ &gridptr->area,
+ &gridptr->xbounds, &gridptr->ybounds };
+ size_t newSize[] = { gridsize, gridsize, gridsize, nv*gridsize,
+ nv*gridsize };
+ for ( size_t i = 0; i < sizeof (resizeP) / sizeof (resizeP[0]); ++i)
+ if ( *(resizeP[i]) )
+ *(resizeP[i]) = (double *)Realloc(*(resizeP[i]), newSize[i]*sizeof(double));
Free(gridptr->mask_gme);
gridptr->mask_gme = NULL;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
else
Warning("Unsupported grid type: %s", gridNamePtr(gridtype));
}
-
-void gridDefArea(int gridID, const double *area)
+static void
+gridDefAreaSerial(grid_t *gridptr, const double *area)
{
- grid_t *gridptr = gridID2Ptr(gridID);
-
size_t size = (size_t)gridptr->size;
if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
+ Error("size undefined for gridID = %d", gridptr->self);
if ( gridptr->area == NULL )
gridptr->area = (double *) Malloc(size*sizeof(double));
@@ -2787,34 +2974,52 @@ void gridDefArea(int gridID, const double *area)
Warning("values already defined!");
memcpy(gridptr->area, area, size * sizeof(double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
}
-void gridInqArea(int gridID, double *area)
+void gridDefArea(int gridID, const double *area)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defArea(gridptr, area);
+ gridMark4Update(gridID);
+}
+static void
+gridInqAreaSerial(grid_t *gridptr, double *area)
+{
if (gridptr->area)
memcpy(area, gridptr->area, (size_t)gridptr->size * sizeof (double));
}
-int gridHasArea(int gridID)
+void gridInqArea(int gridID, double *area)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->inqArea(gridptr, area);
+}
- int hasArea = (gridptr->area != NULL);
+static int
+gridHasAreaBase(grid_t *gridptr)
+{
+ return gridptr->area != NULL;
+}
- return (hasArea);
+int gridHasArea(int gridID)
+{
+ grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->hasArea(gridptr);
}
+static const double *gridInqAreaPtrBase(grid_t *gridptr)
+{
+ return gridptr->area;
+}
+
const double *gridInqAreaPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return (gridptr->area);
+ return gridptr->vtable->inqAreaPtr(gridptr);
}
@@ -2825,7 +3030,7 @@ void gridDefNvertex(int gridID, int nvertex)
if (gridptr->nvertex != nvertex)
{
gridptr->nvertex = nvertex;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -2837,6 +3042,38 @@ int gridInqNvertex(int gridID)
return (gridptr->nvertex);
}
+static void
+gridDefBoundsGeneric(grid_t *gridptr, const double *bounds, int regularSize,
+ double **field)
+{
+ int irregular = gridptr->type == GRID_CURVILINEAR
+ || gridptr->type == GRID_UNSTRUCTURED;
+ size_t nvertex = (size_t)gridptr->nvertex;
+ if ( nvertex == 0 )
+ {
+ Warning("nvertex undefined for gridID = %d. Cannot define bounds!",
+ gridptr->self);
+ return;
+ }
+ size_t size = nvertex * (size_t)(irregular ? gridptr->size : regularSize);
+ if ( size == 0 )
+ Error("size undefined for gridID = %d", gridptr->self);
+
+ if (*field == NULL)
+ *field = (double *)Malloc(size * sizeof (double));
+ else if ( CDI_Debug )
+ Warning("values already defined!");
+
+ memcpy(*field, bounds, size * sizeof (double));
+}
+
+
+static void
+gridDefXBoundsSerial(grid_t *gridptr, const double *xbounds)
+{
+ gridDefBoundsGeneric(gridptr, xbounds, gridptr->xsize, &gridptr->xbounds);
+}
+
/*
@Function gridDefXbounds
@Title Define the bounds of a X-axis
@@ -2854,28 +3091,29 @@ The function @func{gridDefXbounds} defines all bounds of the X-axis.
void gridDefXbounds(int gridID, const double *xbounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defXBounds(gridptr, xbounds);
+ gridMark4Update(gridID);
+}
+static int
+gridInqXBoundsSerial(grid_t *gridptr, double *xbounds)
+{
size_t nvertex = (size_t)gridptr->nvertex;
- if ( nvertex == 0 )
- {
- Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
- return;
- }
int irregular = gridptr->type == GRID_CURVILINEAR
|| gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex
- * (size_t)(irregular ? gridptr->size : gridptr->xsize);
- if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
+ size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
- if (gridptr->xbounds == NULL)
- gridptr->xbounds = (double *) Malloc(size * sizeof (double));
- else if ( CDI_Debug )
- Warning("values already defined!");
+ const double *gridptr_xbounds = gridptr->vtable->inqXBoundsPtr(gridptr);
+ if ( gridptr_xbounds )
+ {
+ if ( size && xbounds )
+ memcpy(xbounds, gridptr_xbounds, size * sizeof (double));
+ }
+ else
+ size = 0;
- memcpy(gridptr->xbounds, xbounds, size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return ((int)size);
}
/*
@@ -2901,27 +3139,26 @@ Otherwise, 0 is returned and @func{xbounds} is empty.
int gridInqXbounds(int gridID, double *xbounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXBounds(gridptr, xbounds);
+}
- size_t nvertex = (size_t)gridptr->nvertex;
-
- int irregular = gridptr->type == GRID_CURVILINEAR
- || gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize);
-
- if ( size && xbounds && gridptr->xbounds )
- memcpy(xbounds, gridptr->xbounds, size * sizeof (double));
-
- if ( gridptr->xbounds == NULL ) size = 0;
-
- return ((int)size);
+static const double *
+gridInqXBoundsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->xbounds;
}
const double *gridInqXboundsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqXBoundsPtr(gridptr);
+}
- return (gridptr->xbounds);
+static void
+gridDefYBoundsSerial(grid_t *gridptr, const double *ybounds)
+{
+ gridDefBoundsGeneric(gridptr, ybounds, gridptr->ysize, &gridptr->ybounds);
}
/*
@@ -2941,30 +3178,32 @@ The function @func{gridDefYbounds} defines all bounds of the Y-axis.
void gridDefYbounds(int gridID, const double *ybounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ gridptr->vtable->defYBounds(gridptr, ybounds);
+ gridMark4Update(gridID);
+}
+static int
+gridInqYBoundsSerial(grid_t *gridptr, double *ybounds)
+{
size_t nvertex = (size_t)gridptr->nvertex;
- if ( nvertex == 0 )
- {
- Warning("nvertex undefined for gridID = %d. Cannot define bounds!", gridID);
- return;
- }
int irregular = gridptr->type == GRID_CURVILINEAR
|| gridptr->type == GRID_UNSTRUCTURED;
size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
- if ( size == 0 )
- Error("size undefined for gridID = %d", gridID);
-
- if ( gridptr->ybounds == NULL )
- gridptr->ybounds = (double *) Malloc(size * sizeof (double));
- else if ( CDI_Debug )
- Warning("values already defined!");
+ const double *gridptr_ybounds = gridptr->vtable->inqYBoundsPtr(gridptr);
+ if ( gridptr_ybounds )
+ {
+ if ( size && ybounds )
+ memcpy(ybounds, gridptr_ybounds, size * sizeof (double));
+ }
+ else
+ size = 0;
- memcpy(gridptr->ybounds, ybounds, size * sizeof (double));
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ return ((int)size);
}
+
/*
@Function gridInqYbounds
@Title Get the bounds of a Y-axis
@@ -2988,35 +3227,98 @@ Otherwise, 0 is returned and @func{ybounds} is empty.
int gridInqYbounds(int gridID, double *ybounds)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYBounds(gridptr, ybounds);
+}
- size_t nvertex = (size_t)gridptr->nvertex;
-
- int irregular = gridptr->type == GRID_CURVILINEAR
- || gridptr->type == GRID_UNSTRUCTURED;
- size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize);
-
- if ( size && ybounds && gridptr->ybounds )
- memcpy(ybounds, gridptr->ybounds, size * sizeof (double));
-
- if ( gridptr->ybounds == NULL ) size = 0;
-
- return ((int)size);
+static const double *
+gridInqYBoundsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->ybounds;
}
const double *gridInqYboundsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
+ return gridptr->vtable->inqYBoundsPtr(gridptr);
+}
+
+static void
+printDblsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const double vals[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%.9g ", vals[i]);
+ }
+ fputs("\n", fp);
+}
+
+static void
+printIntsPrefixAutoBrk(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const int vals[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%d ", vals[i]);
+ }
+ fputs("\n", fp);
+}
- return (gridptr->ybounds);
+static void
+printBounds(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, size_t nvertex, const double bounds[])
+{
+ fputs(prefix, fp);
+ if ( n > 0 )
+ {
+ for ( size_t iv = 0; iv < nvertex; iv++ )
+ fprintf(fp, "%.9g ", bounds[iv]);
+ for ( size_t i = 1; i < (size_t)n; i++ )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ for ( size_t iv = 0; iv < nvertex; iv++ )
+ fprintf(fp, "%.9g ", bounds[i*nvertex+iv]);
+ }
+ fputs("\n", fp);
+ }
}
+static void
+printMask(FILE *fp, const char prefix[], size_t nbyte0,
+ size_t n, const mask_t mask[])
+{
+ fputs(prefix, fp);
+ size_t nbyte = nbyte0;
+ for ( size_t i = 0; i < n; i++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n%*s", (int)nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += (size_t)fprintf(fp, "%d ", (int)mask[i]);
+ }
+ fputs("\n", fp);
+}
static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
{
int xdim, ydim;
- int nbyte;
- int i, iv;
unsigned char uuidOfHGrid[CDI_UUID_SIZE];
int gridID = gridptr->self;
const double *area = gridInqAreaPtr(gridID);
@@ -3032,12 +3334,11 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
int ysize = gridInqYsize(gridID);
int nvertex = gridInqNvertex(gridID);
- int nbyte0 = 0;
- fprintf(fp, "#\n");
- fprintf(fp, "# gridID %d\n", index);
- fprintf(fp, "#\n");
- fprintf(fp, "gridtype = %s\n", gridNamePtr(type));
- fprintf(fp, "gridsize = %d\n", gridsize);
+ fprintf(fp, "#\n"
+ "# gridID %d\n"
+ "#\n"
+ "gridtype = %s\n"
+ "gridsize = %d\n", index, gridNamePtr(type), gridsize);
if ( type != GRID_GME )
{
@@ -3121,20 +3422,21 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
{
double a = 0, lon_0 = 0, lat_0 = 0;
gridInqLaea(gridID, &a, &lon_0, &lat_0);
- fprintf(fp, "a = %g\n", a);
- fprintf(fp, "lon_0 = %g\n", lon_0);
- fprintf(fp, "lat_0 = %g\n", lat_0);
+ fprintf(fp, "a = %g\n"
+ "lon_0 = %g\n"
+ "lat_0 = %g\n", a, lon_0, lat_0);
}
if ( type == GRID_LCC2 )
{
double a = 0, lon_0 = 0, lat_0 = 0, lat_1 = 0, lat_2 = 0;
gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2);
- fprintf(fp, "a = %g\n", a);
- fprintf(fp, "lon_0 = %g\n", lon_0);
- fprintf(fp, "lat_0 = %g\n", lat_0);
- fprintf(fp, "lat_1 = %g\n", lat_1);
- fprintf(fp, "lat_2 = %g\n", lat_2);
+ fprintf(fp, "a = %g\n"
+ "lon_0 = %g\n"
+ "lat_0 = %g\n"
+ "lat_1 = %g\n"
+ "lat_2 = %g\n",
+ a, lon_0, lat_0, lat_1, lat_2);
}
if ( gridptr->isRotated )
@@ -3158,38 +3460,23 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( IS_NOT_EQUAL(xinc, 0) && opt )
{
- fprintf(fp, "xfirst = %g\n", xfirst);
- fprintf(fp, "xinc = %g\n", xinc);
+ fprintf(fp, "xfirst = %g\n"
+ "xinc = %g\n", xfirst, xinc);
}
else
{
- nbyte0 = fprintf(fp, "xvals = ");
- nbyte = nbyte0;
- for ( i = 0; i < xdim; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", xvals[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "xvals = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(xdim > 0 ? xdim : 0), xvals);
}
}
if ( xbounds )
{
- nbyte0 = fprintf(fp, "xbounds = ");
- for ( i = 0; i < xdim; i++ )
- {
- if ( i ) fprintf(fp, "%*s", nbyte0, "");
-
- for ( iv = 0; iv < nvertex; iv++ )
- fprintf(fp, "%.9g ", xbounds[i*nvertex+iv]);
- fprintf(fp, "\n");
- }
+ static const char prefix[] = "xbounds = ";
+ printBounds(fp, prefix, sizeof (prefix),
+ (size_t)(xdim > 0 ? xdim : 0),
+ (size_t)(nvertex > 0 ? nvertex : 0), xbounds);
}
if ( yvals )
@@ -3205,75 +3492,39 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( IS_NOT_EQUAL(yinc, 0) && opt )
{
- fprintf(fp, "yfirst = %g\n", yfirst);
- fprintf(fp, "yinc = %g\n", yinc);
+ fprintf(fp, "yfirst = %g\n"
+ "yinc = %g\n", yfirst, yinc);
}
else
{
- nbyte0 = fprintf(fp, "yvals = ");
- nbyte = nbyte0;
- for ( i = 0; i < ydim; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", yvals[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "yvals = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(ydim > 0 ? ydim : 0), yvals);
}
}
if ( ybounds )
{
- nbyte0 = fprintf(fp, "ybounds = ");
- for ( i = 0; i < ydim; i++ )
- {
- if ( i ) fprintf(fp, "%*s", nbyte0, "");
-
- for ( iv = 0; iv < nvertex; iv++ )
- fprintf(fp, "%.9g ", ybounds[i*nvertex+iv]);
- fprintf(fp, "\n");
- }
+ static const char prefix[] = "ybounds = ";
+ printBounds(fp, prefix, sizeof (prefix),
+ (size_t)(ydim > 0 ? ydim : 0),
+ (size_t)(nvertex > 0 ? nvertex : 0), ybounds);
}
if ( area )
{
- nbyte0 = fprintf(fp, "area = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridsize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%.9g ", area[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "area = ";
+ printDblsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(gridsize > 0 ? gridsize : 0), area);
}
if ( type == GRID_GAUSSIAN_REDUCED )
{
- int *rowlon;
- nbyte0 = fprintf(fp, "rowlon = ");
- nbyte = nbyte0;
- rowlon = (int *) Malloc((size_t)ysize*sizeof(int));
+ static const char prefix[] = "rowlon = ";
+ int *rowlon = (int *)Malloc((size_t)ysize*sizeof(int));
gridInqRowlon(gridID, rowlon);
- for ( i = 0; i < ysize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", rowlon[i]);
- }
- fprintf(fp, "\n");
+ printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(ysize > 0 ? ysize : 0), rowlon);
Free(rowlon);
}
@@ -3286,27 +3537,26 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
&projflag, &scanflag);
- fprintf(fp, "xsize = %d\n", xsize);
- fprintf(fp, "ysize = %d\n", ysize);
-
- fprintf(fp, "originLon = %g\n", originLon);
- fprintf(fp, "originLat = %g\n", originLat);
- fprintf(fp, "lonParY = %g\n", lonParY);
- fprintf(fp, "lat1 = %g\n", lat1);
- fprintf(fp, "lat2 = %g\n", lat2);
- fprintf(fp, "xinc = %g\n", xincm);
- fprintf(fp, "yinc = %g\n", yincm);
- if ( (projflag & 128) == 0 )
- fprintf(fp, "projection = northpole\n");
- else
- fprintf(fp, "projection = southpole\n");
-
+ fprintf(fp,
+ "xsize = %d\n"
+ "ysize = %d\n"
+ "originLon = %g\n"
+ "originLat = %g\n"
+ "lonParY = %g\n"
+ "lat1 = %g\n"
+ "lat2 = %g\n"
+ "xinc = %g\n"
+ "yinc = %g\n"
+ "projection = %s\n"
+ , xsize, ysize, originLon, originLat, lonParY, lat1, lat2,
+ xincm, yincm,
+ (projflag & 128) == 0 ? "northpole" : "southpole");
break;
}
case GRID_SPECTRAL:
{
- fprintf(fp, "truncation = %d\n", trunc);
- fprintf(fp, "complexpacking = %d\n", gridptr->lcomplex );
+ fprintf(fp, "truncation = %d\n"
+ "complexpacking = %d\n", trunc, gridptr->lcomplex );
break;
}
case GRID_FOURIER:
@@ -3330,26 +3580,16 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
fprintf(fp, "uuid = %s\n", uuidOfHGridStr);
}
if ( gridptr->mask )
{
- nbyte0 = fprintf(fp, "mask = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridsize; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", (int) gridptr->mask[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "mask = ";
+ printMask(fp, prefix, sizeof (prefix),
+ (size_t)(gridsize > 0 ? gridsize : 0), gridptr->mask);
}
}
@@ -3365,72 +3605,64 @@ void gridPrint ( int gridID, int index, int opt )
void gridPrintP ( void * voidptr, FILE * fp )
{
grid_t * gridptr = ( grid_t * ) voidptr;
- int nbyte0, nbyte, i;
xassert ( gridptr );
gridPrintKernel ( gridptr , gridptr->self, 0, fp );
- fprintf ( fp, "precision = %d\n", gridptr->prec);
- fprintf ( fp, "nd = %d\n", gridptr->nd );
- fprintf ( fp, "ni = %d\n", gridptr->ni );
- fprintf ( fp, "ni2 = %d\n", gridptr->ni2 );
- fprintf ( fp, "ni3 = %d\n", gridptr->ni3 );
- fprintf ( fp, "number = %d\n", gridptr->number );
- fprintf ( fp, "position = %d\n", gridptr->position );
- fprintf ( fp, "trunc = %d\n", gridptr->trunc );
- fprintf ( fp, "lcomplex = %d\n", gridptr->lcomplex );
- fprintf ( fp, "nrowlon = %d\n", gridptr->nrowlon );
+ fprintf(fp,
+ "precision = %d\n"
+ "nd = %d\n"
+ "ni = %d\n"
+ "ni2 = %d\n"
+ "ni3 = %d\n"
+ "number = %d\n"
+ "position = %d\n"
+ "trunc = %d\n"
+ "lcomplex = %d\n"
+ "nrowlon = %d\n",
+ gridptr->prec, gridptr->nd, gridptr->ni, gridptr->ni2,
+ gridptr->ni3, gridptr->number, gridptr->position, gridptr->trunc,
+ gridptr->lcomplex, gridptr->nrowlon );
if ( gridptr->rowlon )
{
- nbyte0 = fprintf(fp, "rowlon = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridptr->nrowlon; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", gridptr->rowlon[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "rowlon = ";
+ printIntsPrefixAutoBrk(fp, prefix, sizeof (prefix),
+ (size_t)(gridptr->nrowlon > 0
+ ? gridptr->nrowlon : 0), gridptr->rowlon);
}
if ( gridptr->mask_gme )
{
- nbyte0 = fprintf(fp, "mask_gme = ");
- nbyte = nbyte0;
- for ( i = 0; i < gridptr->size; i++ )
- {
- if ( nbyte > 80 )
- {
- fprintf(fp, "\n");
- fprintf(fp, "%*s", nbyte0, "");
- nbyte = nbyte0;
- }
- nbyte += fprintf(fp, "%d ", (int) gridptr->mask_gme[i]);
- }
- fprintf(fp, "\n");
+ static const char prefix[] = "mask_gme = ";
+ printMask(fp, prefix, sizeof (prefix),
+ (size_t)(gridptr->size > 0 ? gridptr->size : 0),
+ gridptr->mask_gme);
}
}
+static const double *gridInqXValsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->xvals;
+}
const double *gridInqXvalsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return ( gridptr->xvals );
+ return gridptr->vtable->inqXValsPtr(gridptr);
}
+static const double *gridInqYValsPtrSerial(grid_t *gridptr)
+{
+ return gridptr->yvals;
+}
+
const double *gridInqYvalsPtr(int gridID)
{
grid_t *gridptr = gridID2Ptr(gridID);
-
- return ( gridptr->yvals );
+ return gridptr->vtable->inqYValsPtr(gridptr);
}
/*
@@ -3476,7 +3708,7 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY,
gridptr->lcc_projflag = projflag;
gridptr->lcc_scanflag = scanflag;
gridptr->lcc_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3545,7 +3777,7 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do
gridptr->lcc2_lat_1 = lat_1;
gridptr->lcc2_lat_2 = lat_2;
gridptr->lcc2_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3585,7 +3817,7 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0)
gridptr->laea_lon_0 = lon_0;
gridptr->laea_lat_0 = lat_0;
gridptr->laea_defined = TRUE;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3618,8 +3850,8 @@ void gridDefComplexPacking(int gridID, int lcomplex)
if (gridptr->lcomplex != lcomplex)
{
- gridptr->lcomplex = lcomplex;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridptr->lcomplex = (short)(lcomplex != 0);
+ gridMark4Update(gridID);
}
}
@@ -3636,10 +3868,10 @@ void gridDefHasDims(int gridID, int hasdims)
{
grid_t* gridptr = gridID2Ptr(gridID);
- if (gridptr->hasdims != hasdims)
+ if (gridptr->hasdims != (hasdims != 0))
{
- gridptr->hasdims = hasdims;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridptr->hasdims = hasdims != 0;
+ gridMark4Update(gridID);
}
}
@@ -3672,7 +3904,7 @@ void gridDefNumber(int gridID, const int number)
if (gridptr->number != number)
{
gridptr->number = number;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3694,8 +3926,7 @@ The function @func{gridInqNumber} returns the reference number to an unstructure
int gridInqNumber(int gridID)
{
grid_t* gridptr = gridID2Ptr(gridID);
-
- return (gridptr->number);
+ return gridptr->number;
}
/*
@@ -3719,7 +3950,7 @@ void gridDefPosition(int gridID, int position)
if (gridptr->position != position)
{
gridptr->position = position;
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3772,7 +4003,7 @@ void gridDefReference(int gridID, const char *reference)
}
gridptr->reference = strdupx(reference);
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
}
@@ -3823,7 +4054,7 @@ void gridDefUUID(int gridID, const unsigned char uuid[CDI_UUID_SIZE])
grid_t* gridptr = gridID2Ptr(gridID);
memcpy(gridptr->uuid, uuid, CDI_UUID_SIZE);
- reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE);
+ gridMark4Update(gridID);
}
/*
@@ -3861,7 +4092,7 @@ gridTxCode ()
return GRID;
}
-enum { gridNint = 27,
+enum { gridNint = 28,
gridNdouble = 24,
gridHasMaskFlag = 1 << 0,
gridHasGMEMaskFlag = 1 << 1,
@@ -3880,9 +4111,13 @@ static int gridGetComponentFlags(const grid_t * gridP)
{
int flags = (gridHasMaskFlag & (int)((unsigned)(gridP->mask == NULL) - 1U))
| (gridHasGMEMaskFlag & (int)((unsigned)(gridP->mask_gme == NULL) - 1U))
- | (gridHasXValsFlag & (int)((unsigned)(gridP->xvals == NULL) - 1U))
- | (gridHasYValsFlag & (int)((unsigned)(gridP->yvals == NULL) - 1U))
- | (gridHasAreaFlag & (int)((unsigned)(gridP->area == NULL) - 1U))
+ | (gridHasXValsFlag
+ & (int)((unsigned)(gridP->vtable->inqXValsPtr((grid_t *)gridP) == NULL) - 1U))
+ | (gridHasYValsFlag
+ & (int)((unsigned)(gridP->vtable->inqYValsPtr((grid_t *)gridP) == NULL) - 1U))
+ | (gridHasAreaFlag
+ & (int)((unsigned)(gridP->vtable->inqAreaPtr((grid_t *)gridP) == NULL)
+ - 1U))
| (gridHasXBoundsFlag & (int)((unsigned)(gridP->xbounds == NULL) - 1U))
| (gridHasYBoundsFlag & (int)((unsigned)(gridP->ybounds == NULL) - 1U))
| (gridHasReferenceFlag & (int)((unsigned)(gridP->reference == NULL) - 1U))
@@ -3892,9 +4127,8 @@ static int gridGetComponentFlags(const grid_t * gridP)
}
-#define GRID_STR_SERIALIZE { gridP->xname, gridP->yname, \
+#define GRID_STR_SERIALIZE(gridP) { gridP->xname, gridP->yname, \
gridP->xlongname, gridP->ylongname, \
- gridP->xstdname, gridP->ystdname, \
gridP->xunits, gridP->yunits }
static int
@@ -3915,7 +4149,7 @@ gridGetPackSize(void * voidP, void *context)
packBuffSize += serializeGetSize(gridNdouble, DATATYPE_FLT64, context);
- if (gridP->xvals)
+ if (gridP->vtable->inqXValsPtr(gridP))
{
if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
count = gridP->size;
@@ -3926,7 +4160,7 @@ gridGetPackSize(void * voidP, void *context)
+ serializeGetSize(1, DATATYPE_UINT32, context);
}
- if (gridP->yvals)
+ if (gridP->vtable->inqYValsPtr(gridP))
{
if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR)
count = gridP->size;
@@ -3937,7 +4171,7 @@ gridGetPackSize(void * voidP, void *context)
+ serializeGetSize(1, DATATYPE_UINT32, context);
}
- if (gridP->area)
+ if (gridP->vtable->inqAreaPtr(gridP))
{
xassert(gridP->size);
packBuffSize +=
@@ -3972,7 +4206,7 @@ gridGetPackSize(void * voidP, void *context)
}
{
- const char *strTab[] = GRID_STR_SERIALIZE;
+ const char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = (int)(sizeof (strTab) / sizeof (strTab[0]));
packBuffSize
+= serializeStrTabGetPackSize(strTab, numStr, context);
@@ -4054,9 +4288,10 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
gridP->size = intBuffer[21];
gridP->xsize = intBuffer[22];
gridP->ysize = intBuffer[23];
- gridP->locked = intBuffer[24];
- gridP->lcomplex = intBuffer[25];
- memberMask = intBuffer[26];
+ gridP->lcomplex = (short)intBuffer[24];
+ memberMask = intBuffer[25];
+ gridP->xstdname = xystdname_tab[intBuffer[26]][0];
+ gridP->ystdname = xystdname_tab[intBuffer[27]][1];
}
if (memberMask & gridHasRowLonFlag)
@@ -4169,7 +4404,7 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
}
{
- char *strTab[] = GRID_STR_SERIALIZE;
+ char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = sizeof (strTab) / sizeof (strTab[0]);
serializeStrTabUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
strTab, numStr, context);
@@ -4256,9 +4491,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
intBuffer[21] = gridP->size;
intBuffer[22] = gridP->xsize;
intBuffer[23] = gridP->ysize;
- intBuffer[24] = gridP->locked;
- intBuffer[25] = gridP->lcomplex;
- intBuffer[26] = memberMask = gridGetComponentFlags(gridP);
+ intBuffer[24] = gridP->lcomplex;
+ intBuffer[25] = memberMask = gridGetComponentFlags(gridP);
+ intBuffer[26] = (int)((const char (*)[2][24])gridP->xstdname
+ - xystdname_tab);
+ intBuffer[27] = (int)((const char (*)[2][24])gridP->ystdname
+ - (const char (*)[2][24])xystdname_tab[0][1]);
serializePack(intBuffer, gridNint, DATATYPE_INT,
packBuffer, packBufferSize, packBufferPos, context);
@@ -4321,9 +4559,10 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
size = gridP->xsize;
xassert(size);
- serializePack(gridP->xvals, size, DATATYPE_FLT64,
+ const double *gridP_xvals = gridP->vtable->inqXValsPtr(gridP);
+ serializePack(gridP_xvals, size, DATATYPE_FLT64,
packBuffer, packBufferSize, packBufferPos, context);
- d = cdiCheckSum(DATATYPE_FLT, size, gridP->xvals);
+ d = cdiCheckSum(DATATYPE_FLT, size, gridP_xvals);
serializePack(&d, 1, DATATYPE_UINT32,
packBuffer, packBufferSize, packBufferPos, context);
}
@@ -4335,9 +4574,10 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
else
size = gridP->ysize;
xassert(size);
- serializePack(gridP->yvals, size, DATATYPE_FLT64,
+ const double *gridP_yvals = gridP->vtable->inqYValsPtr(gridP);
+ serializePack(gridP_yvals, size, DATATYPE_FLT64,
packBuffer, packBufferSize, packBufferPos, context);
- d = cdiCheckSum(DATATYPE_FLT, size, gridP->yvals);
+ d = cdiCheckSum(DATATYPE_FLT, size, gridP_yvals);
serializePack(&d, 1, DATATYPE_UINT32,
packBuffer, packBufferSize, packBufferPos, context);
}
@@ -4386,7 +4626,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
}
{
- const char *strTab[] = GRID_STR_SERIALIZE;
+ const char *strTab[] = GRID_STR_SERIALIZE(gridP);
int numStr = sizeof (strTab) / sizeof (strTab[0]);
serializeStrTabPack(strTab, numStr,
packBuffer, packBufferSize, packBufferPos, context);
@@ -4433,16 +4673,16 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
#undef GRID_STR_SERIALIZE
-struct varDefGridSearchState
+struct gridCompareSearchState
{
int resIDValue;
const grid_t *queryKey;
};
static enum cdiApplyRet
-varDefGridSearch(int id, void *res, void *data)
+gridCompareSearch(int id, void *res, void *data)
{
- struct varDefGridSearchState *state = (struct varDefGridSearchState*)data;
+ struct gridCompareSearchState *state = (struct gridCompareSearchState*)data;
(void)res;
if (gridCompare(id, state->queryKey) == 0)
{
@@ -4453,40 +4693,43 @@ varDefGridSearch(int id, void *res, void *data)
return CDI_APPLY_GO_ON;
}
-int varDefGrid(int vlistID, const grid_t *grid, int mode)
+/* Add grid (which must be Malloc'ed to vlist if not already found */
+struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode)
{
/*
mode: 0 search in vlist and grid table
1 search in grid table
*/
int gridglobdefined = FALSE;
- int griddefined;
+ int griddefined = FALSE;
int gridID = CDI_UNDEFID;
vlist_t *vlistptr = vlist_to_pointer(vlistID);
- griddefined = FALSE;
unsigned ngrids = (unsigned)vlistptr->ngrids;
if ( mode == 0 )
for (unsigned index = 0; index < ngrids; index++ )
{
- gridID = vlistptr->gridIDs[index];
- if ( gridID == UNDEFID )
- Error("Internal problem: undefined gridID %d!", gridID);
+ if ( (gridID = vlistptr->gridIDs[index]) != UNDEFID )
+ {
+ if ( gridCompare(gridID, grid) == 0 )
+ {
+ griddefined = TRUE;
+ break;
+ }
+ }
+ else
+ Error("Internal problem: undefined gridID in vlist "
+ "%d, position %u!", vlistID, index);
- if ( gridCompare(gridID, grid) == 0 )
- {
- griddefined = TRUE;
- break;
- }
}
if ( ! griddefined )
{
- struct varDefGridSearchState query;
+ struct gridCompareSearchState query;
query.queryKey = grid;// = { .queryKey = grid };
if ((gridglobdefined
- = (cdiResHFilterApply(&gridOps, varDefGridSearch, &query)
+ = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query)
== CDI_APPLY_STOP)))
gridID = query.resIDValue;
@@ -4501,15 +4744,51 @@ int varDefGrid(int vlistID, const grid_t *grid, int mode)
if ( ! griddefined )
{
- if ( ! gridglobdefined ) gridID = gridGenerate(grid);
- ngrids = (unsigned)vlistptr->ngrids;
+ if ( ! gridglobdefined )
+ {
+ grid->self = gridID = reshPut(grid, &gridOps);
+ gridComplete(grid);
+ }
vlistptr->gridIDs[ngrids] = gridID;
vlistptr->ngrids++;
}
- return (gridID);
+ return (struct addIffNewRes){ .Id = gridID,
+ .isNew = !griddefined && !gridglobdefined };
}
+const struct gridVirtTable cdiGridVtable
+ = {
+ .destroy = gridDestroyKernel,
+ .copy = grid_copy_base,
+ .copyScalarFields = grid_copy_base_scalar_fields,
+ .copyArrayFields = grid_copy_base_array_fields,
+ .defXVals = gridDefXValsSerial,
+ .defYVals = gridDefYValsSerial,
+ .defMask = gridDefMaskSerial,
+ .defMaskGME = gridDefMaskGMESerial,
+ .defXBounds = gridDefXBoundsSerial,
+ .defYBounds = gridDefYBoundsSerial,
+ .defArea = gridDefAreaSerial,
+ .inqXVal = gridInqXValSerial,
+ .inqYVal = gridInqYValSerial,
+ .inqXVals = gridInqXValsSerial,
+ .inqYVals = gridInqYValsSerial,
+ .inqXValsPtr = gridInqXValsPtrSerial,
+ .inqYValsPtr = gridInqYValsPtrSerial,
+ .compareXYFull = compareXYvals,
+ .compareXYAO = compareXYvals2,
+ .inqArea = gridInqAreaSerial,
+ .inqAreaPtr = gridInqAreaPtrBase,
+ .hasArea = gridHasAreaBase,
+ .inqMask = gridInqMaskSerial,
+ .inqMaskGME = gridInqMaskGMESerial,
+ .inqXBounds = gridInqXBoundsSerial,
+ .inqYBounds = gridInqYBoundsSerial,
+ .inqXBoundsPtr = gridInqXBoundsPtrSerial,
+ .inqYBoundsPtr = gridInqYBoundsPtrSerial,
+};
+
/*
* Local Variables:
* c-file-style: "Java"
diff --git a/libcdi/src/grid.h b/libcdi/src/grid.h
index a248f59..fea99d7 100644
--- a/libcdi/src/grid.h
+++ b/libcdi/src/grid.h
@@ -5,7 +5,44 @@
typedef unsigned char mask_t;
-typedef struct {
+typedef struct grid_t grid_t;
+
+struct gridVirtTable
+{
+ void (*destroy)(grid_t *gridptr);
+ grid_t *(*copy)(grid_t *gridptr);
+ void (*copyScalarFields)(grid_t *gridptrOrig, grid_t *gridptrDup);
+ void (*copyArrayFields)(grid_t *gridptrOrig, grid_t *gridptrDup);
+ void (*defXVals)(grid_t *gridptr, const double *xvals);
+ void (*defYVals)(grid_t *gridptr, const double *yvals);
+ void (*defMask)(grid_t *gridptr, const int *mask);
+ void (*defMaskGME)(grid_t *gridptr, const int *mask);
+ void (*defXBounds)(grid_t *gridptr, const double *xbounds);
+ void (*defYBounds)(grid_t *gridptr, const double *ybounds);
+ void (*defArea)(grid_t *gridptr, const double *area);
+ double (*inqXVal)(grid_t *gridptr, int index);
+ double (*inqYVal)(grid_t *gridptr, int index);
+ int (*inqXVals)(grid_t *gridptr, double *xvals);
+ int (*inqYVals)(grid_t *gridptr, double *yvals);
+ const double *(*inqXValsPtr)(grid_t *gridptr);
+ const double *(*inqYValsPtr)(grid_t *gridptr);
+ /* return if for both grids, all xval and all yval are equal */
+ int (*compareXYFull)(grid_t *gridRef, grid_t *gridTest);
+ /* return if for both grids, x[0], y[0], x[size-1] and y[size-1] are
+ * respectively equal */
+ int (*compareXYAO)(grid_t *gridRef, grid_t *gridTest);
+ void (*inqArea)(grid_t *gridptr, double *area);
+ const double *(*inqAreaPtr)(grid_t *gridptr);
+ int (*hasArea)(grid_t *gridptr);
+ int (*inqMask)(grid_t *gridptr, int *mask);
+ int (*inqMaskGME)(grid_t *gridptr, int *mask_gme);
+ int (*inqXBounds)(grid_t *gridptr, double *xbounds);
+ int (*inqYBounds)(grid_t *gridptr, double *ybounds);
+ const double *(*inqXBoundsPtr)(grid_t *gridptr);
+ const double *(*inqYBoundsPtr)(grid_t *gridptr);
+};
+
+struct grid_t {
int self;
int type; /* grid type */
int prec; /* grid precision */
@@ -57,24 +94,28 @@ typedef struct {
int xsize; /* number of values along X */
int ysize; /* number of values along Y */
int np; /* number of parallels between a pole and the equator */
- int locked;
- int lcomplex;
- int hasdims;
+ short lcomplex;
+ short hasdims;
+ const char *xstdname;
+ const char *ystdname;
char xname[CDI_MAX_NAME];
char yname[CDI_MAX_NAME];
char xlongname[CDI_MAX_NAME];
char ylongname[CDI_MAX_NAME];
- char xstdname[CDI_MAX_NAME];
- char ystdname[CDI_MAX_NAME];
char xunits[CDI_MAX_NAME];
char yunits[CDI_MAX_NAME];
char *name;
-}
-grid_t;
+ const struct gridVirtTable *vtable;
+ void *extraData;
+};
void grid_init(grid_t *gridptr);
+void
+cdiGridTypeInit(grid_t *gridptr, int gridtype, int size);
void grid_free(grid_t *gridptr);
+grid_t *gridID2Ptr(int gridID);
+extern const struct gridVirtTable cdiGridVtable;
unsigned cdiGridCount(void);
@@ -95,16 +136,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
int * unpackBufferPos, int originNamespace, void *context,
int force_id);
-int varDefGrid(int vlistID, const grid_t *grid, int mode);
-
-/* These are used by CDO. */
-void gridGenXvals(int xsize, double xfirst, double xlast,
- double xinc, double *xvals);
-void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast,
- double yinc, double *yvals);
-
-
+struct addIffNewRes
+{
+ int Id;
+ int isNew;
+};
+struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode);
#endif
/*
diff --git a/libcdi/src/ieglib.c b/libcdi/src/ieglib.c
index 2e0d494..cbae283 100644
--- a/libcdi/src/ieglib.c
+++ b/libcdi/src/ieglib.c
@@ -297,15 +297,9 @@ int iegInqDataDP(void *ieg, double *data)
static int
iegDefData(iegrec_t *iegp, int prec, const void *data)
{
- int dprec;
- void *buffer;
+ int dprec = iegDefaultDprec ? iegDefaultDprec : iegp->dprec;
- if ( iegDefaultDprec ) dprec = iegDefaultDprec;
- else dprec = iegp->dprec;
-
- if ( ! dprec ) dprec = prec;
-
- iegp->dprec = dprec;
+ iegp->dprec = dprec = dprec ? dprec : prec;
size_t datasize = (size_t)IEG_G_NumLon(iegp->igdb) * (size_t)IEG_G_NumLat(iegp->igdb);
size_t blocklen = datasize * (size_t)dprec;
@@ -314,16 +308,14 @@ iegDefData(iegrec_t *iegp, int prec, const void *data)
size_t buffersize = iegp->buffersize;
+ void *buffer = iegp->buffer;
if ( buffersize != blocklen )
{
buffersize = blocklen;
- buffer = iegp->buffer;
buffer = Realloc(buffer, buffersize);
iegp->buffer = buffer;
iegp->buffersize = buffersize;
}
- else
- buffer = iegp->buffer;
switch ( dprec )
{
diff --git a/libcdi/src/institution.c b/libcdi/src/institution.c
index 10ea652..69c1cff 100644
--- a/libcdi/src/institution.c
+++ b/libcdi/src/institution.c
@@ -67,7 +67,7 @@ void instituteDefaultEntries ( void )
= { ECMWF = institutDef( 98, 0, "ECMWF", "European Centre for Medium-Range Weather Forecasts"),
MPIMET = institutDef( 98, 232, "MPIMET", "Max-Planck-Institute for Meteorology"),
institutDef( 98, 255, "MPIMET", "Max-Planck-Institute for Meteorology"),
- institutDef( 98, 232, "MPIMET", "Max-Planck Institute for Meteorology"),
+ institutDef( 98, 232, "MPIMET", "Max Planck Institute for Meteorology"),
institutDef( 78, 0, "DWD", "Deutscher Wetterdienst"),
institutDef( 78, 255, "DWD", "Deutscher Wetterdienst"),
MCH = institutDef(215, 255, "MCH", "MeteoSwiss"),
diff --git a/libcdi/src/iterator.c b/libcdi/src/iterator.c
index 2ed5933..eb63a23 100644
--- a/libcdi/src/iterator.c
+++ b/libcdi/src/iterator.c
@@ -433,7 +433,7 @@ int cdiIterator_nextField(CdiIterator* me)
}
}
-static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
+static char* cdiIterator_inqTime(CdiIterator* me, CdiTimeType timeType)
{
sanityCheck(me);
switch(me->filetype)
@@ -441,7 +441,7 @@ static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
#ifdef HAVE_LIBGRIB_API
case FILETYPE_GRB:
case FILETYPE_GRB2:
- return cdiGribIterator_inqTime(me, getEndTime);
+ return cdiGribIterator_inqTime(me, timeType);
#endif
#ifdef HAVE_LIBNETCDF
@@ -459,7 +459,7 @@ static char* cdiIterator_inqTime(CdiIterator* me, bool getEndTime)
#ifdef HAVE_LIBIEG
case FILETYPE_IEG:
#endif
- return cdiFallbackIterator_inqTime(me, getEndTime);
+ return cdiFallbackIterator_inqTime(me, timeType);
default:
Error(kUnexpectedFileTypeMessage);
@@ -490,7 +490,7 @@ This is due to the fact that GRIB-API version 1.12.3 still does not implement th
*/
char* cdiIterator_inqStartTime(CdiIterator* me)
{
- return cdiIterator_inqTime(me, false);
+ return cdiIterator_inqTime(me, kCdiTimeType_startTime);
}
/*
@@ -516,7 +516,34 @@ This is due to the fact that GRIB-API version 1.12.3 still does not implement th
*/
char* cdiIterator_inqEndTime(CdiIterator* me)
{
- return cdiIterator_inqTime(me, true);
+ return cdiIterator_inqTime(me, kCdiTimeType_endTime);
+}
+
+/*
+ at Function cdiIterator_inqRTime
+ at Title Get the validity time of the current field
+
+ at Prototype char* cdiIterator_inqRTime(CdiIterator* me)
+ at Parameter
+ @item iterator The iterator to operate on.
+
+ at Result A malloc'ed string containing the validity time of the current field in the format "YYYY-MM-DDTHH:MM:SS.mmm".
+
+ at Description
+The returned time is the validity time as it is returned by taxisInqVtime(), only more precise.
+That is, if the field is a time point, its time is returned,
+if it is a statistical field with an integration period, the end time of the integration period is returned.
+
+Converts the time to the ISO-8601 format and returns it in a newly allocated buffer.
+The caller is responsible to Free() the resulting string.
+
+If the file is a GRIB file, the calendar that is used to resolve the relative times is the proleptic calendar
+as it is implemented by the standard C mktime() function.
+This is due to the fact that GRIB-API version 1.12.3 still does not implement the calendar identification fields.
+*/
+char* cdiIterator_inqRTime(CdiIterator* me)
+{
+ return cdiIterator_inqTime(me, kCdiTimeType_referenceTime);
}
/*
@@ -701,6 +728,105 @@ int cdiIterator_inqLevelUuid(CdiIterator* me, int* outVgridNumber, int* outLevel
}
/*
+ at Function cdiIterator_inqTile
+ at Title Inquire the tile information for the current field
+
+ at Prototype int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outTileIndex The index of the current tile, -1 if no tile information is available.
+ @item outTileAttribute The attribute of the current tile, -1 if no tile information is available.
+
+ at Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
+
+ at Description
+Inquire the tile index and attribute for the current field.
+*/
+int cdiIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute)
+{
+ sanityCheck(me);
+ switch(me->filetype)
+ {
+ #ifdef HAVE_LIBGRIB_API
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ return cdiGribIterator_inqTile(me, outTileIndex, outTileAttribute);
+ #endif
+
+ #ifdef HAVE_LIBNETCDF
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ #endif
+ #ifdef HAVE_LIBSERVICE
+ case FILETYPE_SRV:
+ #endif
+ #ifdef HAVE_LIBEXTRA
+ case FILETYPE_EXT:
+ #endif
+ #ifdef HAVE_LIBIEG
+ case FILETYPE_IEG:
+ #endif
+ return cdiFallbackIterator_inqTile(me, outTileIndex, outTileAttribute);
+
+ default:
+ Error(kUnexpectedFileTypeMessage);
+ return CDI_ELIBNAVAIL;
+ }
+}
+
+/**
+ at Function cdiIterator_inqTileCount
+ at Title Inquire the tile count and tile attribute counts for the current field
+
+ at Prototype int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outTileCount The number of tiles used for this variable, zero if no tile information is available.
+ @item outTileAttributeCount The number of attributes available for the tile of this field, zero if no tile information is available.
+ Note: This is not the global attribute count, which would be impossible to infer without reading the entire file if it's a GRIB file.
+
+ at Result An error code. CDI_EINVAL if there is no tile information associated with the current field.
+
+ at Description
+Inquire the tile count and tile attribute counts for the current field.
+*/
+int cdiIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount)
+{
+ sanityCheck(me);
+ switch(me->filetype)
+ {
+ #ifdef HAVE_LIBGRIB_API
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ return cdiGribIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
+ #endif
+
+ #ifdef HAVE_LIBNETCDF
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ #endif
+ #ifdef HAVE_LIBSERVICE
+ case FILETYPE_SRV:
+ #endif
+ #ifdef HAVE_LIBEXTRA
+ case FILETYPE_EXT:
+ #endif
+ #ifdef HAVE_LIBIEG
+ case FILETYPE_IEG:
+ #endif
+ return cdiFallbackIterator_inqTileCount(me, outTileCount, outTileAttributeCount);
+
+ default:
+ Error(kUnexpectedFileTypeMessage);
+ return CDI_ELIBNAVAIL;
+ }
+}
+
+/*
@Function cdiIterator_inqParam
@Title Get discipline, category, and number
@@ -720,6 +846,31 @@ CdiParam cdiIterator_inqParam(CdiIterator* me)
}
/*
+ at Function cdiIterator_inqParamParts
+ at Title Get discipline, category, and number
+
+ at Prototype void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber)
+ at Parameter
+ @item iterator The iterator to operate on.
+ @item outDiscipline This is used to return the discipline.
+ @item outCategory This is used to return the category.
+ @item outNumber This is used to return the number.
+
+ at Description
+ Simple metadata inspection function.
+
+ Some FORTRAN compilers produce wrong code for the cdiIterator_inqParam()-wrapper,
+ rendering it unusable from FORTRAN. This function is the workaround.
+*/
+void cdiIterator_inqParamParts(CdiIterator *me, int *outDiscipline, int *outCategory, int *outNumber)
+{
+ CdiParam result = cdiIterator_inqParam(me);
+ if(outDiscipline) *outDiscipline = result.discipline;
+ if(outCategory) *outCategory = result.category;
+ if(outNumber) *outNumber = result.number;
+}
+
+/*
@Function cdiIterator_inqDatatype
@Title Get the datatype of the current field
diff --git a/libcdi/src/iterator_fallback.c b/libcdi/src/iterator_fallback.c
index 74177ba..213f85d 100644
--- a/libcdi/src/iterator_fallback.c
+++ b/libcdi/src/iterator_fallback.c
@@ -11,11 +11,12 @@
struct CdiFallbackIterator {
CdiIterator super;
- int streamId, vlistId;
+ int streamId, vlistId, subtypeId;
char *path; //needed for clone() & serialize()
int variableCount, curVariable;
int curLevelCount, curLevel;
+ int curSubtypeCount, curSubtype;
int curTimestep;
};
@@ -39,12 +40,15 @@ static CdiFallbackIterator *cdiFallbackIterator_condestruct(CdiFallbackIterator
if(me->vlistId == CDI_UNDEFID) goto closeStream;
me->variableCount = vlistNvars(me->vlistId);
if(me->variableCount <= 0) goto closeStream;
+ me->subtypeId = CDI_UNDEFID; //Will be set in cdiFallbackIterator_nextField()
+ me->curSubtypeCount = -1; //Will be set in cdiFallbackIterator_nextField()
me->curLevelCount = -1; //Will be set in cdiFallbackIterator_nextField()
//These values are chosen so that the natural increment at the start of cdiFallbackIterator_nextField() will correctly position us at the first slice.
me->curTimestep = 0;
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
- me->curVariable = 0;
+ me->curVariable = -1;
+ me->curSubtype = -1;
me->curLevel = -1;
me->path = strdup(path);
if(!me->path) goto closeStream;
@@ -70,14 +74,20 @@ CdiIterator *cdiFallbackIterator_new(const char *path, int filetype)
return &cdiFallbackIterator_condestruct(NULL, path, filetype)->super;
}
-//Fetches the info that is published by the variables in the base class from the current field.
-static void fetchSuperInfo(CdiFallbackIterator *me)
+//Fetches the info that is derived from the current variable. Most of this is published by the data members in the base class.
+static void fetchVariableInfo(CdiFallbackIterator *me)
{
+ //Fetch data that's published via base class data members.
me->super.datatype = vlistInqVarDatatype(me->vlistId, me->curVariable);
me->super.timesteptype = vlistInqVarTsteptype(me->vlistId, me->curVariable);
me->super.gridId = vlistInqVarGrid(me->vlistId, me->curVariable);
int param = vlistInqVarParam(me->vlistId, me->curVariable);
cdiDecodeParam(param, &me->super.param.number, &me->super.param.category, &me->super.param.discipline);
+
+ //Fetch the current level and subtype counts.
+ me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
+ me->subtypeId = vlistInqVarSubtype(me->vlistId, me->curVariable);
+ me->curSubtypeCount = (me->subtypeId == CDI_UNDEFID) ? 1 : subtypeInqSize(me->subtypeId);
}
CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
@@ -93,10 +103,12 @@ CdiFallbackIterator *cdiFallbackIterator_clone(CdiIterator *super)
clone->curVariable = me->curVariable;
clone->curLevelCount = me->curLevelCount;
clone->curLevel = me->curLevel;
+ clone->curSubtypeCount = me->curSubtypeCount;
+ clone->curSubtype = me->curSubtype;
clone->curTimestep = me->curTimestep;
clone->super.isAdvanced = super->isAdvanced;
- if(super->isAdvanced) fetchSuperInfo(clone);
+ if(super->isAdvanced) fetchVariableInfo(clone);
return clone;
}
@@ -107,8 +119,8 @@ char *cdiFallbackIterator_serialize(CdiIterator *super)
char *escapedPath = cdiEscapeSpaces(me->path);
char *result = (char *) Malloc(strlen(escapedPath)
- + 5 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
- sprintf(result, "%s %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curTimestep);
+ + 7 * (3 * sizeof (int) * CHAR_BIT / 8 + 1) + 1);
+ sprintf(result, "%s %d %d %d %d %d %d %d", escapedPath, me->variableCount, me->curVariable, me->curLevelCount, me->curLevel, me->curSubtypeCount, me->curSubtype, me->curTimestep);
Free(escapedPath);
return result;
}
@@ -142,11 +154,13 @@ CdiFallbackIterator *cdiFallbackIterator_deserialize(const char *description)
decodeValue(me->curVariable, description);
decodeValue(me->curLevelCount, description);
decodeValue(me->curLevel, description);
+ decodeValue(me->curSubtypeCount, description);
+ decodeValue(me->curSubtype, description);
decodeValue(me->curTimestep, description);
#undef decodeValue
if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) goto closeStream;
- if(me->super.isAdvanced) fetchSuperInfo(me);
+ if(me->super.isAdvanced) fetchVariableInfo(me);
return me;
@@ -164,15 +178,20 @@ fail:
static int advance(CdiFallbackIterator *me)
{
me->curLevel++;
- if(me->curLevel == me->curLevelCount)
+ if(me->curLevel >= me->curLevelCount)
{
me->curLevel = 0;
- me->curVariable++;
- if(me->curVariable == me->variableCount)
+ me->curSubtype++;
+ if(me->curSubtype >= me->curSubtypeCount)
{
- me->curVariable = 0;
- me->curTimestep++;
- if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) return CDI_EEOF;
+ me->curSubtype = 0;
+ me->curVariable++;
+ if(me->curVariable >= me->variableCount)
+ {
+ me->curVariable = 0;
+ me->curTimestep++;
+ if(streamInqTimestep(me->streamId, me->curTimestep) <= 0) return CDI_EEOF;
+ }
}
}
return CDI_NOERR;
@@ -184,21 +203,37 @@ int cdiFallbackIterator_nextField(CdiIterator *super)
int result = advance(me);
if(result) return result;
- if(!me->curLevel)
- { //Fetch the information that may have changed (we are processing a new variable/timestep if this point is reached).
- fetchSuperInfo(me);
- me->curLevelCount = zaxisInqSize(vlistInqVarZaxis(me->vlistId, me->curVariable));
- }
+ if(!me->curLevel && !me->curSubtype) fetchVariableInfo(me); //Check whether we are processing a new variable/timestep and fetch the information that may have changed in this case.
return CDI_NOERR;
}
-char *cdiFallbackIterator_inqTime(CdiIterator *super, bool getEndTime)
+char *cdiFallbackIterator_inqTime(CdiIterator *super, CdiTimeType timeType)
{
CdiFallbackIterator *me = (CdiFallbackIterator *)(void *)super;
- if(getEndTime) return NULL; //The stream interface does not export the start/end times of statistical fields, so we treat all data as point of time data, returning the validity time as the start time.
+
+ //retrieve the time information
int taxisId = vlistInqTaxis(me->vlistId);
- int date = taxisInqVdate(taxisId);
- int time = taxisInqVtime(taxisId);
+ int date = 0, time = 0;
+ switch(timeType)
+ {
+ case kCdiTimeType_referenceTime:
+ date = taxisInqRdate(taxisId);
+ time = taxisInqRtime(taxisId);
+ break;
+
+ case kCdiTimeType_startTime:
+ date = taxisInqVdate(taxisId);
+ time = taxisInqVtime(taxisId);
+ break;
+
+ case kCdiTimeType_endTime:
+ return NULL; //The stream interface does not export the start/end times of statistical fields, so we treat all data as point of time data, returning the validity time as the start time.
+
+ default:
+ assert(0 && "internal error, please report this bug");
+ }
+
+ //decode the time information and reencode it into an ISO-compliant string
int year, month, day, hour, minute, second;
cdiDecodeDate(date, &year, &month, &day);
cdiDecodeTime(time, &hour, &minute, &second);
@@ -278,6 +313,58 @@ int cdiFallbackIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *
return CDI_NOERR;
}
+int cdiFallbackIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
+{
+ CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
+#ifndef __cplusplus
+ if(!outTileIndex) outTileIndex = &(int){0};
+ if(!outTileAttribute) outTileAttribute = &(int){0};
+#else
+ int dummy = 0;
+ if(!outTileIndex) outTileIndex = &dummy;
+ if(!outTileAttribute) outTileAttribute = &dummy;
+#endif
+
+ int error = CDI_NOERR;
+ if(me->subtypeId == CDI_UNDEFID) //must not call subtypeInqAttribute() with an invalid subtype ID, because it would abort the program instead of returning an error
+ {
+ error = CDI_EINVAL;
+ }
+ else
+ {
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileIndex", outTileIndex)) error = CDI_EINVAL;
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "tileAttribute", outTileAttribute)) error = CDI_EINVAL;
+ }
+ if(error) *outTileIndex = *outTileAttribute = -1; //Guarantee defined values in case of an error.
+ return error;
+}
+
+int cdiFallbackIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
+{
+ CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
+#ifndef __cplusplus
+ if(!outTileCount) outTileCount = &(int){0};
+ if(!outTileAttributeCount) outTileAttributeCount = &(int){0};
+#else
+ int temp = 0;
+ if(!outTileCount) outTileCount = &temp;
+ if(!outTileAttributeCount) outTileAttributeCount = &temp;
+#endif
+
+ int error = CDI_NOERR;
+ if(me->subtypeId == CDI_UNDEFID) //must not call subtypeInqAttribute() with an invalid subtype ID, because it would abort the program instead of returning an error
+ {
+ error = CDI_EINVAL;
+ }
+ else
+ {
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTiles", outTileCount)) error = CDI_EINVAL;
+ if(subtypeInqAttribute(me->subtypeId, me->curSubtype, "numberOfTileAttributes", outTileAttributeCount)) error = CDI_EINVAL;
+ }
+ if(error) *outTileCount = *outTileAttributeCount = -1; //Guarantee defined values in case of an error.
+ return CDI_NOERR;
+}
+
char *cdiFallbackIterator_copyVariableName(CdiIterator *super)
{
CdiFallbackIterator *me = (CdiFallbackIterator*)(void *)super;
diff --git a/libcdi/src/iterator_fallback.h b/libcdi/src/iterator_fallback.h
index aee5ae9..6c7170f 100644
--- a/libcdi/src/iterator_fallback.h
+++ b/libcdi/src/iterator_fallback.h
@@ -9,6 +9,7 @@
#define INCLUDE_GUARD_CDI_ITERATOR_FALLBACK_H
#include "cdi.h"
+#include "cdi_int.h"
#include "iterator.h"
typedef struct CdiFallbackIterator CdiFallbackIterator;
@@ -21,11 +22,13 @@ CdiFallbackIterator *cdiFallbackIterator_deserialize(const char *me);
int cdiFallbackIterator_nextField(CdiIterator *me);
-char *cdiFallbackIterator_inqTime(CdiIterator *me, bool getEndTime);
+char *cdiFallbackIterator_inqTime(CdiIterator *me, CdiTimeType timeType);
int cdiFallbackIterator_levelType(CdiIterator *me, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit);
int cdiFallbackIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiFallbackIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
char *cdiFallbackIterator_copyVariableName(CdiIterator *me);
+int cdiFallbackIterator_inqTile(CdiIterator* me, int* outTileIndex, int* outTileAttribute);
+int cdiFallbackIterator_inqTileCount(CdiIterator* me, int* outTileCount, int* outTileAttributeCount);
void cdiFallbackIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
void cdiFallbackIterator_readFieldF(CdiIterator *me, float *buffer, size_t *nmiss);
diff --git a/libcdi/src/iterator_grib.c b/libcdi/src/iterator_grib.c
index 7dd6ba1..fc8ef71 100644
--- a/libcdi/src/iterator_grib.c
+++ b/libcdi/src/iterator_grib.c
@@ -21,14 +21,14 @@
struct CdiGribIterator {
CdiIterator super;
- CdiInputFile* file;
+ CdiInputFile *file;
off_t fileOffset;
- unsigned char* gribBuffer;
+ unsigned char *gribBuffer;
size_t bufferSize, curRecordSize;
#ifdef HAVE_LIBGRIB_API
- grib_handle* gribHandle;
+ grib_handle *gribHandle;
#else
- void* gribHandle;
+ void *gribHandle;
#endif
};
@@ -88,7 +88,7 @@ CdiGribIterator *cdiGribIterator_makeClone(CdiIterator *super)
CdiGribIterator *me = (CdiGribIterator*)super;
//Allocate memory and copy data. (operations that may fail)
- CdiGribIterator* result = (struct CdiGribIterator *) Malloc(sizeof(*result));
+ CdiGribIterator *result = (struct CdiGribIterator *) Malloc(sizeof(*result));
if(!result) goto fail;
result->file = me->file;
@@ -139,9 +139,9 @@ char *cdiGribIterator_serialize(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
- const char* path = cdiInputFile_getPath(me->file);
- char* escapedPath = cdiEscapeSpaces(path);
- char* result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
+ const char *path = cdiInputFile_getPath(me->file);
+ char *escapedPath = cdiEscapeSpaces(path);
+ char *result = (char *) Malloc(strlen(escapedPath) + 3 * sizeof(int) * CHAR_BIT/8);
sprintf(result, "%s %zu", escapedPath, me->fileOffset);
Free(escapedPath);
return result;
@@ -150,8 +150,8 @@ char *cdiGribIterator_serialize(CdiIterator *super)
CdiGribIterator *cdiGribIterator_deserialize(const char *description)
{
- char* path;
- CdiGribIterator* me = (CdiGribIterator *) Malloc(sizeof(*me));
+ char *path;
+ CdiGribIterator *me = (CdiGribIterator *) Malloc(sizeof(*me));
if(!me) goto fail;
description = baseIter_constructFromString(&me->super, description);
@@ -236,7 +236,7 @@ static ssize_t scanToGribMarker(CdiGribIterator *me)
if(scannedBytes + scanSize > kMaxScanSize) scanSize = kMaxScanSize - scannedBytes;
assert(scanSize <= me->bufferSize);
int status = cdiInputFile_read(me->file, me->fileOffset + (off_t)scannedBytes, scanSize, &scanSize, me->gribBuffer);
- if(status != CDI_NOERR && status != CDI_EEOF) return status;
+ if(status != CDI_NOERR && status != CDI_EEOF) return -1;
const unsigned char *startPosition = positionOfGribMarker(me->gribBuffer, scanSize);
if(startPosition)
@@ -246,21 +246,21 @@ static ssize_t scanToGribMarker(CdiGribIterator *me)
//Get the offset for the next iteration if there is a next iteration.
scanSize -= 3; //so that we won't miss a 'GRIB' sequence that happens to be cut off
- scannedBytes += scanSize;
- scannedBytes &= ~(size_t)0xf; //make 16 bytes aligned
+ scanSize &= ~(size_t)0xf; //make 16 bytes aligned
+ if((ssize_t)scanSize <= 0) return -1; //ensure that we make progress
}
return -1;
}
static unsigned decode24(void *beData)
{
- unsigned char* bytes = (unsigned char *)beData;
+ unsigned char *bytes = (unsigned char *)beData;
return ((unsigned)bytes[0] << 16) + ((unsigned)bytes[1] << 8) + (unsigned)bytes[2];
}
static uint64_t decode64(void *beData)
{
- unsigned char* bytes = (unsigned char *)beData;
+ unsigned char *bytes = (unsigned char *)beData;
uint64_t result = 0;
for(size_t i = 0; i < 8; i++) result = (result << 8) + bytes[i];
return result;
@@ -367,10 +367,10 @@ int cdiGribIterator_nextField(CdiIterator *super)
return CDI_NOERR;
}
-char *cdiGribIterator_inqTime(CdiIterator *super, bool getEndTime)
+char *cdiGribIterator_inqTime(CdiIterator *super, CdiTimeType timeType)
{
CdiGribIterator *me = (CdiGribIterator*)super;
- return gribMakeTimeString(me->gribHandle, getEndTime);
+ return gribMakeTimeString(me->gribHandle, timeType);
}
int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit)
@@ -381,13 +381,13 @@ int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outN
int zaxisType = ZAXIS_GENERIC;
if(gribEditionNumber(me->gribHandle) <= 1)
{
- int levelType = gribGetLongDefault(me->gribHandle, "indicatorOfTypeOfLevel", 255);
+ int levelType = (int)gribGetLongDefault(me->gribHandle, "indicatorOfTypeOfLevel", 255);
if(levelSelector && !isGrib1DualLevel(levelType)) levelType = 255;
zaxisType = grib1ltypeToZaxisType(levelType);
}
else
{
- int levelType = gribGetLongDefault(me->gribHandle, levelSelector ? "typeOfSecondFixedSurface" : "typeOfFirstFixedSurface", 255);
+ int levelType = (int)gribGetLongDefault(me->gribHandle, levelSelector ? "typeOfSecondFixedSurface" : "typeOfFirstFixedSurface", 255);
zaxisType = grib2ltypeToZaxisType(levelType);
}
@@ -405,6 +405,7 @@ int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outN
static double logicalLevelValue2(long gribType, long storedValue, long power)
{
double factor = 1;
+ assert(power >= 0);
while(power--) factor *= 10; //this is precise up to factor == 22.
switch(gribType)
{
@@ -450,7 +451,7 @@ static int readLevel2(grib_handle *gribHandle, const char *levelTypeKey, const c
default:
{
- long power = gribGetLongDefault(gribHandle, powerKey, 0); //1 byte
+ long power = 255 & gribGetLongDefault(gribHandle, powerKey, 0); //1 byte
if(power == 255) power = 0;
long value = gribGetLongDefault(gribHandle, valueKey, 0); //4 bytes
*outValue1 = logicalLevelValue2(levelType, value, power);
@@ -525,6 +526,46 @@ int cdiGribIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *outL
return CDI_NOERR;
}
+int cdiGribIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
+{
+ CdiGribIterator *me = (CdiGribIterator*)super;
+ int trash;
+ if(!outTileIndex) outTileIndex = &trash;
+ if(!outTileAttribute) outTileAttribute = &trash;
+
+ //Get the values if possible.
+ int error = CDI_NOERR;
+ long value;
+ if(grib_get_long(me->gribHandle, "tileIndex", &value)) error = CDI_EINVAL;
+ *outTileIndex = (int)value;
+ if(grib_get_long(me->gribHandle, "tileAttribute", &value)) error = CDI_EINVAL;
+ *outTileAttribute = (int)value;
+
+ //Ensure defined return values in case of failure.
+ if(error) *outTileIndex = *outTileAttribute = -1;
+ return error;
+}
+
+int cdiGribIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
+{
+ CdiGribIterator *me = (CdiGribIterator*)super;
+ int trash;
+ if(!outTileCount) outTileCount = &trash;
+ if(!outTileAttributeCount) outTileAttributeCount = &trash;
+
+ //Get the values if possible.
+ int error = CDI_NOERR;
+ long value;
+ if(grib_get_long(me->gribHandle, "numberOfTiles", &value)) error = CDI_EINVAL;
+ *outTileCount = (int)value;
+ if(grib_get_long(me->gribHandle, "numberOfTileAttributes", &value)) error = CDI_EINVAL;
+ *outTileAttributeCount = (int)value;
+
+ //Ensure defined return values in case of failure.
+ if(error) *outTileCount = *outTileAttributeCount = 0;
+ return error;
+}
+
char *cdiGribIterator_copyVariableName(CdiIterator *super)
{
CdiGribIterator *me = (CdiGribIterator*)super;
@@ -549,7 +590,7 @@ void cdiGribIterator_readFieldF(CdiIterator *super, float *buffer, size_t *nmiss
CdiGribIterator *me = (CdiGribIterator*)super;
size_t valueCount = gribGetArraySize(me->gribHandle, "values");
- double* temp = (double *) Malloc(valueCount*sizeof(*temp));
+ double *temp = (double *) Malloc(valueCount*sizeof(*temp));
cdiGribIterator_readField(super, temp, nmiss);
for(size_t i = valueCount; i--; ) buffer[i] = (float)temp[i];
Free(temp);
@@ -572,8 +613,8 @@ void cdiGribIterator_delete(CdiGribIterator *me)
#ifdef HAVE_LIBGRIB_API
if(me) cdiGribIterator_condestruct(me, NULL, 0);
#else
- (void)me;
- xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+ if (me)
+ xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
#endif
}
diff --git a/libcdi/src/iterator_grib.h b/libcdi/src/iterator_grib.h
index 2b19110..65b9962 100644
--- a/libcdi/src/iterator_grib.h
+++ b/libcdi/src/iterator_grib.h
@@ -8,6 +8,7 @@
#define INCLUDE_GUARD_CDI_ITERATOR_GRIB_H
#include "cdi.h"
+#include "cdi_int.h"
#include "iterator.h"
#include "input_file.h"
@@ -25,10 +26,12 @@ CdiGribIterator *cdiGribIterator_deserialize(const char *me);
int cdiGribIterator_nextField(CdiIterator *me);
-char *cdiGribIterator_inqTime(CdiIterator *me, bool getEndTime);
+char *cdiGribIterator_inqTime(CdiIterator *me, CdiTimeType timeType);
int cdiGribIterator_levelType(CdiIterator *me, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit);
int cdiGribIterator_level(CdiIterator *me, int levelSelector, double *outValue1, double *outValue2);
int cdiGribIterator_zaxisUuid(CdiIterator *me, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE]);
+int cdiGribIterator_inqTile(CdiIterator *me, int *outTileIndex, int *outTileAttribute);
+int cdiGribIterator_inqTileCount(CdiIterator *me, int *outTileCount, int *outTileAttributeCount);
char *cdiGribIterator_copyVariableName(CdiIterator *me);
void cdiGribIterator_readField(CdiIterator *me, double *buffer, size_t *nmiss);
diff --git a/libcdi/src/mo_cdi.f90 b/libcdi/src/mo_cdi.f90
index 02a4b7f..1221ad0 100644
--- a/libcdi/src/mo_cdi.f90
+++ b/libcdi/src/mo_cdi.f90
@@ -1,6 +1,6 @@
! >>> Warning: This is a generated file. If you modify it, you get what you deserve. <<<
!
-! Generated by "../../../../libcdi/interfaces/f2003/bindGen.rb" from input file "../../../../libcdi/src/cdi.h".
+! Generated by "../interfaces/f2003/bindGen.rb" from input file "../src/cdi.h".
module mo_cdi
use iso_c_binding
@@ -259,6 +259,7 @@ module mo_cdi
public :: streamWriteRecord
public :: streamWriteRecordF
public :: streamReadRecord
+ public :: streamReadRecordF
public :: streamCopyRecord
public :: cdiIterator_new
public :: cdiIterator_clone
@@ -268,11 +269,15 @@ module mo_cdi
public :: cdiIterator_nextField
public :: cdiIterator_inqStartTime
public :: cdiIterator_inqEndTime
+ public :: cdiIterator_inqRTime
public :: cdiIterator_inqVTime
public :: cdiIterator_inqLevelType
public :: cdiIterator_inqLevel
public :: cdiIterator_inqLevelUuid
+ public :: cdiIterator_inqTile
+ public :: cdiIterator_inqTileCount
public :: cdiIterator_inqParam
+ public :: cdiIterator_inqParamParts
public :: cdiIterator_inqDatatype
public :: cdiIterator_inqTsteptype
public :: cdiIterator_inqVariableName
@@ -404,6 +409,9 @@ module mo_cdi
public :: vlistHasVarKey
public :: vlistInqVarDblKey
public :: vlistInqVarIntKey
+ public :: vlistInqVarNamePtr
+ public :: vlistInqVarLongnamePtr
+ public :: vlistInqVarUnitsPtr
public :: vlistInqNatts
public :: vlistInqAtt
public :: vlistDelAtt
@@ -626,6 +634,7 @@ module mo_cdi
public :: subtypeInqActiveIndex
public :: subtypeDefActiveIndex
public :: subtypeInqTile
+ public :: subtypeInqAttribute
public :: vlistInqVarSubtype
public :: gribapiLibraryVersion
@@ -964,6 +973,14 @@ module mo_cdi
integer(c_int), intent(inout) :: nmiss_dummy
end subroutine streamReadRecord
+ subroutine streamReadRecordF(streamID_dummy, data_dummy, nmiss_dummy)&
+ & bind(c, name = 'streamReadRecordF')
+ import c_float, c_int
+ integer(c_int), value :: streamID_dummy
+ real(c_float), intent(inout) :: data_dummy(*)
+ integer(c_int), intent(inout) :: nmiss_dummy
+ end subroutine streamReadRecordF
+
subroutine streamCopyRecord(streamIDdest_dummy, streamIDsrc_dummy) bind(c,&
& name = 'streamCopyRecord')
import c_int
@@ -3265,6 +3282,32 @@ contains
end if
end function cdiIterator_inqEndTime
+ function cdiIterator_inqRTime(me_dummy) result(f_result)
+ character(kind = c_char), dimension(:), pointer :: f_result
+ type(t_CdiIterator), intent(in) :: me_dummy
+ type(c_ptr) :: cString
+ integer :: rv_shape(1)
+ character(kind = c_char), dimension(:), pointer :: temp
+ interface
+ function lib_cdiIterator_inqRTime(me_dummy) bind(c, name =&
+ & 'cdiIterator_inqRTime') result(c_result)
+ import c_ptr
+ type(c_ptr) :: c_result
+ type(c_ptr), value :: me_dummy
+ end function lib_cdiIterator_inqRTime
+ end interface
+ cString = lib_cdiIterator_inqRTime(me_dummy%ptr)
+ if(c_associated(cString)) then
+ rv_shape(1) = int(lib_strlen(cString))
+ call c_f_pointer(cString, temp, rv_shape)
+ allocate(f_result(rv_shape(1)))
+ f_result = temp
+ call lib_free(cString)
+ else
+ f_result => null()
+ end if
+ end function cdiIterator_inqRTime
+
function cdiIterator_inqVTime(me_dummy) result(f_result)
character(kind = c_char), dimension(:), pointer :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
@@ -3449,6 +3492,48 @@ contains
& outLevelCount_cptr, outUuid_cptr)
end function cdiIterator_inqLevelUuid
+ function cdiIterator_inqTile(me_dummy, outTileIndex_dummy,&
+ & outTileAttribute_dummy) result(f_result)
+ integer(c_int) :: f_result
+ type(t_CdiIterator), intent(in) :: me_dummy
+ integer(c_int), intent(inout) :: outTileIndex_dummy
+ integer(c_int), intent(inout) :: outTileAttribute_dummy
+ interface
+ function lib_cdiIterator_inqTile(me_dummy, outTileIndex_dummy,&
+ & outTileAttribute_dummy) bind(c, name = 'cdiIterator_inqTile')&
+ & result(c_result)
+ import c_int, c_ptr
+ integer(c_int) :: c_result
+ type(c_ptr), value :: me_dummy
+ integer(c_int), intent(inout) :: outTileIndex_dummy
+ integer(c_int), intent(inout) :: outTileAttribute_dummy
+ end function lib_cdiIterator_inqTile
+ end interface
+ f_result = lib_cdiIterator_inqTile(me_dummy%ptr, outTileIndex_dummy,&
+ & outTileAttribute_dummy)
+ end function cdiIterator_inqTile
+
+ function cdiIterator_inqTileCount(me_dummy, outTileCount_dummy,&
+ & outTileAttributeCount_dummy) result(f_result)
+ integer(c_int) :: f_result
+ type(t_CdiIterator), intent(in) :: me_dummy
+ integer(c_int), intent(inout) :: outTileCount_dummy
+ integer(c_int), intent(inout) :: outTileAttributeCount_dummy
+ interface
+ function lib_cdiIterator_inqTileCount(me_dummy, outTileCount_dummy,&
+ & outTileAttributeCount_dummy) bind(c, name = 'cdiIterator_inqTileCount')&
+ & result(c_result)
+ import c_int, c_ptr
+ integer(c_int) :: c_result
+ type(c_ptr), value :: me_dummy
+ integer(c_int), intent(inout) :: outTileCount_dummy
+ integer(c_int), intent(inout) :: outTileAttributeCount_dummy
+ end function lib_cdiIterator_inqTileCount
+ end interface
+ f_result = lib_cdiIterator_inqTileCount(me_dummy%ptr, outTileCount_dummy,&
+ & outTileAttributeCount_dummy)
+ end function cdiIterator_inqTileCount
+
function cdiIterator_inqParam(me_dummy) result(f_result)
type(t_CdiParam) :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
@@ -3463,6 +3548,27 @@ contains
f_result = lib_cdiIterator_inqParam(me_dummy%ptr)
end function cdiIterator_inqParam
+ subroutine cdiIterator_inqParamParts(me_dummy, outDiscipline_dummy,&
+ & outCategory_dummy, outNumber_dummy)
+ type(t_CdiIterator), intent(in) :: me_dummy
+ integer(c_int), intent(inout) :: outDiscipline_dummy
+ integer(c_int), intent(inout) :: outCategory_dummy
+ integer(c_int), intent(inout) :: outNumber_dummy
+ interface
+ subroutine lib_cdiIterator_inqParamParts(me_dummy, outDiscipline_dummy,&
+ & outCategory_dummy, outNumber_dummy) bind(c, name =&
+ & 'cdiIterator_inqParamParts')
+ import c_int, c_ptr
+ type(c_ptr), value :: me_dummy
+ integer(c_int), intent(inout) :: outDiscipline_dummy
+ integer(c_int), intent(inout) :: outCategory_dummy
+ integer(c_int), intent(inout) :: outNumber_dummy
+ end subroutine lib_cdiIterator_inqParamParts
+ end interface
+ call lib_cdiIterator_inqParamParts(me_dummy%ptr, outDiscipline_dummy,&
+ & outCategory_dummy, outNumber_dummy)
+ end subroutine cdiIterator_inqParamParts
+
function cdiIterator_inqDatatype(me_dummy) result(f_result)
integer(c_int) :: f_result
type(t_CdiIterator), intent(in) :: me_dummy
@@ -4395,6 +4501,75 @@ contains
f_result = lib_vlistInqVarIntKey(vlistID_dummy, varID_dummy, name_temp)
end function vlistInqVarIntKey
+ function vlistInqVarNamePtr(vlistID_dummy, varID_dummy) result(f_result)
+ character(kind = c_char), dimension(:), pointer :: f_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ type(c_ptr) :: ptr
+ integer :: rv_shape(1)
+ interface
+ function lib_vlistInqVarNamePtr(vlistID_dummy, varID_dummy) bind(c, name&
+ & = 'vlistInqVarNamePtr') result(c_result)
+ import c_int, c_ptr
+ type(c_ptr) :: c_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ end function lib_vlistInqVarNamePtr
+ end interface
+ f_result => null()
+ ptr = lib_vlistInqVarNamePtr(vlistID_dummy, varID_dummy)
+ if(c_associated(ptr)) then
+ rv_shape(1) = int(lib_strlen(ptr))
+ call c_f_pointer(ptr, f_result, rv_shape)
+ end if
+ end function vlistInqVarNamePtr
+
+ function vlistInqVarLongnamePtr(vlistID_dummy, varID_dummy) result(f_result)
+ character(kind = c_char), dimension(:), pointer :: f_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ type(c_ptr) :: ptr
+ integer :: rv_shape(1)
+ interface
+ function lib_vlistInqVarLongnamePtr(vlistID_dummy, varID_dummy) bind(c,&
+ & name = 'vlistInqVarLongnamePtr') result(c_result)
+ import c_int, c_ptr
+ type(c_ptr) :: c_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ end function lib_vlistInqVarLongnamePtr
+ end interface
+ f_result => null()
+ ptr = lib_vlistInqVarLongnamePtr(vlistID_dummy, varID_dummy)
+ if(c_associated(ptr)) then
+ rv_shape(1) = int(lib_strlen(ptr))
+ call c_f_pointer(ptr, f_result, rv_shape)
+ end if
+ end function vlistInqVarLongnamePtr
+
+ function vlistInqVarUnitsPtr(vlistID_dummy, varID_dummy) result(f_result)
+ character(kind = c_char), dimension(:), pointer :: f_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ type(c_ptr) :: ptr
+ integer :: rv_shape(1)
+ interface
+ function lib_vlistInqVarUnitsPtr(vlistID_dummy, varID_dummy) bind(c, name&
+ & = 'vlistInqVarUnitsPtr') result(c_result)
+ import c_int, c_ptr
+ type(c_ptr) :: c_result
+ integer(c_int), value :: vlistID_dummy
+ integer(c_int), value :: varID_dummy
+ end function lib_vlistInqVarUnitsPtr
+ end interface
+ f_result => null()
+ ptr = lib_vlistInqVarUnitsPtr(vlistID_dummy, varID_dummy)
+ if(c_associated(ptr)) then
+ rv_shape(1) = int(lib_strlen(ptr))
+ call c_f_pointer(ptr, f_result, rv_shape)
+ end if
+ end function vlistInqVarUnitsPtr
+
function vlistInqAtt(vlistID_dummy, varID_dummy, attrnum_dummy, name_dummy,&
& typep_dummy, lenp_dummy) result(f_result)
integer(c_int) :: f_result
@@ -6227,4 +6402,32 @@ contains
end do
end subroutine streamInqHistoryString
+ function subtypeInqAttribute(subtypeID_dummy, index_dummy, key_dummy,&
+ & outValue_dummy) result(f_result)
+ integer(c_int) :: f_result
+ integer(c_int), value :: subtypeID_dummy
+ integer(c_int), value :: index_dummy
+ character(kind = c_char, len = *), intent(in) :: key_dummy
+ integer(c_int), intent(inout) :: outValue_dummy
+ character(kind = c_char) :: key_temp(len(key_dummy) + 1)
+ integer :: key_i
+ interface
+ function lib_subtypeInqAttribute(subtypeID_dummy, index_dummy, key_dummy,&
+ & outValue_dummy) bind(c, name = 'subtypeInqAttribute') result(c_result)
+ import c_char, c_int
+ integer(c_int) :: c_result
+ integer(c_int), value :: subtypeID_dummy
+ integer(c_int), value :: index_dummy
+ character(kind = c_char) :: key_dummy(*)
+ integer(c_int), intent(inout) :: outValue_dummy
+ end function lib_subtypeInqAttribute
+ end interface
+ do key_i = 1, len(key_dummy)
+ key_temp(key_i) = key_dummy(key_i:key_i)
+ end do
+ key_temp(len(key_dummy) + 1) = c_null_char
+ f_result = lib_subtypeInqAttribute(subtypeID_dummy, index_dummy, key_temp,&
+ & outValue_dummy)
+ end function subtypeInqAttribute
+
end module mo_cdi
diff --git a/libcdi/src/namespace.h b/libcdi/src/namespace.h
index 436a759..3609562 100644
--- a/libcdi/src/namespace.h
+++ b/libcdi/src/namespace.h
@@ -55,7 +55,7 @@ union namespaceSwitchValue
void namespaceCleanup ( void );
int namespaceGetNumber ( void );
//void namespaceSetActive(int namespaceID);
-int namespaceGetActive ( void );
+//int namespaceGetActive ( void );
int namespaceIdxEncode ( namespaceTuple_t );
int namespaceIdxEncode2 ( int, int );
namespaceTuple_t namespaceResHDecode ( int );
diff --git a/libcdi/src/pio_client.c b/libcdi/src/pio_client.c
index a8249d7..100e25d 100644
--- a/libcdi/src/pio_client.c
+++ b/libcdi/src/pio_client.c
@@ -122,6 +122,16 @@ cdiPioClientStreamDefVlist_(int streamID, int vlistID)
cdiPioClientStreamWinCreate(streamID, &cspec);
}
+/* If we're not using GNU C, elide __attribute__ */
+#if ! defined __GNUC__ && ! defined __attribute__
+# define __attribute__(x) /*NOTHING*/
+#endif
+
+static void
+cdiPioClientStreamWriteVar_(int streamID, int varID, int memtype,
+ const void *data, int nmiss)
+ __attribute__((noreturn));
+
static void
cdiPioClientStreamWriteVar_(int streamID, int varID, int memtype,
const void *data, int nmiss)
diff --git a/libcdi/src/pio_mpi_fw_at_reblock.c b/libcdi/src/pio_mpi_fw_at_reblock.c
index 57c1901..961ef34 100644
--- a/libcdi/src/pio_mpi_fw_at_reblock.c
+++ b/libcdi/src/pio_mpi_fw_at_reblock.c
@@ -17,6 +17,7 @@
#include <mpi.h>
#include "cdi.h"
+#include "cdi_int.h"
#include "dmemory.h"
#include "error.h"
#include "namespace.h"
@@ -172,7 +173,7 @@ initAFiledataFileWriteAtReblock(const char *filename, size_t bufSize)
#undef MINBLOCKSIZE
/* ensure block size also meets page and direct I/O buffer
* alignment requirements */
- size_t pageSize = cdiPioGetPageSize(largePageAlign),
+ size_t pageSize = cdiGetPageSize(largePageAlign),
IOAlign = getXferBufAlign(filename);
bufBlockAlign = lcm(pageSize, IOAlign);
blockSize = lcm(blockSize, bufBlockAlign);
diff --git a/libcdi/src/pio_server.c b/libcdi/src/pio_server.c
index e203a74..050a6ec 100644
--- a/libcdi/src/pio_server.c
+++ b/libcdi/src/pio_server.c
@@ -278,32 +278,11 @@ buildVarRedist(int headerIdx, size_t streamIdx,
}
-static void
-gatherArray(int headerIdx, size_t streamIdx,
- double *gatherBuf,
- /* index list representing the data elements gathered on
- * this rank */
- Xt_idxlist dstList,
- const struct cdiPioConf *conf)
-{
- Xt_redist gatherRedist = buildVarRedist(headerIdx, streamIdx,
- dstList, conf);
- xt_redist_s_exchange1(gatherRedist,
- rxWin[streamIdx].clientBuf[0].mem, gatherBuf);
- xt_redist_delete(gatherRedist);
-}
-
struct xyzDims
{
int sizes[3];
};
-static inline int
-xyzGridSize(struct xyzDims dims)
-{
- return dims.sizes[0] * dims.sizes[1] * dims.sizes[2];
-}
-
static Xt_idxlist
buildVarSlicesIdxList(int vlistID, int varID, int startLvl, int numLvl)
{
@@ -336,6 +315,23 @@ countVarChunkMissingVals(int vlistID, int varID,
return nmiss;
}
+#ifdef HAVE_LIBNETCDF
+static void
+gatherArray(int headerIdx, size_t streamIdx,
+ double *gatherBuf,
+ /* index list representing the data elements gathered on
+ * this rank */
+ Xt_idxlist dstList,
+ const struct cdiPioConf *conf)
+{
+ Xt_redist gatherRedist = buildVarRedist(headerIdx, streamIdx,
+ dstList, conf);
+ xt_redist_s_exchange1(gatherRedist,
+ rxWin[streamIdx].clientBuf[0].mem, gatherBuf);
+ xt_redist_delete(gatherRedist);
+}
+#endif
+
#ifdef HAVE_PARALLEL_NC4
static void
queryVarBounds(struct PPM_extent varShape[3], int vlistID, int varID)
@@ -1052,7 +1048,7 @@ writeGribStream(size_t streamIdx,
* (size_t)1024 * (size_t)1024,
sizeof (double) * myAggSize);
if (posix_memalign(&rxWin[streamIdx].aggBuf,
- cdiPioGetPageSize(conf->largePageAlign),
+ cdiGetPageSize(conf->largePageAlign),
aggBufSize) == 0) ;
else
rxWin[streamIdx].aggBuf = Malloc(aggBufSize);
diff --git a/libcdi/src/pio_util.c b/libcdi/src/pio_util.c
index c1dd898..811e321 100644
--- a/libcdi/src/pio_util.c
+++ b/libcdi/src/pio_util.c
@@ -189,56 +189,12 @@ cdiPioQueryVarDims(int varShape[3], int vlistID, int varID)
case GRID_CURVILINEAR:
case GRID_UNSTRUCTURED:
xabort("unimplemented grid type: %d", gridType);
- break;
}
varShape[2] = zaxisInqSize(zaxisID);
/* FIXME: other grids have different dimensionality */
return (varShape[2] == 1)?2:3;
}
-size_t
-cdiPioGetPageSize(bool largePageAlign)
-{
- long pagesize = -1L;
- bool nameAssigned = false;
-#if HAVE_DECL__SC_LARGE_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE || HAVE_DECL__SC_PAGESIZE
- int name;
-#if HAVE_DECL__SC_LARGE_PAGESIZE
- if (largePageAlign)
- {
- name = _SC_LARGE_PAGESIZE;
- nameAssigned = true;
- }
- else
-#endif
- {
-#if HAVE_DECL__SC_PAGESIZE || HAVE_DECL__SC_PAGE_SIZE
- name =
-#if HAVE_DECL__SC_PAGESIZE
- _SC_PAGESIZE
-#elif HAVE_DECL__SC_PAGE_SIZE
- _SC_PAGE_SIZE
-#endif
- ;
- nameAssigned = true;
-#endif
- }
- if (nameAssigned)
- pagesize = sysconf(name);
-#endif
- if (pagesize == -1L)
- pagesize =
-#if HAVE_DECL_PAGESIZE
- PAGESIZE
-#elif HAVE_DECL_PAGE_SIZE
- PAGE_SIZE
-#else
- commonPageSize
-#endif
- ;
- return (size_t)pagesize;
-}
-
void
diff --git a/libcdi/src/pio_util.h b/libcdi/src/pio_util.h
index 20d887a..6be66af 100644
--- a/libcdi/src/pio_util.h
+++ b/libcdi/src/pio_util.h
@@ -94,7 +94,7 @@ void printArray ( const char *, const char *, const void *, int, int, const char
#define xprintArray(ps,array,n,datatype) \
if ( ddebug ) \
printArray ( debugString, ps, array, n, datatype, __func__, __FILE__, __LINE__ )
-
+
#define xprintArray3(ps,array,n,datatype) \
if ( ddebug == MAXDEBUG ) \
printArray ( debugString, ps, array, n, datatype, __func__, __FILE__, __LINE__ )
@@ -105,15 +105,6 @@ void printArray ( const char *, const char *, const void *, int, int, const char
int
cdiPioQueryVarDims(int varShape[3], int vlistID, int varID);
-enum {
- /* 8192 is known to work on most systems (4096 isn't on Alpha) */
- commonPageSize = 8192,
-};
-
-size_t
-cdiPioGetPageSize(bool largePageAlign);
-
-
#endif
/*
* Local Variables:
diff --git a/libcdi/src/stream.c b/libcdi/src/stream.c
index 068fb55..79e5ecc 100644
--- a/libcdi/src/stream.c
+++ b/libcdi/src/stream.c
@@ -7,8 +7,6 @@
#endif
#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
#include "binary.h"
#include "cdi.h"
@@ -25,15 +23,10 @@
#include "file.h"
#include "cgribex.h"
#include "gribapi.h"
-#include "cdf.h"
-#include "service.h"
-#include "extra.h"
-#include "ieg.h"
#include "vlist.h"
#include "serialize.h"
#include "resource_handle.h"
#include "resource_unpack.h"
-
#include "namespace.h"
@@ -151,6 +144,7 @@ int cdiGetFiletype(const char *filename, int *byteorder)
if ( CDI_Debug ) Message("found IEG file = %s", filename);
}
#endif
+#if defined (HAVE_LIBCGRIBEX)
else if ( gribCheckSeek(fileID, &recpos, &version) == 0 )
{
if ( version <= 1 )
@@ -164,6 +158,7 @@ int cdiGetFiletype(const char *filename, int *byteorder)
if ( CDI_Debug ) Message("found seeked GRIB2 file = %s", filename);
}
}
+#endif
fileClose(fileID);
@@ -194,9 +189,6 @@ The valid CDI file format types are @func{FILETYPE_GRB}, @func{FILETYPE_GRB2}, @
int streamInqFiletype(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->filetype);
}
@@ -240,9 +232,6 @@ with the file format type @func{FILETYPE_SRV}, @func{FILETYPE_EXT} or @func{FILE
void streamDefByteorder(int streamID, int byteorder)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
streamptr->byteorder = byteorder;
int filetype = streamptr->filetype;
@@ -300,9 +289,6 @@ The valid CDI byte order types are @func{CDI_BIGENDIAN} and @func{CDI_LITTLEENDI
int streamInqByteorder(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->byteorder);
}
@@ -326,9 +312,6 @@ const char *streamFilesuffix(int filetype)
const char *streamFilename(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->filename);
}
@@ -337,9 +320,6 @@ long cdiInqTimeSize(int streamID)
{
int tsID = 0, nrecs;
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
long ntsteps = streamptr->ntsteps;
if ( ntsteps == (long)CDI_UNDEFID )
@@ -433,7 +413,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
case FILETYPE_GRB:
case FILETYPE_GRB2:
{
+#ifndef __cplusplus
fileID = gribOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = gribOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -446,7 +431,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBSERVICE)
case FILETYPE_SRV:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -460,7 +450,13 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBEXTRA)
case FILETYPE_EXT:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
+
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -474,7 +470,12 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBIEG)
case FILETYPE_IEG:
{
+#ifndef __cplusplus
fileID = fileOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = fileOpen(filename, temp);
+#endif
if ( fileID < 0 ) fileID = CDI_ESYSTEM;
if (recordBufIsToBeCreated)
{
@@ -488,18 +489,33 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
#if defined (HAVE_LIBNETCDF)
case FILETYPE_NC:
{
+#ifndef __cplusplus
fileID = cdfOpen(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdfOpen(filename, temp);
+#endif
break;
}
case FILETYPE_NC2:
{
+#ifndef __cplusplus
fileID = cdfOpen64(filename, (char [2]){filemode, 0});
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdfOpen64(filename, temp);
+#endif
break;
}
case FILETYPE_NC4:
case FILETYPE_NC4C:
{
+#ifndef __cplusplus
fileID = cdf4Open(filename, (char [2]){filemode, 0}, &filetype);
+#else
+ char temp[2] = { filemode, 0 };
+ fileID = cdf4Open(filename, temp, &filetype);
+#endif
break;
}
#endif
@@ -516,9 +532,7 @@ int cdiStreamOpenDefaultDelegate(const char *filename, char filemode,
}
-int
-streamOpenID(const char *filename, char filemode, int filetype,
- int resH)
+int streamOpenID(const char *filename, char filemode, int filetype, int resH)
{
int fileID = CDI_UNDEFID;
int status;
@@ -541,37 +555,49 @@ streamOpenID(const char *filename, char filemode, int filetype,
fileID = streamOpenDelegate(filename, filemode, filetype, streamptr, 1);
}
- if (fileID < 0)
+ if ( fileID < 0 )
{
- Free(streamptr->record);
- stream_delete_entry(streamptr);
streamID = fileID;
}
else
{
- streamID = streamptr->self;
+ streamID = streamptr->self;
- if ( streamID < 0 ) return (CDI_ELIMIT);
+ if ( streamID < 0 ) return CDI_ELIMIT;
streamptr->filemode = filemode;
streamptr->filename = strdupx(filename);
streamptr->fileID = fileID;
if ( filemode == 'r' )
- {
- int vlistID = vlistCreate();
- if ( vlistID < 0 ) return(CDI_ELIMIT);
-
- streamptr->vlistID = vlistID;
- /* cdiReadByteorder(streamID); */
- status = cdiInqContents(streamptr);
- if ( status < 0 ) return (status);
- vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
- vlistptr->ntsteps = streamptr->ntsteps;
- }
+ {
+ int vlistID = vlistCreate();
+ if ( vlistID < 0 ) return(CDI_ELIMIT);
+
+ cdiVlistMakeInternal(vlistID);
+ streamptr->vlistID = vlistID;
+ /* cdiReadByteorder(streamID); */
+ status = cdiInqContents(streamptr);
+ if ( status < 0 )
+ {
+ streamID = status;
+ }
+ else
+ {
+ vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
+ vlistptr->ntsteps = streamptr->ntsteps;
+ cdiVlistMakeImmutable(vlistID);
+ }
+ }
}
- return (streamID);
+ if ( streamID < 0 )
+ {
+ Free(streamptr->record);
+ stream_delete_entry(streamptr);
+ }
+
+ return streamID;
}
static int streamOpen(const char *filename, const char *filemode, int filetype)
@@ -613,11 +639,13 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype)
streamptr->fileID = fileID;
streamptr->vlistID = vlistCreate();
+ cdiVlistMakeInternal(streamptr->vlistID);
/* cdiReadByteorder(streamID); */
status = cdiInqContents(streamptr);
if ( status < 0 ) return (status);
vlistptr = vlist_to_pointer(streamptr->vlistID);
vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
+ if(!strcmp(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID);
{
void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
@@ -718,7 +746,7 @@ open stream. Otherwise, a negative number with the error status is returned.
@EndList
@Example
-Here is an example using @func{streamOpenRead} to open an existing netCDF
+Here is an example using @func{streamOpenRead} to open an existing NetCDF
file named @func{foo.nc} for reading:
@Source
@@ -800,7 +828,7 @@ open stream. Otherwise, a negative number with the error status is returned.
@EndList
@Example
-Here is an example using @func{streamOpenWrite} to create a new netCDF file named @func{foo.nc} for writing:
+Here is an example using @func{streamOpenWrite} to create a new NetCDF file named @func{foo.nc} for writing:
@Source
#include "cdi.h"
@@ -986,8 +1014,6 @@ void streamClose(int streamID)
int index;
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
if ( CDI_Debug )
Message("streamID = %d filename = %s", streamID, streamptr->filename);
@@ -1045,8 +1071,7 @@ void streamClose(int streamID)
taxisDestroy(vlistInqTaxis(vlistID));
}
- vlist_unlock(vlistID);
- vlistDestroy(vlistID);
+ cdiVlistDestroy_(vlistID);
}
stream_delete_entry(streamptr);
@@ -1124,8 +1149,6 @@ void streamSync(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
void (*myStreamSync_)(stream_t *streamptr)
= (void (*)(stream_t *))namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func;
myStreamSync_(streamptr);
@@ -1136,11 +1159,11 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
{
int taxisID = 0;
+ stream_check_ptr(__func__, streamptr);
+
if ( CDI_Debug )
Message("streamID = %d tsID = %d", streamptr->self, tsID);
- stream_check_ptr(__func__, streamptr);
-
int vlistID = streamptr->vlistID;
int time_is_varying = vlistHasTime(vlistID);
@@ -1177,7 +1200,7 @@ int cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
streamptr->filetype == FILETYPE_NC2 ||
streamptr->filetype == FILETYPE_NC4 ||
streamptr->filetype == FILETYPE_NC4C)
- && vlistHasTime(vlistID))
+ && time_is_varying)
{
void (*myCdfDefTimestep)(stream_t *streamptr, int tsID)
= (void (*)(stream_t *, int))
@@ -1246,9 +1269,6 @@ int streamInqTimestep(int streamID, int tsID)
int nrecs = 0;
int taxisID;
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
int vlistID = streamptr->vlistID;
if ( tsID < streamptr->rtsteps )
@@ -1331,570 +1351,11 @@ int streamInqTimestep(int streamID, int tsID)
return (nrecs);
}
-/* the single image implementation */
-static
-void cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
- check_parg(nmiss);
-
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- int filetype = streamptr->filetype;
-
- *nmiss = 0;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("grbReadVar not implemented for memtype float!");
- grbReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvReadVar not implemented for memtype float!");
- srvReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extReadVar not implemented for memtype float!");
- extReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegReadVar not implemented for memtype float!");
- iegReadVarDP(streamptr, varID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( memtype == MEMTYPE_FLOAT )
- cdfReadVarSP(streamptr, varID, (float *)data, nmiss);
- else
- cdfReadVarDP(streamptr, varID, (double *)data, nmiss);
-
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
- }
-}
-
-/*
- at Function streamReadVar
- at Title Read a variable
-
- at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVar(int streamID, int varID, double *data, int *nmiss)
-{
- cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
-}
-
-/*
- at Function streamReadVarF
- at Title Read a variable
-
- at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVar reads all the values of one time step of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
-{
- cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
-}
-
-/* the single image implementation */
-void cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
- Error("Writing of non-trivial subtypes not yet implemented!");
-
- stream_check_ptr(__func__, streamptr);
-
- // check taxis
- if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- grb_write_var(streamptr, varID, memtype, data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteVar not implemented for memtype float!");
- srvWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteVar not implemented for memtype float!");
- extWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteVar not implemented for memtype float!");
- iegWriteVarDP(streamptr, varID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var(streamptr, varID, memtype, (double *)data, nmiss);
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
- }
-}
-
-/*
- at Function streamWriteVar
- at Title Write a variable
-
- at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVar writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
-{
- void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
- const void *data, int nmiss)
- = (void (*)(int, int, int, const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
- myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
-}
-
-/*
- at Function streamWriteVarF
- at Title Write a variable
-
- at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item data Pointer to a block of single precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
- at EndFunction
-*/
-void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
-{
- void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
- const void *data, int nmiss)
- = (void (*)(int, int, int, const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
- myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, data, nmiss);
-}
-
-static
-int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
-{
- // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
- // A value > 0 is returned in this case, otherwise it returns zero.
- int status = 0;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
- check_parg(nmiss);
-
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- int filetype = streamptr->filetype;
-
- *nmiss = 0;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- grbReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- srvReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- extReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) return 1;
- iegReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- if ( memtype == MEMTYPE_FLOAT )
- cdfReadVarSliceSP(streamptr, varID, levelID, (float *)data, nmiss);
- else
- cdfReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- status = 2;
- break;
- }
- }
-
- return status;
-}
-
-/*
- at Function streamReadVarSlice
- at Title Read a horizontal slice of a variable
-
- at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVarSlice reads all the values of a horizontal slice of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
-{
- if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
- {
- Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
- size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
- memset(data, 0, elementCount * sizeof(*data));
- }
-}
-
-/*
- at Function streamReadVarSliceF
- at Title Read a horizontal slice of a variable
-
- at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to the location into which the data values are read.
- The caller must allocate space for the returned values.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
-from an open dataset.
- at EndFunction
-*/
-void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
-{
- if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss) )
- {
- // In case the file format does not support single precision reading,
- // we fall back to double precision reading, converting the data on the fly.
- size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
- double *conversionBuffer = (double *) Malloc(elementCount * sizeof(*conversionBuffer));
- streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
- for (size_t i = elementCount; i--; ) data[i] = (float)conversionBuffer[i];
- Free(conversionBuffer);
- }
-}
-
-static
-void cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- check_parg(data);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
- Error("Writing of non-trivial subtypes not yet implemented!");
-
- stream_check_ptr(__func__, streamptr);
-
- // check taxis
- if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- {
- grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
- break;
- }
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteVarSlice not implemented for memtype float!");
- srvWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteVarSlice not implemented for memtype float!");
- extWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteVarSlice not implemented for memtype float!");
- iegWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
- break;
- }
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
- break;
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
- }
-}
-
-/*
- at Function streamWriteVarSlice
- at Title Write a horizontal slice of a variable
-
- at Prototype void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVarSlice writes the values of a horizontal slice of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
-{
- cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss);
-}
-
-/*
- at Function streamWriteVarSliceF
- at Title Write a horizontal slice of a variable
-
- at Prototype void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item varID Variable identifier.
- @Item levelID Level identifier.
- @Item data Pointer to a block of single precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteVarSliceF writes the values of a horizontal slice of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
-Only support for netCDF was implemented in this function.
- at EndFunction
-*/
-void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
-{
- cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss);
-}
-
-
-void
-streamWriteVarChunk(int streamID, int varID,
- const int rect[][2], const double *data, int nmiss)
-{
- void (*myCdiStreamWriteVarChunk_)(int streamID, int varID, int memtype,
- const int rect[][2], const void *data,
- int nmiss)
- = (void (*)(int, int, int, const int [][2], const void *, int))
- namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_CHUNK_).func;
- myCdiStreamWriteVarChunk_(streamID, varID, MEMTYPE_DOUBLE, rect, data, nmiss);
-}
-
-/* single image implementation */
-void
-cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
- const int rect[][2], const void *data, int nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
-
- stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
- // streamDefineTaxis(streamID);
-
- int filetype = streamptr->filetype;
-
- switch (filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
-#endif
-#if defined (HAVE_LIBGRIB) || defined (HAVE_LIBSERVICE) \
- || defined (HAVE_LIBEXTRA) || defined (HAVE_LIBIEG)
- xabort("streamWriteVarChunk not implemented for filetype %s!",
- strfiletype(filetype));
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- if ( streamptr->accessmode == 0 ) cdfEndDef(streamptr);
- cdf_write_var_chunk(streamptr, varID, memtype, rect, data, nmiss);
- break;
-#endif
- default:
- Error("%s support not compiled in!", strfiletype(filetype));
- break;
- }
-}
-
#if 0
void streamWriteContents(int streamID, char *cname)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
int vlistID = streamptr->vlistID;
FILE *cnp = fopen(cname, "w");
@@ -1991,8 +1452,6 @@ off_t streamNvals(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->numvals);
}
@@ -2008,6 +1467,10 @@ off_t streamNvals(int streamID)
@Description
The function @func{streamDefVlist} defines the variable list of a stream.
+To safeguard against errors by modifying the wrong vlist object,
+this function makes the passed vlist object immutable.
+All further vlist changes have to use the vlist object returned by streamInqVlist().
+
@EndFunction
*/
void streamDefVlist(int streamID, int vlistID)
@@ -2023,10 +1486,13 @@ cdiStreamDefVlist_(int streamID, int vlistID)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
if ( streamptr->vlistID == CDI_UNDEFID )
- cdiStreamSetupVlist(streamptr, vlistDuplicate(vlistID));
+ {
+ int vlistCopy = vlistDuplicate(vlistID);
+ cdiVlistMakeInternal(vlistCopy);
+ cdiVlistMakeImmutable(vlistID);
+ cdiStreamSetupVlist(streamptr, vlistCopy);
+ }
else
Warning("vlist already defined for %s!", streamptr->filename);
}
@@ -2050,9 +1516,6 @@ The function @func{streamInqVlist} returns the variable list of a stream.
int streamInqVlist(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->vlistID);
}
@@ -2060,9 +1523,6 @@ int streamInqVlist(int streamID)
void streamDefCompType(int streamID, int comptype)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
if (streamptr->comptype != comptype)
{
streamptr->comptype = comptype;
@@ -2074,9 +1534,6 @@ void streamDefCompType(int streamID, int comptype)
void streamDefCompLevel(int streamID, int complevel)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
if (streamptr->complevel != complevel)
{
streamptr->complevel = complevel;
@@ -2088,9 +1545,6 @@ void streamDefCompLevel(int streamID, int complevel)
int streamInqCompType(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->comptype);
}
@@ -2098,9 +1552,6 @@ int streamInqCompType(int streamID)
int streamInqCompLevel(int streamID)
{
stream_t *streamptr = stream_to_pointer(streamID);
-
- stream_check_ptr(__func__, streamptr);
-
return (streamptr->complevel);
}
@@ -2153,7 +1604,6 @@ cdiStreamSetupVlist(stream_t *streamptr, int vlistID)
void
cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
{
- vlist_lock(vlistID);
int nvars = vlistNvars(vlistID);
streamptr->vlistID = vlistID;
for (int varID = 0; varID < nvars; varID++ )
@@ -2183,10 +1633,14 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
}
break;
#endif
+#ifdef HAVE_LIBGRIB
case FILETYPE_GRB:
case FILETYPE_GRB2:
gribContainersNew(streamptr);
break;
+#endif
+ default:
+ ;
}
}
@@ -2368,8 +1822,6 @@ streamUnpack(char * unpackBuffer, int unpackBufferSize,
return retval;
}
-
-
/*
* Local Variables:
* c-file-style: "Java"
diff --git a/libcdi/src/stream_cdf.c b/libcdi/src/stream_cdf.c
index a832b97..290dd84 100644
--- a/libcdi/src/stream_cdf.c
+++ b/libcdi/src/stream_cdf.c
@@ -7,11 +7,19 @@
//#define TEST_GROUPS 1
#include <limits.h>
-#include <stdio.h>
-#include <string.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
+#ifdef HAVE_MMAP
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+#endif
#include <netcdf.h>
@@ -20,6 +28,7 @@
#include "basetime.h"
#include "gaussgrid.h"
#include "cdi_int.h"
+#include "cdi_uuid.h"
#include "stream_cdf.h"
#include "cdf.h"
#include "cdf_int.h"
@@ -27,17 +36,10 @@
#include "vlist.h"
//#define PROJECTION_TEST
-extern int CDI_cmor_mode;
#undef UNDEFID
#define UNDEFID CDI_UNDEFID
-
-#if defined HAVE_LIBNETCDF
-static void cdfDefGlobalAtts(stream_t *streamptr);
-static void cdfDefLocalAtts(stream_t *streamptr);
-#endif
-
#define BNDS_NAME "bnds"
#define X_AXIS 1
@@ -55,7 +57,6 @@ typedef struct {
char name[CDI_MAX_NAME];
}
ncdim_t;
-
#define MAX_COORDVARS 4
#define MAX_AUXVARS 4
@@ -157,30 +158,30 @@ int get_timeunit(size_t len, const char *ptu)
if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
}
- return (timeunit);
+ return timeunit;
}
static
-int isTimeUnits(const char *timeunits)
+bool isTimeUnits(const char *timeunits)
{
- int status = 0;
+ bool status = false;
if ( strncmp(timeunits, "sec", 3) == 0 ||
strncmp(timeunits, "minute", 6) == 0 ||
strncmp(timeunits, "hour", 4) == 0 ||
strncmp(timeunits, "day", 3) == 0 ||
- strncmp(timeunits, "month", 5) == 0 ) status = 1;
+ strncmp(timeunits, "month", 5) == 0 ) status = true;
- return (status);
+ return status;
}
static
-int isTimeAxisUnits(const char *timeunits)
+bool isTimeAxisUnits(const char *timeunits)
{
char *ptu, *tu;
int timetype = -1;
int timeunit;
- int status = FALSE;
+ bool status = false;
size_t len = strlen(timeunits);
tu = (char *) Malloc((len+1)*sizeof(char));
@@ -203,13 +204,13 @@ int isTimeAxisUnits(const char *timeunits)
else if ( memcmp(ptu, "since", 5) == 0 )
timetype = TAXIS_RELATIVE;
- if ( timetype != -1 ) status = TRUE;
+ if ( timetype != -1 ) status = true;
}
}
Free(tu);
- return (status);
+ return status;
}
static
@@ -272,24 +273,21 @@ void scanTimeString(const char *ptu, int *rdate, int *rtime)
static
int scanTimeUnit(const char *unitstr)
{
- int timeunit = -1;
size_t len = strlen(unitstr);
- timeunit = get_timeunit(len, unitstr);
+ int timeunit = get_timeunit(len, unitstr);
if ( timeunit == -1 )
Message("Unsupported TIMEUNIT: %s!", unitstr);
- return (timeunit);
+ return timeunit;
}
static
void setForecastTime(const char *timestr, taxis_t *taxis)
{
- int len;
-
(*taxis).fdate = 0;
(*taxis).ftime = 0;
- len = (int) strlen(timestr);
+ int len = (int) strlen(timestr);
if ( len == 0 ) return;
int fdate = 0, ftime = 0;
@@ -302,19 +300,17 @@ void setForecastTime(const char *timestr, taxis_t *taxis)
static
int setBaseTime(const char *timeunits, taxis_t *taxis)
{
- char *ptu, *tu;
int timetype = TAXIS_ABSOLUTE;
int rdate = -1, rtime = -1;
- int timeunit;
size_t len = strlen(timeunits);
- tu = (char *) Malloc((len+1) * sizeof (char));
+ char *tu = (char *) Malloc((len+1) * sizeof (char));
memcpy(tu, timeunits, (len+1) * sizeof (char));
- ptu = tu;
+ char *ptu = tu;
for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
- timeunit = get_timeunit(len, ptu);
+ int timeunit = get_timeunit(len, ptu);
if ( timeunit == -1 )
{
Message("Unsupported TIMEUNIT: %s!", timeunits);
@@ -370,7 +366,7 @@ int setBaseTime(const char *timeunits, taxis_t *taxis)
if ( CDI_Debug )
Message("timetype = %d unit = %d", timetype, timeunit);
- return (0);
+ return 0;
}
static
@@ -531,111 +527,7 @@ int cdfInqDatatype(int xtype, int lunsigned)
else if ( xtype == NC_UINT64 ) datatype = DATATYPE_FLT64;
#endif
- return (datatype);
-}
-
-static
-int cdfDefDatatype(int datatype, int filetype)
-{
- int xtype;
-
- if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
- Error("CDI/netCDF library does not support complex numbers!");
-
- if ( filetype == FILETYPE_NC4 )
- {
- if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
- else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
-#if defined (HAVE_NETCDF4)
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_UBYTE;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
-#else
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
-#endif
- else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
- else xtype = NC_FLOAT;
- }
- else
- {
- if ( datatype == DATATYPE_INT8 ) xtype = NC_BYTE;
- else if ( datatype == DATATYPE_INT16 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_INT32 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT8 ) xtype = NC_SHORT;
- else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
- else if ( datatype == DATATYPE_FLT64 ) xtype = NC_DOUBLE;
- else xtype = NC_FLOAT;
- }
-
- return (xtype);
-}
-
-static inline void *
-resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
-{
- if (reqSize > *bufSize)
- {
- *buf = Realloc(*buf, reqSize);
- *bufSize = reqSize;
- }
- return *buf;
-}
-
-static
-void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
-{
- int natts, iatt;
- int atttype, attlen;
- size_t len;
- char attname[CDI_MAX_NAME+1];
- void *attBuf = NULL;
- size_t attBufSize = 0;
-
- vlistInqNatts(vlistID, varID, &natts);
-
- for ( iatt = 0; iatt < natts; iatt++ )
- {
- vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
-
- if ( attlen == 0 ) continue;
-
- if ( atttype == DATATYPE_TXT )
- {
- size_t attSize = (size_t)attlen*sizeof(char);
- char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
- len = (size_t)attlen;
- cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
- }
- else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
- {
- size_t attSize = (size_t)attlen*sizeof(int);
- int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
- len = (size_t)attlen;
- cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
- }
- else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
- {
- size_t attSize = (size_t)attlen * sizeof(double);
- double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
- vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
- len = (size_t)attlen;
- if ( atttype == DATATYPE_FLT32 )
- {
- float attflt_sp[len];
- for ( size_t i = 0; i < len; ++i ) attflt_sp[i] = (float)attflt[i];
- cdf_put_att_float(fileID, ncvarID, attname, NC_FLOAT, len, attflt_sp);
- }
- else
- cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
- }
- }
- Free(attBuf);
+ return datatype;
}
@@ -649,11 +541,18 @@ void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
int ivarID = streamptr1->tsteps[tsID].records[recID].varID;
int gridID = vlistInqVarGrid(vlistID1, ivarID);
int datasize = gridInqSize(gridID);
+ int datatype = vlistInqVarDatatype(vlistID1, ivarID);
- double *data = (double *) Malloc((size_t)datasize * sizeof (double));
+ if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;
+
+ void *data = NULL;
+ if ( memtype == MEMTYPE_DOUBLE )
+ data = Malloc((size_t)datasize*sizeof(double));
+ else
+ data = Malloc((size_t)datasize*sizeof(float));
int nmiss;
- cdfReadRecord(streamptr1, data, &nmiss);
+ cdf_read_record(streamptr1, memtype, data, &nmiss);
cdf_write_record(streamptr2, memtype, data, nmiss);
Free(data);
@@ -692,75 +591,6 @@ void cdfDefRecord(stream_t *streamptr)
(void)streamptr;
}
-
-static
-void cdfWriteGridTraj(stream_t *streamptr, int gridID)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- int gridindex = vlistGridIndex(vlistID, gridID);
- int lonID = streamptr->xdimID[gridindex],
- latID = streamptr->ydimID[gridindex];
-
- double xlon = gridInqXval(gridID, 0),
- xlat = gridInqYval(gridID, 0);
- int tsID = streamptr->curTsID;
- size_t index = (size_t)tsID;
-
- cdf_put_var1_double(fileID, lonID, &index, &xlon);
- cdf_put_var1_double(fileID, latID, &index, &xlat);
-}
-
-static
-void cdfReadGridTraj(stream_t *streamptr, int gridID)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- int gridindex = vlistGridIndex(vlistID, gridID);
- int lonID = streamptr->xdimID[gridindex];
- int latID = streamptr->ydimID[gridindex];
-
- int tsID = streamptr->curTsID;
- size_t index = (size_t)tsID;
-
- double xlon, xlat;
- cdf_get_var1_double(fileID, lonID, &index, &xlon);
- cdf_get_var1_double(fileID, latID, &index, &xlat);
-
- gridDefXvals(gridID, &xlon);
- gridDefYvals(gridID, &xlat);
-}
-
-
-static
-void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
-{
-#if defined (HAVE_NETCDF4)
- int retval;
- /* Set chunking, shuffle, and deflate. */
- int shuffle = 1;
- int deflate = 1;
-
- if ( deflate_level < 1 || deflate_level > 9 ) deflate_level = 1;
-
- if ((retval = nc_def_var_deflate(ncid, ncvarid, shuffle, deflate, deflate_level)))
- {
- Error("nc_def_var_deflate failed, status = %d", retval);
- }
-#else
- static int lwarn = TRUE;
-
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("Deflate compression failed, netCDF4 not available!");
- }
-#endif
-}
-
-
#if defined(NC_SZIP_NN_OPTION_MASK)
static
void cdfDefVarSzip(int ncid, int ncvarid)
@@ -779,7 +609,7 @@ void cdfDefVarSzip(int ncid, int ncvarid)
if ( lwarn )
{
lwarn = FALSE;
- Warning("netCDF4/Szip compression not compiled in!");
+ Warning("NetCDF4/Szip compression not compiled in!");
}
}
else
@@ -789,64 +619,6 @@ void cdfDefVarSzip(int ncid, int ncvarid)
#endif
static
-void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
-{
- if ( streamptr->vars[varID].defmiss == FALSE )
- {
- int fileID;
- int ncvarid;
- double missval;
- int vlistID;
- int xtype;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- ncvarid = streamptr->vars[varID].ncvarid;
- missval = vlistInqVarMissval(vlistID, varID);
-
- if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- xtype = cdfDefDatatype(dtype, streamptr->filetype);
-
- if ( xtype == NC_BYTE && missval > 127 && missval < 256 ) xtype = NC_INT;
-
- cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
- cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
-
- if ( lcheck && streamptr->ncmode == 2 ) cdf_enddef(fileID);
-
- streamptr->vars[varID].defmiss = TRUE;
- }
-}
-
-
-void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
-{
- int varID;
- int levelID;
-
- varID = streamptr->record->varID;
- levelID = streamptr->record->levelID;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
-}
-
-void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
-
- int tsID = streamptr->curTsID;
- int vrecID = streamptr->tsteps[tsID].curRecID;
- int recID = streamptr->tsteps[tsID].recIDs[vrecID];
- int varID = streamptr->tsteps[tsID].records[recID].varID;
- int levelID = streamptr->tsteps[tsID].records[recID].levelID;
-
- cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
-}
-
-static
void cdfDefTimeValue(stream_t *streamptr, int tsID)
{
int fileID = streamptr->fileID;
@@ -1009,7 +781,7 @@ void cdfDefCalendar(int fileID, int ncvarid, int calendar)
if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
}
-static
+
void cdfDefTime(stream_t* streamptr)
{
int time_varid;
@@ -1111,7 +883,6 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
{
char axisname[] = "nc2";
int dimID = UNDEFID;
- int gridID0, gridtype0;
int vlistID = streamptr->vlistID;
int fileID = streamptr->fileID;
@@ -1121,8 +892,8 @@ void cdfDefComplex(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
{
dimID = streamptr->xdimID[index];
@@ -1156,16 +927,12 @@ void cdfDefSP(stream_t *streamptr, int gridID)
*/
char axisname[5] = "nspX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID)/2;
@@ -1173,8 +940,8 @@ void cdfDefSP(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_SPECTRAL )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
@@ -1202,7 +969,7 @@ void cdfDefSP(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->ydimID[gridindex] = dimID;
}
@@ -1212,16 +979,12 @@ void cdfDefFC(stream_t *streamptr, int gridID)
{
char axisname[5] = "nfcX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID)/2;
@@ -1229,8 +992,8 @@ void cdfDefFC(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_FOURIER )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
@@ -1258,142 +1021,117 @@ void cdfDefFC(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->ydimID[gridindex] = dimID;
}
+struct cdfDefTrajLatLonInqs {
+ int (*gridInqDimSize)(int gridID);
+ void (*gridInqDimName)(int gridID, char *dimname);
+ void (*gridInqDimStdname)(int gridID, char *dimstdname);
+ void (*gridInqDimLongname)(int gridID, char *dimlongname);
+ void (*gridInqDimUnits)(int gridID, char *dimunits);
+};
-static
-void cdfDefTrajLon(stream_t *streamptr, int gridID)
-{
- char units[CDI_MAX_NAME];
- char longname[CDI_MAX_NAME];
- char stdname[CDI_MAX_NAME];
- char axisname[CDI_MAX_NAME];
- int gridtype, gridindex;
- int dimID = UNDEFID;
- int fileID;
- int dimlen;
- size_t len;
- int ncvarid;
- int vlistID;
- int xtype = NC_DOUBLE;
-
- if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- gridtype = gridInqType(gridID);
- dimlen = gridInqXsize(gridID);
- if ( dimlen != 1 ) Error("Xsize isn't 1 for %s grid!", gridNamePtr(gridtype));
+static void
+cdfDefTrajLatLon(stream_t *streamptr, int gridID,
+ const struct cdfDefTrajLatLonInqs *inqs,
+ int *dimID, const char *sizeName)
+{
+ nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE;
- gridindex = vlistGridIndex(vlistID, gridID);
- ncvarid = streamptr->xdimID[gridindex];
+ int vlistID = streamptr->vlistID;
+ int dimlen = inqs->gridInqDimSize(gridID);
+ if ( dimlen != 1 )
+ Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID)));
- gridInqXname(gridID, axisname);
- gridInqXlongname(gridID, longname);
- gridInqXstdname(gridID, stdname);
- gridInqXunits(gridID, units);
+ int gridindex = vlistGridIndex(vlistID, gridID);
+ int ncvarid = dimID[gridindex];
if ( ncvarid == UNDEFID )
{
- dimID = streamptr->basetime.ncvarid;
-
+ size_t len;
+ int dimNcID = streamptr->basetime.ncvarid;
+ int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
-
- if ( (len = strlen(stdname)) )
- cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
- if ( (len = strlen(longname)) )
- cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
- if ( (len = strlen(units)) )
- cdf_put_att_text(fileID, ncvarid, "units", len, units);
-
+ {
+ char axisname[CDI_MAX_NAME];
+ inqs->gridInqDimName(gridID, axisname);
+ cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid);
+ }
+ {
+ char stdname[CDI_MAX_NAME];
+ inqs->gridInqDimStdname(gridID, stdname);
+ if ( (len = strlen(stdname)) )
+ cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
+ }
+ {
+ char longname[CDI_MAX_NAME];
+ inqs->gridInqDimLongname(gridID, longname);
+ if ( (len = strlen(longname)) )
+ cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
+ }
+ {
+ char units[CDI_MAX_NAME];
+ inqs->gridInqDimUnits(gridID, units);
+ if ( (len = strlen(units)) )
+ cdf_put_att_text(fileID, ncvarid, "units", len, units);
+ }
cdf_enddef(fileID);
streamptr->ncmode = 2;
}
- streamptr->xdimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
+ dimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
}
-
static
-void cdfDefTrajLat(stream_t *streamptr, int gridID)
+void cdfDefTrajLon(stream_t *streamptr, int gridID)
{
- char units[] = "degrees_north";
- char longname[] = "latitude";
- char stdname[] = "latitude";
- char axisname[] = "tlat";
- int gridtype, gridindex;
- int dimID = UNDEFID;
- int fileID;
- int dimlen;
- size_t len;
- int ncvarid;
- int vlistID;
- int xtype = NC_DOUBLE;
-
- if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
-
- gridtype = gridInqType(gridID);
- dimlen = gridInqYsize(gridID);
- if ( dimlen != 1 ) Error("Ysize isn't 1 for %s grid!", gridNamePtr(gridtype));
-
- gridindex = vlistGridIndex(vlistID, gridID);
- ncvarid = streamptr->ydimID[gridindex];
-
- gridInqYname(gridID, axisname);
- gridInqYlongname(gridID, longname);
- gridInqYstdname(gridID, stdname);
- gridInqYunits(gridID, units);
-
- if ( ncvarid == UNDEFID )
- {
- dimID = streamptr->basetime.ncvarid;
-
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
-
- if ( (len = strlen(stdname)) )
- cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
- if ( (len = strlen(longname)) )
- cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
- if ( (len = strlen(units)) )
- cdf_put_att_text(fileID, ncvarid, "units", len, units);
+ static const struct cdfDefTrajLatLonInqs inqs =
+ { .gridInqDimSize = gridInqXsize,
+ .gridInqDimName = gridInqXname,
+ .gridInqDimStdname = gridInqXstdname,
+ .gridInqDimLongname = gridInqXlongname,
+ .gridInqDimUnits = gridInqXunits
+ };
+ cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->xdimID, "Xsize");
+}
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
- }
- streamptr->ydimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
+static
+void cdfDefTrajLat(stream_t *streamptr, int gridID)
+{
+ static const struct cdfDefTrajLatLonInqs inqs =
+ { .gridInqDimSize = gridInqYsize,
+ .gridInqDimName = gridInqYname,
+ .gridInqDimStdname = gridInqYstdname,
+ .gridInqDimLongname = gridInqYlongname,
+ gridInqYunits
+ };
+ cdfDefTrajLatLon(streamptr, gridID, &inqs, streamptr->ydimID, "Ysize");
}
static
int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode)
{
- int iz, index;
+ int index;
int gridID0;
int ncdimid;
char axisname0[CDI_MAX_NAME];
char axisname2[CDI_MAX_NAME];
- int checkname;
int status;
/* check that the name is not already defined */
- checkname = TRUE;
- iz = 0;
+ int checkname = TRUE;
+ unsigned iz = 0;
do
{
strcpy(axisname2, axisname);
- if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%d", iz+1);
+ if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%u", iz+1);
//status = nc_inq_varid(fileID, axisname2, &ncvarid);
if ( type == 'V' ) /* type Var oder Dim */
@@ -1432,12 +1170,11 @@ int checkGridName(int type, char *axisname, int fileID, int vlistID, int gridID,
while (checkname && iz <= 99);
- if ( iz ) sprintf(&axisname[strlen(axisname)], "_%d", iz+1);
+ if ( iz ) sprintf(&axisname[strlen(axisname)], "_%u", iz+1);
- return (iz);
+ return (int)iz;
}
-
static
void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
{
@@ -1447,40 +1184,37 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
char axisname[CDI_MAX_NAME];
int index;
/* int index2; */
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
int dimIDs[2];
int ngrids = 0;
- int fileID;
size_t len;
int ncvarid = UNDEFID, ncbvarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
if ( ndims ) ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqXsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, axisname);
+ if ( axisname[0] == 0 ) Error("axis name undefined!");
+
gridInqXlongname(gridID, longname);
gridInqXstdname(gridID, stdname);
gridInqXunits(gridID, units);
- if ( axisname[0] == 0 ) Error("axis name undefined!");
-
for ( index = 0; index < ngrids; index++ )
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -1506,28 +1240,21 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
if ( dimID == UNDEFID )
{
- int status;
- status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
+ int status = checkGridName('V', axisname, fileID, vlistID, gridID, ngrids, 'X');
if ( status == 0 && ndims )
status = checkGridName('D', axisname, fileID, vlistID, gridID, ngrids, 'X');
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- if ( ndims )
- {
- cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
- if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
- {
- size_t nvertex = 2;
- if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
- cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
- }
- }
+ if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
- if ( gridInqXvalsPtr(gridID) )
+ int gen_bounds = FALSE;
+ int grid_is_cyclic = gridIsCircular(gridID);
+ const double *pvals = gridInqXvalsPtr(gridID);
+ double *pbounds = NULL;
+ if ( pvals )
{
- cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
+ cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
if ( (len = strlen(stdname)) )
cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
@@ -1538,13 +1265,34 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
cdf_put_att_text(fileID, ncvarid, "axis", 1, "X");
- if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID )
+ if ( gridInqXboundsPtr(gridID) )
+ pbounds = (double*) gridInqXboundsPtr(gridID);
+
+ if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+ {
+ gen_bounds = TRUE;
+ pbounds = (double*) malloc(2*dimlen*sizeof(double));
+ for ( size_t i = 0; i < dimlen-1; ++i )
+ {
+ pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2;
+ pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+ }
+ pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)/2;
+ pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)/2;
+ }
+ if ( pbounds )
+ {
+ size_t nvertex = 2;
+ if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
+ cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+ }
+ if ( pbounds && nvdimID != UNDEFID )
{
strcat(axisname, "_");
strcat(axisname, BNDS_NAME);
dimIDs[0] = dimID;
dimIDs[1] = nvdimID;
- cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
+ cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
}
/*
@@ -1559,8 +1307,9 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
cdf_enddef(fileID);
streamptr->ncmode = 2;
- if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, gridInqXvalsPtr(gridID));
- if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, gridInqXboundsPtr(gridID));
+ if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
+ if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
+ if ( gen_bounds ) Free(pbounds);
if ( ndims == 0 ) streamptr->ncxvarID[gridindex] = ncvarid;
}
@@ -1568,7 +1317,6 @@ void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims)
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
{
@@ -1578,40 +1326,37 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
char axisname[CDI_MAX_NAME];
int index;
/* int index2; */
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
int dimIDs[2];
int ngrids = 0;
- int fileID;
size_t len;
int ncvarid = UNDEFID, ncbvarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
if ( ndims ) ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqYsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqYname(gridID, axisname);
+ if ( axisname[0] == 0 ) Error("axis name undefined!");
+
gridInqYlongname(gridID, longname);
gridInqYstdname(gridID, stdname);
gridInqYunits(gridID, units);
- if ( axisname[0] == 0 ) Error("axis name undefined!");
-
for ( index = 0; index < ngrids; index++ )
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -1644,21 +1389,15 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- if ( ndims )
- {
- cdf_def_dim(fileID, axisname, dimlen, &dimID);
-
- if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
- {
- size_t nvertex = 2;
- if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
- cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
- }
- }
+ if ( ndims ) cdf_def_dim(fileID, axisname, dimlen, &dimID);
- if ( gridInqYvalsPtr(gridID) )
+ int gen_bounds = FALSE;
+ int grid_is_cyclic = gridIsCircular(gridID);
+ const double *pvals = gridInqYvalsPtr(gridID);
+ double *pbounds = NULL;
+ if ( pvals )
{
- cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid);
+ cdf_def_var(fileID, axisname, xtype, ndims, &dimID, &ncvarid);
if ( (len = strlen(stdname)) )
cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);
@@ -1669,13 +1408,34 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
cdf_put_att_text(fileID, ncvarid, "axis", 1, "Y");
- if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID )
+ if ( gridInqYboundsPtr(gridID) )
+ pbounds = (double*) gridInqYboundsPtr(gridID);
+
+ if ( CDI_cmor_mode && grid_is_cyclic && !pbounds )
+ {
+ gen_bounds = TRUE;
+ pbounds = (double*) malloc(2*dimlen*sizeof(double));
+ for ( size_t i = 0; i < dimlen-1; ++i )
+ {
+ pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2;
+ pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2;
+ }
+ pbounds[0] = (pvals[0] < 0) ? -90 : 90;
+ pbounds[2*dimlen-1] = (pvals[dimlen-1] < 0) ? -90 : 90;
+ }
+ if ( pbounds )
+ {
+ size_t nvertex = 2;
+ if ( nc_inq_dimid(fileID, BNDS_NAME, &nvdimID) != NC_NOERR )
+ cdf_def_dim(fileID, BNDS_NAME, nvertex, &nvdimID);
+ }
+ if ( pbounds && nvdimID != UNDEFID )
{
strcat(axisname, "_");
strcat(axisname, BNDS_NAME);
dimIDs[0] = dimID;
dimIDs[1] = nvdimID;
- cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
+ cdf_def_var(fileID, axisname, xtype, 2, dimIDs, &ncbvarid);
cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
}
/*
@@ -1690,8 +1450,9 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
cdf_enddef(fileID);
streamptr->ncmode = 2;
- if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, gridInqYvalsPtr(gridID));
- if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, gridInqYboundsPtr(gridID));
+ if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals);
+ if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds);
+ if ( gen_bounds ) Free(pbounds);
if ( ndims == 0 ) streamptr->ncyvarID[gridindex] = ncvarid;
}
@@ -1699,7 +1460,6 @@ void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims)
streamptr->ydimID[gridindex] = dimID;
}
-
static
void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype)
{
@@ -1727,29 +1487,25 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
char xdimname[4] = "x";
char ydimname[4] = "y";
int index;
- int gridID0, gridtype0, gridindex;
int xdimID = UNDEFID;
int ydimID = UNDEFID;
int dimIDs[3];
- int ngrids;
- int fileID;
size_t len;
int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t xdimlen = (size_t)gridInqXsize(gridID);
size_t ydimlen = (size_t)gridInqYsize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, xaxisname);
gridInqXlongname(gridID, xlongname);
@@ -1764,8 +1520,8 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN ||
gridtype0 == GRID_LONLAT ||
gridtype0 == GRID_CURVILINEAR ||
@@ -1817,7 +1573,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
if ( gridInqXvalsPtr(gridID) )
{
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid);
cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
if ( (len = strlen(xstdname)) )
@@ -1837,7 +1593,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
dimIDs[0] = ydimID;
dimIDs[1] = xdimID;
dimIDs[2] = nvdimID;
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 3, dimIDs, &ncbxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid);
cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
@@ -1846,7 +1602,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
if ( gridInqYvalsPtr(gridID) )
{
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid);
cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
if ( (len = strlen(ystdname)) )
@@ -1866,7 +1622,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
dimIDs[0] = ydimID;
dimIDs[1] = xdimID;
dimIDs[2] = nvdimID;
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 3, dimIDs, &ncbyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid);
cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
@@ -1880,7 +1636,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
static const char longname[] = "area of grid cell";
static const char stdname[] = "cell_area";
- cdf_def_var(fileID, yaxisname_, (nc_type) xtype, 2, dimIDs, &ncavarid);
+ cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid);
cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
@@ -1904,23 +1660,18 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID)
streamptr->ncavarID[gridindex] = ncavarid;
}
-
static
void cdfDefRgrid(stream_t *streamptr, int gridID)
{
char axisname[7] = "rgridX";
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
int lwarn = TRUE;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
@@ -1928,8 +1679,8 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GAUSSIAN_REDUCED )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -1949,7 +1700,7 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
{
if ( lwarn )
{
- Warning("Creating a netCDF file with data on a gaussian reduced grid.");
+ Warning("Creating a NetCDF file with data on a gaussian reduced grid.");
Warning("The further processing of the resulting file is unsupported!");
lwarn = FALSE;
}
@@ -1965,25 +1716,20 @@ void cdfDefRgrid(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefGdim(stream_t *streamptr, int gridID)
{
int index, iz = 0;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
- int vlistID;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
@@ -1992,8 +1738,8 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GENERIC )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -2013,8 +1759,8 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
{
if ( streamptr->ydimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_GENERIC )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -2048,11 +1794,10 @@ void cdfDefGdim(stream_t *streamptr, int gridID)
streamptr->ncmode = 2;
}
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
streamptr->xdimID[gridindex] = dimID;
}
-
static
void cdfDefGridReference(stream_t *streamptr, int gridID)
{
@@ -2083,7 +1828,7 @@ void cdfDefGridUUID(stream_t *streamptr, int gridID)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
{
int fileID = streamptr->fileID;
@@ -2103,7 +1848,7 @@ void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID)
if ( uuidOfVGrid[0] != 0 )
{
char uuidOfVGridStr[37];
- uuid2str(uuidOfVGrid, uuidOfVGridStr);
+ cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
{
int fileID = streamptr->fileID;
@@ -2126,26 +1871,22 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
char xaxisname[CDI_MAX_NAME];
char yaxisname[CDI_MAX_NAME];
int index;
- int gridID0, gridtype0, gridindex;
int dimID = UNDEFID;
- int ngrids;
- int fileID;
size_t len;
int ncxvarid = UNDEFID, ncyvarid = UNDEFID;
int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID;
int nvdimID = UNDEFID;
- int vlistID;
- int xtype = NC_DOUBLE;
+ nc_type xtype = NC_DOUBLE;
if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
- ngrids = vlistNgrids(vlistID);
+ int ngrids = vlistNgrids(vlistID);
size_t dimlen = (size_t)gridInqSize(gridID);
- gridindex = vlistGridIndex(vlistID, gridID);
+ int gridindex = vlistGridIndex(vlistID, gridID);
gridInqXname(gridID, xaxisname);
gridInqXlongname(gridID, xlongname);
@@ -2160,8 +1901,8 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
{
if ( streamptr->xdimID[index] != UNDEFID )
{
- gridID0 = vlistGrid(vlistID, index);
- gridtype0 = gridInqType(gridID0);
+ int gridID0 = vlistGrid(vlistID, index);
+ int gridtype0 = gridInqType(gridID0);
if ( gridtype0 == GRID_UNSTRUCTURED )
{
size_t dimlen0 = (size_t)gridInqSize(gridID0);
@@ -2205,7 +1946,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
if ( gridInqXvalsPtr(gridID) )
{
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 1, &dimID, &ncxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid);
cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
if ( (len = strlen(xstdname)) )
@@ -2222,7 +1963,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
dimIDs[1] = nvdimID;
strcat(xaxisname, "_");
strcat(xaxisname, BNDS_NAME);
- cdf_def_var(fileID, xaxisname, (nc_type) xtype, 2, dimIDs, &ncbxvarid);
+ cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid);
cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncxvarid, "bounds", strlen(xaxisname), xaxisname);
@@ -2231,7 +1972,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
if ( gridInqYvalsPtr(gridID) )
{
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 1, &dimID, &ncyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid);
cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
if ( (len = strlen(ystdname)) )
@@ -2248,7 +1989,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
dimIDs[1] = nvdimID;
strcat(yaxisname, "_");
strcat(yaxisname, BNDS_NAME);
- cdf_def_var(fileID, yaxisname, (nc_type) xtype, 2, dimIDs, &ncbyvarid);
+ cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid);
cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype);
cdf_put_att_text(fileID, ncyvarid, "bounds", strlen(yaxisname), yaxisname);
@@ -2262,7 +2003,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID)
static const char longname[] = "area of grid cell";
static const char stdname[] = "cell_area";
- cdf_def_var(fileID, yaxisname_, (nc_type) xtype, 1, &dimID, &ncavarid);
+ cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid);
cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname);
cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname);
@@ -2293,6 +2034,8 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
int ilev = zaxisInqVctSize(zaxisID)/2;
+ if ( ilev == 0 ) return;
+
int mlev = ilev - 1;
size_t start;
size_t count = 1;
@@ -2308,12 +2051,6 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
return;
}
- if ( ilev == 0 )
- {
- Warning("VCT missing");
- return;
- }
-
int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -2375,6 +2112,8 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
int ilev = zaxisInqVctSize(zaxisID)/2;
+ if ( ilev == 0 ) return;
+
int mlev = ilev - 1;
int hyaiid = 0, hybiid = 0, hyamid, hybmid;
char tmpname[CDI_MAX_NAME];
@@ -2386,12 +2125,6 @@ void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID)
return;
}
- if ( ilev == 0 )
- {
- Warning("VCT missing");
- return;
- }
-
int fileID = streamptr->fileID;
if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -2883,8 +2616,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
if ( gridInqType(gridID) == GRID_SINUSOIDAL )
{
- char varname[] = "sinusoidal";
- char mapname[] = "sinusoidal";
+ static const char varname[] = "sinusoidal";
+ static const char mapname[] = "sinusoidal";
cdf_redef(fileID);
@@ -2902,8 +2635,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
}
else if ( gridInqType(gridID) == GRID_LAEA )
{
- char varname[] = "laea";
- char mapname[] = "lambert_azimuthal_equal_area";
+ static const char varname[] = "laea";
+ static const char mapname[] = "lambert_azimuthal_equal_area";
cdf_redef(fileID);
@@ -2924,8 +2657,8 @@ void cdfDefMapping(stream_t *streamptr, int gridID)
}
else if ( gridInqType(gridID) == GRID_LCC2 )
{
- char varname[] = "Lambert_Conformal";
- char mapname[] = "lambert_conformal_conic";
+ static const char varname[] = "Lambert_Conformal";
+ static const char mapname[] = "lambert_conformal_conic";
cdf_redef(fileID);
@@ -3021,1693 +2754,69 @@ void cdfDefGrid(stream_t *streamptr, int gridID)
else if ( gridtype == GRID_GAUSSIAN_REDUCED )
{
cdfDefRgrid(streamptr, gridID);
- }
- else if ( gridtype == GRID_SPECTRAL )
- {
- cdfDefComplex(streamptr, gridID);
- cdfDefSP(streamptr, gridID);
- }
- else if ( gridtype == GRID_FOURIER )
- {
- cdfDefComplex(streamptr, gridID);
- cdfDefFC(streamptr, gridID);
- }
- else if ( gridtype == GRID_TRAJECTORY )
- {
- cdfDefTrajLon(streamptr, gridID);
- cdfDefTrajLat(streamptr, gridID);
- }
- else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 )
- {
- cdfDefXaxis(streamptr, gridID, 1);
- cdfDefYaxis(streamptr, gridID, 1);
-
- cdfDefMapping(streamptr, gridID);
- }
- /*
- else if ( gridtype == GRID_LCC )
- {
- cdfDefLcc(streamptr, gridID);
- }
- */
- else
- {
- Error("Unsupported grid type: %s", gridNamePtr(gridtype));
- }
-}
-
-static
-int cdfDefVar(stream_t *streamptr, int varID)
-{
- int ncvarid = -1;
- int xid = UNDEFID, yid = UNDEFID;
- size_t xsize = 0, ysize = 0;
- char varname[CDI_MAX_NAME];
- int dims[4];
- int lchunk = FALSE;
- size_t chunks[4] = {0,0,0,0};
- int ndims = 0;
- int tablenum;
- int dimorder[3];
- size_t iax = 0;
- char axis[5];
- int ensID, ensCount, forecast_type;
- int retval;
-
- int fileID = streamptr->fileID;
-
- if ( CDI_Debug )
- Message("streamID = %d, fileID = %d, varID = %d", streamptr->self, fileID, varID);
-
- if ( streamptr->vars[varID].ncvarid != UNDEFID )
- return streamptr->vars[varID].ncvarid;
-
- int vlistID = streamptr->vlistID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- int code = vlistInqVarCode(vlistID, varID);
- int param = vlistInqVarParam(vlistID, varID);
- int pnum, pcat, pdis;
- cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
- int chunktype = vlistInqVarChunkType(vlistID, varID);
-
- vlistInqVarDimorder(vlistID, varID, &dimorder);
-
- int gridsize = gridInqSize(gridID);
- if ( gridsize > 1 ) lchunk = TRUE;
- int gridtype = gridInqType(gridID);
- int gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridtype != GRID_TRAJECTORY )
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize);
- if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize);
- }
-
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- int zid = streamptr->zaxisID[zaxisindex];
- int zaxis_is_scalar = FALSE;
- if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID);
-
- if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */
-
- if ( ((dimorder[0]>0)+(dimorder[1]>0)+(dimorder[2]>0)) < ((xid!=UNDEFID)+(yid!=UNDEFID)+(zid!=UNDEFID)) )
- {
- printf("zid=%d yid=%d xid=%d\n", zid, yid, xid);
- Error("Internal problem, dimension order missing!");
- }
-
- int tid = streamptr->basetime.ncdimid;
-
- if ( tsteptype != TSTEP_CONSTANT )
- {
- if ( tid == UNDEFID ) Error("Internal problem, time undefined!");
- chunks[ndims] = 1;
- dims[ndims++] = tid;
- axis[iax++] = 'T';
- }
- /*
- if ( zid != UNDEFID ) axis[iax++] = 'Z';
- if ( zid != UNDEFID ) chunks[ndims] = 1;
- if ( zid != UNDEFID ) dims[ndims++] = zid;
-
- if ( yid != UNDEFID ) chunks[ndims] = ysize;
- if ( yid != UNDEFID ) dims[ndims++] = yid;
-
- if ( xid != UNDEFID ) chunks[ndims] = xsize;
- if ( xid != UNDEFID ) dims[ndims++] = xid;
- */
- for ( int id = 0; id < 3; ++id )
- {
- if ( dimorder[id] == 3 && zid != UNDEFID )
- {
- axis[iax++] = 'Z';
- chunks[ndims] = 1;
- dims[ndims] = zid;
- ndims++;
- }
- else if ( dimorder[id] == 2 && yid != UNDEFID )
- {
- if ( chunktype == CHUNK_LINES )
- chunks[ndims] = 1;
- else
- chunks[ndims] = ysize;
- dims[ndims] = yid;
- ndims++;
- }
- else if ( dimorder[id] == 1 && xid != UNDEFID )
- {
- chunks[ndims] = xsize;
- dims[ndims] = xid;
- ndims++;
- }
- }
-
- if ( CDI_Debug )
- fprintf(stderr, "chunktype %d chunks %d %d %d %d\n", chunktype, (int)chunks[0], (int)chunks[1], (int)chunks[2], (int)chunks[3]);
-
- int tableID = vlistInqVarTable(vlistID, varID);
-
- const char *name = vlistInqVarNamePtr(vlistID, varID);
- const char *longname = vlistInqVarLongnamePtr(vlistID, varID);
- const char *stdname = vlistInqVarStdnamePtr(vlistID, varID);
- const char *units = vlistInqVarUnitsPtr(vlistID, varID);
-
- if ( name == NULL ) name = tableInqParNamePtr(tableID, code);
- if ( longname == NULL ) longname = tableInqParLongnamePtr(tableID, code);
- if ( units == NULL ) units = tableInqParUnitsPtr(tableID, code);
- if ( name )
- {
- int checkname;
- int iz;
- int status;
-
- sprintf(varname, "%s", name);
-
- checkname = TRUE;
- iz = 0;
-
- while ( checkname )
- {
- if ( iz ) sprintf(varname, "%s_%d", name, iz+1);
-
- status = nc_inq_varid(fileID, varname, &ncvarid);
- if ( status != NC_NOERR )
- {
- checkname = FALSE;
- }
-
- if ( checkname ) iz++;
-
- if ( iz >= CDI_MAX_NAME ) Error("Double entry of variable name '%s'!", name);
- }
-
- if ( strcmp(name, varname) != 0 )
- {
- if ( iz == 1 )
- Warning("Changed double entry of variable name '%s' to '%s'!", name, varname);
- else
- Warning("Changed multiple entry of variable name '%s' to '%s'!", name, varname);
- }
-
- name = varname;
- }
- else
- {
- if ( code < 0 ) code = -code;
- if ( pnum < 0 ) pnum = -pnum;
-
- if ( pdis == 255 )
- sprintf(varname, "var%d", code);
- else
- sprintf(varname, "param%d.%d.%d", pnum, pcat, pdis);
-
- char *varname2 = varname+strlen(varname);
-
- int checkname = TRUE;
- int iz = 0;
-
- while ( checkname )
- {
- if ( iz ) sprintf(varname2, "_%d", iz+1);
-
- int status = nc_inq_varid(fileID, varname, &ncvarid);
- if ( status != NC_NOERR ) checkname = FALSE;
-
- if ( checkname ) iz++;
-
- if ( iz >= CDI_MAX_NAME ) break;
- }
-
- name = varname;
- code = 0;
- pdis = 255;
- }
-
- /* if ( streamptr->ncmode == 2 ) cdf_redef(fileID); */
-
- int dtype = vlistInqVarDatatype(vlistID, varID);
- int xtype = cdfDefDatatype(dtype, streamptr->filetype);
-
- cdf_def_var(fileID, name, (nc_type) xtype, ndims, dims, &ncvarid);
-
-#if defined (HAVE_NETCDF4)
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
- {
- if ( chunktype == CHUNK_AUTO )
- retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
- else
- retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
-
- if ( retval ) Error("nc_def_var_chunking failed, status = %d", retval);
- }
-#endif
-
- if ( streamptr->comptype == COMPRESS_ZIP )
- {
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
- {
- cdfDefVarDeflate(fileID, ncvarid, streamptr->complevel);
- }
- else
- {
- if ( lchunk )
- {
- static int lwarn = TRUE;
-
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("Deflate compression is only available for netCDF4!");
- }
- }
- }
- }
-
- if ( streamptr->comptype == COMPRESS_SZIP )
- {
- if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) )
- {
-#if defined (NC_SZIP_NN_OPTION_MASK)
- cdfDefVarSzip(fileID, ncvarid);
-#else
- static int lwarn = TRUE;
-
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("netCDF4/SZIP compression not available!");
- }
-#endif
- }
- else
- {
- static int lwarn = TRUE;
-
- if ( lwarn )
- {
- lwarn = FALSE;
- Warning("SZIP compression is only available for netCDF4!");
- }
- }
- }
-
- if ( stdname && *stdname )
- cdf_put_att_text(fileID, ncvarid, "standard_name", strlen(stdname), stdname);
-
- if ( longname && *longname )
- cdf_put_att_text(fileID, ncvarid, "long_name", strlen(longname), longname);
-
- if ( units && *units )
- cdf_put_att_text(fileID, ncvarid, "units", strlen(units), units);
-
- if ( code > 0 && pdis == 255 )
- cdf_put_att_int(fileID, ncvarid, "code", NC_INT, 1, &code);
-
- if ( pdis != 255 )
- {
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- cdf_put_att_text(fileID, ncvarid, "param", strlen(paramstr), paramstr);
- }
-
- if ( tableID != UNDEFID )
- {
- tablenum = tableInqNum(tableID);
- if ( tablenum > 0 )
- cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum);
- }
-
- char coordinates[CDI_MAX_NAME];
- coordinates[0] = 0;
-
- if ( zaxis_is_scalar )
- {
- int nczvarID = streamptr->nczvarID[zaxisindex];
- if ( nczvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, nczvarID, coordinates+len);
- }
- }
-
- if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR )
- {
- size_t len = strlen(gridNamePtr(gridtype));
- if ( len > 0 )
- cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype));
- }
-
- if ( gridIsRotated(gridID) )
- {
- char mapping[] = "rotated_pole";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
- }
-
- if ( gridtype == GRID_SINUSOIDAL )
- {
- char mapping[] = "sinusoidal";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
- }
- else if ( gridtype == GRID_LAEA )
- {
- char mapping[] = "laea";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
- }
- else if ( gridtype == GRID_LCC2 )
- {
- char mapping[] = "Lambert_Conformal";
- cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping);
- }
- else if ( gridtype == GRID_TRAJECTORY )
- {
- cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" );
- }
- else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 )
- {
- int ncxvarID = streamptr->ncxvarID[gridindex];
- int ncyvarID = streamptr->ncyvarID[gridindex];
- if ( ncyvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncyvarID, coordinates+len);
- }
- if ( ncxvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncxvarID, coordinates+len);
- }
- }
- else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR )
- {
- char cellarea[CDI_MAX_NAME] = "area: ";
- int ncxvarID = streamptr->ncxvarID[gridindex];
- int ncyvarID = streamptr->ncyvarID[gridindex];
- int ncavarID = streamptr->ncavarID[gridindex];
- if ( ncyvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncyvarID, coordinates+len);
- }
- if ( ncxvarID != CDI_UNDEFID )
- {
- size_t len = strlen(coordinates);
- if ( len ) coordinates[len++] = ' ';
- cdf_inq_varname(fileID, ncxvarID, coordinates+len);
- }
-
- if ( ncavarID != CDI_UNDEFID )
- {
- size_t len = strlen(cellarea);
- cdf_inq_varname(fileID, ncavarID, cellarea+len);
- len = strlen(cellarea);
- cdf_put_att_text(fileID, ncvarid, "cell_measures", len, cellarea);
- }
-
- if ( gridtype == GRID_UNSTRUCTURED )
- {
- int position = gridInqPosition(gridID);
- if ( position > 0 )
- cdf_put_att_int(fileID, ncvarid, "number_of_grid_in_reference", NC_INT, 1, &position);
- }
- }
- else if ( gridtype == GRID_SPECTRAL || gridtype == GRID_FOURIER )
- {
- int gridTruncation = gridInqTrunc(gridID);
- axis[iax++] = '-';
- axis[iax++] = '-';
- cdf_put_att_text(fileID, ncvarid, "axis", iax, axis);
- cdf_put_att_int(fileID, ncvarid, "truncation", NC_INT, 1, &gridTruncation);
- }
-
- size_t len = strlen(coordinates);
- if ( len ) cdf_put_att_text(fileID, ncvarid, "coordinates", len, coordinates);
-
- /* if ( xtype == NC_BYTE || xtype == NC_SHORT || xtype == NC_INT ) */
- {
- int laddoffset, lscalefactor;
- double addoffset, scalefactor;
- int astype = NC_DOUBLE;
-
- addoffset = vlistInqVarAddoffset(vlistID, varID);
- scalefactor = vlistInqVarScalefactor(vlistID, varID);
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
- if ( laddoffset || lscalefactor )
- {
- if ( IS_EQUAL(addoffset, (double) ((float) addoffset)) &&
- IS_EQUAL(scalefactor, (double) ((float) scalefactor)) )
- {
- astype = NC_FLOAT;
- }
-
- if ( xtype == (int) NC_FLOAT ) astype = NC_FLOAT;
-
- cdf_put_att_double(fileID, ncvarid, "add_offset", (nc_type) astype, 1, &addoffset);
- cdf_put_att_double(fileID, ncvarid, "scale_factor", (nc_type) astype, 1, &scalefactor);
- }
- }
-
- if ( dtype == DATATYPE_UINT8 && xtype == NC_BYTE )
- {
- int validrange[2] = {0, 255};
- cdf_put_att_int(fileID, ncvarid, "valid_range", NC_SHORT, 2, validrange);
- cdf_put_att_text(fileID, ncvarid, "_Unsigned", 4, "true");
- }
-
- streamptr->vars[varID].ncvarid = ncvarid;
-
- if ( vlistInqVarMissvalUsed(vlistID, varID) )
- cdfDefVarMissval(streamptr, varID, vlistInqVarDatatype(vlistID, varID), 0);
-
- if ( zid == -1 )
- {
- if ( zaxisInqType(zaxisID) == ZAXIS_CLOUD_BASE ||
- zaxisInqType(zaxisID) == ZAXIS_CLOUD_TOP ||
- zaxisInqType(zaxisID) == ZAXIS_ISOTHERM_ZERO ||
- zaxisInqType(zaxisID) == ZAXIS_TOA ||
- zaxisInqType(zaxisID) == ZAXIS_SEA_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_LAKE_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TA ||
- zaxisInqType(zaxisID) == ZAXIS_SEDIMENT_BOTTOM_TW ||
- zaxisInqType(zaxisID) == ZAXIS_MIX_LAYER ||
- zaxisInqType(zaxisID) == ZAXIS_ATMOSPHERE )
- {
- zaxisInqName(zaxisID, varname);
- cdf_put_att_text(fileID, ncvarid, "level_type", strlen(varname), varname);
- }
- }
-
- if ( vlistInqVarEnsemble( vlistID, varID, &ensID, &ensCount, &forecast_type ) )
- {
- /* void cdf_put_att_int( int ncid, int varid, const char *name, nc_type xtype,
- size_t len, const int *ip )
- */
- cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID);
- cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount);
- cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type);
-
-#ifdef DBG
- if( DBG )
- {
- fprintf( stderr, "cdfDefVar :\n EnsID %d\n Enscount %d\n Forecast init type %d\n", ensID,
- ensCount, forecast_type );
- }
-#endif
- }
-
- /* Attributes */
- defineAttributes(vlistID, varID, fileID, ncvarid);
-
- /* if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); */
-
- return ncvarid;
-}
-
-static
-void scale_add(size_t size, double *data, double addoffset, double scalefactor)
-{
- int laddoffset;
- int lscalefactor;
-
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
- if ( laddoffset || lscalefactor )
- {
- for (size_t i = 0; i < size; ++i )
- {
- if ( lscalefactor ) data[i] *= scalefactor;
- if ( laddoffset ) data[i] += addoffset;
- }
- }
-}
-
-static
-void cdfGetSlapDescription(stream_t *streamptr, int varID, size_t (*start)[4], size_t (*count)[4])
-{
- int vlistID = streamptr->vlistID;
- int tsID = streamptr->curTsID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- int gridindex = vlistGridIndex(vlistID, gridID);
-
- if ( CDI_Debug ) Message("tsID = %d", tsID);
-
- int xid = UNDEFID, yid = UNDEFID;
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfReadGridTraj(streamptr, gridID);
- }
- else
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- int zid = streamptr->zaxisID[zaxisindex];
-
- int ndims = 0;
-#define addDimension(startCoord, length) do \
- { \
- (*start)[ndims] = startCoord; \
- (*count)[ndims] = length; \
- ndims++; \
- } while(0)
- if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
- if ( zid != UNDEFID ) addDimension(0, (size_t)zaxisInqSize(zaxisID));
- if ( yid != UNDEFID ) addDimension(0, (size_t)gridInqYsize(gridID));
- if ( xid != UNDEFID ) addDimension(0, (size_t)gridInqXsize(gridID));
-#undef addDimension
-
- assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
- assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
-
- if ( CDI_Debug )
- for (int idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-}
-
-//Scans the data array for missVals, optionally applying first a scale factor and then an offset.
-//Returns the number of missing + out-of-range values encountered.
-static
-size_t cdfDoInputDataTransformationDP(size_t valueCount, double *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
- {
- const bool haveOffset = IS_NOT_EQUAL(offset, 0);
- const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
- size_t missValCount = 0;
-
- if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
- if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
-
- bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
- assert(!haveRangeCheck || haveMissVal);
-
- switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
- | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
- {
- case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] * scaleFactor + offset;
- }
- break;
- case 13: /* haveRangeCheck & haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] + offset;
- }
- break;
- case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal
- : isMissVal ? data[i] : data[i] * scaleFactor;
- }
- break;
- case 9: /* haveRangeCheck & haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? missVal : data[i];
- }
- break;
- case 7: /* haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = data[i] * scaleFactor + offset;
- break;
- case 6: /* haveOffset & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = data[i] * scaleFactor + offset;
- break;
- case 5: /* haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] += offset;
- break;
- case 4: /* haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] += offset;
- break;
- case 3: /* haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] *= scaleFactor;
- break;
- case 2: /* haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] *= scaleFactor;
- break;
- case 1: /* haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
- break;
- }
-
- return missValCount;
-}
-
-static
-size_t cdfDoInputDataTransformationSP(size_t valueCount, float *data, bool haveMissVal, double missVal, double scaleFactor, double offset, double validMin, double validMax)
- {
- const bool haveOffset = IS_NOT_EQUAL(offset, 0);
- const bool haveScaleFactor = IS_NOT_EQUAL(scaleFactor, 1);
- size_t missValCount = 0;
-
- if ( IS_EQUAL(validMin, VALIDMISS) ) validMin = DBL_MIN;
- if ( IS_EQUAL(validMax, VALIDMISS) ) validMax = DBL_MAX;
-
- bool haveRangeCheck = (IS_NOT_EQUAL(validMax, DBL_MAX)) | (IS_NOT_EQUAL(validMin,DBL_MIN));
- assert(!haveRangeCheck || haveMissVal);
-
- switch ((int)haveMissVal | ((int)haveScaleFactor << 1)
- | ((int)haveOffset << 2) | ((int)haveRangeCheck << 3))
- {
- case 15: /* haveRangeCheck & haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] * scaleFactor + offset);
- }
- break;
- case 13: /* haveRangeCheck & haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] + offset);
- }
- break;
- case 11: /* haveRangeCheck & haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal
- : isMissVal ? data[i] : (float)(data[i] * scaleFactor);
- }
- break;
- case 9: /* haveRangeCheck & haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- {
- int outOfRange = data[i] < validMin || data[i] > validMax;
- int isMissVal = DBL_IS_EQUAL(data[i], missVal);
- missValCount += (size_t)(outOfRange | isMissVal);
- data[i] = outOfRange ? (float)missVal : data[i];
- }
- break;
- case 7: /* haveMissVal & haveScaleFactor & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] * scaleFactor + offset);
- break;
- case 6: /* haveOffset & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] * scaleFactor + offset);
- break;
- case 5: /* haveMissVal & haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] + offset);
- break;
- case 4: /* haveOffset */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] + offset);
- break;
- case 3: /* haveMissVal & haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- if ( DBL_IS_EQUAL(data[i], missVal) )
- missValCount++;
- else
- data[i] = (float)(data[i] * scaleFactor);
- break;
- case 2: /* haveScaleFactor */
- for ( size_t i = 0; i < valueCount; i++ )
- data[i] = (float)(data[i] * scaleFactor);
- break;
- case 1: /* haveMissVal */
- for ( size_t i = 0; i < valueCount; i++ )
- missValCount += (unsigned)DBL_IS_EQUAL(data[i], missVal);
- break;
- }
-
- return missValCount;
-}
-
-static void
-cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dtype, long nvals, size_t xsize, size_t ysize, int swapxy, size_t *start, size_t *count, int memtype, const void *data, int nmiss)
-{
- const double *pdata_dp = (const double *) data;
- double *mdata_dp = NULL;
- double *sdata_dp = NULL;
- const float *pdata_sp = (const float *) data;
- float *mdata_sp = NULL;
- float *sdata_sp = NULL;
-
- /* if ( dtype == DATATYPE_INT8 || dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 ) */
- {
- bool laddoffset, lscalefactor;
- double addoffset, scalefactor;
- double missval;
-
- addoffset = vlistInqVarAddoffset(vlistID, varID);
- scalefactor = vlistInqVarScalefactor(vlistID, varID);
- laddoffset = IS_NOT_EQUAL(addoffset, 0);
- lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
-
- missval = vlistInqVarMissval(vlistID, varID);
-
- if ( laddoffset || lscalefactor )
- {
- if ( memtype == MEMTYPE_FLOAT )
- {
- mdata_sp = (float *) Malloc((size_t)nvals*sizeof(float));
- memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof (float));
- pdata_sp = mdata_sp;
-
- if ( nmiss > 0 )
- {
- for (long i = 0; i < nvals; i++ )
- {
- double temp = mdata_sp[i];
- if ( !DBL_IS_EQUAL(temp, missval) )
- {
- if ( laddoffset ) temp -= addoffset;
- if ( lscalefactor ) temp /= scalefactor;
- mdata_sp[i] = (float)temp;
- }
- }
- }
- else
- {
- for (long i = 0; i < nvals; i++ )
- {
- double temp = mdata_sp[i];
- if ( laddoffset ) temp -= addoffset;
- if ( lscalefactor ) temp /= scalefactor;
- mdata_sp[i] = (float)temp;
- }
- }
- }
- else
- {
- mdata_dp = (double *) Malloc((size_t)nvals * sizeof(double));
- memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof(double));
- pdata_dp = mdata_dp;
-
- if ( nmiss > 0 )
- {
- for (long i = 0; i < nvals; i++ )
- {
- if ( !DBL_IS_EQUAL(mdata_dp[i], missval) )
- {
- if ( laddoffset ) mdata_dp[i] -= addoffset;
- if ( lscalefactor ) mdata_dp[i] /= scalefactor;
- }
- }
- }
- else
- {
- for (long i = 0; i < nvals; i++ )
- {
- if ( laddoffset ) mdata_dp[i] -= addoffset;
- if ( lscalefactor ) mdata_dp[i] /= scalefactor;
- }
- }
- }
- }
-
- if ( dtype == DATATYPE_UINT8 || dtype == DATATYPE_INT8 ||
- dtype == DATATYPE_INT16 || dtype == DATATYPE_INT32 )
- {
- if ( memtype == MEMTYPE_FLOAT )
- {
- if ( mdata_sp == NULL )
- {
- mdata_sp = (float *) Malloc((size_t)nvals * sizeof(float));
- memcpy(mdata_sp, pdata_sp, (size_t)nvals * sizeof(float));
- pdata_sp = mdata_sp;
- }
-
- for (long i = 0; i < nvals; i++ ) mdata_sp[i] = roundf(mdata_sp[i]);
-
- if ( dtype == DATATYPE_UINT8 )
- {
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for ( long i = 0; i < nvals; ++i )
- if ( mdata_sp[i] > 127 ) mdata_sp[i] -= 256;
- }
- }
- }
- else
- {
- if ( mdata_dp == NULL )
- {
- mdata_dp = (double *) Malloc((size_t)nvals * sizeof (double));
- memcpy(mdata_dp, pdata_dp, (size_t)nvals * sizeof (double));
- pdata_dp = mdata_dp;
- }
-
- for (long i = 0; i < nvals; i++ ) mdata_dp[i] = round(mdata_dp[i]);
-
- if ( dtype == DATATYPE_UINT8 )
- {
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for (long i = 0; i < nvals; ++i )
- if ( mdata_dp[i] > 127 ) mdata_dp[i] -= 256;
- }
- }
- }
- }
-
- if ( CDF_Debug && memtype != MEMTYPE_FLOAT )
- {
- double fmin, fmax;
- fmin = 1.0e200;
- fmax = -1.0e200;
- for ( long i = 0; i < nvals; ++i )
- {
- if ( !DBL_IS_EQUAL(pdata_dp[i], missval) )
- {
- if ( pdata_dp[i] < fmin ) fmin = pdata_dp[i];
- if ( pdata_dp[i] > fmax ) fmax = pdata_dp[i];
- }
- }
- Message("nvals = %d, nmiss = %d, missval = %g, minval = %g, maxval = %g",
- nvals, nmiss, missval, fmin, fmax);
- }
- }
-
- if ( swapxy )
- {
- if ( memtype == MEMTYPE_FLOAT )
- {
- /* malloc and the loop imply nvals >= ysize * xsize,
- * but that is not checked and the types don't match */
- sdata_sp = (float *) Malloc((size_t)nvals * sizeof (float));
- for ( size_t j = 0; j < ysize; ++j )
- for ( size_t i = 0; i < xsize; ++i )
- sdata_sp[i*ysize+j] = pdata_sp[j*xsize+i];
- pdata_sp = sdata_sp;
- }
- else
- {
- sdata_dp = (double *) Malloc((size_t)nvals * sizeof (double));
- for ( size_t j = 0; j < ysize; ++j )
- for ( size_t i = 0; i < xsize; ++i )
- sdata_dp[i*ysize+j] = pdata_dp[j*xsize+i];
- pdata_dp = sdata_dp;
- }
- }
-
- if ( memtype == MEMTYPE_FLOAT )
- cdf_put_vara_float(fileID, ncvarid, start, count, pdata_sp);
- else
- cdf_put_vara_double(fileID, ncvarid, start, count, pdata_dp);
-
- if ( mdata_dp ) Free(mdata_dp);
- if ( sdata_dp ) Free(sdata_dp);
- if ( mdata_sp ) Free(mdata_sp);
- if ( sdata_sp ) Free(sdata_sp);
-}
-
-
-void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
-{
- int fileID;
- int gridID;
- int zaxisID;
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
- int ncvarid;
- size_t xsize = 0, ysize = 0;
- size_t size;
- size_t start[5];
- size_t count[5];
- long nvals;
- int swapxy = FALSE;
- int ndims = 0;
- int idim;
- int tsteptype;
- int gridindex, zaxisindex;
- int dtype;
- int vlistID;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
-
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
-
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
- ncvarid = cdfDefVar(streamptr, varID);
-
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
- gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfWriteGridTraj(streamptr, gridID);
- }
- else
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
-
- zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
-
- if ( tsteptype != TSTEP_CONSTANT )
- {
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
- }
- if ( zid != UNDEFID )
- {
- start[ndims] = 0;
- count[ndims] = (size_t)zaxisInqSize(zaxisID);
- ndims++;
- }
- if ( yid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, yid, &size);
- /* count[ndims] = gridInqYsize(gridID); */
- count[ndims] = size;
- ndims++;
- }
- if ( xid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, xid, &size);
- /* count[ndims] = gridInqXsize(gridID); */
- count[ndims] = size;
- ndims++;
- }
-
- if ( CDI_Debug )
- for (idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-
- if ( streamptr->ncmode == 1 )
- {
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
- }
-
- dtype = vlistInqVarDatatype(vlistID, varID);
-
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-
- nvals = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
-
-}
-
-
-void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
- const int rect[][2], const void *data, int nmiss)
-{
- int fileID;
- int gridID;
- int zaxisID;
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
- int ncvarid;
- size_t xsize = 0, ysize = 0;
- size_t start[5];
- size_t count[5];
- long nvals;
- int swapxy = FALSE;
- int ndims = 0;
- int idim;
- int tsteptype;
- int gridindex, zaxisindex;
- int dtype;
- int vlistID;
- int streamID = streamptr->self;
-
- if ( CDI_Debug )
- Message("streamID = %d varID = %d", streamID, varID);
-
- vlistID = streamInqVlist(streamID);
- fileID = streamInqFileID(streamID);
-
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug )
- Message("ntsteps = %ld", ntsteps);
-
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
- ncvarid = cdfDefVar(streamptr, varID);
-
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
- gridindex = vlistGridIndex(vlistID, gridID);
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
- {
- cdfWriteGridTraj(streamptr, gridID);
- }
- else
- {
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
- }
-
- zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
-
- if ( tsteptype != TSTEP_CONSTANT )
- {
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
- }
- if ( zid != UNDEFID )
- {
- int size = zaxisInqSize(zaxisID);
- xassert(rect[2][0] >= 0 && rect[2][0] <= rect[2][1]
- && rect[2][1] <= size);
- start[ndims] = (size_t)rect[2][0];
- count[ndims] = (size_t)rect[2][1] - (size_t)rect[2][0] + 1;
- ndims++;
- }
- if ( yid != UNDEFID )
- {
- size_t size;
- cdf_inq_dimlen(fileID, yid, &size);
- xassert(rect[1][0] >= 0 && rect[1][0] <= rect[1][1]
- && (size_t)rect[1][1] <= size);
- start[ndims] = (size_t)rect[1][0];
- count[ndims] = (size_t)rect[1][1] - (size_t)rect[1][0] + 1;
- ndims++;
- }
- if ( xid != UNDEFID )
- {
- size_t size;
- cdf_inq_dimlen(fileID, xid, &size);
- xassert(rect[0][0] >= 0 && rect[0][0] <= rect[0][1]
- && (size_t)rect[0][1] <= size);
- start[ndims] = (size_t)rect[0][0];
- count[ndims] = (size_t)rect[0][1] - (size_t)rect[0][0] + 1;
- ndims++;
- }
-
- if ( CDI_Debug )
- for (idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-
- if ( streamptr->ncmode == 1 )
- {
- cdf_enddef(fileID);
- streamptr->ncmode = 2;
- }
-
- dtype = vlistInqVarDatatype(vlistID, varID);
-
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-
- nvals = gridInqSize(gridID)*zaxisInqSize(zaxisID);
-
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals,
- xsize, ysize, swapxy, start, count, memtype, data, nmiss);
-}
-
-static
-size_t min_size(size_t a, size_t b)
-{
- return a < b ? a : b;
-}
-
-static
-void transpose2dArrayDP(size_t inWidth, size_t inHeight, double* data)
-{
- const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
- // which should be a decent compromise on many architectures.
-
-#ifdef __cplusplus
- double *temp[inHeight];
- double *out[inWidth];
-
- temp[0] = (double *) Malloc(inHeight * inWidth * sizeof(double));
- out[0] = data;
-
- for(int i = 0; i < inWidth; i++)
- {
- out[i] = out[0] + (inHeight * i);
- }
-
- for(int i = 1; i < inHeight; i++)
- {
- temp[i] = temp[0] + (inWidth * i);
- }
- memcpy(temp[0], data, inHeight * inWidth * sizeof(double));
-#else
- double (*temp)[inWidth] = (double (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
- double (*out)[inHeight] = (double (*)[inHeight])data;
- memcpy(temp, data, inHeight*sizeof(*temp));
-#endif
-
- /*
- for ( size_t y = 0; y < inHeight; ++y )
- for ( size_t x = 0; x < inWidth; ++x )
- out[x][y] = temp[y][x];
- */
-
- for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
- {
- for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
- {
- for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
- {
- for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
- {
- out[x][y] = temp[y][x];
- }
- }
- }
- }
-
- Free(temp[0]);
-}
-
-static
-void transpose2dArraySP(size_t inWidth, size_t inHeight, float* data)
-{
- const size_t cacheBlockSize = 256; // Purely an optimization parameter. Current value of 32 means we are handling 8kB blocks,
- // which should be a decent compromise on many architectures.
-
-#ifndef __cplusplus
- float (*temp)[inWidth] = (float (*)[inWidth]) Malloc(inHeight*sizeof(*temp));
- float (*out)[inHeight] = (float (*)[inHeight])data;
- memcpy(temp, data, inHeight*sizeof(*temp));
- #else
- float *temp[inWidth];
- temp[0] = (float *) Malloc(inWidth * inHeight * sizeof(float));
- for(int i = 1; i < inHeight; i++)
- {
- temp[i] = temp[0] + (inWidth * i);
- }
-
- float **out = (float **)data;
-#endif
-
- /*
- for ( size_t y = 0; y < inHeight; ++y )
- for ( size_t x = 0; x < inWidth; ++x )
- out[x][y] = temp[y][x];
- */
-
- for ( size_t yBlock = 0; yBlock < inHeight; yBlock += cacheBlockSize )
- {
- for ( size_t xBlock = 0; xBlock < inWidth; xBlock += cacheBlockSize )
- {
- for ( size_t y = yBlock, yEnd = min_size(yBlock + cacheBlockSize, inHeight); y < yEnd; y++ )
- {
- for ( size_t x = xBlock, xEnd = min_size(xBlock + cacheBlockSize, inWidth); x < xEnd; x++ )
- {
- out[x][y] = temp[y][x];
- }
- }
- }
- }
-
- Free(temp);
-}
-
-static
-void cdfInqDimIds(stream_t *streamptr, int varId, int (*outDimIds)[3])
-{
- int gridId = vlistInqVarGrid(streamptr->vlistID, varId);
- int gridindex = vlistGridIndex(streamptr->vlistID, gridId);
-
- (*outDimIds)[0] = (*outDimIds)[1] = (*outDimIds)[2] = UNDEFID;
- switch ( gridInqType(gridId) )
- {
- case GRID_TRAJECTORY:
- cdfReadGridTraj(streamptr, gridId);
- break;
-
- case GRID_UNSTRUCTURED:
- (*outDimIds)[0] = streamptr->xdimID[gridindex];
- break;
-
- default:
- (*outDimIds)[0] = streamptr->xdimID[gridindex];
- (*outDimIds)[1] = streamptr->ydimID[gridindex];
- break;
- }
-
- int zaxisID = vlistInqVarZaxis(streamptr->vlistID, varId);
- int zaxisindex = vlistZaxisIndex(streamptr->vlistID, zaxisID);
- (*outDimIds)[2] = streamptr->zaxisID[zaxisindex];
-}
-
-static
-int cdfGetSkipDim(int fileId, int ncvarid, int (*dimIds)[3])
-{
- if((*dimIds)[0] != UNDEFID) return 0;
- if((*dimIds)[1] != UNDEFID) return 0;
- int nvdims;
- cdf_inq_varndims(fileId, ncvarid, &nvdims);
- if(nvdims != 3) return 0;
-
- int varDimIds[3];
- cdf_inq_vardimid(fileId, ncvarid, varDimIds);
- size_t size = 0;
- if ( (*dimIds)[2] == varDimIds[2] )
- {
- cdf_inq_dimlen(fileId, varDimIds[1], &size);
- if ( size == 1 ) return 1;
- }
- else if ( (*dimIds)[2] == varDimIds[1] )
- {
- cdf_inq_dimlen(fileId, varDimIds[2], &size);
- if ( size == 1 ) return 2;
- }
- return 0;
-}
-
-
-static
-void cdfGetSliceSlapDescription(stream_t *streamptr, int varId, int levelId, bool *outSwapXY, size_t (*start)[4], size_t (*count)[4])
-{
- int tsID = streamptr->curTsID;
- if ( CDI_Debug ) Message("tsID = %d", tsID);
-
- int fileId = streamptr->fileID;
- int vlistId = streamptr->vlistID;
- int ncvarid = streamptr->vars[varId].ncvarid;
-
- int gridId = vlistInqVarGrid(vlistId, varId);
- int tsteptype = vlistInqVarTsteptype(vlistId, varId);
- int gridsize = gridInqSize(gridId);
-
- streamptr->numvals += gridsize;
-
- int dimIds[3]; //this array joins the old variables xid, yid, and zid
- cdfInqDimIds(streamptr, varId, &dimIds);
-
- int skipdim = cdfGetSkipDim(fileId, ncvarid, &dimIds);
-
- int dimorder[3];
- vlistInqVarDimorder(vlistId, varId, &dimorder);
-
- *outSwapXY = (dimorder[2] == 2 || dimorder[0] == 1) && dimIds[0] != UNDEFID && dimIds[1] != UNDEFID ;
-
- int ndims = 0;
-
-#define addDimension(startIndex, extent) do { \
- (*start)[ndims] = startIndex; \
- (*count)[ndims] = extent; \
- ndims++; \
- } while(0)
-
- if ( tsteptype != TSTEP_CONSTANT ) addDimension((size_t)tsID, 1);
- if ( skipdim == 1 ) addDimension(0, 1);
-
- for ( int id = 0; id < 3; ++id )
- {
- size_t size;
- int curDimId = dimIds[dimorder[id]-1];
- if ( curDimId == UNDEFID ) continue;
- switch ( dimorder[id] )
- {
- Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
- case 1:
- case 2:
- cdf_inq_dimlen(fileId, curDimId, &size);
- addDimension(0, size);
- break;
-
- case 3:
- addDimension((size_t)levelId, 1);
- break;
-
- default:
- Error("Internal errror: Malformed dimension order encountered. Please report this bug.\n");
- }
- }
-
- if ( skipdim == 2 ) addDimension(0, 1);
-
- assert(ndims <= (int)(sizeof(*start)/sizeof(**start)));
- assert(ndims <= (int)(sizeof(*count)/sizeof(**count)));
-
-#undef addDimension
-
- if ( CDI_Debug )
- for (int idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-
- int nvdims;
- cdf_inq_varndims(fileId, ncvarid, &nvdims);
-
- if ( nvdims != ndims )
- Error("Internal error, variable %s has an unsupported array structure!", vlistInqVarNamePtr(vlistId, varId));
-}
-
-
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- int ncvarid = streamptr->vars[varID].ncvarid;
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
-
- size_t start[4];
- size_t count[4];
- cdfGetSlapDescription(streamptr, varID, &start, &count);
-
- cdf_get_vara_double(fileID, ncvarid, start, count, data);
-
- size_t size = (size_t)gridInqSize(gridID)*(size_t)zaxisInqSize(zaxisID);
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationDP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
-}
-
-
-void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss)
-{
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- int ncvarid = streamptr->vars[varID].ncvarid;
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
-
- size_t start[4];
- size_t count[4];
- cdfGetSlapDescription(streamptr, varID, &start, &count);
-
- cdf_get_vara_float(fileID, ncvarid, start, count, data);
-
- size_t size = (size_t)gridInqSize(gridID) * (size_t)zaxisInqSize(zaxisID);
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationSP(size, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
-}
-
-
-void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss)
-{
- size_t start[4];
- size_t count[4];
-
- if ( CDI_Debug )
- Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- bool swapxy;
- cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
-
- int ncvarid = streamptr->vars[varID].ncvarid;
- int gridId = vlistInqVarGrid(vlistID, varID);
- size_t gridsize = (size_t)gridInqSize(gridId);
- size_t xsize = (size_t)gridInqXsize(gridId);
- size_t ysize = (size_t)gridInqYsize(gridId);
-
- if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
- {
- float *data_fp = (float *) Malloc(gridsize*sizeof(*data_fp));
- cdf_get_vara_float(fileID, ncvarid, start, count, data_fp);
- for ( size_t i = 0; i < gridsize; i++ )
- data[i] = (double) data_fp[i];
- Free(data_fp);
- }
- else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
- {
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for ( size_t i = 0; i < gridsize; i++ )
- if ( data[i] < 0 ) data[i] += 256;
- }
- }
- else
- {
- cdf_get_vara_double(fileID, ncvarid, start, count, data);
- }
-
- if ( swapxy ) transpose2dArrayDP(ysize, xsize, data);
-
- double missval = vlistInqVarMissval(vlistID, varID);
- const bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationDP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
-}
-
-
-void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss)
-{
- size_t start[4];
- size_t count[4];
-
- if ( CDI_Debug )
- Message("streamID = %d varID = %d levelID = %d", streamptr->self, varID, levelID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- bool swapxy;
- cdfGetSliceSlapDescription(streamptr, varID, levelID, &swapxy, &start, &count);
-
- int ncvarid = streamptr->vars[varID].ncvarid;
- int gridId = vlistInqVarGrid(vlistID, varID);
- size_t gridsize = (size_t)gridInqSize(gridId);
- size_t xsize = (size_t)gridInqXsize(gridId);
- size_t ysize = (size_t)gridInqYsize(gridId);
-
- if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT64 )
- {
- double *data_dp = (double *) Malloc(gridsize*sizeof(*data_dp));
- cdf_get_vara_double(fileID, ncvarid, start, count, data_dp);
- for ( size_t i = 0; i < gridsize; i++ )
- data[i] = (float) data_dp[i];
- Free(data_dp);
- }
- else if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_UINT8 )
- {
- nc_type xtype;
- cdf_inq_vartype(fileID, ncvarid, &xtype);
- if ( xtype == NC_BYTE )
- {
- for ( size_t i = 0; i < gridsize; i++ )
- if ( data[i] < 0 ) data[i] += 256;
- }
- }
- else
- {
- cdf_get_vara_float(fileID, ncvarid, start, count, data);
- }
-
- if ( swapxy ) transpose2dArraySP(ysize, xsize, data);
-
- double missval = vlistInqVarMissval(vlistID, varID);
- bool haveMissVal = vlistInqVarMissvalUsed(vlistID, varID);
- double validRange[2];
- if (!(haveMissVal && vlistInqVarValidrange(vlistID, varID, validRange)))
- validRange[0] = DBL_MIN, validRange[1] = DBL_MAX;
- double addoffset = vlistInqVarAddoffset(vlistID, varID);
- double scalefactor = vlistInqVarScalefactor(vlistID, varID);
- size_t nmiss_ = cdfDoInputDataTransformationSP(gridsize, data, haveMissVal, missval, scalefactor, addoffset, validRange[0], validRange[1]);
- assert(nmiss_ <= INT_MAX);
- *nmiss = (int)nmiss_;
-}
-
-
-void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
-{
- size_t xsize = 0, ysize = 0;
- size_t start[5];
- size_t count[5];
- int dimorder[3];
- int xid = UNDEFID, yid = UNDEFID, zid = UNDEFID;
-
- if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID);
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- long ntsteps = streamptr->ntsteps;
- if ( CDI_Debug ) Message("ntsteps = %ld", ntsteps);
-
- if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
-
- int ncvarid = cdfDefVar(streamptr, varID);
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int zaxisID = vlistInqVarZaxis(vlistID, varID);
- int tsteptype = vlistInqVarTsteptype(vlistID, varID);
- vlistInqVarDimorder(vlistID, varID, &dimorder);
-
-
- if ( gridInqType(gridID) == GRID_TRAJECTORY )
+ }
+ else if ( gridtype == GRID_SPECTRAL )
{
- cdfWriteGridTraj(streamptr, gridID);
+ cdfDefComplex(streamptr, gridID);
+ cdfDefSP(streamptr, gridID);
}
- else
+ else if ( gridtype == GRID_FOURIER )
{
- int gridindex = vlistGridIndex(vlistID, gridID);
- xid = streamptr->xdimID[gridindex];
- yid = streamptr->ydimID[gridindex];
+ cdfDefComplex(streamptr, gridID);
+ cdfDefFC(streamptr, gridID);
}
- {
- int zaxisindex = vlistZaxisIndex(vlistID, zaxisID);
- zid = streamptr->zaxisID[zaxisindex];
- }
+ else if ( gridtype == GRID_TRAJECTORY )
+ {
+ cdfDefTrajLon(streamptr, gridID);
+ cdfDefTrajLat(streamptr, gridID);
+ }
+ else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 )
+ {
+ cdfDefXaxis(streamptr, gridID, 1);
+ cdfDefYaxis(streamptr, gridID, 1);
- int swapxy = (dimorder[2] == 2 || dimorder[0] == 1) && xid != UNDEFID && yid != UNDEFID;
+ cdfDefMapping(streamptr, gridID);
+ }
/*
- printf("swapxy %d\n", swapxy);
- printf("dimorder: %d %d %d\n", dimorder[0], dimorder[1], dimorder[2]);
+ else if ( gridtype == GRID_LCC )
+ {
+ cdfDefLcc(streamptr, gridID);
+ }
*/
-
- size_t ndims = 0;
- if ( tsteptype != TSTEP_CONSTANT )
+ else
{
- start[ndims] = (size_t)ntsteps - 1;
- count[ndims] = 1;
- ndims++;
+ Error("Unsupported grid type: %s", gridNamePtr(gridtype));
}
+}
+
+static
+void scale_add(size_t size, double *data, double addoffset, double scalefactor)
+{
+ int laddoffset;
+ int lscalefactor;
- for ( int id = 0; id < 3; ++id )
+ laddoffset = IS_NOT_EQUAL(addoffset, 0);
+ lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+
+ if ( laddoffset || lscalefactor )
{
- if ( dimorder[id] == 3 && zid != UNDEFID )
- {
- start[ndims] = (size_t)levelID;
- count[ndims] = 1;
- ndims++;
- }
- else if ( dimorder[id] == 2 && yid != UNDEFID )
- {
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, yid, &ysize);
- count[ndims] = ysize;
- ndims++;
- }
- else if ( dimorder[id] == 1 && xid != UNDEFID )
+ for (size_t i = 0; i < size; ++i )
{
- start[ndims] = 0;
- cdf_inq_dimlen(fileID, xid, &xsize);
- count[ndims] = xsize;
- ndims++;
+ if ( lscalefactor ) data[i] *= scalefactor;
+ if ( laddoffset ) data[i] += addoffset;
}
}
-
- if ( CDI_Debug )
- for (size_t idim = 0; idim < ndims; idim++)
- Message("dim = %d start = %d count = %d", idim, start[idim], count[idim]);
-
- int dtype = vlistInqVarDatatype(vlistID, varID);
-
- if ( nmiss > 0 ) cdfDefVarMissval(streamptr, varID, dtype, 1);
-
- long nvals = gridInqSize(gridID);
-
- cdf_write_var_data(fileID, vlistID, varID, ncvarid, dtype, nvals, xsize, ysize, swapxy, start, count, memtype, data, nmiss);
-
}
-
static
void cdfCreateRecords(stream_t *streamptr, int tsID)
{
- int varID, levelID, recID, vrecID, zaxisID;
- int nlev, nvrecs;
-
- int vlistID = streamptr->vlistID;
-
if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return;
if ( streamptr->tsteps[tsID].nallrecs > 0 ) return;
+ int vlistID = streamptr->vlistID;
+
tsteps_t* sourceTstep = streamptr->tsteps;
tsteps_t* destTstep = sourceTstep + tsID;
@@ -4718,7 +2827,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
if ( tsID == 0 )
{
- nvrecs = nrecs; /* use all records at first timestep */
+ int nvrecs = nrecs; /* use all records at first timestep */
streamptr->nrecs += nrecs;
@@ -4728,16 +2837,15 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
destTstep->recordSize = nrecs;
destTstep->curRecID = UNDEFID;
destTstep->recIDs = (int *) Malloc((size_t)nvrecs*sizeof (int));;
- for ( recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
+ for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID;
record_t *records = destTstep->records;
- recID = 0;
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = 0, recID = 0; varID < nvars; varID++ )
{
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlev = zaxisInqSize(zaxisID);
- for ( levelID = 0; levelID < nlev; levelID++ )
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int nlev = zaxisInqSize(zaxisID);
+ for ( int levelID = 0; levelID < nlev; levelID++ )
{
recordInitEntry(&records[recID]);
records[recID].varID = (short)varID;
@@ -4748,12 +2856,12 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
}
else if ( tsID == 1 )
{
- nvrecs = 0;
- for ( varID = 0; varID < nvars; varID++ )
+ int nvrecs = 0;
+ for ( int varID = 0; varID < nvars; varID++ )
{
if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
{
- zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
nvrecs += zaxisInqSize(zaxisID);
}
}
@@ -4771,10 +2879,9 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
if ( nvrecs )
{
destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int));
- vrecID = 0;
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ )
{
- varID = destTstep->records[recID].varID;
+ int varID = destTstep->records[recID].varID;
if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT )
{
destTstep->recIDs[vrecID++] = recID;
@@ -4786,7 +2893,7 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
{
if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1);
- nvrecs = streamptr->tsteps[1].nrecs;
+ int nvrecs = streamptr->tsteps[1].nrecs;
streamptr->nrecs += nvrecs;
@@ -4808,54 +2915,38 @@ void cdfCreateRecords(stream_t *streamptr, int tsID)
static
int cdfTimeDimID(int fileID, int ndims, int nvars)
{
- int dimid = UNDEFID;
- int timedimid = UNDEFID;
- char dimname[80];
- char timeunits[CDI_MAX_NAME];
- char attname[CDI_MAX_NAME];
- char name[CDI_MAX_NAME];
- nc_type xtype;
- int nvdims, nvatts;
- int dimids[9];
- int varid, iatt;
-
- for ( dimid = 0; dimid < ndims; dimid++ )
+ for ( int dimid = 0; dimid < ndims; dimid++ )
{
+ char dimname[80];
cdf_inq_dimname(fileID, dimid, dimname);
if ( memcmp(dimname, "time", 4) == 0 )
- {
- timedimid = dimid;
- break;
- }
+ return dimid;
}
- if ( timedimid == UNDEFID )
+
+ for ( int varid = 0; varid < nvars; varid++ )
{
- for ( varid = 0; varid < nvars; varid++ )
+ int nvdims, nvatts, dimids[9];
+ cdf_inq_var(fileID, varid, NULL, NULL, &nvdims, dimids, &nvatts);
+ if ( nvdims == 1 )
{
- cdf_inq_var(fileID, varid, name, &xtype, &nvdims, dimids, &nvatts);
- if ( nvdims == 1 )
+ for ( int iatt = 0; iatt < nvatts; iatt++ )
{
- for ( iatt = 0; iatt < nvatts; iatt++ )
+ char sbuf[CDI_MAX_NAME];
+ cdf_inq_attname(fileID, varid, iatt, sbuf);
+ if ( strncmp(sbuf, "units", 5) == 0 )
{
- cdf_inq_attname(fileID, varid, iatt, attname);
- if ( strncmp(attname, "units", 5) == 0 )
- {
- cdfGetAttText(fileID, varid, "units", sizeof(timeunits), timeunits);
- strtolower(timeunits);
+ cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
+ strtolower(sbuf);
- if ( isTimeUnits(timeunits) )
- {
- timedimid = dimids[0];
- break;
- }
- }
+ if ( isTimeUnits(sbuf) )
+ return dimids[0];
}
}
}
}
- return (timedimid);
+ return UNDEFID;
}
static
@@ -4975,9 +3066,9 @@ void cdfSetDim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype)
}
static
-int isLonAxis(const char *units, const char *stdname)
+bool isLonAxis(const char *units, const char *stdname)
{
- int status = FALSE;
+ bool status = false;
char lc_units[16];
memcpy(lc_units, units, 15);
@@ -4987,26 +3078,26 @@ int isLonAxis(const char *units, const char *stdname)
if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
(memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) )
{
- status = TRUE;
+ status = true;
}
- if ( status == FALSE &&
+ if ( status == false &&
memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) &&
memcmp(lc_units, "degree", 6) == 0 )
{
int ioff = 6;
if ( lc_units[ioff] == 's' ) ioff++;
if ( lc_units[ioff] == '_' ) ioff++;
- if ( lc_units[ioff] == 'e' ) status = TRUE;
+ if ( lc_units[ioff] == 'e' ) status = true;
}
- return (status);
+ return status;
}
static
-int isLatAxis(const char *units, const char *stdname)
+bool isLatAxis(const char *units, const char *stdname)
{
- int status = FALSE;
+ bool status = false;
char lc_units[16];
memcpy(lc_units, units, 15);
@@ -5016,26 +3107,26 @@ int isLatAxis(const char *units, const char *stdname)
if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) &&
(memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) )
{
- status = TRUE;
+ status = true;
}
- if ( status == FALSE &&
+ if ( status == false &&
memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) &&
memcmp(lc_units, "degree", 6) == 0 )
{
int ioff = 6;
if ( lc_units[ioff] == 's' ) ioff++;
if ( lc_units[ioff] == '_' ) ioff++;
- if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = TRUE;
+ if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true;
}
- return (status);
+ return status;
}
static
-int isDBLAxis(/*const char *units,*/ const char *longname)
+bool isDBLAxis(/*const char *units,*/ const char *longname)
{
- int status = FALSE;
+ bool status = false;
if ( strcmp(longname, "depth below land") == 0 ||
strcmp(longname, "depth_below_land") == 0 ||
@@ -5046,56 +3137,65 @@ int isDBLAxis(/*const char *units,*/ const char *longname)
strcmp(ncvars[ncvarid].units, "dm") == 0 ||
strcmp(ncvars[ncvarid].units, "m") == 0 )
*/
- status = TRUE;
+ status = true;
}
- return (status);
+ return status;
}
static
-int unitsIsMeter(const char *units)
+bool unitsIsHeight(const char *units)
{
- return (units[0] == 'm' && (!units[1] || strncmp(units, "meter", 5) == 0));
+ bool status = false;
+ int u0 = units[0];
+
+ if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) ||
+ (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) )
+ {
+ status = true;
+ }
+
+ return status;
}
static
-int isDepthAxis(const char *stdname, const char *longname)
+bool isDepthAxis(const char *stdname, const char *longname)
{
- int status = FALSE;
+ bool status = false;
- if ( strcmp(stdname, "depth") == 0 ) status = TRUE;
+ if ( strcmp(stdname, "depth") == 0 ) status = true;
- if ( status == FALSE )
+ if ( status == false )
if ( strcmp(longname, "depth_below_sea") == 0 ||
strcmp(longname, "depth below sea") == 0 )
{
- status = TRUE;
+ status = true;
}
- return (status);
+ return status;
}
static
-int isHeightAxis(const char *stdname, const char *longname)
+bool isHeightAxis(const char *stdname, const char *longname)
{
- int status = FALSE;
+ bool status = false;
- if ( strcmp(stdname, "height") == 0 ) status = TRUE;
+ if ( strcmp(stdname, "height") == 0 ) status = true;
- if ( status == FALSE )
+ if ( status == false )
if ( strcmp(longname, "height") == 0 ||
strcmp(longname, "height above the surface") == 0 )
{
- status = TRUE;
+ status = true;
}
- return (status);
+ return status;
}
static
-int unitsIsPressure(const char *units)
+bool unitsIsPressure(const char *units)
{
- int status = FALSE;
+ bool status = false;
if ( memcmp(units, "millibar", 8) == 0 ||
memcmp(units, "mb", 2) == 0 ||
@@ -5103,7 +3203,7 @@ int unitsIsPressure(const char *units)
memcmp(units, "hPa", 3) == 0 ||
memcmp(units, "Pa", 2) == 0 )
{
- status = TRUE;
+ status = true;
}
return status;
@@ -5158,9 +3258,9 @@ void scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int
}
static
-int isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
+bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims)
{
- int status = FALSE;
+ bool status = false;
int ncfvarid = ncvarid;
ncvar_t *ncvar = &ncvars[ncvarid];
@@ -5168,7 +3268,7 @@ int isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, cons
{
cdiConvention = CDI_CONVENTION_CF;
- status = TRUE;
+ status = true;
ncvar->zaxistype = ZAXIS_HYBRID;
int dimid = ncvar->dimids[0];
size_t dimlen = ncdims[dimid].len;
@@ -5489,7 +3589,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
if ( warn )
{
warn = FALSE;
- Warning("netCDF attribute grid_type='%s' unsupported!", attstring);
+ Warning("NetCDF attribute grid_type='%s' unsupported!", attstring);
}
}
@@ -5528,7 +3628,7 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
if ( warn )
{
warn = FALSE;
- Warning("netCDF attribute level_type='%s' unsupported!", attstring);
+ Warning("NetCDF attribute level_type='%s' unsupported!", attstring);
}
}
@@ -6143,7 +4243,7 @@ void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncv
{
ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
}
- else if ( unitsIsMeter(ncvars[ncvarid].units) )
+ else if ( unitsIsHeight(ncvars[ncvarid].units) )
{
if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
@@ -6237,7 +4337,7 @@ void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND;
continue;
}
- else if ( unitsIsMeter(ncvars[ncvarid].units) )
+ else if ( unitsIsHeight(ncvars[ncvarid].units) )
{
if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) )
ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA;
@@ -6264,94 +4364,624 @@ void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars)
}
}
}
-}
+}
+
+#if defined (PROJECTION_TEST)
+static
+void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID)
+{
+ int iatt, nvatts;
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
+ nc_type xtype;
+
+ cdf_inq_varnatts(ncfileID, ncvarID, &nvatts);
+
+ for ( iatt = 0; iatt < nvatts; iatt++ )
+ {
+ cdf_inq_attname(ncfileID, ncvarID, iatt, attname);
+ cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype);
+ cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen);
+
+ // printf("%s %d\n", attname, (int)attlen);
+ }
+
+}
+#endif
+
+static
+void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
+{
+ if ( ncvar->chunked )
+ {
+ int ndims = ncvar->ndims;
+
+ if ( grid->type == GRID_UNSTRUCTURED )
+ {
+ if ( ncvar->chunks[ndims-1] == grid->size )
+ ncvar->chunktype = CHUNK_GRID;
+ else
+ ncvar->chunktype = CHUNK_AUTO;
+ }
+ else
+ {
+ if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 &&
+ grid->xsize == ncvar->chunks[ndims-1] &&
+ grid->ysize == ncvar->chunks[ndims-2] )
+ ncvar->chunktype = CHUNK_GRID;
+ else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] )
+ ncvar->chunktype = CHUNK_LINES;
+ else
+ ncvar->chunktype = CHUNK_AUTO;
+ }
+ }
+}
+
+static struct gridVirtTable cdfLazyGridVtable;
+static double *cdfPendingLoad;
+#ifdef HAVE_LIBPTHREAD
+static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT;
+#else
+static bool cdfLazyInitialized;
+#endif
+
+struct cdfLazyGrid
+{
+ grid_t base;
+ const struct gridVirtTable *baseVtable;
+ struct {
+ int datasetNCId, varNCId;
+ } cellAreaGet, xBoundsGet, yBoundsGet;
+ struct xyValGet {
+ double scalefactor, addoffset;
+ size_t start[3], count[3], size, dimsize;
+ int datasetNCId, varNCId;
+ short ndims;
+ } xValsGet, yValsGet;
+#ifdef HAVE_LIBPTHREAD
+ pthread_mutex_t loadSerialize;
+#endif
+};
+
+#ifdef HAVE_LIBPTHREAD
+#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize))
+#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize))
+#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize))
+#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL)
+#else
+#define lock_lazy_load(plGrid)
+#define unlock_lazy_load(plGrid)
+#define destroy_lazy_load_lock(plGrid)
+#define init_lazy_load_lock(plGrid)
+#endif
+
+static void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid)
+{
+ lazyGrid->base.extraData = NULL;
+ if (lazyGrid->base.area == cdfPendingLoad)
+ lazyGrid->base.area = NULL;
+ if (lazyGrid->base.xvals == cdfPendingLoad)
+ lazyGrid->base.xvals = NULL;
+ if (lazyGrid->base.yvals == cdfPendingLoad)
+ lazyGrid->base.yvals = NULL;
+ if (lazyGrid->base.xbounds == cdfPendingLoad)
+ lazyGrid->base.xbounds = NULL;
+ if (lazyGrid->base.ybounds == cdfPendingLoad)
+ lazyGrid->base.ybounds = NULL;
+ destroy_lazy_load_lock(lazyGrid);
+}
+
+static void cdfLazyGridDelete(grid_t *grid)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy;
+ cdfLazyGridDestroy(cdfGrid);
+ baseDestroy(grid);
+}
+
+static void cdfLazyGridDestroyOnce(void)
+{
+ /*
+#ifdef HAVE_MMAP
+ size_t pgSize = cdiGetPageSize(false);
+ munmap(cdfPendingLoad, pgSize);
+#endif
+ */
+}
+
+static void
+cdfLazyGridDefArea(grid_t *grid, const double *area)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->area == cdfPendingLoad)
+ grid->area = NULL;
+ cdfGrid->cellAreaGet.datasetNCId = -1;
+ cdfGrid->cellAreaGet.varNCId = -1;
+ cdfGrid->baseVtable->defArea(grid, area);
+ unlock_lazy_load(cdfGrid);
+}
+
+
+static const double *
+cdfLazyGridInqAreaPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->area == cdfPendingLoad)
+ {
+ grid->area = (double *)Malloc((size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId,
+ lazyGrid->cellAreaGet.varNCId, grid->area);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqAreaPtr(grid);
+}
+
+static void
+cdfLazyGridInqArea(grid_t *grid, double *area)
+{
+ grid->vtable->inqAreaPtr(grid);
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lazyGrid->baseVtable->inqArea(grid, area);
+}
+
+
+static void
+cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp)
+{
+ double *grid_vals
+ = (double *)Malloc(valsGet->size * sizeof (double));
+ *valsp = grid_vals;
+ if ( valsGet->ndims == 3 )
+ cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId,
+ valsGet->start, valsGet->count, grid_vals);
+ else
+ cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals);
+ scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor);
+}
+
+static const double *
+cdfLazyGridInqXValsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->xvals == cdfPendingLoad)
+ cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->xvals);
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqXValsPtr(grid);
+}
+
+static const double *
+cdfLazyGridInqYValsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->yvals == cdfPendingLoad)
+ cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->yvals);
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqYValsPtr(grid);
+}
+
+static double
+cdfLazyGridInqXYVal(grid_t *grid, size_t index,
+ const struct xyValGet *valsGet, double *vals,
+ const double *(*inqValsPtr)(grid_t *gridptr))
+{
+ size_t size = valsGet->size;
+ double v;
+ if ( vals == cdfPendingLoad )
+ {
+ /* prevent full load if only first/last values get inspected */
+ if ( index == 0 || index == size - 1 )
+ {
+ size_t indexND[3];
+ if ( valsGet->ndims == 3 )
+ {
+ indexND[0] = 0;
+ indexND[1] = index / valsGet->count[2];
+ indexND[2] = index % valsGet->count[2];
+ }
+ else if ( valsGet->ndims == 2)
+ {
+ indexND[0] = index / (size_t)grid->xsize;
+ indexND[1] = index % (size_t)grid->xsize;
+ }
+ else
+ indexND[0] = index;
+ cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId,
+ indexND, &v);
+ }
+ else
+ {
+ const double *grid_vals = inqValsPtr(grid);
+ v = grid_vals[index];
+ }
+ }
+ else if ( vals )
+ v = vals[index];
+ else
+ v = 0.0;
+ return v;
+}
+
+static void
+cdfLazyGridDefXVals(grid_t *grid, const double *vals)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->xvals == cdfPendingLoad)
+ grid->xvals = NULL;
+ cdfGrid->xValsGet.datasetNCId = -1;
+ cdfGrid->xValsGet.varNCId = -1;
+ cdfGrid->baseVtable->defXVals(grid, vals);
+ unlock_lazy_load(cdfGrid);
+}
+
+static void
+cdfLazyGridDefYVals(grid_t *grid, const double *vals)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->yvals == cdfPendingLoad)
+ grid->yvals = NULL;
+ cdfGrid->yValsGet.datasetNCId = -1;
+ cdfGrid->yValsGet.varNCId = -1;
+ cdfGrid->baseVtable->defYVals(grid, vals);
+ unlock_lazy_load(cdfGrid);
+}
+
+static double
+cdfLazyGridInqXVal(grid_t *grid, int index)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet,
+ grid->xvals, grid->vtable->inqXValsPtr);
+ unlock_lazy_load(lazyGrid);
+ return rv;
+}
+
+static double
+cdfLazyGridInqYVal(grid_t *grid, int index)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet,
+ grid->yvals, grid->vtable->inqYValsPtr);
+ unlock_lazy_load(lazyGrid);
+ return rv;
+}
+
+static int
+cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef,
+ struct cdfLazyGrid *lazyGridTest)
+{
+ struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet,
+ *valsGetYRef = &lazyGridRef->yValsGet,
+ *valsGetXTest = &lazyGridTest->xValsGet,
+ *valsGetYTest = &lazyGridTest->yValsGet;
+ if (valsGetXRef->datasetNCId == -1
+ || valsGetXTest->datasetNCId == -1
+ || valsGetYRef->datasetNCId == -1
+ || valsGetYTest->datasetNCId == -1)
+ return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base,
+ &lazyGridTest->base);
+ return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId
+ || valsGetXRef->varNCId != valsGetXTest->varNCId
+ || valsGetYRef->datasetNCId != valsGetYTest->datasetNCId
+ || valsGetYRef->varNCId != valsGetYTest->varNCId;
+}
+
+static int
+cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest)
+{
+ int diff;
+ struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+ if (gridTest->vtable == &cdfLazyGridVtable)
+ diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+ else
+ diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest);
+ return diff;
+}
+
+static int
+cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest)
+{
+ int diff;
+ struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef;
+ if (gridTest->vtable == &cdfLazyGridVtable)
+ diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest);
+ else
+ diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest);
+ return diff;
+}
+
+
+static const double *
+cdfLazyGridInqXBoundsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->xbounds == cdfPendingLoad)
+ {
+ grid->xbounds = (double *)Malloc((size_t)grid->nvertex
+ * (size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId,
+ lazyGrid->xBoundsGet.varNCId, grid->xbounds);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqXBoundsPtr(grid);
+}
+
+static void
+cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->xbounds == cdfPendingLoad)
+ grid->xbounds = NULL;
+ cdfGrid->xBoundsGet.datasetNCId = -1;
+ cdfGrid->xBoundsGet.varNCId = -1;
+ cdfGrid->baseVtable->defXBounds(grid, xbounds);
+ unlock_lazy_load(cdfGrid);
+}
+
+static void
+cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds)
+{
+ struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(cdfGrid);
+ if (grid->ybounds == cdfPendingLoad)
+ grid->ybounds = NULL;
+ cdfGrid->yBoundsGet.datasetNCId = -1;
+ cdfGrid->yBoundsGet.varNCId = -1;
+ cdfGrid->baseVtable->defYBounds(grid, ybounds);
+ unlock_lazy_load(cdfGrid);
+}
+
+static const double *
+cdfLazyGridInqYBoundsPtr(grid_t *grid)
+{
+ struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid;
+ lock_lazy_load(lazyGrid);
+ if (grid->ybounds == cdfPendingLoad)
+ {
+ grid->ybounds = (double *)Malloc((size_t)grid->nvertex
+ * (size_t)grid->size * sizeof(double));
+ cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId,
+ lazyGrid->yBoundsGet.varNCId, grid->ybounds);
+ }
+ unlock_lazy_load(lazyGrid);
+ return lazyGrid->baseVtable->inqYBoundsPtr(grid);
+}
+
+static void
+cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup,
+ *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig;
+ lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+ lazyGridDup->baseVtable = lazyGridOrig->baseVtable;
+ lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet;
+ lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet;
+ lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet;
+ lazyGridDup->xValsGet = lazyGridOrig->xValsGet;
+ lazyGridDup->yValsGet = lazyGridOrig->yValsGet;
+ init_lazy_load_lock(lazyGridDup);
+}
+
+static void
+cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup)
+{
+ size_t nrowlon = (size_t)gridptrOrig->nrowlon;
+ size_t gridsize = (size_t)gridptrOrig->size;
+ int gridtype = gridptrOrig->type;
+ int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED;
+ if ( nrowlon )
+ {
+ gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int));
+ memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int));
+ }
+
+ if ( gridptrOrig->xvals != NULL && gridptrOrig->xvals != cdfPendingLoad )
+ {
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize;
+
+ gridptrDup->xvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double));
+ }
-#if defined (PROJECTION_TEST)
-static
-void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID)
-{
- int iatt, nvatts;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- nc_type xtype;
+ if ( gridptrOrig->yvals != NULL && gridptrOrig->yvals != cdfPendingLoad )
+ {
+ size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize;
- cdf_inq_varnatts(ncfileID, ncvarID, &nvatts);
+ gridptrDup->yvals = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double));
+ }
- for ( iatt = 0; iatt < nvatts; iatt++ )
+ if ( gridptrOrig->xbounds != NULL && gridptrOrig->xbounds != cdfPendingLoad )
{
- cdf_inq_attname(ncfileID, ncvarID, iatt, attname);
- cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype);
- cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen);
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize)
+ * (size_t)gridptrOrig->nvertex;
- // printf("%s %d\n", attname, (int)attlen);
+ gridptrDup->xbounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double));
+ }
+
+ if ( gridptrOrig->ybounds != NULL && gridptrOrig->ybounds != cdfPendingLoad )
+ {
+ size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize)
+ * (size_t)gridptrOrig->nvertex;
+
+ gridptrDup->ybounds = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double));
+ }
+
+ {
+ if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad )
+ {
+ size_t size = gridsize;
+
+ gridptrDup->area = (double *)Malloc(size * sizeof (double));
+ memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double));
+ }
+ }
+
+ if ( gridptrOrig->mask != NULL )
+ {
+ size_t size = gridsize;
+
+ gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t));
+ memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t));
}
+ if ( gridptrOrig->mask_gme != NULL )
+ {
+ size_t size = gridsize;
+
+ gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t));
+ memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t));
+ }
+}
+
+static grid_t *
+cdfLazyGridCopy(grid_t *gridptrOrig)
+{
+ struct cdfLazyGrid *lazyGridDup
+ = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup));
+ gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base);
+ gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base);
+ return &lazyGridDup->base;
}
+
+static void
+cdfLazyGridInitOnce(void)
+{
+ cdfLazyGridVtable = cdiGridVtable;
+ cdfLazyGridVtable.destroy = cdfLazyGridDelete;
+ cdfLazyGridVtable.copy = cdfLazyGridCopy;
+ cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields;
+ cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields;
+ cdfLazyGridVtable.defArea = cdfLazyGridDefArea;
+ cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr;
+ cdfLazyGridVtable.inqArea = cdfLazyGridInqArea;
+ cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr;
+ cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr;
+ cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal;
+ cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal;
+ cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals;
+ cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals;
+ cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull;
+ cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO;
+ cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds;
+ cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds;
+ cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr;
+ cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr;
+ /* create inaccessible memory area, if possible, this serves as
+ * dummy value for pointers to data not yet loaded */
+ /*
+#ifdef HAVE_MMAP
+ {
+ size_t pgSize = cdiGetPageSize(false);
+ static const char devZero[] = "/dev/zero";
+ int fd = open(devZero, O_RDWR);
+ if (fd == -1)
+ SysError("Could not open %s to map anonymous memory", devZero);
+ void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0);
+ if (cdfInvalid == MAP_FAILED)
+ SysError("Could not mmap anonymous memory");
+ cdfPendingLoad = cdfInvalid;
+ int rc = close(fd);
+ if (rc == -1)
+ SysError("Could not close %s file handle %d after mapping anonymous"
+ " memory", devZero, fd);
+ }
+#else
+ */
+ cdfPendingLoad = (double *)&cdfPendingLoad;
+ //#endif
+ atexit(cdfLazyGridDestroyOnce);
+#ifndef HAVE_LIBPTHREAD
+ cdfLazyInitialized = true;
#endif
+}
-static
-void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
+static void
+cdfBaseGridInit(grid_t *grid, int gridtype)
{
- if ( ncvar->chunked )
- {
- int ndims = ncvar->ndims;
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
+}
- if ( grid->type == GRID_UNSTRUCTURED )
- {
- if ( ncvar->chunks[ndims-1] == grid->size )
- ncvar->chunktype = CHUNK_GRID;
- else
- ncvar->chunktype = CHUNK_AUTO;
- }
- else
- {
- if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 &&
- grid->xsize == ncvar->chunks[ndims-1] &&
- grid->ysize == ncvar->chunks[ndims-2] )
- ncvar->chunktype = CHUNK_GRID;
- else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] )
- ncvar->chunktype = CHUNK_LINES;
- else
- ncvar->chunktype = CHUNK_AUTO;
- }
- }
+static void
+cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype)
+{
+#ifdef HAVE_LIBPTHREAD
+ pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce);
+#else
+ if (cdfLazyInitialized) ; else cdfLazyGridInitOnce();
+#endif
+ cdfBaseGridInit(&grid->base, gridtype);
+ grid->baseVtable = grid->base.vtable;
+ grid->cellAreaGet.datasetNCId = -1;
+ grid->cellAreaGet.varNCId = -1;
+ grid->xValsGet.datasetNCId = -1;
+ grid->xValsGet.varNCId = -1;
+ grid->yValsGet.datasetNCId = -1;
+ grid->yValsGet.varNCId = -1;
+ grid->xBoundsGet.datasetNCId = -1;
+ grid->xBoundsGet.varNCId = -1;
+ grid->yBoundsGet.datasetNCId = -1;
+ grid->yBoundsGet.varNCId = -1;
+ grid->base.vtable = &cdfLazyGridVtable;
+ init_lazy_load_lock(grid);
+}
+
+static void
+cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+ struct cdfLazyGrid *restrict grid = *gridpptr;
+ if (!grid)
+ *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid));
+ cdfLazyGridInit(grid, gridtype);
+}
+
+static void
+cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype)
+{
+ struct cdfLazyGrid *restrict grid = *gridpptr;
+ if (!grid)
+ *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t));
+ cdfBaseGridInit((grid_t*)grid, gridtype);
}
+
/* define all input grids */
static
void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used)
{
- int ncvarid, ncvarid2;
- int nbdims;
- int i;
- int nvatts;
- int skipvar;
- size_t nvertex;
- grid_t grid;
- grid_t proj;
- int gridindex;
- char name[CDI_MAX_NAME];
- int iatt;
int ltwarn = TRUE;
- size_t attlen;
- char attname[CDI_MAX_NAME];
- double datt;
+ struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL;
+#define grid (&lazyGrid->base)
+#define proj (&lazyProj->base)
- for ( ncvarid = 0; ncvarid < nvars; ++ncvarid )
+ for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid )
{
if ( ncvars[ncvarid].isvar && ncvars[ncvarid].gridID == UNDEFID )
{
- int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
+ int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1};
int xdimid = -1, ydimid = -1;
- int xvarid = -1, yvarid = -1;
int islon = 0, islat = 0;
int nxdims = 0, nydims = 0;
- size_t size = 0, np = 0;
+ size_t size = 0;
size_t xsize = 0, ysize = 0;
- double xinc = 0, yinc = 0;
+ double yinc = 0;
+ struct addIffNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 },
+ gridAdded = { .Id = CDI_UNDEFID, .isNew = 0 };
int ndims = ncvars[ncvarid].ndims;
- for ( i = 0; i < ndims; i++ )
+ for ( int i = 0; i < ndims; i++ )
{
if ( ncvars[ncvarid].dimtype[i] == X_AXIS && nxdims < 2 )
{
@@ -6381,15 +5011,12 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
ydimid = ydimids[0];
}
- if ( ncvars[ncvarid].xvarid != UNDEFID )
- xvarid = ncvars[ncvarid].xvarid;
- else if ( xdimid != UNDEFID )
- xvarid = ncdims[xdimid].ncvarid;
-
- if ( ncvars[ncvarid].yvarid != UNDEFID )
- yvarid = ncvars[ncvarid].yvarid;
- else if ( ydimid != UNDEFID )
- yvarid = ncdims[ydimid].ncvarid;
+ int xvarid = ncvars[ncvarid].xvarid != UNDEFID
+ ? ncvars[ncvarid].xvarid
+ : (xdimid != UNDEFID ? ncdims[xdimid].ncvarid : -1);
+ int yvarid = ncvars[ncvarid].yvarid != UNDEFID
+ ? ncvars[ncvarid].yvarid
+ : (ydimid != UNDEFID ? ncdims[ydimid].ncvarid : -1);
/*
if ( xdimid != UNDEFID )
@@ -6418,18 +5045,26 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( ncvars[ncvarid].gridtype == UNDEFID || ncvars[ncvarid].gridtype == GRID_GENERIC )
if ( xdimid != UNDEFID && xdimid == ydimid && nydims == 0 ) ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED;
- grid_init(&grid);
- grid_init(&proj);
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ cdfLazyGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
+ cdfLazyGridRenew(&lazyProj, GRID_PROJECTION);
+ }
+ else
+ {
+ cdfBaseGridRenew(&lazyGrid, ncvars[ncvarid].gridtype);
+ cdfBaseGridRenew(&lazyProj, GRID_PROJECTION);
+ }
- grid.prec = DATATYPE_FLT64;
- grid.trunc = ncvars[ncvarid].truncation;
+ grid->prec = DATATYPE_FLT64;
+ grid->trunc = ncvars[ncvarid].truncation;
if ( ncvars[ncvarid].gridtype == GRID_TRAJECTORY )
{
if ( ncvars[ncvarid].xvarid == UNDEFID )
- Error("Longitude coordinate undefined for %s!", name);
+ Error("Longitude coordinate undefined for %s!", ncvars[ncvarid].name);
if ( ncvars[ncvarid].yvarid == UNDEFID )
- Error("Latitude coordinate undefined for %s!", name);
+ Error("Latitude coordinate undefined for %s!", ncvars[ncvarid].name);
}
else
{
@@ -6492,7 +5127,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( xvarid != UNDEFID )
{
- skipvar = TRUE;
+ bool skipvar = true;
islon = ncvars[xvarid].islon;
ndims = ncvars[xvarid].ndims;
if ( ndims == 2 || ndims == 3 )
@@ -6500,29 +5135,24 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
ncvars[ncvarid].gridtype = GRID_CURVILINEAR;
size = xsize*ysize;
/* Check size of 2 dimensional coordinate variables */
- {
- int dimid = ncvars[xvarid].dimids[ndims-2];
- size_t dimsize1 = ncdims[dimid].len;
- dimid = ncvars[xvarid].dimids[ndims-1];
- size_t dimsize2 = ncdims[dimid].len;
- if ( dimsize1*dimsize2 == size ) skipvar = FALSE;
- }
+ int dimid = ncvars[xvarid].dimids[ndims-2];
+ size_t dimsize1 = ncdims[dimid].len;
+ dimid = ncvars[xvarid].dimids[ndims-1];
+ size_t dimsize2 = ncdims[dimid].len;
+ skipvar = dimsize1*dimsize2 != size;
}
else if ( ndims == 1 )
{
size = xsize;
/* Check size of 1 dimensional coordinate variables */
- {
- int dimid = ncvars[xvarid].dimids[0];
- size_t dimsize = ncdims[dimid].len;
- if ( dimsize == size ) skipvar = FALSE;
- }
+ int dimid = ncvars[xvarid].dimids[0];
+ size_t dimsize = ncdims[dimid].len;
+ skipvar = dimsize != size;
}
else if ( ndims == 0 && xsize == 0 )
{
- xsize = 1;
- size = xsize;
- skipvar = FALSE;
+ size = xsize = 1;
+ skipvar = false;
}
if ( skipvar )
@@ -6532,38 +5162,48 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
continue;
}
- if ( ncvars[xvarid].xtype == NC_FLOAT ) grid.prec = DATATYPE_FLT32;
- grid.xvals = (double *) Malloc(size*sizeof(double));
-
- if ( ltgrid )
- cdf_get_vara_double(ncvars[xvarid].ncid, xvarid, start, count, grid.xvals);
- else
- cdf_get_var_double(ncvars[xvarid].ncid, xvarid, grid.xvals);
-
- scale_add(size, grid.xvals, ncvars[xvarid].addoffset, ncvars[xvarid].scalefactor);
-
- strcpy(grid.xname, ncvars[xvarid].name);
- strcpy(grid.xlongname, ncvars[xvarid].longname);
- strcpy(grid.xunits, ncvars[xvarid].units);
+ if ( ncvars[xvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->xValsGet = (struct xyValGet){
+ .scalefactor = ncvars[xvarid].scalefactor,
+ .addoffset = ncvars[xvarid].addoffset,
+ .start = { start[0], start[1], start[2] },
+ .count = { count[0], count[1], count[2] },
+ .size = size,
+ .datasetNCId = ncvars[xvarid].ncid,
+ .varNCId = xvarid,
+ .ndims = (short)ndims,
+ };
+ grid->xvals = cdfPendingLoad;
+ }
+ else
+ {
+ grid->xvals = (double *) Malloc(size*sizeof(double));
+ if ( ltgrid )
+ cdf_get_vara_double(ncvars[xvarid].ncid, xvarid,
+ start, count, grid->xvals);
+ else
+ cdf_get_var_double(ncvars[xvarid].ncid, xvarid,
+ grid->xvals);
+ scale_add(size, grid->xvals,
+ ncvars[xvarid].addoffset,
+ ncvars[xvarid].scalefactor);
+ }
+ strcpy(grid->xname, ncvars[xvarid].name);
+ strcpy(grid->xlongname, ncvars[xvarid].longname);
+ strcpy(grid->xunits, ncvars[xvarid].units);
/* don't change the name !!! */
/*
- if ( (len = strlen(grid.xname)) > 2 )
- if ( grid.xname[len-2] == '_' && isdigit((int) grid.xname[len-1]) )
- grid.xname[len-2] = 0;
+ if ( (len = strlen(grid->xname)) > 2 )
+ if ( grid->xname[len-2] == '_' && isdigit((int) grid->xname[len-1]) )
+ grid->xname[len-2] = 0;
*/
- if ( islon && xsize > 1 )
- {
- xinc = fabs(grid.xvals[0] - grid.xvals[1]);
- for ( i = 2; i < (int) xsize; i++ )
- if ( (fabs(grid.xvals[i-1] - grid.xvals[i]) - xinc) > (xinc/1000) ) break;
-
- if ( i < (int) xsize ) xinc = 0;
- }
}
if ( yvarid != UNDEFID )
{
- skipvar = TRUE;
+ bool skipvar = true;
islat = ncvars[yvarid].islat;
ndims = ncvars[yvarid].ndims;
if ( ndims == 2 || ndims == 3 )
@@ -6578,7 +5218,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
dimsize1 = ncdims[dimid].len;
dimid = ncvars[yvarid].dimids[ndims-1];
dimsize2 = ncdims[dimid].len;
- if ( dimsize1*dimsize2 == size ) skipvar = FALSE;
+ skipvar = dimsize1*dimsize2 != size;
}
}
else if ( ndims == 1 )
@@ -6592,14 +5232,13 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
size_t dimsize;
dimid = ncvars[yvarid].dimids[0];
dimsize = ncdims[dimid].len;
- if ( dimsize == size ) skipvar = FALSE;
+ skipvar = dimsize != size;
}
}
else if ( ndims == 0 && ysize == 0 )
{
- ysize = 1;
- size = ysize;
- skipvar = FALSE;
+ size = ysize = 1;
+ skipvar = false;
}
if ( skipvar )
@@ -6609,33 +5248,57 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
continue;
}
- if ( ncvars[yvarid].xtype == NC_FLOAT ) grid.prec = DATATYPE_FLT32;
- grid.yvals = (double *) Malloc(size*sizeof(double));
-
- if ( ltgrid )
- cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid.yvals);
- else
- cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid.yvals);
+ if ( ncvars[yvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32;
+ /* see below for when it's impossible to operate
+ * without y values */
+ if ( !CDI_netcdf_lazy_grid_load
+ || ((ncvars[ncvarid].gridtype == UNDEFID ||
+ ncvars[ncvarid].gridtype == GRID_GENERIC)
+ && islat && (islon || xsize == 0)) )
+ {
+ grid->yvals = (double *) Malloc(size*sizeof(double));
- scale_add(size, grid.yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor);
+ if ( ltgrid )
+ cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid->yvals);
+ else
+ cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid->yvals);
- strcpy(grid.yname, ncvars[yvarid].name);
- strcpy(grid.ylongname, ncvars[yvarid].longname);
- strcpy(grid.yunits, ncvars[yvarid].units);
- /* don't change the name !!! */
- /*
- if ( (len = strlen(grid.yname)) > 2 )
- if ( grid.yname[len-2] == '_' && isdigit((int) grid.yname[len-1]) )
- grid.yname[len-2] = 0;
- */
- if ( islon && (int) ysize > 1 )
- {
- yinc = fabs(grid.yvals[0] - grid.yvals[1]);
- for ( i = 2; i < (int) ysize; i++ )
- if ( (fabs(grid.yvals[i-1] - grid.yvals[i]) - yinc) > (yinc/1000) ) break;
+ scale_add(size, grid->yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor);
- if ( i < (int) ysize ) yinc = 0;
- }
+ /* don't change the name !!! */
+ /*
+ if ( (len = strlen(grid->yname)) > 2 )
+ if ( grid->yname[len-2] == '_' && isdigit((int) grid->yname[len-1]) )
+ grid->yname[len-2] = 0;
+ */
+ if ( islon && (int) ysize > 1 )
+ {
+ yinc = fabs(grid->yvals[0] - grid->yvals[1]);
+ for ( size_t i = 2; i < ysize; i++ )
+ if ( (fabs(grid->yvals[i-1] - grid->yvals[i]) - yinc) > (yinc/1000) )
+ {
+ yinc = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ lazyGrid->yValsGet = (struct xyValGet){
+ .scalefactor = ncvars[yvarid].scalefactor,
+ .addoffset = ncvars[yvarid].addoffset,
+ .start = { start[0], start[1], start[2] },
+ .count = { count[0], count[1], count[2] },
+ .size = size,
+ .datasetNCId = ncvars[yvarid].ncid,
+ .varNCId = yvarid,
+ .ndims = (short)ndims,
+ };
+ grid->yvals = cdfPendingLoad;
+ }
+ strcpy(grid->yname, ncvars[yvarid].name);
+ strcpy(grid->ylongname, ncvars[yvarid].longname);
+ strcpy(grid->yunits, ncvars[yvarid].units);
}
if ( (int) ysize == 0 ) size = xsize;
@@ -6647,22 +5310,12 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( ncvars[ncvarid].gridtype == UNDEFID ||
ncvars[ncvarid].gridtype == GRID_GENERIC )
{
- if ( islat && islon )
- {
- if ( isGaussGrid(ysize, yinc, grid.yvals) )
- {
- ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
- np = ysize/2;
- }
- else
- ncvars[ncvarid].gridtype = GRID_LONLAT;
- }
- else if ( islat && !islon && xsize == 0 )
+ if ( islat && (islon || xsize == 0) )
{
- if ( isGaussGrid(ysize, yinc, grid.yvals) )
+ if ( isGaussGrid(ysize, yinc, grid->yvals) )
{
ncvars[ncvarid].gridtype = GRID_GAUSSIAN;
- np = ysize/2;
+ grid->np = (int)(ysize/2);
}
else
ncvars[ncvarid].gridtype = GRID_LONLAT;
@@ -6683,83 +5336,137 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
case GRID_UNSTRUCTURED:
case GRID_CURVILINEAR:
{
- grid.size = (int)size;
- grid.xsize = (int)xsize;
- grid.ysize = (int)ysize;
- grid.np = (int)np;
+ grid->size = (int)size;
+ grid->xsize = (int)xsize;
+ grid->ysize = (int)ysize;
if ( xvarid != UNDEFID )
{
- grid.xdef = 1;
+ grid->xdef = 1;
if ( ncvars[xvarid].bounds != UNDEFID )
{
- nbdims = ncvars[ncvars[xvarid].bounds].ndims;
+ int nbdims = ncvars[ncvars[xvarid].bounds].ndims;
if ( nbdims == 2 || nbdims == 3 )
{
- nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
- grid.nvertex = (int) nvertex;
- grid.xbounds = (double *) Malloc(nvertex*size*sizeof(double));
- cdf_get_var_double(ncvars[xvarid].ncid, ncvars[xvarid].bounds, grid.xbounds);
+ size_t nvertex = ncdims[ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]].len;
+ grid->nvertex = (int)nvertex;
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->xBoundsGet.datasetNCId
+ = ncvars[xvarid].ncid;
+ lazyGrid->xBoundsGet.varNCId
+ = ncvars[xvarid].bounds;
+ grid->xbounds = cdfPendingLoad;
+ }
+ else
+ {
+ grid->xbounds
+ = (double *)Malloc(nvertex * size
+ * sizeof(double));
+ cdf_get_var_double(ncvars[xvarid].ncid,
+ ncvars[xvarid].bounds,
+ grid->xbounds);
+ }
}
}
}
if ( yvarid != UNDEFID )
{
- grid.ydef = 1;
+ grid->ydef = 1;
if ( ncvars[yvarid].bounds != UNDEFID )
{
- nbdims = ncvars[ncvars[yvarid].bounds].ndims;
+ int nbdims = ncvars[ncvars[yvarid].bounds].ndims;
if ( nbdims == 2 || nbdims == 3 )
{
- nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len;
- /*
- if ( nvertex != grid.nvertex )
+ /* size_t nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len;
+ if ( nvertex != grid->nvertex )
Warning("nvertex problem! nvertex x %d, nvertex y %d",
- grid.nvertex, (int) nvertex);
+ grid->nvertex, (int) nvertex);
*/
- grid.ybounds = (double *) Malloc(nvertex*size*sizeof(double));
- cdf_get_var_double(ncvars[yvarid].ncid, ncvars[yvarid].bounds, grid.ybounds);
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ lazyGrid->yBoundsGet.datasetNCId
+ = ncvars[yvarid].ncid;
+ lazyGrid->yBoundsGet.varNCId
+ = ncvars[yvarid].bounds;
+ grid->ybounds = cdfPendingLoad;
+ }
+ else
+ {
+ int vid
+ = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1];
+ size_t nvertex = ncdims[vid].len;
+ /*
+ if ( nvertex != grid->nvertex )
+ Warning("nvertex problem! nvertex x %d, nvertex y %d",
+ grid->nvertex, (int) nvertex);
+ */
+ grid->ybounds
+ = (double *)Malloc(nvertex * size
+ * sizeof(double));
+ cdf_get_var_double(ncvars[yvarid].ncid,
+ ncvars[yvarid].bounds,
+ grid->ybounds);
+ }
}
}
}
if ( ncvars[ncvarid].cellarea != UNDEFID )
- {
- grid.area = (double *) Malloc(size*sizeof(double));
- cdf_get_var_double(ncvars[ncvarid].ncid, ncvars[ncvarid].cellarea, grid.area);
- }
+ {
+ if (CDI_netcdf_lazy_grid_load)
+ {
+ grid->area = cdfPendingLoad;
+ lazyGrid->cellAreaGet.datasetNCId
+ = ncvars[ncvarid].ncid;
+ lazyGrid->cellAreaGet.varNCId
+ = ncvars[ncvarid].cellarea;
+ }
+ else
+ {
+ grid->area = (double *) Malloc(size*sizeof(double));
+ cdf_get_var_double(ncvars[ncvarid].ncid,
+ ncvars[ncvarid].cellarea,
+ grid->area);
+ }
+ }
break;
}
case GRID_SPECTRAL:
{
- grid.size = (int)size;
- grid.lcomplex = 1;
+ grid->size = (int)size;
+ grid->lcomplex = 1;
break;
}
case GRID_FOURIER:
{
- grid.size = (int)size;
+ grid->size = (int)size;
break;
}
case GRID_TRAJECTORY:
{
- grid.size = 1;
+ grid->size = 1;
break;
}
}
- grid.type = ncvars[ncvarid].gridtype;
+ if (grid->type != ncvars[ncvarid].gridtype)
+ {
+ int gridtype = ncvars[ncvarid].gridtype;
+ grid->type = gridtype;
+ cdiGridTypeInit(grid, gridtype, grid->size);
+ }
- if ( grid.size == 0 )
+ if ( grid->size == 0 )
{
if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) ||
(ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == Z_AXIS) ||
(ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS && ncvars[ncvarid].dimtype[1] == Z_AXIS) )
{
- grid.type = GRID_GENERIC;
- grid.size = 1;
- grid.xsize = 0;
- grid.ysize = 0;
+ grid->type = GRID_GENERIC;
+ grid->size = 1;
+ grid->xsize = 0;
+ grid->ysize = 0;
}
else
{
@@ -6769,18 +5476,21 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
}
}
- if ( number_of_grid_used != UNDEFID && (grid.type == UNDEFID || grid.type == GRID_GENERIC) )
- grid.type = GRID_UNSTRUCTURED;
+ if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) )
+ grid->type = GRID_UNSTRUCTURED;
- if ( number_of_grid_used != UNDEFID && grid.type == GRID_UNSTRUCTURED )
- grid.number = number_of_grid_used;
+ if ( number_of_grid_used != UNDEFID && grid->type == GRID_UNSTRUCTURED )
+ grid->number = number_of_grid_used;
if ( ncvars[ncvarid].gmapid >= 0 && ncvars[ncvarid].gridtype != GRID_CURVILINEAR )
{
+ int nvatts;
cdf_inq_varnatts(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, &nvatts);
- for ( iatt = 0; iatt < nvatts; iatt++ )
+ for ( int iatt = 0; iatt < nvatts; iatt++ )
{
+ size_t attlen;
+ char attname[CDI_MAX_NAME];
cdf_inq_attname(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, iatt, attname);
cdf_inq_attlen(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, &attlen);
@@ -6795,76 +5505,79 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
strtolower(attstring);
if ( strcmp(attstring, "rotated_latitude_longitude") == 0 )
- grid.isRotated = TRUE;
+ grid->isRotated = TRUE;
else if ( strcmp(attstring, "sinusoidal") == 0 )
- grid.type = GRID_SINUSOIDAL;
+ grid->type = GRID_SINUSOIDAL;
else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 )
- grid.type = GRID_LAEA;
+ grid->type = GRID_LAEA;
else if ( strcmp(attstring, "lambert_conformal_conic") == 0 )
- grid.type = GRID_LCC2;
+ grid->type = GRID_LCC2;
else if ( strcmp(attstring, "lambert_cylindrical_equal_area") == 0 )
{
- proj.type = GRID_PROJECTION;
- proj.name = strdup(attstring);
+ proj->type = GRID_PROJECTION;
+ proj->name = strdup(attstring);
}
}
else if ( strcmp(attname, "earth_radius") == 0 )
{
+ double datt;
cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.laea_a = datt;
- grid.lcc2_a = datt;
+ grid->laea_a = datt;
+ grid->lcc2_a = datt;
}
else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )
{
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.laea_lon_0);
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->laea_lon_0);
}
else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )
{
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.lcc2_lon_0);
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->lcc2_lon_0);
}
else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )
{
+ double datt;
cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.laea_lat_0 = datt;
- grid.lcc2_lat_0 = datt;
+ grid->laea_lat_0 = datt;
+ grid->lcc2_lat_0 = datt;
}
else if ( strcmp(attname, "standard_parallel") == 0 )
{
if ( attlen == 1 )
{
+ double datt;
cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt);
- grid.lcc2_lat_1 = datt;
- grid.lcc2_lat_2 = datt;
+ grid->lcc2_lat_1 = datt;
+ grid->lcc2_lat_2 = datt;
}
else
{
double datt2[2];
cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 2, datt2);
- grid.lcc2_lat_1 = datt2[0];
- grid.lcc2_lat_2 = datt2[1];
+ grid->lcc2_lat_1 = datt2[0];
+ grid->lcc2_lat_2 = datt2[1];
}
}
else if ( strcmp(attname, "grid_north_pole_latitude") == 0 )
{
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.ypole);
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->ypole);
}
else if ( strcmp(attname, "grid_north_pole_longitude") == 0 )
{
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.xpole);
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->xpole);
}
else if ( strcmp(attname, "north_pole_grid_longitude") == 0 )
{
- cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid.angle);
+ cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->angle);
}
}
}
- if ( grid.type == GRID_UNSTRUCTURED )
+ if ( grid->type == GRID_UNSTRUCTURED )
{
int zdimid = UNDEFID;
int xdimidx = -1, ydimidx = -1;
- for ( i = 0; i < ndims; i++ )
+ for ( int i = 0; i < ndims; i++ )
{
if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) xdimidx = i;
else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) ydimidx = i;
@@ -6873,96 +5586,100 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID )
{
- if ( grid.xsize > grid.ysize && grid.ysize < 1000 )
+ if ( grid->xsize > grid->ysize && grid->ysize < 1000 )
{
ncvars[ncvarid].dimtype[ydimidx] = Z_AXIS;
ydimid = UNDEFID;
- grid.size = grid.xsize;
- grid.ysize = 0;
+ grid->size = grid->xsize;
+ grid->ysize = 0;
}
- else if ( grid.ysize > grid.xsize && grid.xsize < 1000 )
+ else if ( grid->ysize > grid->xsize && grid->xsize < 1000 )
{
ncvars[ncvarid].dimtype[xdimidx] = Z_AXIS;
xdimid = ydimid;
ydimid = UNDEFID;
- grid.size = grid.ysize;
- grid.xsize = grid.ysize;
- grid.ysize = 0;
+ grid->size = grid->ysize;
+ grid->xsize = grid->ysize;
+ grid->ysize = 0;
}
}
- if ( grid.size != grid.xsize )
+ if ( grid->size != grid->xsize )
{
Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name);
ncvars[ncvarid].isvar = -1;
continue;
}
- if ( ncvars[ncvarid].position > 0 ) grid.position = ncvars[ncvarid].position;
- if ( uuidOfHGrid[0] != 0 ) memcpy(grid.uuid, uuidOfHGrid, 16);
+ if ( ncvars[ncvarid].position > 0 ) grid->position = ncvars[ncvarid].position;
+ if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16);
}
#if defined (PROJECTION_TEST)
- if ( proj.type == GRID_PROJECTION )
+ if ( proj->type == GRID_PROJECTION )
{
- if ( grid.type == GRID_GENERIC )
+ if ( grid->type == GRID_GENERIC )
{
- grid.type = GRID_CURVILINEAR;
+ grid->type = GRID_CURVILINEAR;
}
- if ( grid.type == GRID_CURVILINEAR )
+ if ( grid->type == GRID_CURVILINEAR )
{
- proj.size = grid.size;
- proj.xsize = grid.xsize;
- proj.ysize = grid.ysize;
+ proj->size = grid->size;
+ proj->xsize = grid->xsize;
+ proj->ysize = grid->ysize;
}
- // grid.proj = gridGenerate(proj);
+ // grid->proj = gridGenerate(proj);
}
#endif
if ( CDI_Debug )
{
Message("grid: type = %d, size = %d, nx = %d, ny %d",
- grid.type, grid.size, grid.xsize, grid.ysize);
+ grid->type, grid->size, grid->xsize, grid->ysize);
Message("proj: type = %d, size = %d, nx = %d, ny %d",
- proj.type, proj.size, proj.xsize, proj.ysize);
+ proj->type, proj->size, proj->xsize, proj->ysize);
}
#if defined (PROJECTION_TEST)
- if ( proj.type == GRID_PROJECTION )
+ if ( proj->type == GRID_PROJECTION )
{
- ncvars[ncvarid].gridID = varDefGrid(vlistID, &proj, 1);
+ projAdded = cdiVlistAddGridIfNew(vlistID, proj, 1);
+ ncvars[ncvarid].gridID = projAdded.Id;
copy_numeric_projatts(ncvars[ncvarid].gridID, ncvars[ncvarid].gmapid, ncvars[ncvarid].ncid);
}
else
#endif
- ncvars[ncvarid].gridID = varDefGrid(vlistID, &grid, 1);
+ {
+ gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1);
+ ncvars[ncvarid].gridID = gridAdded.Id;
+ }
- if ( grid.type == GRID_UNSTRUCTURED )
+ if ( grid->type == GRID_UNSTRUCTURED )
{
if ( gridfile[0] != 0 ) gridDefReference(ncvars[ncvarid].gridID, gridfile);
}
- if ( ncvars[ncvarid].chunked ) grid_set_chunktype(&grid, &ncvars[ncvarid]);
+ if ( ncvars[ncvarid].chunked ) grid_set_chunktype(grid, &ncvars[ncvarid]);
- gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID);
+ int gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID);
streamptr->xdimID[gridindex] = xdimid;
streamptr->ydimID[gridindex] = ydimid;
- if ( xdimid == -1 && ydimid == -1 && grid.size == 1 )
+ if ( xdimid == -1 && ydimid == -1 && grid->size == 1 )
gridDefHasDims(ncvars[ncvarid].gridID, FALSE);
if ( CDI_Debug )
Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name);
- for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
+ for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ )
if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].gridID == UNDEFID )
{
int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID;
int xdimidx = -1, ydimidx = -1;
int ndims2 = ncvars[ncvarid2].ndims;
- for ( i = 0; i < ndims2; i++ )
+ for ( int i = 0; i < ndims2; i++ )
{
if ( ncvars[ncvarid2].dimtype[i] == X_AXIS )
{ xdimid2 = ncvars[ncvarid2].dimids[i]; xdimidx = i; }
@@ -6972,7 +5689,7 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
{ zdimid2 = ncvars[ncvarid2].dimids[i]; }
}
- if ( ncvars[ncvarid2].gridtype == UNDEFID && grid.type == GRID_UNSTRUCTURED )
+ if ( ncvars[ncvarid2].gridtype == UNDEFID && grid->type == GRID_UNSTRUCTURED )
{
if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID )
{
@@ -6991,7 +5708,9 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( xdimid == xdimid2 &&
(ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) )
{
- int same_grid = TRUE;
+ int same_grid = ncvars[ncvarid].xvarid == ncvars[ncvarid2].xvarid
+ && ncvars[ncvarid].yvarid == ncvars[ncvarid2].yvarid
+ && ncvars[ncvarid].position == ncvars[ncvarid2].position;
/*
if ( xvarid != -1 && ncvars[ncvarid2].xvarid != UNDEFID &&
xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
@@ -6999,10 +5718,6 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
if ( yvarid != -1 && ncvars[ncvarid2].yvarid != UNDEFID &&
yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
*/
- if ( ncvars[ncvarid].xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE;
- if ( ncvars[ncvarid].yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE;
-
- if ( ncvars[ncvarid].position != ncvars[ncvarid2].position ) same_grid = FALSE;
if ( same_grid )
{
@@ -7014,10 +5729,26 @@ void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nva
}
}
- grid_free(&grid);
- grid_free(&proj);
+ if (gridAdded.isNew)
+ lazyGrid = NULL;
+ if (projAdded.isNew)
+ lazyProj = NULL;
}
}
+ if (lazyGrid)
+ {
+ if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyGrid);
+ grid_free(grid);
+ Free(grid);
+ }
+ if (lazyProj)
+ {
+ if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyProj);
+ grid_free(proj);
+ Free(proj);
+ }
+#undef proj
+#undef grid
}
/* define all input zaxes */
@@ -7227,6 +5958,10 @@ int cmpvarname(const void *s1, const void *s2)
static
void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars)
{
+ if ( CDI_Debug )
+ {
+ for(int i = 0; i < nvars; i++) Message("varids[%d] = %d", i, varids[i]);
+ }
if ( streamptr->sortname )
{
struct varinfo *varInfo
@@ -7244,6 +5979,10 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
varids[varID] = varInfo[varID].ncvarid;
}
Free(varInfo);
+ if ( CDI_Debug )
+ {
+ for(int i = 0; i < nvars; i++) Message("sorted varids[%d] = %d", i, varids[i]);
+ }
}
for ( int varID1 = 0; varID1 < nvars; varID1++ )
@@ -7572,13 +6311,13 @@ void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ng
else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 )
{
attstring[36] = 0;
- str2uuid(attstring, uuidOfHGrid);
+ cdiStr2UUID(attstring, uuidOfHGrid);
// printf("uuid: %d %s\n", attlen, attstring);
}
else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 )
{
attstring[36] = 0;
- str2uuid(attstring, uuidOfVGrid);
+ cdiStr2UUID(attstring, uuidOfVGrid);
}
else
{
@@ -8407,144 +7146,6 @@ int cdfInqTimestep(stream_t * streamptr, int tsID)
}
-void cdfEndDef(stream_t *streamptr)
-{
- int varID;
- int nvars;
- int fileID;
-
- fileID = streamptr->fileID;
-
- cdfDefGlobalAtts(streamptr);
- cdfDefLocalAtts(streamptr);
-
- if ( streamptr->accessmode == 0 )
- {
- nvars = streamptr->nvars;
-
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- for ( varID = 0; varID < nvars; varID++ )
- cdfDefVar(streamptr, varID);
-
- if ( streamptr->ncmode == 2 )
- {
- if ( CDI_netcdf_hdr_pad == 0UL )
- cdf_enddef(fileID);
- else
- cdf__enddef(fileID, CDI_netcdf_hdr_pad);
- }
-
- streamptr->accessmode = 1;
- }
-}
-
-
-static void cdfDefInstitut(stream_t *streamptr)
-{
- int fileID, instID;
- size_t len;
- int vlistID;
-
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- instID = vlistInqInstitut(vlistID);
-
- if ( instID != UNDEFID )
- {
- const char *longname = institutInqLongnamePtr(instID);
- if ( longname )
- {
- len = strlen(longname);
- if ( len > 0 )
- {
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_put_att_text(fileID, NC_GLOBAL, "institution", len, longname);
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
- }
- }
- }
-}
-
-
-static void cdfDefSource(stream_t *streamptr)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int modelID = vlistInqModel(vlistID);
-
- if ( modelID != UNDEFID )
- {
- const char *longname = modelInqNamePtr(modelID);
- if ( longname )
- {
- size_t len = strlen(longname);
- if ( len > 0 )
- {
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
- cdf_put_att_text(fileID, NC_GLOBAL, "source", len, longname);
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
- }
- }
- }
-}
-
-
-static void cdfDefGlobalAtts(stream_t *streamptr)
-{
- int natts;
-
- if ( streamptr->globalatts ) return;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- cdfDefSource(streamptr);
- cdfDefInstitut(streamptr);
-
- vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
-
- if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- defineAttributes(vlistID, CDI_GLOBAL, fileID, NC_GLOBAL);
-
- if ( natts > 0 && streamptr->ncmode == 2 ) cdf_enddef(fileID);
-
- streamptr->globalatts = 1;
-}
-
-
-static void cdfDefLocalAtts(stream_t *streamptr)
-{
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
-
- if ( streamptr->localatts ) return;
- if ( vlistInqInstitut(vlistID) != UNDEFID ) return;
-
- streamptr->localatts = 1;
-
- if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
-
- for ( int varID = 0; varID < streamptr->nvars; varID++ )
- {
- int instID = vlistInqVarInstitut(vlistID, varID);
- if ( instID != UNDEFID )
- {
- int ncvarid = streamptr->vars[varID].ncvarid;
- const char *name = institutInqNamePtr(instID);
- if ( name )
- {
- size_t len = strlen(name);
- cdf_put_att_text(fileID, ncvarid, "institution", len, name);
- }
- }
- }
-
- if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
-}
-
-
void cdfDefHistory(stream_t *streamptr, int size, const char *history)
{
int ncid = streamptr->fileID;
@@ -8567,7 +7168,22 @@ void cdfInqHistoryString(stream_t *streamptr, char *history)
{
int ncid = streamptr->fileID;
if ( streamptr->historyID != UNDEFID )
- cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
+ {
+ nc_type atttype;
+ cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype);
+
+ if ( atttype == NC_CHAR )
+ {
+ cdf_get_att_text(ncid, NC_GLOBAL, "history", history);
+ }
+#if defined (HAVE_NETCDF4)
+ else if ( atttype == NC_STRING )
+ {
+ // ToDo
+ Warning("History attribute with type NC_STRING unsupported!");
+ }
+#endif
+ }
}
diff --git a/libcdi/src/stream_cdf.h b/libcdi/src/stream_cdf.h
index 47241e2..c0228b8 100644
--- a/libcdi/src/stream_cdf.h
+++ b/libcdi/src/stream_cdf.h
@@ -14,21 +14,21 @@ void cdfDefRecord(stream_t * streamptr);
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss);
+void cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss);
void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
-void cdfReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss);
-void cdfReadVarSP(stream_t *streamptr, int varID, float *data, int *nmiss);
-
+void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss);
void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
-void cdfReadVarSliceDP(stream_t *streamptr, int varID, int levelID, double *data, int *nmiss);
-void cdfReadVarSliceSP(stream_t *streamptr, int varID, int levelID, float *data, int *nmiss);
+void cdf_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss);
void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
const int rect[][2], const void *data, int nmiss);
+void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level);
+void cdfDefTime(stream_t* streamptr);
+
#endif
/*
* Local Variables:
diff --git a/libcdi/src/stream_cgribex.c b/libcdi/src/stream_cgribex.c
index 693c772..445e4a9 100644
--- a/libcdi/src/stream_cgribex.c
+++ b/libcdi/src/stream_cgribex.c
@@ -4,7 +4,6 @@
#include <limits.h>
#include <stdio.h>
-// #include <float.h> /* FLT_EPSILON */
#include "dmemory.h"
#include "cdi.h"
@@ -168,7 +167,8 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4,
compyinc = FALSE;
}
- memset(grid, 0, sizeof(grid_t));
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, 0);
switch (gridtype)
{
case GRID_LONLAT:
@@ -362,7 +362,7 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
{
int varID;
int levelID = 0;
- grid_t grid;
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
int vlistID = streamptr->vlistID;
int tsID = streamptr->curTsID;
@@ -383,11 +383,13 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
record->ilevel = level1;
record->ilevel2 = level2;
record->ltype = ISEC1_LevelType;
- record->tsteptype = tsteptype;
+ record->tsteptype = (short)tsteptype;
- cgribexGetGrid(streamptr, isec2, fsec2, isec4, &grid, iret);
+ cgribexGetGrid(streamptr, isec2, fsec2, isec4, grid, iret);
- int gridID = varDefGrid(vlistID, &grid, 0);
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
int zaxistype = grib1ltypeToZaxisType(ISEC1_LevelType);
@@ -1308,12 +1310,13 @@ int cgribexScanTimestep(stream_t * streamptr)
#endif
#if defined (HAVE_LIBCGRIBEX)
-int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
+int cgribexDecode(int memtype, void *gribbuffer, int gribsize, void *data, long datasize,
int unreduced, int *nmiss, double missval)
{
int status = 0;
int iret = 0, iword = 0;
int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
+ float fsec2f[512], fsec3f[2];
double fsec2[512], fsec3[2];
char hoper[2];
@@ -1322,8 +1325,12 @@ int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
FSEC3_MissVal = missval;
- gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, data,
- gridsize, (int *)(void *)gribbuffer, gribsize, &iword, hoper, &iret);
+ if ( memtype == MEMTYPE_FLOAT )
+ gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, hoper, &iret);
+ else
+ gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, hoper, &iret);
if ( ISEC1_Sec2Or3Flag & 64 )
*nmiss = ISEC4_NumValues - ISEC4_NumNonMissValues;
@@ -1333,19 +1340,30 @@ int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
{
double undef_pds, undef_eps;
- int i;
-
MCH_get_undef(isec1, &undef_pds, &undef_eps);
*nmiss = 0;
- for ( i = 0; i < gridsize; i++ )
- if ( (fabs(data[i]-undef_pds) < undef_eps) || IS_EQUAL(data[i],FSEC3_MissVal) ) {
- data[i] = missval;
- (*nmiss)++;
+ if ( memtype == MEMTYPE_FLOAT )
+ {
+ float *restrict dataf = (float*) data;
+ for ( long i = 0; i < datasize; i++ )
+ if ( (fabs(dataf[i]-undef_pds) < undef_eps) || IS_EQUAL(dataf[i],FSEC3_MissVal) ) {
+ dataf[i] = (float)missval;
+ (*nmiss)++;
+ }
+ }
+ else
+ {
+ double *restrict datad = (double*) data;
+ for ( long i = 0; i < datasize; i++ )
+ if ( (fabs(datad[i]-undef_pds) < undef_eps) || IS_EQUAL(datad[i],FSEC3_MissVal) ) {
+ datad[i] = missval;
+ (*nmiss)++;
+ }
}
}
- return (status);
+ return status;
}
#endif
@@ -1534,10 +1552,17 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
rtime = taxisInqRtime(taxisID);
factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
-
timerange = cgribexDefTimerange(tsteptype, factor, calendar,
rdate, rtime, vdate, vtime, &ip1, &ip2);
+ if ( ip2 > 0xFF && timeunit < TUNIT_YEAR )
+ {
+ timeunit++;
+ factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
+ timerange = cgribexDefTimerange(tsteptype, factor, calendar,
+ rdate, rtime, vdate, vtime, &ip1, &ip2);
+ }
+
if ( timerange == -1 || timerange == 3 )
{
timetype = TAXIS_ABSOLUTE;
@@ -1714,8 +1739,6 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
ISEC2_LonIncr = (int)lround(xinc*1000);
}
- // if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON ) ISEC2_LonIncr = 0;
-
if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
{
int np = gridInqNP(gridID);
@@ -1725,8 +1748,6 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
else
{
ISEC2_LatIncr = (int)lround(yinc*1000);
- // if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON ) ISEC2_LatIncr = 0;
-
if ( ISEC2_LatIncr < 0 ) ISEC2_LatIncr = -ISEC2_LatIncr;
}
@@ -1760,12 +1781,12 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
}
case GRID_LCC:
{
- double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
- int xsize, ysize;
- int projflag, scanflag;
+ double originLon = 0.0, originLat = 0.0, lonParY = 0.0,
+ lat1 = 0.0, lat2 = 0.0, xincm = 0.0, yincm = 0.0;
+ int projflag = 0, scanflag = 0;
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ int xsize = gridInqXsize(gridID),
+ ysize = gridInqYsize(gridID);
gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
&projflag, &scanflag);
@@ -1781,7 +1802,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
ISEC2_Lambert_dx = (int)lround(xincm);
ISEC2_Lambert_dy = (int)lround(yincm);
ISEC2_Lambert_LatSP = 0;
- ISEC2_Lambert_LatSP = 0;
+ ISEC2_Lambert_LonSP = 0;
ISEC2_Lambert_ProjFlag = projflag;
ISEC2_ScanFlag = scanflag;
@@ -1839,7 +1860,6 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
{
double level;
int ilevel, zaxistype, ltype;
- static bool lwarning = true;
static bool lwarning_vct = true;
zaxistype = zaxisInqType(zaxisID);
@@ -1934,11 +1954,6 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
}
vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && lwarning )
- {
- Warning("VCT missing. ( param = %d, zaxisID = %d )", ISEC1_Parameter, zaxisID);
- lwarning = false;
- }
if ( vctsize > 255 )
{
ISEC2_NumVCP = 0;
@@ -1986,6 +2001,15 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
{
level = zaxisInqLevel(zaxisID, levelID);
+ char units[128];
+ zaxisInqUnits(zaxisID, units);
+ if ( units[1] == 'm' && !units[2] )
+ {
+ if ( units[0] == 'c' ) level *= 0.01;
+ else if ( units[0] == 'd' ) level *= 0.1;
+ else if ( units[0] == 'k' ) level *= 1000;
+ }
+
ilevel = (int) level;
ISEC1_LevelType = GRIB1_LTYPE_HEIGHT;
ISEC1_Level1 = ilevel;
@@ -2116,9 +2140,7 @@ void cgribexDefaultSec1(int *isec1)
static
void cgribexDefaultSec4(int *isec4)
{
- long i;
-
- for ( i = 2; i <= 10; ++i ) isec4[i] = 0;
+ for ( int i = 2; i <= 10; ++i ) isec4[i] = 0;
}
static
@@ -2153,7 +2175,7 @@ void cgribexDefEnsembleVar(int *isec1, int vlistID, int varID)
#if defined (HAVE_LIBCGRIBEX)
size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize)
+ long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize)
{
size_t nbytes = 0;
int gribsize;
@@ -2198,7 +2220,10 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
if ( isec4[2] == 128 && isec4[3] == 64 )
{
- isec4[16] = (int) (1000*calculate_pfactor(data, ISEC2_PentaJ, isec4[17]));
+ if ( memtype == MEMTYPE_FLOAT )
+ isec4[16] = (int) (1000*calculate_pfactor_float((const float*) data, ISEC2_PentaJ, isec4[17]));
+ else
+ isec4[16] = (int) (1000*calculate_pfactor_double((const double*) data, ISEC2_PentaJ, isec4[17]));
if ( isec4[16] < -10000 ) isec4[16] = -10000;
if ( isec4[16] > 10000 ) isec4[16] = 10000;
}
@@ -2213,15 +2238,15 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
if ( memtype == MEMTYPE_FLOAT )
gribExSP(isec0, isec1, isec2, fsec2f, isec3, fsec3f, isec4, (float*) data,
- (int)datasize, (int *)(void *)gribbuffer, gribsize, &iword, "C", &iret);
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, "C", &iret);
else
gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, (double*) data,
- (int)datasize, (int *)(void *)gribbuffer, gribsize, &iword, "C", &iret);
+ (int) datasize, (int*) gribbuffer, gribsize, &iword, "C", &iret);
if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
nbytes = (size_t)iword * sizeof (int);
- return (nbytes);
+ return nbytes;
}
#endif
/*
diff --git a/libcdi/src/stream_cgribex.h b/libcdi/src/stream_cgribex.h
index 6fef957..43f3525 100644
--- a/libcdi/src/stream_cgribex.h
+++ b/libcdi/src/stream_cgribex.h
@@ -5,12 +5,12 @@ int cgribexScanTimestep1(stream_t * streamptr);
int cgribexScanTimestep2(stream_t * streamptr);
int cgribexScanTimestep(stream_t * streamptr);
-int cgribexDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
+int cgribexDecode(int memtype, void *gribbuffer, int gribsize, void *data, long datasize,
int unreduced, int *nmiss, double missval);
size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char *gribbuffer, size_t gribbuffersize);
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize);
#endif /* _STREAM_CGRIBEX_H */
/*
diff --git a/libcdi/src/stream_ext.c b/libcdi/src/stream_ext.c
index 0aaa821..048de70 100644
--- a/libcdi/src/stream_ext.c
+++ b/libcdi/src/stream_ext.c
@@ -206,44 +206,38 @@ static
void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
size_t recsize, off_t position, int prec, int number)
{
- int leveltype;
- int gridID = CDI_UNDEFID;
- int levelID = 0;
- int tsID, recID, varID;
- record_t *record;
- grid_t grid;
- int vlistID;
-
- vlistID = streamptr->vlistID;
- tsID = streamptr->curTsID;
- recID = recordNewEntry(streamptr, tsID);
- record = &streamptr->tsteps[tsID].records[recID];
-
- (*record).size = recsize;
- (*record).position = position;
- (*record).param = param;
- (*record).ilevel = level;
-
- memset(&grid, 0, sizeof(grid_t));
- grid.type = GRID_GENERIC;
- grid.size = xysize;
- grid.xsize = xysize;
- grid.ysize = 0;
- grid.xvals = NULL;
- grid.yvals = NULL;
- gridID = varDefGrid(vlistID, &grid, 0);
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
+
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level;
+
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, GRID_GENERIC, xysize);
+ grid->xsize = xysize;
+ grid->ysize = 0;
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
/*
if ( level == 0 ) leveltype = ZAXIS_SURFACE;
else leveltype = ZAXIS_GENERIC;
*/
- leveltype = ZAXIS_GENERIC;
+ int leveltype = ZAXIS_GENERIC;
+ int varID, levelID = 0;
varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
- extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
+ extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
NULL, NULL, NULL, NULL, NULL, NULL);
-
- (*record).varID = (short)varID;
- (*record).levelID = (short)levelID;
+ record->varID = (short)varID;
+ record->levelID = (short)levelID;
streamptr->tsteps[tsID].nallrecs++;
streamptr->nrecs++;
diff --git a/libcdi/src/stream_fcommon.c b/libcdi/src/stream_fcommon.c
index 7198c90..482a031 100644
--- a/libcdi/src/stream_fcommon.c
+++ b/libcdi/src/stream_fcommon.c
@@ -5,10 +5,9 @@
#include "file.h"
#include "stream_fcommon.h"
-void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1,
- const char *container_name)
-{
+void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name)
+{
int fileID1 = streamptr1->fileID;
int fileID2 = streamptr2->fileID;
diff --git a/libcdi/src/stream_grb.c b/libcdi/src/stream_grb.c
index f619ab1..a56313a 100644
--- a/libcdi/src/stream_grb.c
+++ b/libcdi/src/stream_grb.c
@@ -1,11 +1,7 @@
-#if defined (HAVE_CONFIG_H)
-# include "config.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
#endif
-#include <stdio.h>
-#include <string.h>
-
-#include "dmemory.h"
#include "cdi.h"
#include "cdi_int.h"
#include "stream_cgribex.h"
@@ -14,8 +10,6 @@
#include "file.h"
#include "cgribex.h" /* gribZip gribGetZip gribGinfo */
#include "gribapi.h"
-#include "namespace.h"
-
int grib1ltypeToZaxisType(int grib_ltype)
@@ -24,34 +18,34 @@ int grib1ltypeToZaxisType(int grib_ltype)
switch ( grib_ltype )
{
- case GRIB1_LTYPE_SURFACE: { zaxistype = ZAXIS_SURFACE; break; }
- case GRIB1_LTYPE_CLOUD_BASE: { zaxistype = ZAXIS_CLOUD_BASE; break; }
- case GRIB1_LTYPE_CLOUD_TOP: { zaxistype = ZAXIS_CLOUD_TOP; break; }
- case GRIB1_LTYPE_ISOTHERM0: { zaxistype = ZAXIS_ISOTHERM_ZERO; break; }
- case GRIB1_LTYPE_TOA: { zaxistype = ZAXIS_TOA; break; }
- case GRIB1_LTYPE_SEA_BOTTOM: { zaxistype = ZAXIS_SEA_BOTTOM; break; }
- case GRIB1_LTYPE_ATMOSPHERE: { zaxistype = ZAXIS_ATMOSPHERE; break; }
- case GRIB1_LTYPE_MEANSEA: { zaxistype = ZAXIS_MEANSEA; break; }
+ case GRIB1_LTYPE_SURFACE: zaxistype = ZAXIS_SURFACE; break;
+ case GRIB1_LTYPE_CLOUD_BASE: zaxistype = ZAXIS_CLOUD_BASE; break;
+ case GRIB1_LTYPE_CLOUD_TOP: zaxistype = ZAXIS_CLOUD_TOP; break;
+ case GRIB1_LTYPE_ISOTHERM0: zaxistype = ZAXIS_ISOTHERM_ZERO; break;
+ case GRIB1_LTYPE_TOA: zaxistype = ZAXIS_TOA; break;
+ case GRIB1_LTYPE_SEA_BOTTOM: zaxistype = ZAXIS_SEA_BOTTOM; break;
+ case GRIB1_LTYPE_ATMOSPHERE: zaxistype = ZAXIS_ATMOSPHERE; break;
+ case GRIB1_LTYPE_MEANSEA: zaxistype = ZAXIS_MEANSEA; break;
case GRIB1_LTYPE_99:
- case GRIB1_LTYPE_ISOBARIC: { zaxistype = ZAXIS_PRESSURE; break; }
- case GRIB1_LTYPE_HEIGHT: { zaxistype = ZAXIS_HEIGHT; break; }
- case GRIB1_LTYPE_ALTITUDE: { zaxistype = ZAXIS_ALTITUDE; break; }
+ case GRIB1_LTYPE_ISOBARIC: zaxistype = ZAXIS_PRESSURE; break;
+ case GRIB1_LTYPE_HEIGHT: zaxistype = ZAXIS_HEIGHT; break;
+ case GRIB1_LTYPE_ALTITUDE: zaxistype = ZAXIS_ALTITUDE; break;
case GRIB1_LTYPE_SIGMA:
- case GRIB1_LTYPE_SIGMA_LAYER: { zaxistype = ZAXIS_SIGMA; break; }
+ case GRIB1_LTYPE_SIGMA_LAYER: zaxistype = ZAXIS_SIGMA; break;
case GRIB1_LTYPE_HYBRID:
- case GRIB1_LTYPE_HYBRID_LAYER: { zaxistype = ZAXIS_HYBRID; break; }
+ case GRIB1_LTYPE_HYBRID_LAYER: zaxistype = ZAXIS_HYBRID; break;
case GRIB1_LTYPE_LANDDEPTH:
- case GRIB1_LTYPE_LANDDEPTH_LAYER: { zaxistype = ZAXIS_DEPTH_BELOW_LAND; break; }
- case GRIB1_LTYPE_ISENTROPIC: { zaxistype = ZAXIS_ISENTROPIC; break; }
- case GRIB1_LTYPE_SEADEPTH: { zaxistype = ZAXIS_DEPTH_BELOW_SEA; break; }
- case GRIB1_LTYPE_LAKE_BOTTOM: { zaxistype = ZAXIS_LAKE_BOTTOM; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM: { zaxistype = ZAXIS_SEDIMENT_BOTTOM; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break; }
- case GRIB1_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break; }
- case GRIB1_LTYPE_MIX_LAYER: { zaxistype = ZAXIS_MIX_LAYER; break; }
+ case GRIB1_LTYPE_LANDDEPTH_LAYER: zaxistype = ZAXIS_DEPTH_BELOW_LAND; break;
+ case GRIB1_LTYPE_ISENTROPIC: zaxistype = ZAXIS_ISENTROPIC; break;
+ case GRIB1_LTYPE_SEADEPTH: zaxistype = ZAXIS_DEPTH_BELOW_SEA; break;
+ case GRIB1_LTYPE_LAKE_BOTTOM: zaxistype = ZAXIS_LAKE_BOTTOM; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM: zaxistype = ZAXIS_SEDIMENT_BOTTOM; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM_TA: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break;
+ case GRIB1_LTYPE_SEDIMENT_BOTTOM_TW: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break;
+ case GRIB1_LTYPE_MIX_LAYER: zaxistype = ZAXIS_MIX_LAYER; break;
}
- return (zaxistype);
+ return zaxistype;
}
@@ -61,34 +55,34 @@ int grib2ltypeToZaxisType(int grib_ltype)
switch ( grib_ltype )
{
- case GRIB2_LTYPE_SURFACE: { zaxistype = ZAXIS_SURFACE; break; }
- case GRIB2_LTYPE_CLOUD_BASE: { zaxistype = ZAXIS_CLOUD_BASE; break; }
- case GRIB2_LTYPE_CLOUD_TOP: { zaxistype = ZAXIS_CLOUD_TOP; break; }
- case GRIB2_LTYPE_ISOTHERM0: { zaxistype = ZAXIS_ISOTHERM_ZERO; break; }
- case GRIB2_LTYPE_TOA: { zaxistype = ZAXIS_TOA; break; }
- case GRIB2_LTYPE_SEA_BOTTOM: { zaxistype = ZAXIS_SEA_BOTTOM; break; }
- case GRIB2_LTYPE_ATMOSPHERE: { zaxistype = ZAXIS_ATMOSPHERE; break; }
- case GRIB2_LTYPE_MEANSEA: { zaxistype = ZAXIS_MEANSEA; break; }
- case GRIB2_LTYPE_ISOBARIC: { zaxistype = ZAXIS_PRESSURE; break; }
- case GRIB2_LTYPE_HEIGHT: { zaxistype = ZAXIS_HEIGHT; break; }
- case GRIB2_LTYPE_ALTITUDE: { zaxistype = ZAXIS_ALTITUDE; break; }
- case GRIB2_LTYPE_SIGMA: { zaxistype = ZAXIS_SIGMA; break; }
+ case GRIB2_LTYPE_SURFACE: zaxistype = ZAXIS_SURFACE; break;
+ case GRIB2_LTYPE_CLOUD_BASE: zaxistype = ZAXIS_CLOUD_BASE; break;
+ case GRIB2_LTYPE_CLOUD_TOP: zaxistype = ZAXIS_CLOUD_TOP; break;
+ case GRIB2_LTYPE_ISOTHERM0: zaxistype = ZAXIS_ISOTHERM_ZERO; break;
+ case GRIB2_LTYPE_TOA: zaxistype = ZAXIS_TOA; break;
+ case GRIB2_LTYPE_SEA_BOTTOM: zaxistype = ZAXIS_SEA_BOTTOM; break;
+ case GRIB2_LTYPE_ATMOSPHERE: zaxistype = ZAXIS_ATMOSPHERE; break;
+ case GRIB2_LTYPE_MEANSEA: zaxistype = ZAXIS_MEANSEA; break;
+ case GRIB2_LTYPE_ISOBARIC: zaxistype = ZAXIS_PRESSURE; break;
+ case GRIB2_LTYPE_HEIGHT: zaxistype = ZAXIS_HEIGHT; break;
+ case GRIB2_LTYPE_ALTITUDE: zaxistype = ZAXIS_ALTITUDE; break;
+ case GRIB2_LTYPE_SIGMA: zaxistype = ZAXIS_SIGMA; break;
case GRIB2_LTYPE_HYBRID:
- /* case GRIB2_LTYPE_HYBRID_LAYER: */ { zaxistype = ZAXIS_HYBRID; break; }
+ /* case GRIB2_LTYPE_HYBRID_LAYER: */ zaxistype = ZAXIS_HYBRID; break;
case GRIB2_LTYPE_LANDDEPTH:
- /* case GRIB2_LTYPE_LANDDEPTH_LAYER: */ { zaxistype = ZAXIS_DEPTH_BELOW_LAND; break; }
- case GRIB2_LTYPE_ISENTROPIC: { zaxistype = ZAXIS_ISENTROPIC; break; }
- case GRIB2_LTYPE_SNOW: { zaxistype = ZAXIS_SNOW; break; }
- case GRIB2_LTYPE_SEADEPTH: { zaxistype = ZAXIS_DEPTH_BELOW_SEA; break; }
- case GRIB2_LTYPE_LAKE_BOTTOM: { zaxistype = ZAXIS_LAKE_BOTTOM; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM: { zaxistype = ZAXIS_SEDIMENT_BOTTOM; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break; }
- case GRIB2_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break; }
- case GRIB2_LTYPE_MIX_LAYER: { zaxistype = ZAXIS_MIX_LAYER; break; }
- case GRIB2_LTYPE_REFERENCE: { zaxistype = ZAXIS_REFERENCE; break; }
+ /* case GRIB2_LTYPE_LANDDEPTH_LAYER: */ zaxistype = ZAXIS_DEPTH_BELOW_LAND; break;
+ case GRIB2_LTYPE_ISENTROPIC: zaxistype = ZAXIS_ISENTROPIC; break;
+ case GRIB2_LTYPE_SNOW: zaxistype = ZAXIS_SNOW; break;
+ case GRIB2_LTYPE_SEADEPTH: zaxistype = ZAXIS_DEPTH_BELOW_SEA; break;
+ case GRIB2_LTYPE_LAKE_BOTTOM: zaxistype = ZAXIS_LAKE_BOTTOM; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM: zaxistype = ZAXIS_SEDIMENT_BOTTOM; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM_TA: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; break;
+ case GRIB2_LTYPE_SEDIMENT_BOTTOM_TW: zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; break;
+ case GRIB2_LTYPE_MIX_LAYER: zaxistype = ZAXIS_MIX_LAYER; break;
+ case GRIB2_LTYPE_REFERENCE: zaxistype = ZAXIS_REFERENCE; break;
}
- return (zaxistype);
+ return zaxistype;
}
@@ -98,27 +92,27 @@ int zaxisTypeToGrib1ltype(int zaxistype)
switch (zaxistype)
{
- case ZAXIS_SURFACE: { grib_ltype = GRIB1_LTYPE_SURFACE; break; }
- case ZAXIS_MEANSEA: { grib_ltype = GRIB1_LTYPE_MEANSEA; break; }
- case ZAXIS_HEIGHT: { grib_ltype = GRIB1_LTYPE_HEIGHT; break; }
- case ZAXIS_ALTITUDE: { grib_ltype = GRIB1_LTYPE_ALTITUDE; break; }
- case ZAXIS_SIGMA: { grib_ltype = GRIB1_LTYPE_SIGMA; break; }
- case ZAXIS_DEPTH_BELOW_SEA: { grib_ltype = GRIB1_LTYPE_SEADEPTH; break; }
- case ZAXIS_ISENTROPIC: { grib_ltype = GRIB1_LTYPE_ISENTROPIC; break; }
- case ZAXIS_CLOUD_BASE: { grib_ltype = GRIB1_LTYPE_CLOUD_BASE; break; }
- case ZAXIS_CLOUD_TOP: { grib_ltype = GRIB1_LTYPE_CLOUD_TOP; break; }
- case ZAXIS_ISOTHERM_ZERO: { grib_ltype = GRIB1_LTYPE_ISOTHERM0; break; }
- case ZAXIS_TOA: { grib_ltype = GRIB1_LTYPE_TOA; break; }
- case ZAXIS_SEA_BOTTOM: { grib_ltype = GRIB1_LTYPE_SEA_BOTTOM; break; }
- case ZAXIS_LAKE_BOTTOM: { grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TA: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TW: { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break; }
- case ZAXIS_MIX_LAYER: { grib_ltype = GRIB1_LTYPE_MIX_LAYER; break; }
- case ZAXIS_ATMOSPHERE: { grib_ltype = GRIB1_LTYPE_ATMOSPHERE; break; }
+ case ZAXIS_SURFACE: grib_ltype = GRIB1_LTYPE_SURFACE; break;
+ case ZAXIS_MEANSEA: grib_ltype = GRIB1_LTYPE_MEANSEA; break;
+ case ZAXIS_HEIGHT: grib_ltype = GRIB1_LTYPE_HEIGHT; break;
+ case ZAXIS_ALTITUDE: grib_ltype = GRIB1_LTYPE_ALTITUDE; break;
+ case ZAXIS_SIGMA: grib_ltype = GRIB1_LTYPE_SIGMA; break;
+ case ZAXIS_DEPTH_BELOW_SEA: grib_ltype = GRIB1_LTYPE_SEADEPTH; break;
+ case ZAXIS_ISENTROPIC: grib_ltype = GRIB1_LTYPE_ISENTROPIC; break;
+ case ZAXIS_CLOUD_BASE: grib_ltype = GRIB1_LTYPE_CLOUD_BASE; break;
+ case ZAXIS_CLOUD_TOP: grib_ltype = GRIB1_LTYPE_CLOUD_TOP; break;
+ case ZAXIS_ISOTHERM_ZERO: grib_ltype = GRIB1_LTYPE_ISOTHERM0; break;
+ case ZAXIS_TOA: grib_ltype = GRIB1_LTYPE_TOA; break;
+ case ZAXIS_SEA_BOTTOM: grib_ltype = GRIB1_LTYPE_SEA_BOTTOM; break;
+ case ZAXIS_LAKE_BOTTOM: grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TA: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TW: grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break;
+ case ZAXIS_MIX_LAYER: grib_ltype = GRIB1_LTYPE_MIX_LAYER; break;
+ case ZAXIS_ATMOSPHERE: grib_ltype = GRIB1_LTYPE_ATMOSPHERE; break;
}
- return (grib_ltype);
+ return grib_ltype;
}
@@ -128,27 +122,27 @@ int zaxisTypeToGrib2ltype(int zaxistype)
switch (zaxistype)
{
- case ZAXIS_SURFACE: { grib_ltype = GRIB2_LTYPE_SURFACE; break; }
- case ZAXIS_MEANSEA: { grib_ltype = GRIB2_LTYPE_MEANSEA; break; }
- case ZAXIS_HEIGHT: { grib_ltype = GRIB2_LTYPE_HEIGHT; break; }
- case ZAXIS_ALTITUDE: { grib_ltype = GRIB2_LTYPE_ALTITUDE; break; }
- case ZAXIS_SIGMA: { grib_ltype = GRIB2_LTYPE_SIGMA; break; }
- case ZAXIS_DEPTH_BELOW_SEA: { grib_ltype = GRIB2_LTYPE_SEADEPTH; break; }
- case ZAXIS_ISENTROPIC: { grib_ltype = GRIB2_LTYPE_ISENTROPIC; break; }
- case ZAXIS_CLOUD_BASE: { grib_ltype = GRIB2_LTYPE_CLOUD_BASE; break; }
- case ZAXIS_CLOUD_TOP: { grib_ltype = GRIB2_LTYPE_CLOUD_TOP; break; }
- case ZAXIS_ISOTHERM_ZERO: { grib_ltype = GRIB2_LTYPE_ISOTHERM0; break; }
- case ZAXIS_TOA: { grib_ltype = GRIB2_LTYPE_TOA; break; }
- case ZAXIS_SEA_BOTTOM: { grib_ltype = GRIB2_LTYPE_SEA_BOTTOM; break; }
- case ZAXIS_LAKE_BOTTOM: { grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TA: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break; }
- case ZAXIS_SEDIMENT_BOTTOM_TW: { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break; }
- case ZAXIS_MIX_LAYER: { grib_ltype = GRIB2_LTYPE_MIX_LAYER; break; }
- case ZAXIS_ATMOSPHERE: { grib_ltype = GRIB2_LTYPE_ATMOSPHERE; break; }
+ case ZAXIS_SURFACE: grib_ltype = GRIB2_LTYPE_SURFACE; break;
+ case ZAXIS_MEANSEA: grib_ltype = GRIB2_LTYPE_MEANSEA; break;
+ case ZAXIS_HEIGHT: grib_ltype = GRIB2_LTYPE_HEIGHT; break;
+ case ZAXIS_ALTITUDE: grib_ltype = GRIB2_LTYPE_ALTITUDE; break;
+ case ZAXIS_SIGMA: grib_ltype = GRIB2_LTYPE_SIGMA; break;
+ case ZAXIS_DEPTH_BELOW_SEA: grib_ltype = GRIB2_LTYPE_SEADEPTH; break;
+ case ZAXIS_ISENTROPIC: grib_ltype = GRIB2_LTYPE_ISENTROPIC; break;
+ case ZAXIS_CLOUD_BASE: grib_ltype = GRIB2_LTYPE_CLOUD_BASE; break;
+ case ZAXIS_CLOUD_TOP: grib_ltype = GRIB2_LTYPE_CLOUD_TOP; break;
+ case ZAXIS_ISOTHERM_ZERO: grib_ltype = GRIB2_LTYPE_ISOTHERM0; break;
+ case ZAXIS_TOA: grib_ltype = GRIB2_LTYPE_TOA; break;
+ case ZAXIS_SEA_BOTTOM: grib_ltype = GRIB2_LTYPE_SEA_BOTTOM; break;
+ case ZAXIS_LAKE_BOTTOM: grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TA: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break;
+ case ZAXIS_SEDIMENT_BOTTOM_TW: grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break;
+ case ZAXIS_MIX_LAYER: grib_ltype = GRIB2_LTYPE_MIX_LAYER; break;
+ case ZAXIS_ATMOSPHERE: grib_ltype = GRIB2_LTYPE_ATMOSPHERE; break;
}
- return (grib_ltype);
+ return grib_ltype;
}
@@ -169,7 +163,7 @@ int grbBitsPerValue(int datatype)
bitsPerValue = 16;
}
- return (bitsPerValue);
+ return bitsPerValue;
}
@@ -190,122 +184,6 @@ void grbDefRecord(stream_t * streamptr)
}
static
-int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
- int unreduced, int *nmiss, double missval, int vlistID, int varID)
-{
- int status = 0;
-
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
- {
-#if defined (HAVE_LIBGRIB_API)
- extern int cdiNAdditionalGRIBKeys;
- if ( cdiNAdditionalGRIBKeys > 0 )
- Error("CGRIBEX decode does not support reading of additional GRIB keys!");
-#endif
- status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval);
- }
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, missval, vlistID, varID);
-#else
- {
- (void)vlistID; (void)varID;
- Error("GRIB_API support not compiled in!");
- }
-#endif
-
- return (status);
-}
-
-
-static int grbUnzipRecord(unsigned char *gribbuffer, size_t *gribsize)
-{
- int zip = 0;
- int izip;
- size_t igribsize;
- size_t ogribsize;
- long unzipsize;
-
- igribsize = *gribsize;
- ogribsize = *gribsize;
-
- if ( (izip = gribGetZip((long)igribsize, gribbuffer, &unzipsize)) > 0 )
- {
- zip = izip;
- if ( izip == 128 ) /* szip */
- {
- unsigned char *itmpbuffer = NULL;
- size_t itmpbuffersize = 0;
-
- if ( unzipsize < (long) igribsize )
- {
- fprintf(stderr, "Decompressed size smaller than compressed size (in %ld; out %ld)!\n", (long)igribsize, unzipsize);
- return (0);
- }
-
- if ( itmpbuffersize < igribsize )
- {
- itmpbuffersize = igribsize;
- itmpbuffer = (unsigned char *) Realloc(itmpbuffer, itmpbuffersize);
- }
-
- memcpy(itmpbuffer, gribbuffer, itmpbuffersize);
-
- unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
-
- ogribsize = (size_t)gribUnzip(gribbuffer, unzipsize, itmpbuffer, (long)igribsize);
-
- Free(itmpbuffer);
-
- if ( ogribsize <= 0 ) Error("Decompression problem!");
- }
- else
- {
- Error("Decompression for %d not implemented!", izip);
- }
- }
-
- *gribsize = ogribsize;
-
- return zip;
-}
-
-
-void grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
-{
- int filetype = streamptr->filetype;
-
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int tsID = streamptr->curTsID;
- int vrecID = streamptr->tsteps[tsID].curRecID;
- int recID = streamptr->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
- int varID = streamptr->tsteps[tsID].records[recID].varID;
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
-
- streamptr->numvals += gridsize;
-
- fileSetPos(fileID, recpos, SEEK_SET);
-
- if (fileRead(fileID, gribbuffer, recsize) != recsize)
- Error("Failed to read GRIB record");
-
- double missval = vlistInqVarMissval(vlistID, varID);
-
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
-
- grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
-}
-
-static
int grbScanTimestep1(stream_t * streamptr)
{
int status = CDI_EUFTYPE;
@@ -323,7 +201,7 @@ int grbScanTimestep1(stream_t * streamptr)
status = gribapiScanTimestep1(streamptr);
#endif
- return (status);
+ return status;
}
static
@@ -346,7 +224,7 @@ int grbScanTimestep2(stream_t * streamptr)
status = gribapiScanTimestep2(streamptr);
#endif
- return (status);
+ return status;
}
static
@@ -370,7 +248,7 @@ int grbScanTimestep(stream_t * streamptr)
Error("Sufficient GRIB support unavailable!");
#endif
- return (status);
+ return status;
}
@@ -390,7 +268,7 @@ int grbInqContents(stream_t * streamptr)
fileSetPos(fileID, 0, SEEK_SET);
- return (status);
+ return status;
}
#endif
@@ -425,334 +303,7 @@ int grbInqTimestep(stream_t * streamptr, int tsID)
nrecs = streamptr->tsteps[tsID].nrecs;
}
- return (nrecs);
-}
-
-
-void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
-{
- int filetype = streamptr->filetype;
-
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
-
- int vlistID = streamptr->vlistID;
- int fileID = streamptr->fileID;
- int tsID = streamptr->curTsID;
-
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
-
- off_t currentfilepos = fileGetPos(fileID);
-
-
- int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
- int nlevs = streamptr->vars[varID].recordTable[0].nlevs;
- if ( CDI_Debug )
- Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
- *nmiss = 0;
- for (int levelID = 0; levelID < nlevs; levelID++ )
- {
- int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
-
- fileSetPos(fileID, recpos, SEEK_SET);
-
- fileRead(fileID, gribbuffer, recsize);
-
- double missval = vlistInqVarMissval(vlistID, varID);
-
- int imiss;
-
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
-
- grbDecode(filetype, gribbuffer, (int)recsize, &data[levelID*gridsize], gridsize,
- streamptr->unreduced, &imiss, missval, vlistID, varID);
-
- *nmiss += imiss;
- }
-
- fileSetPos(fileID, currentfilepos, SEEK_SET);
-}
-
-
-void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss)
-{
- int filetype = streamptr->filetype;
-
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
-
- int vlistID = streamptr->vlistID;
- int gridID = vlistInqVarGrid(vlistID, varID);
- int gridsize = gridInqSize(gridID);
- int tsID = streamptr->curTsID;
-
- if ( CDI_Debug )
- Message("gridID = %d gridsize = %d", gridID, gridsize);
-
- int fileID = streamptr->fileID;
-
- off_t currentfilepos = fileGetPos(fileID);
-
- int isub = subtypeInqActiveIndex(streamptr->vars[varID].subtypeID);
-
-
- int recID = streamptr->vars[varID].recordTable[isub].recordID[levelID];
- off_t recpos = streamptr->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr->tsteps[tsID].records[recID].size;
-
- if ( recsize == 0 )
- Error("Internal problem! Recordsize is zero for record %d at timestep %d",
- recID+1, tsID+1);
-
- fileSetPos(fileID, recpos, SEEK_SET);
-
- fileRead(fileID, gribbuffer, recsize);
-
- double missval = vlistInqVarMissval(vlistID, varID);
-
- streamptr->tsteps[tsID].records[recID].zip = grbUnzipRecord(gribbuffer, &recsize);
-
- grbDecode(filetype, gribbuffer, (int)recsize, data, gridsize, streamptr->unreduced, nmiss, missval, vlistID, varID);
-
- fileSetPos(fileID, currentfilepos, SEEK_SET);
-}
-
-static
-size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int date, int time, int tsteptype, int numavg,
- size_t datasize, const double *data, int nmiss, unsigned char **gribbuffer,
- int comptype, void *gribContainer)
-{
- size_t nbytes = 0;
-
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
- {
- size_t gribbuffersize = datasize*4+3000;
- *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
-
- nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
- date, time, tsteptype, numavg,
- (long)datasize, data, nmiss, *gribbuffer, gribbuffersize);
- }
- else
-#endif
-#ifdef HAVE_LIBGRIB_API
- {
- if ( memtype == MEMTYPE_FLOAT ) Error("gribapiEncode() not implemented for memtype float!");
-
- size_t gribbuffersize;
- nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
- date, time, tsteptype, numavg,
- (long)datasize, data, nmiss, gribbuffer, &gribbuffersize,
- comptype, gribContainer);
- }
-#else
- Error("GRIB_API support not compiled in!");
- (void)gribContainer;
- (void)comptype;
-#endif
-
-
- return (nbytes);
-}
-
-static
-size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
-{
- size_t nbytes = 0;
- unsigned char *buffer;
- size_t buffersize;
- static int lszip_warn = 1;
-
- buffersize = gribbuffersize + 1000; /* compressed record can be greater than source record */
- buffer = (unsigned char *) Malloc(buffersize);
-
- /* memcpy(buffer, gribbuffer, gribbuffersize); */
-
- if ( filetype == FILETYPE_GRB )
- {
- nbytes = (size_t)gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
- }
- else
- {
- if ( lszip_warn ) Warning("Szip compression of GRIB2 records not implemented!");
- lszip_warn = 0;
- nbytes = gribbuffersize;
- }
-
- Free(buffer);
-
- return (nbytes);
-}
-
-
-void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
-{
- size_t nwrite;
- int fileID;
- int gridID;
- int zaxisID;
- unsigned char *gribbuffer = NULL;
- int tsID;
- int vlistID;
- int date, time;
- int tsteptype;
- int numavg = 0;
- size_t nbytes;
- int filetype;
- void *gc = NULL;
-
- filetype = streamptr->filetype;
- fileID = streamptr->fileID;
- vlistID = streamptr->vlistID;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- tsteptype = vlistInqVarTsteptype(vlistID, varID);
-
- int comptype = streamptr->comptype;
-
- tsID = streamptr->curTsID;
- date = streamptr->tsteps[tsID].taxis.vdate;
- time = streamptr->tsteps[tsID].taxis.vtime;
- if ( vlistInqVarTimave(vlistID, varID) )
- numavg = streamptr->tsteps[tsID].taxis.numavg;
-
- if ( CDI_Debug )
- Message("gridID = %d zaxisID = %d", gridID, zaxisID);
-
- size_t datasize = (size_t)gridInqSize(gridID);
- /*
- gribbuffersize = datasize*4+3000;
- gribbuffer = (unsigned char *) Malloc(gribbuffersize);
- */
-#if defined (HAVE_LIBCGRIBEX)
- if ( filetype == FILETYPE_GRB )
- {
- }
- else
-#endif
- {
-#if defined (GRIBCONTAINER2D)
- gribContainer_t **gribContainers = (gribContainer_t **) streamptr->gribContainers;
- gc = (void *) &gribContainers[varID][levelID];
-#else
- gribContainer_t *gribContainers = (gribContainer_t *) streamptr->gribContainers;
- gc = (void *) &gribContainers[varID];
-#endif
- }
-
- if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE;
-
- if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG )
- {
- static int ljpeg_warn = 1;
- if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
- ljpeg_warn = 0;
- }
-
- nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
- datasize, (const double*) data, nmiss, &gribbuffer, comptype, gc);
-
- if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP )
- nbytes = grbSzip(filetype, gribbuffer, nbytes);
-
- {
- size_t (*myFileWrite)(int fileID, const void *restrict buffer,
- size_t len, int tsID)
- = (size_t (*)(int, const void *restrict, size_t, int))
- namespaceSwitchGet(NSSWITCH_FILE_WRITE).func;
- nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
- }
-
- if ( nwrite != nbytes )
- {
- perror(__func__);
- Error("Failed to write GRIB slice!");
- }
-
- if ( gribbuffer ) Free(gribbuffer);
-}
-
-
-void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
-{
- int vlistID, gridID, zaxisID, levelID, nlevs;
- int gridsize;
-
- vlistID = streamptr->vlistID;
- gridID = vlistInqVarGrid(vlistID, varID);
- gridsize = gridInqSize(gridID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- nlevs = zaxisInqSize(zaxisID);
-
- for ( levelID = 0; levelID < nlevs; levelID++ )
- {
- if ( memtype == MEMTYPE_FLOAT )
- grb_write_var_slice(streamptr, varID, levelID, memtype, ((float*)data)+levelID*gridsize, nmiss);
- else
- grb_write_var_slice(streamptr, varID, levelID, memtype, ((double*)data)+levelID*gridsize, nmiss);
- }
-}
-
-
-void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
-{
- int filetype = streamptr1->filetype;
-
- int fileID1 = streamptr1->fileID;
- int fileID2 = streamptr2->fileID;
-
- int tsID = streamptr1->curTsID;
- int vrecID = streamptr1->tsteps[tsID].curRecID;
- int recID = streamptr1->tsteps[tsID].recIDs[vrecID];
- off_t recpos = streamptr1->tsteps[tsID].records[recID].position;
- size_t recsize = streamptr1->tsteps[tsID].records[recID].size;
-
- fileSetPos(fileID1, recpos, SEEK_SET);
-
- /* round up recsize to next multiple of 8 */
- size_t gribbuffersize = ((recsize + 7U) & ~7U);
-
- unsigned char *gribbuffer = (unsigned char *) Malloc(gribbuffersize);
-
- if (fileRead(fileID1, gribbuffer, recsize) != recsize)
- Error("Could not read GRIB record for copying!");
-
- size_t nbytes = recsize;
-
- if ( filetype == FILETYPE_GRB )
- {
- long unzipsize;
- int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize);
-
- if ( izip == 0 )
- if ( streamptr2->comptype == COMPRESS_SZIP )
- nbytes = grbSzip(filetype, gribbuffer, nbytes);
- }
-
- while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;
-
- size_t nwrite = fileWrite(fileID2, gribbuffer, nbytes);
- if ( nwrite != nbytes )
- {
- perror(__func__);
- Error("Could not write record for copying!");
- }
-
- Free(gribbuffer);
-}
-
-
-void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
-{
- int varID, levelID;
-
- varID = streamptr->record->varID;
- levelID = streamptr->record->levelID;
-
- grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ return nrecs;
}
@@ -760,8 +311,6 @@ void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
int filetype = streamptr->filetype;
if ( filetype == FILETYPE_GRB )
diff --git a/libcdi/src/stream_grb.h b/libcdi/src/stream_grb.h
index 13b802c..a2f334f 100644
--- a/libcdi/src/stream_grb.h
+++ b/libcdi/src/stream_grb.h
@@ -3,19 +3,19 @@
int grbBitsPerValue(int datatype);
-int grbInqContents(stream_t * streamptr);
-int grbInqTimestep(stream_t * streamptr, int tsID);
+int grbInqContents(stream_t *streamptr);
+int grbInqTimestep(stream_t *streamptr, int tsID);
-int grbInqRecord(stream_t * streamptr, int *varID, int *levelID);
-void grbDefRecord(stream_t * streamptr);
-void grbReadRecord(stream_t * streamptr, double *data, int *nmiss);
-void grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss);
-void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1);
+int grbInqRecord(stream_t *streamptr, int *varID, int *levelID);
+void grbDefRecord(stream_t *streamptr);
+void grb_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss);
+void grb_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss);
+void grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss);
-void grb_write_var(stream_t * streamptr, int varID, int memtype, const void *data, int nmiss);
+void grb_read_var(stream_t *streamptr, int varID, int memtype, void *data, int *nmiss);
+void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss);
-void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss);
+void grb_read_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, void *data, int *nmiss);
void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss);
int grib1ltypeToZaxisType(int grib_ltype);
diff --git a/libcdi/src/stream_gribapi.c b/libcdi/src/stream_gribapi.c
index 6f29a05..737bc88 100644
--- a/libcdi/src/stream_gribapi.c
+++ b/libcdi/src/stream_gribapi.c
@@ -2,6 +2,7 @@
# include "config.h"
#endif
+#if defined (HAVE_LIBGRIB_API)
#include <limits.h>
#include <stdio.h>
@@ -19,18 +20,14 @@
#include "subtype.h"
-#if defined (HAVE_LIBGRIB_API)
# include "cgribex.h" /* gribGetSize, gribRead, gribGetZip, GRIB1_LTYPE_99 */
# include "gribapi.h"
# include <grib_api.h>
-#endif
extern int cdiInventoryMode;
-#if defined (HAVE_LIBGRIB_API)
-static const var_tile_t dummy_tiles = { -1, -1, -1, -1, -1, -1 };
-#endif
+static const var_tile_t dummy_tiles = { 0, -1, -1, -1, -1, -1 };
typedef struct {
int param;
@@ -45,7 +42,6 @@ typedef struct {
} compvar2_t;
-#if defined (HAVE_LIBGRIB_API)
static
int gribapiGetZaxisType(long editionNumber, int grib_ltype)
{
@@ -320,7 +316,7 @@ int calcLevel(int level_sf, long factor, long level)
}
static
-void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1,
+void grib2GetLevel(grib_handle *gh, int *leveltype1, int *leveltype2, int *lbounds, int *level1,
int *level2, int *level_sf, int *level_unit)
{
int status;
@@ -421,20 +417,14 @@ void gribapiGetString(grib_handle *gh, const char *key, char *string, size_t len
else if ( length == 2 && memcmp(string, "~", length) == 0 ) string[0] = 0;
}
-#if defined (HAVE_LIBGRIB_API)
static
void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
size_t recsize, off_t position, int datatype, int comptype, const char *varname,
int leveltype1, int leveltype2, int lbounds, int level1, int level2, int level_sf, int level_unit,
const var_tile_t *tiles, int lread_additional_keys)
{
- int varID;
int levelID = 0;
- grid_t grid;
- long lpar;
- int status;
char stdname[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
- size_t vlen;
long ens_index = 0, ens_count = 0, ens_forecast_type = 0;
int vlistID = streamptr->vlistID;
@@ -448,15 +438,14 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
// fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype1);
- (*record).size = recsize;
- (*record).position = position;
- (*record).param = param;
- (*record).ilevel = level1;
- (*record).ilevel2 = level2;
- (*record).ltype = leveltype1;
- (*record).tsteptype = tsteptype;
- if ( tiles ) (*record).tiles = *tiles;
- else (*record).tiles = dummy_tiles;
+ record->size = recsize;
+ record->position = position;
+ record->param = param;
+ record->ilevel = level1;
+ record->ilevel2 = level2;
+ record->ltype = leveltype1;
+ record->tsteptype = (short)tsteptype;
+ record->tiles = tiles ? *tiles : dummy_tiles;
//FIXME: This may leave the variable name unterminated (which is the behavior that I found in the code).
// I don't know precisely how this field is used, so I did not change this behavior to avoid regressions,
@@ -470,9 +459,12 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
// I. e. kick the fixed size array and allocate enough space, whatever that may be.
strncpy(record->varname, varname, sizeof(record->varname));
- gribapiGetGrid(gh, &grid);
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ gribapiGetGrid(gh, grid);
- int gridID = varDefGrid(vlistID, &grid, 0);
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1);
@@ -481,17 +473,14 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
case ZAXIS_HYBRID:
case ZAXIS_HYBRID_HALF:
{
- size_t vctsize;
- size_t dummy;
- double *vctptr;
-
+ long lpar;
GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
/* FIXME: assert(lpar >= 0) */
- vctsize = (size_t)lpar;
+ size_t vctsize = (size_t)lpar;
if ( vctsize > 0 )
{
- vctptr = (double *) Malloc(vctsize*sizeof(double));
- dummy = vctsize;
+ double *vctptr = (double *) Malloc(vctsize*sizeof(double));
+ size_t dummy = vctsize;
GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
varDefVCT(vctsize, vctptr);
Free(vctptr);
@@ -501,22 +490,20 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
case ZAXIS_REFERENCE:
{
unsigned char uuid[CDI_UUID_SIZE];
- long ltmp;
- long nhlev, nvgrid;
-
+ long lpar;
GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
if ( lpar != 6 )
{
fprintf(stderr, "Warning ...\n");
}
- GRIB_CHECK(grib_get_long(gh, "nlev", <mp), 0);
- nhlev = ltmp;
- GRIB_CHECK(grib_get_long(gh, "numberOfVGridUsed", <mp), 0);
- nvgrid = ltmp;
+ GRIB_CHECK(grib_get_long(gh, "nlev", &lpar), 0);
+ int nhlev = (int)lpar;
+ GRIB_CHECK(grib_get_long(gh, "numberOfVGridUsed", &lpar), 0);
+ int nvgrid = (int)lpar;
size_t len = (size_t)CDI_UUID_SIZE;
memset(uuid, 0, CDI_UUID_SIZE);
GRIB_CHECK(grib_get_bytes(gh, "uuidOfVGrid", uuid, &len), 0);
- varDefZAxisReference((int) nhlev, (int) nvgrid, uuid);
+ varDefZAxisReference(nhlev, nvgrid, uuid);
break;
}
}
@@ -530,22 +517,19 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
if ( varname[0] != 0 )
{
- vlen = CDI_MAX_NAME;
+ size_t vlen = CDI_MAX_NAME;
gribapiGetString(gh, "name", longname, vlen);
vlen = CDI_MAX_NAME;
gribapiGetString(gh, "units", units, vlen);
-
- {
- vlen = CDI_MAX_NAME;
- status = grib_get_string(gh, "cfName", stdname, &vlen);
- if ( status != 0 || vlen <= 1 ) stdname[0] = 0;
- else if ( strncmp(stdname, "unknown", 7) == 0 ) stdname[0] = 0;
- }
+ vlen = CDI_MAX_NAME;
+ int status = grib_get_string(gh, "cfName", stdname, &vlen);
+ if ( status != 0 || vlen <= 1 || strncmp(stdname, "unknown", 7) == 0 )
+ stdname[0] = 0;
}
// fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units);
/* add the previously read record data to the (intermediate) list of records */
- int tile_index = -1;
+ int tile_index = 0, varID;
varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2, level_sf, level_unit,
datatype, &varID, &levelID, tsteptype, numavg, leveltype1, leveltype2,
varname, stdname, longname, units, tiles, &tile_index);
@@ -559,8 +543,7 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
Get the ensemble Info from the grib-2 Tables and update the intermediate datastructure.
Further update to the "vlist" is handled in the same way as for GRIB-1 by "cdi_generate_vars"
*/
- status = grib_get_long(gh, "typeOfEnsembleForecast", &ens_forecast_type );
- if ( status == 0 )
+ if ( grib_get_long(gh, "typeOfEnsembleForecast", &ens_forecast_type) == 0 )
{
GRIB_CHECK(grib_get_long(gh, "numberOfForecastsInEnsemble", &ens_count ), 0);
GRIB_CHECK(grib_get_long(gh, "perturbationNumber", &ens_index ), 0);
@@ -570,13 +553,11 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
varDefEnsembleInfo(varID, (int)ens_index, (int)ens_count, (int)ens_forecast_type);
long typeOfGeneratingProcess = 0;
- status = grib_get_long(gh, "typeOfGeneratingProcess", &typeOfGeneratingProcess);
- if ( status == 0 )
+ if ( grib_get_long(gh, "typeOfGeneratingProcess", &typeOfGeneratingProcess) == 0 )
varDefTypeOfGeneratingProcess(varID, (int) typeOfGeneratingProcess);
long productDefinitionTemplate = 0;
- status = grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate);
- if ( status == 0 )
+ if ( grib_get_long(gh, "productDefinitionTemplateNumber", &productDefinitionTemplate) == 0 )
varDefProductDefinitionTemplate(varID, (int) productDefinitionTemplate);
int i;
@@ -609,8 +590,7 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
{
int modelID;
long processID;
- status = grib_get_long(gh, "generatingProcessIdentifier", &processID);
- if ( status == 0 )
+ if ( grib_get_long(gh, "generatingProcessIdentifier", &processID) == 0 )
{
/* FIXME: assert(processID >= INT_MIN && processID <= INT_MAX) */
modelID = modelInq(varInqInst(varID), (int)processID, NULL);
@@ -646,7 +626,6 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
Message("varID = %d param = %d zaxistype = %d gridID = %d levelID = %d",
varID, param, zaxistype, gridID, levelID);
}
-#endif
static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype,
int tsteptype, char *name, var_tile_t tiles_data)
@@ -667,9 +646,7 @@ static compvar2_t gribapiVarSet(int param, int level1, int level2, int leveltype
return (compVar);
}
-#endif
-#ifdef HAVE_LIBGRIB_API
static
int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
{
@@ -689,25 +666,25 @@ int gribapiVarCompare(compvar2_t compVar, record_t record, int flag)
compVar0.tiles = record.tiles;
- int rstatus = memcmp(&compVar0, &compVar, sizeof(compvar2_t));
-
- return (rstatus);
+ return memcmp(&compVar0, &compVar, sizeof(compvar2_t));
}
-static void ensureBufferSize(size_t requiredSize, size_t* curSize, unsigned char **buffer) {
+static
+void ensureBufferSize(size_t requiredSize, size_t *curSize, void **buffer)
+{
if ( *curSize < requiredSize )
{
*curSize = requiredSize;
- *buffer = (unsigned char *) Realloc(*buffer, *curSize);
+ *buffer = Realloc(*buffer, *curSize);
}
}
static
-grib_handle* gribapiGetDiskRepresentation(size_t recsize, size_t* buffersize, unsigned char** gribbuffer, int* outDatatype, int* outCompressionType, long* outUnzipsize)
+grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, void **gribbuffer, int *outDatatype, int *outCompressionType, long *outUnzipsize)
{
int lieee = FALSE;
- grib_handle* gh = grib_handle_new_from_message(NULL, (void *) *gribbuffer, recsize);
+ grib_handle *gh = grib_handle_new_from_message(NULL, *gribbuffer, recsize);
if(gribEditionNumber(gh) > 1)
{
size_t len = 256;
@@ -752,9 +729,7 @@ grib_handle* gribapiGetDiskRepresentation(size_t recsize, size_t* buffersize, un
}
return gh;
}
-#endif
-#if defined (HAVE_LIBGRIB_API)
typedef enum { CHECKTIME_OK, CHECKTIME_SKIP, CHECKTIME_STOP, CHECKTIME_INCONSISTENT } checkTimeResult;
static checkTimeResult checkTime(stream_t* streamptr, compvar2_t compVar, const DateTime* verificationTime, const DateTime* expectedVTime) {
// First determine whether the current record exists already.
@@ -782,7 +757,6 @@ static checkTimeResult checkTime(stream_t* streamptr, compvar2_t compVar, const
return CHECKTIME_OK;
}
-#endif
#define gribWarning(text, nrecs, timestep, varname, param, level1, level2) do \
{ \
@@ -792,11 +766,10 @@ static checkTimeResult checkTime(stream_t* streamptr, compvar2_t compVar, const
} \
while(0)
-#if defined (HAVE_LIBGRIB_API)
int gribapiScanTimestep1(stream_t * streamptr)
{
off_t recpos = 0;
- unsigned char *gribbuffer = NULL;
+ void *gribbuffer = NULL;
size_t buffersize = 0;
DateTime datetime0 = { .date = 10101, .time = 0 };
int nrecs_scanned = 0; //Only used for debug output.
@@ -993,10 +966,8 @@ int gribapiScanTimestep1(stream_t * streamptr)
return (0);
}
-#endif
-#ifdef HAVE_LIBGRIB_API
int gribapiScanTimestep2(stream_t * streamptr)
{
int rstatus = 0;
@@ -1013,7 +984,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
int vlistID = streamptr->vlistID;
int taxisID = vlistInqTaxis(vlistID);
- unsigned char *gribbuffer = (unsigned char *) streamptr->record->buffer;
+ void *gribbuffer = streamptr->record->buffer;
size_t buffersize = streamptr->record->buffersize;
int tsID = streamptr->rtsteps;
@@ -1062,7 +1033,7 @@ int gribapiScanTimestep2(stream_t * streamptr)
ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
nrecs_scanned++;
- gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
+ gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
int param = gribapiGetParam(gh);
@@ -1217,10 +1188,8 @@ int gribapiScanTimestep2(stream_t * streamptr)
return (rstatus);
}
-#endif
-#if defined (HAVE_LIBGRIB_API)
int gribapiScanTimestep(stream_t * streamptr)
{
int vrecID, recID;
@@ -1241,7 +1210,7 @@ int gribapiScanTimestep(stream_t * streamptr)
if ( streamptr->tsteps[tsID].recordSize == 0 )
{
- unsigned char* gribbuffer = (unsigned char *) streamptr->record->buffer;
+ void *gribbuffer = streamptr->record->buffer;
size_t buffersize = streamptr->record->buffersize;
cdi_create_records(streamptr, tsID);
@@ -1292,7 +1261,7 @@ int gribapiScanTimestep(stream_t * streamptr)
ensureBufferSize((size_t)unzipsize + 100, &buffersize, &gribbuffer);
nrecs_scanned++;
- gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
+ gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
GRIB_CHECK(my_grib_set_double(gh, "missingValue", cdiDefaultMissval), 0);
int param = gribapiGetParam(gh);
@@ -1450,14 +1419,12 @@ int gribapiScanTimestep(stream_t * streamptr)
return (int)streamptr->ntsteps;
}
-#endif
#ifdef gribWarning
#undef gribWarning
#endif
-#ifdef HAVE_LIBGRIB_API
-int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
+int gribapiDecode(void *gribbuffer, int gribsize, double *data, long gridsize,
int unreduced, int *nmiss, double missval, int vlistID, int varID)
{
int status = 0;
@@ -1480,7 +1447,7 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
}
size_t recsize = (size_t)gribsize;
- grib_handle *gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
+ grib_handle *gh = grib_handle_new_from_message(NULL, gribbuffer, recsize);
GRIB_CHECK(my_grib_set_double(gh, "missingValue", missval), 0);
/* get the size of the values array*/
@@ -1489,8 +1456,8 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
// printf("values_size = %d numberOfPoints = %ld\n", datasize, numberOfPoints);
- if ( gridsize != (int) datasize )
- Error("Internal problem: gridsize(%d) != datasize(%d)!", gridsize, datasize);
+ if ( gridsize != (long) datasize )
+ Error("Internal problem: gridsize(%ld) != datasize(%zu)!", gridsize, datasize);
size_t dummy = datasize;
GRIB_CHECK(grib_get_double_array(gh, "values", data, &dummy), 0);
@@ -1507,12 +1474,10 @@ int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gri
grib_handle_delete(gh);
- return (status);
+ return status;
}
-#endif
-#if defined (HAVE_LIBGRIB_API)
static
void gribapiDefInstitut(grib_handle *gh, int vlistID, int varID)
{
@@ -1661,7 +1626,7 @@ void gribapiDefStepUnits(grib_handle *gh, int timeunit, int proDefTempNum, int g
{
GRIB_CHECK(my_grib_set_long(gh, "stepUnits", unitsOfTime), 0);
if ( proDefTempNum == 8 || proDefTempNum == 11 )
- GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0);
GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
}
}
@@ -1834,6 +1799,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
UNUSED(nmiss);
int gridtype = gridInqType(gridID);
+ int gridsize = gridInqSize(gridID);
if ( editionNumber <= 1 )
if ( gridtype == GRID_GME || gridtype == GRID_UNSTRUCTURED )
@@ -1841,11 +1807,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
if ( gridtype == GRID_GENERIC )
{
- int xsize, ysize, gridsize;
-
- gridsize = gridInqSize(gridID);
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ int xsize = gridInqXsize(gridID);
+ int ysize = gridInqYsize(gridID);
if ( (ysize == 32 || ysize == 48 || ysize == 64 ||
ysize == 96 || ysize == 160 || ysize == 192 ||
@@ -1869,7 +1832,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
}
else if ( gridtype == GRID_CURVILINEAR )
{
- if ( lwarn && gridInqSize(gridID) > 1 )
+ if ( lwarn && gridsize > 1 )
{
lwarn = FALSE;
Warning("Curvilinear grids are unsupported in GRIB format! Created wrong GDS!");
@@ -1883,13 +1846,13 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
if ( comptype )
{
- if ( comptype == COMPRESS_JPEG )
+ if ( comptype == COMPRESS_JPEG && gridsize > 1 )
{
static const char mesg[] = "grid_jpeg";
size_t len = sizeof (mesg) - 1;
GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
}
- else if ( comptype == COMPRESS_SZIP )
+ else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
{
static const char mesg[] = "grid_ccsds";
size_t len = sizeof (mesg) - 1;
@@ -1913,7 +1876,6 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
case GRID_GAUSSIAN_REDUCED:
case GRID_TRAJECTORY:
{
- int nlon = 0, nlat;
double xfirst = 0, xlast = 0, xinc = 0;
double yfirst = 0, ylast = 0, yinc = 0;
double latIncr;
@@ -1943,8 +1905,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
}
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
+ int nlon = gridInqXsize(gridID);
+ int nlat = gridInqYsize(gridID);
if ( gridtype == GRID_GAUSSIAN_REDUCED )
{
@@ -2035,10 +1997,9 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
*/
if ( gridIsRotated(gridID) )
{
- double xpole, ypole, angle;
- xpole = gridInqXpole(gridID);
- ypole = gridInqYpole(gridID);
- angle = gridInqAngle(gridID);
+ double xpole = gridInqXpole(gridID);
+ double ypole = gridInqYpole(gridID);
+ double angle = gridInqAngle(gridID);
/* change from north to south pole */
if ( fabs(ypole) > 0 ) ypole = -ypole;
xpole = xpole + 180;
@@ -2069,13 +2030,13 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
}
else
{
- if ( comptype == COMPRESS_JPEG )
+ if ( comptype == COMPRESS_JPEG && gridsize > 1 )
{
static const char mesg[] = "grid_jpeg";
size_t len = sizeof (mesg) -1;
GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
}
- else if ( comptype == COMPRESS_SZIP )
+ else if ( comptype == COMPRESS_SZIP && gridsize > 1 )
{
static const char mesg[] = "grid_ccsds";
size_t len = sizeof (mesg) -1;
@@ -2094,11 +2055,10 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
case GRID_LCC:
{
double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
- int xsize, ysize;
int projflag, scanflag;
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ int xsize = gridInqXsize(gridID);
+ int ysize = gridInqYsize(gridID);
gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
&projflag, &scanflag);
@@ -2125,10 +2085,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
GRIB_CHECK(my_grib_set_long(gh, "projectionCenterFlag", projflag), 0);
GRIB_CHECK(my_grib_set_long(gh, "scanningMode", scanflag), 0);
}
- /*
- ISEC2_Lambert_LatSP = 0;
- ISEC2_Lambert_LatSP = 0;
- */
+
break;
}
case GRID_SPECTRAL:
@@ -2143,19 +2100,19 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
GRIB_CHECK(my_grib_set_long(gh, "K", trunc), 0);
GRIB_CHECK(my_grib_set_long(gh, "M", trunc), 0);
- // GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridInqSize(gridID)), 0);
+ // GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
/*
if ( lieee )
{
printf("spectral_ieee\n");
- if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridInqSize(gridID)), 0);
+ if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize, 0);
static const char mesg[] = "spectral_ieee";
size_t len = sizeof (mesg) -1;
GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
}
else */ if ( gridInqComplexPacking(gridID) )
{
- if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridInqSize(gridID)), 0);
+ if ( editionNumber == 2 ) GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize), 0);
static const char mesg[] = "spectral_complex";
size_t len = sizeof (mesg) -1;
GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
@@ -2184,8 +2141,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
GRIB_CHECK(my_grib_set_long(gh, "latitudeOfThePolePoint", 90000000), 0);
GRIB_CHECK(my_grib_set_long(gh, "longitudeOfThePolePoint", 0), 0);
- GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridInqSize(gridID)), 0);
- GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridInqSize(gridID)), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
+ GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridsize), 0);
if ( comptype == COMPRESS_SZIP )
{
@@ -2293,7 +2250,6 @@ static
void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID, int levelID, int gcinit, int proddef_template_num)
{
int lbounds = 0;
- static int warning = 1;
double dlevel1 = 0, dlevel2 = 0;
int zaxistype = zaxisInqType(zaxisID);
@@ -2333,7 +2289,26 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
case ZAXIS_DEPTH_BELOW_SEA:
case ZAXIS_ISENTROPIC:
{
- if ( editionNumber <= 1 )
+ if ( zaxistype == ZAXIS_HEIGHT )
+ {
+ double sf = 1;
+ char units[128];
+ zaxisInqUnits(zaxisID, units);
+ if ( units[1] == 'm' && !units[2] )
+ {
+ if ( units[0] == 'c' ) sf = 0.01;
+ else if ( units[0] == 'd' ) sf = 0.1;
+ else if ( units[0] == 'k' ) sf = 1000;
+ }
+ if ( IS_NOT_EQUAL(sf, 1) )
+ {
+ level *= sf;
+ dlevel1 *= sf;
+ dlevel2 *= sf;
+ }
+ }
+
+ if ( editionNumber <= 1 )
{
gribapiDefLevelType(gh, gcinit, "indicatorOfTypeOfLevel", zaxisTypeToGrib1ltype(zaxistype));
GRIB_CHECK(my_grib_set_long(gh, "level", (long)level), 0);
@@ -2410,15 +2385,11 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
if ( !gcinit )
{
int vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && warning )
+ if ( vctsize > 0 )
{
- char paramstr[32];
- cdiParamToString(param, paramstr, sizeof(paramstr));
- Warning("VCT missing ( param = %s, zaxisID = %d )", paramstr, zaxisID);
- warning = 0;
+ GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
+ GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
}
- GRIB_CHECK(my_grib_set_long(gh, "PVPresent", 1), 0);
- GRIB_CHECK(grib_set_double_array(gh, "pv", zaxisInqVctPtr(zaxisID), (size_t)vctsize), 0);
}
break;
@@ -2575,14 +2546,12 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int param, int zaxisID,
}
}
}
-#endif
/* #define GRIBAPIENCODETEST 1 */
-#ifdef HAVE_LIBGRIB_API
size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
+ long datasize, const double *data, int nmiss, void **gribbuffer, size_t *gribbuffersize,
int comptype, void *gribContainer)
{
size_t recsize = 0;
@@ -2700,7 +2669,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
GRIB_CHECK(grib_get_message(gh, (const void **)&dummy, &recsize), 0);
recsize += 512; /* add some space for possible filling */
*gribbuffersize = recsize;
- *gribbuffer = (unsigned char *) Malloc(*gribbuffersize);
+ *gribbuffer = Malloc(*gribbuffersize);
/* get a copy of the coded message */
GRIB_CHECK(grib_get_message_copy(gh, *gribbuffer, &recsize), 0);
@@ -2711,7 +2680,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
gc->init = TRUE;
- return (recsize);
+ return recsize;
}
#endif
diff --git a/libcdi/src/stream_gribapi.h b/libcdi/src/stream_gribapi.h
index d3ff963..ac4755b 100644
--- a/libcdi/src/stream_gribapi.h
+++ b/libcdi/src/stream_gribapi.h
@@ -5,12 +5,12 @@ int gribapiScanTimestep1(stream_t * streamptr);
int gribapiScanTimestep2(stream_t * streamptr);
int gribapiScanTimestep(stream_t * streamptr);
-int gribapiDecode(unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
+int gribapiDecode(void *gribbuffer, int gribsize, double *data, long datasize,
int unreduced, int *nmiss, double missval, int vlistID, int varID);
size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
- int vdate, int vtime, int tsteptype, int numavg,
- long datasize, const double *data, int nmiss, unsigned char **gribbuffer, size_t *gribbuffersize,
+ int vdate, int vtime, int tsteptype, int numavg,
+ long datasize, const double *data, int nmiss, void **gribbuffer, size_t *gribbuffersize,
int ljpeg, void *gribContainer);
#endif /* _STREAM_GRIBAPI_H */
diff --git a/libcdi/src/stream_ieg.c b/libcdi/src/stream_ieg.c
index b798514..20c08f9 100644
--- a/libcdi/src/stream_ieg.c
+++ b/libcdi/src/stream_ieg.c
@@ -266,9 +266,7 @@ calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylas
static
void iegDefGrid(int *gdb, int gridID)
{
- int gridtype;
-
- gridtype = gridInqType(gridID);
+ int gridtype = gridInqType(gridID);
if ( gridtype == GRID_GENERIC )
{
@@ -399,7 +397,6 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
{
double level;
int ilevel, leveltype;
- static int warning = 1;
static int vct_warning = 1;
leveltype = zaxisInqType(zaxisID);
@@ -443,12 +440,6 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
}
vctsize = zaxisInqVctSize(zaxisID);
- if ( vctsize == 0 && warning )
- {
- Warning("VCT missing. ( code = %d, zaxisID = %d )",
- IEG_P_Parameter(pdb), zaxisID);
- warning = 0;
- }
if ( vctsize > 100 )
{
/* IEG_G_NumVCP(gdb) = 0; */
@@ -644,23 +635,13 @@ static
void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct,
size_t recsize, off_t position, int prec)
{
- int leveltype;
- int gridID = UNDEFID;
int levelID = 0;
- int tsID, recID, varID;
- int datatype;
- int level1, level2;
- int gridtype;
- int lbounds = 0;
- record_t *record;
- grid_t grid;
- int vlistID;
-
- vlistID = streamptr->vlistID;
- tsID = streamptr->curTsID;
- recID = recordNewEntry(streamptr, tsID);
- record = &streamptr->tsteps[tsID].records[recID];
+ int vlistID = streamptr->vlistID;
+ int tsID = streamptr->curTsID;
+ int recID = recordNewEntry(streamptr, tsID);
+ record_t *record = &streamptr->tsteps[tsID].records[recID];
+ int level1, level2;
if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER )
{
level1 = IEG_P_Level1(pdb);
@@ -680,21 +661,18 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
record->ilevel2 = level2;
record->ltype = IEG_P_LevelType(pdb);
- if ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 )
- gridtype = GRID_LONLAT;
- else if ( IEG_G_GridType(gdb) == 4 )
- gridtype = GRID_GAUSSIAN;
- else
- gridtype = GRID_GENERIC;
+ int gridtype =
+ ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 ) ? GRID_LONLAT :
+ ( IEG_G_GridType(gdb) == 4 ) ? GRID_GAUSSIAN : GRID_GENERIC;
- memset(&grid, 0, sizeof(grid_t));
- grid.type = gridtype;
- grid.size = IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb);
- grid.xsize = IEG_G_NumLon(gdb);
- grid.ysize = IEG_G_NumLat(gdb);
- grid.xinc = 0;
- grid.yinc = 0;
- grid.xdef = 0;
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, gridtype, IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb));
+ grid->xsize = IEG_G_NumLon(gdb);
+ grid->ysize = IEG_G_NumLat(gdb);
+ grid->xinc = 0;
+ grid->yinc = 0;
+ grid->xdef = 0;
int iresfac = IEG_G_ResFac(gdb);
if ( iresfac == 0 ) iresfac = 1000;
@@ -702,68 +680,70 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
/* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */
{
- if ( grid.xsize > 1 )
+ if ( grid->xsize > 1 )
{
if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 )
- grid.xinc = IEG_G_LonIncr(gdb) * resfac;
+ grid->xinc = IEG_G_LonIncr(gdb) * resfac;
else
- grid.xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid.xsize - 1);
+ grid->xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid->xsize - 1);
/* correct xinc if necessary */
if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 )
{
- double xinc = 360. / grid.xsize;
- /* FIXME: why not use grid.xinc != xinc as condition? */
- if ( fabs(grid.xinc-xinc) > 0.0 )
+ double xinc = 360. / grid->xsize;
+ /* FIXME: why not use grid->xinc != xinc as condition? */
+ if ( fabs(grid->xinc-xinc) > 0.0 )
{
- grid.xinc = xinc;
- if ( CDI_Debug ) Message("set xinc to %g", grid.xinc);
+ grid->xinc = xinc;
+ if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
}
}
}
- grid.xfirst = IEG_G_FirstLon(gdb) * resfac;
- grid.xlast = IEG_G_LastLon(gdb) * resfac;
- grid.xdef = 2;
+ grid->xfirst = IEG_G_FirstLon(gdb) * resfac;
+ grid->xlast = IEG_G_LastLon(gdb) * resfac;
+ grid->xdef = 2;
}
- grid.ydef = 0;
+ grid->ydef = 0;
/* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */
{
- if ( grid.ysize > 1 )
+ if ( grid->ysize > 1 )
{
if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 )
- grid.yinc = IEG_G_LatIncr(gdb) * resfac;
+ grid->yinc = IEG_G_LatIncr(gdb) * resfac;
else
- grid.yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid.ysize - 1);
+ grid->yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid->ysize - 1);
}
- grid.yfirst = IEG_G_FirstLat(gdb) * resfac;
- grid.ylast = IEG_G_LastLat(gdb) * resfac;
- grid.ydef = 2;
+ grid->yfirst = IEG_G_FirstLat(gdb) * resfac;
+ grid->ylast = IEG_G_LastLat(gdb) * resfac;
+ grid->ydef = 2;
}
/*
- grid.xfirst= IEG_G_FirstLon(gdb) * resfac;
- grid.xlast = IEG_G_LastLon(gdb) * resfac;
- grid.xinc = IEG_G_LonIncr(gdb) * resfac;
- grid.xdef = 2;
- grid.yfirst= IEG_G_FirstLat(gdb) * resfac;
- grid.ylast = IEG_G_LastLat(gdb) * resfac;
- grid.yinc = IEG_G_LatIncr(gdb) * resfac;
- grid.ydef = 2;
+ grid->xfirst= IEG_G_FirstLon(gdb) * resfac;
+ grid->xlast = IEG_G_LastLon(gdb) * resfac;
+ grid->xinc = IEG_G_LonIncr(gdb) * resfac;
+ grid->xdef = 2;
+ grid->yfirst= IEG_G_FirstLat(gdb) * resfac;
+ grid->ylast = IEG_G_LastLat(gdb) * resfac;
+ grid->yinc = IEG_G_LatIncr(gdb) * resfac;
+ grid->ydef = 2;
*/
- grid.xvals = NULL;
- grid.yvals = NULL;
+ grid->xvals = NULL;
+ grid->yvals = NULL;
- grid.isRotated = FALSE;
+ grid->isRotated = FALSE;
if ( IEG_G_GridType(gdb) == 10 )
{
- grid.isRotated = TRUE;
- grid.ypole = - IEG_G_LatSP(gdb) * resfac;
- grid.xpole = IEG_G_LonSP(gdb) * resfac - 180;
- grid.angle = 0;
+ grid->isRotated = TRUE;
+ grid->ypole = - IEG_G_LatSP(gdb) * resfac;
+ grid->xpole = IEG_G_LonSP(gdb) * resfac - 180;
+ grid->angle = 0;
}
- gridID = varDefGrid(vlistID, &grid, 0);
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
- leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
+ int leveltype = iegGetZaxisType(IEG_P_LevelType(pdb));
if ( leveltype == ZAXIS_HYBRID )
{
@@ -776,10 +756,11 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc
varDefVCT(vctsize, tmpvct);
}
- if ( IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER ) lbounds = 1;
+ int lbounds = IEG_P_LevelType(pdb) == IEG_LTYPE_HYBRID_LAYER ? 1 : 0;
- datatype = iegInqDatatype(prec);
+ int datatype = iegInqDatatype(prec);
+ int varID;
varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0,
datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
NULL, NULL, NULL, NULL, NULL, NULL);
diff --git a/libcdi/src/stream_read.c b/libcdi/src/stream_read.c
new file mode 100644
index 0000000..c4e9d7f
--- /dev/null
+++ b/libcdi/src/stream_read.c
@@ -0,0 +1,357 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_grb.h"
+#include "stream_cdf.h"
+#include "stream_srv.h"
+#include "stream_ext.h"
+#include "stream_ieg.h"
+#include "dmemory.h"
+#include "namespace.h"
+
+
+/* the single image implementation */
+static
+int cdiStreamReadVar(int streamID, int varID, int memtype, void *data, int *nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+
+ check_parg(data);
+ check_parg(nmiss);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int filetype = streamptr->filetype;
+
+ *nmiss = 0;
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_read_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadVarDP(streamptr, varID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_read_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ at Function streamReadVar
+ at Title Read a variable
+
+ at Prototype void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVar(int streamID, int varID, double *data, int *nmiss)
+{
+ cdiStreamReadVar(streamID, varID, MEMTYPE_DOUBLE, data, nmiss);
+}
+
+/*
+ at Function streamReadVarF
+ at Title Read a variable
+
+ at Prototype void streamReadVar(int streamID, int varID, float *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamReadVar reads all the values of one time step of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarF(int streamID, int varID, float *data, int *nmiss)
+{
+ if ( cdiStreamReadVar(streamID, varID, MEMTYPE_FLOAT, data, nmiss) )
+ {
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadVar(streamID, varID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
+ }
+}
+
+
+static
+int cdiStreamReadVarSlice(int streamID, int varID, int levelID, int memtype, void *data, int *nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+
+ check_parg(data);
+ check_parg(nmiss);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int filetype = streamptr->filetype;
+
+ *nmiss = 0;
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_read_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadVarSliceDP(streamptr, varID, levelID, (double *)data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_read_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ status = 2;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ at Function streamReadVarSlice
+ at Title Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamReadVarSlice reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSlice(int streamID, int varID, int levelID, double *data, int *nmiss)
+{
+ if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, data, nmiss) )
+ {
+ Warning("Unexpected error returned from cdiStreamReadVarSlice()!");
+ size_t elementCount = (size_t)gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ memset(data, 0, elementCount * sizeof(*data));
+ }
+}
+
+/*
+ at Function streamReadVarSliceF
+ at Title Read a horizontal slice of a variable
+
+ at Prototype void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenRead}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to the location into which the data values are read.
+ The caller must allocate space for the returned values.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamReadVarSliceF reads all the values of a horizontal slice of a variable
+from an open dataset.
+ at EndFunction
+*/
+void streamReadVarSliceF(int streamID, int varID, int levelID, float *data, int *nmiss)
+{
+ if ( cdiStreamReadVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, data, nmiss) )
+ {
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
+ }
+}
+
+static
+int stream_read_record(int streamID, int memtype, void *data, int *nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision reading.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ check_parg(data);
+ check_parg(nmiss);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ *nmiss = 0;
+
+ switch (streamptr->filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grb_read_record(streamptr, memtype, data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegReadRecord(streamptr, (double *)data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_read_record(streamptr, memtype, data, nmiss);
+ break;
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+ break;
+ }
+ }
+
+ return status;
+}
+
+
+void streamReadRecord(int streamID, double *data, int *nmiss)
+{
+ stream_read_record(streamID, MEMTYPE_DOUBLE, (void *) data, nmiss);
+}
+
+
+void streamReadRecordF(int streamID, float *data, int *nmiss)
+{
+ if ( stream_read_record(streamID, MEMTYPE_FLOAT, (void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision reading,
+ // we fall back to double precision reading, converting the data on the fly.
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ streamReadRecord(streamID, conversionBuffer, nmiss);
+ for ( size_t i = elementCount; i--; ) data[i] = (float) conversionBuffer[i];
+ Free(conversionBuffer);
+ }
+}
diff --git a/libcdi/src/stream_record.c b/libcdi/src/stream_record.c
index 3316cc4..ea43cd1 100644
--- a/libcdi/src/stream_record.c
+++ b/libcdi/src/stream_record.c
@@ -107,7 +107,6 @@ void streamInqRecord(int streamID, int *varID, int *levelID)
check_parg(levelID);
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
cdiDefAccesstype(streamID, TYPE_REC);
@@ -154,7 +153,6 @@ The function streamDefRecord defines the meta-data of the next record.
void streamDefRecord(int streamID, int varID, int levelID)
{
stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
int tsID = streamptr->curTsID;
@@ -220,144 +218,13 @@ void streamDefRecord(int streamID, int varID, int levelID)
}
-void streamReadRecord(int streamID, double *data, int *nmiss)
-{
- check_parg(data);
- check_parg(nmiss);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
- *nmiss = 0;
-
- switch (streamptr->filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grbReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- srvReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- extReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- iegReadRecord(streamptr, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- cdfReadRecord(streamptr, data, nmiss);
- break;
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(streamptr->filetype));
- break;
- }
- }
-}
-
-static void
-stream_write_record(int streamID, int memtype, const void *data, int nmiss)
-{
- check_parg(data);
-
- stream_t *streamptr = stream_to_pointer(streamID);
- stream_check_ptr(__func__, streamptr);
-
- switch (streamptr->filetype)
- {
-#if defined (HAVE_LIBGRIB)
- case FILETYPE_GRB:
- case FILETYPE_GRB2:
- grb_write_record(streamptr, memtype, data, nmiss);
- break;
-#endif
-#if defined (HAVE_LIBSERVICE)
- case FILETYPE_SRV:
- if ( memtype == MEMTYPE_FLOAT ) Error("srvWriteRecord not implemented for memtype float!");
- srvWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBEXTRA)
- case FILETYPE_EXT:
- if ( memtype == MEMTYPE_FLOAT ) Error("extWriteRecord not implemented for memtype float!");
- extWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBIEG)
- case FILETYPE_IEG:
- if ( memtype == MEMTYPE_FLOAT ) Error("iegWriteRecord not implemented for memtype float!");
- iegWriteRecord(streamptr, (const double *)data);
- break;
-#endif
-#if defined (HAVE_LIBNETCDF)
- case FILETYPE_NC:
- case FILETYPE_NC2:
- case FILETYPE_NC4:
- case FILETYPE_NC4C:
- {
- cdf_write_record(streamptr, memtype, data, nmiss);
- break;
- }
-#endif
- default:
- {
- Error("%s support not compiled in!", strfiletype(streamptr->filetype));
- break;
- }
- }
-}
-
-/*
- at Function streamWriteRecord
- at Title Write a horizontal slice of a variable
-
- at Prototype void streamWriteRecord(int streamID, const double *data, int nmiss)
- at Parameter
- @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
- @Item data Pointer to a block of double precision floating point data values to be written.
- @Item nmiss Number of missing values.
-
- at Description
-The function streamWriteRecord writes the values of a horizontal slice (record) of a variable to an open dataset.
-The values are converted to the external data type of the variable, if necessary.
- at EndFunction
-*/
-void streamWriteRecord(int streamID, const double *data, int nmiss)
-{
- stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
-}
-
-void streamWriteRecordF(int streamID, const float *data, int nmiss)
-{
- stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, nmiss);
-}
-
-
void streamCopyRecord(int streamID2, int streamID1)
{
- stream_t *streamptr1 = stream_to_pointer(streamID1);
- stream_t *streamptr2 = stream_to_pointer(streamID2);
-
- stream_check_ptr(__func__, streamptr1);
- stream_check_ptr(__func__, streamptr2);
-
- int filetype1 = streamptr1->filetype;
- int filetype2 = streamptr2->filetype;
- int filetype = FILETYPE_UNDEF;
+ stream_t *streamptr1 = stream_to_pointer(streamID1),
+ *streamptr2 = stream_to_pointer(streamID2);
+ int filetype1 = streamptr1->filetype,
+ filetype2 = streamptr2->filetype,
+ filetype = FILETYPE_UNDEF;
if ( filetype1 == filetype2 ) filetype = filetype2;
else
diff --git a/libcdi/src/stream_srv.c b/libcdi/src/stream_srv.c
index ef89486..52752b0 100644
--- a/libcdi/src/stream_srv.c
+++ b/libcdi/src/stream_srv.c
@@ -102,23 +102,20 @@ int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
void srvReadRecord(stream_t *streamptr, double *data, int *nmiss)
{
- int vlistID, fileID;
int status;
- int recID, vrecID, tsID;
- off_t recpos;
int header[8];
- int varID, gridID;
+ int gridID;
int i, size;
double missval;
void *srvp = streamptr->record->exsep;
- vlistID = streamptr->vlistID;
- fileID = streamptr->fileID;
- tsID = streamptr->curTsID;
- vrecID = streamptr->tsteps[tsID].curRecID;
- recID = streamptr->tsteps[tsID].recIDs[vrecID];
- recpos = streamptr->tsteps[tsID].records[recID].position;
- varID = streamptr->tsteps[tsID].records[recID].varID;
+ int vlistID = streamptr->vlistID;
+ int fileID = streamptr->fileID;
+ int tsID = streamptr->curTsID;
+ int vrecID = streamptr->tsteps[tsID].curRecID;
+ int recID = streamptr->tsteps[tsID].recIDs[vrecID];
+ int varID = streamptr->tsteps[tsID].records[recID].varID;
+ off_t recpos = streamptr->tsteps[tsID].records[recID].position;
fileSetPos(fileID, recpos, SEEK_SET);
@@ -153,23 +150,20 @@ void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
void srvDefRecord(stream_t *streamptr)
{
- int gridID;
int header[8];
- int xsize, ysize;
- int datatype;
- int pdis, pcat, pnum;
- srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
+ Record *restrict record = streamptr->record;
+ srvrec_t *restrict srvp = (srvrec_t*) record->exsep;
+ int gridID = record->gridID;
- gridID = streamptr->record->gridID;
-
- cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
+ int pdis, pcat, pnum;
+ cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
header[0] = pnum;
- header[1] = streamptr->record->level;
- header[2] = streamptr->record->date;
- header[3] = streamptr->record->time;
+ header[1] = record->level;
+ header[2] = record->date;
+ header[3] = record->time;
- xsize = gridInqXsize(gridID);
- ysize = gridInqYsize(gridID);
+ int xsize = gridInqXsize(gridID),
+ ysize = gridInqYsize(gridID);
if ( xsize == 0 || ysize == 0 )
{
xsize = gridInqSize(gridID);
@@ -184,7 +178,7 @@ void srvDefRecord(stream_t *streamptr)
header[6] = 0;
header[7] = 0;
- datatype = streamptr->record->prec;
+ int datatype = record->prec;
srvp->dprec = srvDefDatatype(datatype);
@@ -215,15 +209,16 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
record->param = param;
record->ilevel = level;
- grid_t grid;
- memset(&grid, 0, sizeof(grid_t));
- grid.type = GRID_GENERIC;
- grid.size = xsize*ysize;
- grid.xsize = xsize;
- grid.ysize = ysize;
- grid.xvals = NULL;
- grid.yvals = NULL;
- int gridID = varDefGrid(vlistID, &grid, 0);
+ grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
+ grid_init(grid);
+ cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize);
+ grid->xsize = xsize;
+ grid->ysize = ysize;
+ grid->xvals = NULL;
+ grid->yvals = NULL;
+ struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
+ int gridID = gridAdded.Id;
+ if (!gridAdded.isNew) Free(grid);
/*
if ( level == 0 ) leveltype = ZAXIS_SURFACE;
else leveltype = ZAXIS_GENERIC;
@@ -253,38 +248,29 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys
static
void srvScanTimestep1(stream_t *streamptr)
{
- int header[8];
- int prec = 0;
- int status;
- int fileID;
- int rxsize = 0, rysize = 0;
- int param = 0;
- int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
DateTime datetime0 = { LONG_MIN, LONG_MIN };
- int tsID;
- int varID;
off_t recpos;
- int nrecords, nrecs, recID;
- int taxisID = -1;
taxis_t *taxis;
- int vlistID;
srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
streamptr->curTsID = 0;
- tsID = tstepsNewEntry(streamptr);
- taxis = &streamptr->tsteps[tsID].taxis;
+ {
+ int tsID = tstepsNewEntry(streamptr);
+ if ( tsID != 0 )
+ Error("Internal problem! tstepsNewEntry returns %d", tsID);
+ taxis = &streamptr->tsteps[tsID].taxis;
+ }
- if ( tsID != 0 )
- Error("Internal problem! tstepsNewEntry returns %d", tsID);
- fileID = streamptr->fileID;
+ int fileID = streamptr->fileID;
- nrecs = 0;
+ int nrecs = 0;
while ( TRUE )
{
+ int header[8];
recpos = fileGetPos(fileID);
- status = srvRead(fileID, srvp);
+ int status = srvRead(fileID, srvp);
if ( status != 0 )
{
streamptr->ntsteps = 1;
@@ -294,15 +280,15 @@ void srvScanTimestep1(stream_t *streamptr)
srvInqHeader(srvp, header);
- prec = srvp->dprec;
- rcode = header[0];
- rlevel = header[1];
- vdate = header[2];
- vtime = header[3];
- rxsize = header[4];
- rysize = header[5];
+ int prec = srvp->dprec;
+ int rcode = header[0];
+ int rlevel = header[1];
+ int vdate = header[2];
+ int vtime = header[3];
+ int rxsize = header[4];
+ int rysize = header[5];
- param = cdiEncodeParam(rcode, 255, 255);
+ int param = cdiEncodeParam(rcode, 255, 255);
if ( nrecs == 0 )
{
@@ -311,11 +297,10 @@ void srvScanTimestep1(stream_t *streamptr)
}
else
{
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
if ( streamptr->tsteps[0].records[recID].param == param
&& streamptr->tsteps[0].records[recID].ilevel == rlevel )
- break;
- if ( recID < nrecs ) break;
+ goto tstepScanLoopFinished;
DateTime datetime = { .date = vdate, .time = vtime };
if ( datetimeCmp(datetime, datetime0) )
Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
@@ -329,21 +314,22 @@ void srvScanTimestep1(stream_t *streamptr)
srv_add_record(streamptr, param, rlevel, rxsize, rysize, recsize, recpos, prec);
}
+ tstepScanLoopFinished:
streamptr->rtsteps = 1;
cdi_generate_vars(streamptr);
- taxisID = taxisCreate(TAXIS_ABSOLUTE);
+ int taxisID = taxisCreate(TAXIS_ABSOLUTE);
taxis->type = TAXIS_ABSOLUTE;
taxis->vdate = (int)datetime0.date;
taxis->vtime = (int)datetime0.time;
- vlistID = streamptr->vlistID;
+ int vlistID = streamptr->vlistID;
vlistDefTaxis(vlistID, taxisID);
vlist_check_contents(vlistID);
- nrecords = streamptr->tsteps[0].nallrecs;
+ int nrecords = streamptr->tsteps[0].nallrecs;
if ( nrecords < streamptr->tsteps[0].recordSize )
{
streamptr->tsteps[0].recordSize = nrecords;
@@ -354,12 +340,12 @@ void srvScanTimestep1(stream_t *streamptr)
streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
streamptr->tsteps[0].nrecs = nrecords;
- for ( recID = 0; recID < nrecords; recID++ )
+ for ( int recID = 0; recID < nrecords; recID++ )
streamptr->tsteps[0].recIDs[recID] = recID;
if ( streamptr->ntsteps == -1 )
{
- tsID = tstepsNewEntry(streamptr);
+ int tsID = tstepsNewEntry(streamptr);
if ( tsID != streamptr->rtsteps )
Error("Internal error. tsID = %d", tsID);
@@ -372,10 +358,8 @@ void srvScanTimestep1(stream_t *streamptr)
if ( taxis->vdate == 0 && taxis->vtime == 0 )
{
streamptr->ntsteps = 0;
- for ( varID = 0; varID < streamptr->nvars; varID++ )
- {
- vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
- }
+ for ( int varID = 0; varID < streamptr->nvars; varID++ )
+ vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
}
}
}
diff --git a/libcdi/src/stream_write.c b/libcdi/src/stream_write.c
new file mode 100644
index 0000000..eef2129
--- /dev/null
+++ b/libcdi/src/stream_write.c
@@ -0,0 +1,431 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cdi.h"
+#include "cdi_int.h"
+#include "stream_grb.h"
+#include "stream_cdf.h"
+#include "stream_srv.h"
+#include "stream_ext.h"
+#include "stream_ieg.h"
+#include "dmemory.h"
+#include "namespace.h"
+
+
+/* the single image implementation */
+int cdiStreamWriteVar_(int streamID, int varID, int memtype, const void *data, int nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+
+ check_parg(data);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+ if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
+ Error("Writing of non-trivial subtypes not yet implemented!");
+
+ // check taxis
+ if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
+
+ int filetype = streamptr->filetype;
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_write_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteVarDP(streamptr, varID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_write_var(streamptr, varID, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ at Function streamWriteVar
+ at Title Write a variable
+
+ at Prototype void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamWriteVar writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVar(int streamID, int varID, const double *data, int nmiss)
+{
+ void (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+ const void *data, int nmiss)
+ = (void (*)(int, int, int, const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+
+ myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+}
+
+/*
+ at Function streamWriteVarF
+ at Title Write a variable
+
+ at Prototype void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item data Pointer to a block of single precision floating point data values to be written.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamWriteVarF writes the values of one time step of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
+{
+ int (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype,
+ const void *data, int nmiss)
+ = (int (*)(int, int, int, const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
+
+ if ( myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, (const void *) conversionBuffer, nmiss);
+ Free(conversionBuffer);
+ }
+}
+
+static
+int cdiStreamWriteVarSlice(int streamID, int varID, int levelID, int memtype, const void *data, int nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+
+ check_parg(data);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+ if (subtypeInqActiveIndex(streamptr->vars[varID].subtypeID) != 0)
+ Error("Writing of non-trivial subtypes not yet implemented!");
+
+ // check taxis
+ if ( streamptr->curTsID == CDI_UNDEFID ) streamDefTimestep(streamID, 0);
+
+ int filetype = streamptr->filetype;
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ {
+ grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ {
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteVarSliceDP(streamptr, varID, levelID, (double *)data);
+ break;
+ }
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
+ break;
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ at Function streamWriteVarSlice
+ at Title Write a horizontal slice of a variable
+
+ at Prototype void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamWriteVarSlice writes the values of a horizontal slice of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarSlice(int streamID, int varID, int levelID, const double *data, int nmiss)
+{
+ cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+}
+
+/*
+ at Function streamWriteVarSliceF
+ at Title Write a horizontal slice of a variable
+
+ at Prototype void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item varID Variable identifier.
+ @Item levelID Level identifier.
+ @Item data Pointer to a block of single precision floating point data values to be written.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamWriteVarSliceF writes the values of a horizontal slice of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteVarSliceF(int streamID, int varID, int levelID, const float *data, int nmiss)
+{
+ if ( cdiStreamWriteVarSlice(streamID, varID, levelID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ streamWriteVarSlice(streamID, varID, levelID, conversionBuffer, nmiss);
+ Free(conversionBuffer);
+ }
+}
+
+
+void
+streamWriteVarChunk(int streamID, int varID,
+ const int rect[][2], const double *data, int nmiss)
+{
+ void (*myCdiStreamWriteVarChunk_)(int streamID, int varID, int memtype,
+ const int rect[][2], const void *data,
+ int nmiss)
+ = (void (*)(int, int, int, const int [][2], const void *, int))
+ namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_CHUNK_).func;
+ myCdiStreamWriteVarChunk_(streamID, varID, MEMTYPE_DOUBLE, rect, data, nmiss);
+}
+
+/* single image implementation */
+void
+cdiStreamWriteVarChunk_(int streamID, int varID, int memtype,
+ const int rect[][2], const void *data, int nmiss)
+{
+ if ( CDI_Debug ) Message("streamID = %d varID = %d", streamID, varID);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ // streamDefineTaxis(streamID);
+
+ int filetype = streamptr->filetype;
+
+ switch (filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+#endif
+#if defined (HAVE_LIBGRIB) || defined (HAVE_LIBSERVICE) \
+ || defined (HAVE_LIBEXTRA) || defined (HAVE_LIBIEG)
+ xabort("streamWriteVarChunk not implemented for filetype %s!",
+ strfiletype(filetype));
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ cdf_write_var_chunk(streamptr, varID, memtype, rect, data, nmiss);
+ break;
+#endif
+ default:
+ Error("%s support not compiled in!", strfiletype(filetype));
+ break;
+ }
+}
+
+static
+int stream_write_record(int streamID, int memtype, const void *data, int nmiss)
+{
+ // May fail if memtype == MEMTYPE_FLOAT and the file format does not support single precision writing.
+ // A value > 0 is returned in this case, otherwise it returns zero.
+ int status = 0;
+
+ check_parg(data);
+
+ stream_t *streamptr = stream_to_pointer(streamID);
+
+ switch (streamptr->filetype)
+ {
+#if defined (HAVE_LIBGRIB)
+ case FILETYPE_GRB:
+ case FILETYPE_GRB2:
+ grb_write_record(streamptr, memtype, data, nmiss);
+ break;
+#endif
+#if defined (HAVE_LIBSERVICE)
+ case FILETYPE_SRV:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ srvWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBEXTRA)
+ case FILETYPE_EXT:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ extWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBIEG)
+ case FILETYPE_IEG:
+ if ( memtype == MEMTYPE_FLOAT ) return 1;
+ iegWriteRecord(streamptr, (const double *)data);
+ break;
+#endif
+#if defined (HAVE_LIBNETCDF)
+ case FILETYPE_NC:
+ case FILETYPE_NC2:
+ case FILETYPE_NC4:
+ case FILETYPE_NC4C:
+ {
+ cdf_write_record(streamptr, memtype, data, nmiss);
+ break;
+ }
+#endif
+ default:
+ {
+ Error("%s support not compiled in!", strfiletype(streamptr->filetype));
+ break;
+ }
+ }
+
+ return status;
+}
+
+/*
+ at Function streamWriteRecord
+ at Title Write a horizontal slice of a variable
+
+ at Prototype void streamWriteRecord(int streamID, const double *data, int nmiss)
+ at Parameter
+ @Item streamID Stream ID, from a previous call to @fref{streamOpenWrite}.
+ @Item data Pointer to a block of double precision floating point data values to be written.
+ @Item nmiss Number of missing values.
+
+ at Description
+The function streamWriteRecord writes the values of a horizontal slice (record) of a variable to an open dataset.
+The values are converted to the external data type of the variable, if necessary.
+ at EndFunction
+*/
+void streamWriteRecord(int streamID, const double *data, int nmiss)
+{
+ stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+}
+
+
+void streamWriteRecordF(int streamID, const float *data, int nmiss)
+{
+ if ( stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
+ {
+ // In case the file format does not support single precision writing,
+ // we fall back to double precision writing, converting the data on the fly.
+ stream_t *streamptr = stream_to_pointer(streamID);
+ int varID = streamptr->record->varID;
+ size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
+ double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
+ for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
+ streamWriteRecord(streamID, conversionBuffer, nmiss);
+ Free(conversionBuffer);
+ }
+}
+
diff --git a/libcdi/src/subtype.c b/libcdi/src/subtype.c
index 70cdf0d..9c14901 100644
--- a/libcdi/src/subtype.c
+++ b/libcdi/src/subtype.c
@@ -79,7 +79,7 @@ enum {
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR ATTRIBUTE LISTS */
+/* SUBROUTINES FOR ATTRIBUTE LISTS */
/* ------------------------------------------------------------------- */
@@ -211,7 +211,7 @@ static void subtypeAttsDuplicate(struct subtype_attr_t *a1, struct subtype_entry
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR LIST OF ENTRIES */
+/* SUBROUTINES FOR LIST OF ENTRIES */
/* ------------------------------------------------------------------- */
@@ -335,7 +335,7 @@ static void subtypeEntryDuplicate(struct subtype_entry_t *a1, subtype_t* dst)
/* ------------------------------------------------------------------- */
-/* SUBROUTINES FOR THE SUBTYPE ITSELF */
+/* SUBROUTINES FOR THE SUBTYPE ITSELF */
/* ------------------------------------------------------------------- */
/* Print-out subtype data structure together with its attributes. */
@@ -546,7 +546,7 @@ void subtypeDefEntryDataP(struct subtype_entry_t *subtype_entry_ptr, int key, in
/* ------------------------------------------------------------------- */
-/* IMPLEMENTATIONS FOR KEY-VALUE-PAIR QUERIES */
+/* IMPLEMENTATIONS FOR KEY-VALUE-PAIR QUERIES */
/* ------------------------------------------------------------------- */
@@ -595,7 +595,7 @@ subtype_query_t matchAND(subtype_query_t q1, subtype_query_t q2)
/* ------------------------------------------------------------------- */
-/* SPECIFIC IMPLEMENTATIONS FOR TILE SETS */
+/* SPECIFIC IMPLEMENTATIONS FOR TILE SETS */
/* ------------------------------------------------------------------- */
@@ -607,39 +607,39 @@ void tilesetInsertP(subtype_t *s1, subtype_t *s2)
{
if (s1 == NULL) Error("Internal error!");
if (s2 == NULL) Error("Internal error!");
- struct subtype_entry_t
+ struct subtype_entry_t
*entry1 = s1->entries,
*entry2 = s2->entries;
struct subtype_attr_t *att_ptr2;
/* test all entries of set 2 against set 1, to check if entry
already exists: */
- if (subtypeAttsCompare(s1->globals.atts, s2->globals.atts) != differ)
+ if (subtypeAttsCompare(s1->globals.atts, s2->globals.atts) != differ)
{
while (entry1 != NULL) {
- int found = 1;
- entry2 = s2->entries;
- while (entry2 != NULL) {
- found &= (subtypeAttsCompare(entry1->atts, entry2->atts) != differ);
- entry2 = entry2->next;
- }
- if (found)
- {
- return;
- }
- entry1 = entry1->next;
+ int found = 1;
+ entry2 = s2->entries;
+ while (entry2 != NULL) {
+ found &= (subtypeAttsCompare(entry1->atts, entry2->atts) != differ);
+ entry2 = entry2->next;
+ }
+ if (found)
+ {
+ return;
+ }
+ entry1 = entry1->next;
}
-
+
entry2 = s2->entries;
while (entry2 != NULL) {
- entry1 = subtypeEntryInsert(s1);
-
- att_ptr2 = entry2->atts;
- while (att_ptr2 != NULL) {
- (void) subtypeAttrInsert(entry1, att_ptr2->key, att_ptr2->val);
- att_ptr2 = att_ptr2->next;
- }
- entry2 = entry2->next;
+ entry1 = subtypeEntryInsert(s1);
+
+ att_ptr2 = entry2->atts;
+ while (att_ptr2 != NULL) {
+ (void) subtypeAttrInsert(entry1, att_ptr2->key, att_ptr2->val);
+ att_ptr2 = att_ptr2->next;
+ }
+ entry2 = entry2->next;
}
}
else
@@ -655,7 +655,7 @@ void tilesetInsertP(subtype_t *s1, subtype_t *s2)
/* ------------------------------------------------------------------- */
-/* IMPLEMENTATIONS FOR ROUTINES VISIBLE THROUGH CDI.H */
+/* IMPLEMENTATIONS FOR ROUTINES VISIBLE THROUGH CDI.H */
/* ------------------------------------------------------------------- */
@@ -750,22 +750,22 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion)
int match = 1;
/* test if this entry matches ALL criteria. */
for (int j=0; (j<criterion.nAND) && (match); j++)
- {
- if (CDI_Debug) Message("check criterion %d : %d --?-- %d", j,
- criterion.key_value_pairs[0][j], criterion.key_value_pairs[1][j]);
- struct subtype_attr_t* att_ptr =
- subtypeAttrFind(entry->atts, criterion.key_value_pairs[0][j]);
- if (att_ptr == NULL)
- {
- match = 0;
- if (CDI_Debug) Message("did not find %d", criterion.key_value_pairs[0][j]);
- }
- else
- {
- if (CDI_Debug) Message("found %d", criterion.key_value_pairs[0][j]);
- match &= (att_ptr->val == criterion.key_value_pairs[1][j]);
- }
- }
+ {
+ if (CDI_Debug) Message("check criterion %d : %d --?-- %d", j,
+ criterion.key_value_pairs[0][j], criterion.key_value_pairs[1][j]);
+ struct subtype_attr_t* att_ptr =
+ subtypeAttrFind(entry->atts, criterion.key_value_pairs[0][j]);
+ if (att_ptr == NULL)
+ {
+ match = 0;
+ if (CDI_Debug) Message("did not find %d", criterion.key_value_pairs[0][j]);
+ }
+ else
+ {
+ if (CDI_Debug) Message("found %d", criterion.key_value_pairs[0][j]);
+ match &= (att_ptr->val == criterion.key_value_pairs[1][j]);
+ }
+ }
if (match) return entry->self;
}
entry = entry->next;
@@ -777,10 +777,50 @@ int subtypeInqSubEntry(int subtypeID, subtype_query_t criterion)
int subtypeInqTile(int subtypeID, int tileindex, int attribute)
{
return subtypeInqSubEntry(subtypeID,
- matchAND(keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], tileindex),
- keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], attribute)));
+ matchAND(keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEINDEX], tileindex),
+ keyValuePair(cdiSubtypeAttributeName[SUBTYPE_ATT_TILEATTRIBUTE], attribute)));
}
+int subtypeInqAttribute(int subtypeID, int index, const char* key, int* outValue)
+{
+ //Validate input params.
+ if(subtypeID == CDI_UNDEFID) xabort("CDI_UNDEFID was passed to %s() as a subtypeID. Please check the origin of that ID.", __func__);
+ subtype_t *subtype_ptr = (subtype_t *)reshGetVal(subtypeID, &subtypeOps);
+ if(!subtype_ptr) xabort("Internal error: subtypeID %d resolved to NULL.", subtypeID);
+
+ if((unsigned)index >= (unsigned)subtype_ptr->nentries)
+ {
+ xabort("index argument of %s() is out of range. Expected 0 <= index < %d, but got index = %d.", __func__, subtype_ptr->nentries, index);
+ }
+
+#ifndef __cplusplus
+ if(!outValue) outValue = &(int){0};
+#else
+ int dummy = 0;
+ if(!outValue) outValue = &dummy;
+#endif
+
+ if(!key) return CDI_EINVAL;
+ int iKey = attribute_to_index(key);
+ if(iKey < 0) return CDI_EINVAL;
+
+ //Find the entry.
+ struct subtype_entry_t* entry = subtype_ptr->entries;
+ for(; index--; entry = entry->next) if(!entry) xabort("internal error: preliminary end of subtype entry list");
+
+ //Find the attribute.
+ for(struct subtype_attr_t* attribute = entry->atts; attribute; attribute = attribute->next)
+ {
+ if(attribute->key == iKey)
+ {
+ *outValue = attribute->val;
+ return CDI_NOERR;
+ }
+ }
+
+ //Failed to find the attribute if this point is reached.
+ return CDI_EINVAL;
+}
/* Construct a new subtype for a tile set. If a corresponding subtype
* already exists, then we return this subtype ID instead.
@@ -837,7 +877,7 @@ int vlistInsertTrivialTileSubtype(int vlistID)
/* ------------------------------------------------------------------- */
-/* NOT YET IMPLEMENTED */
+/* NOT YET IMPLEMENTED */
/* ------------------------------------------------------------------- */
static int subtypeGetPackSize( void * subtype_ptr, void *context)
diff --git a/libcdi/src/table.c b/libcdi/src/table.c
index 2babc18..a3eb991 100644
--- a/libcdi/src/table.c
+++ b/libcdi/src/table.c
@@ -360,7 +360,7 @@ int tableRead(const char *tablefile)
*/
if ( id == 0 ) continue;
- while ( isdigit((int) *pline) ) pline++;
+ while ( isdigit((int) *pline) ) pline++;
if ( strchr(pline, '|') )
err = decodeForm2(pline, name, longname, units);
@@ -369,7 +369,7 @@ int tableRead(const char *tablefile)
if ( err ) continue;
- if ( name[0] ) sprintf(name, "var%d", id);
+ if ( name[0] == 0 ) sprintf(name, "var%d", id);
tableDefEntry(tableID, id, name, longname, units);
}
diff --git a/libcdi/src/table.h b/libcdi/src/table.h
index faebeff..0c624f8 100644
--- a/libcdi/src/table.h
+++ b/libcdi/src/table.h
@@ -1,3 +1,4 @@
+/* Automatically generated, do not edit! */
#ifndef _TABLE_H
#define _TABLE_H
@@ -552,177 +553,177 @@ static const PAR mpiom1[] = {
};
static const PAR ecmwf[] = {
- { 1, 0, "STRF", "Stream function", "m**2 s**-1" },
- { 2, 0, "VPOT", "Velocity potential", "m**2 s**-1" },
- { 3, 0, "PT", "Potential temperature", "K" },
- { 4, 0, "EQPT", "Equivalent potential temperature", "K" },
- { 5, 0, "SEPT", "Saturated equivalent potential temperature", "K" },
- { 11, 0, "UDVW", "U component of divergent wind", "m s**-1" },
- { 12, 0, "VDVW", "V component of divergent wind", "m s**-1" },
- { 13, 0, "URTW", "U component of rotational wind", "m s**-1" },
- { 14, 0, "VRTW", "V component of rotational wind", "m s**-1" },
- { 21, 0, "UCTP", "Unbalanced component of temperature", "K" },
- { 22, 0, "UCLN", "Unbalanced component of logarithm of surface pressure", NULL },
- { 23, 0, "UCDV", "Unbalanced component of divergence", "s**-1" },
- { 26, 0, "CL", "Lake cover", NULL },
- { 27, 0, "CVL", "Low vegetation cover", NULL },
- { 28, 0, "CVH", "High vegetation cover", NULL },
- { 29, 0, "TVL", "Type of low vegetation", NULL },
- { 30, 0, "TVH", "Type of high vegetation", NULL },
- { 31, 0, "CI", "Sea-ice cover", NULL },
- { 32, 0, "ASN", "Snow albedo", NULL },
- { 33, 0, "RSN", "Snow density kg", "m**-3" },
- { 34, 0, "SSTK", "Sea surface temperature", "K" },
- { 35, 0, "ISTL1", "Ice surface temperature layer 1", "K" },
- { 36, 0, "ISTL2", "Ice surface temperature layer 2", "K" },
- { 37, 0, "ISTL3", "Ice surface temperature layer 3", "K" },
- { 38, 0, "ISTL4", "Ice surface temperature layer 4", "K" },
- { 39, 0, "SWVL1", "Volumetric soil water layer 1", "m**3 m**-3" },
- { 40, 0, "SWVL2", "Volumetric soil water layer 2", "m**3 m**-3" },
- { 41, 0, "SWVL3", "Volumetric soil water layer 3", "m**3 m**-3" },
- { 42, 0, "SWVL4", "Volumetric soil water layer 4", "m**3 m**-3" },
- { 43, 0, "SLT", "Soil type", NULL },
- { 44, 0, "ES", "Snow evaporation m of water", NULL },
- { 45, 0, "SMLT", "Snowmelt m of water", NULL },
- { 46, 0, "SDUR", "Solar duration", "s" },
- { 47, 0, "DSRP", "Direct solar radiation", "w m**-2" },
- { 48, 0, "MAGSS", "Magnitude of surface stress", "N m**-2 s" },
- { 49, 0, "WG10", "Wind gust at 10 metres", "m s**-1" },
- { 50, 0, "LSPF", "Large-scale precipitation fraction", "s" },
- { 51, 0, "MX2T24", "Maximum 2 metre temperature", "K" },
- { 52, 0, "MN2T24", "Minimum 2 metre temperature", "K" },
- { 53, 0, "MONT", "Montgomery potential", "m**2 s**-2" },
- { 54, 0, "PRES", "Pressure", "Pa" },
- { 55, 0, "MN2T24", "Mean 2 metre temperature past 24 hours", "K" },
- { 56, 0, "MN2D24", "Mean 2 metre dewpoint temperature past 24 hours", "K" },
- { 60, 0, "PV", "Potential vorticity", "K m**2 kg**-1 s**-1" },
- { 127, 0, "AT", "Atmospheric tide", NULL },
- { 128, 0, "BV", "Budget values", NULL },
- { 129, 0, "Z", "Geopotential", "m**2 s**-2" },
- { 130, 0, "T", "Temperature", "K" },
- { 131, 0, "U", "U velocity", "m s**-1" },
- { 132, 0, "V", "V velocity", "m s**-1" },
- { 133, 0, "Q", "Specific humidity", "kg kg**-1" },
- { 134, 0, "SP", "Surface pressure", "Pa" },
- { 135, 0, "W", "Vertical velocity", "Pa s**-1" },
- { 136, 0, "TCW", "Total column water", "kg m**-2" },
- { 137, 0, "TCWV", "Total column water vapour", "kg m**-2" },
- { 138, 0, "VO", "Vorticity (relative)", "s**-1" },
- { 139, 0, "STL1", "Soil temperature level 1", "K" },
- { 140, 0, "SWL1", "Soil wetness level 1 m of water", NULL },
- { 141, 0, "SD", "Snow depth 1 m of water equivalent", NULL },
- { 142, 0, "LSP", "Stratiform precipitation (Large scale precipitation)", "m" },
- { 143, 0, "CP", "Convective precipitation", "m" },
- { 144, 0, "SF", "Snowfall (convective + stratiform)", "m" },
- { 145, 0, "BLD", "Boundary layer dissipation", "W m**-2 s" },
- { 146, 0, "SSHF", "Surface sensible heat flux", "W m**-2 s" },
- { 147, 0, "SLHF", "Surface latent heat flux", "W m**-2 s" },
- { 148, 0, "CHNK", "Charnock", NULL },
- { 149, 0, "SNR", "Surface net radiation", "W m**-2 s" },
- { 150, 0, "TNR", "Top net radiation", NULL },
- { 151, 0, "MSL", "Mean sea-level pressure", "Pa" },
- { 152, 0, "LNSP", "Logarithm of surface pressure", NULL },
- { 153, 0, "SWHR", "Short-wave heating rate", "K" },
- { 154, 0, "LWHR", "Long-wave heating rate", "K" },
- { 155, 0, "D", "Divergence", "s**-1" },
- { 156, 0, "GH", "Height m Geopotential height", NULL },
- { 157, 0, "R", "Relative humidity", "%" },
- { 158, 0, "TSP", "Tendency of surface pressure", "Pa s**-1" },
- { 159, 0, "BLH", "Boundary layer height", "m" },
- { 160, 0, "SDOR", "Standard deviation of orography", NULL },
- { 161, 0, "ISOR", "Anisotropy of sub-gridscale orography", NULL },
- { 162, 0, "ANOR", "Angle of sub-gridscale orography", "rad" },
- { 163, 0, "SLOR", "Slope of sub-gridscale orography", NULL },
- { 164, 0, "TCC", "Total cloud cover", NULL },
- { 165, 0, "U10M", "10 metre U wind component", "m s**-1" },
- { 166, 0, "V10M", "10 metre V wind component", "m s**-1" },
- { 167, 0, "T2M", "2 metre temperature", "K" },
- { 168, 0, "D2M", "2 metre dewpoint temperature", "K" },
- { 169, 0, "SSRD", "Surface solar radiation downwards", "W m**-2 s" },
- { 170, 0, "STL2", "Soil temperature level 2", "K" },
- { 171, 0, "SWL2", "Soil wetness level 2", "m of water" },
- { 172, 0, "LSM", "Land/sea mask", NULL },
- { 173, 0, "SR", "Surface roughness", "m" },
- { 174, 0, "AL", "Albedo", NULL },
- { 175, 0, "STRD", "Surface thermal radiation downwards", "W m**-2 s" },
- { 176, 0, "SSR", "Surface solar radiation", "W m**-2 s" },
- { 177, 0, "STR", "Surface thermal radiation", "W m**-2 s" },
- { 178, 0, "TSR", "Top solar radiation", "W m**-2 s" },
- { 179, 0, "TTR", "Top thermal radiation", "W m**-2 s" },
- { 180, 0, "EWSS", "East/West surface stress", "N m**-2 s" },
- { 181, 0, "NSSS", "North/South surface stress", "N m**-2 s" },
- { 182, 0, "E", "Evaporation", "m of water" },
- { 183, 0, "STL3", "Soil temperature level 3", "K" },
- { 184, 0, "SWL3", "Soil wetness level 3", "m of water" },
- { 185, 0, "CCC", "Convective cloud cover", NULL },
- { 186, 0, "LCC", "Low cloud cover", NULL },
- { 187, 0, "MCC", "Medium cloud cover", NULL },
- { 188, 0, "HCC", "High cloud cover", NULL },
- { 189, 0, "SUND", "Sunshine duration", "s" },
- { 190, 0, "EWOV", "EW component of subgrid orographic variance", "m**2" },
- { 191, 0, "NSOV", "NS component of subgrid orographic variance", "m**2" },
- { 192, 0, "NWOV", "NWSE component of subgrid orographic variance", "m**2" },
- { 193, 0, "NEOV", "NESW component of subgrid orographic variance", "m**2" },
- { 194, 0, "BTMP", "Brightness temperature", "K" },
- { 195, 0, "LGWS", "Lat. component of gravity wave stress", "N m**-2 s" },
- { 196, 0, "MGWS", "Meridional component of gravity wave stress", "N m**-2 s" },
- { 197, 0, "GWD", "Gravity wave dissipation", "W m**-2 s" },
- { 198, 0, "SRC", "Skin reservoir content", "m of water" },
- { 199, 0, "VEG", "Vegetation fraction", NULL },
- { 200, 0, "VSO", "Variance of sub-gridscale orography", "m**2" },
- { 201, 0, "MX2T", "Maximum 2 metre temperature since previous post-processing", "K" },
- { 202, 0, "MN2T", "Minimum 2 metre temperature since previous post-processing", "K" },
- { 203, 0, "O3", "Ozone mass mixing ratio", "kg kg**-1" },
- { 204, 0, "PAW", "Precipiation analysis weights", NULL },
- { 205, 0, "RO", "Runoff", "m" },
- { 206, 0, "TCO3", "Total column ozone", "kg m**-2" },
- { 207, 0, "WS10", "10 meter windspeed", "m s**-1" },
- { 208, 0, "TSRC", "Top net solar radiation, clear sky", "W m**-2" },
- { 209, 0, "TTRC", "Top net thermal radiation, clear sky", "W m**-2" },
- { 210, 0, "SSRC", "Surface net solar radiation, clear sky", "W m**-2" },
- { 211, 0, "STRC", "Surface net thermal radiation, clear sky", "W m**-2" },
- { 212, 0, "SI", "Solar insolation", "W m**-2" },
- { 214, 0, "DHR", "Diabatic heating by radiation", "K" },
- { 215, 0, "DHVD", "Diabatic heating by vertical diffusion", "K" },
- { 216, 0, "DHCC", "Diabatic heating by cumulus convection", "K" },
- { 217, 0, "DHLC", "Diabatic heating large-scale condensation", "K" },
- { 218, 0, "VDZW", "Vertical diffusion of zonal wind", "m s**-1" },
- { 219, 0, "VDMW", "Vertical diffusion of meridional wind", "m s**-1" },
- { 220, 0, "EWGD", "EW gravity wave drag tendency", "m s**-1" },
- { 221, 0, "NSGD", "NS gravity wave drag tendency", "m s**-1" },
- { 222, 0, "CTZW", "Convective tendency of zonal wind", "m s**-1" },
- { 223, 0, "CTMW", "Convective tendency of meridional wind", "m s**-1" },
- { 224, 0, "VDH", "Vertical diffusion of humidity", "kg kg**-1" },
- { 225, 0, "HTCC", "Humidity tendency by cumulus convection", "kg kg**-1" },
- { 226, 0, "HTLC", "Humidity tendency large-scale condensation", "kg kg**-1" },
- { 227, 0, "CRNH", "Change from removing negative humidity", "kg kg**-1" },
- { 228, 0, "TP", "Total precipitation", "m" },
- { 229, 0, "IEWS", "Instantaneous X surface stress", "N m**-2" },
- { 230, 0, "INSS", "Instantaneous Y surface stress", "N m**-2" },
- { 231, 0, "ISHF", "Instantaneous surface heat flux", "W m**-2" },
- { 232, 0, "IE", "Instantaneous moisture flux", "kg m**-2 s" },
- { 233, 0, "ASQ", "Apparent surface humidity", "kg kg**-1" },
- { 234, 0, "LSRH", "Logarithm of surface roughness length for heat", NULL },
- { 235, 0, "SKT", "Skin temperature", "K" },
- { 236, 0, "STL4", "Soil temperature level 4", "K" },
- { 237, 0, "SWL4", "Soil wetness level 4", "m" },
- { 238, 0, "TSN", "Temperature of snow layer", "K" },
- { 239, 0, "CSF", "Convective snowfall", "m of water equivalent" },
- { 240, 0, "LSF", "Large-scale snowfall", "m of water equivalent" },
- { 241, 0, "ACF", "Accumulated cloud fraction tendency", NULL },
- { 242, 0, "ALW", "Accumulated liquid water tendency", NULL },
- { 243, 0, "FAL", "Forecast albedo", NULL },
- { 244, 0, "FSR", "Forecast surface roughness", "m" },
- { 245, 0, "FLSR", "Forecast log of surface roughness for heat", NULL },
- { 246, 0, "CLWC", "Cloud liquid water content", "kg kg**-1" },
- { 247, 0, "CIWC", "Cloud ice water content", "kg kg**-1" },
- { 248, 0, "CC", "Cloud cover", NULL },
- { 249, 0, "AIW", "Accumulated ice water tendency", NULL },
- { 250, 0, "ICE", "Ice age", NULL },
- { 251, 0, "ATTE", "Adiabatic tendency of temperature", "K" },
- { 252, 0, "ATHE", "Adiabatic tendency of humidity", "kg kg**-1" },
- { 253, 0, "ATZE", "Adiabatic tendency of zonal wind", "m s**-1" },
- { 254, 0, "ATMW", "Adiabatic tendency of meridional wind", "m s**-1" },
+ { 1, 0, "STRF", "Stream function", "m**2 s**-1" },
+ { 2, 0, "VPOT", "Velocity potential", "m**2 s**-1" },
+ { 3, 0, "PT", "Potential temperature", "K" },
+ { 4, 0, "EQPT", "Equivalent potential temperature", "K" },
+ { 5, 0, "SEPT", "Saturated equivalent potential temperature", "K" },
+ { 11, 0, "UDVW", "U component of divergent wind", "m s**-1" },
+ { 12, 0, "VDVW", "V component of divergent wind", "m s**-1" },
+ { 13, 0, "URTW", "U component of rotational wind", "m s**-1" },
+ { 14, 0, "VRTW", "V component of rotational wind", "m s**-1" },
+ { 21, 0, "UCTP", "Unbalanced component of temperature", "K" },
+ { 22, 0, "UCLN", "Unbalanced component of logarithm of surface pressure", NULL },
+ { 23, 0, "UCDV", "Unbalanced component of divergence", "s**-1" },
+ { 26, 0, "CL", "Lake cover", NULL },
+ { 27, 0, "CVL", "Low vegetation cover", NULL },
+ { 28, 0, "CVH", "High vegetation cover", NULL },
+ { 29, 0, "TVL", "Type of low vegetation", NULL },
+ { 30, 0, "TVH", "Type of high vegetation", NULL },
+ { 31, 0, "CI", "Sea-ice cover", NULL },
+ { 32, 0, "ASN", "Snow albedo", NULL },
+ { 33, 0, "RSN", "Snow density kg", "m**-3" },
+ { 34, 0, "SSTK", "Sea surface temperature", "K" },
+ { 35, 0, "ISTL1", "Ice surface temperature layer 1", "K" },
+ { 36, 0, "ISTL2", "Ice surface temperature layer 2", "K" },
+ { 37, 0, "ISTL3", "Ice surface temperature layer 3", "K" },
+ { 38, 0, "ISTL4", "Ice surface temperature layer 4", "K" },
+ { 39, 0, "SWVL1", "Volumetric soil water layer 1", "m**3 m**-3" },
+ { 40, 0, "SWVL2", "Volumetric soil water layer 2", "m**3 m**-3" },
+ { 41, 0, "SWVL3", "Volumetric soil water layer 3", "m**3 m**-3" },
+ { 42, 0, "SWVL4", "Volumetric soil water layer 4", "m**3 m**-3" },
+ { 43, 0, "SLT", "Soil type", NULL },
+ { 44, 0, "ES", "Snow evaporation m of water", NULL },
+ { 45, 0, "SMLT", "Snowmelt m of water", NULL },
+ { 46, 0, "SDUR", "Solar duration", "s" },
+ { 47, 0, "DSRP", "Direct solar radiation", "w m**-2" },
+ { 48, 0, "MAGSS", "Magnitude of surface stress", "N m**-2 s" },
+ { 49, 0, "WG10", "Wind gust at 10 metres", "m s**-1" },
+ { 50, 0, "LSPF", "Large-scale precipitation fraction", "s" },
+ { 51, 0, "MX2T24", "Maximum 2 metre temperature", "K" },
+ { 52, 0, "MN2T24", "Minimum 2 metre temperature", "K" },
+ { 53, 0, "MONT", "Montgomery potential", "m**2 s**-2" },
+ { 54, 0, "PRES", "Pressure", "Pa" },
+ { 55, 0, "MEAN2T24", "Mean 2 metre temperature past 24 hours", "K" },
+ { 56, 0, "MEAN2D24", "Mean 2 metre dewpoint temperature past 24 hours", "K" },
+ { 60, 0, "PV", "Potential vorticity", "K m**2 kg**-1 s**-1" },
+ { 127, 0, "AT", "Atmospheric tide", NULL },
+ { 128, 0, "BV", "Budget values", NULL },
+ { 129, 0, "Z", "Geopotential", "m**2 s**-2" },
+ { 130, 0, "T", "Temperature", "K" },
+ { 131, 0, "U", "U velocity", "m s**-1" },
+ { 132, 0, "V", "V velocity", "m s**-1" },
+ { 133, 0, "Q", "Specific humidity", "kg kg**-1" },
+ { 134, 0, "SP", "Surface pressure", "Pa" },
+ { 135, 0, "W", "Vertical velocity", "Pa s**-1" },
+ { 136, 0, "TCW", "Total column water", "kg m**-2" },
+ { 137, 0, "TCWV", "Total column water vapour", "kg m**-2" },
+ { 138, 0, "VO", "Vorticity (relative)", "s**-1" },
+ { 139, 0, "STL1", "Soil temperature level 1", "K" },
+ { 140, 0, "SWL1", "Soil wetness level 1 m of water", NULL },
+ { 141, 0, "SD", "Snow depth 1 m of water equivalent", NULL },
+ { 142, 0, "LSP", "Stratiform precipitation (Large scale precipitation)", "m" },
+ { 143, 0, "CP", "Convective precipitation", "m" },
+ { 144, 0, "SF", "Snowfall (convective + stratiform)", "m" },
+ { 145, 0, "BLD", "Boundary layer dissipation", "W m**-2 s" },
+ { 146, 0, "SSHF", "Surface sensible heat flux", "W m**-2 s" },
+ { 147, 0, "SLHF", "Surface latent heat flux", "W m**-2 s" },
+ { 148, 0, "CHNK", "Charnock", NULL },
+ { 149, 0, "SNR", "Surface net radiation", "W m**-2 s" },
+ { 150, 0, "TNR", "Top net radiation", NULL },
+ { 151, 0, "MSL", "Mean sea-level pressure", "Pa" },
+ { 152, 0, "LNSP", "Logarithm of surface pressure", NULL },
+ { 153, 0, "SWHR", "Short-wave heating rate", "K" },
+ { 154, 0, "LWHR", "Long-wave heating rate", "K" },
+ { 155, 0, "D", "Divergence", "s**-1" },
+ { 156, 0, "GH", "Height m Geopotential height", NULL },
+ { 157, 0, "R", "Relative humidity", "%" },
+ { 158, 0, "TSP", "Tendency of surface pressure", "Pa s**-1" },
+ { 159, 0, "BLH", "Boundary layer height", "m" },
+ { 160, 0, "SDOR", "Standard deviation of orography", NULL },
+ { 161, 0, "ISOR", "Anisotropy of sub-gridscale orography", NULL },
+ { 162, 0, "ANOR", "Angle of sub-gridscale orography", "rad" },
+ { 163, 0, "SLOR", "Slope of sub-gridscale orography", NULL },
+ { 164, 0, "TCC", "Total cloud cover", NULL },
+ { 165, 0, "U10M", "10 metre U wind component", "m s**-1" },
+ { 166, 0, "V10M", "10 metre V wind component", "m s**-1" },
+ { 167, 0, "T2M", "2 metre temperature", "K" },
+ { 168, 0, "D2M", "2 metre dewpoint temperature", "K" },
+ { 169, 0, "SSRD", "Surface solar radiation downwards", "W m**-2 s" },
+ { 170, 0, "STL2", "Soil temperature level 2", "K" },
+ { 171, 0, "SWL2", "Soil wetness level 2", "m of water" },
+ { 172, 0, "LSM", "Land/sea mask", NULL },
+ { 173, 0, "SR", "Surface roughness", "m" },
+ { 174, 0, "AL", "Albedo", NULL },
+ { 175, 0, "STRD", "Surface thermal radiation downwards", "W m**-2 s" },
+ { 176, 0, "SSR", "Surface solar radiation", "W m**-2 s" },
+ { 177, 0, "STR", "Surface thermal radiation", "W m**-2 s" },
+ { 178, 0, "TSR", "Top solar radiation", "W m**-2 s" },
+ { 179, 0, "TTR", "Top thermal radiation", "W m**-2 s" },
+ { 180, 0, "EWSS", "East/West surface stress", "N m**-2 s" },
+ { 181, 0, "NSSS", "North/South surface stress", "N m**-2 s" },
+ { 182, 0, "E", "Evaporation", "m of water" },
+ { 183, 0, "STL3", "Soil temperature level 3", "K" },
+ { 184, 0, "SWL3", "Soil wetness level 3", "m of water" },
+ { 185, 0, "CCC", "Convective cloud cover", NULL },
+ { 186, 0, "LCC", "Low cloud cover", NULL },
+ { 187, 0, "MCC", "Medium cloud cover", NULL },
+ { 188, 0, "HCC", "High cloud cover", NULL },
+ { 189, 0, "SUND", "Sunshine duration", "s" },
+ { 190, 0, "EWOV", "EW component of subgrid orographic variance", "m**2" },
+ { 191, 0, "NSOV", "NS component of subgrid orographic variance", "m**2" },
+ { 192, 0, "NWOV", "NWSE component of subgrid orographic variance", "m**2" },
+ { 193, 0, "NEOV", "NESW component of subgrid orographic variance", "m**2" },
+ { 194, 0, "BTMP", "Brightness temperature", "K" },
+ { 195, 0, "LGWS", "Lat. component of gravity wave stress", "N m**-2 s" },
+ { 196, 0, "MGWS", "Meridional component of gravity wave stress", "N m**-2 s" },
+ { 197, 0, "GWD", "Gravity wave dissipation", "W m**-2 s" },
+ { 198, 0, "SRC", "Skin reservoir content", "m of water" },
+ { 199, 0, "VEG", "Vegetation fraction", NULL },
+ { 200, 0, "VSO", "Variance of sub-gridscale orography", "m**2" },
+ { 201, 0, "MX2T", "Maximum 2 metre temperature since previous post-processing", "K" },
+ { 202, 0, "MN2T", "Minimum 2 metre temperature since previous post-processing", "K" },
+ { 203, 0, "O3", "Ozone mass mixing ratio", "kg kg**-1" },
+ { 204, 0, "PAW", "Precipiation analysis weights", NULL },
+ { 205, 0, "RO", "Runoff", "m" },
+ { 206, 0, "TCO3", "Total column ozone", "kg m**-2" },
+ { 207, 0, "WS10", "10 meter windspeed", "m s**-1" },
+ { 208, 0, "TSRC", "Top net solar radiation, clear sky", "W m**-2" },
+ { 209, 0, "TTRC", "Top net thermal radiation, clear sky", "W m**-2" },
+ { 210, 0, "SSRC", "Surface net solar radiation, clear sky", "W m**-2" },
+ { 211, 0, "STRC", "Surface net thermal radiation, clear sky", "W m**-2" },
+ { 212, 0, "SI", "Solar insolation", "W m**-2" },
+ { 214, 0, "DHR", "Diabatic heating by radiation", "K" },
+ { 215, 0, "DHVD", "Diabatic heating by vertical diffusion", "K" },
+ { 216, 0, "DHCC", "Diabatic heating by cumulus convection", "K" },
+ { 217, 0, "DHLC", "Diabatic heating large-scale condensation", "K" },
+ { 218, 0, "VDZW", "Vertical diffusion of zonal wind", "m s**-1" },
+ { 219, 0, "VDMW", "Vertical diffusion of meridional wind", "m s**-1" },
+ { 220, 0, "EWGD", "EW gravity wave drag tendency", "m s**-1" },
+ { 221, 0, "NSGD", "NS gravity wave drag tendency", "m s**-1" },
+ { 222, 0, "CTZW", "Convective tendency of zonal wind", "m s**-1" },
+ { 223, 0, "CTMW", "Convective tendency of meridional wind", "m s**-1" },
+ { 224, 0, "VDH", "Vertical diffusion of humidity", "kg kg**-1" },
+ { 225, 0, "HTCC", "Humidity tendency by cumulus convection", "kg kg**-1" },
+ { 226, 0, "HTLC", "Humidity tendency large-scale condensation", "kg kg**-1" },
+ { 227, 0, "CRNH", "Change from removing negative humidity", "kg kg**-1" },
+ { 228, 0, "TP", "Total precipitation", "m" },
+ { 229, 0, "IEWS", "Instantaneous X surface stress", "N m**-2" },
+ { 230, 0, "INSS", "Instantaneous Y surface stress", "N m**-2" },
+ { 231, 0, "ISHF", "Instantaneous surface heat flux", "W m**-2" },
+ { 232, 0, "IE", "Instantaneous moisture flux", "kg m**-2 s" },
+ { 233, 0, "ASQ", "Apparent surface humidity", "kg kg**-1" },
+ { 234, 0, "LSRH", "Logarithm of surface roughness length for heat", NULL },
+ { 235, 0, "SKT", "Skin temperature", "K" },
+ { 236, 0, "STL4", "Soil temperature level 4", "K" },
+ { 237, 0, "SWL4", "Soil wetness level 4", "m" },
+ { 238, 0, "TSN", "Temperature of snow layer", "K" },
+ { 239, 0, "CSF", "Convective snowfall", "m of water equivalent" },
+ { 240, 0, "LSF", "Large-scale snowfall", "m of water equivalent" },
+ { 241, 0, "ACF", "Accumulated cloud fraction tendency", NULL },
+ { 242, 0, "ALW", "Accumulated liquid water tendency", NULL },
+ { 243, 0, "FAL", "Forecast albedo", NULL },
+ { 244, 0, "FSR", "Forecast surface roughness", "m" },
+ { 245, 0, "FLSR", "Forecast log of surface roughness for heat", NULL },
+ { 246, 0, "CLWC", "Cloud liquid water content", "kg kg**-1" },
+ { 247, 0, "CIWC", "Cloud ice water content", "kg kg**-1" },
+ { 248, 0, "CC", "Cloud cover", NULL },
+ { 249, 0, "AIW", "Accumulated ice water tendency", NULL },
+ { 250, 0, "ICE", "Ice age", NULL },
+ { 251, 0, "ATTE", "Adiabatic tendency of temperature", "K" },
+ { 252, 0, "ATHE", "Adiabatic tendency of humidity", "kg kg**-1" },
+ { 253, 0, "ATZE", "Adiabatic tendency of zonal wind", "m s**-1" },
+ { 254, 0, "ATMW", "Adiabatic tendency of meridional wind", "m s**-1" },
};
static const PAR remo[] = {
@@ -1224,7 +1225,8 @@ static const PAR cosmo250[] = {
};
-static void tableDefault(void)
+static
+void tableDefault(void)
{
int tableID, instID, modelID;
@@ -1423,12 +1425,3 @@ static void tableDefault(void)
}
#endif /* _TABLE_H */
-/*
- * Local Variables:
- * c-file-style: "Java"
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * show-trailing-whitespace: t
- * require-trailing-newline: t
- * End:
- */
diff --git a/libcdi/src/taxis.c b/libcdi/src/taxis.c
index 20167ae..a0db8d5 100644
--- a/libcdi/src/taxis.c
+++ b/libcdi/src/taxis.c
@@ -1008,28 +1008,26 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
}
}
+
void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
{
- int year, month, day, hour, minute, second;
- int rdate, rtime;
- int timeunit;
- int calendar;
- int julday, secofday, days, secs;
+ int rdate = taxis->rdate;
+ int rtime = taxis->rtime;
- *vdate = 0;
- *vtime = 0;
-
- timeunit = (*taxis).unit;
- calendar = (*taxis).calendar;
-
- rdate = (*taxis).rdate;
- rtime = (*taxis).rtime;
-
- if ( rdate == 0 && rtime == 0 && DBL_IS_EQUAL(timevalue, 0.) ) return;
+ if ( DBL_IS_EQUAL(timevalue, 0.) )
+ {
+ *vdate = rdate;
+ *vtime = rtime;
+ return;
+ }
+ int year, month, day, hour, minute, second;
cdiDecodeDate(rdate, &year, &month, &day);
cdiDecodeTime(rtime, &hour, &minute, &second);
+ int timeunit = taxis->unit;
+ int calendar = taxis->calendar;
+
if ( timeunit == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
{
timeunit = TUNIT_DAY;
@@ -1038,24 +1036,22 @@ void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
{
- int nmon, dpm;
- double fmon;
-
if ( timeunit == TUNIT_YEAR ) timevalue *= 12;
- nmon = (int) timevalue;
- fmon = timevalue - nmon;
+ int nmon = (int) timevalue;
+ double fmon = timevalue - nmon;
month += nmon;
while ( month > 12 ) { month -= 12; year++; }
while ( month < 1 ) { month += 12; year--; }
- dpm = days_per_month(calendar, year, month);
+ int dpm = days_per_month(calendar, year, month);
timeunit = TUNIT_DAY;
timevalue = fmon*dpm;
}
+ int julday, secofday, days, secs;
encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday, &secofday);
cdiDecodeTimevalue(timeunit, timevalue, &days, &secs);
@@ -1414,50 +1410,49 @@ taxisPrintKernel(taxis_t * taxisptr, FILE * fp)
taxisInqVdateBounds ( taxisptr->self, &vdate_lb, &vdate_ub);
taxisInqVtimeBounds ( taxisptr->self, &vtime_lb, &vtime_ub);
- fprintf ( fp, "#\n");
- fprintf ( fp, "# taxisID %d\n", taxisptr->self);
- fprintf ( fp, "#\n");
- fprintf ( fp, "self = %d\n", taxisptr->self );
- fprintf ( fp, "used = %d\n", taxisptr->used );
- fprintf ( fp, "type = %d\n", taxisptr->type );
- fprintf ( fp, "vdate = %d\n", taxisptr->vdate );
- fprintf ( fp, "vtime = %d\n", taxisptr->vtime );
- fprintf ( fp, "rdate = %d\n", taxisptr->rdate );
- fprintf ( fp, "rtime = %d\n", taxisptr->rtime );
- fprintf ( fp, "fdate = %d\n", taxisptr->fdate );
- fprintf ( fp, "ftime = %d\n", taxisptr->ftime );
- fprintf ( fp, "calendar = %d\n", taxisptr->calendar );
- fprintf ( fp, "unit = %d\n", taxisptr->unit );
- fprintf ( fp, "numavg = %d\n", taxisptr->numavg );
- fprintf ( fp, "climatology = %d\n", taxisptr->climatology );
- fprintf ( fp, "has_bounds = %d\n", taxisptr->has_bounds );
- fprintf ( fp, "vdate_lb = %d\n", vdate_lb );
- fprintf ( fp, "vtime_lb = %d\n", vtime_lb );
- fprintf ( fp, "vdate_ub = %d\n", vdate_ub );
- fprintf ( fp, "vtime_ub = %d\n", vtime_ub );
- fprintf ( fp, "fc_unit = %d\n", taxisptr->fc_unit );
- fprintf ( fp, "fc_period = %g\n", taxisptr->fc_period );
- fprintf ( fp, "\n");
-}
-
-static void taxisPrint ( int taxisID )
-{
- taxis_t * taxisptr;
-
- taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
- taxisPrintKernel ( taxisptr, stdout );
+ fprintf(fp,
+ "#\n"
+ "# taxisID %d\n"
+ "#\n"
+ "self = %d\n"
+ "used = %d\n"
+ "type = %d\n"
+ "vdate = %d\n"
+ "vtime = %d\n"
+ "rdate = %d\n"
+ "rtime = %d\n"
+ "fdate = %d\n"
+ "ftime = %d\n"
+ "calendar = %d\n"
+ "unit = %d\n"
+ "numavg = %d\n"
+ "climatology = %d\n"
+ "has_bounds = %d\n"
+ "vdate_lb = %d\n"
+ "vtime_lb = %d\n"
+ "vdate_ub = %d\n"
+ "vtime_ub = %d\n"
+ "fc_unit = %d\n"
+ "fc_period = %g\n"
+ "\n", taxisptr->self, taxisptr->self,
+ taxisptr->used, taxisptr->type,
+ taxisptr->vdate, taxisptr->vtime,
+ taxisptr->rdate, taxisptr->rtime,
+ taxisptr->fdate, taxisptr->ftime,
+ taxisptr->calendar, taxisptr->unit,
+ taxisptr->numavg, taxisptr->climatology,
+ taxisptr->has_bounds,
+ vdate_lb, vtime_lb, vdate_ub, vtime_ub,
+ taxisptr->fc_unit, taxisptr->fc_period );
}
static int
taxisCompareP(void *taxisptr1, void *taxisptr2)
{
- taxis_t * t1, * t2;
-
- t1 = ( taxis_t * ) taxisptr1;
- t2 = ( taxis_t * ) taxisptr2;
+ const taxis_t *t1 = ( const taxis_t * ) taxisptr1,
+ *t2 = ( const taxis_t * ) taxisptr2;
- xassert ( t1 );
- xassert ( t2 );
+ xassert ( t1 && t2 );
return ! ( t1->used == t2->used &&
t1->type == t2->type &&
diff --git a/libcdi/src/timebase.h b/libcdi/src/timebase.h
index 00ebf34..2f750df 100644
--- a/libcdi/src/timebase.h
+++ b/libcdi/src/timebase.h
@@ -3,6 +3,10 @@
#include <inttypes.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* date format: YYYYMMDD */
/* time format: hhmmss */
@@ -22,6 +26,10 @@ double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *d
void encode_juldaysec(int calendar, int year, int month, int day, int hour, int minute, int second, int *julday, int *secofday);
void decode_juldaysec(int calendar, int julday, int secofday, int *year, int *month, int *day, int *hour, int *minute, int *second);
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _TIMEBASE_H */
/*
diff --git a/libcdi/src/util.c b/libcdi/src/util.c
index 25f4845..cd8a6d2 100644
--- a/libcdi/src/util.c
+++ b/libcdi/src/util.c
@@ -13,7 +13,7 @@
#include "cdi.h"
#include "cdi_int.h"
-#include "create_uuid.h"
+#include "cdi_uuid.h"
#include "dmemory.h"
#include "binary.h"
@@ -67,7 +67,8 @@ enum {
uuidNumHexChars = 36,
};
-void uuid2str(const unsigned char *uuid, char *uuidstr)
+
+void cdiUUID2Str(const unsigned char *uuid, char *uuidstr)
{
if ( uuid == NULL || uuidstr == NULL ) return;
@@ -82,7 +83,7 @@ void uuid2str(const unsigned char *uuid, char *uuidstr)
}
-int str2uuid(const char *uuidstr, unsigned char *uuid)
+int cdiStr2UUID(const char *uuidstr, unsigned char *uuid)
{
if ( uuid == NULL || uuidstr == NULL || strlen(uuidstr) != uuidNumHexChars)
return -1;
@@ -151,8 +152,7 @@ char* cdiUnescapeSpaces(const char* string, const char** outStringEnd)
#ifdef HAVE_DECL_UUID_GENERATE
#include <sys/time.h>
#include <uuid/uuid.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
static int uuid_seeded = 0;
static char uuid_rand_state[31 * sizeof (long)];
@@ -181,8 +181,7 @@ typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
#include <uuid.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
uint32_t status;
uuid_create((uuid_t *)(void *)uuid, &status);
@@ -194,8 +193,7 @@ create_uuid(unsigned char *uuid)
}
#else
#include <sys/time.h>
-void
-create_uuid(unsigned char *uuid)
+void cdiCreateUUID(unsigned char *uuid)
{
static int uuid_seeded = 0;
static char uuid_rand_state[31 * sizeof (long)];
diff --git a/libcdi/src/varscan.c b/libcdi/src/varscan.c
index e33e093..d89fa32 100644
--- a/libcdi/src/varscan.c
+++ b/libcdi/src/varscan.c
@@ -8,6 +8,7 @@
#include "cdi.h"
#include "cdi_int.h"
+#include "cdi_uuid.h"
#include "dmemory.h"
#include "resource_handle.h"
#include "varscan.h"
@@ -395,39 +396,22 @@ int varInsertTileSubtype(vartable_t *vptr, const var_tile_t *tiles)
{
if ( tiles == NULL ) return -1;
- int totalno_of_tileattr_pairs = -1;
- int tileClassification = -1;
- int numberOfTiles = -1;
- int numberOfAttributes = -1;
- int tileindex = -1;
- int attribute = -1;
-
- if ( tiles )
- {
- totalno_of_tileattr_pairs = tiles->totalno_of_tileattr_pairs;
- tileClassification = tiles->tileClassification;
- numberOfTiles = tiles->numberOfTiles;
- numberOfAttributes = tiles->numberOfAttributes;
- tileindex = tiles->tileindex;
- attribute = tiles->attribute;
- }
-
/* first, generate a subtype based on the info in "tiles". */
subtype_t *subtype_ptr;
subtypeAllocate(&subtype_ptr, SUBTYPE_TILES);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS, totalno_of_tileattr_pairs);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TILE_CLASSIFICATION , tileClassification);
- subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_NUMBER_OF_TILES , numberOfTiles);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS, tiles->totalno_of_tileattr_pairs);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TILE_CLASSIFICATION , tiles->tileClassification);
+ subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_NUMBER_OF_TILES , tiles->numberOfTiles);
/*
* Here, we create a tile set for comparison that contains only one
* tile/attribute pair (based on "tiles").
*/
struct subtype_entry_t *entry = subtypeEntryInsert(subtype_ptr);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_NUMBER_OF_ATTR, numberOfAttributes);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEINDEX, tileindex);
- subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEATTRIBUTE, attribute);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_NUMBER_OF_ATTR, tiles->numberOfAttributes);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEINDEX, tiles->tileindex);
+ subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEATTRIBUTE, tiles->attribute);
if (vptr->tiles == NULL) {
vptr->tiles = subtype_ptr;
@@ -957,7 +941,7 @@ struct varDefZAxisSearchState
int zaxistype;
int nlevels;
int lbounds;
- double *levels;
+ const double *levels;
const char *longname;
const char *units;
int ltype;
@@ -980,23 +964,19 @@ varDefZAxisSearch(int id, void *res, void *data)
}
-int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
- double *levels1, double *levels2, int vctsize, double *vct, char *name,
- char *longname, const char *units, int prec, int mode, int ltype1)
+int varDefZaxis(int vlistID, int zaxistype, int nlevels, const double *levels, int lbounds,
+ const double *levels1, const double *levels2, int vctsize, const double *vct, char *name,
+ const char *longname, const char *units, int prec, int mode, int ltype1)
{
/*
mode: 0 search in vlist and zaxis table
1 search in zaxis table
*/
int zaxisdefined = 0;
- int nzaxis;
int zaxisID = UNDEFID;
int zaxisglobdefined = 0;
- vlist_t *vlistptr;
-
- vlistptr = vlist_to_pointer(vlistID);
-
- nzaxis = vlistptr->nzaxis;
+ vlist_t *vlistptr = vlist_to_pointer(vlistID);
+ int nzaxis = vlistptr->nzaxis;
if ( mode == 0 )
for ( int index = 0; index < nzaxis; index++ )
@@ -1047,15 +1027,8 @@ int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbo
zaxisDefUbounds(zaxisID, levels2);
}
- if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
- {
- /* if ( vctsize > 0 && vctsize >= 2*(nlevels+1)) */
- /* if ( vctsize > 0 && vctsize >= 2*(nlevels)) */
- if ( vctsize > 0 )
- zaxisDefVct(zaxisID, vctsize, vct);
- else
- Warning("VCT missing");
- }
+ if ( (zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF) && vctsize > 0 )
+ zaxisDefVct(zaxisID, vctsize, vct);
zaxisDefName(zaxisID, name);
zaxisDefLongname(zaxisID, longname);
diff --git a/libcdi/src/varscan.h b/libcdi/src/varscan.h
index 366ceba..c992a7f 100644
--- a/libcdi/src/varscan.h
+++ b/libcdi/src/varscan.h
@@ -15,9 +15,9 @@ void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
void varDefVCT(size_t vctsize, double *vctptr);
void varDefZAxisReference(int nlev, int nvgrid, unsigned char uuid[CDI_UUID_SIZE]);
-int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
- double *levels1, double *levels2, int vctsize, double *vct, char *name,
- char *longname, const char *units, int prec, int mode, int ltype);
+int varDefZaxis(int vlistID, int zaxistype, int nlevels, const double *levels, int lbounds,
+ const double *levels1, const double *levels2, int vctsize, const double *vct, char *name,
+ const char *longname, const char *units, int prec, int mode, int ltype);
void varDefMissval(int varID, double missval);
void varDefCompType(int varID, int comptype);
diff --git a/libcdi/src/vlist.c b/libcdi/src/vlist.c
index 11e0822..f941413 100644
--- a/libcdi/src/vlist.c
+++ b/libcdi/src/vlist.c
@@ -93,7 +93,8 @@ vlist_t *vlist_to_pointer(int vlistID)
static
void vlist_init_entry(vlist_t *vlistptr)
{
- vlistptr->locked = 0;
+ vlistptr->immutable = 0;
+ vlistptr->internal = 0;
vlistptr->self = CDI_UNDEFID;
vlistptr->nvars = 0;
vlistptr->vars = NULL;
@@ -158,32 +159,22 @@ static
void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
{
int vlistID2 = vlistptr2->self;
+ int vlist2internal = vlistptr2->internal;
memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
+ vlistptr2->internal = vlist2internal; //the question who's responsible to destroy the vlist is tied to its containing memory region, so we retain this flag
+ vlistptr2->immutable = 0; //this is a copy, so it's mutable, independent of whether the original is mutable or not
vlistptr2->atts.nelems = 0;
vlistptr2->self = vlistID2;
}
-void vlist_lock(int vlistID)
+void cdiVlistMakeInternal(int vlistID)
{
- vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
- if ( !vlistptr->locked )
- {
- vlistptr->locked += 1;
- reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
- }
+ vlist_to_pointer(vlistID)->internal = 1;
}
-
-void vlist_unlock(int vlistID)
+void cdiVlistMakeImmutable(int vlistID)
{
- vlist_t *vlistptr = vlist_to_pointer(vlistID);
-
- if ( vlistptr->locked )
- {
- vlistptr->locked -= 1;
- reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE);
- }
+ vlist_to_pointer(vlistID)->immutable = 1;
}
/*
@@ -277,12 +268,25 @@ void vlistDestroy(int vlistID)
{
vlist_t *vlistptr = vlist_to_pointer(vlistID);
- if ( vlistptr->locked != 0 )
- Warning("Destroying of a locked object (vlistID=%d) failed!", vlistID);
+ if ( vlistptr->internal )
+ Warning("Attempt to destroy an internal vlist object by the user (vlistID=%d).", vlistID);
else
vlist_delete(vlistptr);
}
+// destroy an internal vlist object
+void cdiVlistDestroy_(int vlistID)
+{
+ vlist_t *vlistptr = vlist_to_pointer(vlistID);
+
+ if(!vlistptr->internal)
+ Warning("Destroying a vlist object that is owned by the user.\n"
+ "This is most likely because of a missing vlistDestroy() in the application code.\n"
+ "If that's not the case, and you are absolutely certain about it, please report the bug.");
+
+ vlist_delete(vlistptr);
+}
+
static
void var_copy_entries(var_t *var2, var_t *var1)
{
@@ -493,13 +497,8 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, const double *
zaxisDefUbounds(zaxisID, ubounds);
}
- if ( zaxistype == ZAXIS_HYBRID )
- {
- if ( vctsize > 0 )
- zaxisDefVct(zaxisID, vctsize, vct);
- else
- Warning("VCT missing");
- }
+ if ( zaxistype == ZAXIS_HYBRID && vctsize > 0 )
+ zaxisDefVct(zaxisID, vctsize, vct);
}
nzaxis = vlistptr->nzaxis;
@@ -730,12 +729,12 @@ void vlistCat(int vlistID2, int vlistID1)
var_copy_entries(&vars2[varID2], &vars1[varID]);
- int nlevs = zaxisInqSize(vars1[varID].zaxisID);
if ( vars1[varID].levinfo )
{
- vars2[varID2].levinfo = (levinfo_t *) Malloc((size_t)nlevs * sizeof(levinfo_t));
+ size_t nlevs = (size_t)zaxisInqSize(vars1[varID].zaxisID);
+ vars2[varID2].levinfo = (levinfo_t *) Malloc(nlevs * sizeof(levinfo_t));
memcpy(vars2[varID2].levinfo, vars1[varID].levinfo,
- (size_t)nlevs * sizeof(levinfo_t));
+ nlevs * sizeof(levinfo_t));
}
vars2[varID2].atts.nelems = 0;
@@ -1437,12 +1436,10 @@ int vlistSubtypeIndex(int vlistID, int subtypeID)
vlist_t *vlistptr = vlist_to_pointer(vlistID);
int index;
- for ( index = 0 ; index < vlistptr->nsubtypes ; index++ )
+ for(index = vlistptr->nsubtypes; index--; )
if ( subtypeID == vlistptr->subtypeIDs[index] ) break;
- if ( index == vlistptr->nsubtypes ) index = -1;
-
- return (index);
+ return index;
}
@@ -1519,6 +1516,7 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace,
xassert(!force_id || p->self == targetID);
if (!force_id)
targetID = p->self;
+ cdiVlistMakeInternal(p->self);
p->taxisID = namespaceAdaptKey(tempbuf[2], originNamespace);
p->tableID = tempbuf[3];
p->instID = namespaceAdaptKey(tempbuf[4], originNamespace);
diff --git a/libcdi/src/vlist.h b/libcdi/src/vlist.h
index 6fdd5cd..0179579 100644
--- a/libcdi/src/vlist.h
+++ b/libcdi/src/vlist.h
@@ -116,7 +116,10 @@ var_t;
typedef struct
{
- int locked;
+ //set when a vlist is passed to streamDefVlist() to safeguard against modifications of the wrong vlist object
+ bool immutable;
+ //set if this vlist has been created by CDI itself, and must not be destroyed by the user, consequently
+ bool internal;
int self;
int nvars; /* number of variables */
int ngrids;
@@ -138,15 +141,15 @@ vlist_t;
vlist_t *vlist_to_pointer(int vlistID);
+void cdiVlistMakeInternal(int vlistID);
+void cdiVlistMakeImmutable(int vlistID);
void vlistCheckVarID(const char *caller, int vlistID, int varID);
-const char *vlistInqVarNamePtr(int vlistID, int varID);
-const char *vlistInqVarLongnamePtr(int vlistID, int varID);
const char *vlistInqVarStdnamePtr(int vlistID, int varID);
-const char *vlistInqVarUnitsPtr(int vlistID, int varID);
void vlistDestroyVarName(int vlistID, int varID);
void vlistDestroyVarLongname(int vlistID, int varID);
void vlistDestroyVarStdname(int vlistID, int varID);
void vlistDestroyVarUnits(int vlistID, int varID);
+void cdiVlistDestroy_(int vlistID);
void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype);
int vlistInqVarMissvalUsed(int vlistID, int varID);
int vlistHasTime(int vlistID);
@@ -167,9 +170,6 @@ void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]);
int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum);
-void vlist_lock(int vlistID);
-void vlist_unlock(int vlistID);
-
void resize_opt_grib_entries(var_t *var, int nentries);
diff --git a/libcdi/src/vlist_var.c b/libcdi/src/vlist_var.c
index 0d0d309..3ad263e 100644
--- a/libcdi/src/vlist_var.c
+++ b/libcdi/src/vlist_var.c
@@ -637,7 +637,7 @@ The function @func{vlistInqVarStdname} returns the standard name of a variable i
otherwise the result is an empty string.
@Result
- at func{vlistInqVarName} returns the standard name of the variable to the parameter stdname.
+ at func{vlistInqVarStdname} returns the standard name of the variable to the parameter stdname.
@EndFunction
*/
@@ -1768,9 +1768,10 @@ void vlistDefVarIntKey(int vlistID, int varID, const char *name, int value)
if (vlistptr == NULL) Error("Internal error!");
int idx;
- if ( vlistptr->locked != 0 )
- Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
- "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+ if ( vlistptr->immutable )
+ Error("vlistDefVarIntKey() was called on an immutable vlist object (vlistID = %d)\n"
+ "Either call vlistDefVarIntKey() before passing the vlist object to streamDefVlist(),\n"
+ "or use the stream-internal vlist by calling streamInqVlist().", vlistID);
for ( idx=0; idx<vlistptr->vars[varID].opt_grib_nentries; idx++)
if ( (strcmp(name, vlistptr->vars[varID].opt_grib_kvpair[idx].keyword) == 0 ) &&
@@ -1830,9 +1831,10 @@ void vlistDefVarDblKey(int vlistID, int varID, const char *name, double value)
if (vlistptr == NULL) Error("Internal error!");
int idx;
- if ( vlistptr->locked != 0 )
- Error("User defined vlist object (vlistID=%d) isn't allowed!\n"
- "Need a CDI internal vlist object from streamInqVlist(streamID).", vlistID);
+ if ( vlistptr->immutable )
+ Error("vlistDefVarDblKey() was called on an immutable vlist object (vlistID = %d)\n"
+ "Either call vlistDefVarIntKey() before passing the vlist object to streamDefVlist(),\n"
+ "or use the stream-internal vlist by calling streamInqVlist().", vlistID);
for ( idx=0; idx<vlistptr->vars[varID].opt_grib_nentries; idx++)
if ( (strcmp(name, vlistptr->vars[varID].opt_grib_kvpair[idx].keyword) == 0 ) &&
@@ -2026,6 +2028,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB)
| FCMPFLT(validrange[0]) | FCMPFLT(validrange[1]);
#undef FCMP
#undef FCMPFLT
+#undef FCMPSTR
#undef FCMP2
if ((diff |= ((pva->levinfo == NULL) ^ (pvb->levinfo == NULL))))
return 1;
diff --git a/libcdi/src/zaxis.c b/libcdi/src/zaxis.c
index d61a5b9..10bdeaa 100644
--- a/libcdi/src/zaxis.c
+++ b/libcdi/src/zaxis.c
@@ -11,6 +11,7 @@
#include "cdi.h"
#include "cdi_cksum.h"
#include "cdi_int.h"
+#include "cdi_uuid.h"
#include "resource_handle.h"
#include "resource_unpack.h"
#include "varscan.h"
@@ -1194,7 +1195,6 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
unsigned char uuid[CDI_UUID_SIZE];
int levelID;
int nbyte;
- double level;
xassert ( zaxisptr );
@@ -1223,16 +1223,14 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
fprintf(fp, "%*s", nbyte0, "");
nbyte = nbyte0;
}
- level = zaxisInqLevel(zaxisID, levelID);
- nbyte += fprintf(fp, "%.9g ", level);
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->vals[levelID]);
}
fprintf(fp, "\n");
if ( zaxisptr->lbounds && zaxisptr->ubounds )
{
- double level1, level2;
+ nbyte0 = fprintf(fp, "lbounds = ");
nbyte = nbyte0;
- nbyte0 = fprintf(fp, "bounds = ");
for ( levelID = 0; levelID < nlevels; levelID++ )
{
if ( nbyte > 80 )
@@ -1241,27 +1239,35 @@ static void zaxisPrintKernel ( zaxis_t * zaxisptr, int index, FILE * fp )
fprintf(fp, "%*s", nbyte0, "");
nbyte = nbyte0;
}
- level1 = zaxisInqLbound(zaxisID, levelID);
- level2 = zaxisInqUbound(zaxisID, levelID);
- nbyte += fprintf(fp, "%.9g-%.9g ", level1, level2);
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->lbounds[levelID]);
+ }
+ fprintf(fp, "\n");
+
+ nbyte0 = fprintf(fp, "ubounds = ");
+ nbyte = nbyte0;
+ for ( levelID = 0; levelID < nlevels; levelID++ )
+ {
+ if ( nbyte > 80 )
+ {
+ fprintf(fp, "\n");
+ fprintf(fp, "%*s", nbyte0, "");
+ nbyte = nbyte0;
+ }
+ nbyte += fprintf(fp, "%.9g ", zaxisptr->ubounds[levelID]);
}
fprintf(fp, "\n");
}
if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
{
- int i;
- int vctsize;
- const double *vct;
-
- vctsize = zaxisptr->vctsize;
- vct = zaxisptr->vct;
+ int vctsize = zaxisptr->vctsize;
+ const double *vct = zaxisptr->vct;
fprintf(fp, "vctsize = %d\n", vctsize);
if ( vctsize )
{
nbyte0 = fprintf(fp, "vct = ");
nbyte = nbyte0;
- for ( i = 0; i < vctsize; i++ )
+ for ( int i = 0; i < vctsize; i++ )
{
if ( nbyte > 70 || i == vctsize/2 )
{
diff --git a/libcdi/tables/gen_tableheaderfile.in b/libcdi/tables/gen_tableheaderfile.in
index 0a393a2..54b3f8c 100755
--- a/libcdi/tables/gen_tableheaderfile.in
+++ b/libcdi/tables/gen_tableheaderfile.in
@@ -10,7 +10,8 @@ PTFILES=""
#
#########################################
#
-exec 3<"$DEFTABLES"
+rm -f "$OFILE"
+exec 3<"$DEFTABLES" 4>"$OFILE"
#
item=0
while read -u3 PTFILE[item] ; do
@@ -27,9 +28,9 @@ unset PTFILE[item]
#
#########################################
#
-rm -f $OFILE
#
-cat >> $OFILE <<EOF
+cat >&4 <<EOF
+/* Automatically generated, do not edit! */
#ifndef _TABLE_H
#define _TABLE_H
@@ -38,21 +39,20 @@ EOF
for TFILE in "${PTFILE[@]}"; do
echo "process: $TFILE"
rm -f ptfile
- ../app/createtable "$TFILE" - >>"$OFILE"
+ @abs_top_builddir@/app/createtable "$TFILE" - >&4
done
#
-cat >> $OFILE <<EOF
+cat >&4 <<EOF
-static void
-tableDefault(void)
+static
+void tableDefault(void)
{
int tableID, instID, modelID;
EOF
#
settabvar() {
- val=`grep $2 $1 | cut -f 2 -d "="`
- echo $val
+ grep "$2" "$1" | cut -f 2 -d "="
}
#
item=0
@@ -76,7 +76,7 @@ if [ -z $TABLE_SU ] ; then TABLE_SU=0; fi
echo "ID = $TABLE_ID name=$TABLE_NA model=$TABLE_MO inistitut=$TABLE_IN center=$TABLE_CE subcenter=$TABLE_SU"
TABLENAME=`echo ${TFBASENAME} | sed -e "s/\./_/g" `
#
-cat >> $OFILE <<EOF
+cat >&4 <<EOF
/*
* define table : ${TFBASENAME}
@@ -97,7 +97,7 @@ EOF
#
done
#
-cat >> $OFILE <<EOF
+cat >&4 <<EOF
}
#endif /* _TABLE_H */
diff --git a/libcdi/tests/cksum_read.c b/libcdi/tests/cksum_read.c
index 0b3493a..190b610 100644
--- a/libcdi/tests/cksum_read.c
+++ b/libcdi/tests/cksum_read.c
@@ -11,6 +11,10 @@
#include "var_cksum.h"
#include "stream_cksum.h"
+#ifdef __cplusplus
+#define PRIx32 ""
+#endif
+
static struct cksum_table *
read_table(const char *table_fname, size_t *table_len)
{
diff --git a/libcdi/tests/cksum_write.c b/libcdi/tests/cksum_write.c
index 0e87873..68e848c 100644
--- a/libcdi/tests/cksum_write.c
+++ b/libcdi/tests/cksum_write.c
@@ -12,6 +12,7 @@
#include <unistd.h>
#include "cdi.h"
+#include "cdi_uuid.h"
#include "cksum.h"
#include "simple_model_helper.h"
@@ -226,11 +227,10 @@ main(int argc, char *argv[])
/* add uuids to zaxis and grid */
{
unsigned char uuid[16];
- int str2uuid(const char *uuidstr, unsigned char *uuid);
static char gridUUIDTxt[] = "107d7a5b-348c-4d1a-90a9-d745914f2fb6";
- str2uuid(gridUUIDTxt, uuid);
+ cdiStr2UUID(gridUUIDTxt, uuid);
gridDefUUID(gridID, uuid);
static char zaxisUUIDTxt[2][37] = {
@@ -240,7 +240,7 @@ main(int argc, char *argv[])
for (int i = 0; i < 2; ++i)
{
- str2uuid(zaxisUUIDTxt[i], uuid);
+ cdiStr2UUID(zaxisUUIDTxt[i], uuid);
zaxisDefUUID(zaxisID[i], uuid);
}
}
diff --git a/libcdi/tests/deco2d_model.c b/libcdi/tests/deco2d_model.c
index f86cb0a..838d318 100644
--- a/libcdi/tests/deco2d_model.c
+++ b/libcdi/tests/deco2d_model.c
@@ -31,13 +31,14 @@ typedef int MPI_Comm;
#include "pio_write.h"
#include "simple_model_helper.h"
-#include "create_uuid.h"
+#include "cdi_uuid.h"
enum {
ntfiles = 2,
nproma = 16,
};
+
static void
modelRegionCompute(double region[], int nlev, int nlat, int nlon,
const int chunkStart[3], const int chunkSize[3],
@@ -148,10 +149,11 @@ modelRun(struct model_config setup, MPI_Comm comm)
lats[i] = ((double)(i * 180))/nlat - 90.0;
gridDefXvals ( gridID, lons );
gridDefYvals ( gridID, lats );
+ if (setup.create_uuid)
{
unsigned char uuid[CDI_UUID_SIZE];
if (rank == 0)
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
#if USE_MPI
MPI_Bcast(uuid, CDI_UUID_SIZE, MPI_UNSIGNED_CHAR, 0, comm);
#endif
@@ -197,10 +199,11 @@ modelRun(struct model_config setup, MPI_Comm comm)
= zaxisCreate(ZAXIS_PRESSURE, varDesc[varIdx].nlev);
zaxisDefLevels(varDesc[varIdx].zaxisID, levs);
}
+ if (setup.create_uuid)
{
unsigned char uuid[16];
if (rank == 0)
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
#if USE_MPI
MPI_Bcast(uuid, CDI_UUID_SIZE, MPI_UNSIGNED_CHAR, 0, comm);
#endif
@@ -213,6 +216,18 @@ modelRun(struct model_config setup, MPI_Comm comm)
= (size_t)nlon * (size_t)nlat * (size_t)varDesc[varIdx].nlev;
#ifdef USE_MPI
{
+ for (size_t i = 0; i < varIdx; ++i)
+ if (varDesc[i].nlev == varLevs)
+ {
+ varDesc[varIdx].redist4gather = varDesc[i].redist4gather;
+ varDesc[varIdx].partDesc = varDesc[i].partDesc;
+ for (size_t j = 0; j < 2; ++j)
+ {
+ varDesc[varIdx].start[j] = varDesc[i].start[j];
+ varDesc[varIdx].chunkSize[j] = varDesc[i].chunkSize[j];
+ }
+ goto partDescriptionSet;
+ }
int start[2], chunkSize[3], varSize[2] = { nlon, nlat };
for (size_t i = 0; i < 2; ++i)
{
@@ -229,13 +244,6 @@ modelRun(struct model_config setup, MPI_Comm comm)
Xt_int varSizeXt[3] = { (Xt_int)nlon, (Xt_int)nlat, (Xt_int)varLevs };
chunkSize[2] = varLevs;
Xt_int varStartXt[3] = { start[0], start[1], 0 };
- for (size_t i = 0; i < varIdx; ++i)
- if (varDesc[i].nlev == varLevs)
- {
- varDesc[varIdx].redist4gather = varDesc[i].redist4gather;
- varDesc[varIdx].partDesc = varDesc[i].partDesc;
- goto gatherRedistSet;
- }
Xt_idxlist part_idxlist
= xt_idxsection_new(0, (varLevs > 1 ? 3 : 2), varSizeXt,
chunkSize, varStartXt),
@@ -274,7 +282,7 @@ modelRun(struct model_config setup, MPI_Comm comm)
Free(src_blocks);
xt_xmap_delete(xmap4gather);
}
- gatherRedistSet: ;
+ partDescriptionSet: ;
}
#endif
varDesc[varIdx].code = GRIB_USERDEF + (int)varIdx;
@@ -316,6 +324,14 @@ modelRun(struct model_config setup, MPI_Comm comm)
taxisDefVdate(taxisID, vdatetime[1]);
taxisDefVtime(taxisID, vdatetime[0]);
streamDefTimestep ( streamID, tsID );
+ if (setup.filetype == FILETYPE_EXT)
+ {
+ /* EXTRA doesn't store time, only date
+ * set the value to 0 before checksumming, because a
+ * time field of 0 is what reading an EXTRA file will
+ * return */
+ vdatetime[0] = 0;
+ }
for (size_t varIdx = 0; varIdx < nVars; ++varIdx)
{
size_t varLevs = (size_t)varDesc[varIdx].nlev;
diff --git a/libcdi/tests/pio_write.c b/libcdi/tests/pio_write.c
index b78463c..360f296 100644
--- a/libcdi/tests/pio_write.c
+++ b/libcdi/tests/pio_write.c
@@ -34,7 +34,7 @@ static const struct model_config default_setup
#else
= { .nlon = 12, .nts = 3, .nlat = 6, .nvars = 5,
.filetype = FILETYPE_GRB, .datatype = DATATYPE_PACK24,
- .compute_checksum = 1,
+ .compute_checksum = 1, .create_uuid = 0,
.suffix = "grb",
.max_nlev = 5,
};
@@ -96,11 +96,13 @@ parse_unsignedarg(const char msg[])
typedef int (*pioRoleFunc)(MPI_Comm commSuper, int IOMode, int nProcsIO);
static void
-parse_long_option(int pioConfHandle, pioRoleFunc *pioRoleAssign,
+parse_long_option(struct model_config *restrict setup,
+ int pioConfHandle, pioRoleFunc *pioRoleAssign,
const char *str)
{
static const char cacheRedistStr[] = "cache-redists",
- pioRoleSchemeOptionStr[] = "pio-role-scheme";
+ pioRoleSchemeOptionStr[] = "pio-role-scheme",
+ uuidCreateOptionStr[] = "no-create-uuid";
if (!strncmp(str, cacheRedistStr, sizeof (cacheRedistStr) - 1))
{
#ifdef USE_MPI
@@ -144,6 +146,14 @@ parse_long_option(int pioConfHandle, pioRoleFunc *pioRoleAssign,
pioRoleSchemeOptionStr);
#endif
}
+ else if (!strcmp(str, uuidCreateOptionStr + 3))
+ {
+ setup->create_uuid = true;
+ }
+ else if (!strcmp(str, uuidCreateOptionStr))
+ {
+ setup->create_uuid = false;
+ }
else
invalidOptionDie("unknown long option: %s\n", str);
}
@@ -222,7 +232,7 @@ int main(int argc, char *argv[])
break;
#endif
case 'q':
- parse_long_option(pioConfHandle, &pioRoleAssign, optarg);
+ parse_long_option(&setup, pioConfHandle, &pioRoleAssign, optarg);
break;
case 'f':
{
diff --git a/libcdi/tests/pio_write.h b/libcdi/tests/pio_write.h
index 9a9ed6a..78ea38f 100644
--- a/libcdi/tests/pio_write.h
+++ b/libcdi/tests/pio_write.h
@@ -11,7 +11,7 @@ struct model_config
{
int nlon, nlat, nts, max_nlev, nvars;
int filetype, datatype;
- bool compute_checksum;
+ bool compute_checksum, create_uuid;
const char *suffix;
};
diff --git a/libcdi/tests/simple_model.c b/libcdi/tests/simple_model.c
index f46c620..97222f1 100644
--- a/libcdi/tests/simple_model.c
+++ b/libcdi/tests/simple_model.c
@@ -29,7 +29,7 @@ typedef int MPI_Comm;
#include "pio_write.h"
#include "simple_model_helper.h"
-#include "create_uuid.h"
+#include "cdi_uuid.h"
enum {
ntfiles = 2,
@@ -116,10 +116,11 @@ modelRun(struct model_config setup, MPI_Comm comm)
lats[i] = ((double)(i * 180))/nlat - 90.0;
gridDefXvals ( gridID, lons );
gridDefYvals ( gridID, lats );
+ if (setup.create_uuid)
{
unsigned char uuid[CDI_UUID_SIZE];
if (rank == 0)
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
#if USE_MPI
MPI_Bcast(uuid, CDI_UUID_SIZE, MPI_UNSIGNED_CHAR, 0, comm);
#endif
@@ -165,10 +166,11 @@ modelRun(struct model_config setup, MPI_Comm comm)
= zaxisCreate(ZAXIS_PRESSURE, varDesc[varIdx].nlev);
zaxisDefLevels(varDesc[varIdx].zaxisID, levs);
}
+ if (setup.create_uuid)
{
unsigned char uuid[16];
if (rank == 0)
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
#if USE_MPI
MPI_Bcast(uuid, CDI_UUID_SIZE, MPI_UNSIGNED_CHAR, 0, comm);
#endif
@@ -181,17 +183,25 @@ modelRun(struct model_config setup, MPI_Comm comm)
= (size_t)nlon * (size_t)nlat * (size_t)varDesc[varIdx].nlev;
#ifdef USE_MPI
{
+ for (size_t i = 0; i < varIdx; ++i)
+ if (varDesc[i].nlev == varLevs)
+ {
+ varDesc[varIdx].partDesc = varDesc[i].partDesc;
+ varDesc[varIdx].start = varDesc[i].start;
+ varDesc[varIdx].chunkSize = varDesc[i].chunkSize;
+ goto partDescriptionSet;
+ }
struct PPM_extent range
= PPM_uniform_partition((struct PPM_extent){ 0,
(int32_t)varDesc[varIdx].size }, comm_size, rank);
int start = range.first;
int chunkSize = range.size;
- Xt_idxlist idxlist
- = xt_idxstripes_new(&(struct Xt_stripe){ .start = start,
- .nstrides = chunkSize, .stride = 1 }, 1);
varDesc[varIdx].start = start;
varDesc[varIdx].chunkSize = chunkSize;
- varDesc[varIdx].partDesc = idxlist;
+ varDesc[varIdx].partDesc
+ = xt_idxstripes_new(&(struct Xt_stripe){ .start = start,
+ .nstrides = chunkSize, .stride = 1 }, 1);
+ partDescriptionSet: ;
}
#endif
varDesc[varIdx].code = GRIB_USERDEF + (int)varIdx;
@@ -245,23 +255,24 @@ modelRun(struct model_config setup, MPI_Comm comm)
{
#ifdef USE_MPI
int start = varDesc[varIdx].start;
- int chunk = varDesc[varIdx].chunkSize;
+ size_t chunkSize = (size_t)varDesc[varIdx].chunkSize;
#else
- int chunk = (int)varDesc[varIdx].size;
+ size_t chunkSize = varDesc[varIdx].size;
int start = 0;
#endif
- if (varslice_size < (size_t)chunk)
+ if (varslice_size < chunkSize)
{
- varslice = (double *)realloc(varslice, (size_t)chunk * sizeof (var[0]));
- varslice_size = (size_t)chunk;
+ varslice = (double *)Realloc(varslice, chunkSize * sizeof (var[0]));
+ varslice_size = chunkSize;
}
- modelRegionCompute(varslice, (size_t)start, (size_t)chunk,
+ modelRegionCompute(varslice, (size_t)start, chunkSize,
varDesc[varIdx].nlev, nlat, nlon,
tsID, lons, lats,
mscale, mrscale);
if (setup.compute_checksum)
{
#if USE_MPI
+ int chunk = (int)chunkSize;
xmpi(MPI_Gather(&chunk, 1, MPI_INT,
chunks, 1, MPI_INT, 0, comm));
if (rank == 0)
@@ -270,7 +281,7 @@ modelRun(struct model_config setup, MPI_Comm comm)
for (size_t i = 1; i < (size_t)comm_size; ++i)
displs[i] = displs[i - 1] + chunks[i - 1];
}
- xmpi(MPI_Gatherv(varslice, chunk, MPI_DOUBLE,
+ xmpi(MPI_Gatherv(varslice, (size_t)chunkSize, MPI_DOUBLE,
var, chunks, displs, MPI_DOUBLE, 0, comm));
#else
var = varslice;
@@ -342,6 +353,9 @@ modelRun(struct model_config setup, MPI_Comm comm)
if (zID != CDI_UNDEFID)
{
zaxisDestroy(zID);
+#if USE_MPI
+ xt_idxlist_delete(varDesc[varIdx].partDesc);
+#endif
for (size_t j = varIdx + 1; j < nVars; ++j)
if (zID == varDesc[j].zaxisID)
varDesc[j].zaxisID = CDI_UNDEFID;
diff --git a/libcdi/tests/test_resource_copy.c b/libcdi/tests/test_resource_copy.c
index c662fac..9d09677 100644
--- a/libcdi/tests/test_resource_copy.c
+++ b/libcdi/tests/test_resource_copy.c
@@ -6,7 +6,7 @@
#include <string.h>
#include "cdi.h"
-#include "create_uuid.h"
+#include "cdi_uuid.h"
#include "dmemory.h"
#include "error.h"
#include "resource_handle.h"
@@ -87,7 +87,7 @@ static int defineGrid (void)
gridDefComplexPacking ( gridID, 1 );
{
unsigned char uuid[CDI_UUID_SIZE];
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
gridDefUUID(gridID, uuid);
}
@@ -113,7 +113,7 @@ static int defineZaxis (void)
zaxisDefWeights ( zaxisID, &levs[0] );
{
unsigned char uuid[CDI_UUID_SIZE];
- create_uuid(uuid);
+ cdiCreateUUID(uuid);
zaxisDefUUID(zaxisID, uuid);
}
@@ -218,6 +218,7 @@ static int modelRun(MPI_Comm comm)
streamID = streamOpenWrite("example.grb", FILETYPE_GRB);
if ( streamID < 0 ) xabort ( "Could not open file" );
defineStream ( streamID, vlistID );
+ vlistDestroy(temp.id1);
vlistDestroy(temp.id2);
}
diff --git a/m4/acx_options.m4 b/m4/acx_options.m4
index 7367fdd..94a5232 100644
--- a/m4/acx_options.m4
+++ b/m4/acx_options.m4
@@ -2,6 +2,7 @@ AC_DEFUN([ACX_OPTIONS],
[
# ----------------------------------------------------------------------
# Checks for multithreaded compiling + linking
+ENABLE_THREADS=no
AC_ARG_WITH([threads],
[AC_HELP_STRING([--with-threads=<yes/no/directory>],
[Compile + link for multithreading [default=yes]])],
@@ -12,7 +13,8 @@ THREADS_LIBS=''
AS_CASE([$with_threads],
[no],[AC_MSG_CHECKING([multithreading])
AC_MSG_RESULT([suppressed])],
- [yes],[AX_PTHREAD([AC_DEFINE([HAVE_LIBPTHREAD],[1],[Define 1 for multithread support])],[AC_MSG_ERROR([multithreaded settings NOT found])])
+ [yes],[AX_PTHREAD([AC_DEFINE([HAVE_LIBPTHREAD],[1],[Define 1 for multithread support])
+ ENABLE_THREADS=yes],[AC_MSG_ERROR([multithreaded settings NOT found])])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
@@ -22,8 +24,10 @@ AS_CASE([$with_threads],
CPPFLAGS="-I$THREADS_ROOT/include $CPPFLAGS "
AC_CHECK_HEADERS(pthread.h)
AC_CHECK_LIB([pthread],[pthread_create])
+ ENABLE_THREADS=yes
THREADS_LIBS=" -L$THREADS_ROOT/lib -lpthread"
THREADS_INCLUDE=" -I$THREADS_ROOT/include"])
+AC_SUBST([ENABLE_THREADS])
AC_SUBST([THREADS_INCLUDE])
AC_SUBST([THREADS_LIBS])
# ----------------------------------------------------------------------
diff --git a/src/Adisit.c b/src/Adisit.c
index f085c25..a4ece15 100644
--- a/src/Adisit.c
+++ b/src/Adisit.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -328,9 +328,17 @@ void *Adisit(void *argument)
offset = gridsize*levelID;
- if ( varID == thoID ) streamReadRecord(streamID1, tho.ptr+offset, &(tho.nmiss));
- if ( varID == saoID ) streamReadRecord(streamID1, sao.ptr+offset, &(sao.nmiss));
- }
+ if ( varID == thoID )
+ {
+ streamReadRecord(streamID1, tho.ptr+offset, &nmiss);
+ tho.nmiss = (size_t) nmiss;
+ }
+ if ( varID == saoID )
+ {
+ streamReadRecord(streamID1, sao.ptr+offset, &nmiss);
+ sao.nmiss = (size_t) nmiss;
+ }
+ }
if (operatorID == ADISIT )
{
diff --git a/src/Afterburner.c b/src/Afterburner.c
index 034b836..c7a3f9f 100644
--- a/src/Afterburner.c
+++ b/src/Afterburner.c
@@ -50,10 +50,7 @@ void scan_darray(char *namelist, const char *name, double *values, int maxValue
long get_nfft(void);
-char *zaxisNamePtr(int leveltype);
-char *vlistInqVarNamePtr(int vlistID, int varID);
-char *vlistInqVarLongnamePtr(int vlistID, int varID);
-char *vlistInqVarUnitsPtr(int vlistID, int varID);
+char zaxistypename[CDI_MAX_NAME];
typedef struct {
int lana, nrecs;
@@ -954,9 +951,10 @@ void after_defineLevel(struct Control *globs, struct Variable *vars)
}
}
else
- Error( "%s level data unsupported for TYPE %d",
- zaxisNamePtr(zaxisInqType(iVertID)), globs->Type);
-
+ {
+ zaxisName(zaxisInqType(iVertID), zaxistypename);
+ Error("%s level data unsupported for TYPE %d", zaxistypename, globs->Type);
+ }
break;
}
case 30:
@@ -1091,7 +1089,7 @@ void after_setCodes(struct Control *globs, struct Variable *vars, int maxCodes,
{
int code;
int table, modelID, tableID;
- char *name, *longname;
+ const char *name, *longname;
int varID;
if ( globs->Verbose ) lprintf(stdout);
@@ -1172,6 +1170,7 @@ void after_checkNamelist(struct Control *globs)
}
}
+#if defined(AFTERBURNER)
static
void after_usage(void)
{
@@ -1186,8 +1185,8 @@ void after_usage(void)
/* fprintf(stderr, " option -h : help (this output)\n"); */
/* fprintf(stderr, " option -p : parallel read on\n"); */
fprintf(stderr, " <InputFiles> : ECHAM or ECMWF Ana or ReAna files\n");
- fprintf(stderr, " <OutputFile> : GRIB, netCDF or SERVICE format file\n");
- fprintf(stderr, "<VarianceFile> : GRIB, netCDF or SERVICE format file\n");
+ fprintf(stderr, " <OutputFile> : GRIB, NetCDF or SERVICE format file\n");
+ fprintf(stderr, "<VarianceFile> : GRIB, NetCDF or SERVICE format file\n");
fprintf(stderr, " namelist is read from <stdin>\n");
fprintf(stderr, " output is written to <stdout>\n\n");
@@ -1200,6 +1199,7 @@ void after_usage(void)
exit(1);
}
+#endif
static
void after_parini(struct Control *globs, struct Variable *vars)
@@ -1210,7 +1210,7 @@ void after_parini(struct Control *globs, struct Variable *vars)
{
#if defined(CDO)
fprintf(stderr, "Default namelist: \n");
- fprintf(stderr, " TYPE = 0, CODE = -1, LEVEL = -1, MULTI = 0, DAYIN = 30, MEAN = 0, TIMESEL = -1, UNITSEL = 0\n");
+ fprintf(stderr, " TYPE=0, CODE=-1, LEVEL=-1, INTERVAL=0, MEAN=0, EXTRAPOLATE=0\n");
#endif
fprintf(stdout, "Enter namelist parameter:\n");
}
@@ -1221,7 +1221,9 @@ void after_parini(struct Control *globs, struct Variable *vars)
if ( length == 0L )
{
fprintf(stderr,"\n stdin not connected\n");
+#if defined(AFTERBURNER)
after_usage();
+#endif
}
fseek(stdin, 0L, SEEK_SET);
}
@@ -1272,7 +1274,7 @@ void after_parini(struct Control *globs, struct Variable *vars)
int gribFormat = scan_par_obsolate(namelist, "grib", 0);
int cdfFormat = scan_par_obsolate(namelist, "netcdf", 0);
- if ( gribFormat && cdfFormat ) Error( "GRIB or netCDF?");
+ if ( gribFormat && cdfFormat ) Error( "GRIB or NetCDF?");
switch ( fileFormat )
{
@@ -1466,14 +1468,19 @@ void after_precntl(struct Control *globs, struct Variable *vars)
if ( leveltype == ZAXIS_HYBRID && globs->nvct == 0 )
{
nhzaxis++;
- if ( numlevel != (zaxisInqVctSize(zaxisID)/2 - 1) )
+ int nvct = zaxisInqVctSize(zaxisID);
+ if ( numlevel != (nvct/2 - 1) )
{
- if ( ! (numlevel == 191 && zaxisInqVctSize(zaxisID) == 0) )
+ if ( nvct == 0 )
+ {
+ if ( numlevel != 191 )
+ Warning("VCT missing for hybrid level data with %d levels!", numlevel);
+ }
+ else
{
- Warning( "Skip %d hybrid level data with %d levels!",
- (zaxisInqVctSize(zaxisID)/2 - 1), numlevel);
- continue;
+ Warning("Skip %d hybrid level data with %d levels!", (nvct/2 - 1), numlevel);
}
+ continue;
}
}
@@ -1522,8 +1529,7 @@ void after_precntl(struct Control *globs, struct Variable *vars)
}
if ( numlevel != (globs->nvct/2 - 1) )
- Error("Number of hybrid levels %d does not match vct levels %d",
- numlevel, globs->nvct/2-1);
+ Error("Number of hybrid levels %d does not match VCT levels %d", numlevel, globs->nvct/2-1);
if ( globs->Debug )
for ( i = 0; i < globs->nvct/2; i++ )
@@ -1633,7 +1639,7 @@ void after_postcntl(struct Control *globs, struct Variable *vars)
int ovarID, ogridID, ozaxisID;
int ovarID2;
int ivarID, instID, modelID, tableID;
- char *name, *longname, *units;
+ const char *name, *longname, *units;
char histstring[99];
int datatype;
@@ -1652,9 +1658,10 @@ void after_postcntl(struct Control *globs, struct Variable *vars)
{
gridID = vars[code].igridID;
zaxisID = vars[code].izaxisID;
+ zaxisName(zaxisInqType(zaxisID), zaxistypename);
fprintf(stderr," Detected Code %3d grid %-8s size %5d level %2d %-8s\n",
code, gridNamePtr(gridInqType(gridID)), gridInqSize(gridID),
- zaxisInqSize(zaxisID), zaxisNamePtr(zaxisInqType(zaxisID)));
+ zaxisInqSize(zaxisID), zaxistypename);
}
@@ -1756,41 +1763,47 @@ void after_postcntl(struct Control *globs, struct Variable *vars)
{
gridID = vars[code].ogridID;
zaxisID = vars[code].ozaxisID;
+ zaxisName(zaxisInqType(zaxisID), zaxistypename);
fprintf(stderr," Selected Code %3d grid %-8s size %5d level %2d %-8s\n",
code, gridNamePtr(gridInqType(gridID)), gridInqSize(gridID),
- zaxisInqSize(zaxisID), zaxisNamePtr(zaxisInqType(zaxisID)));
+ zaxisInqSize(zaxisID), zaxistypename);
}
}
-#if defined(AFTERBURNER)
static
void after_readVct(struct Control *globs, const char *vctfile)
{
char line[1024];
- int i, n;
+ int i, n, nlines = 0;
double va, vb;
FILE *fp = fopen(vctfile, "r");
if ( fp == NULL ) SysError( "Open failed on %s", vctfile);
- while ( fgets(line, 1023, fp) ) globs->nvct++;
-
- globs->nvct *= 2;
+ while ( fgets(line, 1023, fp) )
+ {
+ if ( line[0] == '#' || line[0] == '\0' ) continue;
+ nlines++;
+ }
+
+ globs->nvct = nlines*2;
globs->vct = (double *) Malloc(globs->nvct*sizeof(double));
-
+
rewind(fp);
- for ( i = 0; i < globs->nvct/2; i++ )
+
+ i = 0;
+ while ( fgets(line, 1023, fp) )
{
- fgets(line, 1023, fp);
+ if ( line[0] == '#' || line[0] == '\0' ) continue;
sscanf(line, "%d %lg %lg", &n, &va, &vb);
globs->vct[i] = va;
globs->vct[i+globs->nvct/2] = vb;
+ i++;
}
- fprintf(stdout, " Reading VCT for %d hybrid levels from file %s\n", globs->nvct/2-1, vctfile);
+ fprintf(stdout, " Read VCT with %d hybrid levels from file %s\n", globs->nvct/2-1, vctfile);
fclose(fp);
}
-#endif
#if defined(AFTERBURNER)
static
@@ -2076,7 +2089,7 @@ void after_processing(struct Control *globs, struct Variable *vars)
Error("Can't write fourier coefficients to GRIB!");
else if ( ofiletype == FILETYPE_NC || ofiletype == FILETYPE_NC2 ||
ofiletype == FILETYPE_NC4 )
- Error("Can't write fourier coefficients to netCDF!");
+ Error("Can't write fourier coefficients to NetCDF!");
}
filename = strrchr(ifile,'/');
@@ -2335,7 +2348,7 @@ int afterburner(int argc, char *argv[])
fprintf(stderr, " Maximum ffts to run in parallel: %ld\n", get_nfft());
}
- /* read option VCT */
+ /* read optional VCT */
if ( Vctfile ) after_readVct(globs, Vctfile);
/* --------------------- */
@@ -2368,6 +2381,12 @@ void *Afterburner(void *argument)
globs->Verbose = cdoVerbose;
+ if ( operatorArgc() == 1 )
+ {
+ const char *vctfile = operatorArgv()[0];
+ after_readVct(globs, vctfile);
+ }
+
struct Variable vars[MaxCodes+5];
for ( int code = 0; code < MaxCodes+5; code++ ) after_variable_init(&vars[code]);
diff --git a/src/Arith.c b/src/Arith.c
index c6caf27..5c2277a 100644
--- a/src/Arith.c
+++ b/src/Arith.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -37,6 +37,7 @@ void *Arith(void *argument)
{
enum {FILL_NONE, FILL_TS, FILL_VAR, FILL_VARTS, FILL_FILE};
int filltype = FILL_NONE;
+ int nmiss;
int gridsize;
int nrecs, nrecs2, nvars = 0, nlev, recID;
int nlevels2 = 1;
@@ -250,8 +251,9 @@ void *Arith(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamIDx1, &varID, &levelID);
- streamReadRecord(streamIDx1, fieldx1->ptr, &fieldx1->nmiss);
-
+ streamReadRecord(streamIDx1, fieldx1->ptr, &nmiss);
+ fieldx1->nmiss = (size_t) nmiss;
+
if ( tsID == 0 || filltype == FILL_NONE || filltype == FILL_FILE || filltype == FILL_VARTS )
{
int lstatus = nlevels2 > 1 ? varID == 0 : recID == 0;
@@ -259,7 +261,8 @@ void *Arith(void *argument)
if ( lstatus || (filltype != FILL_VAR && filltype != FILL_VARTS) )
{
streamInqRecord(streamIDx2, &varID2, &levelID2);
- streamReadRecord(streamIDx2, fieldx2->ptr, &fieldx2->nmiss);
+ streamReadRecord(streamIDx2, fieldx2->ptr, &nmiss);
+ fieldx2->nmiss = (size_t) nmiss;
}
if ( filltype == FILL_TS )
@@ -308,7 +311,7 @@ void *Arith(void *argument)
farfun(&field1, field2, operfunc);
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, (int)field1.nmiss);
}
tsID++;
diff --git a/src/Arithc.c b/src/Arithc.c
index b3aa92b..350802d 100644
--- a/src/Arithc.c
+++ b/src/Arithc.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -72,6 +72,7 @@ int *fill_vars(int vlistID)
void *Arithc(void *argument)
{
+ int nmiss;
int nrecs, recID;
int varID, levelID;
@@ -122,7 +123,8 @@ void *Arithc(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t) nmiss;
if ( vars[varID] )
{
@@ -138,8 +140,9 @@ void *Arithc(void *argument)
if ( DBL_IS_EQUAL(field.ptr[i], field.missval) ) field.nmiss++;
}
+ nmiss = (int) field.nmiss;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, field.ptr, field.nmiss);
+ streamWriteRecord(streamID2, field.ptr, nmiss);
}
tsID++;
}
diff --git a/src/Arithdays.c b/src/Arithdays.c
index 0db2bab..08bfda5 100644
--- a/src/Arithdays.c
+++ b/src/Arithdays.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
@@ -83,6 +84,7 @@ void *Arithdays(void *argument)
int vdate, vtime;
int year, month, day;
int calendar;
+ int nmiss;
double rconst;
field_t field;
@@ -149,15 +151,16 @@ void *Arithdays(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vlistInqVarGrid(vlistID1, varID);
field.missval = vlistInqVarMissval(vlistID1, varID);
farcfun(&field, rconst, operfunc);
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, field.ptr, field.nmiss);
+ streamWriteRecord(streamID2, field.ptr, (int)field.nmiss);
}
tsID++;
}
diff --git a/src/Arithlat.c b/src/Arithlat.c
index ba58276..f2a9827 100644
--- a/src/Arithlat.c
+++ b/src/Arithlat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/CDIread.c b/src/CDIread.c
index e7aadc8..9561063 100644
--- a/src/CDIread.c
+++ b/src/CDIread.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -29,10 +29,10 @@ const char *filetypestr(int filetype)
{
case FILETYPE_GRB: return ("GRIB"); break;
case FILETYPE_GRB2: return ("GRIB2"); break;
- case FILETYPE_NC: return ("netCDF"); break;
- case FILETYPE_NC2: return ("netCDF2"); break;
- case FILETYPE_NC4: return ("netCDF4"); break;
- case FILETYPE_NC4C: return ("netCDF4 classic"); break;
+ case FILETYPE_NC: return ("NetCDF"); break;
+ case FILETYPE_NC2: return ("NetCDF2"); break;
+ case FILETYPE_NC4: return ("NetCDF4"); break;
+ case FILETYPE_NC4C: return ("NetCDF4 classic"); break;
case FILETYPE_SRV: return ("SERVICE"); break;
case FILETYPE_EXT: return ("EXTRA"); break;
case FILETYPE_IEG: return ("IEG"); break;
@@ -80,10 +80,10 @@ void print_stat(const char *sinfo, int memtype, int datatype, int filetype, off_
void *CDIread(void *argument)
{
- int memtype = MEMTYPE_DOUBLE;
+ int memtype = CDO_Memtype;
int streamID;
int tsID, varID, levelID;
- int gridsize, i, nmiss;
+ int gridsize, nmiss;
int recID, nrecs;
int vlistID;
int filetype = -1, datatype = -1;
@@ -99,13 +99,6 @@ void *CDIread(void *argument)
cdoInitialize(argument);
- char *envstr = getenv("MEMTYPE");
- if ( envstr )
- {
- if ( strcmp(envstr, "float") == 0 ) memtype = MEMTYPE_FLOAT;
- else if ( strcmp(envstr, "double") == 0 ) memtype = MEMTYPE_DOUBLE;
- }
-
if ( cdoVerbose ) cdoPrint("parameter: <nruns>");
if ( operatorArgc() > 1 ) cdoAbort("Too many arguments!");
@@ -152,9 +145,8 @@ void *CDIread(void *argument)
if ( memtype == MEMTYPE_FLOAT )
{
- cdoAbort("streamReadRecordF not implemented!");
- // streamReadRecordF(streamID, farray, &nmiss);
- for ( i = 0; i < gridsize; ++i ) darray[i] = farray[i];
+ streamReadRecordF(streamID, farray, &nmiss);
+ // for ( int i = 0; i < gridsize; ++i ) darray[i] = farray[i];
data_size += gridsize*4;
}
else
diff --git a/src/CDItest.c b/src/CDItest.c
index 7942956..70902a4 100644
--- a/src/CDItest.c
+++ b/src/CDItest.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/CDIwrite.c b/src/CDIwrite.c
index b71f3f2..529a7a8 100644
--- a/src/CDIwrite.c
+++ b/src/CDIwrite.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -30,10 +30,10 @@ const char *filetypestr(int filetype)
{
case FILETYPE_GRB: return ("GRIB"); break;
case FILETYPE_GRB2: return ("GRIB2"); break;
- case FILETYPE_NC: return ("netCDF"); break;
- case FILETYPE_NC2: return ("netCDF2"); break;
- case FILETYPE_NC4: return ("netCDF4"); break;
- case FILETYPE_NC4C: return ("netCDF4 classic"); break;
+ case FILETYPE_NC: return ("NetCDF"); break;
+ case FILETYPE_NC2: return ("NetCDF2"); break;
+ case FILETYPE_NC4: return ("NetCDF4"); break;
+ case FILETYPE_NC4C: return ("NetCDF4 classic"); break;
case FILETYPE_SRV: return ("SERVICE"); break;
case FILETYPE_EXT: return ("EXTRA"); break;
case FILETYPE_IEG: return ("IEG"); break;
@@ -91,7 +91,7 @@ void print_stat(const char *sinfo, int memtype, int datatype, int filetype, off_
void *CDIwrite(void *argument)
{
- int memtype = MEMTYPE_DOUBLE;
+ int memtype = CDO_Memtype;
int nvars = 10, nlevs = 0, ntimesteps = 30;
const char *defaultgrid = "global_.2";
int streamID;
@@ -116,13 +116,6 @@ void *CDIwrite(void *argument)
cdoInitialize(argument);
- char *envstr = getenv("MEMTYPE");
- if ( envstr )
- {
- if ( strcmp(envstr, "float") == 0 ) memtype = MEMTYPE_FLOAT;
- else if ( strcmp(envstr, "double") == 0 ) memtype = MEMTYPE_DOUBLE;
- }
-
if ( cdoVerbose ) cdoPrint("parameter: <nruns, <grid, <nlevs, <ntimesteps, <nvars>>>>>");
if ( operatorArgc() > 5 ) cdoAbort("Too many arguments!");
@@ -200,7 +193,6 @@ void *CDIwrite(void *argument)
vars[varID][levelID] = (double*) Malloc(gridsize*sizeof(double));
for ( i = 0; i < gridsize; ++i )
vars[varID][levelID][i] = varID + array[i]*(levelID+1);
- // vars[varID][levelID][i] = varID + rand()/(RAND_MAX+1.0);
}
}
diff --git a/src/CMOR.c b/src/CMOR.c
index 6b010e6..bba174e 100644
--- a/src/CMOR.c
+++ b/src/CMOR.c
@@ -1,51 +1,699 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
-#include "par_io.h"
#include "pstream.h"
+#include <search.h>
+#include <ctype.h>
#if defined(HAVE_LIBCMOR)
-//#include "cmor.h"
-#endif
+#include "cmor.h"
-void *CMOR(void *argument)
+struct cc_var
{
- cdoInitialize(argument);
+ int cdi_varID;
+ int cmor_varID;
+ char datatype;
+ void *data;
+};
-#if defined(HAVE_LIBCMOR)
- /*
- if ( cdoVerbose )
- cdoPrint("Using CMOR version %d.%d.%d.", CMOR_VERSION_MAJOR, CMOR_VERSION_MINOR, CMOR_VERSION_PATCH);
- */
- int streamID = streamOpenRead(cdoStreamName(0));
+static struct cc_var *find_var(int cdi_varID, struct cc_var vars[], int nvars)
+{
+ for ( int i = 0; i < nvars; i++ )
+ if ( cdi_varID == vars[i].cdi_varID )
+ return &vars[i];
+ return NULL;
+}
+
+static char *trim(char *s)
+{
+ int n;
+ if (s == NULL) return s;
+ while ( *s != '\0' && (isspace(*s) || *s == '"') )
+ s++;
+ n = strlen(s);
+ while ( n > 0 && (isspace(s[n - 1]) || s[n - 1] == '"') )
+ n--;
+ s[n] = '\0';
+ return s;
+}
+
+static ENTRY *hinsert(const char *key, const char *value)
+{
+ /* Insert new keys. Do not overwrite values of existing keys. */
+ ENTRY e, *ep;
+
+ e.key = strdup(key);
+ e.data = (void *)strdup(value);
+ ep = hsearch(e, FIND);
+ if ( ep == NULL )
+ {
+ ep = hsearch(e, ENTER);
+ }
+ else
+ {
+ free(e.key);
+ free(e.data);
+ }
+ return ep;
+}
+
+static ENTRY *hreplace(const char *key, const char *value)
+{
+ /* Overwrites values of existing keys. */
+ ENTRY e, *ep;
+
+ e.key = strdup(key);
+ e.data = (void *)strdup(value);
+ ep = hsearch(e, FIND);
+ if ( ep == NULL )
+ {
+ ep = hsearch(e, ENTER);
+ }
+ else
+ {
+ free(e.key);
+ free(ep->data);
+ ep->data = e.data;
+ }
+ return ep;
+}
+
+static ENTRY *parse_kv(char *kvstr)
+{
+ char *key = trim(strtok(kvstr, "="));
+ char *value = trim(strtok(NULL, "="));
+ if ( key == NULL || value == NULL )
+ return NULL;
+ return hinsert(key, value);
+}
+
+static int parse_kv_file(const char *filename, int verbose)
+{
+ FILE *fp;
+ char line[CMOR_MAX_STRING], *comment;
+
+ fp = fopen(filename, "r");
+ if ( fp == NULL )
+ {
+ if ( verbose )
+ cdoWarning("cannot open '%s'", filename);
+ return 1;
+ }
+ while ( fgets(line, sizeof(line), fp) != NULL )
+ {
+ comment = strchr(line, '#');
+ if ( comment ) *comment = '\0';
+ parse_kv(line);
+ }
+ fclose(fp);
+ return 0;
+}
+
+static void parse_kv_cmdline(int nparams, char **params)
+{
+ int i, j, k, size;
+ char *p;
+
+ /* Assume key = value pairs. That is, if params[i] contains no '='
+ * then treat it as if it belongs to the value of params[i-1],
+ * separated by a ','.*/
+ i = 0;
+ while ( i < nparams )
+ {
+ j = 1;
+ size = strlen(params[i]) + 1;
+ while ( i + j < nparams && strchr(params[i + j], '=') == NULL )
+ {
+ size += strlen(params[i + j]) + 1;
+ j++;
+ }
+ p = (char *) Malloc(size);
+ strcpy(p, params[i]);
+ for (k = 1; k < j; k++)
+ {
+ strcat(p, ",");
+ strcat(p, params[i + k]);
+ }
+ parse_kv(p);
+ free(p);
+ i += j;
+ }
+}
+
+static char *get_val(char *key, char *def)
+{
+ ENTRY e, *ep;
+
+ e.key = key;
+ ep = hsearch(e, FIND);
+ if ( ep )
+ return (char *)ep->data;
+ else
+ return def;
+}
+
+static char *substitute(char *word)
+{
+ ENTRY e, *ep;
+ char *key;
+
+ key = (char *) Malloc(strlen(word) + 12);
+ sprintf(key, "substitute_%s", word);
+ e.key = key;
+ ep = hsearch(e, FIND);
+ Free(key);
+ if ( ep )
+ return (char *)ep->data;
+ else
+ return word;
+}
+
+static void dump_global_attributes(int streamID)
+{
+ int i, natts;
+ char name[CDI_MAX_NAME];
+ char buffer[8];
+ char *value;
+ int type, len;
+ int vlistID = streamInqVlist(streamID);
+
+ vlistInqNatts(vlistID, CDI_GLOBAL, &natts);
+ for ( i = 0; i < natts; i++ )
+ {
+ value = NULL;
+ vlistInqAtt(vlistID, CDI_GLOBAL, i, name, &type, &len);
+ switch ( type )
+ {
+ case DATATYPE_TXT:
+ value = Malloc(len + 1);
+ vlistInqAttTxt(vlistID, CDI_GLOBAL, name, len, value);
+ value[len] = '\0';
+ break;
+ case DATATYPE_INT32:
+ value = Malloc(CDI_MAX_NAME);
+ vlistInqAttInt(vlistID, CDI_GLOBAL, name, len, (int *)buffer);
+ snprintf(value, CDI_MAX_NAME, "%i", *(int *)buffer);
+ break;
+ case DATATYPE_FLT64:
+ value = Malloc(CDI_MAX_NAME);
+ vlistInqAttFlt(vlistID, CDI_GLOBAL, name, len, (double *)buffer);
+ snprintf(value, CDI_MAX_NAME, "%e", *(double *)buffer);
+ break;
+ default:
+ printf("Unsupported type %i name %s\n", type, name);
+ }
+ hinsert(name, value);
+ if ( value ) Free(value);
+ }
+}
+
+static void dump_special_attributes(int streamID)
+{
+ int fileID;
+ size_t historysize;
+ char *history, *new_history;
+ const char *value;
+ int vlistID = streamInqVlist(streamID);
+
+ /* Any new history will be appended to the existing history. */
+ fileID = pstreamFileID(streamID);
+ historysize = (size_t) streamInqHistorySize(fileID);
+ if ( historysize )
+ {
+ new_history = get_val("history", NULL);
+ if ( new_history ) historysize += strlen(new_history) + 1;
+ history = Malloc(historysize + 1);
+ memset(history, 0, historysize + 1);
+ streamInqHistoryString(fileID, history);
+ if ( new_history )
+ {
+ strcat(history, " ");
+ strcat(history, new_history);
+ }
+ hreplace("history", history);
+ Free(history);
+ }
+
+ value = institutInqLongnamePtr(vlistInqVarInstitut(vlistID, 0));
+ if ( value ) hinsert("institution", value);
+
+ value = modelInqNamePtr(vlistInqVarModel(vlistID, 0));
+ if ( value ) hinsert("source", value);
+}
+
+static void read_config_files(void)
+{
+ char *info_files;
+ char *filename;
+ char *home;
+ const char *dotconfig = ".cdocmorinfo";
+
+ /* Files from info key in command line. */
+ info_files = get_val("info", "");
+ filename = strtok(info_files, ",");
+ while ( filename != NULL )
+ {
+ parse_kv_file(trim(filename), 1);
+ filename = strtok(NULL, ",");
+ }
+
+ /* Config file in user's $HOME directory. */
+ home = getenv("HOME");
+ filename = Malloc(strlen(home) + strlen(dotconfig) + 2);
+ sprintf(filename, "%s/%s", home, dotconfig);
+ parse_kv_file(filename, 0);
+ Free(filename);
+
+ /* System wide configuration. */
+ parse_kv_file("/etc/cdocmor.info", 0);
+}
+
+static int in_list(char **list, const char *needle)
+{
+ while ( *list )
+ if ( strcmp(*list++, needle) == 0 )
+ return 1;
+ return 0;
+}
+
+static void setup(int streamID, char *table)
+{
+ char *chunk;
+ char *logfile;
+ int netcdf_file_action, exit_control;
+ int set_verbosity;
+ int create_subdirectories;
+ int *month_lengths;
+ int table_id;
+ int taxisID = vlistInqTaxis(streamInqVlist(streamID));
+ char *calendar;
+ double branch_time = atof(get_val("branch_time", "0.0"));
+
+ chunk = get_val("chunk", "replace");
+ if ( strcasecmp(chunk, "replace") == 0 )
+ netcdf_file_action = CMOR_REPLACE;
+ else if ( strcasecmp(chunk, "append") == 0 )
+ netcdf_file_action = CMOR_APPEND;
+
+ set_verbosity = CMOR_NORMAL;
+ if ( strcasecmp(get_val("set_verbosity", ""), "CMOR_QUIET") == 0 )
+ set_verbosity = CMOR_QUIET;
+
+ exit_control = CMOR_NORMAL;
+ if ( strcasecmp(get_val("exit_control", ""), "CMOR_EXIT_ON_MAJOR") == 0 )
+ exit_control = CMOR_EXIT_ON_MAJOR;
+ if ( strcasecmp(get_val("exit_control", ""), "CMOR_EXIT_ON_WARNING") == 0 )
+ exit_control = CMOR_EXIT_ON_WARNING;
+
+ logfile = get_val("logfile", NULL);
+
+ create_subdirectories = atoi(get_val("create_subdirectories", "0"));
+ cmor_setup(get_val("inpath", "/usr/share/cmor/"),
+ &netcdf_file_action,
+ &set_verbosity,
+ &exit_control,
+ logfile,
+ &create_subdirectories);
+
+ switch ( taxisInqCalendar(taxisID) )
+ {
+ case CALENDAR_STANDARD:
+ calendar = "gregorian";
+ break;
+ case CALENDAR_PROLEPTIC:
+ calendar = "proleptic_gregorian";
+ break;
+ case CALENDAR_360DAYS:
+ calendar = "360_day";
+ break;
+ case CALENDAR_365DAYS:
+ calendar = "noleap";
+ break;
+ case CALENDAR_366DAYS:
+ calendar = "all_leap";
+ break;
+ default:
+ cdoAbort("Unsupported calendar type.");
+ }
+
+ if ( get_val("month_lengths", NULL) )
+ {
+ char *month_lengths_str = strdup(get_val("month_lengths", ""));
+ char *month_str = strtok(month_lengths_str, ",");
+ int month = 0;
+ month_lengths = Malloc(12 * sizeof(int));
+ while ( month < 12 && month_str != NULL )
+ {
+ month_lengths[month++] = atoi(month_str);
+ month_str = strtok(NULL, ",");
+ }
+ if ( month != 12 )
+ cdoAbort("Invalid format for month_lengths");
+ }
+ else
+ {
+ month_lengths = NULL;
+ }
+ cmor_dataset(get_val("outpath", "./"),
+ get_val("experiment_id", ""),
+ get_val("institution", ""),
+ get_val("source", ""),
+ calendar,
+ atoi(get_val("realization", "1")),
+ get_val("contact", ""),
+ get_val("history", ""),
+ get_val("comment", ""),
+ get_val("references", ""),
+ atoi(get_val("leap_year", "0")),
+ atoi(get_val("leap_month", "0")),
+ month_lengths,
+ get_val("model_id", ""),
+ get_val("forcing", ""),
+ atoi(get_val("initialization_method", "1")),
+ atoi(get_val("physics_version", "1")),
+ get_val("institute_id", ""),
+ get_val("parent_experiment_id", ""),
+ &branch_time,
+ get_val("parent_experiment_rip", ""));
+
+ cmor_load_table(table, &table_id);
+ cmor_set_table(table_id);
+}
+
+static void define_variables(int streamID, struct cc_var vars[], int *nvars)
+{
int vlistID = streamInqVlist(streamID);
int taxisID = vlistInqTaxis(vlistID);
+ size_t gridsize = vlistGridsizeMax(vlistID);
+ struct cc_var *var;
+ int varID, gridID;
+ char name[CDI_MAX_NAME], units[CDI_MAX_NAME];
+ int length;
+ double *coord_vals, *cell_bounds;
+ int ndims, levels;
+ char missing_value[sizeof(double)];
+ double tolerance = 1e-4;
+ int axis_ids[CMOR_MAX_AXES];
+ char *select_vars = get_val("var", NULL);
+ int year, month, day, hour, minute, second;
+ int timeunit = taxisInqTunit(taxisID);
+ char taxis_units[CMOR_MAX_STRING];
+ char **name_list, *var_name;
+ int i;
+
+ cdiDecodeDate(taxisInqRdate(taxisID), &year, &month, &day);
+ cdiDecodeTime(taxisInqRtime(taxisID), &hour, &minute, &second);
+ if ( timeunit == TUNIT_QUARTER || timeunit == TUNIT_30MINUTES )
+ timeunit = TUNIT_MINUTE;
+ if ( timeunit == TUNIT_3HOURS ||
+ timeunit == TUNIT_6HOURS ||
+ timeunit == TUNIT_12HOURS )
+ timeunit = TUNIT_HOUR;
- int gridsize = vlistGridsizeMax(vlistID);
- double *array = (double*) Malloc(gridsize*sizeof(double));
+ sprintf(taxis_units, "%s since %d-%d-%d %02d:%02d:%02d",
+ tunitNamePtr(timeunit), year, month, day, hour,
+ minute, second);
- int recID, varID, levelID, nrecs, nmiss;
- int tsID = 0;
- while ( (nrecs = streamInqTimestep(streamID, tsID)) )
+ if ( select_vars )
{
- for ( recID = 0; recID < nrecs; recID++ )
- {
+ name_list = Malloc((strlen(select_vars) + 1) * sizeof(char *));
+ var_name = strtok(select_vars, ",");
+ i = 0;
+ while ( var_name != NULL )
+ {
+ name_list[i++] = trim(var_name);
+ var_name = strtok(NULL, ",");
+ }
+ name_list[i] = NULL;
+ }
+ else
+ {
+ name_list = NULL;
+ }
+
+ *nvars = 0;
+ for ( varID = 0; varID < vlistNvars(vlistID); varID++ )
+ {
+ vlistInqVarName(vlistID, varID, name);
+ if ( name_list == NULL || in_list(name_list, name) )
+ {
+ var = &vars[(*nvars)++];
+ var->cdi_varID = varID;
+ gridID = vlistInqVarGrid(vlistID, varID);
+ ndims = 0;
+
+ /* Time-Axis */
+ cmor_axis(&axis_ids[ndims++],
+ substitute("time"),
+ taxis_units,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL);
+
+ /* Z-Axis */
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ levels = zaxisInqSize(zaxisID);
+ if ( zaxisInqType(zaxisID) != ZAXIS_SURFACE )
+ {
+ coord_vals = Malloc(levels * sizeof(double));
+ zaxisInqLevels(zaxisID, coord_vals);
+ zaxisInqName(zaxisID, name);
+ zaxisInqUnits(zaxisID, units);
+ cmor_axis(&axis_ids[ndims++],
+ substitute(name),
+ units,
+ levels,
+ (void *)coord_vals,
+ 'd',
+ NULL,
+ 0,
+ NULL);
+ }
+
+ /* Y-Axis */
+ gridInqYname(gridID, name);
+ gridInqYunits(gridID, units);
+ length = gridInqYsize(gridID);
+ coord_vals = Malloc(length * sizeof(double));
+ gridInqYvals(gridID, coord_vals);
+ cell_bounds = Malloc(2 * length * sizeof(double));
+ gridInqYbounds(gridID, cell_bounds);
+ cmor_axis(&axis_ids[ndims++],
+ substitute(name),
+ units,
+ length,
+ (void *)coord_vals,
+ 'd',
+ (void *)cell_bounds,
+ 2,
+ NULL);
+
+ /* X-Axis */
+ gridInqXname(gridID, name);
+ gridInqXunits(gridID, units);
+ length = gridInqXsize(gridID);
+ coord_vals = Malloc(length * sizeof(double));
+ gridInqXvals(gridID, coord_vals);
+ cell_bounds = Malloc(2 * length * sizeof(double));
+ gridInqXbounds(gridID, cell_bounds);
+ cmor_axis(&axis_ids[ndims++],
+ substitute(name),
+ units,
+ length,
+ (void *)coord_vals,
+ 'd',
+ (void *)cell_bounds,
+ 2,
+ NULL);
+
+ /* Variable */
+ vlistInqVarUnits(vlistID, varID, units);
+ vlistInqVarName(vlistID, varID, name);
+ if ( vlistInqVarDatatype(vlistID, varID) == DATATYPE_FLT32 )
+ {
+ var->datatype = 'f';
+ *(float *) missing_value = vlistInqVarMissval(vlistID, varID);
+ var->data = Malloc(gridsize * levels * sizeof(float));
+ }
+ else
+ {
+ var->datatype = 'd';
+ *(double *) missing_value = vlistInqVarMissval(vlistID, varID);
+ var->data = Malloc(gridsize * levels * sizeof(double));
+ }
+ cmor_variable(&var->cmor_varID,
+ substitute(name),
+ units,
+ ndims,
+ axis_ids,
+ var->datatype,
+ (void *) missing_value,
+ &tolerance,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
+ }
+ if ( name_list ) Free(name_list);
+}
+
+static void write_variables(int streamID, struct cc_var vars[], int nvars)
+{
+ struct cc_var *var;
+ int vlistID = streamInqVlist(streamID);
+ int taxisID = vlistInqTaxis(vlistID);
+ size_t gridsize = vlistGridsizeMax(vlistID);
+ double time_val;
+ double time_bnds[2];
+ double *time_bndsp;
+ int has_bnds = taxisHasBounds(taxisID);
+ int tsID;
+ int vdate0b, vdate1b;
+ int vtime0b, vtime1b;
+ juldate_t juldate, r_juldate;
+ int calendar = taxisInqCalendar(taxisID);
+ int tunitsec;
+ int nrecs;
+ int varID, levelID;
+ int nmiss;
+ double *buffer;
+ int i;
+
+ buffer = (double *) Malloc(gridsize * sizeof(double));
+
+ switch ( taxisInqTunit(taxisID) )
+ {
+ case TUNIT_MINUTE: tunitsec = 60; break;
+ case TUNIT_HOUR: tunitsec = 3600; break;
+ case TUNIT_DAY: tunitsec = 86400; break;
+ default: tunitsec = 3600;
+ }
+
+ r_juldate = juldate_encode(calendar,
+ taxisInqRdate(taxisID),
+ taxisInqRtime(taxisID));
+ tsID = 0;
+ while ( (nrecs = streamInqTimestep(streamID, tsID++)) )
+ {
+ juldate = juldate_encode(calendar,
+ taxisInqVdate(taxisID),
+ taxisInqVtime(taxisID));
+ time_val = juldate_to_seconds(juldate_sub(juldate, r_juldate))
+ / tunitsec;
+
+ if ( has_bnds )
+ {
+ taxisInqVdateBounds(taxisID, &vdate0b, &vdate1b);
+ taxisInqVtimeBounds(taxisID, &vtime0b, &vtime1b);
+
+ juldate = juldate_encode(calendar, vdate0b, vtime0b);
+ time_bnds[0] = juldate_to_seconds(juldate_sub(juldate, r_juldate))
+ / tunitsec;
+
+ juldate = juldate_encode(calendar, vdate1b, vtime1b);
+ time_bnds[1] = juldate_to_seconds(juldate_sub(juldate, r_juldate))
+ / tunitsec;
+ time_bndsp = time_bnds;
+ }
+ else
+ {
+ time_bndsp = NULL;
+ }
+
+ while ( nrecs-- )
+ {
streamInqRecord(streamID, &varID, &levelID);
- streamReadRecord(streamID, array, &nmiss);
+ var = find_var(varID, vars, nvars);
+ if ( var )
+ {
+ if ( var->datatype == 'f' )
+ {
+ streamReadRecord(streamID, buffer, &nmiss);
+ for ( i = 0; i < gridsize; i++ )
+ ((float *)var->data)[gridsize * levelID + i] =
+ (float)buffer[i];
+ }
+ else
+ {
+ streamReadRecord(streamID,
+ (double *)var->data + gridsize * levelID,
+ &nmiss);
+ }
+ }
}
- tsID++;
+ for ( i = 0; i < nvars; i++ )
+ cmor_write(vars[i].cmor_varID,
+ vars[i].data,
+ vars[i].datatype,
+ NULL,
+ 1,
+ &time_val,
+ time_bndsp,
+ NULL);
}
+ Free(buffer);
+}
+#endif
+
+void *CMOR(void *argument)
+{
+ cdoInitialize(argument);
+
+#if defined(HAVE_LIBCMOR)
+ int nparams = operatorArgc();
+ char **params = operatorArgv();
+ int nvars, nvars_max;
+ int streamID;
+ struct cc_var *vars;
+
+ if ( nparams < 1 ) cdoAbort("Too few arguments!");
+
+ hcreate(100);
+
+ /* Command line config has highest priority. */
+ parse_kv_cmdline(nparams - 1, ¶ms[1]);
+
+ /* Config files are read with descending priority. */
+ read_config_files();
+
+ streamID = streamOpenRead(cdoStreamName(0));
+ /* Existing attributes have lowest priority. */
+ dump_global_attributes(streamID);
+ dump_special_attributes(streamID);
+
+ nvars_max = vlistNvars(streamInqVlist(streamID));
+ vars = (struct cc_var *) Malloc(nvars_max * sizeof(struct cc_var));
+
+ setup(streamID, params[0]);
+ define_variables(streamID, vars, &nvars);
+ write_variables(streamID, vars, nvars);
streamClose(streamID);
+ cmor_close();
- if ( array ) Free(array);
+ hdestroy();
+ for ( int i = 0; i < nvars; i++ )
+ Free(vars[i].data);
+ Free(vars);
#else
cdoWarning("CMOR support not compiled in!");
#endif
cdoFinish();
-
return 0;
}
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/Cat.c b/src/Cat.c
index 476ac87..ceb8e7a 100644
--- a/src/Cat.c
+++ b/src/Cat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -30,24 +30,22 @@
void *Cat(void *argument)
{
- int streamID1, streamID2 = CDI_UNDEFID;
+ bool lconstvars = true;
int nrecs;
- int tsID1, tsID2 = 0, recID, varID, levelID;
- int vlistID1, vlistID2 = CDI_UNDEFID;
- int taxisID1, taxisID2 = CDI_UNDEFID;
- int lcopy = FALSE;
- int gridsize;
+ int tsID2 = 0, varID, levelID;
+ int streamID2 = CDI_UNDEFID;
+ int vlistID2 = CDI_UNDEFID;
+ int taxisID2 = CDI_UNDEFID;
int nmiss;
- int ntsteps, nvars;
- int timer_cat;
double tw0 = 0, tw = 0;
double *array = NULL;
cdoInitialize(argument);
- if ( UNCHANGED_RECORD ) lcopy = TRUE;
+ bool lcopy = false;
+ if ( UNCHANGED_RECORD ) lcopy = true;
- timer_cat = timer_new("cat");
+ int timer_cat = timer_new("cat");
if ( cdoTimer ) timer_start(timer_cat);
int streamCnt = cdoStreamCnt();
@@ -58,10 +56,10 @@ void *Cat(void *argument)
if ( cdoVerbose ) cdoPrint("Process file: %s", cdoStreamName(indf)->args);
if ( cdoTimer ) tw0 = timer_val(timer_cat);
- streamID1 = streamOpenRead(cdoStreamName(indf));
+ int streamID1 = streamOpenRead(cdoStreamName(indf));
- vlistID1 = streamInqVlist(streamID1);
- taxisID1 = vlistInqTaxis(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int taxisID1 = vlistInqTaxis(vlistID1);
if ( indf == 0 )
{
@@ -91,8 +89,8 @@ void *Cat(void *argument)
taxisID2 = taxisDuplicate(taxisID1);
vlistDefTaxis(vlistID2, taxisID2);
- ntsteps = vlistNtsteps(vlistID1);
- nvars = vlistNvars(vlistID1);
+ int ntsteps = vlistNtsteps(vlistID1);
+ int nvars = vlistNvars(vlistID1);
if ( ntsteps == 1 )
{
@@ -103,7 +101,8 @@ void *Cat(void *argument)
}
if ( ntsteps == 0 && nfiles > 1 )
- {
+ {
+ lconstvars = false;
for ( varID = 0; varID < nvars; ++varID )
vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
}
@@ -113,7 +112,7 @@ void *Cat(void *argument)
if ( ! lcopy )
{
- gridsize = vlistGridsizeMax(vlistID1);
+ size_t gridsize = (size_t) vlistGridsizeMax(vlistID1);
array = (double*) Malloc(gridsize*sizeof(double));
}
}
@@ -124,9 +123,9 @@ void *Cat(void *argument)
int ntsteps = vlistNtsteps(vlistID1);
- tsID1 = 0;
+ int tsID1 = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID1)) )
- {
+ {
{
double fstatus = indf+1.;
if ( ntsteps > 1 ) fstatus = indf+(tsID1+1.)/ntsteps;
@@ -137,9 +136,14 @@ void *Cat(void *argument)
streamDefTimestep(streamID2, tsID2);
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
+
+ if ( lconstvars && tsID2 > 0 && tsID1 == 0 )
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+ continue;
+
streamDefRecord(streamID2, varID, levelID);
if ( lcopy )
@@ -156,6 +160,7 @@ void *Cat(void *argument)
tsID1++;
tsID2++;
}
+
streamClose(streamID1);
if ( cdoTimer ) tw = timer_val(timer_cat) - tw0;
diff --git a/src/CdoMagicsMapper.c b/src/CdoMagicsMapper.c
index 3996519..a982354 100644
--- a/src/CdoMagicsMapper.c
+++ b/src/CdoMagicsMapper.c
@@ -1,33 +1,37 @@
#if defined(HAVE_CONFIG_H)
-# include "config.h" /* HAVE_LIBMAGICS */
+# include "config.h"
#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "CdoMagicsMapper.h"
#include "magics_template_parser.h"
#define PARAM_COUNT sizeof( mapper ) / sizeof ( CdoMagicsMapper )
-/* extern int SetMagicsParameterValue( char *param_name, char *param_type, char *param_value ) */
+/* extern int SetMagicsParameterValue( const char *param_name, const char *param_type, const char *param_value ) */
-int Set_magics_param_CCOLS( char *user_name, char *param_value );
-int Reset_magics_param_CCOLS( char *user_name );
+int Set_magics_param_CCOLS( const char *user_name, const char *param_value );
+int Reset_magics_param_CCOLS( const char *user_name );
-int Set_magics_param_CLEVS( char *user_name, char *param_value );
-int Reset_magics_param_CLEVS( char *user_name );
+int Set_magics_param_CLEVS( const char *user_name, const char *param_value );
+int Reset_magics_param_CLEVS( const char *user_name );
-int Set_magics_param_CTABLE( char *user_name, char *param_value );
-int Reset_magics_param_CTABLE( char *user_name );
+int Set_magics_param_CTABLE( const char *user_name, const char *param_value );
+int Reset_magics_param_CTABLE( const char *user_name );
/* Define an array of Mapper structures to sort. */
typedef struct
{
- char *cdo_name;
- char *magics_name;
- char *magics_type;
- int (*Set_magics_param)( char *user_name, char *param_value ); /* Function to Update the Corresponding Magics parameters */
- int (*Reset_magics_param)(char *user_name ); /* Function to Reset the Corresponding Magics parameters */
+ const char *cdo_name;
+ const char *magics_name;
+ const char *magics_type;
+ int (*Set_magics_param)( const char *user_name, const char *param_value ); /* Function to Update the Corresponding Magics parameters */
+ int (*Reset_magics_param)(const char *user_name ); /* Function to Reset the Corresponding Magics parameters */
} CdoMagicsMapper;
@@ -58,93 +62,88 @@ CdoMagicsMapper mapper[] =
}
};
-int Compare( CdoMagicsMapper *Parameter_one , CdoMagicsMapper *Parameter_two );
void PrintResult ( const CdoMagicsMapper *c );
-int Set_magics_param_CCOLS( char *user_name, char *param_value )
+int Set_magics_param_CCOLS( const char *user_name, const char *param_value )
{
- if( user_name == NULL )
- return 1;
- printf("Setting the CCOLS magics params \n");
+ if( user_name == NULL )
+ return 1;
+ printf("Setting the CCOLS magics params \n");
- SetMagicsParameterValue( "contour_shade_colour_method", "string", "list" );
- SetMagicsParameterValue( "contour_shade_colour_list","stringarray", param_value );
+ SetMagicsParameterValue( "contour_shade_colour_method", "string", "list" );
+ SetMagicsParameterValue( "contour_shade_colour_list","stringarray", param_value );
#if 0
#endif
- return 0;
+ return 0;
}
-int Reset_magics_param_CCOLS( char *user_name )
-
+int Reset_magics_param_CCOLS( const char *user_name )
{
- printf("Re-Setting the CCOLS magics params \n");
- return 0;
+ (void)user_name;
+ printf("Re-Setting the CCOLS magics params \n");
+ return 0;
}
-int Set_magics_param_CLEVS( char *user_name, char *param_value )
-
+int Set_magics_param_CLEVS( const char *user_name, const char *param_value )
{
- if( user_name == NULL )
- return 1;
+ if( user_name == NULL )
+ return 1;
- SetMagicsParameterValue( "contour_level_selection_type","string", "level_list" );
- SetMagicsParameterValue( "contour_level_list","floatarray", param_value );
+ SetMagicsParameterValue( "contour_level_selection_type","string", "level_list" );
+ SetMagicsParameterValue( "contour_level_list","floatarray", param_value );
- return 0;
+ return 0;
}
-int Reset_magics_param_CLEVS( char *user_name )
-
+int Reset_magics_param_CLEVS( const char *user_name )
{
- SetMagicsParameterValue( "contour_level_selection_type","string", "count" );
- printf("Re-Setting the CLEVS magics params \n");
- return 0;
+ (void)user_name;
+ SetMagicsParameterValue( "contour_level_selection_type","string", "count" );
+ printf("Re-Setting the CLEVS magics params \n");
+ return 0;
}
-int Set_magics_param_CTABLE( char *user_name, char *param_value )
-
+int Set_magics_param_CTABLE( const char *user_name, const char *param_value )
{
- if( user_name == NULL )
- return 1;
- printf("Setting the CTABLE magics params \n");
+ (void)param_value;
+
+ if( user_name == NULL )
+ return 1;
+ printf("Setting the CTABLE magics params \n");
#if 0
-#if defined(HAVE_LIBMAGICS)
- SetMagicsParameterValue( "contour_level_list", "floatarray", param_value );
+ SetMagicsParameterValue( "contour_level_list", "floatarray", param_value );
#endif
-#endif
- return 0;
+ return 0;
}
-int Reset_magics_param_CTABLE( char *user_name )
-
+int Reset_magics_param_CTABLE( const char *user_name )
{
- printf("Re-Setting the CTABLE magics params \n");
- return 0;
+ (void)user_name;
+ printf("Re-Setting the CTABLE magics params \n");
+ return 0;
}
/* This is the comparison function used for sorting and searching. */
-int Compare( CdoMagicsMapper *p1, CdoMagicsMapper *p2 )
-
+int Compare( const void *p1, const void *p2 )
{
- return strcmp ( p1->cdo_name, p2->cdo_name );
+ return strcmp ( ((CdoMagicsMapper *)p1)->cdo_name, ((CdoMagicsMapper *)p2)->cdo_name );
}
/* Print information about a critter. */
void PrintResult ( const CdoMagicsMapper *c )
-
{
- printf ( "CDO Name:%s\t MAGICS Name:%s\t MAGICS Type:%s\n", c->cdo_name, c->magics_name, c->magics_type );
+ printf ( "CDO Name:%s\t MAGICS Name:%s\t MAGICS Type:%s\n", c->cdo_name, c->magics_name, c->magics_type );
}
@@ -153,34 +152,33 @@ void PrintResult ( const CdoMagicsMapper *c )
/* int GetMagicsParameterInfo( const char *user_name, char **magics_name, char **magics_type ) */
int GetMagicsParameterInfo( const char *user_name, char *param_value )
-
{
- static int once = 1;
- int ret_flag = 0;
- CdoMagicsMapper target, *result;
- target.cdo_name = (char *) user_name;
-
- if( once )
- {
- qsort ( mapper, PARAM_COUNT, sizeof ( CdoMagicsMapper ), ( void * )Compare );
- once = 0;
- }
-
- result = bsearch ( &target, mapper, PARAM_COUNT, sizeof ( CdoMagicsMapper ),
- ( void * )Compare );
- if ( result )
- {
- result->Set_magics_param( result->cdo_name, param_value );
-
- /*
- *magics_name = result->magics_name;
- *magics_type = result->magics_type;
- */
- }
- else
- {
- /* Call the Reset functions of all the features to Reset the magics params to default in the calling function */
- ret_flag = 1;
- }
- return ret_flag;
+ static int once = 1;
+ int ret_flag = 0;
+ CdoMagicsMapper target, *result;
+ target.cdo_name = (char *) user_name;
+
+ if( once )
+ {
+ qsort (mapper, PARAM_COUNT, sizeof( CdoMagicsMapper ), Compare);
+ once = 0;
+ }
+
+ result = (CdoMagicsMapper*) bsearch(&target, mapper, PARAM_COUNT, sizeof ( CdoMagicsMapper ), Compare);
+ if ( result )
+ {
+ result->Set_magics_param( result->cdo_name, param_value );
+
+ /*
+ *magics_name = result->magics_name;
+ *magics_type = result->magics_type;
+ */
+ }
+ else
+ {
+ /* Call the Reset functions of all the features to Reset the magics params to default in the calling function */
+ ret_flag = 1;
+ }
+
+ return ret_flag;
}
diff --git a/src/CdoMagicsMapper.h b/src/CdoMagicsMapper.h
index 06f5fc1..bd5798a 100644
--- a/src/CdoMagicsMapper.h
+++ b/src/CdoMagicsMapper.h
@@ -1,10 +1,6 @@
#ifndef CDO_MAGICS_MAPPER_HH
#define CDO_MAGICS_MAPPER_HH
-#include<stdio.h>
-#include<stdlib.h>
-#include<string.h>
-
/* void FindMagicsStruct ( const char *user_name ); */
int GetMagicsParameterInfo( const char *user_name, char *param_value );
diff --git a/src/Change.c b/src/Change.c
index efea385..597f2ba 100644
--- a/src/Change.c
+++ b/src/Change.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Change_e5slm.c b/src/Change_e5slm.c
index cef1c6f..d448fec 100644
--- a/src/Change_e5slm.c
+++ b/src/Change_e5slm.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Cloudlayer.c b/src/Cloudlayer.c
index 2626853..a2c2aea 100644
--- a/src/Cloudlayer.c
+++ b/src/Cloudlayer.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Collgrid.c b/src/Collgrid.c
index bf7a9a5..559dcfe 100644
--- a/src/Collgrid.c
+++ b/src/Collgrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -85,11 +85,14 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
int lsouthnorth = TRUE;
int gridID2 = -1;
int idx;
- int nx, ny, ix, iy, i, j, ij, offset;
+ int ny, ix, iy, i, j, ij, offset;
int lregular = FALSE;
int lcurvilinear = FALSE;
double *xvals2 = NULL, *yvals2 = NULL;
+ int nx = -1;
+ if ( nxblocks != -1 ) nx = nxblocks;
+
int gridID = vlistGrid(ef[0].vlistID, igrid);
int gridtype = gridInqType(gridID);
if ( gridtype == GRID_GENERIC && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 )
@@ -151,9 +154,15 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
if ( yvals[fileID][0] > yvals[fileID][ysize[fileID]-1] ) lsouthnorth = FALSE;
}
}
+ else
+ {
+ xyinfo[fileID].x = 0;
+ xyinfo[fileID].y = 0;
+ xyinfo[fileID].id = fileID;
+ }
}
- if ( cdoVerbose )
+ if ( cdoVerbose && lregular )
for ( int fileID = 0; fileID < nfiles; fileID++ )
printf("1 %d %g %g \n", xyinfo[fileID].id, xyinfo[fileID].x, xyinfo[fileID].y);
@@ -174,17 +183,19 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
for ( int fileID = 0; fileID < nfiles; fileID++ )
printf("3 %d %g %g \n", xyinfo[fileID].id, xyinfo[fileID].x, xyinfo[fileID].y);
- nx = 1;
- for ( int fileID = 1; fileID < nfiles; fileID++ )
+ if ( nx <= 0 )
{
- if ( DBL_IS_EQUAL(xyinfo[0].y, xyinfo[fileID].y) ) nx++;
- else break;
+ nx = 1;
+ for ( int fileID = 1; fileID < nfiles; fileID++ )
+ {
+ if ( DBL_IS_EQUAL(xyinfo[0].y, xyinfo[fileID].y) ) nx++;
+ else break;
+ }
}
}
else
{
- nx = nxblocks;
- if ( nx <= 0 ) cdoAbort("Parameter nx missing!");
+ if ( nx <= 0 ) nx = nfiles;
}
ny = nfiles/nx;
@@ -269,6 +280,15 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
if ( xvals2 ) Free(xvals2);
if ( yvals2 ) Free(yvals2);
+ for ( int fileID = 0; fileID < nfiles; fileID++ )
+ {
+ if ( xvals[fileID] ) Free(xvals[fileID]);
+ if ( yvals[fileID] ) Free(yvals[fileID]);
+ }
+ Free(xvals);
+ Free(yvals);
+ Free(xyinfo);
+
char string[1024];
string[0] = 0;
gridID = vlistGrid(ef[0].vlistID, igrid);
@@ -285,22 +305,13 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
gridInqYunits(gridID, string);
gridDefYunits(gridID2, string);
- for ( int fileID = 0; fileID < nfiles; fileID++ )
- {
- if ( xvals[fileID] ) Free(xvals[fileID]);
- if ( yvals[fileID] ) Free(yvals[fileID]);
- }
- Free(xvals);
- Free(yvals);
- Free(xyinfo);
-
return gridID2;
}
void *Collgrid(void *argument)
{
- int nxblocks = 1;
+ int nxblocks = -1;
int varID, recID;
int nrecs, nrecs0;
int levelID;
@@ -476,8 +487,7 @@ void *Collgrid(void *argument)
{
if ( gridIDs[i] != -1 )
{
- if ( gridID == vlistGrid(vlistID2, i) )
- vars[varID] = TRUE;
+ if ( gridID == vlistGrid(vlistID2, i) ) vars[varID] = TRUE;
break;
}
}
diff --git a/src/Command.c b/src/Command.c
index d6c6a75..bc7b431 100644
--- a/src/Command.c
+++ b/src/Command.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Comp.c b/src/Comp.c
index 1a2f887..ad4be40 100644
--- a/src/Comp.c
+++ b/src/Comp.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Compc.c b/src/Compc.c
index da9abe7..cfdbc62 100644
--- a/src/Compc.c
+++ b/src/Compc.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Complextorect.c b/src/Complextorect.c
index c0c1940..04d432e 100644
--- a/src/Complextorect.c
+++ b/src/Complextorect.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -123,5 +123,5 @@ void *Complextorect(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Cond.c b/src/Cond.c
index 7f34566..3233d09 100644
--- a/src/Cond.c
+++ b/src/Cond.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Cond2.c b/src/Cond2.c
index 1e7af49..6e08f73 100644
--- a/src/Cond2.c
+++ b/src/Cond2.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Condc.c b/src/Condc.c
index 41720a1..3979662 100644
--- a/src/Condc.c
+++ b/src/Condc.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Consecstat.c b/src/Consecstat.c
index 7ee6152..c48f4ed 100644
--- a/src/Consecstat.c
+++ b/src/Consecstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -128,7 +128,8 @@ void *Consecstat(void *argument)
int histvdate = 0, histvtime = 0;
int recID, nrecs;
int varID, nvars;
- int levelID, nlevels;
+ int levelID, nlevels;
+ int nmiss;
double refval = 0.0;
field_t **vars = NULL, **hist = NULL, **periods = NULL;
@@ -199,7 +200,8 @@ void *Consecstat(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(istreamID, &varID, &levelID);
- streamReadRecord(istreamID, field.ptr, &field.nmiss);
+ streamReadRecord(istreamID, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vlistInqVarGrid(ovlistID, varID);
field.missval = vlistInqVarMissval(ovlistID, varID);
@@ -209,14 +211,14 @@ void *Consecstat(void *argument)
{
case CONSECSUM:
streamDefRecord(ostreamID, varID, levelID);
- streamWriteRecord(ostreamID, vars[varID][levelID].ptr, vars[varID][levelID].nmiss);
+ streamWriteRecord(ostreamID, vars[varID][levelID].ptr, (int)vars[varID][levelID].nmiss);
break;
case CONSECTS:
if ( itsID != 0 )
{
selEndOfPeriod(&periods[varID][levelID], hist[varID][levelID], vars[varID][levelID], FALSE);
streamDefRecord(ostreamID, varID, levelID);
- streamWriteRecord(ostreamID, periods[varID][levelID].ptr, periods[varID][levelID].nmiss);
+ streamWriteRecord(ostreamID, periods[varID][levelID].ptr, (int)periods[varID][levelID].nmiss);
}
#if defined(_OPENMP)
#pragma omp parallel for default(shared) schedule(static)
@@ -251,7 +253,7 @@ void *Consecstat(void *argument)
{
selEndOfPeriod(&periods[varID][levelID], hist[varID][levelID], vars[varID][levelID], TRUE);
streamDefRecord(ostreamID, varID, levelID);
- streamWriteRecord(ostreamID, periods[varID][levelID].ptr, periods[varID][levelID].nmiss);
+ streamWriteRecord(ostreamID, periods[varID][levelID].ptr, (int)periods[varID][levelID].nmiss);
}
}
}
diff --git a/src/Copy.c b/src/Copy.c
index 508c899..411ae37 100644
--- a/src/Copy.c
+++ b/src/Copy.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -30,30 +30,27 @@
void *Copy(void *argument)
{
- int SELALL, SZIP;
- int operatorID;
- int streamID1, streamID2 = CDI_UNDEFID;
+ bool lconstvars = true;
+ int streamID2 = CDI_UNDEFID;
+ int vlistID2 = CDI_UNDEFID;
+ int taxisID2 = CDI_UNDEFID;
int nrecs;
- int tsID1, tsID2, recID, varID, levelID;
- int lcopy = FALSE;
- int gridsize;
- int vlistID1, vlistID2 = CDI_UNDEFID;
+ int recID, varID, levelID;
int nmiss;
- int streamCnt, nfiles, indf;
- int taxisID1, taxisID2 = CDI_UNDEFID;
int ntsteps, nvars;
double *array = NULL;
par_io_t parIO;
cdoInitialize(argument);
- cdoOperatorAdd("copy", 0, 0, NULL);
- SELALL = cdoOperatorAdd("selall", 0, 0, NULL);
- SZIP = cdoOperatorAdd("szip", 0, 0, NULL);
+ cdoOperatorAdd("copy", 0, 0, NULL);
+ int SELALL = cdoOperatorAdd("selall", 0, 0, NULL);
+ int SZIP = cdoOperatorAdd("szip", 0, 0, NULL);
- if ( UNCHANGED_RECORD ) lcopy = TRUE;
+ bool lcopy = false;
+ if ( UNCHANGED_RECORD ) lcopy = true;
- operatorID = cdoOperatorID();
+ int operatorID = cdoOperatorID();
if ( operatorID == SZIP )
{
@@ -61,18 +58,18 @@ void *Copy(void *argument)
cdoCompLevel = 0;
}
- streamCnt = cdoStreamCnt();
- nfiles = streamCnt - 1;
+ int streamCnt = cdoStreamCnt();
+ int nfiles = streamCnt - 1;
- tsID2 = 0;
- for ( indf = 0; indf < nfiles; indf++ )
+ int tsID2 = 0;
+ for ( int indf = 0; indf < nfiles; indf++ )
{
if ( cdoVerbose ) cdoPrint("Process file: %s", cdoStreamName(indf)->args);
- streamID1 = streamOpenRead(cdoStreamName(indf));
+ int streamID1 = streamOpenRead(cdoStreamName(indf));
- vlistID1 = streamInqVlist(streamID1);
- taxisID1 = vlistInqTaxis(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int taxisID1 = vlistInqTaxis(vlistID1);
if ( indf == 0 )
{
@@ -95,13 +92,14 @@ void *Copy(void *argument)
if ( ntsteps == 0 && nfiles > 1 )
{
+ lconstvars = false;
for ( varID = 0; varID < nvars; ++varID )
vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
}
streamDefVlist(streamID2, vlistID2);
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
array = (double*) Malloc(gridsize*sizeof(double));
if ( cdoParIO )
{
@@ -115,7 +113,7 @@ void *Copy(void *argument)
vlistCompare(vlistID1, vlistID2, CMP_ALL);
}
- tsID1 = 0;
+ int tsID1 = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID1)) )
{
taxisCopyTimestep(taxisID2, taxisID1);
@@ -127,6 +125,11 @@ void *Copy(void *argument)
if ( lcopy && (operatorID == SELALL || operatorID == SZIP) )
{
streamInqRecord(streamID1, &varID, &levelID);
+
+ if ( lconstvars && tsID2 > 0 && tsID1 == 0 )
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+ continue;
+
streamDefRecord(streamID2, varID, levelID);
streamCopyRecord(streamID2, streamID1);
}
@@ -142,6 +145,11 @@ void *Copy(void *argument)
else
{
streamInqRecord(streamID1, &varID, &levelID);
+
+ if ( lconstvars && tsID2 > 0 && tsID1 == 0 )
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+ continue;
+
streamReadRecord(streamID1, array, &nmiss);
}
/*
diff --git a/src/Deltime.c b/src/Deltime.c
index dbc08ff..9dd98ea 100644
--- a/src/Deltime.c
+++ b/src/Deltime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -164,5 +164,5 @@ void *Deltime(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Derivepar.c b/src/Derivepar.c
index 28cb0b1..c878d96 100644
--- a/src/Derivepar.c
+++ b/src/Derivepar.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/Detrend.c b/src/Detrend.c
index 315d306..6a1875d 100644
--- a/src/Detrend.c
+++ b/src/Detrend.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -56,12 +56,12 @@ void detrend(long nts, double missval1, double *array1, double *array2)
n++;
}
- work1 = DIV(SUB(sumjx, DIV(MUL(sumx, sumj), n) ),
- SUB(sumjj, DIV(MUL(sumj, sumj), n)) );
- work2 = SUB(DIV(sumx, n), MUL(work1, DIV(sumj, n)));
+ work1 = DIVMN( SUBMN(sumjx, DIVMN( MULMN(sumx, sumj), n) ),
+ SUBMN(sumjj, DIVMN( MULMN(sumj, sumj), n)) );
+ work2 = SUBMN( DIVMN(sumx, n), MULMN(work1, DIVMN(sumj, n)));
for ( j = 0; j < nts; j++ )
- array2[j] = SUB(array1[j], ADD(work2, MUL(j, work1)));
+ array2[j] = SUBMN(array1[j], ADDMN(work2, MULMN(j, work1)));
}
diff --git a/src/Diff.c b/src/Diff.c
index 23dd7bb..9244412 100644
--- a/src/Diff.c
+++ b/src/Diff.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Distgrid.c b/src/Distgrid.c
index 27c13ae..9e97b83 100644
--- a/src/Distgrid.c
+++ b/src/Distgrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Duplicate.c b/src/Duplicate.c
index 18dcf87..6d7f563 100644
--- a/src/Duplicate.c
+++ b/src/Duplicate.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ void *Duplicate(void *argument)
int nvars, nlevel;
int ntsteps;
int *vdate = NULL, *vtime = NULL;
- int idup, ndup = 1;
+ int idup, ndup = 2;
field_t ***vars = NULL;
cdoInitialize(argument);
diff --git a/src/EOFs.c b/src/EOFs.c
index d670010..695949c 100644
--- a/src/EOFs.c
+++ b/src/EOFs.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Echam5ini.c b/src/Echam5ini.c
index 43612d1..7e5bb2b 100644
--- a/src/Echam5ini.c
+++ b/src/Echam5ini.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -104,7 +104,7 @@ static
void nce(int istat)
{
/*
- This routine provides a simple interface to netCDF error message routine.
+ This routine provides a simple interface to NetCDF error message routine.
*/
if ( istat != NC_NOERR ) cdoAbort(nc_strerror(istat));
@@ -268,7 +268,7 @@ int import_e5ml(const char *filename, VAR **vars)
nvars = nvars_ml + 1;
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
return (nvars);
@@ -605,7 +605,7 @@ void export_e5ml(const char *filename, VAR *vars, int nvars, int vdate, int vtim
nce(nc_close(nc_file_id));
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
}
@@ -1075,7 +1075,7 @@ int import_e5res(const char *filename, VAR **vars, ATTS *atts)
nvars = varid;
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
return (nvars);
@@ -1420,7 +1420,7 @@ void export_e5res(const char *filename, VAR *vars, int nvars)
nce(nc_close(nc_file_id));
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
}
diff --git a/src/Enlarge.c b/src/Enlarge.c
index 3d9268a..e1f5a71 100644
--- a/src/Enlarge.c
+++ b/src/Enlarge.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Enlargegrid.c b/src/Enlargegrid.c
index 0fca3c3..0a0aebe 100644
--- a/src/Enlargegrid.c
+++ b/src/Enlargegrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Ensstat.c b/src/Ensstat.c
index a7da8b6..7d142d4 100644
--- a/src/Ensstat.c
+++ b/src/Ensstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Ensstat3.c b/src/Ensstat3.c
index 45f6a66..98328df 100644
--- a/src/Ensstat3.c
+++ b/src/Ensstat3.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Ensval.c b/src/Ensval.c
index 1338930..f80c06d 100644
--- a/src/Ensval.c
+++ b/src/Ensval.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Eof3d.c b/src/Eof3d.c
index 5883300..b91c303 100644
--- a/src/Eof3d.c
+++ b/src/Eof3d.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Eofcoeff.c b/src/Eofcoeff.c
index 0a62b97..96c066f 100644
--- a/src/Eofcoeff.c
+++ b/src/Eofcoeff.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -127,8 +127,8 @@ void *Eofcoeff(void * argument)
if ( levelID >= nlevs )
cdoAbort("Internal error - too high levelID");
- streamReadRecord(streamID1, eof[varID][levelID][eofID].ptr,
- &eof[varID][levelID][eofID].nmiss);
+ streamReadRecord(streamID1, eof[varID][levelID][eofID].ptr, &nmiss);
+ eof[varID][levelID][eofID].nmiss = (size_t) nmiss;
}
eofID++;
}
@@ -203,7 +203,8 @@ void *Eofcoeff(void * argument)
{
streamInqRecord(streamID2, &varID, &levelID);
missval2 = vlistInqVarMissval(vlistID2, varID);
- streamReadRecord(streamID2, in.ptr, &in.nmiss);
+ streamReadRecord(streamID2, in.ptr, &nmiss);
+ in.nmiss = (size_t) nmiss;
for (eofID = 0; eofID < neof; eofID++ )
{
diff --git a/src/Eofcoeff3d.c b/src/Eofcoeff3d.c
index e647975..db1d24f 100644
--- a/src/Eofcoeff3d.c
+++ b/src/Eofcoeff3d.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -127,8 +127,8 @@ void *Eofcoeff3d(void * argument)
if ( levelID >= nlevs )
cdoAbort("Internal error - too high levelID");
- streamReadRecord(streamID1, eof[varID][levelID][eofID].ptr,
- &eof[varID][levelID][eofID].nmiss);
+ streamReadRecord(streamID1, eof[varID][levelID][eofID].ptr, &nmiss);
+ eof[varID][levelID][eofID].nmiss = (size_t) nmiss;
}
eofID++;
}
@@ -212,8 +212,8 @@ void *Eofcoeff3d(void * argument)
{
streamInqRecord(streamID2, &varID, &levelID);
missval2 = vlistInqVarMissval(vlistID2, varID);
- streamReadRecord(streamID2, in.ptr, &in.nmiss);
-
+ streamReadRecord(streamID2, in.ptr, &nmiss);
+ in.nmiss = (size_t) nmiss;
for (eofID = 0; eofID < neof; eofID++ )
{
@@ -248,7 +248,7 @@ void *Eofcoeff3d(void * argument)
for ( eofID = 0; eofID < neof; eofID++ ) {
for ( varID = 0; varID < nvars; varID++ ) {
streamDefRecord(streamIDs[eofID], varID, 0);
- streamWriteRecord(streamIDs[eofID],out[varID][eofID].ptr,out[varID][eofID].nmiss);
+ streamWriteRecord(streamIDs[eofID], out[varID][eofID].ptr, (int)out[varID][eofID].nmiss);
}
}
diff --git a/src/Exprf.c b/src/Exprf.c
index 54b232f..83ee7b3 100644
--- a/src/Exprf.c
+++ b/src/Exprf.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
Exprf aexprf Append evaluated expressions from script file
*/
/*
-Operatoren: +, -, *, \, ^
+Operatoren: +, -, *, \, ^, ==, !=, >, <, >=, <=, <=>, &&, ||, ?:
Functions: sqrt, exp, log, log10, sin, cos, tan, asin, acos, atan
Functions: min, max, avg, std, var
Constansts: M_PI, M_E
@@ -38,242 +38,512 @@ Constansts: M_PI, M_E
#include "cdo.h"
#include "cdo_int.h"
#include "pstream.h"
+#include "grid.h"
#include "expr.h"
+void grid_cell_area(int gridID, double *array);
+int getSurfaceID(int vlistID);
-void *Expr(void *argument)
+static
+char *exprs_from_arg(const char *arg)
{
- int operatorID;
char *exprs = NULL;
- const char *exprf = NULL;
- int streamID1, streamID2 = CDI_UNDEFID;
- int offset;
- int nrecs, nvars, nvars1, nvars2;
- int gridID, zaxisID;
- int tsID, recID, varID, levelID;
- int vlistID1, vlistID2;
- int gridsize, nlevel;
- int nmiss;
- int taxisID1, taxisID2;
- //int lwarn = TRUE;
- double missval;
- double *array = NULL;
- double *single1, *single2;
- parse_parm_t parse_arg;
- void *scanner;
- int yy_scan_string(const char *str, void *scanner);
+
+ size_t slen = strlen(arg);
+ exprs = (char*) Malloc(slen+2);
+ strcpy(exprs, operatorArgv()[0]);
+ if ( exprs[slen-1] != ';' )
+ {
+ exprs[slen] = ';';
+ exprs[slen+1] = 0;
+ }
- cdoInitialize(argument);
+ return exprs;
+}
- yylex_init(&scanner);
- yyset_extra(&parse_arg, scanner);
+static
+char *exprs_from_file(const char *exprf)
+{
+ char *exprs = NULL;
+
+ /* Open expr script file for reading */
+ FILE *fp = fopen(exprf, "r");
+ if( fp == NULL ) cdoAbort("Open failed on %s", exprf);
+ struct stat filestat;
+ if ( stat(exprf, &filestat) != 0 ) cdoAbort("Stat failed on %s", exprf);
-# define REPLACES_VARIABLES(id) cdoOperatorF1(id)
-# define READS_COMMAND_LINE(id) cdoOperatorF2(id)
+ size_t fsize = (size_t) filestat.st_size;
+ exprs = (char*) Malloc(fsize+1);
- cdoOperatorAdd("expr", 1, 1, "expressions");
- cdoOperatorAdd("exprf", 1, 0, "expr script filename");
- cdoOperatorAdd("aexpr", 0, 1, "expressions");
- cdoOperatorAdd("aexprf", 0, 0, "expr script filename");
+ int ichar, ipos = 0;
+ while ( (ichar = fgetc(fp)) != EOF ) exprs[ipos++] = ichar;
- operatorID = cdoOperatorID();
+ exprs[ipos] = 0;
+ if ( ipos == 0 ) cdoAbort("%s is empty!", exprf);
- operatorInputArg(cdoOperatorEnter(operatorID));
+ fclose(fp);
- if ( READS_COMMAND_LINE(operatorID) )
- {
- size_t slen;
+ return exprs;
+}
- slen = strlen(operatorArgv()[0]);
- exprs = (char*) Malloc(slen+2);
- strcpy(exprs, operatorArgv()[0]);
- if ( exprs[slen-1] != ';' )
- {
- exprs[slen] = ';';
- exprs[slen+1] = 0;
- }
- }
- else
- {
- int ichar, ipos = 0;
- FILE *fp;
- size_t fsize;
- struct stat filestat;
+#define MAX_PARAMS 4096
- exprf = operatorArgv()[0];
- /* Open script file for reading */
- if( (fp = fopen(exprf, "r")) == NULL ) cdoAbort("Open failed on %s", exprf);
+static
+paramType *params_new(int vlistID)
+{
+ paramType *params = (paramType*) Malloc(MAX_PARAMS*sizeof(paramType));
+ memset(params, 0, MAX_PARAMS*sizeof(paramType));
- if ( stat(exprf, &filestat) != 0 ) cdoAbort("Stat failed on %s", exprf);
+ int nvars1 = vlistNvars(vlistID);
- fsize = (size_t) filestat.st_size;
- exprs = (char*) Malloc(fsize+1);
+ char name[CDI_MAX_NAME];
+ char longname[CDI_MAX_NAME];
+ char units[CDI_MAX_NAME];
+ for ( int varID = 0; varID < nvars1; varID++ )
+ {
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ int steptype = vlistInqVarTsteptype(vlistID, varID);
+ int ngp = gridInqSize(gridID);
+ int nlev = zaxisInqSize(zaxisID);
+ double missval = vlistInqVarMissval(vlistID, varID);
+
+ vlistInqVarName(vlistID, varID, name);
+ vlistInqVarLongname(vlistID, varID, longname);
+ vlistInqVarUnits(vlistID, varID, units);
+
+ params[varID].select = false;
+ params[varID].remove = false;
+ params[varID].lmiss = true;
+ params[varID].coord = 0;
+ params[varID].gridID = gridID;
+ params[varID].zaxisID = zaxisID;
+ params[varID].steptype = steptype;
+ params[varID].ngp = ngp;
+ params[varID].nlev = nlev;
+ params[varID].missval = missval;
+ params[varID].nmiss = 0;
+ params[varID].data = NULL;
+ params[varID].name = strdup(name);
+ params[varID].longname = strdup(longname);
+ params[varID].units = strdup(units);
+ }
- while ( (ichar = fgetc(fp)) != EOF ) exprs[ipos++] = ichar;
+ return params;
+}
- exprs[ipos] = 0;
+static
+void params_add_coord(parse_param_t *parse_arg, int coord, int cdiID, int size, const char *units, const char *longname)
+{
+ int ncoords = parse_arg->ncoords;
+ if ( ncoords >= parse_arg->maxcoords )
+ cdoAbort("Too many coordinates (limit=%d)", parse_arg->maxcoords);
+
+ parse_arg->coords[ncoords].needed = false;
+ parse_arg->coords[ncoords].coord = coord;
+ parse_arg->coords[ncoords].cdiID = cdiID;
+ parse_arg->coords[ncoords].size = size;
+ parse_arg->coords[ncoords].units = NULL;
+ parse_arg->coords[ncoords].longname = NULL;
+ parse_arg->coords[ncoords].data = NULL;
+ if ( units ) parse_arg->coords[ncoords].units = strdup(units);
+ if ( longname ) parse_arg->coords[ncoords].longname = strdup(longname);
+
+ parse_arg->ncoords++;
+}
- if ( ipos == 0 ) cdoAbort("%s is empty!", exprf);
- fclose(fp);
+int params_get_coordID(parse_param_t *parse_arg, int coord, int cdiID)
+{
+ int ncoords = parse_arg->ncoords;
+ for ( int coordID = 0; coordID < ncoords; ++coordID )
+ {
+ if ( parse_arg->coords[coordID].coord == coord &&
+ parse_arg->coords[coordID].cdiID == cdiID )
+ return coordID;
}
- if ( cdoVerbose ) cdoPrint(exprs);
-
+ cdoAbort("%s: coordinate %c not found!", __func__, coord);
+
+ return -1;
+}
- streamID1 = streamOpenRead(cdoStreamName(0));
+static
+void params_add_coordinates(int vlistID, parse_param_t *parse_arg)
+{
+ char longname[CDI_MAX_NAME];
+ char units[CDI_MAX_NAME];
+ int ngrids = vlistNgrids(vlistID);
+ for ( int index = 0; index < ngrids; ++index )
+ {
+ int gridID = vlistGrid(vlistID, index);
+ int size = gridInqSize(gridID);
+ gridInqXunits(gridID, units);
+ params_add_coord(parse_arg, 'x', gridID, size, units, "longitude");
+ gridInqYunits(gridID, units);
+ params_add_coord(parse_arg, 'y', gridID, size, units, "latitude");
+
+ params_add_coord(parse_arg, 'a', gridID, size, "m^2", "grid cell area");
+ params_add_coord(parse_arg, 'w', gridID, size, NULL, "grid cell area weights");
+ }
+ int nzaxis = vlistNzaxis(vlistID);
+ for ( int index = 0; index < nzaxis; ++index )
+ {
+ int zaxisID = vlistZaxis(vlistID, index);
+ int size = zaxisInqSize(zaxisID);
+ zaxisInqUnits(zaxisID, units);
+ zaxisInqLongname(zaxisID, longname);
+ params_add_coord(parse_arg, 'z', zaxisID, size, units, longname);
+ }
+}
- vlistID1 = streamInqVlist(streamID1);
+static
+int params_add_ts(parse_param_t *parse_arg)
+{
+ int varID = -1;
+ paramType *params = parse_arg->params;
+ if ( params )
+ {
+ varID = parse_arg->nparams;
+ if ( varID >= parse_arg->maxparams )
+ cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams);
+
+ params[varID].name = strdup("_ts");
+ params[varID].gridID = parse_arg->pointID;
+ params[varID].zaxisID = parse_arg->surfaceID;
+ params[varID].steptype = TIME_VARIABLE;
+ params[varID].ngp = 1;
+ params[varID].nlev = 1;
+
+ parse_arg->nparams++;
+ }
- nvars1 = vlistNvars(vlistID1);
+ return varID;
+}
- if ( REPLACES_VARIABLES(operatorID) )
+static
+void params_delete(paramType *params)
+{
+ if ( params )
{
- vlistID2 = vlistCreate();
- nvars = 0;
+ for ( int varID = 0; varID < MAX_PARAMS; varID++ )
+ {
+ if ( params[varID].data ) Free(params[varID].data);
+ if ( params[varID].name ) Free(params[varID].name);
+ if ( params[varID].longname ) Free(params[varID].longname);
+ if ( params[varID].units ) Free(params[varID].units);
+ }
+ Free(params);
}
+}
+
+void *Expr(void *argument)
+{
+ cdoInitialize(argument);
+
+ parse_param_t parse_arg;
+ void *scanner;
+ int yy_scan_string(const char *str, void *scanner);
+
+ yylex_init(&scanner);
+ yyset_extra(&parse_arg, scanner);
+
+#define REPLACES_VARIABLES(id) cdoOperatorF1(id)
+#define READS_COMMAND_LINE(id) cdoOperatorF2(id)
+
+ cdoOperatorAdd("expr", 1, 1, "expressions");
+ cdoOperatorAdd("exprf", 1, 0, "expr script filename");
+ cdoOperatorAdd("aexpr", 0, 1, "expressions");
+ cdoOperatorAdd("aexprf", 0, 0, "expr script filename");
+
+ int operatorID = cdoOperatorID();
+
+ operatorInputArg(cdoOperatorEnter(operatorID));
+
+ char *exprs = NULL;
+ if ( READS_COMMAND_LINE(operatorID) )
+ exprs = exprs_from_arg(operatorArgv()[0]);
else
- {
- vlistID2 = vlistDuplicate(vlistID1);
- nvars = nvars1;
- }
+ exprs = exprs_from_file(operatorArgv()[0]);
- parse_arg.init = 1;
- parse_arg.vlistID1 = vlistID1;
- parse_arg.vlistID2 = vlistID2;
- parse_arg.nvars1 = 0;
- parse_arg.debug = 0;
- if ( cdoVerbose ) parse_arg.debug = 1;
- parse_arg.gridID2 = -1;
- parse_arg.zaxisID2 = -1;
- parse_arg.tsteptype2 = -1;
-
- /* Set all input variables to 'needed' if replacing is switched off */
- for ( varID = 0; varID < nvars1; varID++ )
- parse_arg.var_needed[varID] = ! REPLACES_VARIABLES(operatorID);
+ if ( cdoVerbose ) cdoPrint(exprs);
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+ int vlistID1 = streamInqVlist(streamID1);
+ int nvars1 = vlistNvars(vlistID1);
+ int ngrids = vlistNgrids(vlistID1);
+ int nzaxis = vlistNzaxis(vlistID1);
+ int maxcoords = ngrids*4+nzaxis;
+
+ int pointID = gridCreate(GRID_GENERIC, 1);
+ int surfaceID = getSurfaceID(vlistID1);
+
+ paramType *params = params_new(vlistID1);
+
+ parse_arg.maxparams = MAX_PARAMS;
+ parse_arg.nparams = nvars1;
+ parse_arg.nvars1 = nvars1;
+ parse_arg.init = true;
+ parse_arg.debug = false;
+ if ( cdoVerbose ) parse_arg.debug = true;
+ parse_arg.params = params;
+ parse_arg.pointID = pointID;
+ parse_arg.surfaceID = surfaceID;
+ parse_arg.needed = (bool*) Malloc(nvars1*sizeof(bool));
+ parse_arg.coords = (coordType*) Malloc(maxcoords*sizeof(coordType));
+ parse_arg.maxcoords = maxcoords;
+ parse_arg.ncoords = 0;
+
+ /* Set all input variables to 'needed' if replacing is switched off */
+ for ( int varID = 0; varID < nvars1; varID++ )
+ parse_arg.needed[varID] = ! REPLACES_VARIABLES(operatorID);
+
+ int vartsID = params_add_ts(&parse_arg);
+ parse_arg.tsID = vartsID;
+ params_add_coordinates(vlistID1, &parse_arg);
+
+ CDO_parser_errorno = 0;
yy_scan_string(exprs, scanner);
yyparse(&parse_arg, scanner);
+ if ( CDO_parser_errorno != 0 ) cdoAbort("Syntax error!");
- parse_arg.init = 0;
+ parse_arg.init = false;
- nvars2 = vlistNvars(vlistID2);
- if ( nvars2 == 0 ) cdoAbort("No output variable found!");
-
- if ( cdoVerbose ) vlistPrint(vlistID2);
+ if ( cdoVerbose )
+ for ( int varID = 0; varID < nvars1; varID++ )
+ if ( parse_arg.needed[varID] )
+ cdoPrint("Needed var: %d %s", varID, params[varID].name);
if ( cdoVerbose )
- for ( varID = 0; varID < nvars1; varID++ )
- if ( parse_arg.var_needed[varID] )
- printf("Needed var: %d %s\n", varID, parse_arg.var[varID]);
+ for ( int varID = 0; varID < parse_arg.nparams; varID++ )
+ cdoPrint("var: %d %s ngp=%lu nlev=%lu coord=%c",
+ varID, params[varID].name, params[varID].ngp, params[varID].nlev, params[varID].coord);
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = taxisDuplicate(taxisID1);
- vlistDefTaxis(vlistID2, taxisID2);
+ int *varIDmap = (int*) Malloc(parse_arg.nparams*sizeof(int));
- streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+ int vlistID2 = vlistCreate();
+ if ( ! REPLACES_VARIABLES(operatorID) )
+ {
+ vlistClearFlag(vlistID1);
+ int pidx = 0;
+ for ( int varID = 0; varID < nvars1; varID++ )
+ {
+ params[varID].select = false;
+ if ( params[varID].remove == false )
+ {
+ varIDmap[pidx++] = varID;
+ int nlevs = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
+ for ( int levID = 0; levID < nlevs; levID++ )
+ vlistDefFlag(vlistID1, varID, levID, TRUE);
+ }
+ }
+ vlistCopyFlag(vlistID2, vlistID1);
+ }
- streamDefVlist(streamID2, vlistID2);
+ for ( int pidx = 0; pidx < parse_arg.nparams; pidx++ )
+ {
+ if ( pidx < nvars1 && params[pidx].select == false ) continue;
+ if ( pidx >= nvars1 && params[pidx].name[0] == '_' ) continue;
+ if ( pidx >= nvars1 && params[pidx].remove == true ) continue;
+ if ( pidx >= nvars1 && params[pidx].coord ) continue;
+
+ int varID = vlistDefVar(vlistID2, params[pidx].gridID, params[pidx].zaxisID, params[pidx].steptype);
+ vlistDefVarName(vlistID2, varID, params[pidx].name);
+ if ( params[pidx].lmiss ) vlistDefVarMissval(vlistID2, varID, params[pidx].missval);
+ if ( params[pidx].units ) vlistDefVarUnits(vlistID2, varID, params[pidx].units);
+ if ( params[pidx].longname ) vlistDefVarLongname(vlistID2, varID, params[pidx].longname);
+ if ( memcmp(params[pidx].name, "var", 3) == 0 )
+ {
+ if ( strlen(params[pidx].name) > 3 && isdigit(params[pidx].name[3]) )
+ {
+ int code = atoi(params[pidx].name+3);
+ vlistDefVarCode(vlistID2, varID, code);
+ }
+ }
+ varIDmap[varID] = pidx;
+ }
- parse_arg.vardata1 = (double**) Malloc(nvars1*sizeof(double*));
- parse_arg.vardata2 = (double**) Malloc(nvars2*sizeof(double*));
+ int nvars2 = vlistNvars(vlistID2);
+ if ( nvars2 == 0 ) cdoAbort("No output variable found!");
- for ( varID = 0; varID < nvars1; varID++ )
+ for ( int varID = 0; varID < nvars1; varID++ )
{
- gridID = vlistInqVarGrid(vlistID1, varID);
- zaxisID = vlistInqVarZaxis(vlistID1, varID);
- /* parse_arg.missval[varID] = vlistInqVarMissval(vlistID1, varID); */
-
- gridsize = gridInqSize(gridID);
- nlevel = zaxisInqSize(zaxisID);
- if ( parse_arg.var_needed[varID] )
- parse_arg.vardata1[varID] = (double*) Malloc(gridsize*nlevel*sizeof(double));
- else
- parse_arg.vardata1[varID] = NULL;
+ if ( parse_arg.needed[varID] )
+ {
+ size_t ngp = params[varID].ngp;
+ size_t nlev = params[varID].nlev;
+ params[varID].data = (double*) Malloc(ngp*nlev*sizeof(double));
+ }
}
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = parse_arg.nvars1; varID < parse_arg.nparams; varID++ )
{
- parse_arg.vardata2[varID] = parse_arg.vardata1[varID];
+ size_t ngp = params[varID].ngp;
+ size_t nlev = params[varID].nlev;
+ params[varID].data = (double*) Malloc(ngp*nlev*sizeof(double));
}
- for ( varID = nvars; varID < nvars2; varID++ )
+ for ( int i = 0; i < parse_arg.ncoords; i++ )
{
- gridID = vlistInqVarGrid(vlistID2, varID);
- zaxisID = vlistInqVarZaxis(vlistID2, varID);
-
- gridsize = gridInqSize(gridID);
- nlevel = zaxisInqSize(zaxisID);
- parse_arg.vardata2[varID] = (double*) Malloc(gridsize*nlevel*sizeof(double));
+ if ( parse_arg.coords[i].needed )
+ {
+ int coord = parse_arg.coords[i].coord;
+ if ( coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w' )
+ {
+ int gridID = parse_arg.coords[i].cdiID;
+ size_t ngp = parse_arg.coords[i].size;
+ double *data = (double*) malloc(ngp*sizeof(double));
+ parse_arg.coords[i].data = data;
+ if ( coord == 'x' || coord == 'y' )
+ {
+ if ( gridInqType(gridID) == GRID_GENERIC )
+ cdoAbort("Grid has no geographical coordinates!");
+ if ( gridInqType(gridID) == GRID_GME )
+ gridID = gridToUnstructured(gridID, 0);
+ if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
+ gridID = gridToCurvilinear(gridID, 0);
+
+ if ( coord == 'x' ) gridInqXvals(gridID, data);
+ else if ( coord == 'y' ) gridInqYvals(gridID, data);
+
+ if ( gridID != parse_arg.coords[i].cdiID ) gridDestroy(gridID);
+ }
+ else if ( coord == 'a' )
+ {
+ grid_cell_area(gridID, data);
+ }
+ else if ( coord == 'w' )
+ {
+ data[0] = 1;
+ if ( ngp > 1 )
+ {
+ int wstatus = gridWeights(gridID, data);
+ if ( wstatus )
+ cdoWarning("Grid cell bounds not available, using constant grid cell area weights!");
+ }
+ }
+ }
+ else if ( coord == 'z' )
+ {
+ int zaxisID = parse_arg.coords[i].cdiID;
+ size_t nlev = parse_arg.coords[i].size;
+ double *data = (double*) malloc(nlev*sizeof(double));
+ parse_arg.coords[i].data = data;
+ zaxisInqLevels(zaxisID, data);
+ }
+ else
+ cdoAbort("Computation of coordinate %c not implemented!", coord);
+ }
+ }
+
+ for ( int varID = parse_arg.nvars1; varID < parse_arg.nparams; varID++ )
+ {
+ int coord = params[varID].coord;
+ if ( coord )
+ {
+ char *varname = strdup(params[varID].name);
+ varname[strlen(varname)-2] = 0;
+ if ( coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w' )
+ {
+ int coordID = params_get_coordID(&parse_arg, coord, params[varID].gridID);
+ int gridID = parse_arg.coords[coordID].cdiID;
+ size_t ngp = parse_arg.coords[coordID].size;
+ double *data = parse_arg.coords[coordID].data;
+ assert(gridID==params[varID].gridID);
+ assert(data!=NULL);
+
+ memcpy(params[varID].data, data, ngp*sizeof(double));
+ }
+ else if ( coord == 'z' )
+ {
+ int coordID = params_get_coordID(&parse_arg, coord, params[varID].zaxisID);
+ int zaxisID = parse_arg.coords[coordID].cdiID;
+ size_t nlev = parse_arg.coords[coordID].size;
+ double *data = parse_arg.coords[coordID].data;
+ assert(zaxisID==params[varID].zaxisID);
+ assert(data!=NULL);
+
+ memcpy(params[varID].data, data, nlev*sizeof(double));
+ }
+ else
+ cdoAbort("Computation of coordinate %c not implemented!", coord);
+
+ free(varname);
+ }
}
+
+ if ( cdoVerbose ) vlistPrint(vlistID2);
+
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = taxisDuplicate(taxisID1);
+ vlistDefTaxis(vlistID2, taxisID2);
- gridsize = vlistGridsizeMax(vlistID1);
- array = (double*) Malloc(gridsize*sizeof(double));
+ int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
- tsID = 0;
+ streamDefVlist(streamID2, vlistID2);
+
+ int nrecs;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
+ params[vartsID].data[0] = tsID+1;
taxisCopyTimestep(taxisID2, taxisID1);
streamDefTimestep(streamID2, tsID);
-
- for ( varID = 0; varID < nvars; varID++ ) parse_arg.nmiss[varID] = 0;
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int varID = 0; varID < nvars1; varID++ ) params[varID].nmiss = 0;
+
+ for ( int recID = 0; recID < nrecs; recID++ )
{
+ int varID, levelID;
streamInqRecord(streamID1, &varID, &levelID);
- if ( parse_arg.var_needed[varID] )
+ if ( parse_arg.needed[varID] )
{
- gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
- offset = gridsize*levelID;
- single1 = parse_arg.vardata1[varID] + offset;
- streamReadRecord(streamID1, single1, &nmiss);
- parse_arg.nmiss[varID] += nmiss;
- /*
- if ( nmiss && lwarn )
- {
- cdoWarning("Missing values unsupported for this operator!");
- lwarn = FALSE;
- }
- */
+ size_t offset = params[varID].ngp*levelID;
+ double *vardata = params[varID].data + offset;
+ int nmiss;
+ streamReadRecord(streamID1, vardata, &nmiss);
+ params[varID].nmiss += nmiss;
}
}
- for ( varID = nvars; varID < nvars2; varID++ )
+ for ( int varID = 0; varID < nvars2; varID++ )
{
- gridID = vlistInqVarGrid(vlistID2, varID);
- zaxisID = vlistInqVarZaxis(vlistID2, varID);
- gridsize = gridInqSize(gridID);
- nlevel = zaxisInqSize(zaxisID);
+ int pidx = varIDmap[varID];
+ if ( pidx < nvars1 ) continue;
+ size_t ngp = params[pidx].ngp;
+ size_t nlev = params[pidx].nlev;
- memset(parse_arg.vardata2[varID], 0, gridsize*nlevel*sizeof(double));
+ params[pidx].nmiss = 0;
+ memset(params[pidx].data, 0, ngp*nlev*sizeof(double));
}
yy_scan_string(exprs, scanner);
yyparse(&parse_arg, scanner);
- for ( varID = 0; varID < nvars2; varID++ )
+ for ( int varID = 0; varID < nvars2; varID++ )
{
- gridID = vlistInqVarGrid(vlistID2, varID);
- zaxisID = vlistInqVarZaxis(vlistID2, varID);
- missval = vlistInqVarMissval(vlistID2, varID);
+ int pidx = varIDmap[varID];
- gridsize = gridInqSize(gridID);
- nlevel = zaxisInqSize(zaxisID);
- for ( levelID = 0; levelID < nlevel; levelID++ )
+ if ( tsID > 0 && params[pidx].steptype == TIME_CONSTANT ) continue;
+
+ double missval = vlistInqVarMissval(vlistID2, varID);
+
+ size_t ngp = params[pidx].ngp;
+ int nlev = (int) params[pidx].nlev;
+ for ( int levelID = 0; levelID < nlev; levelID++ )
{
- long i;
- offset = gridsize*levelID;
- single2 = parse_arg.vardata2[varID] + offset;
+ size_t offset = ngp*levelID;
+ double *vardata = params[pidx].data + offset;
- nmiss = 0;
- for ( i = 0; i < gridsize; i++ )
- if ( DBL_IS_EQUAL(single2[i], missval) ) nmiss++;
+ int nmiss = 0;
+ for ( size_t i = 0; i < ngp; i++ )
+ if ( DBL_IS_EQUAL(vardata[i], missval) ) nmiss++;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, single2, nmiss);
+ streamWriteRecord(streamID2, vardata, nmiss);
}
}
@@ -287,9 +557,23 @@ void *Expr(void *argument)
yylex_destroy(scanner);
- if ( array ) Free(array);
if ( exprs ) Free(exprs);
+ params_delete(params);
+
+ if ( parse_arg.needed ) Free(parse_arg.needed);
+ if ( parse_arg.coords )
+ {
+ for ( int i = 0; i < parse_arg.ncoords; i++ )
+ {
+ if ( parse_arg.coords[i].data ) Free(parse_arg.coords[i].data);
+ if ( parse_arg.coords[i].units ) Free(parse_arg.coords[i].units);
+ if ( parse_arg.coords[i].longname ) Free(parse_arg.coords[i].longname);
+ }
+ Free(parse_arg.coords);
+ }
+ if ( varIDmap ) Free(varIDmap);
+
cdoFinish();
return 0;
diff --git a/src/FC.c b/src/FC.c
index f764a4a..ffd30ce 100644
--- a/src/FC.c
+++ b/src/FC.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Filedes.c b/src/Filedes.c
index d081aaa..393570b 100644
--- a/src/Filedes.c
+++ b/src/Filedes.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -81,20 +81,46 @@ void printAtts(FILE *fp, int vlistID, int varID)
}
static
-void partab(FILE *fp, int vlistID, int option)
+void printHistory(FILE *fp, int streamID)
{
+ int fileID = pstreamFileID(streamID);
+ size_t historysize = (size_t) streamInqHistorySize(fileID);
+ if ( historysize > 0 )
+ {
+ char *history = (char*) Malloc(historysize+1);
+ history[historysize] = 0;
+ streamInqHistoryString(fileID, history);
+ fprintf(fp, " history=%s\n", history);
+ }
+}
+
+static
+void printSource(FILE *fp, int vlistID, int varID)
+{
+ /* institute info */
+ const char *instptr = institutInqLongnamePtr(vlistInqVarInstitut(vlistID, varID));
+ if ( instptr ) fprintf(fp, " institution=%s\n", instptr);
+
+ /* source info */
+ const char *modelptr = modelInqNamePtr(vlistInqVarModel(vlistID, varID));
+ if ( modelptr ) fprintf(fp, " source=%s\n", modelptr);
+}
+
+static
+void partab(FILE *fp, int streamID, int option)
+{
+ int vlistID = streamInqVlist(streamID);
int varID, datatype = -1;
int param;
char pstr[32];
char paramstr[32];
char varname[CDI_MAX_NAME], varlongname[CDI_MAX_NAME], varstdname[CDI_MAX_NAME], varunits[CDI_MAX_NAME];
int natts;
- int nvars;
int chunktype;
int linebreak = 1;
double missval;
- nvars = vlistNvars(vlistID);
+ int nvars = vlistNvars(vlistID);
if ( option == 4 ) linebreak = 0;
if ( option == 2 )
@@ -104,6 +130,8 @@ void partab(FILE *fp, int vlistID, int option)
{
fprintf(fp, "¶meter\n");
fprintf(fp, " name=_GLOBAL_\n");
+ printHistory(fp, streamID);
+ printSource(fp, vlistID, 0);
printAtts(fp, vlistID, CDI_GLOBAL);
fprintf(fp, "/\n");
}
@@ -229,16 +257,16 @@ void filedes(int streamID)
printf(" GRIB2 data\n");
break;
case FILETYPE_NC:
- printf(" netCDF data\n");
+ printf(" NetCDF data\n");
break;
case FILETYPE_NC2:
- printf(" netCDF2 data\n");
+ printf(" NetCDF2 data\n");
break;
case FILETYPE_NC4:
- printf(" netCDF4 data\n");
+ printf(" NetCDF4 data\n");
break;
case FILETYPE_NC4C:
- printf(" netCDF4 classic data\n");
+ printf(" NetCDF4 classic data\n");
break;
case FILETYPE_SRV:
printf(" SERVICE data\n");
@@ -410,11 +438,10 @@ void *Filedes(void *argument)
else if ( operatorID == PARTAB || operatorID == SPARTAB || operatorID == PARTAB2 )
{
int option = 1;
-
if ( operatorID == SPARTAB ) option = 4;
if ( operatorID == PARTAB2 ) option = 2;
- partab(stdout, vlistID, option);
+ partab(stdout, streamID, option);
}
else if ( operatorID == FILEDES )
{
diff --git a/src/Fillmiss.c b/src/Fillmiss.c
index d6ff705..5f1079c 100644
--- a/src/Fillmiss.c
+++ b/src/Fillmiss.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -409,6 +409,7 @@ void setmisstodis(field_t *field1, field_t *field2, int num_neighbors)
void *Fillmiss(void *argument)
{
+ int nmiss;
int nrecs, recID, varID, levelID;
void (*fill_method) (field_t *fin , field_t *fout , int) = NULL;
@@ -488,7 +489,8 @@ void *Fillmiss(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
streamDefRecord(streamID2, varID, levelID);
diff --git a/src/Filter.c b/src/Filter.c
index c65ca9f..9fb56a4 100644
--- a/src/Filter.c
+++ b/src/Filter.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Fldrms.c b/src/Fldrms.c
index 6a258c5..982c249 100644
--- a/src/Fldrms.c
+++ b/src/Fldrms.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -37,6 +37,7 @@ void *Fldrms(void *argument)
int recID, nrecs;
int tsID, varID, levelID;
int lim;
+ int nmiss;
int ndiffgrids;
int needWeights = FALSE;
double slon, slat;
@@ -122,9 +123,11 @@ void *Fldrms(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
streamInqRecord(streamID2, &varID, &levelID);
- streamReadRecord(streamID2, field2.ptr, &field2.nmiss);
+ streamReadRecord(streamID2, field2.ptr, &nmiss);
+ field2.nmiss = (size_t) nmiss;
field1.grid = vlistInqVarGrid(vlistID1, varID);
field2.grid = vlistInqVarGrid(vlistID2, varID);
@@ -152,7 +155,7 @@ void *Fldrms(void *argument)
fldrms(field1, field2, &field3);
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, &sglval, field3.nmiss);
+ streamWriteRecord(streamID3, &sglval, (int)field3.nmiss);
}
tsID++;
}
diff --git a/src/Fldstat.c b/src/Fldstat.c
index 73f0659..69bc186 100644
--- a/src/Fldstat.c
+++ b/src/Fldstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Fldstat fldmean Field mean
Fldstat fldavg Field average
Fldstat fldstd Field standard deviation
- Fldstat fldstd1 Field standard deviation [Divisor is (n-1)]
+ Fldstat fldstd1 Field standard deviation [Normalize by (n-1)]
Fldstat fldvar Field variance
- Fldstat fldvar1 Field variance [Divisor is (n-1)]
+ Fldstat fldvar1 Field variance [Normalize by (n-1)]
Fldstat fldpctl Field percentiles
*/
@@ -210,9 +210,10 @@ void *Fldstat(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
- field.grid = vlistInqVarGrid(vlistID1, varID);
+ field.nmiss = (size_t)nmiss;
+ field.grid = vlistInqVarGrid(vlistID1, varID);
field.size = gridInqSize(field.grid);
if ( needWeights && field.grid != lastgrid )
@@ -222,7 +223,7 @@ void *Fldstat(void *argument)
if ( useweights && field.size > 1 )
{
int wstatus = gridWeights(field.grid, field.weight);
- if ( wstatus != 0 && tsID == 0 && levelID == 0 )
+ if ( wstatus && tsID == 0 && levelID == 0 )
{
char varname[CDI_MAX_NAME];
vlistInqVarName(vlistID1, varID, varname);
diff --git a/src/Fldstat2.c b/src/Fldstat2.c
index 049015e..b644138 100644
--- a/src/Fldstat2.c
+++ b/src/Fldstat2.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -56,8 +56,8 @@ double correlation_s(const double * restrict in0, const double * restrict in1,
}
out = IS_NOT_EQUAL(wsum0, 0) ?
- DIV((sum01 * wsum0 - sum0 * sum1),
- SQRT((sum00 * wsum0 - sum0 * sum0) *
+ DIVMN((sum01 * wsum0 - sum0 * sum1),
+ SQRTMN((sum00 * wsum0 - sum0 * sum0) *
(sum11 * wsum0 - sum1 * sum1))) : missval1;
return (out);
diff --git a/src/Fourier.c b/src/Fourier.c
index cea048c..c160373 100644
--- a/src/Fourier.c
+++ b/src/Fourier.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -212,5 +212,5 @@ void *Fourier(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Gengrid.c b/src/Gengrid.c
index e91478e..31cc633 100644
--- a/src/Gengrid.c
+++ b/src/Gengrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Gradsdes.c b/src/Gradsdes.c
index 2c2b06a..e498e67 100644
--- a/src/Gradsdes.c
+++ b/src/Gradsdes.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -680,27 +680,24 @@ void ctl_options(FILE *gdp, int yrev, int zrev, int sequential, int bigendian, i
static
void ctl_undef(FILE *gdp, int vlistID)
{
- double missval;
-
- missval = vlistInqVarMissval(vlistID, 0);
+ double missval = vlistInqVarMissval(vlistID, 0);
fprintf(gdp, "UNDEF %g\n", missval);
}
static
void ctl_vars(FILE *gdp, int filetype, int vlistID, int nvarsout, int *vars)
{
- int varID, nvars;
int ltype, code;
int zaxisID, nlev;
int i, j;
int len;
char varname[CDI_MAX_NAME], varlongname[CDI_MAX_NAME], varunits[CDI_MAX_NAME];
- nvars = vlistNvars(vlistID);
+ int nvars = vlistNvars(vlistID);
fprintf(gdp, "VARS %d\n", nvarsout);
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = 0; varID < nvars; varID++ )
{
if ( vars[varID] == TRUE )
{
@@ -1043,7 +1040,7 @@ void *Gradsdes(void *argument)
filetype != FILETYPE_GRB )
{
if ( filetype == FILETYPE_NC )
- // cdoAbort("Unsupported file format: netCDF");
+ // cdoAbort("Unsupported file format: NetCDF");
;
else if ( filetype == FILETYPE_GRB2 )
//cdoAbort("Unsupported file format: GRIB2");
@@ -1193,7 +1190,7 @@ void *Gradsdes(void *argument)
}
else if ( filetype == FILETYPE_NC )
{
- fprintf(gdp, "DTYPE netCDF\n");
+ fprintf(gdp, "DTYPE NetCDF\n");
}
/* XYHEADER */
diff --git a/src/Gridboxstat.c b/src/Gridboxstat.c
index 248d2bf..76b84d0 100644
--- a/src/Gridboxstat.c
+++ b/src/Gridboxstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Gridboxstat gridboxmean Gridbox mean
Gridboxstat gridboxavg Gridbox average
Gridboxstat gridboxstd Gridbox standard deviation
- Gridboxstat gridboxstd1 Gridbox standard deviation [Divisor is (n-1)]
+ Gridboxstat gridboxstd1 Gridbox standard deviation [Normalize by (n-1)]
Gridboxstat gridboxvar Gridbox variance
- Gridboxstat gridboxvar1 Gridbox variance [Divisor is (n-1)]
+ Gridboxstat gridboxvar1 Gridbox variance [Normalize by (n-1)]
*/
@@ -557,6 +557,7 @@ void gridboxstat(field_t *field1, field_t *field2, int xinc, int yinc, int statf
void *Gridboxstat(void *argument)
{
+ int nmiss;
int lastgrid = -1;
int wstatus = FALSE;
int index;
@@ -638,7 +639,8 @@ void *Gridboxstat(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
field1.grid = vlistInqVarGrid(vlistID1, varID);
field1.size = gridInqSize(field1.grid);
@@ -662,7 +664,7 @@ void *Gridboxstat(void *argument)
gridboxstat(&field1, &field2, xinc, yinc, operfunc);
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, field2.ptr, field2.nmiss);
+ streamWriteRecord(streamID2, field2.ptr, (int)field2.nmiss);
}
tsID++;
}
diff --git a/src/Gridcell.c b/src/Gridcell.c
index c0d4ec7..666f3eb 100644
--- a/src/Gridcell.c
+++ b/src/Gridcell.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -38,6 +38,44 @@ double orthodrome(double px1, double py1, double px2, double py2)
}
+void grid_cell_area(int gridID, double *array)
+{
+ int gridtype = gridInqType(gridID);
+ if ( gridtype == GRID_LONLAT ||
+ gridtype == GRID_GAUSSIAN ||
+ gridtype == GRID_LCC ||
+ gridtype == GRID_GME ||
+ gridtype == GRID_CURVILINEAR ||
+ gridtype == GRID_UNSTRUCTURED )
+ {
+ if ( gridHasArea(gridID) )
+ {
+ if ( cdoVerbose ) cdoPrint("Using existing grid cell area!");
+ gridInqArea(gridID, array);
+ }
+ else
+ {
+ int status = gridGenArea(gridID, array);
+ if ( status == 1 )
+ cdoAbort("%s: Grid corner missing!", __func__);
+ else if ( status == 2 )
+ cdoAbort("%s: Can't compute grid cell area for this grid!", __func__);
+
+ int ngp = gridInqSize(gridID);
+ for ( int i = 0; i < ngp; ++i )
+ array[i] *= PlanetRadius*PlanetRadius;
+ }
+ }
+ else
+ {
+ if ( gridtype == GRID_GAUSSIAN_REDUCED )
+ cdoAbort("Unsupported grid type: %s, use CDO option -R to convert reduced to regular grid!",
+ gridNamePtr(gridtype));
+ else
+ cdoAbort("%s: Unsupported grid type: %s", __func__, gridNamePtr(gridtype));
+ }
+}
+
void *Gridcell(void *argument)
{
int GRIDAREA, GRIDWGTS, GRIDMASK, GRIDDX, GRIDDY;
@@ -135,39 +173,7 @@ void *Gridcell(void *argument)
if ( operatorID == GRIDAREA )
{
- gridtype = gridInqType(gridID);
- if ( gridtype == GRID_LONLAT ||
- gridtype == GRID_GAUSSIAN ||
- gridtype == GRID_LCC ||
- gridtype == GRID_GME ||
- gridtype == GRID_CURVILINEAR ||
- gridtype == GRID_UNSTRUCTURED )
- {
- if ( gridHasArea(gridID) )
- {
- if ( cdoVerbose ) cdoPrint("Using existing grid cell area!");
- gridInqArea(gridID, array);
- }
- else
- {
- status = gridGenArea(gridID, array);
- if ( status == 1 )
- cdoAbort("Grid corner missing!");
- else if ( status == 2 )
- cdoAbort("Can't compute grid cell areas for this grid!");
-
- for ( i = 0; i < gridsize; ++i )
- array[i] *= PlanetRadius*PlanetRadius;
- }
- }
- else
- {
- if ( gridtype == GRID_GAUSSIAN_REDUCED )
- cdoAbort("Unsupported grid type: %s, use CDO option -R to convert reduced to regular grid!",
- gridNamePtr(gridtype));
- else
- cdoAbort("Unsupported grid type: %s", gridNamePtr(gridtype));
- }
+ grid_cell_area(gridID, array);
}
else if ( operatorID == GRIDWGTS )
{
diff --git a/src/Gridsearch.c b/src/Gridsearch.c
index 9be79af..4993765 100644
--- a/src/Gridsearch.c
+++ b/src/Gridsearch.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Harmonic.c b/src/Harmonic.c
index af39598..ba3db04 100644
--- a/src/Harmonic.c
+++ b/src/Harmonic.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Hi.c b/src/Hi.c
index f2d515a..1a93ce0 100755
--- a/src/Hi.c
+++ b/src/Hi.c
@@ -91,6 +91,7 @@ void *Hi(void *argument)
{
int streamID1, streamID2, streamID3, streamID4;
int gridsize;
+ int nmiss;
int nrecs, nrecs2, nrecs3, recID;
int tsID;
int gridID, zaxisID;
@@ -165,13 +166,16 @@ void *Hi(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID1, &levelID1);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
-
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
+
streamInqRecord(streamID2, &varID2, &levelID2);
- streamReadRecord(streamID2, field2.ptr, &field2.nmiss);
+ streamReadRecord(streamID2, field2.ptr, &nmiss);
+ field2.nmiss = (size_t) nmiss;
streamInqRecord(streamID3, &varID3, &levelID3);
- streamReadRecord(streamID3, field3.ptr, &field3.nmiss);
+ streamReadRecord(streamID3, field3.ptr, &nmiss);
+ field3.nmiss = (size_t) nmiss;
if ( varID1 != varID2 || varID1 != varID3 || levelID1 != levelID2 || levelID1 != levelID3 )
cdoAbort("Input streams have different structure!");
@@ -190,7 +194,7 @@ void *Hi(void *argument)
farexpr(&field1, field2, field3, humidityIndex);
streamDefRecord(streamID4, varID4, levelID1);
- streamWriteRecord(streamID4, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID4, field1.ptr, (int)field1.nmiss);
}
tsID++;
diff --git a/src/Histogram.c b/src/Histogram.c
index 5f1eb95..1805dc1 100644
--- a/src/Histogram.c
+++ b/src/Histogram.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Importamsr.c b/src/Importamsr.c
index 95bf82c..9217c6e 100644
--- a/src/Importamsr.c
+++ b/src/Importamsr.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Importbinary.c b/src/Importbinary.c
index 49e292b..91dc656 100644
--- a/src/Importbinary.c
+++ b/src/Importbinary.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Importcmsaf.c b/src/Importcmsaf.c
index e577cf2..8fa2b00 100644
--- a/src/Importcmsaf.c
+++ b/src/Importcmsaf.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Importobs.c b/src/Importobs.c
index 61fdf3c..fd38bec 100644
--- a/src/Importobs.c
+++ b/src/Importobs.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Info.c b/src/Info.c
index f9ffdb8..3c284f6 100644
--- a/src/Info.c
+++ b/src/Info.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Input.c b/src/Input.c
index 64a6a04..ca6de8a 100644
--- a/src/Input.c
+++ b/src/Input.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intgrid.c b/src/Intgrid.c
index 7dc4493..2f82010 100644
--- a/src/Intgrid.c
+++ b/src/Intgrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intgridtraj.c b/src/Intgridtraj.c
index 0765c6c..9cd9823 100644
--- a/src/Intgridtraj.c
+++ b/src/Intgridtraj.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intlevel.c b/src/Intlevel.c
index ef3a61c..2009e9f 100644
--- a/src/Intlevel.c
+++ b/src/Intlevel.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intlevel3d.c b/src/Intlevel3d.c
index 9d1dc1b..73033a6 100644
--- a/src/Intlevel3d.c
+++ b/src/Intlevel3d.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intntime.c b/src/Intntime.c
index e36383a..a28e400 100644
--- a/src/Intntime.c
+++ b/src/Intntime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Inttime.c b/src/Inttime.c
index d61dfb9..fc9b8ea 100644
--- a/src/Inttime.c
+++ b/src/Inttime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Intyear.c b/src/Intyear.c
index 2e4c4d1..bbf83e6 100644
--- a/src/Intyear.c
+++ b/src/Intyear.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Invert.c b/src/Invert.c
index 2d519ad..fdad71c 100644
--- a/src/Invert.c
+++ b/src/Invert.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -135,21 +135,13 @@ void invertLonDes(int vlistID)
static
void invertLatDes(int vlistID)
{
- int index, ngrids;
- int gridID1, gridID2;
- int nlat, nlon, size;
- int ilat, ilon;
- int gridtype, nv, iv;
- double *yv1, *yv2;
- double *yb1, *yb2;
-
- ngrids = vlistNgrids(vlistID);
- for ( index = 0; index < ngrids; index++ )
+ int ngrids = vlistNgrids(vlistID);
+ for ( int index = 0; index < ngrids; index++ )
{
- gridID1 = vlistGrid(vlistID, index);
- gridID2 = gridDuplicate(gridID1);
+ int gridID1 = vlistGrid(vlistID, index);
+ int gridID2 = gridDuplicate(gridID1);
- gridtype = gridInqType(gridID1);
+ int gridtype = gridInqType(gridID1);
if ( gridtype != GRID_GENERIC && gridtype != GRID_GAUSSIAN &&
gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR )
@@ -157,32 +149,30 @@ void invertLatDes(int vlistID)
if ( gridInqYvals(gridID1, NULL) )
{
- nlon = gridInqXsize(gridID1);
- nlat = gridInqYsize(gridID1);
+ int nlon = gridInqXsize(gridID1);
+ int nlat = gridInqYsize(gridID1);
- if ( gridtype == GRID_CURVILINEAR )
- size = nlon*nlat;
- else
- size = nlat;
+ int size = nlat;
+ if ( gridtype == GRID_CURVILINEAR ) size = nlon*nlat;
- yv1 = (double*) Malloc(size*sizeof(double));
- yv2 = (double*) Malloc(size*sizeof(double));
+ double *yv1 = (double*) Malloc(size*sizeof(double));
+ double *yv2 = (double*) Malloc(size*sizeof(double));
if ( gridtype == GRID_CURVILINEAR )
{
gridInqXvals(gridID1, yv1);
- for ( ilat = 0; ilat < nlat; ilat++ )
- for ( ilon = 0; ilon < nlon; ilon++ )
+ for ( int ilat = 0; ilat < nlat; ilat++ )
+ for ( int ilon = 0; ilon < nlon; ilon++ )
yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
gridDefXvals(gridID2, yv2);
gridInqYvals(gridID1, yv1);
- for ( ilat = 0; ilat < nlat; ilat++ )
- for ( ilon = 0; ilon < nlon; ilon++ )
+ for ( int ilat = 0; ilat < nlat; ilat++ )
+ for ( int ilon = 0; ilon < nlon; ilon++ )
yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
gridDefYvals(gridID2, yv2);
@@ -191,7 +181,7 @@ void invertLatDes(int vlistID)
{
gridInqYvals(gridID1, yv1);
- for ( ilat = 0; ilat < nlat; ilat++ )
+ for ( int ilat = 0; ilat < nlat; ilat++ )
yv2[nlat-ilat-1] = yv1[ilat];
gridDefYvals(gridID2, yv2);
@@ -203,31 +193,29 @@ void invertLatDes(int vlistID)
if ( gridInqYbounds(gridID1, NULL) )
{
- nlon = gridInqXsize(gridID1);
- nlat = gridInqYsize(gridID1);
+ int nlon = gridInqXsize(gridID1);
+ int nlat = gridInqYsize(gridID1);
- nv = gridInqNvertex(gridID1);
+ int nv = gridInqNvertex(gridID1);
- if ( gridtype == GRID_CURVILINEAR )
- size = nv*nlon*nlat;
- else
- size = nv*nlat;
+ int size = nlat;
+ if ( gridtype == GRID_CURVILINEAR ) size = nlon*nlat;
- yb1 = (double*) Malloc(size*sizeof(double));
- yb2 = (double*) Malloc(size*sizeof(double));
+ double *yb1 = (double*) Malloc(size*sizeof(double));
+ double *yb2 = (double*) Malloc(size*sizeof(double));
gridInqYbounds(gridID1, yb1);
if ( gridtype == GRID_CURVILINEAR )
{
- for ( ilat = 0; ilat < nlat; ilat++ )
- for ( ilon = 0; ilon < nlon; ilon++ )
- for ( iv = 0; iv < nv; iv++ )
+ for ( int ilat = 0; ilat < nlat; ilat++ )
+ for ( int ilon = 0; ilon < nlon; ilon++ )
+ for ( int iv = 0; iv < nv; iv++ )
yb2[(nlat-ilat-1)*nlon*nv + ilon*nv + iv] = yb1[ilat*nlon*nv + ilon*nv + iv];
}
else
{
- for ( ilat = 0; ilat < nlat; ilat++ )
+ for ( int ilat = 0; ilat < nlat; ilat++ )
{
yb2[nlat*2-ilat*2-1] = yb1[ilat*2];
yb2[nlat*2-ilat*2-2] = yb1[ilat*2+1];
diff --git a/src/Invertlev.c b/src/Invertlev.c
index a1fcb18..8183c61 100644
--- a/src/Invertlev.c
+++ b/src/Invertlev.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Isosurface.c b/src/Isosurface.c
index 777a7e9..0181d01 100644
--- a/src/Isosurface.c
+++ b/src/Isosurface.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Kvl.c b/src/Kvl.c
index 0e05ff0..f8bb495 100644
--- a/src/Kvl.c
+++ b/src/Kvl.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Log.c b/src/Log.c
index 83933ca..27a180b 100644
--- a/src/Log.c
+++ b/src/Log.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Maggraph.c b/src/Maggraph.c
index e801d44..4effca3 100644
--- a/src/Maggraph.c
+++ b/src/Maggraph.c
@@ -2,8 +2,7 @@
# include "config.h" /* HAVE_LIBMAGICS */
#endif
-#include<limits.h> /* TEMPORARY FIX, UNTIL NEXT MAGICS LIBRARY RELEASE */
-
+#include <limits.h>
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
@@ -11,28 +10,16 @@
#include "pstream.h"
#if defined(HAVE_LIBMAGICS)
-#include "magics_api.h"
-#endif
+#include "magics_api.h"
-#if defined(HAVE_LIBXML2)
-
-#include<libxml/parser.h>
-#include<libxml/tree.h>
-#include "template_parser.h"
#include "magics_template_parser.h"
#include "results_template_parser.h"
-#include <ctype.h>
-
-
-extern xmlNode *magics_node;
-
-#endif
+#include "StringUtilities.h"
#define DBG 0
-
-char *line_colours[] = { "red", "green", "blue", "yellow", "cyan", "magenta",
+const char *line_colours[] = {"red", "green", "blue", "yellow", "cyan", "magenta",
"avocado","beige", "brick", "brown", "burgundy",
"charcoal", "chestnut", "coral", "cream",
"evergreen", "gold",
@@ -52,18 +39,14 @@ char *line_colours[] = { "red", "green", "blue", "yellow", "cyan", "magenta"
"bluishpurple", "purple",
};
-char *graph_params[] = {"ymin","ymax","sigma","stat","obsv","device"};
+const char *graph_params[] = {"ymin","ymax","sigma","stat","obsv","device"};
int graph_param_count = sizeof(graph_params)/sizeof(char*);
int num_colours = sizeof( line_colours )/sizeof( char* );
-void VerifyGraphParameters( int num_param, char **param_names );
-int compareDateOrTimeStr( char *datetimestr1, char *datetimestr2, char *sep_char );
+int compareDateOrTimeStr( char *datetimestr1, char *datetimestr2, const char *sep_char );
-extern int checkdevice();
-extern int IsNumeric();
-extern void StrToUpperCase();
-extern int StringSplitWithSeperator();
+extern int checkdevice(char *device_in);
extern char *DEVICE;
extern char *DEVICE_TABLE;
@@ -73,14 +56,13 @@ extern int DEVICE_COUNT;
static
void maggraph(const char *plotfile, const char *varname,const char *varunits, long nfiles, long *nts, int **vdate, int **vtime, double **datatab, int nparam, char **params)
{
-
char *lines[1];
char *temp_str;
char **split_str = NULL;
- char *sep_char = "=";
+ const char *sep_char = "=";
char **date_time_str[nfiles];
char min_date_time_str[1024], max_date_time_str[1024];
- int min_index, max_index;
+ int min_index = 0, max_index = 0;
char vdatestr[32], vtimestr[32], legend_text_data[256];
char vdatestr1[32], vtimestr1[32];
char vdatestr2[32], vtimestr2[32];
@@ -91,11 +73,11 @@ void maggraph(const char *plotfile, const char *varname,const char *varunits, lo
int count ;
int num_years = 0, num_months = 0, num_days = 0;
int ret;
- long tsID, fileID, i, ntime_steps;
- double *date_time;
+ long tsID, fileID, i, ntime_steps = 0;
+ double *date_time = NULL;
double min_val = 1.0e+200, max_val = -1.0e+200;
- double *mean_val, *std_dev_val;
- double *spread_min, *spread_max;
+ double *mean_val = NULL, *std_dev_val = NULL;
+ double *spread_min = NULL, *spread_max = NULL;
double y_min_val = 1.0e+200, y_max_val = -1.0e+200;
if( DBG )
@@ -458,6 +440,7 @@ void maggraph(const char *plotfile, const char *varname,const char *varunits, lo
split_str_count = 0;
sep_char = "-";
split_str_count = StringSplitWithSeperator( max_date_time_str, sep_char, &split_str );
+ (void)split_str_count;
num_years = atoi( split_str[0] );
num_months = atoi( split_str[1] );
num_days = atoi( split_str[2] );
@@ -487,10 +470,7 @@ void maggraph(const char *plotfile, const char *varname,const char *varunits, lo
1. Loop over the Files
2. Loop over the number of time steps
3. Set the attributes for the magics data and plot
- */
-
-#if defined(HAVE_LIBMAGICS)
-
+ */
/* magics_template_parser( magics_node ); */
@@ -701,14 +681,10 @@ void maggraph(const char *plotfile, const char *varname,const char *varunits, lo
if( DBG )
fprintf(stderr, "%s\n",lines[0]);
-
-#endif
-
}
-int compareDateOrTimeStr( char *datetimestr1, char *datetimestr2, char *sep_char )
+int compareDateOrTimeStr( char *datetimestr1, char *datetimestr2, const char *sep_char )
{
-
int split_str_count1, split_str_count2;
int i,flag[3]; /* '3' since, three fields are expected in the input strings */
char **split_str1 = NULL;
@@ -754,12 +730,8 @@ int compareDateOrTimeStr( char *datetimestr1, char *datetimestr2, char *sep_char
return 0;
}
-
-#if defined(HAVE_LIBMAGICS)
-
static
void init_MAGICS( )
-
{
setenv( "MAGPLUS_QUIET","1",1 ); /* To suppress magics messages */
mag_open();
@@ -770,53 +742,156 @@ void init_MAGICS( )
}
-
static
void quit_MAGICS( )
-
{
-
mag_close ();
if( DBG )
fprintf( stdout,"Exiting From MAGICS\n" );
}
+static
+void VerifyGraphParameters( int num_param, char **param_names )
+{
+ int i, j;
+ int found = FALSE, syntax = TRUE, halt_flag = FALSE, split_str_count;
+ char **split_str = NULL;
+ const char *sep_char = "=";
+ char *temp_str;
+
+ for ( i = 0; i < num_param; ++i )
+ {
+ split_str_count = 0;
+ found = FALSE;
+ syntax = TRUE;
+ split_str_count = StringSplitWithSeperator( param_names[i], sep_char, &split_str );
+ if( split_str_count > 1 )
+ {
+ for ( j = 0; j < graph_param_count; ++j )
+ {
+ if( !strcmp( split_str[0], graph_params[j] ) )
+ {
+ found = TRUE;
+ if( !strcmp( split_str[0],"obsv" ) || !strcmp( split_str[0],"stat" ) )
+ {
+ if( IsNumeric( split_str[1] ) )
+ syntax = FALSE;
+ else
+ {
+ temp_str = strdup( split_str[1] );
+ StrToUpperCase( temp_str );
+ if( strcmp( temp_str,"TRUE" ) && strcmp( temp_str,"FALSE" ) )
+ syntax = FALSE;
+ }
+ }
+
+ if( !strcmp( split_str[0],"ymin" ) || !strcmp( split_str[0],"ymax" ) || !strcmp( split_str[0],"sigma" ) )
+ {
+ if( !IsNumeric( split_str[1] ) )
+ syntax = FALSE;
+ }
+
+
+ if( !strcmp( split_str[0],"device" ) )
+ {
+ if( IsNumeric( split_str[1] ) )
+ syntax = FALSE;
+ else
+ {
+ if( !strcmp( split_str[0],"device" ) )
+ {
+ if( DBG )
+ fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
+ if( checkdevice( split_str[1] ) )
+ syntax = FALSE;
+
+ /* Graph not supported in google earth format */
+ if( !strcmp( split_str[1],"GIF_ANIMATION" ) || !strcmp( split_str[1],"gif_animation" ))
+ {
+ syntax = FALSE;
+ fprintf( stderr,"Animation not supported for Graph!\n");
+ if( DBG )
+ fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
+ }
+ if( !strcmp( split_str[1],"KML" ) || !strcmp( split_str[1],"kml" ) )
+ {
+ syntax = FALSE;
+ fprintf( stderr," 'kml' format not supported for Graph!\n");
+ if( DBG )
+ fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
+ }
+ }
+ }
+ }
+
+/*
+ if( !strcmp( split_str[0],"xml" ) )
+ {
+ if( ( fp = fopen( split_str[1],"r") ) == NULL )
+ {
+ fprintf( stderr,"Input XML File not found in specified path '%s'\n", split_str[1] );
+ halt_flag = TRUE;
+ }
+ else
+ {
+ // HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR
+ fclose(fp);
+ init_XMLtemplate_parser( split_str[1] );
+ updatemagics_and_results_nodes( );
+ }
+ }
+*/
+ }
+ }
+ }
+ else
+ {
+ syntax = FALSE;
+ }
+
+ if( found == FALSE )
+ {
+ halt_flag = TRUE;
+ fprintf( stderr,"Unknown parameter '%s'!\n", param_names[i] );
+ }
+ if( found == TRUE && syntax == FALSE )
+ {
+ halt_flag = TRUE;
+ fprintf( stderr,"Invalid parameter specification '%s'!\n", param_names[i] );
+ }
+ Free( split_str );
+ }
+
+ if( halt_flag == TRUE )
+ {
+ exit(0);
+ }
+}
#endif
#define NINC_ALLOC 1024
void *Maggraph(void *argument)
{
- const char *ofilename;
+ cdoInitialize(argument);
+
+#if defined(HAVE_LIBMAGICS)
char varname[CDI_MAX_NAME], units[CDI_MAX_NAME];
- char **pnames = NULL;
int varID, levelID;
int gridID;
int nrecs;
- int tsID;
- int streamID;
- int vlistID, vlistID0 = -1;
+ int vlistID0 = -1;
int nmiss;
- int taxisID;
- int **vdate = NULL, **vtime = NULL;
- int fileID, nfiles;
- long *nts, nts_alloc;
- int nparam = 0;
- double **datatab = NULL;
- double val;
- int i;
+ long nts_alloc;
- cdoInitialize(argument);
-
- nparam = operatorArgc();
- pnames = operatorArgv();
+ int nparam = operatorArgc();
+ char **pnames = operatorArgv();
- if( nparam )
- VerifyGraphParameters(nparam,pnames);
+ if ( nparam ) VerifyGraphParameters(nparam,pnames);
- nfiles = cdoStreamCnt() - 1;
- ofilename = cdoStreamName(nfiles)->args;
+ int nfiles = cdoStreamCnt() - 1;
+ const char *ofilename = cdoStreamName(nfiles)->args;
if( DBG )
{
@@ -824,12 +899,12 @@ void *Maggraph(void *argument)
fprintf( stderr," files %s\n",ofilename );
}
- datatab = (double **) Malloc(nfiles*sizeof(double *));
- vdate = (int **) Malloc(nfiles*sizeof(int *));
- vtime = (int **) Malloc(nfiles*sizeof(int *));
- nts = (long*) Malloc(nfiles*sizeof(long));
+ double **datatab = (double **) Malloc(nfiles*sizeof(double *));
+ int **vdate = (int **) Malloc(nfiles*sizeof(int *));
+ int **vtime = (int **) Malloc(nfiles*sizeof(int *));
+ long *nts = (long*) Malloc(nfiles*sizeof(long));
- for ( fileID = 0; fileID < nfiles; fileID++ )
+ for ( int fileID = 0; fileID < nfiles; fileID++ )
{
datatab[fileID] = NULL;
vdate[fileID] = NULL;
@@ -837,16 +912,15 @@ void *Maggraph(void *argument)
nts[fileID] = 0;
}
- for ( fileID = 0; fileID < nfiles; fileID++ )
+ for ( int fileID = 0; fileID < nfiles; fileID++ )
{
-
-
if( DBG )
fprintf( stderr," file %d is %s\n", fileID, cdoStreamName(fileID)->args );
- streamID = streamOpenRead(cdoStreamName(fileID));
+
+ int streamID = streamOpenRead(cdoStreamName(fileID));
- vlistID = streamInqVlist(streamID);
- taxisID = vlistInqTaxis(vlistID);
+ int vlistID = streamInqVlist(streamID);
+ int taxisID = vlistInqTaxis(vlistID);
vlistInqVarUnits(vlistID, 0, units);
if( DBG )
@@ -855,10 +929,13 @@ void *Maggraph(void *argument)
{
vlistInqVarName(vlistID, 0, varname);
-
gridID = vlistInqVarGrid(vlistID, 0);
+ int zaxisID = vlistInqVarZaxis(vlistID, 0);
+ int nvars = vlistNvars(vlistID);
+ if ( nvars > 1 ) cdoAbort("Input stream has more than on variable!");
if ( gridInqSize(gridID) != 1 ) cdoAbort("Variable has more than one grid point!");
+ if ( zaxisInqSize(zaxisID) != 1 ) cdoAbort("Variable has more than one level!");
vlistID0 = vlistDuplicate(vlistID);
}
@@ -867,11 +944,11 @@ void *Maggraph(void *argument)
vlistCompare(vlistID0, vlistID, CMP_ALL);
}
- tsID = 0;
+ int tsID = 0;
nts_alloc = 0;
while ( (nrecs = streamInqTimestep(streamID, tsID)) )
{
- if ( nrecs != 1 ) cdoAbort("Input streams have more than one record!\n");
+ if ( nrecs != 1 ) cdoAbort("Input stream has more than one point in time!");
if ( tsID == 0 )
{
@@ -890,7 +967,8 @@ void *Maggraph(void *argument)
vdate[ fileID ] = (int*) Realloc(vdate[fileID], nts_alloc*sizeof(int));
vtime[ fileID ] = (int*) Realloc(vtime[fileID], nts_alloc*sizeof(int));
}
-
+
+ double val;
streamInqRecord( streamID, &varID, &levelID );
streamReadRecord( streamID, &val, &nmiss );
datatab[ fileID ][ tsID ] = val;
@@ -904,173 +982,47 @@ void *Maggraph(void *argument)
streamClose(streamID);
}
-#if defined(HAVE_LIBXML2)
/* HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR */
/*
init_XMLtemplate_parser( Filename );
updatemagics_and_results_nodes( );
*/
-#endif
-
-#if defined(HAVE_LIBMAGICS)
init_MAGICS( );
-#endif
cdoPrint(" Creating PLOT for %s", varname);
if( DBG )
{
fprintf(stderr, "Num params %d\n", nparam);
- for( i = 0; i< nparam; i++ )
+ for( int i = 0; i< nparam; i++ )
fprintf(stderr, "Param %s\n", pnames[i]);
}
maggraph(ofilename, varname, units, nfiles, nts, vdate, vtime, datatab, nparam, pnames);
-#if defined(HAVE_LIBXML2)
/* quit_XMLtemplate_parser( ); */
-#endif
-#if defined(HAVE_LIBMAGICS)
quit_MAGICS( );
-#endif
if ( vlistID0 != -1 ) vlistDestroy(vlistID0);
- for ( fileID = 0; fileID < nfiles; fileID++ )
+ for ( int fileID = 0; fileID < nfiles; fileID++ )
{
if ( datatab[fileID] ) Free(datatab[fileID]);
}
Free(datatab);
-
if ( vdate ) Free(vdate);
if ( vtime ) Free(vtime);
- cdoFinish();
-
- return 0;
-}
-
-
-void VerifyGraphParameters( int num_param, char **param_names )
-
-{
- int i, j;
- int found = FALSE, syntax = TRUE, halt_flag = FALSE, split_str_count;
- char **split_str = NULL;
- char *sep_char = "=";
- char *temp_str;
+#else
- for ( i = 0; i < num_param; ++i )
- {
- split_str_count = 0;
- found = FALSE;
- syntax = TRUE;
- split_str_count = StringSplitWithSeperator( param_names[i], sep_char, &split_str );
- if( split_str_count > 1 )
- {
- for ( j = 0; j < graph_param_count; ++j )
- {
- if( !strcmp( split_str[0], graph_params[j] ) )
- {
- found = TRUE;
- if( !strcmp( split_str[0],"obsv" ) || !strcmp( split_str[0],"stat" ) )
- {
- if( IsNumeric( split_str[1] ) )
- syntax = FALSE;
- else
- {
- temp_str = strdup( split_str[1] );
- StrToUpperCase( temp_str );
- if( strcmp( temp_str,"TRUE" ) && strcmp( temp_str,"FALSE" ) )
- syntax = FALSE;
- }
- }
-
- if( !strcmp( split_str[0],"ymin" ) || !strcmp( split_str[0],"ymax" ) || !strcmp( split_str[0],"sigma" ) )
- {
- if( !IsNumeric( split_str[1] ) )
- syntax = FALSE;
- }
-
-
- if( !strcmp( split_str[0],"device" ) )
- {
- if( IsNumeric( split_str[1] ) )
- syntax = FALSE;
- else
- {
- if( !strcmp( split_str[0],"device" ) )
- {
- if( DBG )
- fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
- if( checkdevice( split_str[1] ) )
- syntax = FALSE;
+ cdoAbort("MAGICS support not compiled in!");
- /* Graph not supported in google earth format */
- if( !strcmp( split_str[1],"GIF_ANIMATION" ) || !strcmp( split_str[1],"gif_animation" ))
- {
- syntax = FALSE;
- fprintf( stderr,"Animation not supported for Graph!\n");
- if( DBG )
- fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
- }
- if( !strcmp( split_str[1],"KML" ) || !strcmp( split_str[1],"kml" ) )
- {
- syntax = FALSE;
- fprintf( stderr," 'kml' format not supported for Graph!\n");
- if( DBG )
- fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
- }
- }
- }
- }
+#endif
-/*
- if( !strcmp( split_str[0],"xml" ) )
- {
- if( ( fp = fopen( split_str[1],"r") ) == NULL )
- {
- fprintf( stderr,"Input XML File not found in specified path '%s'\n", split_str[1] );
- halt_flag = TRUE;
- }
- else
- {
-#if defined(HAVE_LIBXML2)
- // HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR
- fclose(fp);
- init_XMLtemplate_parser( split_str[1] );
- updatemagics_and_results_nodes( );
-#endif
- }
- }
-*/
- }
- }
- }
- else
- {
- syntax = FALSE;
- }
-
- if( found == FALSE )
- {
- halt_flag = TRUE;
- fprintf( stderr,"Unknown parameter '%s'!\n", param_names[i] );
- }
- if( found == TRUE && syntax == FALSE )
- {
- halt_flag = TRUE;
- fprintf( stderr,"Invalid parameter specification '%s'!\n", param_names[i] );
- }
- Free( split_str );
- }
-
- if( halt_flag == TRUE )
- {
- exit(0);
- }
-
+ cdoFinish();
+
+ return 0;
}
diff --git a/src/Magplot.c b/src/Magplot.c
index 20d50b4..085c9b9 100644
--- a/src/Magplot.c
+++ b/src/Magplot.c
@@ -7,32 +7,41 @@
#include "cdo_int.h"
#include "grid.h"
#include "pstream.h"
+
+
+#if defined(HAVE_LIBMAGICS)
+
#include "magics_api.h"
-#include<libxml/parser.h>
-#include<libxml/tree.h>
-#include "template_parser.h"
#include "magics_template_parser.h"
#include "results_template_parser.h"
-
-xmlDoc *param_doc = NULL;
-xmlNode *root_node = NULL, *magics_node = NULL, *results_node = NULL;
+#include "StringUtilities.h"
#define DBG 0
+/***** ADDED for handling plots with defined lat lon min max *****/
+/*** LAT_MIN,LAT_MAX, LON_MIN,LON_MAX ****/
+/**** lat_min,lat_max,lon_min,lon_max ****/
+
+/****
+subpage_lower_left_latitude
+subpage_lower_left_longitude
+subpage_upper_right_latitude
+subpage_upper_right_longitude
+****/
int CONTOUR, SHADED, GRFILL;
-char *contour_params[] = {"min","max","count","interval","list","colour","thickness","style","RGB","device", "step_freq","file_split"};
+const char *contour_params[] = {"min","max","count","interval","list","colour","thickness","style","RGB","device", "step_freq","file_split","lat_min","lat_max","lon_min","lon_max","projection"};
int contour_param_count = sizeof(contour_params)/sizeof(char*);
-char *shaded_params[] = {"min","max","count","interval","list","colour_min","colour_max","colourtable","RGB","colour_triad","device","step_freq","file_split"};
+const char *shaded_params[] = {"min","max","count","interval","list","colour_min","colour_max","colour_table","RGB","colour_triad","device","step_freq","file_split","lat_min","lat_max","lon_min","lon_max","projection"};
int shaded_param_count = sizeof(shaded_params)/sizeof(char*);
-char *grfill_params[] = {"min","max","count","interval","list","colour_min","colour_max","colourtable","resolution","RGB","colour_triad","device","step_freq","file_split"};
+const char *grfill_params[] = {"min","max","count","interval","list","colour_min","colour_max","colour_table","resolution","RGB","colour_triad","device","step_freq","file_split","lat_min","lat_max","lon_min","lon_max","projection"};
int grfill_param_count = sizeof(grfill_params)/sizeof(char*);
-char *STD_COLOUR_TABLE[] = {"red", "green", "blue", "yellow", "cyan", "magenta", "black", "avocado",
+const char *STD_COLOUR_TABLE[] = {"red", "green", "blue", "yellow", "cyan", "magenta", "black", "avocado",
"beige", "brick", "brown", "burgundy",
"charcoal", "chestnut", "coral", "cream",
"evergreen", "gold", "grey",
@@ -59,12 +68,22 @@ int STD_COLOUR_COUNT = sizeof( STD_COLOUR_TABLE )/sizeof( char* );
int USR_COLOUR_COUNT =0;
-char *STYLE_TABLE[] = { "SOLID","DASH","DOT","CHAIN_DASH","CHAIN_DOT"};
+const char *STYLE_TABLE[] = { "SOLID","DASH","DOT","CHAIN_DASH","CHAIN_DOT"};
int STYLE_COUNT = sizeof( STYLE_TABLE )/ sizeof( char *);
-char *DEVICE_TABLE[] = { "PS","EPS","PDF","PNG","GIF","GIF_ANIMATION","JPEG","SVG","KML"};
+const char *DEVICE_TABLE[] = { "PS","EPS","PDF","PNG","GIF","GIF_ANIMATION","JPEG","SVG","KML"};
int DEVICE_COUNT = sizeof( DEVICE_TABLE )/ sizeof( char *);
+
+/*char *PROJECTION_TABLE[] = { "cylindrical", "polar_stereographic", "polar_north", "geos", "meteosat", "meteosat_57E", "goes_east", "lambert", "EPSG3857", "goode", "collignon", "mollweide", "robinson", "bonne", "google", "efas", "EPSG4326", "lambert_north_atlantic", "mercator", "cartesian", "taylor", "tephigram" };
+*/
+/** The following projections are having some issues to be clarified with Magics++ **/
+
+const char *PROJECTION_TABLE[] = { "cylindrical", "polar_stereographic", "polar_north", "geos", "meteosat", "meteosat_57E", "lambert", "EPSG3857", "goode", "collignon", "mollweide", "robinson", "bonne", "google", "efas", "EPSG4326", "lambert_north_atlantic", "mercator" };
+int PROJECTION_COUNT = sizeof( PROJECTION_TABLE )/ sizeof( char *);
+
+
+
int ANIM_FLAG = 0, STEP_FREQ = 0; /* '0' for static images like jpeg,ps, etc.. , '1' for animation formats */
@@ -72,33 +91,27 @@ int checkcolour( char *colour_in );
int ReadColourTable ( char *filepath );
int checkstyle( char *style_in );
int checkdevice( char *device_in );
-void VerifyPlotParameters( int num_param, char **param_names, int opID );
-
-extern int IsNumeric();
-extern void StrToUpperCase();
-extern void StrToLowerCase();
-extern int StringSplitWithSeperator();
-extern void StrReplaceChar( );
+int checkprojection( char *projection_in );
/* Magics default values */
int COUNT = 10, isRGB = FALSE, THICKNESS = 1, NUM_LEVELS = 0, FILE_SPLIT = FALSE;
double YMIN = 1.0e+200, YMAX = -1.0e+200, INTERVAL = 8.0, RESOLUTION = 10.0f, *LEV_LIST = NULL ;
-char *COLOUR = NULL, *COLOUR_MIN = NULL, *COLOUR_MAX = NULL, *STYLE = NULL, *DEVICE = NULL, *COLOUR_TRIAD = NULL;
+double LAT_MIN = 1.0e+200, LAT_MAX = -1.e+200;
+double LON_MIN = 1.0e+200, LON_MAX = -1.e+200;
+const char *COLOUR = NULL, *COLOUR_MIN = NULL, *COLOUR_MAX = NULL, *STYLE = NULL, *DEVICE = NULL, *COLOUR_TRIAD = NULL, *PROJECTION = NULL;
static
-void magplot( const char *plotfile, int operatorID, const char *varname, const char *units, long nlon, long nlat, double *grid_center_lon, double *grid_center_lat, double *array, int nparam, char **params, char *datetime )
+void magplot( const char *plotfile, int operatorID, const char *varname, const char *units, long nlon, long nlat, double *grid_center_lon, double *grid_center_lat, double *array, int nparam, char **params, char *datetime, bool lregular)
{
long i;
double dlon = 0, dlat = 0;
char plotfilename[4096];
char *titlename;
- int j, split_str_count, split_str_count1;
- char *sep_char = "=";
- char **split_str = NULL, **split_str1 = NULL;
- char *temp_str = NULL;
- char orig_char = ';', rep_char = ',';
+ int j, split_str_count;
+ const char *sep_char = "=";
+ char **split_str = NULL;
char tempname[256];
@@ -116,47 +129,29 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
sep_char = "=";
split_str_count = StringSplitWithSeperator( params[i], sep_char, &split_str );
- if( !strcmp( split_str[0],"min" ) )
- fprintf(stderr," Min Val %g\n",YMIN );
-
- if( !strcmp( split_str[0],"max" ) )
- fprintf(stderr,"Max Val %g\n",YMAX );
-
- if( !strcmp( split_str[0],"resolution" ) )
- fprintf( stderr,"RESOLUTION %g\n",RESOLUTION );
-
- if( !strcmp( split_str[0],"colour" ) )
- fprintf(stderr,"COLOUR %s\n",COLOUR );
+ if ( !strcmp( split_str[0],"min" ) ) fprintf(stderr,"Min Val %g\n",YMIN );
+ if ( !strcmp( split_str[0],"max" ) ) fprintf(stderr,"Max Val %g\n",YMAX );
+ // if ( !strcmp( split_str[0],"resolution" ) ) fprintf( stderr,"RESOLUTION %g\n",RESOLUTION );
+ if ( !strcmp( split_str[0],"colour" ) ) fprintf(stderr,"COLOUR %s\n",COLOUR );
+ if ( !strcmp( split_str[0],"colour_min" ) ) fprintf(stderr,"COLOUR %s\n",COLOUR_MIN );
+ if ( !strcmp( split_str[0],"colour_max" ) ) fprintf(stderr,"COLOUR %s\n",COLOUR_MAX );
+ if ( !strcmp( split_str[0],"interval" ) ) fprintf(stderr,"INTERVAL %f\n",INTERVAL );
+ if( !strcmp( split_str[0],"count" ) ) fprintf(stderr,"COUNT %d\n",COUNT );
- if( !strcmp( split_str[0],"colour_min" ) )
- fprintf(stderr,"COLOUR %s\n",COLOUR_MIN );
-
- if( !strcmp( split_str[0],"colour_max" ) )
- fprintf(stderr,"COLOUR %s\n",COLOUR_MAX );
-
- if( !strcmp( split_str[0],"interval" ) )
- fprintf( stderr,"INTERVAL %f\n",INTERVAL );
-
- if( !strcmp( split_str[0],"count" ) )
- fprintf( stderr,"COUNT %d\n",COUNT );
-
- if( !strcmp( split_str[0],"list" ) )
+ if ( !strcmp( split_str[0],"list" ) )
{
- for( j = 0; j < split_str_count1; j++ )
- fprintf( stderr,"LIST %f\n",LEV_LIST[j] );
+ for( j = 0; j < split_str_count; j++ ) fprintf(stderr,"LIST %f\n",LEV_LIST[j] );
}
- if( !strcmp( split_str[0],"thickness" ) )
- fprintf( stderr,"THICKNESS %d\n",THICKNESS );
-
- if( !strcmp( split_str[0],"style" ) )
- fprintf( stderr,"STYLE %s\n",STYLE );
-
- if( !strcmp( split_str[0],"device" ) )
- fprintf( stderr,"DEVICE %s\n",DEVICE );
-
- if( !strcmp( split_str[0],"step_freq" ) )
- fprintf( stderr,"STEP_FREQ %d\n",STEP_FREQ );
+ if ( !strcmp( split_str[0],"thickness" ) ) fprintf(stderr,"THICKNESS %d\n",THICKNESS );
+ if ( !strcmp( split_str[0],"style" ) ) fprintf(stderr,"STYLE %s\n",STYLE );
+ if ( !strcmp( split_str[0],"device" ) ) fprintf(stderr,"DEVICE %s\n",DEVICE );
+ if ( !strcmp( split_str[0],"step_freq" ) ) fprintf(stderr,"STEP_FREQ %d\n",STEP_FREQ );
+ if ( !strcmp( split_str[0],"lat_min" ) ) fprintf(stderr,"Lat Min Val %g\n",LAT_MIN );
+ if ( !strcmp( split_str[0],"lat_max" ) ) fprintf(stderr,"Lat Max Val %g\n",LAT_MAX );
+ if ( !strcmp( split_str[0],"lon_min" ) ) fprintf(stderr,"Lon Min Val %g\n",LON_MIN );
+ if ( !strcmp( split_str[0],"lon_max" ) ) fprintf(stderr,"Lon Max Val %g\n",LON_MAX );
+ if ( !strcmp( split_str[0],"projection" ) ) fprintf(stderr,"PROJECTION %s\n",PROJECTION );
Free(split_str);
}
@@ -184,47 +179,75 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_set2r("input_field", array, nlon, nlat);
- /*
- mag_setc("input_field_organization", "REGULAR");
- mag_set2r("input_field_latitudes", grid_center_lat, nlon, nlat);
- mag_set2r("input_field_longitudes", grid_center_lon, nlon, nlat);
- */
-
- mag_setr("input_field_initial_latitude", grid_center_lat[0]);
- mag_setr("input_field_latitude_step", dlat);
+ if ( lregular )
+ {
+ mag_setc("input_field_organization", "REGULAR");
+ // mag_setc("input_field_organization", "GAUSSIAN");
+
+ mag_setr("input_field_initial_latitude", grid_center_lat[0]);
+ mag_setr("input_field_latitude_step", dlat);
+
+ mag_setr("input_field_initial_longitude", grid_center_lon[0]);
+ mag_setr("input_field_longitude_step", dlon);
+ }
+ else
+ {
+ mag_setc("input_field_organization", "NONREGULAR");
- mag_setr("input_field_initial_longitude", grid_center_lon[0]);
- mag_setr("input_field_longitude_step", dlon);
-
+ mag_set2r("input_field_latitudes", grid_center_lat, nlon, nlat);
+ mag_set2r("input_field_longitudes", grid_center_lon, nlon, nlat);
+ }
+
/* magics_template_parser( magics_node ); */
/* results_template_parser(results_node, varname ); */
-
/* set up the coastline attributes */
/* mag_setc ("map_coastline_colour", "khaki"); */
/* mag_setc ("map_grid_colour", "grey"); */
-
/* Parameters common to all operators */
if( DEVICE )
{
mag_setc ("output_format", DEVICE );
}
+ if( PROJECTION )
+ {
+ mag_setc ( "subpage_map_projection", PROJECTION );
+ }
+
mag_seti ("map_label_latitude_frequency",2);
mag_seti ("map_label_longitude_frequency",2);
/*mag_setr ("map_label_height",0.5);*/
mag_setr ("map_label_height",0.4);
-
/* define the contouring parameters */
if ( operatorID == SHADED )
{
-
mag_setc ( "contour", "off" );
mag_setc ( "contour_shade", "on" );
mag_setc ( "contour_shade_method", "area_fill" );
mag_setc ( "contour_label", "off" );
+
+ if( LAT_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_latitude", LAT_MIN );
+ }
+
+ if( LON_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_longitude", LON_MIN );
+ }
+
+ if( LAT_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_latitude", LAT_MAX );
+ }
+
+ if( LON_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_longitude", LON_MAX );
+ }
if( YMIN < 1.0e+200 )
{
@@ -238,13 +261,13 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_setr( "contour_max_level", YMAX );
}
- if( COLOUR_MIN )
- mag_setc( "contour_shade_min_level_colour", COLOUR_MIN );
-
if( COLOUR_MAX )
mag_setc( "contour_shade_max_level_colour", COLOUR_MAX );
- if( INTERVAL != 8.0f )
+ if( COLOUR_MIN )
+ mag_setc( "contour_shade_min_level_colour", COLOUR_MIN );
+
+ if( IS_NOT_EQUAL(INTERVAL, 8.0f) )
{
mag_setc( "contour_level_selection_type", "INTERVAL" );
mag_setr( "contour_interval", INTERVAL );
@@ -267,7 +290,7 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_setc( "contour_shade_colour_method", "LIST" );
mag_set1c( "contour_shade_colour_list",( const char **)USR_COLOUR_TABLE, USR_COLOUR_COUNT );
}
-
+
if( COLOUR_TRIAD )
{
mag_setc( "contour_shade_colour_direction", COLOUR_TRIAD );
@@ -290,20 +313,38 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
if( DBG )
{
- mag_enqc ( "output_name", &tempname );
- fprintf( stderr, " SHADED Done %s!\n",tempname );
- fprintf( stderr, " SHADED Done!\n" );
+ mag_enqc ( "output_name", (char*)&tempname );
+ fprintf( stderr, " SHADED Done %s!\n",tempname );
+ fprintf( stderr, " SHADED Done!\n" );
}
}
else if ( operatorID == CONTOUR )
{
-
mag_setc ("contour", "on");
mag_setc ("contour_shade", "off");
mag_setc ("contour_label", "on");
mag_setc ("contour_highlight", "off");
-
+ if( LAT_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_latitude", LAT_MIN );
+ }
+
+ if( LON_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_longitude", LON_MIN );
+ }
+
+ if( LAT_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_latitude", LAT_MAX );
+ }
+
+ if( LON_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_longitude", LON_MAX );
+ }
+
if( YMIN < 1.0e+200 )
mag_setr( "contour_min_level", YMIN );
@@ -315,7 +356,7 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_setc( "contour_line_colour", COLOUR );
- if( INTERVAL != 8.0f )
+ if( IS_NOT_EQUAL(INTERVAL, 8.0f) )
{
mag_setc( "contour_level_selection_type", "INTERVAL" );
mag_setr( "contour_interval", INTERVAL );
@@ -339,20 +380,44 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
if( STYLE )
mag_setc( "contour_line_style", STYLE );
+ /* Adjust Set The page slightly to fit the legend */
+ mag_setr ( "subpage_x_length", 24. );
+ mag_setr ( "subpage_y_length", 30. );
+
if( DBG )
fprintf( stderr, " CONTOUR Done!\n" );
}
else if ( operatorID == GRFILL )
{
-
mag_setc ( "contour", "off" );
mag_setc ( "contour_shade", "on" );
- mag_setc ( "contour_shade_technique", "cell_shading" );
+ // mag_setc ( "contour_shade_technique", "cell_shading" );
+ mag_setc ( "contour_shade_technique", "grid_shading" );
mag_setc ( "contour_shade_method", "area_fill" );
mag_setc ( "contour_label", "off" );
+ if( LAT_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_latitude", LAT_MIN );
+ }
+
+ if( LON_MIN < 1.0e+200 )
+ {
+ mag_setr( "subpage_lower_left_longitude", LON_MIN );
+ }
+
+ if( LAT_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_latitude", LAT_MAX );
+ }
+
+ if( LON_MAX > -1.0e+200 )
+ {
+ mag_setr( "subpage_upper_right_longitude", LON_MAX );
+ }
+
if( YMIN < 1.0e+200 )
{
mag_setr( "contour_shade_min_level", YMIN );
@@ -379,7 +444,7 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
if( COLOUR_MAX )
mag_setc( "contour_shade_max_level_colour", COLOUR_MAX );
- if( INTERVAL != 8.0f )
+ if( IS_NOT_EQUAL(INTERVAL, 8.0f) )
{
mag_setc( "contour_level_selection_type", "INTERVAL" );
mag_setr( "contour_interval", INTERVAL );
@@ -402,10 +467,10 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_setc( "contour_shade_colour_method", "LIST" );
mag_set1c( "contour_shade_colour_list",( const char ** ) USR_COLOUR_TABLE, USR_COLOUR_COUNT );
}
-
- if( RESOLUTION != 10.0f)
+ /*
+ if( IS_NOT_EQUAL(RESOLUTION, 10.0f) )
mag_setr( "contour_shade_cell_resolution", RESOLUTION );
-
+ */
if( COLOUR_TRIAD )
mag_setc( "contour_shade_colour_direction", COLOUR_TRIAD );
@@ -448,10 +513,7 @@ void magplot( const char *plotfile, int operatorID, const char *varname, const c
mag_setc("text_justification", "left");
mag_text();
- if( LEV_LIST )
- Free(LEV_LIST);
-
-
+ if ( LEV_LIST ) Free(LEV_LIST);
}
@@ -468,246 +530,31 @@ void init_MAGICS( )
mag_setc( "output_ps_split" , "on" );
}
-static
-void quit_MAGICS( )
-{
-
- mag_close ();
- if( DBG )
- fprintf( stderr,"Exiting From MAGICS\n" );
-
-}
-
-void *Magplot(void *argument)
-{
- int operatorID;
- int varID, recID;
- int gridsize;
- int gridID;
- int nrecs;
- int levelID;
- int tsID;
- int streamID;
- int vlistID;
- int nmiss;
- int nlon, nlat;
- int nlev;
- int zaxisID, taxisID;
- int vdate, vtime;
- int nparam = 0;
- int i;
- char **pnames = NULL;
- char varname[CDI_MAX_NAME];
- double missval;
- double *array = NULL;
- double *grid_center_lat = NULL, *grid_center_lon = NULL;
- char units[CDI_MAX_NAME];
- char vdatestr[32], vtimestr[32], datetimestr[64];
-
-
- cdoInitialize(argument);
-
-
- nparam = operatorArgc();
- pnames = operatorArgv();
-
- CONTOUR = cdoOperatorAdd("contour", 0, 0, NULL);
- SHADED = cdoOperatorAdd("shaded", 0, 0, NULL);
- GRFILL = cdoOperatorAdd("grfill", 0, 0, NULL);
-
- operatorID = cdoOperatorID();
-
- if( nparam )
- {
- if( DBG )
- {
- for( i = 0; i < nparam; i++ )
- fprintf( stderr,"Param %d is %s!\n",i+1, pnames[i] );
- }
-
- VerifyPlotParameters( nparam, pnames, operatorID );
- }
-
- streamID = streamOpenRead(cdoStreamName(0));
-
- vlistID = streamInqVlist(streamID);
- taxisID = vlistInqTaxis(vlistID);
-
- varID = 0;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- missval = vlistInqVarMissval(vlistID, varID);
-
- if ( gridInqType(gridID) == GRID_GME ) cdoAbort("GME grid unspported!");
- if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) cdoAbort("Unstructured grid unspported!");
-
- if ( gridInqType(gridID) != GRID_CURVILINEAR )
- gridID = gridToCurvilinear(gridID, 1);
-
- gridsize = gridInqSize(gridID);
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
- nlev = zaxisInqSize(zaxisID);
-
- array = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
-
- gridInqYvals(gridID, grid_center_lat);
- gridInqXvals(gridID, grid_center_lon);
-
- /* Convert lat/lon units if required */
- gridInqXunits(gridID, units);
- grid_to_degree(units, gridsize, grid_center_lon, "grid center lon");
- gridInqYunits(gridID, units);
- grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
-
- tsID = 0;
-
- /* HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR */
- /*
- init_XMLtemplate_parser( Filename );
- updatemagics_and_results_nodes( );
- */
-
-
- init_MAGICS( );
-
- while ( (nrecs = streamInqTimestep(streamID, tsID)) )
- {
- if( ANIM_FLAG )
- {
- if( nrecs > 1 )
- {
- cdoWarning("File has more than one variable! Animation creation not possible!!! \n");
- break;
- }
- if( tsID % STEP_FREQ )
- {
- tsID++;
- continue;
- }
- }
- else
- {
- if( STEP_FREQ )
- {
- if( tsID % STEP_FREQ )
- {
- tsID++;
- cdoWarning("NOT PLOTTING STEP %d!!!\n",tsID);
- continue;
- }
- }
- else
- {
- if( tsID )
- {
- cdoWarning("File variables have values at more than one time step! Images created for first time step!!!");
- cdoWarning("To plot steps at a particular interval, set 'step_freq' to the frequency of the steps to be plotted!!!");
- cdoWarning("To plot steps at random interval, set 'step_freq' to '1' and select the steps using the selection operators!!!");
- break;
- }
- }
- }
-
- vdate = taxisInqVdate(taxisID);
- vtime = taxisInqVtime(taxisID);
-
- date2str(vdate, vdatestr, sizeof(vdatestr));
- time2str(vtime, vtimestr, sizeof(vtimestr));
- sprintf( datetimestr, "%s %s", vdatestr, vtimestr );
- if( DBG )
- fprintf( stderr,"Date %s Time %s\n",vdatestr, vtimestr );
-
- for ( recID = 0; recID < nrecs; recID++ )
- {
- streamInqRecord(streamID, &varID, &levelID);
- streamReadRecord(streamID, array, &nmiss);
- vlistInqVarName(vlistID, varID, varname);
- vlistInqVarUnits(vlistID, varID, units);
-
- if ( operatorID == SHADED || operatorID == CONTOUR || operatorID == GRFILL )
- {
- if( DBG )
- {
- if( operatorID == SHADED )
- fprintf( stderr," Creating SHADED PLOT for %s\n",varname );
- else if( operatorID == CONTOUR )
- fprintf( stderr," Creating CONTOUR PLOT for %s\n",varname );
- else if( operatorID == GRFILL )
- fprintf( stderr," Creating GRFILL PLOT for %s\n",varname );
- }
-
- if( DBG )
- fprintf( stderr,"Plot %d\n",varID );
- magplot(cdoStreamName(1)->args, operatorID, varname, units, nlon, nlat, grid_center_lon, grid_center_lat, array, nparam, pnames, datetimestr );
- }
- else
- fprintf(stderr,"operator not implemented\n");
- }
-
- if( DBG )
- fprintf( stderr,"TimeStep %d\n",tsID );
-
-
- tsID++;
- /*
- if( !STEP_FREQ && tsID )
- {
- cdoWarning("File variables have values at more than one time step! Images created for first time step!!!");
- cdoWarning("To plot steps at a particular interval, set 'step_freq' to the frequency of the steps to be plotted!!!");
- cdoWarning("To plot steps at random interval, set 'step_freq' to '1' and select the steps using the selection operators!!!");
- break;
- }
- else
- {
- tsID++;
- if( DBG )
- fprintf( stderr,"TimeStep %d\n",tsID );
- }
- */
- }
-
- if( ANIM_FLAG )
- {
- if( FILE_SPLIT == TRUE )
- cdoWarning("File split parameter ignored!!!");
- }
- quit_MAGICS( );
-
- streamClose(streamID);
-
- if ( array ) Free(array);
- if ( grid_center_lon ) Free(grid_center_lon);
- if ( grid_center_lat ) Free(grid_center_lat);
-
-/* quit_XMLtemplate_parser( ); */
-
- cdoFinish();
-
- return 0;
-
-}
-
+static
+void quit_MAGICS( )
+{
+ mag_close ();
+ if( DBG )
+ fprintf( stderr,"Exiting From MAGICS\n" );
+}
+static
void VerifyPlotParameters( int num_param, char **param_names, int opID )
-
{
int i, j, k;
int found = FALSE, syntax = TRUE, halt_flag = FALSE, /* file_found = TRUE, */ split_str_count;
- int param_count;
- char **params;
+ int param_count = 0;
+ const char **params = NULL;
char **split_str = NULL, **split_str1 = NULL;
- char *sep_char = "=";
+ const char *sep_char = "=";
char *temp_str;
- char orig_char = ';', rep_char = ',';
+ const char orig_char = ';', rep_char = ',';
FILE *fp;
/*
char *contour_params[] = {"ymin","ymax","count","interval","list","colour","thickness","style"};
- char *shaded_params[] = {"ymin","ymax","count","interval","list","colour_min","colour_max","colortable","step_freq"};
- char *grfill_params[] = {"ymin","ymax","count","interval","list","colour_min","colour_max","colortable","resolution"};
+ char *shaded_params[] = {"ymin","ymax","count","interval","list","colour_min","colour_max","colour_table","step_freq"};
+ char *grfill_params[] = {"ymin","ymax","count","interval","list","colour_min","colour_max","colour_table","resolution"};
*/
@@ -748,7 +595,8 @@ void VerifyPlotParameters( int num_param, char **param_names, int opID )
if( !strcmp( split_str[0],"colour" ) || !strcmp( split_str[0],"style" ) ||
!strcmp( split_str[0],"colour_min" ) || !strcmp( split_str[0],"colour_max" ) ||
!strcmp( split_str[0],"RGB" ) || !strcmp( split_str[0],"colour_triad" )||
- !strcmp( split_str[0],"device") || !strcmp( split_str[0],"file_split" )
+ !strcmp( split_str[0],"device") || !strcmp( split_str[0],"file_split" ) ||
+ !strcmp( split_str[0],"projection")
)
{
if( IsNumeric( split_str[1] ) )
@@ -856,12 +704,19 @@ void VerifyPlotParameters( int num_param, char **param_names, int opID )
COLOUR_TRIAD = "anti_clockwise";
}
}
+ else if( !strcmp( split_str[0],"projection" ) )
+ {
+ if( checkprojection( split_str[1] ) )
+ syntax = FALSE;
+ }
}
}
- if( !strcmp( split_str[0],"min" ) || !strcmp( split_str[0],"max" ) ||
- !strcmp( split_str[0],"count" ) || !strcmp( split_str[0],"interval" ) ||
- !strcmp( split_str[0],"thickness" ) || !strcmp( split_str[0],"resolution" ) ||
+ if( !strcmp( split_str[0],"min" ) || !strcmp( split_str[0],"max" ) ||
+ !strcmp( split_str[0],"lat_min" ) || !strcmp( split_str[0],"lat_max" ) ||
+ !strcmp( split_str[0],"lon_min" ) || !strcmp( split_str[0],"lon_max" ) ||
+ !strcmp( split_str[0],"count" ) || !strcmp( split_str[0],"interval" ) ||
+ !strcmp( split_str[0],"thickness" ) || !strcmp( split_str[0],"resolution" ) ||
!strcmp( split_str[0],"step_freq" )
)
{
@@ -897,10 +752,26 @@ void VerifyPlotParameters( int num_param, char **param_names, int opID )
{
STEP_FREQ = atoi( split_str[1] );
}
+ if( !strcmp( split_str[0],"lat_min" ) )
+ {
+ LAT_MIN = atof( split_str[1] );
+ }
+ if( !strcmp( split_str[0],"lat_max" ) )
+ {
+ LAT_MAX = atof( split_str[1] );
+ }
+ if( !strcmp( split_str[0],"lon_min" ) )
+ {
+ LON_MIN = atof( split_str[1] );
+ }
+ if( !strcmp( split_str[0],"lon_max" ) )
+ {
+ LON_MAX = atof( split_str[1] );
+ }
}
}
- if( !strcmp( split_str[0],"colourtable" ) )
+ if( !strcmp( split_str[0],"colour_table" ) )
{
if( ( fp = fopen( split_str[1],"r") ) == NULL )
{
@@ -973,12 +844,10 @@ void VerifyPlotParameters( int num_param, char **param_names, int opID )
int checkcolour( char *colour_in )
-
{
-
- int i, n, found = FALSE;
+ int i, n;
int split_str_count;
- char *sep_char =",";
+ const char *sep_char =",";
char **split_str = NULL;
float rgb_values[3];
char temp[256];
@@ -1048,99 +917,96 @@ int checkcolour( char *colour_in )
}
StrToLowerCase( colour_in );
- for( i = 0 ; i < STD_COLOUR_COUNT; i++ )
+ for ( i = 0 ; i < STD_COLOUR_COUNT; i++ )
{
- if( !strcmp( STD_COLOUR_TABLE[i], colour_in ) )
- {
- found = TRUE;
- return 0;
- }
+ if ( !strcmp( STD_COLOUR_TABLE[i], colour_in ) ) return 0;
}
- cdoWarning( "Specified Colour not in Standard colour list, resetting to blue(default colour)!" );
- return 1;
+ cdoWarning( "Specified Colour not in Standard colour list, resetting to blue(default colour)!" );
+ return 1;
}
if( DBG )
- cdoWarning( "Colour %s verified!",ref );
+ cdoWarning( "Colour %s verified!",ref );
+
return 0;
}
-int ReadColourTable ( char *filepath )
-
+int ReadColourTable( char *filepath )
{
+ int i, num_colors = 0;
+ char orig_char = ';', rep_char = ',';
- FILE *fp;
- int i, num_colors;
- char **temp_table = NULL;
- char orig_char = ';', rep_char = ',';
-
- fp = fopen( filepath,"r" );
+ FILE *fp = fopen( filepath,"r" );
- if( !fp )
- {
- fprintf( stdout, "File Not available!" );
- return 1;
- }
+ if ( !fp )
+ {
+ fprintf( stdout, "File Not available!" );
+ return 1;
+ }
- fscanf( fp, "%d", &num_colors );
+ fscanf( fp, "%d", &num_colors );
- if( DBG )
- fprintf( stderr, "Num Colours %d\n", num_colors );
+ if( DBG )
+ fprintf( stderr, "Num Colours %d\n", num_colors );
- if( !num_colors )
- {
- cdoWarning("No colours found in File, proceeding with Standard Colour table!\n");
- fclose(fp);
- return 1;
- }
+ if ( !num_colors )
+ {
+ cdoWarning("No colours found in File, proceeding with Standard Colour table!\n");
+ fclose(fp);
+ return 1;
+ }
- USR_COLOUR_COUNT = 0;
- USR_COLOUR_TABLE = ( char **) Malloc( num_colors * sizeof( char* ));
- temp_table = ( char **) Malloc( num_colors * sizeof( char* ));
+ USR_COLOUR_COUNT = 0;
+ USR_COLOUR_TABLE = ( char **) Malloc( num_colors * sizeof( char* ));
+ char **temp_table = ( char **) Malloc( num_colors * sizeof( char* ));
- for( i =0; i < num_colors; i++ )
- {
- temp_table[i] = ( char *) Malloc( 256 * sizeof( char ));
- fscanf( fp, "%s", temp_table[i] );
- if( DBG )
- fprintf( stdout, "%s\n", temp_table[i] );
- }
+ for ( i = 0; i < num_colors; i++ )
+ {
+ temp_table[i] = (char *) Malloc(256 * sizeof( char ));
+ fscanf( fp, "%s", temp_table[i] );
+ if( DBG )
+ fprintf( stdout, "%s\n", temp_table[i] );
+ }
- for( i = 0; i < num_colors; i++ )
- {
- if( DBG )
- fprintf( stdout, "%s \n", temp_table[i] );
+ fclose(fp);
+
+ for ( i = 0; i < num_colors; i++ )
+ {
+ if( DBG )
+ fprintf( stdout, "%s \n", temp_table[i] );
- if( !checkcolour( temp_table[i] ) )
- {
- if( isRGB )
- StrReplaceChar( temp_table[i], orig_char, rep_char ); /* replace ';' in RGB format to ',' */
+ if ( !checkcolour( temp_table[i] ) )
+ {
+ if( isRGB )
+ StrReplaceChar( temp_table[i], orig_char, rep_char ); /* replace ';' in RGB format to ',' */
- if( DBG )
- fprintf( stdout, "Before appending %s\n", temp_table[i] );
-
- USR_COLOUR_TABLE[ USR_COLOUR_COUNT ] = strdup( temp_table[i] );
+ if( DBG )
+ fprintf( stdout, "Before appending %s\n", temp_table[i] );
+
+ USR_COLOUR_TABLE[ USR_COLOUR_COUNT ] = strdup( temp_table[i] );
- /* strcpy( USR_COLOUR_TABLE[ USR_COLOUR_COUNT ], temp_table[i] ); */
- USR_COLOUR_COUNT++;
+ /* strcpy( USR_COLOUR_TABLE[ USR_COLOUR_COUNT ], temp_table[i] ); */
+ USR_COLOUR_COUNT++;
- if( DBG )
- fprintf( stdout, "After appending %s\n", temp_table[i] );
- }
- }
+ if( DBG )
+ fprintf( stdout, "After appending %s\n", temp_table[i] );
+ }
+ }
- if( USR_COLOUR_COUNT < num_colors )
- {
- cdoWarning( " Discarding improper format colours and continuing!\n" );
- }
-
- fclose(fp);
- return 0;
+ if( USR_COLOUR_COUNT < num_colors )
+ {
+ cdoWarning( " Discarding improper format colours and continuing!\n" );
+ }
+
+ for ( i = 0; i < num_colors; i++ ) free(temp_table[i]);
+ free(temp_table);
+
+ return 0;
}
-int checkstyle( char *style_in )
+int checkstyle( char *style_in )
{
int i, found = FALSE;
StrToUpperCase( style_in );
@@ -1165,7 +1031,6 @@ int checkstyle( char *style_in )
int checkdevice( char *device_in )
-
{
int i, found = FALSE;
StrToUpperCase( device_in );
@@ -1196,3 +1061,238 @@ int checkdevice( char *device_in )
return 1;
}
+
+
+int checkprojection( char *projection_in )
+{
+ int i, found = FALSE;
+
+ /*StrToUpperCase( projection_in );*/
+
+ for( i = 0 ; i < PROJECTION_COUNT; i++ )
+ {
+ if( DBG )
+ fprintf( stderr, "Input %s ref %s\n",projection_in, PROJECTION_TABLE[i] );
+
+ if( !strcmp( PROJECTION_TABLE[i], projection_in ) )
+ {
+ found = TRUE;
+ PROJECTION = projection_in;
+ return 0;
+ }
+ }
+
+ if( !found )
+ {
+ cdoWarning( " Projection specified with Improper value!\n" );
+ cdoWarning( " Specify one of the following:\n" );
+ cdoWarning( " cylindrical polar_stereographic polar_north geos meteosat meteosat_57E geos_east lambert EPSG3857 goode collignon mollweide robinson bonne google efas EPSG4326 lambert_north_atlantic mercator cartesian taylor tephigram\n" );
+
+ }
+
+ return 1;
+}
+#endif
+
+
+void *Magplot(void *argument)
+{
+ cdoInitialize(argument);
+
+#if defined(HAVE_LIBMAGICS)
+ int nrecs;
+ int levelID;
+ int nmiss;
+ char varname[CDI_MAX_NAME];
+ char units[CDI_MAX_NAME];
+ char vdatestr[32], vtimestr[32], datetimestr[64];
+
+ int nparam = operatorArgc();
+ char **pnames = operatorArgv();
+
+ CONTOUR = cdoOperatorAdd("contour", 0, 0, NULL);
+ SHADED = cdoOperatorAdd("shaded", 0, 0, NULL);
+ GRFILL = cdoOperatorAdd("grfill", 0, 0, NULL);
+
+ int operatorID = cdoOperatorID();
+
+ if( nparam )
+ {
+ if( DBG )
+ {
+ for( int i = 0; i < nparam; i++ )
+ fprintf( stderr,"Param %d is %s!\n",i+1, pnames[i] );
+ }
+
+ VerifyPlotParameters( nparam, pnames, operatorID );
+ }
+
+ int streamID = streamOpenRead(cdoStreamName(0));
+
+ int vlistID = streamInqVlist(streamID);
+ int taxisID = vlistInqTaxis(vlistID);
+
+ int varID = 0;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ // int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ // double missval = vlistInqVarMissval(vlistID, varID);
+
+ int gridtype = gridInqType(gridID);
+ if ( gridtype == GRID_GME ) cdoAbort("GME grid unspported!");
+ if ( gridtype == GRID_UNSTRUCTURED ) cdoAbort("Unstructured grid unspported!");
+
+ bool lregular = false;
+ if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN ) lregular = true;
+
+ if ( gridtype != GRID_CURVILINEAR ) gridID = gridToCurvilinear(gridID, 1);
+
+ int gridsize = gridInqSize(gridID);
+ int nlon = gridInqXsize(gridID);
+ int nlat = gridInqYsize(gridID);
+ //int nlev = zaxisInqSize(zaxisID);
+
+ double *array = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+
+ gridInqXvals(gridID, grid_center_lon);
+ gridInqYvals(gridID, grid_center_lat);
+
+ /* Convert lat/lon units if required */
+ gridInqXunits(gridID, units);
+ grid_to_degree(units, gridsize, grid_center_lon, "grid center lon");
+ gridInqYunits(gridID, units);
+ grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
+
+ int tsID = 0;
+
+ /* HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR */
+ /*
+ init_XMLtemplate_parser( Filename );
+ updatemagics_and_results_nodes( );
+ */
+
+
+ init_MAGICS( );
+
+ while ( (nrecs = streamInqTimestep(streamID, tsID)) )
+ {
+ if( ANIM_FLAG )
+ {
+ if( nrecs > 1 )
+ {
+ cdoWarning("File has more than one variable! Animation creation not possible!!! \n");
+ break;
+ }
+ if( tsID % STEP_FREQ )
+ {
+ tsID++;
+ continue;
+ }
+ }
+ else
+ {
+ if( STEP_FREQ )
+ {
+ if( tsID % STEP_FREQ )
+ {
+ tsID++;
+ cdoWarning("NOT PLOTTING STEP %d!!!\n",tsID);
+ continue;
+ }
+ }
+ else
+ {
+ if( tsID )
+ {
+ cdoWarning("File variables have values at more than one time step! Images created for first time step!!!");
+ cdoWarning("To plot steps at a particular interval, set 'step_freq' to the frequency of the steps to be plotted!!!");
+ cdoWarning("To plot steps at random interval, set 'step_freq' to '1' and select the steps using the selection operators!!!");
+ break;
+ }
+ }
+ }
+
+ int vdate = taxisInqVdate(taxisID);
+ int vtime = taxisInqVtime(taxisID);
+
+ date2str(vdate, vdatestr, sizeof(vdatestr));
+ time2str(vtime, vtimestr, sizeof(vtimestr));
+ sprintf( datetimestr, "%s %s", vdatestr, vtimestr );
+ if( DBG )
+ fprintf( stderr,"Date %s Time %s\n",vdatestr, vtimestr );
+
+ for ( int recID = 0; recID < nrecs; recID++ )
+ {
+ streamInqRecord(streamID, &varID, &levelID);
+ streamReadRecord(streamID, array, &nmiss);
+ vlistInqVarName(vlistID, varID, varname);
+ vlistInqVarUnits(vlistID, varID, units);
+
+ if ( operatorID == SHADED || operatorID == CONTOUR || operatorID == GRFILL )
+ {
+ if( DBG )
+ {
+ if( operatorID == SHADED )
+ fprintf( stderr," Creating SHADED PLOT for %s\n",varname );
+ else if( operatorID == CONTOUR )
+ fprintf( stderr," Creating CONTOUR PLOT for %s\n",varname );
+ else if( operatorID == GRFILL )
+ fprintf( stderr," Creating GRFILL PLOT for %s\n",varname );
+ }
+
+ if( DBG )
+ fprintf( stderr,"Plot %d\n",varID );
+ magplot(cdoStreamName(1)->args, operatorID, varname, units, nlon, nlat, grid_center_lon, grid_center_lat, array, nparam, pnames, datetimestr, lregular);
+ }
+ else
+ fprintf(stderr,"operator not implemented\n");
+ }
+
+ if( DBG )
+ fprintf( stderr,"TimeStep %d\n",tsID );
+
+
+ tsID++;
+ /*
+ if( !STEP_FREQ && tsID )
+ {
+ cdoWarning("File variables have values at more than one time step! Images created for first time step!!!");
+ cdoWarning("To plot steps at a particular interval, set 'step_freq' to the frequency of the steps to be plotted!!!");
+ cdoWarning("To plot steps at random interval, set 'step_freq' to '1' and select the steps using the selection operators!!!");
+ break;
+ }
+ else
+ {
+ tsID++;
+ if( DBG )
+ fprintf( stderr,"TimeStep %d\n",tsID );
+ }
+ */
+ }
+
+ if( ANIM_FLAG )
+ {
+ if( FILE_SPLIT == TRUE )
+ cdoWarning("File split parameter ignored!!!");
+ }
+ quit_MAGICS( );
+
+ streamClose(streamID);
+
+ if ( array ) Free(array);
+ if ( grid_center_lon ) Free(grid_center_lon);
+ if ( grid_center_lat ) Free(grid_center_lat);
+
+/* quit_XMLtemplate_parser( ); */
+#else
+
+ cdoAbort("MAGICS support not compiled in!");
+
+#endif
+
+ cdoFinish();
+
+ return 0;
+
+}
diff --git a/src/Magvector.c b/src/Magvector.c
index f32b2f7..9c29ecd 100644
--- a/src/Magvector.c
+++ b/src/Magvector.c
@@ -8,33 +8,26 @@
#include "grid.h"
#include "pstream.h"
+
+#if defined(HAVE_LIBMAGICS)
+
#include "magics_api.h"
-#include<libxml/parser.h>
-#include<libxml/tree.h>
-#include "template_parser.h"
#include "magics_template_parser.h"
#include "results_template_parser.h"
-
-extern xmlNode *magics_node;
+#include "StringUtilities.h"
#define DBG 0
int VECTOR, STREAM;
-char *vector_params[] = {"thin_fac","unit_vec","device","step_freq"};
+const char *vector_params[] = {"thin_fac","unit_vec","device","step_freq"};
int vector_param_count = sizeof(vector_params)/sizeof(char*);
-void VerifyVectorParameters( int num_param, char **param_names, int opID );
-
/* Default Magics Values */
double THIN_FAC = 2.0, UNIT_VEC = 25.0;
extern int ANIM_FLAG,STEP_FREQ;
-extern int checkdevice();
-extern int IsNumeric();
-extern void StrToUpperCase();
-extern int StringSplitWithSeperator();
-
+extern int checkdevice(char *device_in);
extern char *DEVICE;
extern char *DEVICE_TABLE;
@@ -48,12 +41,13 @@ void magvector( const char *plotfile, int operatorID, const char *varname, long
double dlon = 0, dlat = 0;
int split_str_count;
char plotfilename[4096];
- char *sep_char= "=";
+ const char *sep_char= "=";
char **split_str=NULL;
char *temp_str = NULL;
char *titlename;
-
+ (void)varname;
+
if( uarray == NULL && varray == NULL )
{
fprintf( stderr," No Velocity Components in input file, cannot creaate Vector PLOT!\n" );
@@ -80,7 +74,8 @@ void magvector( const char *plotfile, int operatorID, const char *varname, long
split_str_count = 0;
sep_char = "=";
split_str_count = StringSplitWithSeperator( params[i], sep_char, &split_str );
-
+ (void)split_str_count;
+
if( !strcmp( split_str[0],"thin_fac" ) )
{
THIN_FAC = atof( split_str[1] );
@@ -128,10 +123,6 @@ void magvector( const char *plotfile, int operatorID, const char *varname, long
dlat /= (nlat-1);
}
-
-/* #if defined(HAVE_LIBMAGICS) */
-
-
/* magics_template_parser( magics_node ); */
/* results_template_parser(results_node, varname ); */
@@ -176,11 +167,11 @@ void magvector( const char *plotfile, int operatorID, const char *varname, long
mag_seti( "wind_arrow_thickness",1 );
mag_coast();
- if( THIN_FAC != 2.0f )
+ if( IS_NOT_EQUAL(THIN_FAC, 2.0f) )
mag_setr("wind_thinning_factor",THIN_FAC);
/*wind_arrow_unit_velocity */
- if( UNIT_VEC != 25.0f )
+ if( IS_NOT_EQUAL(UNIT_VEC, 25.0f) )
mag_setr("wind_arrow_unit_velocity",UNIT_VEC);
mag_wind();
@@ -193,7 +184,6 @@ void magvector( const char *plotfile, int operatorID, const char *varname, long
}
}
-
static
void init_MAGICS( )
@@ -218,67 +208,148 @@ void quit_MAGICS( )
}
-void *Magvector(void *argument)
+static
+void VerifyVectorParameters( int num_param, char **param_names, int opID )
{
- int operatorID;
- int varID, recID;
- int gridsize;
- int gridID;
+
+ int i, j;
+ int found = FALSE, syntax = TRUE, halt_flag = FALSE, split_str_count;
+ int param_count = 0;
+ const char **params = NULL;
+ char **split_str = NULL;
+ const char *sep_char = "=";
+
+ /* char *vector_params[] = {"min","max","count","interval","list","colour","thickness","style","RGB"}; */
+
+ for ( i = 0; i < num_param; ++i )
+ {
+ split_str_count = 0;
+ found = FALSE;
+ syntax = TRUE;
+ split_str_count = StringSplitWithSeperator( param_names[i], sep_char, &split_str );
+
+ if( DBG )
+ fprintf( stderr, "Verifying params!\n");
+
+ if( split_str_count > 1 )
+ {
+
+ if( opID == VECTOR )
+ {
+ param_count = vector_param_count;
+ params = vector_params;
+ }
+
+ for ( j = 0; j < param_count; ++j )
+ {
+ if( !strcmp( split_str[0], params[j] ) )
+ {
+ found = TRUE;
+
+ if( !strcmp( split_str[0],"thin_fac" ) || !strcmp( split_str[0],"unit_vec" ) ||
+ !strcmp( split_str[0],"step_freq" )
+ )
+ {
+ if( !IsNumeric( split_str[1] ) )
+ syntax = FALSE;
+ }
+
+ if( !strcmp( split_str[0],"device" ) )
+ {
+ if( IsNumeric( split_str[1] ) )
+ syntax = FALSE;
+ else
+ {
+ if( !strcmp( split_str[0],"device" ) )
+ {
+ if( DBG )
+ fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
+ if( checkdevice( split_str[1] ) )
+ syntax = FALSE;
+
+ /* Vector not supported in google earth format */
+ if( !strcmp( split_str[1],"KML" ) || !strcmp( split_str[1],"kml" ) )
+ {
+ syntax = FALSE;
+ if( DBG )
+ fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ syntax = FALSE;
+ }
+
+ if( found == FALSE )
+ {
+ halt_flag = TRUE;
+ fprintf( stderr,"Invalid parameter '%s'\n", param_names[i] );
+ }
+ if( found == TRUE && syntax == FALSE )
+ {
+ halt_flag = TRUE;
+ fprintf( stderr,"Invalid parameter specification '%s'\n", param_names[i] );
+ }
+
+ if( split_str )
+ Free( split_str );
+ }
+
+ if( halt_flag == TRUE )
+ {
+ exit(0);
+ }
+}
+#endif
+
+
+void *Magvector(void *argument)
+{
+ cdoInitialize(argument);
+
+#if defined(HAVE_LIBMAGICS)
int nrecs;
int levelID;
- int tsID;
- int streamID;
- int vlistID;
int nmiss;
- int nlon, nlat;
- int nlev;
- int zaxisID, taxisID;
- int vdate, vtime;
- int found;
- int nparam = 0;
- int i;
- char **pnames = NULL;
char varname[CDI_MAX_NAME];
- double missval;
- double *uarray = NULL;
- double *varray = NULL;
- double *grid_center_lat = NULL, *grid_center_lon = NULL;
char units[CDI_MAX_NAME];
char vdatestr[32],vtimestr[32],datetimestr[64];
-
- cdoInitialize(argument);
-
- nparam = operatorArgc();
- pnames = operatorArgv();
+ int nparam = operatorArgc();
+ char **pnames = operatorArgv();
- VECTOR = cdoOperatorAdd("vector", 0, 0, NULL);
- STREAM = cdoOperatorAdd("stream", 0, 0, NULL);
+ int VECTOR = cdoOperatorAdd("vector", 0, 0, NULL);
+ int STREAM = cdoOperatorAdd("stream", 0, 0, NULL);
- operatorID = cdoOperatorID();
+ int operatorID = cdoOperatorID();
- if( nparam )
+ if ( nparam )
{
if( DBG )
{
- for( i = 0; i < nparam; i++ )
+ for( int i = 0; i < nparam; i++ )
fprintf( stderr,"Param %d is %s!\n",i+1, pnames[i] );
}
VerifyVectorParameters( nparam, pnames, operatorID );
}
- streamID = streamOpenRead(cdoStreamName(0));
+ int streamID = streamOpenRead(cdoStreamName(0));
- vlistID = streamInqVlist(streamID);
- taxisID = vlistInqTaxis(vlistID);
+ int vlistID = streamInqVlist(streamID);
+ int taxisID = vlistInqTaxis(vlistID);
- found = 0;
- varID = 0;
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- missval = vlistInqVarMissval(vlistID, varID);
+ int found = 0;
+ int varID = 0;
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ // int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ // double missval = vlistInqVarMissval(vlistID, varID);
if ( gridInqType(gridID) == GRID_GME ) cdoAbort("GME grid unspported!");
if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) cdoAbort("Unstructured grid unspported!");
@@ -286,15 +357,15 @@ void *Magvector(void *argument)
if ( gridInqType(gridID) != GRID_CURVILINEAR )
gridID = gridToCurvilinear(gridID, 1);
- gridsize = gridInqSize(gridID);
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
- nlev = zaxisInqSize(zaxisID);
+ int gridsize = gridInqSize(gridID);
+ int nlon = gridInqXsize(gridID);
+ int nlat = gridInqYsize(gridID);
+ // int nlev = zaxisInqSize(zaxisID);
- uarray = (double*) Malloc(gridsize*sizeof(double));
- varray = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+ double *uarray = (double*) Malloc(gridsize*sizeof(double));
+ double *varray = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
gridInqYvals(gridID, grid_center_lat);
gridInqXvals(gridID, grid_center_lon);
@@ -305,7 +376,7 @@ void *Magvector(void *argument)
gridInqYunits(gridID, units);
grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
- tsID = 0;
+ int tsID = 0;
/* HARDCODED THE FILE NAME .. TO BE SENT AS COMMAND LINE ARGUMENT FOR THE MAGICS OPERATOR */
/*
@@ -335,14 +406,14 @@ void *Magvector(void *argument)
}
}
- vdate = taxisInqVdate(taxisID);
- vtime = taxisInqVtime(taxisID);
+ int vdate = taxisInqVdate(taxisID);
+ int vtime = taxisInqVtime(taxisID);
date2str(vdate, vdatestr, sizeof(vdatestr));
time2str(vtime, vtimestr, sizeof(vtimestr));
sprintf(datetimestr, "%s %s", vdatestr,vtimestr);
- for( recID = 0; recID < nrecs; recID++ )
+ for( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID, &varID, &levelID);
@@ -419,109 +490,13 @@ void *Magvector(void *argument)
quit_MAGICS( );
- cdoFinish();
-
- return 0;
-
-}
-
-
-
-void VerifyVectorParameters( int num_param, char **param_names, int opID )
-
-{
+#else
- int i, j;
- int found = FALSE, syntax = TRUE, halt_flag = FALSE, split_str_count;
- int param_count;
- char **params;
- char **split_str = NULL;
- char *sep_char = "=";
+ cdoAbort("MAGICS support not compiled in!");
- /* char *vector_params[] = {"min","max","count","interval","list","colour","thickness","style","RGB"}; */
+#endif
- for ( i = 0; i < num_param; ++i )
- {
- split_str_count = 0;
- found = FALSE;
- syntax = TRUE;
- split_str_count = StringSplitWithSeperator( param_names[i], sep_char, &split_str );
-
- if( DBG )
- fprintf( stderr, "Verifying params!\n");
-
- if( split_str_count > 1 )
- {
-
- if( opID == VECTOR )
- {
- param_count = vector_param_count;
- params = vector_params;
- }
-
- for ( j = 0; j < param_count; ++j )
- {
- if( !strcmp( split_str[0], params[j] ) )
- {
- found = TRUE;
-
- if( !strcmp( split_str[0],"thin_fac" ) || !strcmp( split_str[0],"unit_vec" ) ||
- !strcmp( split_str[0],"step_freq" )
- )
- {
- if( !IsNumeric( split_str[1] ) )
- syntax = FALSE;
- }
-
- if( !strcmp( split_str[0],"device" ) )
- {
- if( IsNumeric( split_str[1] ) )
- syntax = FALSE;
- else
- {
- if( !strcmp( split_str[0],"device" ) )
- {
- if( DBG )
- fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
- if( checkdevice( split_str[1] ) )
- syntax = FALSE;
+ cdoFinish();
- /* Vector not supported in google earth format */
- if( !strcmp( split_str[1],"KML" ) || !strcmp( split_str[1],"kml" ) )
- {
- syntax = FALSE;
- if( DBG )
- fprintf( stderr,"Parameter value '%s'\n",split_str[1] );
- }
- }
- }
- }
- }
- }
- }
- else
- {
- syntax = FALSE;
- }
-
- if( found == FALSE )
- {
- halt_flag = TRUE;
- fprintf( stderr,"Invalid parameter '%s'\n", param_names[i] );
- }
- if( found == TRUE && syntax == FALSE )
- {
- halt_flag = TRUE;
- fprintf( stderr,"Invalid parameter specification '%s'\n", param_names[i] );
- }
-
- if( split_str )
- Free( split_str );
- }
-
- if( halt_flag == TRUE )
- {
- exit(0);
- }
-
+ return 0;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 14dfe12..9cdeff3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ libcdo_la_SOURCES = \
cdo_task.c \
cdo_task.h \
cdo_history.c \
+ cdi_uuid.h \
after_sptrans.c \
after_fctrans.c \
after_dvtrans.c \
@@ -19,6 +20,7 @@ libcdo_la_SOURCES = \
afterburnerlib.c\
afterburner.h \
vct_l191.h \
+ calendar.h \
constants.h \
constants.c \
color.c \
@@ -40,6 +42,8 @@ libcdo_la_SOURCES = \
exception.c \
expr.c \
expr.h \
+ expr_fun.c \
+ expr_fun.h \
expr_lex.c \
expr_yacc.c \
expr_yacc.h \
@@ -257,6 +261,7 @@ cdo_SOURCES += Adisit.c \
Output.c \
Outputgmt.c \
Pack.c \
+ Pardup.c \
Pinfo.c \
Pressure.c \
Regres.c \
@@ -306,6 +311,7 @@ cdo_SOURCES += Adisit.c \
Templates.c \
Test.c \
Tests.c \
+ Timedt.c \
Timcount.c \
Timpctl.c \
Timselpctl.c \
@@ -320,7 +326,6 @@ cdo_SOURCES += Adisit.c \
Trend.c \
Trms.c \
Tstepcount.c \
- Vardup.c \
Vargen.c \
Varrms.c \
Vertintml.c \
@@ -328,6 +333,7 @@ cdo_SOURCES += Adisit.c \
Vertstat.c \
Vertcum.c \
Vertwind.c \
+ Verifygrid.c \
Wct.c \
Wind.c \
Writegrid.c \
@@ -359,7 +365,7 @@ cdo_SOURCES += nearpt3c.h
# cellsearchorder.h
#endif
-if ENABLE_MAGICS
+#if ENABLE_MAGICS
cdo_SOURCES += Magplot.c \
Magvector.c \
Maggraph.c \
@@ -373,7 +379,7 @@ cdo_SOURCES += Magplot.c \
StringUtilities.c \
CdoMagicsMapper.h \
CdoMagicsMapper.c
-endif
+#endif
cdo_CPPFLAGS = -I$(top_srcdir)/libcdi/src
cdo_LDADD = libcdo.la $(top_builddir)/libcdi/src/libcdi.la
diff --git a/src/Makefile.in b/src/Makefile.in
index 53768be..a75a43f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -80,30 +80,9 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = cdo$(EXEEXT)
-#if ENABLE_NEARPT3
-#cdo_SOURCES += \
-# nearpt3x.h \
-# nearpt3c.h \
-# nearpt3c.cc \
-# cellsearchorder.h
-#endif
- at ENABLE_MAGICS_TRUE@am__append_1 = Magplot.c \
- at ENABLE_MAGICS_TRUE@ Magvector.c \
- at ENABLE_MAGICS_TRUE@ Maggraph.c \
- at ENABLE_MAGICS_TRUE@ template_parser.h \
- at ENABLE_MAGICS_TRUE@ template_parser.c \
- at ENABLE_MAGICS_TRUE@ results_template_parser.h \
- at ENABLE_MAGICS_TRUE@ results_template_parser.c \
- at ENABLE_MAGICS_TRUE@ magics_template_parser.h \
- at ENABLE_MAGICS_TRUE@ magics_template_parser.c \
- at ENABLE_MAGICS_TRUE@ StringUtilities.h \
- at ENABLE_MAGICS_TRUE@ StringUtilities.c \
- at ENABLE_MAGICS_TRUE@ CdoMagicsMapper.h \
- at ENABLE_MAGICS_TRUE@ CdoMagicsMapper.c
-
- at ENABLE_ALL_STATIC_TRUE@am__append_2 = -all-static
+ at ENABLE_ALL_STATIC_TRUE@am__append_1 = -all-static
noinst_PROGRAMS = cdotest$(EXEEXT)
- at ENABLE_ALL_STATIC_TRUE@am__append_3 = -all-static
+ at ENABLE_ALL_STATIC_TRUE@am__append_2 = -all-static
subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/config.h.in $(top_srcdir)/config/mkinstalldirs \
@@ -132,12 +111,12 @@ am_libcdo_la_OBJECTS = libcdo_la-cdo_pthread.lo libcdo_la-cdo_vlist.lo \
libcdo_la-color.lo libcdo_la-commandline.lo \
libcdo_la-datetime.lo libcdo_la-ecacore.lo \
libcdo_la-ecautil.lo libcdo_la-exception.lo libcdo_la-expr.lo \
- libcdo_la-expr_lex.lo libcdo_la-expr_yacc.lo \
- libcdo_la-features.lo libcdo_la-field.lo libcdo_la-field2.lo \
- libcdo_la-fieldc.lo libcdo_la-fieldmem.lo \
- libcdo_la-fieldmer.lo libcdo_la-fieldzon.lo \
- libcdo_la-gradsdeslib.lo libcdo_la-grid.lo \
- libcdo_la-grid_area.lo libcdo_la-grid_gme.lo \
+ libcdo_la-expr_fun.lo libcdo_la-expr_lex.lo \
+ libcdo_la-expr_yacc.lo libcdo_la-features.lo \
+ libcdo_la-field.lo libcdo_la-field2.lo libcdo_la-fieldc.lo \
+ libcdo_la-fieldmem.lo libcdo_la-fieldmer.lo \
+ libcdo_la-fieldzon.lo libcdo_la-gradsdeslib.lo \
+ libcdo_la-grid.lo libcdo_la-grid_area.lo libcdo_la-grid_gme.lo \
libcdo_la-grid_lcc.lo libcdo_la-grid_rot.lo \
libcdo_la-gridreference.lo libcdo_la-griddes.lo \
libcdo_la-griddes_h5.lo libcdo_la-griddes_nc.lo \
@@ -178,52 +157,6 @@ am__v_lt_0 = --silent
am__v_lt_1 =
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
-am__cdo_SOURCES_DIST = cdo.c Adisit.c Afterburner.c Arith.c Arithc.c \
- Arithdays.c Arithlat.c CDItest.c CDIread.c CDIwrite.c Cat.c \
- Change.c Change_e5slm.c Cloudlayer.c CMOR.c Collgrid.c \
- Command.c Comp.c Compc.c Complextorect.c Cond.c Cond2.c \
- Condc.c Consecstat.c Copy.c Deltime.c Derivepar.c Detrend.c \
- Diff.c Distgrid.c Duplicate.c EOFs.c Eof3d.c EcaIndices.c \
- Echam5ini.c Enlarge.c Enlargegrid.c Ensstat.c Ensstat3.c \
- Ensval.c Eofcoeff.c Eofcoeff3d.c Exprf.c FC.c Filedes.c \
- Fillmiss.c Filter.c Fldrms.c Fldstat.c Fldstat2.c Fourier.c \
- Gengrid.c Gradsdes.c Gridboxstat.c Gridcell.c Gridsearch.c \
- Harmonic.c Hi.c Histogram.c Importamsr.c Importbinary.c \
- Importcmsaf.c Importobs.c Info.c Input.c Intgrid.c \
- Intgridtraj.c Intlevel.c Intlevel3d.c Intntime.c Inttime.c \
- Intyear.c Invert.c Invertlev.c Isosurface.c Kvl.c Log.c \
- Maskbox.c Mastrfu.c Math.c Merge.c Mergegrid.c Mergetime.c \
- Merstat.c Monarith.c Mrotuv.c Mrotuvb.c Ninfo.c Nmltest.c \
- Output.c Outputgmt.c Pack.c Pinfo.c Pressure.c Regres.c \
- Remap.c Remapeta.c Replace.c Replacevalues.c Rhopot.c Rotuv.c \
- Runpctl.c Runstat.c Seascount.c Seaspctl.c Seasstat.c Selbox.c \
- Select.c Seloperator.c Selrec.c Seltime.c Selvar.c Set.c \
- Setbox.c Setgatt.c Setgrid.c Sethalo.c Setmiss.c Setpartab.c \
- Setrcaname.c Settime.c Setzaxis.c Showinfo.c Sinfo.c Smooth9.c \
- Sort.c Sorttimestamp.c Specinfo.c Spectral.c Spectrum.c \
- Split.c Splitrec.c Splitsel.c Splittime.c Splityear.c SSOpar.c \
- Subtrend.c Tee.c Templates.c Test.c Tests.c Timcount.c \
- Timpctl.c Timselpctl.c Timselstat.c Timsort.c Timstat.c \
- Timstat2.c Timstat3.c Tinfo.c Tocomplex.c Transpose.c Trend.c \
- Trms.c Tstepcount.c Vardup.c Vargen.c Varrms.c Vertintml.c \
- Vertintap.c Vertstat.c Vertcum.c Vertwind.c Wct.c Wind.c \
- Writegrid.c Writerandom.c XTimstat.c YAR.c Yearmonstat.c \
- Ydayarith.c Ydaypctl.c Ydaystat.c Ydrunpctl.c Ydrunstat.c \
- Yhourarith.c Yhourstat.c Ymonarith.c Ymonpctl.c Ymonstat.c \
- Yseaspctl.c Yseasstat.c Zonstat.c cdo.h nearpt3c.h Magplot.c \
- Magvector.c Maggraph.c template_parser.h template_parser.c \
- results_template_parser.h results_template_parser.c \
- magics_template_parser.h magics_template_parser.c \
- StringUtilities.h StringUtilities.c CdoMagicsMapper.h \
- CdoMagicsMapper.c
- at ENABLE_MAGICS_TRUE@am__objects_1 = cdo-Magplot.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-Magvector.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-Maggraph.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-template_parser.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-results_template_parser.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-magics_template_parser.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-StringUtilities.$(OBJEXT) \
- at ENABLE_MAGICS_TRUE@ cdo-CdoMagicsMapper.$(OBJEXT)
am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
cdo-Afterburner.$(OBJEXT) cdo-Arith.$(OBJEXT) \
cdo-Arithc.$(OBJEXT) cdo-Arithdays.$(OBJEXT) \
@@ -266,7 +199,8 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
cdo-Merstat.$(OBJEXT) cdo-Monarith.$(OBJEXT) \
cdo-Mrotuv.$(OBJEXT) cdo-Mrotuvb.$(OBJEXT) cdo-Ninfo.$(OBJEXT) \
cdo-Nmltest.$(OBJEXT) cdo-Output.$(OBJEXT) \
- cdo-Outputgmt.$(OBJEXT) cdo-Pack.$(OBJEXT) cdo-Pinfo.$(OBJEXT) \
+ cdo-Outputgmt.$(OBJEXT) cdo-Pack.$(OBJEXT) \
+ cdo-Pardup.$(OBJEXT) cdo-Pinfo.$(OBJEXT) \
cdo-Pressure.$(OBJEXT) cdo-Regres.$(OBJEXT) \
cdo-Remap.$(OBJEXT) cdo-Remapeta.$(OBJEXT) \
cdo-Replace.$(OBJEXT) cdo-Replacevalues.$(OBJEXT) \
@@ -289,17 +223,18 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
cdo-Splityear.$(OBJEXT) cdo-SSOpar.$(OBJEXT) \
cdo-Subtrend.$(OBJEXT) cdo-Tee.$(OBJEXT) \
cdo-Templates.$(OBJEXT) cdo-Test.$(OBJEXT) cdo-Tests.$(OBJEXT) \
- cdo-Timcount.$(OBJEXT) cdo-Timpctl.$(OBJEXT) \
- cdo-Timselpctl.$(OBJEXT) cdo-Timselstat.$(OBJEXT) \
- cdo-Timsort.$(OBJEXT) cdo-Timstat.$(OBJEXT) \
- cdo-Timstat2.$(OBJEXT) cdo-Timstat3.$(OBJEXT) \
- cdo-Tinfo.$(OBJEXT) cdo-Tocomplex.$(OBJEXT) \
- cdo-Transpose.$(OBJEXT) cdo-Trend.$(OBJEXT) cdo-Trms.$(OBJEXT) \
- cdo-Tstepcount.$(OBJEXT) cdo-Vardup.$(OBJEXT) \
- cdo-Vargen.$(OBJEXT) cdo-Varrms.$(OBJEXT) \
- cdo-Vertintml.$(OBJEXT) cdo-Vertintap.$(OBJEXT) \
- cdo-Vertstat.$(OBJEXT) cdo-Vertcum.$(OBJEXT) \
- cdo-Vertwind.$(OBJEXT) cdo-Wct.$(OBJEXT) cdo-Wind.$(OBJEXT) \
+ cdo-Timedt.$(OBJEXT) cdo-Timcount.$(OBJEXT) \
+ cdo-Timpctl.$(OBJEXT) cdo-Timselpctl.$(OBJEXT) \
+ cdo-Timselstat.$(OBJEXT) cdo-Timsort.$(OBJEXT) \
+ cdo-Timstat.$(OBJEXT) cdo-Timstat2.$(OBJEXT) \
+ cdo-Timstat3.$(OBJEXT) cdo-Tinfo.$(OBJEXT) \
+ cdo-Tocomplex.$(OBJEXT) cdo-Transpose.$(OBJEXT) \
+ cdo-Trend.$(OBJEXT) cdo-Trms.$(OBJEXT) \
+ cdo-Tstepcount.$(OBJEXT) cdo-Vargen.$(OBJEXT) \
+ cdo-Varrms.$(OBJEXT) cdo-Vertintml.$(OBJEXT) \
+ cdo-Vertintap.$(OBJEXT) cdo-Vertstat.$(OBJEXT) \
+ cdo-Vertcum.$(OBJEXT) cdo-Vertwind.$(OBJEXT) \
+ cdo-Verifygrid.$(OBJEXT) cdo-Wct.$(OBJEXT) cdo-Wind.$(OBJEXT) \
cdo-Writegrid.$(OBJEXT) cdo-Writerandom.$(OBJEXT) \
cdo-XTimstat.$(OBJEXT) cdo-YAR.$(OBJEXT) \
cdo-Yearmonstat.$(OBJEXT) cdo-Ydayarith.$(OBJEXT) \
@@ -308,7 +243,12 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
cdo-Yhourarith.$(OBJEXT) cdo-Yhourstat.$(OBJEXT) \
cdo-Ymonarith.$(OBJEXT) cdo-Ymonpctl.$(OBJEXT) \
cdo-Ymonstat.$(OBJEXT) cdo-Yseaspctl.$(OBJEXT) \
- cdo-Yseasstat.$(OBJEXT) cdo-Zonstat.$(OBJEXT) $(am__objects_1)
+ cdo-Yseasstat.$(OBJEXT) cdo-Zonstat.$(OBJEXT) \
+ cdo-Magplot.$(OBJEXT) cdo-Magvector.$(OBJEXT) \
+ cdo-Maggraph.$(OBJEXT) cdo-template_parser.$(OBJEXT) \
+ cdo-results_template_parser.$(OBJEXT) \
+ cdo-magics_template_parser.$(OBJEXT) \
+ cdo-StringUtilities.$(OBJEXT) cdo-CdoMagicsMapper.$(OBJEXT)
cdo_OBJECTS = $(am_cdo_OBJECTS)
cdo_DEPENDENCIES = libcdo.la $(top_builddir)/libcdi/src/libcdi.la
cdo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -355,8 +295,7 @@ am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libcdo_la_SOURCES) $(cdo_SOURCES) $(cdotest_SOURCES)
-DIST_SOURCES = $(libcdo_la_SOURCES) $(am__cdo_SOURCES_DIST) \
- $(cdotest_SOURCES)
+DIST_SOURCES = $(libcdo_la_SOURCES) $(cdo_SOURCES) $(cdotest_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -419,6 +358,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_CDI_LIB = @ENABLE_CDI_LIB@
ENABLE_CGRIBEX = @ENABLE_CGRIBEX@
+ENABLE_CXX = @ENABLE_CXX@
ENABLE_DATA = @ENABLE_DATA@
ENABLE_EXTRA = @ENABLE_EXTRA@
ENABLE_GRIB = @ENABLE_GRIB@
@@ -429,6 +369,7 @@ ENABLE_NC4 = @ENABLE_NC4@
ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
ENABLE_NETCDF = @ENABLE_NETCDF@
ENABLE_SERVICE = @ENABLE_SERVICE@
+ENABLE_THREADS = @ENABLE_THREADS@
EXEEXT = @EXEEXT@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
@@ -558,43 +499,52 @@ top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = libcdo.la
libcdo_la_SOURCES = cdo_int.h compare.h cdo_pthread.c cdo_vlist.c \
cdo_getopt.c cdo_getopt.h cdo_task.c cdo_task.h cdo_history.c \
- after_sptrans.c after_fctrans.c after_dvtrans.c \
+ cdi_uuid.h after_sptrans.c after_fctrans.c after_dvtrans.c \
after_vertint.c after_vertint.h after_namelist.c \
- afterburnerlib.c afterburner.h vct_l191.h constants.h \
- constants.c color.c color.h commandline.c const.h counter.h \
- datetime.c datetime.h dmemory.h ecacore.c ecacore.h ecautil.c \
- ecautil.h error.h etopo.h temp.h mask.h exception.c expr.c \
- expr.h expr_lex.c expr_yacc.c expr_yacc.h features.c field.c \
- field.h field2.c fieldc.c fieldmem.c fieldmer.c fieldzon.c \
- functs.h gradsdeslib.c gradsdeslib.h grid.c grid.h grid_area.c \
- grid_gme.c grid_lcc.c grid_rot.c gridreference.c griddes.c \
- griddes.h griddes_h5.c griddes_nc.c hetaeta.c hetaeta.h \
- institution.c interpol.c interpol.h job.c juldate.c \
- grid_search.c grid_search.h kvlist.c kvlist.h list.c list.h \
- merge_sort2.c merge_sort2.h modules.c modules.h namelist.c \
- namelist.h normal.c nth_element.c nth_element.h \
- operator_help.h par_io.c par_io.h percentiles_hist.c \
- percentiles_hist.h percentiles.c percentiles.h pipe.c pipe.h \
- pragma_omp_atomic_update.h printinfo.h process.c process.h \
- pstream.c pstream.h pstream_write.h pstream_int.h \
- pthread_debug.c pthread_debug.h readline.c realtime.c remap.h \
- remaplib.c remapsort.c remap_scrip_io.c remap_search_reg2d.c \
- remap_search_latbins.c remap_store_link.c remap_store_link.h \
- remap_store_link_cnsrv.c remap_store_link_cnsrv.h \
- remap_conserv.c remap_conserv_scrip.c remap_distwgt.c \
- remap_bicubic_scrip.c remap_bilinear_scrip.c stdnametable.c \
- stdnametable.h specspace.c specspace.h statistic.c statistic.h \
- table.c text.c text.h timebase.h timer.c userlog.c util.c \
- util.h zaxis.c kdtreelib/kdtree.h kdtreelib/kdtree_cartesian.c \
- kdtreelib/kdtree_common.c kdtreelib/kdtree_spherical.c \
- kdtreelib/pmergesort.c kdtreelib/pqueue.c kdtreelib/pqueue.h \
- clipping/clipping.c clipping/clipping.h clipping/area.c \
- clipping/area.h clipping/ensure_array_size.c \
- clipping/ensure_array_size.h clipping/geometry.h \
- clipping/grid.h clipping/points.h clipping/dep_list.h \
- clipping/grid_cell.c clipping/grid_cell.h \
+ afterburnerlib.c afterburner.h vct_l191.h calendar.h \
+ constants.h constants.c color.c color.h commandline.c const.h \
+ counter.h datetime.c datetime.h dmemory.h ecacore.c ecacore.h \
+ ecautil.c ecautil.h error.h etopo.h temp.h mask.h exception.c \
+ expr.c expr.h expr_fun.c expr_fun.h expr_lex.c expr_yacc.c \
+ expr_yacc.h features.c field.c field.h field2.c fieldc.c \
+ fieldmem.c fieldmer.c fieldzon.c functs.h gradsdeslib.c \
+ gradsdeslib.h grid.c grid.h grid_area.c grid_gme.c grid_lcc.c \
+ grid_rot.c gridreference.c griddes.c griddes.h griddes_h5.c \
+ griddes_nc.c hetaeta.c hetaeta.h institution.c interpol.c \
+ interpol.h job.c juldate.c grid_search.c grid_search.h \
+ kvlist.c kvlist.h list.c list.h merge_sort2.c merge_sort2.h \
+ modules.c modules.h namelist.c namelist.h normal.c \
+ nth_element.c nth_element.h operator_help.h par_io.c par_io.h \
+ percentiles_hist.c percentiles_hist.h percentiles.c \
+ percentiles.h pipe.c pipe.h pragma_omp_atomic_update.h \
+ printinfo.h process.c process.h pstream.c pstream.h \
+ pstream_write.h pstream_int.h pthread_debug.c pthread_debug.h \
+ readline.c realtime.c remap.h remaplib.c remapsort.c \
+ remap_scrip_io.c remap_search_reg2d.c remap_search_latbins.c \
+ remap_store_link.c remap_store_link.h remap_store_link_cnsrv.c \
+ remap_store_link_cnsrv.h remap_conserv.c remap_conserv_scrip.c \
+ remap_distwgt.c remap_bicubic_scrip.c remap_bilinear_scrip.c \
+ stdnametable.c stdnametable.h specspace.c specspace.h \
+ statistic.c statistic.h table.c text.c text.h timebase.h \
+ timer.c userlog.c util.c util.h zaxis.c kdtreelib/kdtree.h \
+ kdtreelib/kdtree_cartesian.c kdtreelib/kdtree_common.c \
+ kdtreelib/kdtree_spherical.c kdtreelib/pmergesort.c \
+ kdtreelib/pqueue.c kdtreelib/pqueue.h clipping/clipping.c \
+ clipping/clipping.h clipping/area.c clipping/area.h \
+ clipping/ensure_array_size.c clipping/ensure_array_size.h \
+ clipping/geometry.h clipping/grid.h clipping/points.h \
+ clipping/dep_list.h clipping/grid_cell.c clipping/grid_cell.h \
clipping/intersection.c clipping/utils.c clipping/utils.h
#
+#if ENABLE_NEARPT3
+#cdo_SOURCES += \
+# nearpt3x.h \
+# nearpt3c.h \
+# nearpt3c.cc \
+# cellsearchorder.h
+#endif
+
+#if ENABLE_MAGICS
cdo_SOURCES = cdo.c Adisit.c Afterburner.c Arith.c Arithc.c \
Arithdays.c Arithlat.c CDItest.c CDIread.c CDIwrite.c Cat.c \
Change.c Change_e5slm.c Cloudlayer.c CMOR.c Collgrid.c \
@@ -611,34 +561,39 @@ cdo_SOURCES = cdo.c Adisit.c Afterburner.c Arith.c Arithc.c \
Intyear.c Invert.c Invertlev.c Isosurface.c Kvl.c Log.c \
Maskbox.c Mastrfu.c Math.c Merge.c Mergegrid.c Mergetime.c \
Merstat.c Monarith.c Mrotuv.c Mrotuvb.c Ninfo.c Nmltest.c \
- Output.c Outputgmt.c Pack.c Pinfo.c Pressure.c Regres.c \
- Remap.c Remapeta.c Replace.c Replacevalues.c Rhopot.c Rotuv.c \
- Runpctl.c Runstat.c Seascount.c Seaspctl.c Seasstat.c Selbox.c \
- Select.c Seloperator.c Selrec.c Seltime.c Selvar.c Set.c \
- Setbox.c Setgatt.c Setgrid.c Sethalo.c Setmiss.c Setpartab.c \
- Setrcaname.c Settime.c Setzaxis.c Showinfo.c Sinfo.c Smooth9.c \
- Sort.c Sorttimestamp.c Specinfo.c Spectral.c Spectrum.c \
- Split.c Splitrec.c Splitsel.c Splittime.c Splityear.c SSOpar.c \
- Subtrend.c Tee.c Templates.c Test.c Tests.c Timcount.c \
- Timpctl.c Timselpctl.c Timselstat.c Timsort.c Timstat.c \
- Timstat2.c Timstat3.c Tinfo.c Tocomplex.c Transpose.c Trend.c \
- Trms.c Tstepcount.c Vardup.c Vargen.c Varrms.c Vertintml.c \
- Vertintap.c Vertstat.c Vertcum.c Vertwind.c Wct.c Wind.c \
- Writegrid.c Writerandom.c XTimstat.c YAR.c Yearmonstat.c \
- Ydayarith.c Ydaypctl.c Ydaystat.c Ydrunpctl.c Ydrunstat.c \
- Yhourarith.c Yhourstat.c Ymonarith.c Ymonpctl.c Ymonstat.c \
- Yseaspctl.c Yseasstat.c Zonstat.c cdo.h nearpt3c.h \
- $(am__append_1)
+ Output.c Outputgmt.c Pack.c Pardup.c Pinfo.c Pressure.c \
+ Regres.c Remap.c Remapeta.c Replace.c Replacevalues.c Rhopot.c \
+ Rotuv.c Runpctl.c Runstat.c Seascount.c Seaspctl.c Seasstat.c \
+ Selbox.c Select.c Seloperator.c Selrec.c Seltime.c Selvar.c \
+ Set.c Setbox.c Setgatt.c Setgrid.c Sethalo.c Setmiss.c \
+ Setpartab.c Setrcaname.c Settime.c Setzaxis.c Showinfo.c \
+ Sinfo.c Smooth9.c Sort.c Sorttimestamp.c Specinfo.c Spectral.c \
+ Spectrum.c Split.c Splitrec.c Splitsel.c Splittime.c \
+ Splityear.c SSOpar.c Subtrend.c Tee.c Templates.c Test.c \
+ Tests.c Timedt.c Timcount.c Timpctl.c Timselpctl.c \
+ Timselstat.c Timsort.c Timstat.c Timstat2.c Timstat3.c Tinfo.c \
+ Tocomplex.c Transpose.c Trend.c Trms.c Tstepcount.c Vargen.c \
+ Varrms.c Vertintml.c Vertintap.c Vertstat.c Vertcum.c \
+ Vertwind.c Verifygrid.c Wct.c Wind.c Writegrid.c Writerandom.c \
+ XTimstat.c YAR.c Yearmonstat.c Ydayarith.c Ydaypctl.c \
+ Ydaystat.c Ydrunpctl.c Ydrunstat.c Yhourarith.c Yhourstat.c \
+ Ymonarith.c Ymonpctl.c Ymonstat.c Yseaspctl.c Yseasstat.c \
+ Zonstat.c cdo.h nearpt3c.h Magplot.c Magvector.c Maggraph.c \
+ template_parser.h template_parser.c results_template_parser.h \
+ results_template_parser.c magics_template_parser.h \
+ magics_template_parser.c StringUtilities.h StringUtilities.c \
+ CdoMagicsMapper.h CdoMagicsMapper.c
+#endif
cdo_CPPFLAGS = -I$(top_srcdir)/libcdi/src
cdo_LDADD = libcdo.la $(top_builddir)/libcdi/src/libcdi.la
-cdo_LDFLAGS = $(am__append_2)
+cdo_LDFLAGS = $(am__append_1)
libcdo_la_CPPFLAGS = $(cdo_CPPFLAGS)
cdotest_SOURCES = cdo_int.h \
cdotest.c
cdotest_LDADD = $(cdo_LDADD)
cdotest_CPPFLAGS = $(cdo_CPPFLAGS)
-cdotest_LDFLAGS = $(cdo_LDFLAGS) $(am__append_3)
+cdotest_LDFLAGS = $(cdo_LDFLAGS) $(am__append_2)
#cdo-userlog.o: userlog.c config.h
# $(COMPILE) -DLOGPATH=${exec_prefix}/log -c -o cdo-userlog.o `test -f 'userlog.c' || echo '$(srcdir)/'`userlog.c
@@ -916,6 +871,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Output.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Outputgmt.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Pack.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Pardup.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Pinfo.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Pressure.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Regres.Po at am__quote@
@@ -967,6 +923,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Test.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Tests.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Timcount.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Timedt.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Timpctl.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Timselpctl.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Timselstat.Po at am__quote@
@@ -980,9 +937,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Trend.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Trms.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Tstepcount.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vardup.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vargen.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Varrms.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Verifygrid.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vertcum.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vertintap.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vertintml.Po at am__quote@
@@ -1032,6 +989,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-ecautil.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-exception.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-expr.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-expr_fun.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-expr_lex.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-expr_yacc.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-features.Plo at am__quote@
@@ -1263,6 +1221,13 @@ libcdo_la-expr.lo: expr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-expr.lo `test -f 'expr.c' || echo '$(srcdir)/'`expr.c
+libcdo_la-expr_fun.lo: expr_fun.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-expr_fun.lo -MD -MP -MF $(DEPDIR)/libcdo_la-expr_fun.Tpo -c -o libcdo_la-expr_fun.lo `test -f 'expr_fun.c' || echo '$(srcdir)/'`expr_fun.c
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-expr_fun.Tpo $(DEPDIR)/libcdo_la-expr_fun.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='expr_fun.c' object='libcdo_la-expr_fun.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-expr_fun.lo `test -f 'expr_fun.c' || echo '$(srcdir)/'`expr_fun.c
+
libcdo_la-expr_lex.lo: expr_lex.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-expr_lex.lo -MD -MP -MF $(DEPDIR)/libcdo_la-expr_lex.Tpo -c -o libcdo_la-expr_lex.lo `test -f 'expr_lex.c' || echo '$(srcdir)/'`expr_lex.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-expr_lex.Tpo $(DEPDIR)/libcdo_la-expr_lex.Plo
@@ -3062,6 +3027,20 @@ cdo-Pack.obj: Pack.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Pack.obj `if test -f 'Pack.c'; then $(CYGPATH_W) 'Pack.c'; else $(CYGPATH_W) '$(srcdir)/Pack.c'; fi`
+cdo-Pardup.o: Pardup.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Pardup.o -MD -MP -MF $(DEPDIR)/cdo-Pardup.Tpo -c -o cdo-Pardup.o `test -f 'Pardup.c' || echo '$(srcdir)/'`Pardup.c
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Pardup.Tpo $(DEPDIR)/cdo-Pardup.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Pardup.c' object='cdo-Pardup.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Pardup.o `test -f 'Pardup.c' || echo '$(srcdir)/'`Pardup.c
+
+cdo-Pardup.obj: Pardup.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Pardup.obj -MD -MP -MF $(DEPDIR)/cdo-Pardup.Tpo -c -o cdo-Pardup.obj `if test -f 'Pardup.c'; then $(CYGPATH_W) 'Pardup.c'; else $(CYGPATH_W) '$(srcdir)/Pardup.c'; fi`
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Pardup.Tpo $(DEPDIR)/cdo-Pardup.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Pardup.c' object='cdo-Pardup.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Pardup.obj `if test -f 'Pardup.c'; then $(CYGPATH_W) 'Pardup.c'; else $(CYGPATH_W) '$(srcdir)/Pardup.c'; fi`
+
cdo-Pinfo.o: Pinfo.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Pinfo.o -MD -MP -MF $(DEPDIR)/cdo-Pinfo.Tpo -c -o cdo-Pinfo.o `test -f 'Pinfo.c' || echo '$(srcdir)/'`Pinfo.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Pinfo.Tpo $(DEPDIR)/cdo-Pinfo.Po
@@ -3748,6 +3727,20 @@ cdo-Tests.obj: Tests.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Tests.obj `if test -f 'Tests.c'; then $(CYGPATH_W) 'Tests.c'; else $(CYGPATH_W) '$(srcdir)/Tests.c'; fi`
+cdo-Timedt.o: Timedt.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Timedt.o -MD -MP -MF $(DEPDIR)/cdo-Timedt.Tpo -c -o cdo-Timedt.o `test -f 'Timedt.c' || echo '$(srcdir)/'`Timedt.c
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Timedt.Tpo $(DEPDIR)/cdo-Timedt.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Timedt.c' object='cdo-Timedt.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Timedt.o `test -f 'Timedt.c' || echo '$(srcdir)/'`Timedt.c
+
+cdo-Timedt.obj: Timedt.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Timedt.obj -MD -MP -MF $(DEPDIR)/cdo-Timedt.Tpo -c -o cdo-Timedt.obj `if test -f 'Timedt.c'; then $(CYGPATH_W) 'Timedt.c'; else $(CYGPATH_W) '$(srcdir)/Timedt.c'; fi`
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Timedt.Tpo $(DEPDIR)/cdo-Timedt.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Timedt.c' object='cdo-Timedt.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Timedt.obj `if test -f 'Timedt.c'; then $(CYGPATH_W) 'Timedt.c'; else $(CYGPATH_W) '$(srcdir)/Timedt.c'; fi`
+
cdo-Timcount.o: Timcount.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Timcount.o -MD -MP -MF $(DEPDIR)/cdo-Timcount.Tpo -c -o cdo-Timcount.o `test -f 'Timcount.c' || echo '$(srcdir)/'`Timcount.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Timcount.Tpo $(DEPDIR)/cdo-Timcount.Po
@@ -3944,20 +3937,6 @@ cdo-Tstepcount.obj: Tstepcount.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Tstepcount.obj `if test -f 'Tstepcount.c'; then $(CYGPATH_W) 'Tstepcount.c'; else $(CYGPATH_W) '$(srcdir)/Tstepcount.c'; fi`
-cdo-Vardup.o: Vardup.c
- at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Vardup.o -MD -MP -MF $(DEPDIR)/cdo-Vardup.Tpo -c -o cdo-Vardup.o `test -f 'Vardup.c' || echo '$(srcdir)/'`Vardup.c
- at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Vardup.Tpo $(DEPDIR)/cdo-Vardup.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Vardup.c' object='cdo-Vardup.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Vardup.o `test -f 'Vardup.c' || echo '$(srcdir)/'`Vardup.c
-
-cdo-Vardup.obj: Vardup.c
- at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Vardup.obj -MD -MP -MF $(DEPDIR)/cdo-Vardup.Tpo -c -o cdo-Vardup.obj `if test -f 'Vardup.c'; then $(CYGPATH_W) 'Vardup.c'; else $(CYGPATH_W) '$(srcdir)/Vardup.c'; fi`
- at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Vardup.Tpo $(DEPDIR)/cdo-Vardup.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Vardup.c' object='cdo-Vardup.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Vardup.obj `if test -f 'Vardup.c'; then $(CYGPATH_W) 'Vardup.c'; else $(CYGPATH_W) '$(srcdir)/Vardup.c'; fi`
-
cdo-Vargen.o: Vargen.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Vargen.o -MD -MP -MF $(DEPDIR)/cdo-Vargen.Tpo -c -o cdo-Vargen.o `test -f 'Vargen.c' || echo '$(srcdir)/'`Vargen.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Vargen.Tpo $(DEPDIR)/cdo-Vargen.Po
@@ -4056,6 +4035,20 @@ cdo-Vertwind.obj: Vertwind.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Vertwind.obj `if test -f 'Vertwind.c'; then $(CYGPATH_W) 'Vertwind.c'; else $(CYGPATH_W) '$(srcdir)/Vertwind.c'; fi`
+cdo-Verifygrid.o: Verifygrid.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Verifygrid.o -MD -MP -MF $(DEPDIR)/cdo-Verifygrid.Tpo -c -o cdo-Verifygrid.o `test -f 'Verifygrid.c' || echo '$(srcdir)/'`Verifygrid.c
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Verifygrid.Tpo $(DEPDIR)/cdo-Verifygrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Verifygrid.c' object='cdo-Verifygrid.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Verifygrid.o `test -f 'Verifygrid.c' || echo '$(srcdir)/'`Verifygrid.c
+
+cdo-Verifygrid.obj: Verifygrid.c
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Verifygrid.obj -MD -MP -MF $(DEPDIR)/cdo-Verifygrid.Tpo -c -o cdo-Verifygrid.obj `if test -f 'Verifygrid.c'; then $(CYGPATH_W) 'Verifygrid.c'; else $(CYGPATH_W) '$(srcdir)/Verifygrid.c'; fi`
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Verifygrid.Tpo $(DEPDIR)/cdo-Verifygrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='Verifygrid.c' object='cdo-Verifygrid.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Verifygrid.obj `if test -f 'Verifygrid.c'; then $(CYGPATH_W) 'Verifygrid.c'; else $(CYGPATH_W) '$(srcdir)/Verifygrid.c'; fi`
+
cdo-Wct.o: Wct.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Wct.o -MD -MP -MF $(DEPDIR)/cdo-Wct.Tpo -c -o cdo-Wct.o `test -f 'Wct.c' || echo '$(srcdir)/'`Wct.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Wct.Tpo $(DEPDIR)/cdo-Wct.Po
diff --git a/src/Maskbox.c b/src/Maskbox.c
index ffd17eb..781c2ef 100644
--- a/src/Maskbox.c
+++ b/src/Maskbox.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Mastrfu.c b/src/Mastrfu.c
index e4dd31c..6ab75b8 100644
--- a/src/Mastrfu.c
+++ b/src/Mastrfu.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Math.c b/src/Math.c
index e7e1300..013432c 100644
--- a/src/Math.c
+++ b/src/Math.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -145,7 +145,7 @@ void *Math(void *argument)
break;
case SQRT:
for ( i = 0; i < gridsize; i++ )
- array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : SQRT(array1[i]);
+ array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : SQRTMN(array1[i]);
break;
case EXP:
for ( i = 0; i < gridsize; i++ )
diff --git a/src/Merge.c b/src/Merge.c
index 6bc4254..3f30447 100644
--- a/src/Merge.c
+++ b/src/Merge.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Mergegrid.c b/src/Mergegrid.c
index fdd5229..0b5963b 100644
--- a/src/Mergegrid.c
+++ b/src/Mergegrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Mergetime.c b/src/Mergetime.c
index bfc45d5..7b97a70 100644
--- a/src/Mergetime.c
+++ b/src/Mergetime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -37,13 +37,11 @@ void *Mergetime(void *argument)
int fileID;
int taxisID1, taxisID2 = CDI_UNDEFID;
int lcopy = FALSE;
- int gridsize;
int nmiss;
int vdate, vtime;
int last_vdate = -1, last_vtime = -1;
int next_fileID;
int skip_same_time = FALSE;
- int process_timestep;
double *array = NULL;
typedef struct
{
@@ -127,13 +125,13 @@ void *Mergetime(void *argument)
if ( ! lcopy )
{
- gridsize = vlistGridsizeMax(sf[0].vlistID);
+ size_t gridsize = vlistGridsizeMax(sf[0].vlistID);
array = (double*) Malloc(gridsize*sizeof(double));
}
while ( TRUE )
{
- process_timestep = TRUE;
+ bool process_timestep = true;
next_fileID = -1;
vdate = 0;
@@ -165,7 +163,7 @@ void *Mergetime(void *argument)
time2str(vtime, vtimestr, sizeof(vtimestr));
cdoPrint("Timestep %4d in stream %d (%s %s) already exists, skipped!",
sf[fileID].tsID+1, sf[fileID].streamID, vdatestr, vtimestr);
- process_timestep = FALSE;
+ process_timestep = false;
}
if ( process_timestep )
@@ -191,7 +189,12 @@ void *Mergetime(void *argument)
for ( recID = 0; recID < sf[fileID].nrecs; recID++ )
{
streamInqRecord(sf[fileID].streamID, &varID, &levelID);
- streamDefRecord(streamID2, varID, levelID);
+
+ if ( tsID2 > 0 && sf[fileID].tsID == 0 )
+ if ( vlistInqVarTsteptype(sf[fileID].vlistID, varID) == TSTEP_CONSTANT )
+ continue;
+
+ streamDefRecord(streamID2, varID, levelID);
if ( lcopy )
{
diff --git a/src/Merstat.c b/src/Merstat.c
index da85562..cab72a0 100644
--- a/src/Merstat.c
+++ b/src/Merstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Merstat mermean Meridional mean
Merstat meravg Meridional average
Merstat merstd Meridional standard deviation
- Merstat merstd Meridional standard deviation [Divisor is (n-1)]
+ Merstat merstd Meridional standard deviation [Normalize by (n-1)]
Merstat mervar Meridional variance
- Merstat mervar Meridional variance [Divisor is (n-1)]
+ Merstat mervar Meridional variance [Normalize by (n-1)]
Merstat merpctl Meridional percentiles
*/
@@ -43,6 +43,7 @@ void *Merstat(void *argument)
int gridID1, gridID2 = -1, lastgrid = -1;
int wstatus = FALSE;
int index;
+ int nmiss;
int recID, nrecs;
int varID, levelID;
int needWeights = FALSE;
@@ -140,8 +141,8 @@ void *Merstat(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
-
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
field1.grid = vlistInqVarGrid(vlistID1, varID);
if ( needWeights && field1.grid != lastgrid )
{
@@ -162,7 +163,7 @@ void *Merstat(void *argument)
merfun(field1, &field2, operfunc);
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, field2.ptr, field2.nmiss);
+ streamWriteRecord(streamID2, field2.ptr, (int)field2.nmiss);
}
tsID++;
}
diff --git a/src/Monarith.c b/src/Monarith.c
index 7014e11..1440e16 100644
--- a/src/Monarith.c
+++ b/src/Monarith.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -40,6 +40,7 @@ void *Monarith(void *argument)
int tsID, tsID2;
int varID, levelID;
int offset;
+ int nmiss;
int vlistID1, vlistID2, vlistID3;
int taxisID1, taxisID2, taxisID3;
int vdate;
@@ -140,8 +141,8 @@ void *Monarith(void *argument)
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
- streamReadRecord(streamID2, vardata2[varID]+offset, &field2.nmiss);
- varnmiss2[varID][levelID] = field2.nmiss;
+ streamReadRecord(streamID2, vardata2[varID]+offset, &nmiss);
+ varnmiss2[varID][levelID] = nmiss;
}
tsID2++;
@@ -154,23 +155,22 @@ void *Monarith(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
+ field1.grid = vlistInqVarGrid(vlistID1, varID);
+ field1.missval = vlistInqVarMissval(vlistID1, varID);
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
memcpy(field2.ptr, vardata2[varID]+offset, gridsize*sizeof(double));
- field2.nmiss = varnmiss2[varID][levelID];
-
- field1.grid = vlistInqVarGrid(vlistID1, varID);
- field1.missval = vlistInqVarMissval(vlistID1, varID);
-
+ field2.nmiss = varnmiss2[varID][levelID];
field2.grid = vlistInqVarGrid(vlistID2, varID);
field2.missval = vlistInqVarMissval(vlistID2, varID);
farfun(&field1, field2, operfunc);
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, (int)field1.nmiss);
}
tsID++;
diff --git a/src/Mrotuv.c b/src/Mrotuv.c
index 3a4b951..4042276 100644
--- a/src/Mrotuv.c
+++ b/src/Mrotuv.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Mrotuvb.c b/src/Mrotuvb.c
index 26f39c1..749c7df 100644
--- a/src/Mrotuvb.c
+++ b/src/Mrotuvb.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Ninfo.c b/src/Ninfo.c
index e70a62e..607c205 100644
--- a/src/Ninfo.c
+++ b/src/Ninfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Nmltest.c b/src/Nmltest.c
index efbfbcc..5294c84 100644
--- a/src/Nmltest.c
+++ b/src/Nmltest.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Output.c b/src/Output.c
index f346dda..4ddfdd8 100644
--- a/src/Output.c
+++ b/src/Output.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Outputgmt.c b/src/Outputgmt.c
index f78be18..75c3cb9 100644
--- a/src/Outputgmt.c
+++ b/src/Outputgmt.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,7 @@
/*
This module contains the following operators:
-*/
-/*
- Output center or bounderies for GMT plotting
-
- Plotting example:
+ Output field with grid cell center or cell bounds for plotting with GMT
- outputcenter
- outputbounds
@@ -44,108 +40,6 @@
double intlin(double x, double y1, double x1, double y2, double x2);
static
-int pnpoly(int npol, double *xp, double *yp, double x, double y)
-{
- int i, j, c = 0;
-
- for (i = 0, j = npol-1; i < npol; j = i++) {
- if ((((yp[i]<=y) && (y<yp[j])) ||
- ((yp[j]<=y) && (y<yp[i]))) &&
- (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
-
- c = !c;
- }
- return c;
-}
-
-
-static
-double PolygonArea_old(int np, double *xp, double *yp)
-{
- int i, j;
- double area = 0;
-
- for ( i = 0; i < np; i++ )
- {
- j = (i + 1) % np;
- area += xp[i] * yp[j];
- area -= yp[i] * xp[j];
- }
-
- area /= 2;
- /* return(area < 0 ? -area : area); */
- return (area);
-}
-
-
-static
-double PolygonArea(int np, double *xp, double *yp, double yc)
-{
- int i, j;
- double area = 0.;
-
- /* Process area in Radians */
-
- for ( i = 0; i < np; i++ )
- {
- j = (i + 1) % np;
- area += DEG2RAD*xp[i] * DEG2RAD*yp[j];
- area -= DEG2RAD*yp[i] * DEG2RAD*xp[j];
- }
- area *= 0.5 * cos(DEG2RAD*yc);
- return (area);
-}
-
-static
-int ccw(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y)
-{
- /*
- This function says wether the point are orientated clockwise
- +1 positive orientation
- -1 negative orientation
- 0 points are on a line --> no orientation
-
- This is done by a comparision of the gradient of
- dy1/dx1 = p1 - p0 vs.
- dy2/dx2 = p2 - p0
- To avoid singularities at dx1=0 OR dx2 = 0 we multiply with dx1*dx2
- */
- double dx1, dx2, dy1, dy2;
-
- dx1 = p1x - p0x; dy1 = p1y - p0y;
- dx2 = p2x - p0x; dy2 = p2y - p0y;
- if ( dx1*dy2 > dy1*dx2 ) return +1;
- if ( dx1*dy2 < dy1*dx2 ) return -1;
- if ( (dx1*dx2 < 0 ) || (dy1*dy2 < 0)) return -1;
- if ( (dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2)) return +1;
-
- return 0;
-}
-
-static
-int intersect(double pix, double piy, double pjx, double pjy,
- double pkx, double pky, double plx, double ply)
-{
- /*This function returns if there is an intersection between the lines
- line1 between pi and pj and
- line2 between pk and pl,
- whereas pi = (pix, piy).
-
- This can done by means of ccw since the product of ccw(pi,pj,pk)*ccw(pi,pj,pl)
- shows if pk and pl are on different or the same side(s) of the line1 (They must
- have different signums to be on different sides).
-
- Consequently if and ONLY IF pk as well as pl are on different sides of line1
- AND pi as well as pj are on different sides of line2 there HAS TO be an intersection.
- */
-
- return ( ( ccw(pix, piy, pjx, pjy, pkx, pky) *
- ccw(pix, piy, pjx, pjy, plx, ply) <= 0 ) &&
- ( ccw(pkx, pky, plx, ply, pix, piy) *
- ccw(pkx, pky, plx, ply, pjx, pjy) <= 0 ) );
-}
-
-static
int check_ncorner(int ncorner, const double *lon_bounds, const double *lat_bounds)
{
int ncorner_new = ncorner;
@@ -160,399 +54,6 @@ int check_ncorner(int ncorner, const double *lon_bounds, const double *lat_bound
return ncorner_new;
}
-static
-void verify_grid(int gridtype, int gridsize, int ncorner,
- double *grid_center_lon, double *grid_center_lat,
- double *grid_corner_lon, double *grid_corner_lat)
-{
- int i0, i, j, k, l;
- int l0;
- int nout;
- int isinside, convex, alone, isnegative;
- const int mnv = ncorner+1;
- int cuts[mnv][mnv];
- int *alone_cell;
- int check_corners;
- double lon, lat = 0;
- double lon_bounds[mnv], lat_bounds[mnv];
- double area, sumarea;
-
- alone_cell = (int*) Malloc(gridsize*ncorner*sizeof(int));
-
- check_corners = 0; /* don't execute corner checking (last loop) */
- nout = 0;
- sumarea = 0;
- /*
- for ( i = 0; i < gridsize; ++i )
- {
- lon = grid_center_lon[i];
- lat = grid_center_lat[i];
- for ( k = 0; k < ncorner; ++k )
- {
- lon_bounds[k] = grid_corner_lon[i*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i*ncorner+k];
- if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
- }
- lon_bounds[ncorner] = lon_bounds[0];
- lat_bounds[ncorner] = lat_bounds[0];
- fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i+1, lon, lat);
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
- fprintf(stdout, "\n");
- }
- */
-
- /* Check if center is inside bounds of cell */
- for ( i = 0; i < gridsize; ++i )
- {
- lon = grid_center_lon[i];
- lat = grid_center_lat[i];
-
- for ( k = 0; k < ncorner; ++k )
- {
- lon_bounds[k] = grid_corner_lon[i*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i*ncorner+k];
- if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
- }
- lon_bounds[ncorner] = lon_bounds[0];
- lat_bounds[ncorner] = lat_bounds[0];
-
- isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
-
- if ( !isinside ) nout++;
- if ( !isinside && cdoVerbose )
- {
- if ( nout == 1 )
- {
- fprintf(stdout,"\n CENTER IS OUT OF BOUNDS");
- fprintf(stdout,"\n :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " Corner %2i : ", k+1);
- fprintf(stdout,"\n Number Index center_lon center_lat area*10^6 :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k+1, k+1);
- fprintf(stdout, "\n");
- }
- area = PolygonArea(ncorner+1, lon_bounds, lat_bounds,lat);
- fprintf(stdout, " %6i %6i %9.4f %9.4f %9.5f :",
- nout, i+1, lon, lat, area*pow(10,6));
-
- int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
-
- for ( k = 0; k < ncorner_new; k++ )
- fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
- for ( k = ncorner_new; k < ncorner; k++ )
- fprintf(stdout, " ---- ---- : ");
- fprintf(stdout, "\n");
- }
- }
-
- if ( nout )
- cdoWarning("%d of %d points out of bounds!", nout, gridsize);
-
- /* check that all cell bounds have the same orientation */
-
- nout = 0;
- for ( i = 0; i < gridsize; ++i )
- {
- lon = grid_center_lon[i];
- lat = grid_center_lat[i];
-
- for ( k = 0; k < ncorner; ++k )
- {
- lon_bounds[k] = grid_corner_lon[i*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i*ncorner+k];
- if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
- }
- lon_bounds[ncorner] = lon_bounds[0];
- lat_bounds[ncorner] = lat_bounds[0];
-
- area = PolygonArea(ncorner+1, lon_bounds, lat_bounds, lat);
-
- isnegative = area < 0 ? 1 : 0;
- sumarea += area < 0 ? -area : area;
-
- if ( isnegative ) nout++;
-
- if ( isnegative && cdoVerbose )
- {
- if ( nout == 1 )
- {
- fprintf(stdout,"\n :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " Corner %2i : ", k+1);
- fprintf(stdout,"\n Number Index center_lon center_lat :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k+1, k+1);
- fprintf(stdout, "\n");
- }
- fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i+1, lon, lat);
-
- int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
-
- for ( k = 0; k < ncorner_new; k++ )
- fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
- for ( k = ncorner_new; k < ncorner; k++ )
- fprintf(stdout, " ---- ---- : ");
-
- fprintf(stdout, "\n");
- }
- }
-
- if ( nout )
- cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
-
- if ( cdoVerbose )
- fprintf(stdout, "area-error: %9.5f%%\n", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
-
- if ( fabs(100.*(sumarea - 4.*M_PI)/4.*M_PI) > 0.1)
- cdoWarning("area-error: %9.5f%%", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
-
- /* check that all cells are convex */
-
- nout = 0;
- for ( i0 = 0; i0 < gridsize; i0++ )
- {
- lon = grid_center_lon[i0];
- lat = grid_center_lat[i0];
-
- for ( k = 0; k < ncorner; k++ )
- {
- lon_bounds[k] = grid_corner_lon[i0*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i0*ncorner+k];
- /* Find cells that cover left and right border of the grid and adjust
- coordinates --> they become closed polygons on theta-phi plane! */
- if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
- }
-
- /* Reset found cuts for the current cell before starting the search */
- for ( i = 0; i < ncorner; i++ )
- for ( j = 0; j < ncorner; j++ )
- cuts[i][j] = 0;
-
- /* Loops cover all combinations between inner lines of the Polygon
- Check whether each inner line is cut by an other (inner) one at least once.
- - Only if there is a cut every inner line the Polygon is convex
- - We assume: Points are in either cyclic or anticyclic order
- */
- for ( i = 0; i < ncorner-1; i++ )
- {
- /* j = i+2 excludes lines from one corner to an other (j=i+1) and
- from one point to itself (j=i)*/
- for ( j = i+2 ; j < ncorner; j++ )
- {
- /* Exclude the line between the last and first corner */
- if ( i == 0 && j == ncorner-1 ) continue;
-
- /* k = i+1: if starting point is in common lines to different corners
- do not intersect */
- for ( k = i+1; k < ncorner - 1; k++ )
- {
- if ( i == k ) l0 = j+1;
- else l0 = k+2;
-
- for ( l = l0; l < ncorner; l++ )
- {
- if ( cuts[k][l] && cuts[i][j] ) continue;
- /* Exlude the line between the last and first corner
- Exlude the line itself (l!=i, k!=j)
- Check if line ij and kl intersect each other.
- If so increment respective counters for intersections.
- It is not relevant by which line a line is intersected -
- it is only relevant if they is itersected! */
- if ( ! ( k==0 && l == ncorner-1 ) && ( l != j ) && ( k != j ) )
- {
- if ( intersect(lon_bounds[i], lat_bounds[i], lon_bounds[j], lat_bounds[j],
- lon_bounds[k], lat_bounds[k], lon_bounds[l], lat_bounds[l]) )
- {
- cuts[i][j]++; cuts[k][l]++; cuts[j][i]++; cuts[l][k]++;
- }
- }
- }
- }
- }
- }
-
- convex = 1;
- /* The following loop covers all inner lines of the Polygon
- (The assumption applies that the points are in cyclic order) */
- for ( i = 0; i < ncorner-1; i++ )
- for ( j = i+2; j < ncorner; j++)
- {
- if ( i == 0 && j == ncorner-1 ) continue;
- if ( ! cuts[i][j] ) convex = 0;
- }
- if ( !convex ) nout++;
- if ( cdoVerbose && ( !convex ) )
- {
- if ( nout == 1 )
- {
- fprintf(stdout,"\n NO CONVEX POLYGON");
- fprintf(stdout,"\n :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " Corner %2i : ", k);
- fprintf(stdout,"\n Number Index center_lon center_lat :");
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k, k);
- fprintf(stdout, "\n");
- }
-
- fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i0+1, lon, lat);
- for ( k = 0; k < ncorner; k++ )
- fprintf(stdout, " %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
- fprintf(stdout, "\n");
- }
- }
-
- if ( nout )
- cdoWarning("%d of %d cells are not Convex!", nout, gridsize);
-
- if ( check_corners )
- {
- /*
- Check if there is a corner at the same point of
- an other cell foreach corner of each cell
- */
- nout = 0;
- for ( i = 0; i < gridsize*ncorner; i++ )
- alone_cell[i] = 1;
-
- for ( i = 0; i < gridsize*ncorner; i++ )
- {
- if ( ! alone_cell[i] ) continue;
- alone = 1;
- lon = grid_corner_lon[i];
- lat = grid_corner_lat[i];
- for ( j = 0; j < gridsize*ncorner; j++ )
- if ( j != i &&
- IS_EQUAL(grid_corner_lat[j], lat) &&
- IS_EQUAL(grid_corner_lon[j], lon) )
- { alone = 0; alone_cell[i] = alone_cell[j] = 1; break; }
- if ( alone )
- {
- if ( lon >= 180. ) lon -= 360.;
- else if ( lon < 180. ) lon += 360.;
- for ( j = i+1; j < gridsize*ncorner; j++ )
- if (j != i &&
- IS_EQUAL(grid_corner_lat[j], lat) &&
- IS_EQUAL(grid_corner_lon[j], lon) )
- { alone = 0; alone_cell[i] = alone_cell[j] = 0; break; }
- }
- if ( alone )
- {
- nout++;
- if ( cdoVerbose )
- {
- if ( nout == 1 )
- {
- fprintf(stdout,"\n VERTEX ALONE ON GRID\n");
- fprintf(stdout," number cell-Index Vert-Index : lon lat\n");
- }
- fprintf(stdout, " %6i %6i %6i : %10.4f %10.4f\n",
- nout, i/ncorner, i, grid_corner_lon[i], grid_corner_lat[i]);
- }
- }
- }
-
- if ( nout )
- cdoWarning("%d of %d corners are lonely on the grid!", nout, gridsize*ncorner);
- }
-
- Free(alone_cell);
-}
-
-
-void verify_grid_old(int gridtype, int gridsize, int ncorner,
- double *grid_center_lon, double *grid_center_lat,
- double *grid_corner_lon, double *grid_corner_lat)
-{
- int i, k;
- int nout;
- int isinside;
- int isnegative;
- double area;
- double lon, lat;
- double lon_bounds[ncorner], lat_bounds[ncorner];
-
- /* check that all centers are inside the bounds */
-
- nout = 0;
- for ( i = 0; i < gridsize; ++i )
- {
- lon = grid_center_lon[i];
- lat = grid_center_lat[i];
-
- for ( k = 0; k < ncorner; ++k )
- {
- lon_bounds[k] = grid_corner_lon[i*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i*ncorner+k];
- }
-
- for ( k = 0; k < ncorner; ++k )
- {
- if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
- }
-
- lon_bounds[ncorner] = lon_bounds[0];
- lat_bounds[ncorner] = lat_bounds[0];
-
- isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
-
- if ( !isinside ) nout++;
-
- if ( !isinside && cdoVerbose )
- printf("center: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
- lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
- }
-
- if ( nout > 0 )
- cdoWarning("%d of %d points out of bounds!", nout, gridsize);
-
-
- /* check that all cell bounds have the same orientation */
-
- nout = 0;
- for ( i = 0; i < gridsize; ++i )
- {
- lon = grid_center_lon[i];
- lat = grid_center_lat[i];
-
- for ( k = 0; k < ncorner; ++k )
- {
- lon_bounds[k] = grid_corner_lon[i*ncorner+k];
- lat_bounds[k] = grid_corner_lat[i*ncorner+k];
- }
-
- for ( k = 0; k < ncorner; ++k )
- {
- if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
- if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
- }
-
- lon_bounds[ncorner] = lon_bounds[0];
- lat_bounds[ncorner] = lat_bounds[0];
-
- area = PolygonArea_old(ncorner+1, lon_bounds, lat_bounds);
-
- if ( area < 0 ) isnegative = 1;
- else isnegative = 0;
-
- if ( isnegative ) nout++;
-
- if ( isnegative && cdoVerbose )
- printf("bounds: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
- lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
- }
-
- if ( nout > 0 )
- cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
-}
-
void make_cyclic(double *array1, double *array2, int nlon, int nlat)
{
@@ -576,65 +77,167 @@ void make_cyclic(double *array1, double *array2, int nlon, int nlat)
}
}
+static
+void array_stat(int ngp, double *restrict array, double missval, double *minval, double *maxval, double *meanval)
+{
+ double rmin = DBL_MAX;
+ double rmax = -DBL_MAX;
+ double rmean = 0;
+
+ int nvals = 0;
+ for ( int i = 0; i < ngp; i++ )
+ {
+ if ( !DBL_IS_EQUAL(array[i], missval) )
+ {
+ if ( array[i] < rmin ) rmin = array[i];
+ if ( array[i] > rmax ) rmax = array[i];
+ rmean += array[i];
+ nvals++;
+ }
+ }
+
+ if ( IS_EQUAL(rmin, DBL_MAX) ) rmin = missval;
+ if ( IS_EQUAL(rmax, -DBL_MAX) ) rmax = missval;
+
+ if ( nvals ) rmean /= nvals;
+ else rmean = missval;
+
+ *minval = rmin;
+ *maxval = rmax;
+ *meanval = rmean;
+}
+
+static
+void output_vrml(int nlon, int nlat, int ngp, double *restrict array, double missval, CPT *cpt)
+{
+ double minval, maxval, meanval;
+ array_stat(ngp, array, missval, &minval, &maxval, &meanval);
+
+ double dx = 10./nlon;
+
+ printf("Viewpoint {\n");
+ printf(" description \"viewpoint1\"\n");
+ printf(" orientation 0 0 1 0\n");
+ printf(" position 0.0 0.0 10.0\n");
+ printf("}\n");
+ printf("\n");
+ printf("Background {\n");
+ printf(" skyColor [\n");
+ printf(" 0.0 0.1 0.8,\n");
+ printf(" 0.0 0.5 1.0,\n");
+ printf(" 1.0 1.0 1.0\n");
+ printf(" ]\n");
+ printf(" skyAngle [0.785, 1.571]\n");
+ printf("\n");
+ printf(" groundColor [\n");
+ printf(" 0.0 0.0 0.0,\n");
+ printf(" 0.3 0.3 0.3,\n");
+ printf(" 0.5 0.5 0.5\n");
+ printf(" ]\n");
+ printf(" groundAngle [0.785, 1.571]\n");
+ printf("}\n");
+ printf("\n");
+ printf("Transform {\n");
+ printf(" children [\n");
+ printf(" Shape {\n");
+ printf(" appearance Appearance {\n");
+ printf(" material Material {}\n");
+ printf(" }\n");
+ printf(" geometry ElevationGrid {\n");
+ printf(" colorPerVertex TRUE\n");
+ printf(" solid FALSE\n");
+ printf(" xDimension %d\n", nlon);
+ printf(" zDimension %d\n", nlat);
+ printf(" xSpacing %g\n", dx);
+ printf(" zSpacing %g\n", dx);
+ printf(" color Color {\n");
+ printf(" color [\n");
+ for ( int j = nlat-1; j >= 0 ; --j )
+ for ( int i = 0; i < nlon; ++i )
+ {
+ int r = 0, g = 0, b = 0;
+ double val = array[j*nlon+i];
+
+ if ( !DBL_IS_EQUAL(val, missval) )
+ {
+ int n;
+ for ( n = 0; n < cpt->ncolors; n++ )
+ if ( val > cpt->lut[n].z_low && val <= cpt->lut[n].z_high ) break;
+
+ if ( n == cpt->ncolors )
+ {
+ r = cpt->bfn[0].rgb[0]; g = cpt->bfn[0].rgb[1]; b = cpt->bfn[0].rgb[2];
+ }
+ else
+ {
+ // r = cpt->lut[n].rgb_high[0]; g = cpt->lut[n].rgb_high[1]; b = cpt->lut[n].rgb_high[2];
+ r = intlin(val, cpt->lut[n].rgb_low[0], cpt->lut[n].z_low, cpt->lut[n].rgb_high[0], cpt->lut[n].z_high);
+ g = intlin(val, cpt->lut[n].rgb_low[1], cpt->lut[n].z_low, cpt->lut[n].rgb_high[1], cpt->lut[n].z_high);
+ b = intlin(val, cpt->lut[n].rgb_low[2], cpt->lut[n].z_low, cpt->lut[n].rgb_high[2], cpt->lut[n].z_high);
+ }
+ }
+ else
+ {
+ r = cpt->bfn[2].rgb[0]; g = cpt->bfn[2].rgb[1]; b = cpt->bfn[2].rgb[2];
+ }
+ printf(" %.3g %.3g %.3g,\n", r/255., g/255., b/255.);
+ }
+ printf(" ]\n");
+ printf(" }\n");
+ printf(" height [\n");
+
+ for ( int j = nlat-1; j >= 0 ; --j )
+ for ( int i = 0; i < nlon; ++i )
+ printf("%g,\n", array[j*nlon+i]);
+
+ printf(" ]\n");
+ printf(" }\n");
+ printf(" }\n");
+ printf(" ]\n");
+ printf(" translation -5 0 %g\n", -5.*nlat/nlon);
+ printf(" rotation 0.0 0.0 0.0 0.0\n");
+ printf(" scale 1.0 %g 1.0\n", 0.5/(maxval-minval));
+ printf("}\n");
+}
+
void *Outputgmt(void *argument)
{
- int GRIDVERIFY, OUTPUTCENTER, OUTPUTCENTER2, OUTPUTCENTERCPT, OUTPUTBOUNDS;
- int OUTPUTBOUNDSCPT, OUTPUTVECTOR, OUTPUTTRI, OUTPUTVRML;
- int operatorID;
- int process_data = TRUE;
int i, j;
- int varID0, varID, recID;
- int nvals;
- int gridsize = 0;
+ int varID0, recID;
int gridsize2 = 0;
- int gridID, code;
int nrecs;
int levelID;
- int tsID;
- int streamID = 0;
- int vlistID;
int nmiss;
- int nlon, nlat, nalloc;
- int nlev, lzon = FALSE, lmer = FALSE, lhov = FALSE;
+ int lzon = FALSE, lmer = FALSE, lhov = FALSE;
int ncorner = 0, ic;
int status;
int lgrid_gen_bounds = FALSE, luse_grid_corner = FALSE;
- int zaxisID, taxisID;
int ninc = 1;
- int vdate, vtime;
char varname[CDI_MAX_NAME];
double level;
- double missval;
- double *array = NULL;
double *array2 = NULL;
- double *parray;
double *uf = NULL, *vf = NULL, *alpha = NULL, *auv = NULL;
- double *grid_center_lat = NULL, *grid_center_lon = NULL;
double *grid_center_lat2 = NULL, *grid_center_lon2 = NULL;
double *grid_corner_lat = NULL, *grid_corner_lon = NULL;
- double *plat, *plon;
- double *zaxis_center_lev, *zaxis_lower_lev, *zaxis_upper_lev;
int *grid_mask = NULL;
FILE *cpt_fp;
CPT cpt;
- int grid_is_circular;
char units[CDI_MAX_NAME];
char vdatestr[32], vtimestr[32];
cdoInitialize(argument);
- GRIDVERIFY = cdoOperatorAdd("gridverify", 0, 0, NULL);
- OUTPUTCENTER = cdoOperatorAdd("outputcenter", 0, 0, NULL);
- OUTPUTCENTER2 = cdoOperatorAdd("outputcenter2", 0, 0, NULL);
- OUTPUTCENTERCPT = cdoOperatorAdd("outputcentercpt", 0, 0, NULL);
- OUTPUTBOUNDS = cdoOperatorAdd("outputbounds", 0, 0, NULL);
- OUTPUTBOUNDSCPT = cdoOperatorAdd("outputboundscpt", 0, 0, NULL);
- OUTPUTVECTOR = cdoOperatorAdd("outputvector", 0, 0, NULL);
- OUTPUTTRI = cdoOperatorAdd("outputtri", 0, 0, NULL);
- OUTPUTVRML = cdoOperatorAdd("outputvrml", 0, 0, NULL);
+ int OUTPUTCENTER = cdoOperatorAdd("gmtxyz", 0, 0, NULL);
+ int OUTPUTCENTER2 = cdoOperatorAdd("outputcenter2", 0, 0, NULL);
+ int OUTPUTCENTERCPT = cdoOperatorAdd("outputcentercpt", 0, 0, NULL);
+ int OUTPUTBOUNDS = cdoOperatorAdd("gmtcells", 0, 0, NULL);
+ int OUTPUTBOUNDSCPT = cdoOperatorAdd("outputboundscpt", 0, 0, NULL);
+ int OUTPUTVECTOR = cdoOperatorAdd("outputvector", 0, 0, NULL);
+ int OUTPUTTRI = cdoOperatorAdd("outputtri", 0, 0, NULL);
+ int OUTPUTVRML = cdoOperatorAdd("outputvrml", 0, 0, NULL);
- operatorID = cdoOperatorID();
+ int operatorID = cdoOperatorID();
if ( operatorID == OUTPUTVECTOR )
{
@@ -644,20 +247,13 @@ void *Outputgmt(void *argument)
if ( ninc < 1 ) cdoAbort("Increment must be greater than 0!");
}
- if ( operatorID == GRIDVERIFY )
- {
- process_data = FALSE;
- luse_grid_corner = TRUE;
- }
-
if ( operatorID == OUTPUTBOUNDS || operatorID == OUTPUTBOUNDSCPT )
luse_grid_corner = TRUE;
if ( operatorID == OUTPUTCENTERCPT || operatorID == OUTPUTBOUNDSCPT || operatorID == OUTPUTVRML )
{
- char *cpt_file;
-
- cpt_file = operatorArgv()[0];
+ operatorCheckArgc(1);
+ char *cpt_file = operatorArgv()[0];
if ( (cpt_fp = fopen (cpt_file, "r")) == NULL )
cdoAbort("Open failed on color palette table %s", cpt_file);
@@ -669,17 +265,17 @@ void *Outputgmt(void *argument)
if ( cdoVerbose ) cptWrite(stderr, cpt);
}
- streamID = streamOpenRead(cdoStreamName(0));
+ int streamID = streamOpenRead(cdoStreamName(0));
- vlistID = streamInqVlist(streamID);
- taxisID = vlistInqTaxis(vlistID);
+ int vlistID = streamInqVlist(streamID);
+ int taxisID = vlistInqTaxis(vlistID);
- varID = 0;
+ int varID = 0;
vlistInqVarName(vlistID, varID, varname);
- code = vlistInqVarCode(vlistID, varID);
- gridID = vlistInqVarGrid(vlistID, varID);
- zaxisID = vlistInqVarZaxis(vlistID, varID);
- missval = vlistInqVarMissval(vlistID, varID);
+ int code = vlistInqVarCode(vlistID, varID);
+ int gridID = vlistInqVarGrid(vlistID, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID, varID);
+ double missval = vlistInqVarMissval(vlistID, varID);
if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 1);
@@ -689,10 +285,10 @@ void *Outputgmt(void *argument)
lgrid_gen_bounds = TRUE;
}
- gridsize = gridInqSize(gridID);
- nlon = gridInqXsize(gridID);
- nlat = gridInqYsize(gridID);
- nlev = zaxisInqSize(zaxisID);
+ int gridsize = gridInqSize(gridID);
+ int nlon = gridInqXsize(gridID);
+ int nlat = gridInqYsize(gridID);
+ int nlev = zaxisInqSize(zaxisID);
if ( gridInqMaskGME(gridID, NULL) )
{
@@ -732,10 +328,10 @@ void *Outputgmt(void *argument)
else
ncorner = 4;
- grid_is_circular = gridIsCircular(gridID);
+ int grid_is_circular = gridIsCircular(gridID);
- grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
gridInqYvals(gridID, grid_center_lat);
gridInqXvals(gridID, grid_center_lon);
@@ -746,9 +342,9 @@ void *Outputgmt(void *argument)
gridInqYunits(gridID, units);
grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
- nvals = gridsize;
- plon = grid_center_lon;
- plat = grid_center_lat;
+ int nvals = gridsize;
+ double *plon = grid_center_lon;
+ double *plat = grid_center_lat;
if ( operatorID == OUTPUTCENTER2 && grid_is_circular )
{
@@ -773,16 +369,16 @@ void *Outputgmt(void *argument)
plat = grid_center_lat2;
}
- zaxis_center_lev = (double*) Malloc(nlev*sizeof(double));
- zaxis_lower_lev = (double*) Malloc(nlev*sizeof(double));
- zaxis_upper_lev = (double*) Malloc(nlev*sizeof(double));
+ double *zaxis_center_lev = (double*) Malloc(nlev*sizeof(double));
+ double *zaxis_lower_lev = (double*) Malloc(nlev*sizeof(double));
+ double *zaxis_upper_lev = (double*) Malloc(nlev*sizeof(double));
zaxisInqLevels(zaxisID, zaxis_center_lev);
if ( luse_grid_corner )
{
if ( ncorner == 0 ) cdoAbort("grid corner missing!");
- nalloc = ncorner*gridsize;
+ int nalloc = ncorner*gridsize;
grid_corner_lat = (double*) Realloc(grid_corner_lat, nalloc*sizeof(double));
grid_corner_lon = (double*) Realloc(grid_corner_lon, nalloc*sizeof(double));
@@ -828,13 +424,13 @@ void *Outputgmt(void *argument)
if ( cdoVerbose )
for ( i = 0; i < nlev; ++i )
- printf("level: %d %g %g %g\n",
+ fprintf(stderr, "level: %d %g %g %g\n",
i+1, zaxis_lower_lev[i], zaxis_center_lev[i], zaxis_upper_lev[i]);
}
}
- array = (double*) Malloc(gridsize*sizeof(double));
- parray = array;
+ double *array = (double*) Malloc(gridsize*sizeof(double));
+ double *parray = array;
if ( operatorID == OUTPUTCENTER2 && grid_is_circular )
{
@@ -850,17 +446,11 @@ void *Outputgmt(void *argument)
auv = (double*) Malloc(gridsize*sizeof(double));
}
- if ( operatorID == GRIDVERIFY )
- verify_grid(gridInqType(gridID), gridsize, ncorner,
- grid_center_lon, grid_center_lat,
- grid_corner_lon, grid_corner_lat);
-
- tsID = 0;
- if ( process_data )
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID, tsID)) )
{
- vdate = taxisInqVdate(taxisID);
- vtime = taxisInqVtime(taxisID);
+ int vdate = taxisInqVdate(taxisID);
+ int vtime = taxisInqVtime(taxisID);
date2str(vdate, vdatestr, sizeof(vdatestr));
time2str(vtime, vtimestr, sizeof(vtimestr));
@@ -914,35 +504,21 @@ void *Outputgmt(void *argument)
if ( operatorID == OUTPUTCENTER || operatorID == OUTPUTCENTER2 || operatorID == OUTPUTCENTERCPT )
{
+ if ( cdoVerbose )
+ {
+ double minval, maxval, meanval;
+ array_stat(gridsize, array, missval, &minval, &maxval, &meanval);
+ double range = maxval - minval;
+ fprintf(stderr, "makecpt -T%g/%g/%g -Crainbow > gmt.cpt\n", minval, maxval, range/20);
+ fprintf(stderr, "pscontour -K -JQ0/10i -Rd -I -Cgmt.cpt data.gmt > gmtplot.ps\n");
+ fprintf(stderr, "pscoast -O -J -R -Dc -W -B40g20 >> gmtplot.ps\n");
+ }
+
for ( i = 0; i < nvals; i++ )
{
if ( grid_mask )
if ( grid_mask[i] == 0 ) continue;
- if ( operatorID == OUTPUTCENTERCPT )
- {
- int r = 0, g = 0, b = 0, n;
-
- if ( !DBL_IS_EQUAL(array[i], missval) )
- {
- for ( n = 0; n < cpt.ncolors; n++ )
- if ( array[i] > cpt.lut[n].z_low && array[i] <= cpt.lut[n].z_high ) break;
-
- if ( n == cpt.ncolors )
- {
- r = cpt.bfn[0].rgb[0]; g = cpt.bfn[0].rgb[1]; b = cpt.bfn[0].rgb[2];
- }
- else
- {
- r = cpt.lut[n].rgb_high[0]; g = cpt.lut[n].rgb_high[1]; b = cpt.lut[n].rgb_high[2];
- }
- }
- else
- {
- r = cpt.bfn[2].rgb[0]; g = cpt.bfn[2].rgb[1]; b = cpt.bfn[2].rgb[2];
- }
- }
-
if ( operatorID == OUTPUTCENTER )
{
if ( lzon )
@@ -972,7 +548,7 @@ void *Outputgmt(void *argument)
}
else if ( operatorID == OUTPUTTRI )
{
- int ij, c1, c2, c3;
+ int c1, c2, c3;
int mlon, ip1;
if ( gridInqType(gridID) != GRID_CURVILINEAR ) cdoAbort("Unsupported grid!");
@@ -984,7 +560,6 @@ void *Outputgmt(void *argument)
{
ip1 = i+1;
if ( i == nlon-1 ) ip1 = 0;
- ij = j*nlon+i;
c1 = (j)*nlon+ip1;
c2 = (j)*nlon+i;
c3 = (j+1)*nlon+i;
@@ -1028,111 +603,26 @@ void *Outputgmt(void *argument)
}
else if ( operatorID == OUTPUTVRML )
{
- double minval = 1e33;
- double maxval = -1e33;
- double meanval = 0;
- for ( i = 0; i < gridsize; i++ )
- {
- if ( array[i] < minval ) minval = array[i];
- if ( array[i] > maxval ) maxval = array[i];
- meanval += array[i];
- }
- meanval /= gridsize;
-
- double dx = 10./nlon;
-
- printf("Viewpoint {\n");
- printf(" description \"viewpoint1\"\n");
- printf(" orientation 0 0 1 0\n");
- printf(" position 0.0 0.0 10.0\n");
- printf("}\n");
- printf("\n");
- printf("Background {\n");
- printf(" skyColor [\n");
- printf(" 0.0 0.1 0.8,\n");
- printf(" 0.0 0.5 1.0,\n");
- printf(" 1.0 1.0 1.0\n");
- printf(" ]\n");
- printf(" skyAngle [0.785, 1.571]\n");
- printf("\n");
- printf(" groundColor [\n");
- printf(" 0.0 0.0 0.0,\n");
- printf(" 0.3 0.3 0.3,\n");
- printf(" 0.5 0.5 0.5\n");
- printf(" ]\n");
- printf(" groundAngle [0.785, 1.571]\n");
- printf("}\n");
- printf("\n");
- printf("Transform {\n");
- printf(" children [\n");
- printf(" Shape {\n");
- printf(" appearance Appearance {\n");
- printf(" material Material {}\n");
- printf(" }\n");
- printf(" geometry ElevationGrid {\n");
- printf(" colorPerVertex TRUE\n");
- printf(" solid FALSE\n");
- printf(" xDimension %d\n", nlon);
- printf(" zDimension %d\n", nlat);
- printf(" xSpacing %g\n", dx);
- printf(" zSpacing %g\n", dx);
- printf(" color Color {\n");
- printf(" color [\n");
- for ( j = nlat-1; j >= 0 ; --j )
- for ( i = 0; i < nlon; ++i )
- {
- int r = 0, g = 0, b = 0, n;
- double val = array[j*nlon+i];
-
- if ( !DBL_IS_EQUAL(val, missval) )
- {
- for ( n = 0; n < cpt.ncolors; n++ )
- if ( val > cpt.lut[n].z_low && val <= cpt.lut[n].z_high ) break;
-
- if ( n == cpt.ncolors )
- {
- r = cpt.bfn[0].rgb[0]; g = cpt.bfn[0].rgb[1]; b = cpt.bfn[0].rgb[2];
- }
- else
- {
- // r = cpt.lut[n].rgb_high[0]; g = cpt.lut[n].rgb_high[1]; b = cpt.lut[n].rgb_high[2];
- r = intlin(val, cpt.lut[n].rgb_low[0], cpt.lut[n].z_low, cpt.lut[n].rgb_high[0], cpt.lut[n].z_high);
- g = intlin(val, cpt.lut[n].rgb_low[1], cpt.lut[n].z_low, cpt.lut[n].rgb_high[1], cpt.lut[n].z_high);
- b = intlin(val, cpt.lut[n].rgb_low[2], cpt.lut[n].z_low, cpt.lut[n].rgb_high[2], cpt.lut[n].z_high);
- }
- }
- else
- {
- r = cpt.bfn[2].rgb[0]; g = cpt.bfn[2].rgb[1]; b = cpt.bfn[2].rgb[2];
- }
- printf(" %.3g %.3g %.3g,\n", r/255., g/255., b/255.);
- }
- printf(" ]\n");
- printf(" }\n");
- printf(" height [\n");
- // for ( j = 0; j < nlat; ++j )
- for ( j = nlat-1; j >= 0 ; --j )
- {
- for ( i = 0; i < nlon; ++i )
- {
- printf("%g,\n", array[j*nlon+i]);
- }
- }
- printf(" ]\n");
- printf(" }\n");
- printf(" }\n");
- printf(" ]\n");
- printf(" translation -5 0 %g\n", -5.*nlat/nlon);
- printf(" rotation 0.0 0.0 0.0 0.0\n");
- printf(" scale 1.0 %g 1.0\n", 0.5/(maxval-minval));
- printf("}\n");
+ output_vrml(nlon, nlat, gridsize, array, missval, &cpt);
}
else if ( operatorID == OUTPUTBOUNDS || operatorID == OUTPUTBOUNDSCPT )
{
+ if ( cdoVerbose )
+ {
+ double minval, maxval, meanval;
+ array_stat(gridsize, array, missval, &minval, &maxval, &meanval);
+ double range = maxval - minval;
+ fprintf(stderr, "makecpt -T%g/%g/%g -Crainbow > gmt.cpt\n", minval, maxval, range/20);
+ fprintf(stderr, "psxy -K -JQ0/10i -Rd -L -Cgmt.cpt -m data.gmt > gmtplot.ps\n");
+ // fprintf(stderr, "psxy -K -Jx0.028id -Rd -L -Cgmt.cpt -m data.gmt > gmtplot.ps\n");
+ // fprintf(stderr, "psxy -K -JN0/10i -Rd -L -Cgmt.cpt -m data.gmt > gmtplot.ps\n");
+ fprintf(stderr, "pscoast -O -J -R -Dc -W -B40g20 >> gmtplot.ps\n");
+ fprintf(stderr, "ps2pdf gmtplot.ps\n");
+ }
+
for ( i = 0; i < gridsize; i++ )
{
- if ( grid_mask )
- if ( grid_mask[i] == 0 ) continue;
+ if ( grid_mask && grid_mask[i] == 0 ) continue;
if ( !DBL_IS_EQUAL(array[i], missval) )
fprintf(stdout, "> -Z%g", array[i]);
@@ -1172,8 +662,8 @@ void *Outputgmt(void *argument)
double xlev[4], xlat[4];
double levmin = zaxis_lower_lev[levelID];
double levmax = zaxis_upper_lev[levelID];
- double latmin = grid_corner_lat[i*4+0];
- double latmax = grid_corner_lat[i*4+0];
+ double latmin = grid_corner_lat[i*4];
+ double latmax = grid_corner_lat[i*4];
for ( ic = 1; ic < 4; ic++ )
{
if ( grid_corner_lat[i*4+ic] < latmin ) latmin = grid_corner_lat[i*4+ic];
@@ -1196,8 +686,8 @@ void *Outputgmt(void *argument)
double xlev[4], xlon[4];
double levmin = zaxis_lower_lev[levelID];
double levmax = zaxis_upper_lev[levelID];
- double lonmin = grid_corner_lon[i*4+0];
- double lonmax = grid_corner_lon[i*4+0];
+ double lonmin = grid_corner_lon[i*4];
+ double lonmax = grid_corner_lon[i*4];
for ( ic = 1; ic < 4; ic++ )
{
if ( grid_corner_lon[i*4+ic] < lonmin ) lonmin = grid_corner_lon[i*4+ic];
diff --git a/src/Pack.c b/src/Pack.c
index a55830d..8b0f44a 100644
--- a/src/Pack.c
+++ b/src/Pack.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Vardup.c b/src/Pardup.c
similarity index 95%
rename from src/Vardup.c
rename to src/Pardup.c
index 0f7ebc3..0fa1cfc 100644
--- a/src/Vardup.c
+++ b/src/Pardup.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,8 @@
/*
This module contains the following operators:
- Vardup pardup Duplicate parameters
- Vardup parmul Multiply parameters
+ Pardup pardup Duplicate parameters
+ Pardup parmul Multiply parameters
*/
#include <cdi.h>
@@ -28,7 +28,7 @@
#include "pstream.h"
-void *Vardup(void *argument)
+void *Pardup(void *argument)
{
int nrecs;
int recID, varID, varID2, levelID;
diff --git a/src/Pinfo.c b/src/Pinfo.c
index d568757..4adfd5b 100644
--- a/src/Pinfo.c
+++ b/src/Pinfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Pressure.c b/src/Pressure.c
index b617d47..471f785 100644
--- a/src/Pressure.c
+++ b/src/Pressure.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Regres.c b/src/Regres.c
index dc16dc2..fa557cf 100644
--- a/src/Regres.c
+++ b/src/Regres.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -139,14 +139,14 @@ void *Regres(void *argument)
for ( i = 0; i < gridsize; i++ )
{
- temp1 = SUB(work[2][varID][levelID].ptr[i],
- DIV(MUL(work[0][varID][levelID].ptr[i], work[3][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
- temp2 = SUB(work[1][varID][levelID].ptr[i],
- DIV(MUL(work[0][varID][levelID].ptr[i], work[0][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
-
- field2.ptr[i] = DIV(temp1, temp2);
- field1.ptr[i] = SUB(DIV(work[3][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]),
- MUL(DIV(work[0][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]), field2.ptr[i]));
+ temp1 = SUBMN(work[2][varID][levelID].ptr[i],
+ DIVMN( MULMN(work[0][varID][levelID].ptr[i], work[3][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
+ temp2 = SUBMN(work[1][varID][levelID].ptr[i],
+ DIVMN( MULMN(work[0][varID][levelID].ptr[i], work[0][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
+
+ field2.ptr[i] = DIVMN(temp1, temp2);
+ field1.ptr[i] = SUBMN( DIVMN(work[3][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]),
+ MULMN( DIVMN(work[0][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]), field2.ptr[i]));
}
/*
diff --git a/src/Remap.c b/src/Remap.c
index 81919a8..bf41b82 100644
--- a/src/Remap.c
+++ b/src/Remap.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -831,7 +831,7 @@ void *Remap(void *argument)
if ( lremapxxx )
{
- operatorInputArg("grid description file or name, remap weights file (SCRIP netCDF)");
+ operatorInputArg("grid description file or name, remap weights file (SCRIP NetCDF)");
operatorCheckArgc(2);
gridID2 = cdoDefineGrid(operatorArgv()[0]);
remap_file = operatorArgv()[1];
diff --git a/src/Remapeta.c b/src/Remapeta.c
index 35d1146..44f7d2c 100644
--- a/src/Remapeta.c
+++ b/src/Remapeta.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,11 +35,9 @@
static
void setmissval(long nvals, int *imiss, double missval, double *array)
{
- long i;
-
if ( imiss )
{
- for ( i = 0; i < nvals; ++i )
+ for ( long i = 0; i < nvals; ++i )
if ( imiss[i] ) array[i] = missval;
}
}
@@ -115,8 +113,7 @@ double *vctFromFile(const char *filename, int *nvct)
while ( readline(fp, line, 1024) )
{
- if ( line[0] == '#' ) continue;
- if ( line[0] == '\0' ) continue;
+ if ( line[0] == '#' || line[0] == '\0' ) continue;
pline = line;
num = (int) strtod(pline, &pline);
diff --git a/src/Replace.c b/src/Replace.c
index 4cedf6b..2782114 100644
--- a/src/Replace.c
+++ b/src/Replace.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Replacevalues.c b/src/Replacevalues.c
index 1de165f..3c49c2b 100644
--- a/src/Replacevalues.c
+++ b/src/Replacevalues.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Rhopot.c b/src/Rhopot.c
index e6b3fcb..5e9863a 100644
--- a/src/Rhopot.c
+++ b/src/Rhopot.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -296,9 +296,17 @@ void *Rhopot(void *argument)
offset = gridsize*levelID;
- if ( varID == toID ) streamReadRecord(streamID1, to.ptr+offset, &(to.nmiss));
- if ( varID == saoID ) streamReadRecord(streamID1, sao.ptr+offset, &(sao.nmiss));
- }
+ if ( varID == toID )
+ {
+ streamReadRecord(streamID1, to.ptr+offset, &nmiss);
+ to.nmiss = (size_t) nmiss;
+ }
+ if ( varID == saoID )
+ {
+ streamReadRecord(streamID1, sao.ptr+offset, &nmiss);
+ sao.nmiss = (size_t) nmiss;
+ }
+ }
calc_rhopot(gridsize, nlevel, pressure, to, sao, rho);
diff --git a/src/Rotuv.c b/src/Rotuv.c
index f5e9f10..a2f7672 100644
--- a/src/Rotuv.c
+++ b/src/Rotuv.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Runstat.c b/src/Runstat.c
index c973f19..1187ffa 100644
--- a/src/Runstat.c
+++ b/src/Runstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Runstat runmean Running mean
Runstat runavg Running average
Runstat runvar Running variance
- Runstat runvar1 Running variance [Divisor is (n-1)]
+ Runstat runvar1 Running variance [Normalize by (n-1)]
Runstat runstd Running standard deviation
- Runstat runstd1 Running standard deviation [Divisor is (n-1)]
+ Runstat runstd1 Running standard deviation [Normalize by (n-1)]
*/
#include <cdi.h>
@@ -82,7 +82,7 @@ void *Runstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
int streamID1 = streamOpenRead(cdoStreamName(0));
diff --git a/src/Seascount.c b/src/Seascount.c
index 9c5c3c8..c8f2ef1 100644
--- a/src/Seascount.c
+++ b/src/Seascount.c
@@ -38,6 +38,7 @@ void *Seascount(void *argument)
int varID, levelID, recID;
int tsID;
int otsID;
+ int nmiss;
long nsets;
int i;
int year, month, day, seas, seas0 = 0;
@@ -131,7 +132,8 @@ void *Seascount(void *argument)
vars1[varID][levelID].nmiss = gridsize;
}
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[varID][levelID].grid;
field.missval = vars1[varID][levelID].missval;
@@ -158,7 +160,7 @@ void *Seascount(void *argument)
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID][levelID].ptr, (int)vars1[varID][levelID].nmiss);
}
if ( nrecs == 0 ) break;
diff --git a/src/Seasstat.c b/src/Seasstat.c
index 6ea36fa..b3e51c1 100644
--- a/src/Seasstat.c
+++ b/src/Seasstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Seasstat seasmean Seasonal mean
Seasstat seasavg Seasonal average
Seasstat seasvar Seasonal variance
- Seasstat seasvar1 Seasonal variance [Divisor is (n-1)]
+ Seasstat seasvar1 Seasonal variance [Normalize by (n-1)]
Seasstat seasstd Seasonal standard deviation
- Seasstat seasstd1 Seasonal standard deviation [Divisor is (n-1)]
+ Seasstat seasstd1 Seasonal standard deviation [Normalize by (n-1)]
*/
@@ -46,7 +46,7 @@ void *Seasstat(void *argument)
int vdate1 = 0, vtime1 = 0;
int nrecs;
int varID, levelID, recID;
- long nsets;
+ int nsets;
int i;
int year, month, day, seas, seas0 = 0;
int nmiss;
@@ -76,7 +76,7 @@ void *Seasstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
int streamID1 = streamOpenRead(cdoStreamName(0));
@@ -180,7 +180,8 @@ void *Seasstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[varID][levelID].grid;
field.missval = vars1[varID][levelID].missval;
@@ -272,7 +273,7 @@ void *Seasstat(void *argument)
time2str(vtime0, vtimestr0, sizeof(vtimestr0));
date2str(vdate1, vdatestr1, sizeof(vdatestr1));
time2str(vtime1, vtimestr1, sizeof(vtimestr1));
- cdoPrint("season %3d %3s start %s %s end %s %s ntimesteps %d",
+ cdoPrint("season: %3d %3s start: %s %s end: %s %s ntimesteps: %d",
nseason, seas_name[seas0], vdatestr0, vtimestr0, vdatestr1, vtimestr1, nsets);
}
@@ -295,7 +296,7 @@ void *Seasstat(void *argument)
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID][levelID].ptr, (int)vars1[varID][levelID].nmiss);
}
if ( nrecs == 0 ) break;
diff --git a/src/Selbox.c b/src/Selbox.c
index f33887d..829eaf6 100644
--- a/src/Selbox.c
+++ b/src/Selbox.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Select.c b/src/Select.c
index 1e7c0bb..c10a32b 100644
--- a/src/Select.c
+++ b/src/Select.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -54,13 +54,13 @@ static PARAMETER Parameter[] =
static int NumParameter = sizeof(Parameter) / sizeof(Parameter[0]);
*/
-#define PML_DEF(name, size, txt) int flag_##name[size]; int npar_##name = 0; int max_##name = size; const char str_##name[] = txt
+#define PML_DEF(name, size, txt) bool flag_##name[size]; int npar_##name = 0; int max_##name = size; const char str_##name[] = txt
#define PML_DEF_INT(name, size, txt) int par_##name[size]; int name = 0; PML_DEF(name, size, txt)
#define PML_DEF_FLT(name, size, txt) double par_##name[size]; double name = 0; PML_DEF(name, size, txt)
-#define PML_DEF_WORD(name, size, txt) char *par_##name[size]; char *name = 0; PML_DEF(name, size, txt)
-#define PML_INIT_INT(name) memset(flag_##name, 0, max_##name * sizeof(int))
-#define PML_INIT_FLT(name) memset(flag_##name, 0, max_##name * sizeof(int))
-#define PML_INIT_WORD(name) memset(flag_##name, 0, max_##name * sizeof(int))
+#define PML_DEF_WORD(name, size, txt) char *par_##name[size]; const char *name = 0; PML_DEF(name, size, txt)
+#define PML_INIT_INT(name) memset(flag_##name, 0, max_##name * sizeof(bool))
+#define PML_INIT_FLT(name) memset(flag_##name, 0, max_##name * sizeof(bool))
+#define PML_INIT_WORD(name) memset(flag_##name, 0, max_##name * sizeof(bool))
#define PML_ADD_INT(nml, name) pmlAdd(nml, #name, PML_INT, 0, par_##name, sizeof(par_##name)/sizeof(int))
#define PML_ADD_FLT(nml, name) pmlAdd(nml, #name, PML_FLT, 0, par_##name, sizeof(par_##name)/sizeof(double))
#define PML_ADD_WORD(nml, name) pmlAdd(nml, #name, PML_WORD, 0, par_##name, sizeof(par_##name)/sizeof(char *))
@@ -74,6 +74,7 @@ static int NumParameter = sizeof(Parameter) / sizeof(Parameter[0]);
#define PAR_CHECK_FLT(name) par_check_flt(npar_##name, par_##name, flag_##name, name)
#define PAR_CHECK_WORD(name) par_check_word(npar_##name, par_##name, flag_##name, name)
#define PAR_CHECK_DATE(name) par_check_date(npar_##name, par_##name, flag_##name, name)
+#define PAR_CHECK_SEASON(name, month) par_check_season(npar_##name, par_##name, flag_##name, month)
#define MAX_PLIST_ENTRY 256
#define MAX_PML_ENTRY 256
@@ -130,13 +131,11 @@ void pml_init(pml_t *pml, const char *name)
pml_t *pmlNew(const char *name)
{
- pml_t *pml;
-
- pml = (pml_t*) Malloc(sizeof(pml_t));
+ pml_t *pml = (pml_t*) Malloc(sizeof(pml_t));
pml_init(pml, name);
- return (pml);
+ return pml;
}
@@ -189,16 +188,13 @@ void pmlPrint(pml_t *pml)
int pmlAdd(pml_t *pml, const char *name, int type, int dis, void *ptr, size_t size)
{
- pml_entry_t *pml_entry;
- int entry = 0;
-
if ( pml->size >= MAX_PML_ENTRY )
{
fprintf(stderr, "Too many entries in parameter list %s! (Max = %d)\n", pml->name, MAX_PML_ENTRY);
return -1;
}
- pml_entry = (pml_entry_t*) Malloc(sizeof(pml_entry_t));
+ pml_entry_t *pml_entry = (pml_entry_t*) Malloc(sizeof(pml_entry_t));
pml_entry->name = strdup(name);
pml_entry->len = strlen(name);
@@ -208,10 +204,10 @@ int pmlAdd(pml_t *pml, const char *name, int type, int dis, void *ptr, size_t si
pml_entry->dis = dis;
pml_entry->occ = 0;
- entry = pml->size;
+ int entry = pml->size;
pml->entry[pml->size++] = pml_entry;
- return (entry);
+ return entry;
}
@@ -235,7 +231,7 @@ int pmlNum(pml_t *pml, const char *name)
if ( i == pml->size )
fprintf(stderr, "Parameter list entry %s not found in %s\n", name, pml->name);
- return (nocc);
+ return nocc;
}
void split_intstring(const char *intstr, int *first, int *last, int *inc);
@@ -278,17 +274,16 @@ int pml_add_entry(pml_entry_t *entry, char *arg)
fprintf(stderr, "unsupported type!\n");
}
- return (status);
+ return status;
}
void pmlProcess(pml_entry_t *entry, int argc, char **argv)
{
- int i;
char *parg;
char *epos;
- for ( i = 0; i < argc; ++i )
+ for ( int i = 0; i < argc; ++i )
{
parg = argv[i];
if ( i == 0 )
@@ -313,10 +308,9 @@ int pmlRead(pml_t *pml, int argc, char **argv)
int params[MAX_PML_ENTRY];
int num_par[MAX_PML_ENTRY];
int nparams = 0;
- int i, istart;
+ int i;
char *epos;
size_t len;
- char *parbuf;
int bufsize = 0;
int status = 0;
/*
@@ -329,10 +323,10 @@ int pmlRead(pml_t *pml, int argc, char **argv)
bufsize += len+1;
}
- parbuf = (char*) Malloc(bufsize*sizeof(char));
+ char *parbuf = (char*) Malloc(bufsize*sizeof(char));
memset(parbuf, 0, bufsize*sizeof(char));
- istart = 0;
+ int istart = 0;
while ( istart < argc )
{
epos = strchr(argv[istart], '=');
@@ -353,7 +347,7 @@ int pmlRead(pml_t *pml, int argc, char **argv)
if ( i == pml->size )
{
- fprintf(stderr, "Parameter >%s< has not a valid keyword!\n", argv[istart]);
+ fprintf(stderr, "Parameter >%s< has an invalid keyword!\n", argv[istart]);
status = 2;
goto END_LABEL;
}
@@ -388,43 +382,43 @@ int pmlRead(pml_t *pml, int argc, char **argv)
Free(parbuf);
- return (status);
+ return status;
}
-int par_check_int(int npar, int *parlist, int *flaglist, int par)
+bool par_check_int(int npar, int *parlist, bool *flaglist, int par)
{
- int found = 0;
+ bool found = false;
for ( int i = 0; i < npar; i++ )
- if ( par == parlist[i] ) { found = 1; flaglist[i] = TRUE;/* break;*/}
+ if ( par == parlist[i] ) { found = true; flaglist[i] = true;/* break;*/}
- return (found);
+ return found;
}
-int par_check_flt(int npar, double *parlist, int *flaglist, double par)
+bool par_check_flt(int npar, double *parlist, bool *flaglist, double par)
{
- int found = 0;
+ bool found = false;
for ( int i = 0; i < npar; i++ )
- if ( fabs(par - parlist[i]) < 1.e-4 ) { found = 1; flaglist[i] = TRUE;/* break;*/}
+ if ( fabs(par - parlist[i]) < 1.e-4 ) { found = true; flaglist[i] = true;/* break;*/}
- return (found);
+ return found;
}
-int par_check_word(int npar, char **parlist, int *flaglist, char *par)
+bool par_check_word(int npar, char **parlist, bool *flaglist, const char *par)
{
- int found = 0;
+ bool found = false;
for ( int i = 0; i < npar; i++ )
- if ( wildcardmatch(parlist[i], par) == 0 ) { found = 1; flaglist[i] = TRUE;/* break;*/}
+ if ( wildcardmatch(parlist[i], par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
- return (found);
+ return found;
}
-int par_check_date(int npar, char **parlist, int *flaglist, char *par)
+bool par_check_date(int npar, char **parlist, bool *flaglist, const char *par)
{
- int found = 0;
+ bool found = false;
char wcdate[512];
if ( *par == ' ' ) ++par;
@@ -433,33 +427,51 @@ int par_check_date(int npar, char **parlist, int *flaglist, char *par)
{
strcpy(wcdate, parlist[i]);
strcat(wcdate, "*");
- if ( wildcardmatch(wcdate, par) == 0 ) { found = 1; flaglist[i] = TRUE;/* break;*/}
+ if ( wildcardmatch(wcdate, par) == 0 ) { found = true; flaglist[i] = true;/* break;*/}
}
- return (found);
+ return found;
}
+void season_to_months(const char *season, int *imonths);
-void par_check_int_flag(int npar, int *parlist, int *flaglist, const char *txt)
+bool par_check_season(int npar, char **parlist, bool *flaglist, int month)
+{
+ assert(month>=1&&month<=12);
+ bool found = false;
+ int imon[13]; /* 1-12 ! */
+
+ for ( int i = 0; i < npar; i++ )
+ {
+ for ( int m = 0; m < 13; ++m ) imon[m] = 0;
+ season_to_months(parlist[i], imon);
+ if ( imon[month] ) { found = true; flaglist[i] = true;/* break;*/}
+ }
+
+ return found;
+}
+
+
+void par_check_int_flag(int npar, int *parlist, bool *flaglist, const char *txt)
{
for ( int i = 0; i < npar; ++i )
- if ( flaglist[i] == FALSE )
+ if ( flaglist[i] == false )
cdoWarning("%s >%d< not found!", txt, parlist[i]);
}
-void par_check_flt_flag(int npar, double *parlist, int *flaglist, const char *txt)
+void par_check_flt_flag(int npar, double *parlist, bool *flaglist, const char *txt)
{
for ( int i = 0; i < npar; ++i )
- if ( flaglist[i] == FALSE )
+ if ( flaglist[i] == false )
cdoWarning("%s >%g< not found!", txt, parlist[i]);
}
-void par_check_word_flag(int npar, char **parlist, int *flaglist, const char *txt)
+void par_check_word_flag(int npar, char **parlist, bool *flaglist, const char *txt)
{
for ( int i = 0; i < npar; ++i )
- if ( flaglist[i] == FALSE )
+ if ( flaglist[i] == false )
cdoWarning("%s >%s< not found!", txt, parlist[i]);
}
@@ -487,36 +499,33 @@ int vlist_get_psvarid(int vlistID, int zaxisID)
if ( cdoVerbose && psvarid == -1 )
cdoWarning("Surface pressure variable not found - %s", psname);
}
-
+
return psvarid;
}
void *Select(void *argument)
{
+ bool lconstvars = true;
int streamID2 = CDI_UNDEFID;
- int tsID1, tsID2, nrecs;
+ int nrecs;
int nvars, nvars2, nlevs;
- int zaxisID, levID;
+ int zaxisID;
int varID2, levelID2;
- int recID, varID, levelID;
- int iparam;
- int vdate, vtime;
+ int varID, levelID;
int last_year = -999999999;
char paramstr[32];
char varname[CDI_MAX_NAME];
char stdname[CDI_MAX_NAME];
+ char gname[CDI_MAX_NAME];
+ char zname[CDI_MAX_NAME];
int vlistID0 = -1, vlistID2 = -1;
- int i;
int result = FALSE;
- int gridsize;
- int nmiss;
int taxisID2 = CDI_UNDEFID;
int ntsteps;
- int ltimsel = FALSE;
- int second;
- int npar;
- int *vars = NULL;
+ bool ltimsel = false;
+ bool *vars = NULL;
+ double **vardata2 = NULL;
double *array = NULL;
double fstartdate = -99999999999.;
double fenddate = -99999999999.;
@@ -529,13 +538,19 @@ void *Select(void *argument)
PML_DEF_INT(hour, 24, "Hour");
PML_DEF_INT(minute, 60, "Minute");
PML_DEF_INT(code, 1024, "Code number");
- PML_DEF_INT(ltype, 1024, "Level type");
PML_DEF_INT(levidx, 1024, "Level index");
+ PML_DEF_INT(ltype, 256, "Level type");
+ PML_DEF_INT(zaxisnum, 256, "Zaxis number");
+ PML_DEF_INT(gridnum, 256, "Grid number");
PML_DEF_FLT(level, 1024, "Level");
PML_DEF_WORD(name, 1024, "Variable name");
PML_DEF_WORD(param, 1024, "Parameter");
+ PML_DEF_WORD(zaxisname, 256, "Zaxis name");
+ PML_DEF_WORD(gridname, 256, "Grid name");
+ PML_DEF_WORD(steptype, 32, "Time step type");
PML_DEF_WORD(startdate, 1, "Start date");
PML_DEF_WORD(enddate, 1, "End date");
+ PML_DEF_WORD(season, 12, "Season");
PML_DEF_WORD(date, 1024, "Date");
PML_INIT_INT(timestep_of_year);
@@ -546,22 +561,28 @@ void *Select(void *argument)
PML_INIT_INT(hour);
PML_INIT_INT(minute);
PML_INIT_INT(code);
- PML_INIT_INT(ltype);
PML_INIT_INT(levidx);
+ PML_INIT_INT(ltype);
+ PML_INIT_INT(zaxisnum);
+ PML_INIT_INT(gridnum);
PML_INIT_FLT(level);
PML_INIT_WORD(name);
PML_INIT_WORD(param);
+ PML_INIT_WORD(zaxisname);
+ PML_INIT_WORD(gridname);
+ PML_INIT_WORD(steptype);
PML_INIT_WORD(startdate);
PML_INIT_WORD(enddate);
+ PML_INIT_WORD(season);
PML_INIT_WORD(date);
cdoInitialize(argument);
- int SELECT = cdoOperatorAdd("select", 0, 0, "parameter list");
- int DELETE = cdoOperatorAdd("delete", 0, 0, "parameter list");
+ int SELECT = cdoOperatorAdd("select", 0, 0, "parameter list");
+ int DELETE = cdoOperatorAdd("delete", 0, 0, "parameter list");
- int lcopy = FALSE;
- if ( UNCHANGED_RECORD ) lcopy = TRUE;
+ bool lcopy = false;
+ if ( UNCHANGED_RECORD ) lcopy = true;
int operatorID = cdoOperatorID();
@@ -571,7 +592,7 @@ void *Select(void *argument)
char **argnames = operatorArgv();
if ( cdoVerbose )
- for ( i = 0; i < nsel; i++ )
+ for ( int i = 0; i < nsel; i++ )
printf("name %d = %s\n", i+1, argnames[i]);
pml_t *pml = pmlNew("SELECT");
@@ -584,13 +605,19 @@ void *Select(void *argument)
PML_ADD_INT(pml, hour);
PML_ADD_INT(pml, minute);
PML_ADD_INT(pml, code);
- PML_ADD_INT(pml, ltype);
PML_ADD_INT(pml, levidx);
+ PML_ADD_INT(pml, ltype);
+ PML_ADD_INT(pml, zaxisnum);
+ PML_ADD_INT(pml, gridnum);
PML_ADD_FLT(pml, level);
PML_ADD_WORD(pml, name);
PML_ADD_WORD(pml, param);
+ PML_ADD_WORD(pml, zaxisname);
+ PML_ADD_WORD(pml, gridname);
+ PML_ADD_WORD(pml, steptype);
PML_ADD_WORD(pml, startdate);
PML_ADD_WORD(pml, enddate);
+ PML_ADD_WORD(pml, season);
PML_ADD_WORD(pml, date);
pmlRead(pml, nsel, argnames);
@@ -605,24 +632,28 @@ void *Select(void *argument)
PML_NUM(pml, hour);
PML_NUM(pml, minute);
PML_NUM(pml, code);
- PML_NUM(pml, ltype);
PML_NUM(pml, levidx);
+ PML_NUM(pml, ltype);
+ PML_NUM(pml, zaxisnum);
+ PML_NUM(pml, gridnum);
PML_NUM(pml, level);
PML_NUM(pml, name);
PML_NUM(pml, param);
+ PML_NUM(pml, zaxisname);
+ PML_NUM(pml, gridname);
+ PML_NUM(pml, steptype);
PML_NUM(pml, startdate);
PML_NUM(pml, enddate);
+ PML_NUM(pml, season);
PML_NUM(pml, date);
- /*
- pmlDelete(pml);
- */
int streamCnt = cdoStreamCnt();
int nfiles = streamCnt - 1;
if ( !cdoVerbose && nfiles > 1 ) progressInit();
- tsID2 = 0;
+ timestep = 0;
+ int tsID2 = 0;
for ( int indf = 0; indf < nfiles; indf++ )
{
if ( !cdoVerbose && nfiles > 1 ) progressStatus(0, 1, (indf+1.)/nfiles);
@@ -633,13 +664,15 @@ void *Select(void *argument)
int vlistID1 = streamInqVlist(streamID1);
int taxisID1 = vlistInqTaxis(vlistID1);
+ bool lcopy_const = false;
+
if ( indf == 0 )
{
// vlistID0 = vlistDuplicate(vlistID1);
vlistClearFlag(vlistID1);
nvars = vlistNvars(vlistID1);
- vars = (int*) Malloc(nvars*sizeof(int));
+ vars = (bool*) Malloc(nvars*sizeof(bool));
if ( operatorID == DELETE )
{
@@ -648,7 +681,7 @@ void *Select(void *argument)
{
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
- for ( levID = 0; levID < nlevs; levID++ )
+ for ( int levID = 0; levID < nlevs; levID++ )
vlistDefFlag(vlistID1, varID, levID, TRUE);
}
}
@@ -659,8 +692,8 @@ void *Select(void *argument)
for ( varID = 0; varID < nvars; varID++ )
{
- iparam = vlistInqVarParam(vlistID1, varID);
- code = vlistInqVarCode(vlistID1, varID);
+ int iparam = vlistInqVarParam(vlistID1, varID);
+ code = vlistInqVarCode(vlistID1, varID);
vlistInqVarName(vlistID1, varID, varname);
vlistInqVarStdname(vlistID1, varID, stdname);
@@ -669,60 +702,79 @@ void *Select(void *argument)
name = varname;
param = paramstr;
+ int gridID = vlistInqVarGrid(vlistID1, varID);
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
ltype = zaxis2ltype(zaxisID);
-
- vars[varID] = FALSE;
+ zaxisnum = vlistZaxisIndex(vlistID1, zaxisID)+1;
+ int zaxistype = zaxisInqType(zaxisID);
+ zaxisName(zaxistype, zname);
+ zaxisname = zname;
+
+ gridnum = vlistGridIndex(vlistID1, gridID)+1;
+ int gridtype = gridInqType(gridID);
+ gridName(gridtype, gname);
+ gridname = gname;
+
+ int tsteptype = vlistInqVarTsteptype(vlistID1, varID);
+ if ( tsteptype == TSTEP_CONSTANT ) steptype = "constant";
+ else if ( tsteptype == TSTEP_INSTANT ) steptype = "instant";
+ else if ( tsteptype == TSTEP_INSTANT2 ) steptype = "instant";
+ else if ( tsteptype == TSTEP_INSTANT3 ) steptype = "instant";
+ else if ( tsteptype == TSTEP_MIN ) steptype = "min";
+ else if ( tsteptype == TSTEP_MAX ) steptype = "max";
+ else if ( tsteptype == TSTEP_AVG ) steptype = "avg";
+ else if ( tsteptype == TSTEP_ACCUM ) steptype = "accum";
+ else if ( tsteptype == TSTEP_RANGE ) steptype = "range";
+ else if ( tsteptype == TSTEP_DIFF ) steptype = "diff";
+ else steptype = "unknown";
+
+ vars[varID] = false;
+ bool found_code = npar_code && PAR_CHECK_INT(code);
+ bool found_name = npar_name && PAR_CHECK_WORD(name);
+ bool found_param = npar_param && PAR_CHECK_WORD(param);
+ bool found_grid = npar_gridnum && PAR_CHECK_INT(gridnum);
+ bool found_gname = npar_gridname && PAR_CHECK_WORD(gridname);
+ bool found_stype = npar_steptype && PAR_CHECK_WORD(steptype);
+ bool found_ltype = npar_ltype && PAR_CHECK_INT(ltype);
+ bool found_zaxis = npar_zaxisnum && PAR_CHECK_INT(zaxisnum);
+ bool found_zname = npar_zaxisname && PAR_CHECK_WORD(zaxisname);
+ bool lvar = found_code || found_name || found_param;
+ bool lstep = npar_steptype ? found_stype : true;
+ bool lgrid = (npar_gridnum || npar_gridname) ? (found_grid || found_gname) : true;
+ bool lvert = (npar_ltype || npar_zaxisnum || npar_zaxisname) ? (found_ltype || found_zaxis || found_zname) : true;
- if ( npar_ltype )
- {
- if ( !vars[varID] && npar_code && PAR_CHECK_INT(ltype) && PAR_CHECK_INT(code) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_name && PAR_CHECK_INT(ltype) && PAR_CHECK_WORD(name) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_param && PAR_CHECK_INT(ltype) && PAR_CHECK_WORD(param) ) vars[varID] = TRUE;
- if ( !vars[varID] && !npar_code && !npar_name && !npar_param )
- {
- if ( PAR_CHECK_INT(ltype) ) vars[varID] = TRUE;
- else
- {
- for ( levID = 0; levID < nlevs; levID++ )
- {
- levidx = levID + 1;
- level = zaxisInqLevel(zaxisID, levID);
- if ( !vars[varID] && npar_levidx && PAR_CHECK_INT(ltype) && PAR_CHECK_INT(levidx) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_level && PAR_CHECK_INT(ltype) && PAR_CHECK_FLT(level) ) vars[varID] = TRUE;
- }
- }
- }
- }
- else
- {
- if ( !vars[varID] && npar_code && PAR_CHECK_INT(code) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_name && PAR_CHECK_WORD(name) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_param && PAR_CHECK_WORD(param) ) vars[varID] = TRUE;
- if ( !vars[varID] && !npar_code && !npar_name && !npar_param )
- {
- for ( levID = 0; levID < nlevs; levID++ )
- {
- levidx = levID + 1;
- level = zaxisInqLevel(zaxisID, levID);
- if ( !vars[varID] && npar_levidx && PAR_CHECK_INT(levidx) ) vars[varID] = TRUE;
- if ( !vars[varID] && npar_level && PAR_CHECK_FLT(level) ) vars[varID] = TRUE;
- }
- }
- }
+ if ( !vars[varID] && lgrid && lvar) vars[varID] = true;
+ if ( !vars[varID] && lvert && lvar) vars[varID] = true;
+ if ( !vars[varID] && lstep && lvar) vars[varID] = true;
+ if ( !vars[varID] && !lvar )
+ {
+ if ( found_grid || found_gname ) vars[varID] = true;
+ else if ( found_stype ) vars[varID] = true;
+ else if ( found_ltype || found_zaxis || found_zname ) vars[varID] = true;
+ else if ( npar_levidx || npar_level )
+ {
+ for ( int levID = 0; levID < nlevs; levID++ )
+ {
+ levidx = levID + 1;
+ level = zaxisInqLevel(zaxisID, levID);
+ if ( !vars[varID] && npar_levidx && PAR_CHECK_INT(levidx) ) vars[varID] = true;
+ if ( !vars[varID] && npar_level && PAR_CHECK_FLT(level) ) vars[varID] = true;
+ }
+ }
+ }
}
for ( varID = 0; varID < nvars; varID++ )
{
if ( vars[varID] )
{
- zaxisID = vlistInqVarZaxis(vlistID1, varID);
+ int zaxisID = vlistInqVarZaxis(vlistID1, varID);
if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID )
{
int psvarid = vlist_get_psvarid(vlistID1, zaxisID);
- if ( psvarid != -1 && !vars[psvarid] ) vars[psvarid] = TRUE;
+ if ( psvarid != -1 && !vars[psvarid] ) vars[psvarid] = true;
}
}
}
@@ -734,7 +786,7 @@ void *Select(void *argument)
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
- for ( levID = 0; levID < nlevs; levID++ )
+ for ( int levID = 0; levID < nlevs; levID++ )
{
levidx = levID + 1;
level = zaxisInqLevel(zaxisID, levID);
@@ -765,38 +817,45 @@ void *Select(void *argument)
}
PAR_CHECK_INT_FLAG(code);
- PAR_CHECK_INT_FLAG(ltype);
PAR_CHECK_INT_FLAG(levidx);
+ PAR_CHECK_INT_FLAG(ltype);
+ PAR_CHECK_INT_FLAG(zaxisnum);
+ PAR_CHECK_INT_FLAG(gridnum);
PAR_CHECK_FLT_FLAG(level);
PAR_CHECK_WORD_FLAG(name);
PAR_CHECK_WORD_FLAG(param);
+ PAR_CHECK_WORD_FLAG(zaxisname);
+ PAR_CHECK_WORD_FLAG(gridname);
+ PAR_CHECK_WORD_FLAG(steptype);
- if ( npar_date || npar_startdate || npar_enddate ) ltimsel = TRUE;
- if ( npar_timestep_of_year || npar_timestep || npar_year || npar_month || npar_day || npar_hour || npar_minute ) ltimsel = TRUE;
+ if ( npar_date || npar_startdate || npar_enddate || npar_season ) ltimsel = true;
+ if ( npar_timestep_of_year || npar_timestep || npar_year || npar_month || npar_day || npar_hour || npar_minute ) ltimsel = true;
- npar = 0;
+ int npar = 0;
for ( varID = 0; varID < nvars; varID++ )
{
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
-
- for ( levID = 0; levID < nlevs; levID++ )
- if ( vlistInqFlag(vlistID1, varID, levID) == result ) break;
-
- if ( levID < nlevs ) npar++;
+ for ( int levID = 0; levID < nlevs; levID++ )
+ if ( vlistInqFlag(vlistID1, varID, levID) == result )
+ {
+ npar++;
+ break;
+ }
}
if ( npar == 0 )
{
- if ( ltimsel == TRUE )
+ if ( ltimsel == true )
{
+ lcopy_const = true;
+
for ( varID = 0; varID < nvars; varID++ )
{
- vars[varID] = TRUE;
+ vars[varID] = true;
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
-
- for ( levID = 0; levID < nlevs; levID++ )
+ for ( int levID = 0; levID < nlevs; levID++ )
vlistDefFlag(vlistID1, varID, levID, TRUE);
}
}
@@ -813,7 +872,7 @@ void *Select(void *argument)
{
zaxisID = vlistInqVarZaxis(vlistID1, varID);
nlevs = zaxisInqSize(zaxisID);
- for ( levID = 0; levID < nlevs; levID++ )
+ for ( int levID = 0; levID < nlevs; levID++ )
vlistDefFlag(vlistID0, varID, levID, vlistInqFlag(vlistID1, varID, levID));
}
@@ -845,15 +904,16 @@ void *Select(void *argument)
if ( ntsteps2 == 0 || ntsteps2 == 1 ) vlistDefNtsteps(vlistID2, ntsteps2);
if ( ntsteps2 == 0 && nfiles > 1 )
- {
+ {
+ lconstvars = false;
for ( varID = 0; varID < nvars2; ++varID )
vlistDefVarTsteptype(vlistID2, varID, TSTEP_INSTANT);
}
- /* add support for negative timestep values */
+ // support for negative timestep values
if ( npar_timestep > 0 && ntsteps > 0 && nfiles == 1 )
{
- for ( i = 0; i < npar_timestep; i++ )
+ for ( int i = 0; i < npar_timestep; i++ )
{
if ( par_timestep[i] < 0 )
{
@@ -866,7 +926,7 @@ void *Select(void *argument)
if ( ! lcopy )
{
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
array = (double*) Malloc(gridsize*sizeof(double));
}
@@ -888,28 +948,35 @@ void *Select(void *argument)
goto END_LABEL;
}
- int lstop = FALSE;
- tsID1 = 0;
+ if ( lcopy_const )
+ {
+ vardata2 = (double**) malloc(nvars2*sizeof(double));
+ for ( varID = 0; varID < nvars2; ++varID ) vardata2[varID] = NULL;
+ }
+
+ bool lstop = false;
+ int tsID1 = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID1)) )
{
- int copytimestep = TRUE;
+ timestep++;
+ bool copytimestep = true;
- if ( ltimsel == TRUE )
+ if ( ltimsel == true )
{
- copytimestep = FALSE;
- timestep = tsID1 + 1;
+ copytimestep = false;
if ( operatorID == SELECT && npar_timestep > 0 && timestep > par_timestep[npar_timestep-1] )
{
- lstop = TRUE;
+ lstop = true;
break;
}
- vdate = taxisInqVdate(taxisID1);
- vtime = taxisInqVtime(taxisID1);
-
+ int vdate = taxisInqVdate(taxisID1);
+ int vtime = taxisInqVtime(taxisID1);
+ int second;
cdiDecodeDate(vdate, &year, &month, &day);
cdiDecodeTime(vtime, &hour, &minute, &second);
+ UNUSED(season);
if ( year != last_year )
{
@@ -919,20 +986,21 @@ void *Select(void *argument)
timestep_of_year++;
- if ( npar_timestep && PAR_CHECK_INT(timestep) ) copytimestep = TRUE;
- if ( npar_timestep_of_year && PAR_CHECK_INT(timestep_of_year) ) copytimestep = TRUE;
+ if ( npar_timestep && PAR_CHECK_INT(timestep) ) copytimestep = true;
+ if ( npar_timestep_of_year && PAR_CHECK_INT(timestep_of_year) ) copytimestep = true;
if ( !copytimestep && npar_date == 0 && npar_timestep == 0 && npar_timestep_of_year == 0 )
{
- int lyear = 0, lmonth = 0, lday = 0, lhour = 0, lminute = 0;
+ bool lseason = false, lyear = false, lmonth = false, lday = false, lhour = false, lminute = false;
- if ( npar_year == 0 || (npar_year && PAR_CHECK_INT(year)) ) lyear = TRUE;
- if ( npar_month == 0 || (npar_month && PAR_CHECK_INT(month)) ) lmonth = TRUE;
- if ( npar_day == 0 || (npar_day && PAR_CHECK_INT(day)) ) lday = TRUE;
- if ( npar_hour == 0 || (npar_hour && PAR_CHECK_INT(hour)) ) lhour = TRUE;
- if ( npar_minute == 0 || (npar_minute && PAR_CHECK_INT(minute)) ) lminute = TRUE;
+ if ( npar_season == 0 || (npar_season && PAR_CHECK_SEASON(season, month)) ) lseason = true;
+ if ( npar_year == 0 || (npar_year && PAR_CHECK_INT(year)) ) lyear = true;
+ if ( npar_month == 0 || (npar_month && PAR_CHECK_INT(month)) ) lmonth = true;
+ if ( npar_day == 0 || (npar_day && PAR_CHECK_INT(day)) ) lday = true;
+ if ( npar_hour == 0 || (npar_hour && PAR_CHECK_INT(hour)) ) lhour = true;
+ if ( npar_minute == 0 || (npar_minute && PAR_CHECK_INT(minute)) ) lminute = true;
- if ( lyear && lmonth && lday && lhour && lminute ) copytimestep = TRUE;
+ if ( lseason && lyear && lmonth && lday && lhour && lminute ) copytimestep = true;
}
double fdate = ((double)vdate) + ((double)vtime)/1000000.;
@@ -941,17 +1009,17 @@ void *Select(void *argument)
{
if ( fdate > fenddate )
{
- flag_enddate[0] = TRUE;
- copytimestep = FALSE;
+ flag_enddate[0] = true;
+ copytimestep = false;
if ( operatorID == SELECT )
{
- lstop = TRUE;
+ lstop = true;
break;
}
}
else
{
- copytimestep = TRUE;
+ copytimestep = true;
}
}
@@ -959,12 +1027,12 @@ void *Select(void *argument)
{
if ( fdate < fstartdate )
{
- copytimestep = FALSE;
+ copytimestep = false;
}
else
{
- flag_startdate[0] = TRUE;
- copytimestep = TRUE;
+ flag_startdate[0] = true;
+ copytimestep = true;
}
}
@@ -974,30 +1042,57 @@ void *Select(void *argument)
char vdatetimestr[64];
datetime2str(vdate, vtime, vdatetimestr, sizeof(vdatetimestr));
date = vdatetimestr;
- if ( PAR_CHECK_DATE(date) ) copytimestep = TRUE;
+ if ( PAR_CHECK_DATE(date) ) copytimestep = true;
}
if ( operatorID == DELETE ) copytimestep = !copytimestep;
+
+ if ( copytimestep && indf == 0 && tsID1 == 0 ) lcopy_const = false;
}
- if ( copytimestep == TRUE )
+ if ( copytimestep == true )
{
if ( streamID2 == CDI_UNDEFID )
{
streamID2 = streamOpenWrite(cdoStreamName(nfiles), cdoFiletype());
-
streamDefVlist(streamID2, vlistID2);
}
taxisCopyTimestep(taxisID2, taxisID1);
-
streamDefTimestep(streamID2, tsID2);
-
- for ( recID = 0; recID < nrecs; recID++ )
+
+ if ( lcopy_const && tsID2 == 0 )
+ {
+ for ( varID2 = 0; varID2 < nvars2; ++varID2 )
+ {
+ if ( vardata2[varID2] )
+ {
+ double missval = vlistInqVarMissval(vlistID2, varID2);
+ int gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2));
+ int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID2));
+ for ( int levelID2 = 0; levelID2 < nlevel; ++levelID2 )
+ {
+ double *pdata = vardata2[varID2]+gridsize*levelID;
+ int nmiss = 0;
+ for ( int i = 0; i < gridsize; ++i )
+ if ( DBL_IS_EQUAL(pdata[i], missval) ) nmiss++;
+
+ streamDefRecord(streamID2, varID2, levelID2);
+ streamWriteRecord(streamID2, pdata, nmiss);
+ }
+ }
+ }
+ }
+
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
if ( vlistInqFlag(vlistID0, varID, levelID) == TRUE )
{
+ if ( lconstvars && tsID2 > 0 && tsID1 == 0 )
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
+ continue;
+
varID2 = vlistFindVar(vlistID2, varID);
levelID2 = vlistFindLevel(vlistID2, varID, levelID);
@@ -1008,13 +1103,38 @@ void *Select(void *argument)
}
else
{
+ int nmiss;
streamReadRecord(streamID1, array, &nmiss);
streamWriteRecord(streamID2, array, nmiss);
}
}
}
- tsID2++;
+
+ tsID2++;
}
+ else if ( lcopy_const && indf == 0 && tsID1 == 0 )
+ {
+ for ( int recID = 0; recID < nrecs; recID++ )
+ {
+ streamInqRecord(streamID1, &varID, &levelID);
+ if ( vlistInqFlag(vlistID0, varID, levelID) == TRUE )
+ {
+ varID2 = vlistFindVar(vlistID2, varID);
+ if ( vlistInqVarTsteptype(vlistID2, varID2) == TSTEP_CONSTANT )
+ {
+ levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+ int gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID2));
+ if ( levelID == 0 )
+ {
+ int nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID2));
+ vardata2[varID2] = (double*) malloc(gridsize*nlevel*sizeof(double));
+ }
+ int nmiss;
+ streamReadRecord(streamID1, vardata2[varID2]+gridsize*levelID, &nmiss);
+ }
+ }
+ }
+ }
tsID1++;
}
@@ -1038,6 +1158,7 @@ void *Select(void *argument)
PAR_CHECK_WORD_FLAG(startdate);
UNUSED(str_enddate);
// PAR_CHECK_WORD_FLAG(enddate);
+ PAR_CHECK_WORD_FLAG(season);
PAR_CHECK_WORD_FLAG(date);
if ( streamID2 != CDI_UNDEFID ) streamClose(streamID2);
@@ -1049,10 +1170,17 @@ void *Select(void *argument)
if ( array ) Free(array);
if ( vars ) Free(vars);
+ if ( vardata2 )
+ {
+ for ( varID = 0; varID < nvars2; ++ varID )
+ if ( vardata2[varID] ) free(vardata2[varID]);
+
+ free(vardata2);
+ }
if ( tsID2 == 0 ) cdoAbort("No timesteps selected!");
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Seloperator.c b/src/Seloperator.c
index 7cab6cb..bc871d2 100644
--- a/src/Seloperator.c
+++ b/src/Seloperator.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Selrec.c b/src/Selrec.c
index 862d3ed..43b819c 100644
--- a/src/Selrec.c
+++ b/src/Selrec.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -64,7 +64,7 @@ void *Selrec(void *argument)
filetype = streamInqFiletype(streamID1);
if ( filetype == FILETYPE_NC || filetype == FILETYPE_NC2 || filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C )
- cdoAbort("This operator does not work on netCDF data!");
+ cdoAbort("This operator does not work on NetCDF data!");
vlistID1 = streamInqVlist(streamID1);
vlistID2 = vlistDuplicate(vlistID1);
@@ -112,5 +112,5 @@ void *Selrec(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Seltime.c b/src/Seltime.c
index eb7fa9b..30fd852 100644
--- a/src/Seltime.c
+++ b/src/Seltime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -22,9 +22,9 @@
Seltime seltime Select times
Seltime selhour Select hours
Seltime selday Select days
- Seltime selmon Select months
+ Seltime selmonth Select months
Seltime selyear Select years
- Seltime selseas Select seasons
+ Seltime selseason Select seasons
Seltime seldate Select dates
Seltime selsmon Select single month
*/
@@ -40,77 +40,58 @@
#include "list.h"
+void season_to_months(const char *season, int *imonths)
+{
+ const char *smons = "JFMAMJJASONDJFMAMJJASOND";
+ const int imons[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ assert(strlen(smons)==(sizeof(imons)/sizeof(int)));
+
+ size_t len = strlen(season);
+ if ( len == 3 && strcmp(season, "ANN") == 0 )
+ {
+ for ( size_t k = 0; k < 12; ++k ) imonths[k+1] = 1;
+ }
+ else
+ {
+ if ( len > 12 ) cdoAbort("Too many months %d (limit=12)!", (int)len);
+ // char *sstr = strcasestr(smons, season); // nonstandard extension
+ const char *sstr = strstr(smons, season);
+ if ( sstr == NULL ) cdoAbort("Season %s not available!", season);
+ size_t ks = (size_t)(sstr-smons);
+ size_t ke = ks + len;
+ for ( size_t k = ks; k < ke; ++k ) imonths[imons[k]]++;
+ }
+}
+
static
int seaslist(LIST *ilist)
{
- int i;
- char Seas[3];
- int seas[4] = {FALSE, FALSE, FALSE, FALSE};
- int imon[17]; /* 1-16 ! */
- int ival;
- size_t len;
-
- int season_start = get_season_start();
+ int imon[13]; /* 1-12 ! */
+ for ( int i = 0; i < 13; ++i ) imon[i] = 0;
+
int nsel = operatorArgc();
if ( isdigit(*operatorArgv()[0]))
- for ( i = 0; i < nsel; i++ )
- {
- ival = parameter2int(operatorArgv()[i]);
- if ( ival == 1 || ival == 13 ) seas[0] = TRUE;
- else if ( ival == 2 || ival == 14 ) seas[1] = TRUE;
- else if ( ival == 3 || ival == 15 ) seas[2] = TRUE;
- else if ( ival == 4 || ival == 16 ) seas[3] = TRUE;
- else cdoAbort("Season %d not available!", ival);
- }
- else
- for ( i = 0; i < nsel; i++ )
- {
- len = strlen(operatorArgv()[i]);
- if ( len > 3 ) len = 3;
- while ( len-- > 0 ) Seas[len] = toupper(operatorArgv()[i][len]);
- if ( season_start == START_DEC )
- {
- if ( memcmp(Seas, "DJF", 3) == 0 ) seas[0] = TRUE;
- else if ( memcmp(Seas, "MAM", 3) == 0 ) seas[1] = TRUE;
- else if ( memcmp(Seas, "JJA", 3) == 0 ) seas[2] = TRUE;
- else if ( memcmp(Seas, "SON", 3) == 0 ) seas[3] = TRUE;
- else cdoAbort("Season %s not available!", operatorArgv()[i]);
- }
- else
- {
- if ( memcmp(Seas, "JFM", 3) == 0 ) seas[0] = TRUE;
- else if ( memcmp(Seas, "AMJ", 3) == 0 ) seas[1] = TRUE;
- else if ( memcmp(Seas, "JAS", 3) == 0 ) seas[2] = TRUE;
- else if ( memcmp(Seas, "OND", 3) == 0 ) seas[3] = TRUE;
- else cdoAbort("Season %s not available!", operatorArgv()[i]);
- }
- }
-
- for ( i = 0; i < 17; ++i ) imon[i] = 0;
-
- if ( season_start == START_DEC )
{
- if ( seas[0] ) { imon[12]++; imon[ 1]++; imon[ 2]++; imon[13]++; }
- if ( seas[1] ) { imon[ 3]++; imon[ 4]++; imon[ 5]++; imon[14]++; }
- if ( seas[2] ) { imon[ 6]++; imon[ 7]++; imon[ 8]++; imon[15]++; }
- if ( seas[3] ) { imon[ 9]++; imon[10]++; imon[11]++; imon[16]++; }
+ for ( int i = 0; i < nsel; i++ )
+ {
+ int ival = parameter2int(operatorArgv()[i]);
+ if ( ival == 1 ) { imon[12]++; imon[ 1]++; imon[ 2]++; }
+ else if ( ival == 2 ) { imon[ 3]++; imon[ 4]++; imon[ 5]++; }
+ else if ( ival == 3 ) { imon[ 6]++; imon[ 7]++; imon[ 8]++; }
+ else if ( ival == 4 ) { imon[ 9]++; imon[10]++; imon[11]++; }
+ else cdoAbort("Season %d not available!", ival);
+ }
}
else
{
- if ( seas[0] ) { imon[ 1]++; imon[ 2]++; imon[ 3]++; imon[13]++; }
- if ( seas[1] ) { imon[ 4]++; imon[ 5]++; imon[ 6]++; imon[14]++; }
- if ( seas[2] ) { imon[ 7]++; imon[ 8]++; imon[ 9]++; imon[15]++; }
- if ( seas[3] ) { imon[10]++; imon[11]++; imon[12]++; imon[16]++; }
+ for ( int i = 0; i < nsel; i++ )
+ season_to_months(operatorArgv()[i], imon);
}
-
+
nsel = 0;
- for ( i = 1; i < 17; ++i )
- {
- if ( imon[i] )
- listSetInt(ilist, nsel++, i);
- }
+ for ( int i = 1; i < 13; ++i ) if ( imon[i] ) listSetInt(ilist, nsel++, i);
- return (nsel);
+ return nsel;
}
@@ -223,9 +204,9 @@ void *Seltime(void *argument)
int SELTIME = cdoOperatorAdd("seltime", func_time, 0, "times (format hh:mm:ss)");
int SELHOUR = cdoOperatorAdd("selhour", func_time, 0, "hours");
int SELDAY = cdoOperatorAdd("selday", func_date, 0, "days");
- int SELMON = cdoOperatorAdd("selmon", func_date, 0, "months");
+ int SELMONTH = cdoOperatorAdd("selmonth", func_date, 0, "months");
int SELYEAR = cdoOperatorAdd("selyear", func_date, 0, "years");
- int SELSEAS = cdoOperatorAdd("selseas", func_date, 0, "seasons");
+ int SELSEASON = cdoOperatorAdd("selseason", func_date, 0, "seasons");
int SELSMON = cdoOperatorAdd("selsmon", func_date, 0, "month[,nts1[,nts2]]");
int operatorID = cdoOperatorID();
@@ -237,7 +218,7 @@ void *Seltime(void *argument)
operatorInputArg(cdoOperatorEnter(operatorID));
- if ( operatorID == SELSEAS )
+ if ( operatorID == SELSEASON )
{
nsel = seaslist(ilist);
}
@@ -421,6 +402,10 @@ void *Seltime(void *argument)
selfound[0] = TRUE;
selfound[nsel-1] = TRUE;
}
+ else if ( selfval > fltarr[nsel-1] )
+ {
+ break;
+ }
}
else
{
@@ -603,8 +588,7 @@ void *Seltime(void *argument)
if ( its2 < nts2 )
cdoWarning("%d timesteps missing after the last month!", nts2-its2);
- if ( ! lcopy )
- if ( array ) Free(array);
+ if ( array ) Free(array);
for ( isel = 0; isel < nsel; isel++ )
{
@@ -652,7 +636,7 @@ void *Seltime(void *argument)
{
cdoWarning("Day %d not found!", intarr[isel]);
}
- else if ( operatorID == SELMON )
+ else if ( operatorID == SELMONTH )
{
cdoWarning("Month %d not found!", intarr[isel]);
}
@@ -660,7 +644,7 @@ void *Seltime(void *argument)
{
cdoWarning("Year %d not found!", intarr[isel]);
}
- else if ( operatorID == SELSEAS )
+ else if ( operatorID == SELSEASON )
{
if ( isel < 3 )
cdoWarning("Month %d not found!", intarr[isel]);
@@ -687,5 +671,5 @@ void *Seltime(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Selvar.c b/src/Selvar.c
index f0fd924..7cfb7a8 100644
--- a/src/Selvar.c
+++ b/src/Selvar.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -144,6 +144,7 @@ void *Selvar(void *argument)
int vlistID1 = streamInqVlist(streamID1);
int nvars = vlistNvars(vlistID1);
+ int *vars = (int*) Malloc(nvars*sizeof(int));
if ( operatorID == SELGRID && !args_are_numeric && nsel == 1 && strncmp(argnames[0], "var=", 4) == 0 )
{
@@ -170,6 +171,8 @@ void *Selvar(void *argument)
vlistClearFlag(vlistID1);
for ( varID = 0; varID < nvars; varID++ )
{
+ vars[varID] = FALSE;
+
vlistInqVarName(vlistID1, varID, varname);
vlistInqVarStdname(vlistID1, varID, stdname);
param = vlistInqVarParam(vlistID1, varID);
@@ -210,7 +213,7 @@ void *Selvar(void *argument)
}
else if ( operatorID == SELSTDNAME )
{
- found = strcmp(argnames[isel], stdname) == 0;
+ found = wildcardmatch(argnames[isel], stdname) == 0;
}
else if ( operatorID == SELLEVEL )
{
@@ -265,22 +268,30 @@ void *Selvar(void *argument)
{
vlistDefFlag(vlistID1, varID, levID, !INVERTS_SELECTION(operatorID));
selfound[isel] = TRUE;
+ vars[varID] = TRUE;
}
-
}
}
}
int npar = 0;
+ for ( varID = 0; varID < nvars; varID++ ) if ( vars[varID] ) npar++;
+
for ( varID = 0; varID < nvars; varID++ )
{
- zaxisID = vlistInqVarZaxis(vlistID1, varID);
- nlevs = zaxisInqSize(zaxisID);
-
- for ( levID = 0; levID < nlevs; levID++ )
- if ( vlistInqFlag(vlistID1, varID, levID) == TRUE ) break;
-
- if ( levID < nlevs ) npar++;
+ if ( vars[varID] )
+ {
+ int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+ if ( zaxisInqType(zaxisID) == ZAXIS_HYBRID )
+ {
+ int psvarid = vlist_get_psvarid(vlistID1, zaxisID);
+ if ( psvarid != -1 && !vars[psvarid] )
+ {
+ vars[psvarid] = TRUE;
+ vlistDefFlag(vlistID1, psvarid, 0, !INVERTS_SELECTION(operatorID));
+ }
+ }
+ }
}
for ( isel = 0; isel < nsel; isel++ )
@@ -408,6 +419,8 @@ void *Selvar(void *argument)
if ( ! lcopy )
if ( array ) Free(array);
+ if ( vars ) Free(vars);
+
if ( selfound ) Free(selfound);
listDelete(ilist);
@@ -415,5 +428,5 @@ void *Selvar(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Set.c b/src/Set.c
index bb90b0b..dbfeca3 100644
--- a/src/Set.c
+++ b/src/Set.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Setbox.c b/src/Setbox.c
index d5cb8b3..bd1538f 100644
--- a/src/Setbox.c
+++ b/src/Setbox.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Setgatt.c b/src/Setgatt.c
index 27573bc..bab54ae 100644
--- a/src/Setgatt.c
+++ b/src/Setgatt.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Setgrid.c b/src/Setgrid.c
index ff1a1f2..b02fce6 100644
--- a/src/Setgrid.c
+++ b/src/Setgrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Sethalo.c b/src/Sethalo.c
index 7b55569..9c8c0c1 100644
--- a/src/Sethalo.c
+++ b/src/Sethalo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Setmiss.c b/src/Setmiss.c
index 8328734..a1f15e9 100644
--- a/src/Setmiss.c
+++ b/src/Setmiss.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Setpartab.c b/src/Setpartab.c
index fdabb6e..6915c5f 100644
--- a/src/Setpartab.c
+++ b/src/Setpartab.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -598,8 +598,7 @@ void check_data(int vlistID2, int varID2, int varID, var_t *vars, long gridsize,
void *Setpartab(void *argument)
{
int nrecs;
- int recID, varID, levelID;
- int varID2, levelID2;
+ int varID, levelID;
int nmiss;
int delvars = FALSE;
int tableID = -1;
@@ -681,31 +680,54 @@ void *Setpartab(void *argument)
if ( tableformat == 0 )
{
- for ( varID = 0; varID < nvars; varID++ )
- vlistDefVarTable(vlistID2, varID, tableID);
+ /*
+ for ( int varID = 0; varID < nvars; varID++ )
+ vlistDefVarTable(vlistID2, varID, tableID);
+ */
+ char name[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
+ for ( int varID = 0; varID < nvars; varID++ )
+ {
+ int param = vlistInqVarParam(vlistID2, varID);
+ int pdis, pcat, pnum;
+ cdiDecodeParam(param, &pnum, &pcat, &pdis);
+ if ( pdis == 255 )
+ {
+ int code = pnum;
+ if ( tableInqParName(tableID, code, name) == 0 )
+ {
+ vlistDefVarName(vlistID2, varID, name);
+ longname[0] = 0;
+ tableInqParLongname(tableID, code, longname);
+ vlistDefVarLongname(vlistID2, varID, longname);
+ units[0] = 0;
+ tableInqParUnits(tableID, code, units);
+ vlistDefVarUnits(vlistID2, varID, units);
+ }
+ }
+ vlistDefVarTable(vlistID2, varID, tableID);
+ }
}
else
{
read_partab(ptmode, nvars, vlistID2, vars);
- for ( varID = 0; varID < nvars; ++varID )
- if ( vars[varID].remove ) break;
-
- if ( varID < nvars ) delvars = TRUE;
+ for ( int varID = 0; varID < nvars; ++varID )
+ if ( vars[varID].remove )
+ {
+ delvars = TRUE;
+ break;
+ }
if ( delvars )
{
- int levID, nlevs, zaxisID;
- int vlistIDx;
-
vlistClearFlag(vlistID1);
vlistClearFlag(vlistID2);
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = 0; varID < nvars; varID++ )
{
- zaxisID = vlistInqVarZaxis(vlistID2, varID);
- nlevs = zaxisInqSize(zaxisID);
- for ( levID = 0; levID < nlevs; levID++ )
+ int zaxisID = vlistInqVarZaxis(vlistID2, varID);
+ int nlevs = zaxisInqSize(zaxisID);
+ for ( int levID = 0; levID < nlevs; levID++ )
{
vlistDefFlag(vlistID1, varID, levID, TRUE);
vlistDefFlag(vlistID2, varID, levID, TRUE);
@@ -717,7 +739,7 @@ void *Setpartab(void *argument)
}
}
- vlistIDx = vlistCreate();
+ int vlistIDx = vlistCreate();
vlistCopyFlag(vlistIDx, vlistID2);
vlistDestroy(vlistID2);
@@ -725,7 +747,7 @@ void *Setpartab(void *argument)
vlistID2 = vlistIDx;
}
- for ( varID = 0; varID < nvars; ++varID )
+ for ( int varID = 0; varID < nvars; ++varID )
convertVarUnits(vars, varID, vars[varID].name);
}
@@ -749,12 +771,12 @@ void *Setpartab(void *argument)
streamDefTimestep(streamID2, tsID1);
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- varID2 = varID;
- levelID2 = levelID;
+ int varID2 = varID;
+ int levelID2 = levelID;
if ( delvars )
{
@@ -826,7 +848,7 @@ void *Setpartab(void *argument)
#if defined(HAVE_UDUNITS2)
UDUNITS_LOCK();
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = 0; varID < nvars; varID++ )
if ( vars[varID].ut_converter ) cv_free((cv_converter*)vars[varID].ut_converter);
if ( ut_read )
diff --git a/src/Setrcaname.c b/src/Setrcaname.c
index d7d4407..79b7b75 100644
--- a/src/Setrcaname.c
+++ b/src/Setrcaname.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Settime.c b/src/Settime.c
index f6fe1e7..81a873b 100644
--- a/src/Settime.c
+++ b/src/Settime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -35,6 +35,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
@@ -113,7 +114,7 @@ void *Settime(void *argument)
int nmiss;
int gridsize;
int tunit = TUNIT_DAY;
- int ijulinc = 0, incperiod = 0, incunit = 0;
+ int ijulinc = 0, incperiod = 1, incunit = 86400;
int year = 1, month = 1, day = 1, hour = 0, minute = 0, second = 0;
int day0;
int taxis_has_bounds, copy_timestep = FALSE;
@@ -174,10 +175,13 @@ void *Settime(void *argument)
if ( operatorArgc() == 3 )
{
const char *timeunits = operatorArgv()[2];
- incperiod = (int)strtol(timeunits, NULL, 10);
- if ( timeunits[0] == '-' || timeunits[0] == '+' ) timeunits++;
- while ( isdigit((int) *timeunits) ) timeunits++;
-
+ int ich = timeunits[0];
+ if ( ich == '-' || ich == '+' || isdigit(ich) )
+ {
+ incperiod = (int)strtol(timeunits, NULL, 10);
+ if ( ich == '-' || ich == '+' ) timeunits++;
+ while ( isdigit((int) *timeunits) ) timeunits++;
+ }
get_tunits(timeunits, &incperiod, &incunit, &tunit);
}
/* increment in seconds */
diff --git a/src/Setzaxis.c b/src/Setzaxis.c
index 2f94240..0adcc29 100644
--- a/src/Setzaxis.c
+++ b/src/Setzaxis.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Showinfo.c b/src/Showinfo.c
index e1a804c..b62d2c9 100644
--- a/src/Showinfo.c
+++ b/src/Showinfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Sinfo.c b/src/Sinfo.c
index bea40a0..9762015 100644
--- a/src/Sinfo.c
+++ b/src/Sinfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
#include "pstream.h"
#include "util.h"
+#include "cdi_uuid.h"
#include "printinfo.h"
const char *tunit2str(int tunits)
@@ -127,11 +128,11 @@ void *Sinfo(void *argument)
set_text_color(stdout, BRIGHT, BLACK);
if ( lensemble )
- fprintf(stdout, "%6d : Institut Source Ttype Einfo Levels Num Points Num Dtype : ", -(indf+1));
+ fprintf(stdout, "%6d : Institut Source Steptype Einfo Levels Num Points Num Dtype : ", -(indf+1));
else if ( nsubtypes > 0 )
- fprintf(stdout, "%6d : Institut Source Ttype Subtypes Levels Num Points Num Dtype : ", -(indf+1));
+ fprintf(stdout, "%6d : Institut Source Steptype Subtypes Levels Num Points Num Dtype : ", -(indf+1));
else
- fprintf(stdout, "%6d : Institut Source Ttype Levels Num Points Num Dtype : ", -(indf+1));
+ fprintf(stdout, "%6d : Institut Source Steptype Levels Num Points Num Dtype : ", -(indf+1));
if ( operfunc == func_name ) fprintf(stdout, "Parameter name");
else if ( operfunc == func_code ) fprintf(stdout, "Table Code");
diff --git a/src/Smooth9.c b/src/Smooth9.c
index b482901..53c44df 100644
--- a/src/Smooth9.c
+++ b/src/Smooth9.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Sort.c b/src/Sort.c
index 8941dbc..bebe4ac 100644
--- a/src/Sort.c
+++ b/src/Sort.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Sorttimestamp.c b/src/Sorttimestamp.c
index e9b4449..fe7fc79 100644
--- a/src/Sorttimestamp.c
+++ b/src/Sorttimestamp.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Specinfo.c b/src/Specinfo.c
index 71c8e11..406d964 100644
--- a/src/Specinfo.c
+++ b/src/Specinfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Spectral.c b/src/Spectral.c
index b4680d8..525ef47 100644
--- a/src/Spectral.c
+++ b/src/Spectral.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Spectrum.c b/src/Spectrum.c
index 8843729..3da32a5 100644
--- a/src/Spectrum.c
+++ b/src/Spectrum.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Split.c b/src/Split.c
index 44f38ed..b55743b 100644
--- a/src/Split.c
+++ b/src/Split.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Splitrec.c b/src/Splitrec.c
index c0d2605..f1d9371 100644
--- a/src/Splitrec.c
+++ b/src/Splitrec.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Splitsel.c b/src/Splitsel.c
index 71951db..71681f7 100644
--- a/src/Splitsel.c
+++ b/src/Splitsel.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -151,8 +151,11 @@ void *Splitsel(void *argument)
{
streamInqRecord(streamID1, &varID, &levelID);
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT )
- streamReadRecord(streamID1, vars[varID][levelID].ptr, &vars[varID][levelID].nmiss);
- }
+ {
+ streamReadRecord(streamID1, vars[varID][levelID].ptr, &nmiss);
+ vars[varID][levelID].nmiss = (size_t) nmiss;
+ }
+ }
}
index = 0;
diff --git a/src/Splittime.c b/src/Splittime.c
index 53589df..d7cdc6e 100644
--- a/src/Splittime.c
+++ b/src/Splittime.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Splityear.c b/src/Splityear.c
index 507a2b7..bf1333f 100644
--- a/src/Splityear.c
+++ b/src/Splityear.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/StringUtilities.c b/src/StringUtilities.c
index 2181dcd..aa9c91f 100644
--- a/src/StringUtilities.c
+++ b/src/StringUtilities.c
@@ -1,69 +1,68 @@
+#include "cdo_int.h"
#include "StringUtilities.h"
#define DBG 0
-int StringSplitWithSeperator( char *source_string, char *seperator, char*** ptr_split_string )
-
+int StringSplitWithSeperator(const char *source_string, const char *seperator, char*** ptr_split_string )
{
- char *duplicate_src = NULL, **temp_list = NULL , *temp_str = NULL, *saveptr;
- int n = 0, i;
- int str_len = 0, sep_count = 0;
+ char *duplicate_src = NULL, **temp_list = NULL , *temp_str = NULL, *saveptr;
+ int n = 0, i;
+ int str_len = 0, sep_count = 0;
- str_len = strlen( source_string );
+ str_len = strlen( source_string );
- if( !str_len )
- return 0;
+ if( !str_len )
+ return 0;
- if( DBG )
- fprintf(stderr, "StringSplitWithSeperator Input str %s , seperator %s \n", source_string, seperator );
+ if( DBG )
+ fprintf(stderr, "StringSplitWithSeperator Input str %s , seperator %s \n", source_string, seperator );
- duplicate_src = strdup(source_string);
+ duplicate_src = strdup(source_string);
- for( i = 0; i < str_len; i++ )
- {
- if( duplicate_src[i] == *seperator )
- sep_count++;
- }
+ for( i = 0; i < str_len; i++ )
+ {
+ if( duplicate_src[i] == *seperator )
+ sep_count++;
+ }
- temp_list = (char**) Malloc( sizeof( char* ) * (sep_count+1));
+ temp_list = (char**) Malloc( sizeof( char* ) * (sep_count+1));
- if( DBG )
- fprintf(stderr, "Input str %s , seperator %s sep count %d\n", duplicate_src, seperator, sep_count );
-
- while( ( temp_str = strtok_r( duplicate_src, seperator, &saveptr ) ) )
- {
- temp_list[n] = temp_str;
- n++;
- duplicate_src = saveptr;
- }
+ if( DBG )
+ fprintf(stderr, "Input str %s , seperator %s sep count %d\n", duplicate_src, seperator, sep_count );
+
+ while( ( temp_str = strtok_r( duplicate_src, seperator, &saveptr ) ) )
+ {
+ temp_list[n] = temp_str;
+ n++;
+ duplicate_src = saveptr;
+ }
- if( DBG )
- {
- for( i = 0; i < n; i++ )
- fprintf(stderr, "str %s \n", temp_list[i] );
- }
+ if( DBG )
+ {
+ for( i = 0; i < n; i++ )
+ fprintf(stderr, "str %s \n", temp_list[i] );
+ }
- *ptr_split_string = temp_list;
-
- return n;
+ *ptr_split_string = temp_list;
+
+ return n;
}
-
int IsNumeric (const char *s)
{
- char *ptr;
- if (s == NULL || *s == '\0' || isspace(*s))
- return 0;
+ char *ptr;
+ if (s == NULL || *s == '\0' || isspace(*s))
+ return 0;
- strtod (s, &ptr);
- return *ptr == '\0';
+ strtod (s, &ptr);
+ return *ptr == '\0';
}
void StrToUpperCase ( char *sPtr )
{
- while ( *sPtr != '\0' )
+ while ( *sPtr != '\0' )
{
*sPtr = toupper ( ( unsigned char ) *sPtr );
++sPtr;
@@ -73,7 +72,7 @@ void StrToUpperCase ( char *sPtr )
void StrToLowerCase ( char *sPtr )
{
- while ( *sPtr != '\0' )
+ while ( *sPtr != '\0' )
{
*sPtr = tolower ( ( unsigned char ) *sPtr );
++sPtr;
@@ -83,7 +82,6 @@ void StrToLowerCase ( char *sPtr )
/* To replace a single char with another single char in a given string */
void StrReplaceChar( char *str_in, char orig_char, char rep_char )
-
{
char *ref = NULL;
@@ -107,4 +105,3 @@ void StrReplaceChar( char *str_in, char orig_char, char rep_char )
return ;
}
-
diff --git a/src/StringUtilities.h b/src/StringUtilities.h
index 53d6988..25724dd 100644
--- a/src/StringUtilities.h
+++ b/src/StringUtilities.h
@@ -1,12 +1,7 @@
#ifndef STR_UTILITIES_H
#define STR_UTILITIES_H
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
-#include <ctype.h>
-
-int StringSplitWithSeperator( char *source_string, char *seperator, char*** ptr_split_string );
+int StringSplitWithSeperator(const char *source_string, const char *seperator, char*** ptr_split_string );
int IsNumeric (const char *s);
diff --git a/src/Subtrend.c b/src/Subtrend.c
index e364634..6ac1205 100644
--- a/src/Subtrend.c
+++ b/src/Subtrend.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -113,7 +113,7 @@ void *Subtrend(void *argument)
missval1 = missval;
missval2 = missval;
for ( i = 0; i < gridsize; i++ )
- field4.ptr[i] = SUB(field1.ptr[i], ADD(vars2[varID][levelID].ptr[i], MUL(vars3[varID][levelID].ptr[i], tsID)));
+ field4.ptr[i] = SUBMN(field1.ptr[i], ADDMN(vars2[varID][levelID].ptr[i], MULMN(vars3[varID][levelID].ptr[i], tsID)));
nmiss = 0;
for ( i = 0; i < gridsize; i++ )
diff --git a/src/Tee.c b/src/Tee.c
index 4b91160..73c3990 100644
--- a/src/Tee.c
+++ b/src/Tee.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Templates.c b/src/Templates.c
index 8954256..1a1b57f 100644
--- a/src/Templates.c
+++ b/src/Templates.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -23,39 +23,36 @@
void *Template1(void *argument)
{
- int streamID1, streamID2 = CDI_UNDEFID;
int nrecs;
- int tsID, recID, varID, levelID;
- int vlistID1, vlistID2;
- int taxisID1, taxisID2;
+ int recID, varID, levelID;
int lcopy = FALSE;
int gridsize, nmiss;
- double *array = NULL;
cdoInitialize(argument);
if ( UNCHANGED_RECORD ) lcopy = TRUE;
- streamID1 = streamOpenRead(cdoStreamName(0));
+ int streamID1 = streamOpenRead(cdoStreamName(0));
- vlistID1 = streamInqVlist(streamID1);
- vlistID2 = vlistDuplicate(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = vlistDuplicate(vlistID1);
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = taxisDuplicate(taxisID1);
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = taxisDuplicate(taxisID1);
vlistDefTaxis(vlistID2, taxisID2);
- streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+ int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
streamDefVlist(streamID2, vlistID2);
+ double *array = NULL;
if ( ! lcopy )
{
gridsize = vlistGridsizeMax(vlistID1);
array = (double*) Malloc(gridsize*sizeof(double));
}
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
taxisCopyTimestep(taxisID2, taxisID1);
@@ -86,8 +83,7 @@ void *Template1(void *argument)
vlistDestroy(vlistID2);
- if ( ! lcopy )
- if ( array ) Free(array);
+ if ( array ) Free(array);
cdoFinish();
@@ -97,34 +93,29 @@ void *Template1(void *argument)
void *Template2(void *argument)
{
- int streamID1, streamID2 = CDI_UNDEFID;
int nrecs;
- int tsID, recID, varID, levelID;
- int vlistID1, vlistID2;
- int gridsize;
+ int recID, varID, levelID;
int nmiss;
- int taxisID1, taxisID2;
- double *array = NULL;
cdoInitialize(argument);
- streamID1 = streamOpenRead(cdoStreamName(0));
+ int streamID1 = streamOpenRead(cdoStreamName(0));
- vlistID1 = streamInqVlist(streamID1);
- vlistID2 = vlistDuplicate(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = vlistDuplicate(vlistID1);
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = taxisDuplicate(taxisID1);
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = taxisDuplicate(taxisID1);
vlistDefTaxis(vlistID2, taxisID2);
- streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+ int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
streamDefVlist(streamID2, vlistID2);
- gridsize = vlistGridsizeMax(vlistID1);
- array = (double*) Malloc(gridsize*sizeof(double));
+ int gridsize = vlistGridsizeMax(vlistID1);
+ double *array = (double*) Malloc(gridsize*sizeof(double));
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
taxisCopyTimestep(taxisID2, taxisID1);
diff --git a/src/Test.c b/src/Test.c
index 07c8a14..e0c24bc 100644
--- a/src/Test.c
+++ b/src/Test.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Tests.c b/src/Tests.c
index d7ab0f6..9a87bc9 100644
--- a/src/Tests.c
+++ b/src/Tests.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Timcount.c b/src/Timcount.c
index 241230d..14ac303 100644
--- a/src/Timcount.c
+++ b/src/Timcount.c
@@ -49,6 +49,7 @@ void *Timcount(void *argument)
int streamID1, streamID2;
int vlistID1, vlistID2, taxisID1, taxisID2;
int nvars;
+ int nmiss;
int nwpv; // number of words per value; real:1 complex:2
int *recVarID, *recLevelID;
field_t **vars1 = NULL;
@@ -132,7 +133,8 @@ void *Timcount(void *argument)
vars1[varID][levelID].nmiss = gridsize;
}
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[varID][levelID].grid;
field.missval = vars1[varID][levelID].missval;
@@ -159,7 +161,7 @@ void *Timcount(void *argument)
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID][levelID].ptr, (int)vars1[varID][levelID].nmiss);
}
if ( nrecs == 0 ) break;
diff --git a/src/Timedt.c b/src/Timedt.c
new file mode 100644
index 0000000..981fea4
--- /dev/null
+++ b/src/Timedt.c
@@ -0,0 +1,121 @@
+/*
+ This file is part of CDO. CDO is a collection of Operators to
+ manipulate and analyse Climate model Data.
+
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ See COPYING file for copying and redistribution conditions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+/*
+ This module contains the following operators:
+
+ Timedt timedt Delta t
+*/
+
+
+#include <cdi.h>
+#include "cdo.h"
+#include "cdo_int.h"
+#include "pstream.h"
+
+
+void *Timedt(void *argument)
+{
+ int varID, levelID;
+ int nmiss;
+
+ cdoInitialize(argument);
+
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = vlistDuplicate(vlistID1);
+
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = taxisDuplicate(taxisID1);
+ vlistDefTaxis(vlistID2, taxisID2);
+
+ int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+ streamDefVlist(streamID2, vlistID2);
+
+ field_t **vars = field_malloc(vlistID1, FIELD_PTR);
+
+ int gridsizemax = vlistGridsizeMax(vlistID1);
+ double *array1 = (double*) Malloc(gridsizemax*sizeof(double));
+ double *array2 = (double*) Malloc(gridsizemax*sizeof(double));
+
+ int tsID = 0;
+ int nrecs = streamInqTimestep(streamID1, tsID);
+ for ( int recID = 0; recID < nrecs; ++recID )
+ {
+ streamInqRecord(streamID1, &varID, &levelID);
+ streamReadRecord(streamID1, vars[varID][levelID].ptr, &nmiss);
+ vars[varID][levelID].nmiss = nmiss;
+ }
+
+ tsID++;
+ int tsID2 = 0;
+ while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+ {
+ taxisCopyTimestep(taxisID2, taxisID1);
+ streamDefTimestep(streamID2, tsID2);
+
+ for ( int recID = 0; recID < nrecs; ++recID )
+ {
+ streamInqRecord(streamID1, &varID, &levelID);
+ streamReadRecord(streamID1, array1, &nmiss);
+
+ double missval = vars[varID][levelID].missval;
+ double *array0 = vars[varID][levelID].ptr;
+ int gridsize = vars[varID][levelID].size;
+ if ( nmiss || vars[varID][levelID].nmiss )
+ {
+ for ( int i = 0; i < gridsize; ++i )
+ {
+ if ( DBL_IS_EQUAL(array0[i], missval) || DBL_IS_EQUAL(array1[i], missval) )
+ array2[i] = missval;
+ else
+ array2[i] = array1[i] - array0[i];
+ }
+
+ nmiss = 0;
+ for ( int i = 0; i < gridsize; ++i )
+ if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
+ }
+ else
+ {
+ for ( int i = 0; i < gridsize; ++i )
+ array2[i] = array1[i] - array0[i];
+ }
+
+ for ( int i = 0; i < gridsize; ++i ) array0[i] = array1[i];
+
+ streamDefRecord(streamID2, varID, levelID);
+ streamWriteRecord(streamID2, array2, nmiss);
+ }
+
+ tsID++;
+ tsID2++;
+ }
+
+ free(array1);
+ free(array2);
+ field_free(vars, vlistID1);
+
+ streamClose(streamID2);
+ streamClose(streamID1);
+
+ cdoFinish();
+
+ return 0;
+}
diff --git a/src/Timselstat.c b/src/Timselstat.c
index 906e31b..a003dc2 100644
--- a/src/Timselstat.c
+++ b/src/Timselstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Timselstat timselmean Time range mean
Timselstat timselavg Time range average
Timselstat timselvar Time range variance
- Timselstat timselvar1 Time range variance [Divisor is (n-1)]
+ Timselstat timselvar1 Time range variance [Normalize by (n-1)]
Timselstat timselstd Time range standard deviation
- Timselstat timselstd1 Time range standard deviation [Divisor is (n-1)]
+ Timselstat timselstd1 Time range standard deviation [Normalize by (n-1)]
*/
@@ -75,7 +75,7 @@ void *Timselstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
int streamID1 = streamOpenRead(cdoStreamName(0));
@@ -159,7 +159,7 @@ void *Timselstat(void *argument)
if ( nsets == 0 )
{
streamReadRecord(streamID1, vars1[varID][levelID].ptr, &nmiss);
- vars1[varID][levelID].nmiss = nmiss;
+ vars1[varID][levelID].nmiss = (size_t)nmiss;
if ( nmiss > 0 || samp1[varID][levelID].ptr )
{
@@ -176,7 +176,8 @@ void *Timselstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[varID][levelID].grid;
field.missval = vars1[varID][levelID].missval;
@@ -268,7 +269,7 @@ void *Timselstat(void *argument)
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID][levelID].ptr, (int)vars1[varID][levelID].nmiss);
}
if ( nrecs == 0 ) break;
diff --git a/src/Timsort.c b/src/Timsort.c
index 0fa5c85..56fa368 100644
--- a/src/Timsort.c
+++ b/src/Timsort.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Timstat.c b/src/Timstat.c
index dd65735..5e21483 100644
--- a/src/Timstat.c
+++ b/src/Timstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,45 +24,45 @@
Timstat timmean Time mean
Timstat timavg Time average
Timstat timvar Time variance
- Timstat timvar1 Time variance [Divisor is (n-1)]
+ Timstat timvar1 Time variance [Normalize by (n-1)]
Timstat timstd Time standard deviation
- Timstat timstd1 Time standard deviation [Divisor is (n-1)]
+ Timstat timstd1 Time standard deviation [Normalize by (n-1)]
Hourstat hourmin Hourly minimum
Hourstat hourmax Hourly maximum
Hourstat hoursum Hourly sum
Hourstat hourmean Hourly mean
Hourstat houravg Hourly average
Hourstat hourvar Hourly variance
- Hourstat hourvar1 Hourly variance [Divisor is (n-1)]
+ Hourstat hourvar1 Hourly variance [Normalize by (n-1)]
Hourstat hourstd Hourly standard deviation
- Hourstat hourstd1 Hourly standard deviation [Divisor is (n-1)]
+ Hourstat hourstd1 Hourly standard deviation [Normalize by (n-1)]
Daystat daymin Daily minimum
Daystat daymax Daily maximum
Daystat daysum Daily sum
Daystat daymean Daily mean
Daystat dayavg Daily average
Daystat dayvar Daily variance
- Daystat dayvar1 Daily variance [Divisor is (n-1)]
+ Daystat dayvar1 Daily variance [Normalize by (n-1)]
Daystat daystd Daily standard deviation
- Daystat daystd1 Daily standard deviation [Divisor is (n-1)]
+ Daystat daystd1 Daily standard deviation [Normalize by (n-1)]
Monstat monmin Monthly minimum
Monstat monmax Monthly maximum
Monstat monsum Monthly sum
Monstat monmean Monthly mean
Monstat monavg Monthly average
Monstat monvar Monthly variance
- Monstat monvar1 Monthly variance [Divisor is (n-1)]
+ Monstat monvar1 Monthly variance [Normalize by (n-1)]
Monstat monstd Monthly standard deviation
- Monstat monstd1 Monthly standard deviation [Divisor is (n-1)]
+ Monstat monstd1 Monthly standard deviation [Normalize by (n-1)]
Yearstat yearmin Yearly minimum
Yearstat yearmax Yearly maximum
Yearstat yearsum Yearly sum
Yearstat yearmean Yearly mean
Yearstat yearavg Yearly average
Yearstat yearvar Yearly variance
- Yearstat yearvar1 Yearly variance [Divisor is (n-1)]
+ Yearstat yearvar1 Yearly variance [Normalize by (n-1)]
Yearstat yearstd Yearly standard deviation
- Yearstat yearstd1 Yearly standard deviation [Divisor is (n-1)]
+ Yearstat yearstd1 Yearly standard deviation [Normalize by (n-1)]
*/
@@ -72,20 +72,22 @@
#include "pstream.h"
+typedef struct {
+ short varID;
+ short levelID;
+} recinfo_t;
+
+
void *Timstat(void *argument)
{
+ enum {HOUR_LEN=4, DAY_LEN=6, MON_LEN=8, YEAR_LEN=10};
int timestat_date = TIMESTAT_MEAN;
- int gridsize;
- int vdate = 0, vtime = 0;
int vdate0 = 0, vtime0 = 0;
int nrecs;
- int varID, levelID, recID;
- long nsets;
- int i;
+ int varID, levelID;
int streamID3 = -1;
int vlistID3, taxisID3 = -1;
int nmiss;
- int nlevel;
int lvfrac = FALSE;
int nwpv; // number of words per value; real:1 complex:2
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
@@ -94,51 +96,51 @@ void *Timstat(void *argument)
cdoInitialize(argument);
- cdoOperatorAdd("timmin", func_min, DATE_LEN, NULL);
- cdoOperatorAdd("timmax", func_max, DATE_LEN, NULL);
- cdoOperatorAdd("timsum", func_sum, DATE_LEN, NULL);
- cdoOperatorAdd("timmean", func_mean, DATE_LEN, NULL);
- cdoOperatorAdd("timavg", func_avg, DATE_LEN, NULL);
- cdoOperatorAdd("timvar", func_var, DATE_LEN, NULL);
- cdoOperatorAdd("timvar1", func_var1, DATE_LEN, NULL);
- cdoOperatorAdd("timstd", func_std, DATE_LEN, NULL);
- cdoOperatorAdd("timstd1", func_std1, DATE_LEN, NULL);
- cdoOperatorAdd("yearmin", func_min, 10, NULL);
- cdoOperatorAdd("yearmax", func_max, 10, NULL);
- cdoOperatorAdd("yearsum", func_sum, 10, NULL);
- cdoOperatorAdd("yearmean", func_mean, 10, NULL);
- cdoOperatorAdd("yearavg", func_avg, 10, NULL);
- cdoOperatorAdd("yearvar", func_var, 10, NULL);
- cdoOperatorAdd("yearvar1", func_var1, 10, NULL);
- cdoOperatorAdd("yearstd", func_std, 10, NULL);
- cdoOperatorAdd("yearstd1", func_std1, 10, NULL);
- cdoOperatorAdd("monmin", func_min, 8, NULL);
- cdoOperatorAdd("monmax", func_max, 8, NULL);
- cdoOperatorAdd("monsum", func_sum, 8, NULL);
- cdoOperatorAdd("monmean", func_mean, 8, NULL);
- cdoOperatorAdd("monavg", func_avg, 8, NULL);
- cdoOperatorAdd("monvar", func_var, 8, NULL);
- cdoOperatorAdd("monvar1", func_var1, 8, NULL);
- cdoOperatorAdd("monstd", func_std, 8, NULL);
- cdoOperatorAdd("monstd1", func_std1, 8, NULL);
- cdoOperatorAdd("daymin", func_min, 6, NULL);
- cdoOperatorAdd("daymax", func_max, 6, NULL);
- cdoOperatorAdd("daysum", func_sum, 6, NULL);
- cdoOperatorAdd("daymean", func_mean, 6, NULL);
- cdoOperatorAdd("dayavg", func_avg, 6, NULL);
- cdoOperatorAdd("dayvar", func_var, 6, NULL);
- cdoOperatorAdd("dayvar1", func_var1, 6, NULL);
- cdoOperatorAdd("daystd", func_std, 6, NULL);
- cdoOperatorAdd("daystd1", func_std1, 6, NULL);
- cdoOperatorAdd("hourmin", func_min, 4, NULL);
- cdoOperatorAdd("hourmax", func_max, 4, NULL);
- cdoOperatorAdd("hoursum", func_sum, 4, NULL);
- cdoOperatorAdd("hourmean", func_mean, 4, NULL);
- cdoOperatorAdd("houravg", func_avg, 4, NULL);
- cdoOperatorAdd("hourvar", func_var, 4, NULL);
- cdoOperatorAdd("hourvar1", func_var1, 4, NULL);
- cdoOperatorAdd("hourstd", func_std, 4, NULL);
- cdoOperatorAdd("hourstd1", func_std1, 4, NULL);
+ cdoOperatorAdd("timmin", func_min, DATE_LEN, NULL);
+ cdoOperatorAdd("timmax", func_max, DATE_LEN, NULL);
+ cdoOperatorAdd("timsum", func_sum, DATE_LEN, NULL);
+ cdoOperatorAdd("timmean", func_mean, DATE_LEN, NULL);
+ cdoOperatorAdd("timavg", func_avg, DATE_LEN, NULL);
+ cdoOperatorAdd("timvar", func_var, DATE_LEN, NULL);
+ cdoOperatorAdd("timvar1", func_var1, DATE_LEN, NULL);
+ cdoOperatorAdd("timstd", func_std, DATE_LEN, NULL);
+ cdoOperatorAdd("timstd1", func_std1, DATE_LEN, NULL);
+ cdoOperatorAdd("yearmin", func_min, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearmax", func_max, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearsum", func_sum, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearmean", func_mean, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearavg", func_avg, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearvar", func_var, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearvar1", func_var1, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearstd", func_std, YEAR_LEN, NULL);
+ cdoOperatorAdd("yearstd1", func_std1, YEAR_LEN, NULL);
+ cdoOperatorAdd("monmin", func_min, MON_LEN, NULL);
+ cdoOperatorAdd("monmax", func_max, MON_LEN, NULL);
+ cdoOperatorAdd("monsum", func_sum, MON_LEN, NULL);
+ cdoOperatorAdd("monmean", func_mean, MON_LEN, NULL);
+ cdoOperatorAdd("monavg", func_avg, MON_LEN, NULL);
+ cdoOperatorAdd("monvar", func_var, MON_LEN, NULL);
+ cdoOperatorAdd("monvar1", func_var1, MON_LEN, NULL);
+ cdoOperatorAdd("monstd", func_std, MON_LEN, NULL);
+ cdoOperatorAdd("monstd1", func_std1, MON_LEN, NULL);
+ cdoOperatorAdd("daymin", func_min, DAY_LEN, NULL);
+ cdoOperatorAdd("daymax", func_max, DAY_LEN, NULL);
+ cdoOperatorAdd("daysum", func_sum, DAY_LEN, NULL);
+ cdoOperatorAdd("daymean", func_mean, DAY_LEN, NULL);
+ cdoOperatorAdd("dayavg", func_avg, DAY_LEN, NULL);
+ cdoOperatorAdd("dayvar", func_var, DAY_LEN, NULL);
+ cdoOperatorAdd("dayvar1", func_var1, DAY_LEN, NULL);
+ cdoOperatorAdd("daystd", func_std, DAY_LEN, NULL);
+ cdoOperatorAdd("daystd1", func_std1, DAY_LEN, NULL);
+ cdoOperatorAdd("hourmin", func_min, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourmax", func_max, HOUR_LEN, NULL);
+ cdoOperatorAdd("hoursum", func_sum, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourmean", func_mean, HOUR_LEN, NULL);
+ cdoOperatorAdd("houravg", func_avg, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourvar", func_var, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourvar1", func_var1, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourstd", func_std, HOUR_LEN, NULL);
+ cdoOperatorAdd("hourstd1", func_std1, HOUR_LEN, NULL);
int operatorID = cdoOperatorID();
int operfunc = cdoOperatorF1(operatorID);
@@ -147,7 +149,7 @@ void *Timstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
if ( operfunc == func_mean )
{
@@ -179,13 +181,19 @@ void *Timstat(void *argument)
if ( taxisInqType(taxisID2) == TAXIS_FORECAST ) taxisDefType(taxisID2, TAXIS_RELATIVE);
vlistDefTaxis(vlistID2, taxisID2);
- int nvars = vlistNvars(vlistID1);
- int nrecords = vlistNrecs(vlistID1);
+ int nvars = vlistNvars(vlistID1);
+ int maxrecs = vlistNrecs(vlistID1);
if ( cmplen == 0 && CDO_Reduce_Dim )
for ( varID = 0; varID < nvars; ++varID )
vlistDefVarTsteptype(vlistID2, varID, TSTEP_CONSTANT);
+ const char *freq = NULL;
+ if ( comparelen == DAY_LEN ) freq = "day";
+ else if ( comparelen == MON_LEN ) freq = "mon";
+ else if ( comparelen == YEAR_LEN ) freq = "year";
+ if ( freq ) vlistDefAttTxt(vlistID2, CDI_GLOBAL, "frequency", (int)strlen(freq), freq);
+
int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
streamDefVlist(streamID2, vlistID2);
@@ -218,19 +226,25 @@ void *Timstat(void *argument)
streamDefVlist(streamID3, vlistID3);
}
- int *recVarID = (int*) Malloc(nrecords*sizeof(int));
- int *recLevelID = (int*) Malloc(nrecords*sizeof(int));
+ recinfo_t *recinfo = (recinfo_t *) malloc(maxrecs*sizeof(recinfo_t));
dtlist_type *dtlist = dtlist_new();
dtlist_set_stat(dtlist, timestat_date);
dtlist_set_calendar(dtlist, taxisInqCalendar(taxisID1));
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
+ int FIELD_MEMTYPE = 0;
+ if ( CDO_Memtype == MEMTYPE_FLOAT ) FIELD_MEMTYPE = MEMTYPE_FLOAT;
+
field_t field;
field_init(&field);
- field.ptr = (double*) Malloc(gridsize*sizeof(double));
+ field.memtype = FIELD_MEMTYPE;
+ if ( FIELD_MEMTYPE == MEMTYPE_FLOAT )
+ field.ptrf = (float*) Malloc(gridsize*sizeof(float));
+ else
+ field.ptr = (double*) Malloc(gridsize*sizeof(double));
field_t **vars1 = field_malloc(vlistID1, FIELD_PTR);
field_t **samp1 = field_malloc(vlistID1, FIELD_NONE);
@@ -241,42 +255,44 @@ void *Timstat(void *argument)
int otsID = 0;
while ( TRUE )
{
- nsets = 0;
+ int nsets = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
dtlist_taxisInqTimestep(dtlist, taxisID1, nsets);
- vdate = dtlist_get_vdate(dtlist, nsets);
- vtime = dtlist_get_vtime(dtlist, nsets);
+ int vdate = dtlist_get_vdate(dtlist, nsets);
+ int vtime = dtlist_get_vtime(dtlist, nsets);
if ( nsets == 0 ) SET_DATE(indate2, vdate, vtime);
SET_DATE(indate1, vdate, vtime);
if ( DATE_IS_NEQ(indate1, indate2, cmplen) ) break;
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
if ( tsID == 0 )
{
- recVarID[recID] = varID;
- recLevelID[recID] = levelID;
+ recinfo[recID].varID = varID;
+ recinfo[recID].levelID = levelID;
}
- nwpv = vars1[varID][levelID].nwpv;
- gridsize = gridInqSize(vars1[varID][levelID].grid);
+ field_t *pvar1 = &vars1[varID][levelID];
+
+ nwpv = pvar1->nwpv;
+ gridsize = gridInqSize(pvar1->grid);
if ( nsets == 0 )
{
- streamReadRecord(streamID1, vars1[varID][levelID].ptr, &nmiss);
- vars1[varID][levelID].nmiss = nmiss;
+ streamReadRecord(streamID1, pvar1->ptr, &nmiss);
+ pvar1->nmiss = (size_t)nmiss;
if ( nmiss > 0 || samp1[varID][levelID].ptr )
{
if ( samp1[varID][levelID].ptr == NULL )
samp1[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
- for ( i = 0; i < nwpv*gridsize; i++ )
- if ( DBL_IS_EQUAL(vars1[varID][levelID].ptr[i], vars1[varID][levelID].missval) )
+ for ( int i = 0; i < nwpv*gridsize; i++ )
+ if ( DBL_IS_EQUAL(pvar1->ptr[i], pvar1->missval) )
samp1[varID][levelID].ptr[i] = 0;
else
samp1[varID][levelID].ptr[i] = 1;
@@ -284,42 +300,52 @@ void *Timstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
- field.grid = vars1[varID][levelID].grid;
- field.missval = vars1[varID][levelID].missval;
+ if ( CDO_Memtype == MEMTYPE_FLOAT )
+ streamReadRecordF(streamID1, field.ptrf, &nmiss);
+ else
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
+ field.size = gridsize;
+ field.grid = pvar1->grid;
+ field.missval = pvar1->missval;
if ( field.nmiss > 0 || samp1[varID][levelID].ptr )
{
if ( samp1[varID][levelID].ptr == NULL )
{
samp1[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
- for ( i = 0; i < nwpv*gridsize; i++ )
+ for ( int i = 0; i < nwpv*gridsize; i++ )
samp1[varID][levelID].ptr[i] = nsets;
}
- for ( i = 0; i < nwpv*gridsize; i++ )
- if ( !DBL_IS_EQUAL(field.ptr[i], vars1[varID][levelID].missval) )
+ for ( int i = 0; i < nwpv*gridsize; i++ )
+ if ( !DBL_IS_EQUAL(field.ptr[i], pvar1->missval) )
samp1[varID][levelID].ptr[i]++;
}
if ( lvarstd )
{
- farsumq(&vars2[varID][levelID], field);
- farsum(&vars1[varID][levelID], field);
+ field_t *pvar2 = &vars2[varID][levelID];
+ farsumq(pvar2, field);
+ farsum(pvar1, field);
}
else
{
- farfun(&vars1[varID][levelID], field, operfunc);
+ farfun(pvar1, field, operfunc);
}
}
}
if ( nsets == 0 && lvarstd )
- for ( varID = 0; varID < nvars; varID++ )
- {
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pvar2 = &vars2[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevel; levelID++ )
- farmoq(&vars2[varID][levelID], vars1[varID][levelID]);
+
+ farmoq(pvar2, *pvar1);
}
vdate0 = vdate;
@@ -331,42 +357,38 @@ void *Timstat(void *argument)
if ( nrecs == 0 && nsets == 0 ) break;
if ( lmean )
- for ( varID = 0; varID < nvars; varID++ )
- {
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevel; levelID++ )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- farcdiv(&vars1[varID][levelID], (double)nsets);
- else
- {
- // farround(&samp1[varID][levelID]); not necessary
- fardiv(&vars1[varID][levelID], samp1[varID][levelID]);
- }
- }
+
+ if ( samp1[varID][levelID].ptr == NULL )
+ farcdiv(pvar1, (double)nsets);
+ else
+ fardiv(pvar1, samp1[varID][levelID]);
}
else if ( lvarstd )
- for ( varID = 0; varID < nvars; varID++ )
- {
- if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevel; levelID++ )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- {
- if ( lstd )
- farcstd(&vars1[varID][levelID], vars2[varID][levelID], nsets, divisor);
- else
- farcvar(&vars1[varID][levelID], vars2[varID][levelID], nsets, divisor);
- }
- else
- {
- if ( lstd )
- farstd(&vars1[varID][levelID], vars2[varID][levelID], samp1[varID][levelID], divisor);
- else
- farvar(&vars1[varID][levelID], vars2[varID][levelID], samp1[varID][levelID], divisor);
- }
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pvar2 = &vars2[varID][levelID];
+
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
+
+ if ( samp1[varID][levelID].ptr == NULL )
+ {
+ if ( lstd ) farcstd(pvar1, *pvar2, nsets, divisor);
+ else farcvar(pvar1, *pvar2, nsets, divisor);
+ }
+ else
+ {
+ if ( lstd ) farstd(pvar1, *pvar2, samp1[varID][levelID], divisor);
+ else farvar(pvar1, *pvar2, samp1[varID][levelID], divisor);
}
}
@@ -379,35 +401,36 @@ void *Timstat(void *argument)
}
if ( lvfrac && operfunc == func_mean )
- for ( varID = 0; varID < nvars; varID++ )
- {
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevel = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevel; levelID++ )
- {
- nwpv = vars1[varID][levelID].nwpv;
- gridsize = gridInqSize(vars1[varID][levelID].grid);
- missval = vars1[varID][levelID].missval;
- if ( samp1[varID][levelID].ptr )
- {
- int irun = 0;
- for ( i = 0; i < nwpv*gridsize; ++i )
- {
- if ( (samp1[varID][levelID].ptr[i] / nsets) < vfrac )
- {
- vars1[varID][levelID].ptr[i] = missval;
- irun++;
- }
- }
-
- if ( irun )
- {
- nmiss = 0;
- for ( i = 0; i < nwpv*gridsize; ++i )
- if ( DBL_IS_EQUAL(vars1[varID][levelID].ptr[i], missval) ) nmiss++;
- vars1[varID][levelID].nmiss = nmiss;
- }
- }
+
+ nwpv = pvar1->nwpv;
+ gridsize = gridInqSize(pvar1->grid);
+ missval = pvar1->missval;
+ if ( samp1[varID][levelID].ptr )
+ {
+ int irun = 0;
+ for ( int i = 0; i < nwpv*gridsize; ++i )
+ {
+ if ( (samp1[varID][levelID].ptr[i] / nsets) < vfrac )
+ {
+ pvar1->ptr[i] = missval;
+ irun++;
+ }
+ }
+
+ if ( irun )
+ {
+ nmiss = 0;
+ for ( int i = 0; i < nwpv*gridsize; ++i )
+ if ( DBL_IS_EQUAL(pvar1->ptr[i], missval) ) nmiss++;
+ pvar1->nmiss = (size_t)nmiss;
+ }
}
}
@@ -420,15 +443,17 @@ void *Timstat(void *argument)
streamDefTimestep(streamID3, otsID);
}
- for ( recID = 0; recID < nrecords; recID++ )
+ for ( int recID = 0; recID < maxrecs; recID++ )
{
- varID = recVarID[recID];
- levelID = recLevelID[recID];
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, pvar1->ptr, (int)pvar1->nmiss);
+
if ( cdoDiag )
{
if ( samp1[varID][levelID].ptr )
@@ -455,9 +480,7 @@ void *Timstat(void *argument)
streamClose(streamID1);
if ( field.ptr ) Free(field.ptr);
-
- if ( recVarID ) Free(recVarID);
- if ( recLevelID ) Free(recLevelID);
+ Free(recinfo);
cdoFinish();
diff --git a/src/Timstat2.c b/src/Timstat2.c
index b33791e..9b73a70 100644
--- a/src/Timstat2.c
+++ b/src/Timstat2.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -42,19 +42,19 @@ int correlation_t(long gridsize, double missval1, double missval2, int *nofvals,
if ( nvals > 0 )
{
- temp0 = MUL(work0[i], work1[i]);
- temp1 = SUB(work4[i], DIV(temp0, nvals));
- temp2 = MUL(work0[i], work0[i]);
- temp3 = MUL(work1[i], work1[i]);
- temp4 = SUB(work2[i], DIV(temp2, nvals));
- temp5 = SUB(work3[i], DIV(temp3, nvals));
- temp6 = MUL(temp4, temp5);
-
- cor = DIV(temp1, SQRT(temp6));
- /*
- if ( cor < -1) cor = -1;
- else if ( cor > 1) cor = 1;
- */
+ temp0 = MULMN(work0[i], work1[i]);
+ temp1 = SUBMN(work4[i], DIVMN(temp0, nvals));
+ temp2 = MULMN(work0[i], work0[i]);
+ temp3 = MULMN(work1[i], work1[i]);
+ temp4 = SUBMN(work2[i], DIVMN(temp2, nvals));
+ temp5 = SUBMN(work3[i], DIVMN(temp3, nvals));
+ temp6 = MULMN(temp4, temp5);
+
+ cor = DIVMN(temp1, SQRTMN(temp6));
+
+ if ( cor < -1 ) cor = -1;
+ else if ( cor > 1 ) cor = 1;
+
if ( DBL_IS_EQUAL(cor, missval1) ) nmiss++;
}
else
@@ -87,8 +87,8 @@ int covariance_t(long gridsize, double missval1, double missval2, int *nofvals,
if ( nvals > 0 )
{
- temp = DIV(MUL(work0[i], work1[i]), dnvals*dnvals);
- covar = SUB(DIV(work2[i], dnvals), temp);
+ temp = DIVMN( MULMN(work0[i], work1[i]), dnvals*dnvals);
+ covar = SUBMN( DIVMN(work2[i], dnvals), temp);
if ( DBL_IS_EQUAL(covar, missval1) ) nmiss++;
}
diff --git a/src/Timstat3.c b/src/Timstat3.c
index 05060d3..84f6a00 100644
--- a/src/Timstat3.c
+++ b/src/Timstat3.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -44,7 +44,7 @@ void *Timstat3(void *argument)
int nlevs;
int i, iw, is;
int varID, recID, levelID, gridID;
- int nmiss3;
+ int nmiss;
double rconst, risk;
double fnvals0, fnvals1;
double missval, missval1, missval2;
@@ -190,8 +190,9 @@ void *Timstat3(void *argument)
recLevelID[recID] = levelID;
}
- streamReadRecord(streamID[is], in[is].ptr, &in[is].nmiss);
-
+ streamReadRecord(streamID[is], in[is].ptr, &nmiss);
+ in[is].nmiss = (size_t) nmiss;
+
for ( i = 0; i < gridsize; ++i )
{
/*
@@ -235,11 +236,11 @@ void *Timstat3(void *argument)
fnvals0 = iwork[0][varID][levelID][i];
fnvals1 = iwork[1][varID][levelID][i];
- temp0 = DIV(MUL(fwork[0][varID][levelID].ptr[i], fwork[0][varID][levelID].ptr[i]), fnvals0);
- temp1 = DIV(MUL(fwork[2][varID][levelID].ptr[i], fwork[2][varID][levelID].ptr[i]), fnvals1);
- temp2 = SUB(fwork[1][varID][levelID].ptr[i], temp0);
- temp3 = SUB(fwork[3][varID][levelID].ptr[i], temp1);
- statistic = DIV(temp2, ADD(temp2, MUL(rconst, temp3)));
+ temp0 = DIVMN( MULMN(fwork[0][varID][levelID].ptr[i], fwork[0][varID][levelID].ptr[i]), fnvals0);
+ temp1 = DIVMN( MULMN(fwork[2][varID][levelID].ptr[i], fwork[2][varID][levelID].ptr[i]), fnvals1);
+ temp2 = SUBMN(fwork[1][varID][levelID].ptr[i], temp0);
+ temp3 = SUBMN(fwork[3][varID][levelID].ptr[i], temp1);
+ statistic = DIVMN(temp2, ADDMN(temp2, MULMN(rconst, temp3)));
if ( fnvals0 <= 1 || fnvals1 <= 1 )
fractil_1 = fractil_2 = missval1;
@@ -271,35 +272,35 @@ void *Timstat3(void *argument)
for ( j = 0; j < n_in; j++ )
{
fnvals = iwork[j][varID][levelID][i];
- tmp = DIV(MUL(fwork[2*j][varID][levelID].ptr[i], fwork[2*j][varID][levelID].ptr[i]), fnvals);
- temp0 = ADD(temp0, DIV(SUB(fwork[2*j+1][varID][levelID].ptr[i], tmp), var_factor[j]));
- deg_of_freedom = ADD(deg_of_freedom, fnvals);
+ tmp = DIVMN( MULMN(fwork[2*j][varID][levelID].ptr[i], fwork[2*j][varID][levelID].ptr[i]), fnvals);
+ temp0 = ADDMN(temp0, DIVMN( SUBMN(fwork[2*j+1][varID][levelID].ptr[i], tmp), var_factor[j]));
+ deg_of_freedom = ADDMN(deg_of_freedom, fnvals);
}
if ( !DBL_IS_EQUAL(temp0, missval1) && temp0 < 0 ) /* This is possible because */
temp0 = 0; /* of rounding errors */
- stddev_estimator = SQRT(DIV(temp0, deg_of_freedom));
+ stddev_estimator = SQRTMN( DIVMN(temp0, deg_of_freedom));
mean_estimator = -rconst;
for ( j = 0; j < n_in; j++ )
{
fnvals = iwork[j][varID][levelID][i];
- mean_estimator = ADD(mean_estimator,
- MUL(mean_factor[j],
- DIV(fwork[2*j][varID][levelID].ptr[i], fnvals)));
+ mean_estimator = ADDMN(mean_estimator,
+ MULMN(mean_factor[j],
+ DIVMN(fwork[2*j][varID][levelID].ptr[i], fnvals)));
}
temp1 = 0;
for ( j = 0; j < n_in; j++ )
{
fnvals = iwork[j][varID][levelID][i];
- temp1 = ADD(temp1, DIV(MUL(MUL(mean_factor[j], mean_factor[j]),
+ temp1 = ADDMN(temp1, DIVMN( MULMN( MULMN(mean_factor[j], mean_factor[j]),
var_factor[j]), fnvals));
}
- norm = SQRT(temp1);
+ norm = SQRTMN(temp1);
- temp2 = DIV(DIV(mean_estimator, norm), stddev_estimator);
+ temp2 = DIVMN( DIVMN(mean_estimator, norm), stddev_estimator);
fractil = deg_of_freedom < 1 ? missval1 :
student_t_inv (deg_of_freedom, 1 - risk/2, __func__);
@@ -308,12 +309,12 @@ void *Timstat3(void *argument)
}
}
- nmiss3 = 0;
+ nmiss = 0;
for ( i = 0; i < gridsize; i++ )
- if ( DBL_IS_EQUAL(out[0].ptr[i], missval1) ) nmiss3++;
+ if ( DBL_IS_EQUAL(out[0].ptr[i], missval1) ) nmiss++;
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, out[0].ptr, nmiss3);
+ streamWriteRecord(streamID3, out[0].ptr, nmiss);
}
for ( varID = 0; varID < nvars; varID++ )
diff --git a/src/Tinfo.c b/src/Tinfo.c
index c4b84aa..a4d21a1 100644
--- a/src/Tinfo.c
+++ b/src/Tinfo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
diff --git a/src/Tocomplex.c b/src/Tocomplex.c
index fd55574..2e6630b 100644
--- a/src/Tocomplex.c
+++ b/src/Tocomplex.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -123,5 +123,5 @@ void *Tocomplex(void *argument)
cdoFinish();
- return (NULL);
+ return 0;
}
diff --git a/src/Transpose.c b/src/Transpose.c
index d1d217d..27c64e4 100644
--- a/src/Transpose.c
+++ b/src/Transpose.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Trend.c b/src/Trend.c
index 322589f..b143ef3 100644
--- a/src/Trend.c
+++ b/src/Trend.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -145,14 +145,14 @@ void *Trend(void *argument)
for ( i = 0; i < gridsize; i++ )
{
- temp1 = SUB(work[2][varID][levelID].ptr[i],
- DIV(MUL(work[0][varID][levelID].ptr[i], work[3][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
- temp2 = SUB(work[1][varID][levelID].ptr[i],
- DIV(MUL(work[0][varID][levelID].ptr[i], work[0][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
-
- field2.ptr[i] = DIV(temp1, temp2);
- field1.ptr[i] = SUB(DIV(work[3][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]),
- MUL(DIV(work[0][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]), field2.ptr[i]));
+ temp1 = SUBMN(work[2][varID][levelID].ptr[i],
+ DIVMN( MULMN(work[0][varID][levelID].ptr[i], work[3][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
+ temp2 = SUBMN(work[1][varID][levelID].ptr[i],
+ DIVMN( MULMN(work[0][varID][levelID].ptr[i], work[0][varID][levelID].ptr[i]), work[4][varID][levelID].ptr[i]));
+
+ field2.ptr[i] = DIVMN(temp1, temp2);
+ field1.ptr[i] = SUBMN( DIVMN(work[3][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]),
+ MULMN( DIVMN(work[0][varID][levelID].ptr[i], work[4][varID][levelID].ptr[i]), field2.ptr[i]));
}
nmiss = 0;
diff --git a/src/Trms.c b/src/Trms.c
index 026731b..8c25e67 100644
--- a/src/Trms.c
+++ b/src/Trms.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -50,12 +50,12 @@ void trms(field_t field1, field_t field2, double *dp, field_t *field3)
for ( i = 0; i < len; i++ )
{
wp = w[i]*dp[k*len+i];
- rsum = ADD(rsum, MUL(wp, MUL(SUB(array2[k*len+i], array1[k*len+i]),
- SUB(array2[k*len+i], array1[k*len+i]))));
- rsumw = ADD(rsumw, wp);
+ rsum = ADDMN(rsum, MULMN(wp, MULMN( SUBMN(array2[k*len+i], array1[k*len+i]),
+ SUBMN(array2[k*len+i], array1[k*len+i]))));
+ rsumw = ADDMN(rsumw, wp);
}
- ravg = SQRT(DIV(rsum, rsumw));
+ ravg = SQRTMN( DIVMN(rsum, rsumw));
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
diff --git a/src/Tstepcount.c b/src/Tstepcount.c
index 94267f9..89acbae 100644
--- a/src/Tstepcount.c
+++ b/src/Tstepcount.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Vargen.c b/src/Vargen.c
index 4e89d3d..2a8237a 100644
--- a/src/Vargen.c
+++ b/src/Vargen.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -400,7 +400,7 @@ void *Vargen(void *argument)
if ( operatorID == RANDOM )
{
for ( i = 0; i < gridsize; i++ )
- array[i] = rand()/(RAND_MAX+1.0);
+ array[i] = ((double)rand())/((double)RAND_MAX);
}
else if ( operatorID == SINCOS || operatorID == COSHILL )
{
diff --git a/src/Varrms.c b/src/Varrms.c
index 0a68f2c..c36b6fc 100644
--- a/src/Varrms.c
+++ b/src/Varrms.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Verifygrid.c b/src/Verifygrid.c
new file mode 100644
index 0000000..496ffb6
--- /dev/null
+++ b/src/Verifygrid.c
@@ -0,0 +1,1188 @@
+/*
+ This file is part of CDO. CDO is a collection of Operators to
+ manipulate and analyse Climate model Data.
+
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ See COPYING file for copying and redistribution conditions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+/*
+ This module contains the following operators:
+*/
+
+#if defined(HAVE_CONFIG_H)
+# include "config.h" /* VERSION */
+#endif
+
+#include <cdi.h>
+#include "cdo.h"
+#include "cdo_int.h"
+#include "grid.h"
+#include "pstream.h"
+#include "clipping/geometry.h"
+#include "clipping/clipping.c"
+#include "math.h"
+
+struct axis {
+ double axis_vector[3];
+};
+
+static double Euclidean_norm (double a[]) {
+
+ /* Computes the Euclidean norm of a vector given in Cartesian coordinates. */
+
+ return sqrt(pow(a[0],2) + pow(a[1],2) + pow(a[2],2));
+}
+
+static struct axis divide_by_scalar (struct axis a, double scalar) {
+
+ /* Component-wise scalar division of a three dimensional axis vector given in Cartesian coordinates. */
+
+ a.axis_vector[0] = a.axis_vector[0]/scalar;
+ a.axis_vector[1] = a.axis_vector[1]/scalar;
+ a.axis_vector[2] = a.axis_vector[2]/scalar;
+
+ return a;
+}
+
+static struct axis normalize_vector(struct axis a){
+
+ /* Normalizes an axis vector a by dividing it though its magnitude. */
+
+ a = divide_by_scalar(a, Euclidean_norm(a.axis_vector));
+
+ return a;
+}
+
+static struct axis compute_the_new_z_axis(double cell_corners_in_Euclidean_space[]){
+
+ /* Takes the first three corners/vertices of the cell and computes two edges originating at the first corner/vertex. These two edges are on the same plane as all the other vertices. THERE NEED TO BE AT LEAST THREE CORNERS. */
+
+ double edge_one[3] = {(cell_corners_in_Euclidean_space)[3 + 0] -(cell_corners_in_Euclidean_space)[0],
+ (cell_corners_in_Euclidean_space)[3 + 1] -(cell_corners_in_Euclidean_space)[1],
+ (cell_corners_in_Euclidean_space)[3 + 2] -(cell_corners_in_Euclidean_space)[2]};
+
+ double edge_two[3] = {(cell_corners_in_Euclidean_space)[6 + 0] - (cell_corners_in_Euclidean_space)[0],
+ (cell_corners_in_Euclidean_space)[6 + 1] - (cell_corners_in_Euclidean_space)[1],
+ (cell_corners_in_Euclidean_space)[6 + 2] - (cell_corners_in_Euclidean_space)[2]};
+
+ struct axis new_z_axis;
+
+ /* The cross product of the two edges is the surface normal and the new z-axis. crossproduct_d is defined in clipping/geometry.h */
+
+ crossproduct_d(edge_one, edge_two, new_z_axis.axis_vector);
+
+ new_z_axis = normalize_vector(new_z_axis);
+
+ return new_z_axis;
+}
+
+
+static struct axis compute_the_new_y_axis(struct axis new_z_axis){
+
+ /* Then the new y-axis is the result of the cross product of the new z-axis and the old x-axis. crossproduct_d is defined in clipping/geometry.h */
+
+ struct axis old_x_axis;
+
+ old_x_axis.axis_vector[0] = 1;
+ old_x_axis.axis_vector[1] = 0;
+ old_x_axis.axis_vector[2] = 0;
+
+ struct axis new_y_axis;
+
+ crossproduct_d(new_z_axis.axis_vector, old_x_axis.axis_vector, new_y_axis.axis_vector);
+
+ new_y_axis = normalize_vector(new_y_axis);
+
+ return new_y_axis;
+}
+
+static struct axis compute_the_new_x_axis(struct axis new_z_axis, struct axis new_y_axis){
+
+ /* The new x-axis is the result of the cross product of the new z-axis and the new y-axis. crossproduct_d is defined in clipping/geometry.h */
+
+ struct axis new_x_axis;
+
+ crossproduct_d(new_y_axis.axis_vector, new_z_axis.axis_vector, new_x_axis.axis_vector);
+
+ new_x_axis = normalize_vector(new_x_axis);
+
+ return new_x_axis;
+}
+
+static void project_Euclidean_corner_coordinates_onto_the_cell_plane(struct axis new_x_axis, struct axis new_y_axis, double (*p_cell_corners_in_Euclidean_space)[30], double (*p_cell_corners_on_cell_plane)[20], int ncorners){
+
+ /* All corner points are projected onto the new x- and y-axes. dotproduct is defined in clipping/clipping.c */
+
+ double corner_vector[3];
+
+ for (int corner_no = 0; corner_no < ncorners; corner_no++){
+
+ for (int vector_component = 0; vector_component < 3; ++vector_component){
+ corner_vector[vector_component] = (*p_cell_corners_in_Euclidean_space)[(corner_no * 3) + vector_component];
+ }
+
+ (*p_cell_corners_on_cell_plane)[(corner_no * 2) + 0] = dotproduct(new_x_axis.axis_vector, corner_vector);
+ (*p_cell_corners_on_cell_plane)[(corner_no * 2) + 1] = dotproduct(new_y_axis.axis_vector, corner_vector);
+
+ }
+
+ /* The last vertex is set to be the same as the first one in order to close the cell.*/
+
+ (*p_cell_corners_on_cell_plane)[(ncorners * 2) + 0] = (*p_cell_corners_on_cell_plane)[0];
+ (*p_cell_corners_on_cell_plane)[(ncorners * 2) + 1] = (*p_cell_corners_on_cell_plane)[1];
+
+ /*
+ printf("The coordinates of the cell vertices on the cell plane are: ");
+
+ for (int corner_no =0; corner_no <= ncorners; corner_no++){
+ printf("(%f, %f) ", cell_corners_on_cell_plane[(corner_no * 2) + 0], cell_corners_on_cell_plane[(corner_no * 2) + 1]);
+ }
+
+ printf("\n\n");
+ */
+}
+
+static void project_Euclidean_center_coordinates_onto_the_cell_plane(struct axis new_x_axis, struct axis new_y_axis, double (*p_center_point_in_Euclidean_space)[3], double (*p_center_point_on_cell_plane)[2]){
+
+ /* The center point is projected onto the new x- and -y-axes. dotproduct is defined in clipping/clipping.c */
+
+ (*p_center_point_on_cell_plane)[0] = dotproduct((new_x_axis.axis_vector), (*p_center_point_in_Euclidean_space));
+ (*p_center_point_on_cell_plane)[1] = dotproduct((new_y_axis.axis_vector), (*p_center_point_in_Euclidean_space));
+
+ /*
+ printf("The coordinates of the presumed center point of the cell on the cell plane are: (%f, %f)\n\n", (*p_center_point_on_cell_plane)[0], (*p_center_point_on_cell_plane)[1]);
+ */
+}
+
+static double is_point_left_of_edge(double point_on_line_1[2], double point_on_line_2[2], double point[2]){
+
+ /*
+ Computes whether a point is left of the line through point_on_line_1 and point_on_line_2. This is part of the solution to the point in polygon problem.
+ Returns 0 if the point is on the line, > 0 if the point is left of the line, and < 0 if the point is right of the line.
+ This algorithm is by Dan Sunday (geomalgorithms.com) and is completely free for use and modification.
+ */
+
+ /*
+ printf("Testing whether point (%f, %f) is left of the the edge from point (%f, %f) and point (%f, %f)... ", point[0], point[1], point_on_line_1[0], point_on_line_1[1], point_on_line_2[0], point_on_line_2[1]);
+ */
+ double answer = ((point_on_line_2[0] - point_on_line_1[0]) * (point[1] - point_on_line_1[1])
+ - (point[0] - point_on_line_1[0]) * (point_on_line_2[1] - point_on_line_1[1]));
+
+ if (answer == 0){
+ printf("the point lies on the edge.\n");
+ }
+
+ if (answer > 0){
+ printf("the point lies left of the edge.\n");
+ }
+
+ if (answer < 0){
+ printf("the point lies to the right of the edge.\n");
+ }
+
+ return answer;
+}
+
+static double is_point_left_of_edge_without_printfs(double point_on_line_1[2], double point_on_line_2[2], double point[2]){
+
+ /*
+ Computes whether a point is left of the line through point_on_line_1 and point_on_line_2. This is part of the solution to the point in polygon problem.
+ Returns 0 if the point is on the line, > 0 if the point is left of the line, and < 0 if the point is right of the line.
+ This algorithm is by Dan Sunday (geomalgorithms.com) and is completely free for use and modification.
+ */
+
+ /*
+ printf("Testing whether point (%f, %f) is left of the the edge from point (%f, %f) and point (%f, %f)... ", point[0], point[1], point_on_line_1[0], point_on_line_1[1], point_on_line_2[0], point_on_line_2[1]);
+ */
+ double answer = ((point_on_line_2[0] - point_on_line_1[0]) * (point[1] - point_on_line_1[1])
+ - (point[0] - point_on_line_1[0]) * (point_on_line_2[1] - point_on_line_1[1]));
+ return answer;
+}
+
+static int winding_numbers_algorithm_without_printfs(double cell_corners[], int number_corners, double point[]){
+
+ /*
+ Computes whether a point is inside the bounds of a cell. This is the solution to the point in polygon problem.
+ Returns 0 if the point is outside, returns 1 if the point is inside the cell.
+ Based on an algorithm by Dan Sunday (geomalgorithms.com). His algorithm is completely free for use and modification.
+ */
+
+ int winding_number = 0;
+
+ for (int i = 0; i < number_corners; i++){
+ if (cell_corners[i * 2 + 1] <= point[1]){
+ if (cell_corners[(i + 1) * 2 + 1] > point[1]){
+
+ double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
+ double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
+
+ if (is_point_left_of_edge_without_printfs(point_on_edge_1, point_on_edge_2, point) > 0){
+ winding_number++;
+ }
+ }
+ }
+ else {
+ if (cell_corners[(i + 1) * 2 + 1] <= point[1]){
+
+ double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
+ double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
+
+ if (is_point_left_of_edge_without_printfs(point_on_edge_1, point_on_edge_2, point) < 0){
+ winding_number--;
+ }
+ }
+ }
+ }
+ return winding_number;
+}
+
+static int winding_numbers_algorithm_with_printfs(double cell_corners[], int number_corners, double point[]){
+
+ /*
+ Computes whether a point is inside the bounds of a cell. This is the solution to the point in polygon problem.
+ Returns 0 if the point is outside, returns 1 if the point is inside the cell.
+ Based on an algorithm by Dan Sunday (geomalgorithms.com). His algorithm is completely free for use and modification.
+ */
+
+ printf("Checking if the presumed center point lies within the bounds of the cell ... \n\n");
+
+ int winding_number = 0;
+
+ for (int i = 0; i < number_corners; i++){
+ printf("Edge number %u from vertex (%f, %f) to vertex (%f, %f):\n\n", i+1, cell_corners[i * 2 + 0], cell_corners[i * 2 + 1], cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]);
+ if (cell_corners[i * 2 + 1] <= point[1]){
+ if (cell_corners[(i + 1) * 2 + 1] > point[1]){
+ printf("There is an upward crossing of the ray y = %f.\n", point[1]);
+
+ double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
+ double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
+
+ if (is_point_left_of_edge(point_on_edge_1, point_on_edge_2, point) > 0){
+ winding_number++;
+ printf("The upward edge crossing happened on the right side of the presumed center point. The new winding number is increased to %u.\n", winding_number);
+ }
+ else {
+ printf("The downward edge crossing happened on the left side of the presumed center point. The winding number remains unchanged.\n");
+ }
+ }
+ else {
+ printf("There is NO crossing of the ray y = %f.\n", point[1]);
+ }
+ }
+ else {
+ if (cell_corners[(i + 1) * 2 + 1] <= point[1]){
+ printf("There is a downward crossing of the ray y = %f.\n", point[1]);
+
+ double point_on_edge_1[2] = {cell_corners[i * 2 + 0], cell_corners[i * 2 + 1]};
+ double point_on_edge_2[2] = {cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 1) * 2 + 1]};
+
+ if (is_point_left_of_edge(point_on_edge_1, point_on_edge_2, point) < 0){
+ winding_number--;
+ printf("The downward edge crossing happened on the right side of the presumed center point. The new winding number is decreased to %u.\n", winding_number);
+ }
+ else {
+ printf("The downward edge crossing happened on the left side of the presumed center point. The winding number remains unchanged.\n");
+ }
+ }
+ else {
+ printf("There is NO crossing of the ray y = %f.\n", point[1]);
+ }
+ }
+ printf("\n");
+ }
+ return winding_number;
+}
+
+static double perp_dot_product(double vector_one[2], double vector_two[2]){
+
+ /*
+ The perp-dot product is used for testing if a simple polygon is convex. From Hill, F. S. Jr. "The Pleasures of 'Perp Dot' Products." Chapter II.5 in Graphics Gems IV, Academic Press, 1994
+ It uses a vector that is perpendicular to vector_one (rotated 90 degrees counterclockwise) to calculate the dot product with vector_two.
+ It is positive if vector_one is less than 90 degrees away from vector_two indicating a left turn between vector_one and vector_two, and is negative otherwise.
+ If all edges of a simple polygon wind the same way, it is convex.
+ */
+
+ return (vector_one[0] * vector_two[1]) - (vector_one[1] - vector_two[0]);
+
+}
+
+static double sign(double x){
+
+ /* Is +1 if x is positive, -1 if x is negative and 0 if x is zero.*/
+
+ return (x > 0) - (x < 0);
+}
+
+
+static int is_simple_polygon_convex(double cell_corners[], int number_corners){
+
+ /* Uses the perp-dot product to tell if a simple polygon, a cell, is convex. */
+
+ double direction = 0;
+
+ for (int i = 0; i < number_corners - 1; i++){
+
+ /* Tests in which direction edge B winds that is connected to edge A when walking along the polygon edges. Does so for all edges of the polygon. */
+
+ double edge_a[2] = {cell_corners[(i + 1) * 2 + 0] - cell_corners[i * 2 + 0], cell_corners[(i + 1) * 2 + 1] - cell_corners[i * 2 + 1]};
+ double edge_b[2] = {cell_corners[(i + 2) * 2 + 0] - cell_corners[(i + 1) * 2 + 0], cell_corners[(i + 2) * 2 + 1] - cell_corners[(i + 1) * 2 + 1]};
+
+ double turns_to = sign(perp_dot_product(edge_a, edge_b));
+
+ /* In the first iteration the direction of winding of the entire polygon is set. Better not be 0.*/
+
+ if (i == 1){
+ direction = turns_to;
+ }
+
+ if (sign(direction) != sign(turns_to)){
+ if (direction != 0){
+ return 0;
+ }
+ }
+ else{
+ direction = turns_to;
+ }
+ }
+ return 1;
+}
+
+static double calculate_twice_the_polygon_area(double cell_corners[], int number_corners){
+
+ /* This algorithm works with non-convex and even self-intersecting polygons. It results in twice the area of the polygon. */
+
+ double twice_the_polygon_area = 0;
+
+ for (int i = 0; i < number_corners - 1; i++){
+
+ twice_the_polygon_area += (cell_corners[(i + 1) * 2 + 0] - cell_corners[i * 2 + 0]) * (cell_corners[(i + 1) * 2 + 1] - cell_corners[i * 2 + 1]);
+ }
+ return twice_the_polygon_area;
+}
+
+static int are_polygon_vertices_arranged_in_clockwise_order(double twice_the_cell_area){
+
+ /* A positive area indicates a clockwise arrangement of vertices, a negative area a counterclockwise arrangement. There should be an area to begin with. */
+
+ double area_sign = sign(twice_the_cell_area);
+
+ if (area_sign > 0){
+ return 1;
+ }
+ if (area_sign < 0){
+ return 0;
+ }
+}
+
+
+
+double intlin(double x, double y1, double x1, double y2, double x2);
+
+static
+int pnpoly(int npol, double *xp, double *yp, double x, double y)
+{
+ int i, j, c = 0;
+
+ for (i = 0, j = npol-1; i < npol; j = i++) {
+ if ((((yp[i]<=y) && (y<yp[j])) ||
+ ((yp[j]<=y) && (y<yp[i]))) &&
+ (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
+
+ c = !c;
+ }
+ return c;
+}
+
+
+static
+double PolygonArea_old(int np, double *xp, double *yp)
+{
+ int i, j;
+ double area = 0;
+
+ for ( i = 0; i < np; i++ )
+ {
+ j = (i + 1) % np;
+ area += xp[i] * yp[j];
+ area -= yp[i] * xp[j];
+ }
+
+ area /= 2;
+ /* return(area < 0 ? -area : area); */
+ return (area);
+}
+
+
+static
+double PolygonArea(int np, double *xp, double *yp, double yc)
+{
+ int i, j;
+ double area = 0.;
+
+ /* Process area in Radians */
+
+ for ( i = 0; i < np; i++ )
+ {
+ j = (i + 1) % np;
+ area += DEG2RAD*xp[i] * DEG2RAD*yp[j];
+ area -= DEG2RAD*yp[i] * DEG2RAD*xp[j];
+ }
+ area *= 0.5 * cos(DEG2RAD*yc);
+ return (area);
+}
+
+static
+int ccw(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y)
+{
+ /*
+ This function says wether the point are orientated clockwise
+ +1 positive orientation
+ -1 negative orientation
+ 0 points are on a line --> no orientation
+
+ This is done by a comparision of the gradient of
+ dy1/dx1 = p1 - p0 vs.
+ dy2/dx2 = p2 - p0
+ To avoid singularities at dx1=0 OR dx2 = 0 we multiply with dx1*dx2
+ */
+ double dx1, dx2, dy1, dy2;
+
+ dx1 = p1x - p0x; dy1 = p1y - p0y;
+ dx2 = p2x - p0x; dy2 = p2y - p0y;
+ if ( dx1*dy2 > dy1*dx2 ) return +1;
+ if ( dx1*dy2 < dy1*dx2 ) return -1;
+ if ( (dx1*dx2 < 0 ) || (dy1*dy2 < 0)) return -1;
+ if ( (dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2)) return +1;
+
+ return 0;
+}
+
+static
+int intersect(double pix, double piy, double pjx, double pjy,
+ double pkx, double pky, double plx, double ply)
+{
+ /*This function returns if there is an intersection between the lines
+ line1 between pi and pj and
+ line2 between pk and pl,
+ whereas pi = (pix, piy).
+
+ This can done by means of ccw since the product of ccw(pi,pj,pk)*ccw(pi,pj,pl)
+ shows if pk and pl are on different or the same side(s) of the line1 (They must
+ have different signums to be on different sides).
+
+ Consequently if and ONLY IF pk as well as pl are on different sides of line1
+ AND pi as well as pj are on different sides of line2 there HAS TO be an intersection.
+ */
+
+ return ( ( ccw(pix, piy, pjx, pjy, pkx, pky) *
+ ccw(pix, piy, pjx, pjy, plx, ply) <= 0 ) &&
+ ( ccw(pkx, pky, plx, ply, pix, piy) *
+ ccw(pkx, pky, plx, ply, pjx, pjy) <= 0 ) );
+}
+
+static
+int check_ncorner(int ncorner, const double *lon_bounds, const double *lat_bounds)
+{
+ int ncorner_new = ncorner;
+ int k;
+
+ for ( k=ncorner-1; k>0; --k )
+ if ( IS_NOT_EQUAL(lon_bounds[k], lon_bounds[k-1]) ||
+ IS_NOT_EQUAL(lat_bounds[k], lat_bounds[k-1]) ) break;
+
+ if ( k < ncorner-1 ) ncorner_new = k+1;
+
+ return ncorner_new;
+}
+
+static
+void verify_grid(int gridsize, int ncorner,
+ double *grid_center_lon, double *grid_center_lat,
+ double *grid_corner_lon, double *grid_corner_lat)
+{
+ int i0, i, j, k, l;
+ int l0;
+ int nout;
+ int isinside, convex, alone, isnegative;
+ const int mnv = ncorner+1;
+ int cuts[mnv][mnv];
+ int *alone_cell;
+ int check_corners;
+ double lon, lat = 0;
+ double lon_bounds[mnv], lat_bounds[mnv];
+ double area, sumarea;
+
+ alone_cell = (int*) Malloc(gridsize*ncorner*sizeof(int));
+
+ check_corners = 0; /* don't execute corner checking (last loop) */
+ nout = 0;
+ sumarea = 0;
+ /*
+ for ( i = 0; i < gridsize; ++i )
+ {
+ lon = grid_center_lon[i];
+ lat = grid_center_lat[i];
+ for ( k = 0; k < ncorner; ++k )
+ {
+ lon_bounds[k] = grid_corner_lon[i*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+ if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
+ }
+ lon_bounds[ncorner] = lon_bounds[0];
+ lat_bounds[ncorner] = lat_bounds[0];
+ fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i+1, lon, lat);
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
+ fprintf(stdout, "\n");
+ }
+ */
+
+ /* Check if center is inside bounds of cell */
+ for ( i = 0; i < gridsize; ++i )
+ {
+ lon = grid_center_lon[i];
+ lat = grid_center_lat[i];
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ lon_bounds[k] = grid_corner_lon[i*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+ if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
+ }
+ lon_bounds[ncorner] = lon_bounds[0];
+ lat_bounds[ncorner] = lat_bounds[0];
+
+ isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
+
+ if ( !isinside ) nout++;
+ if ( !isinside && cdoVerbose )
+ {
+ if ( nout == 1 )
+ {
+ fprintf(stdout,"\n CENTER IS OUT OF BOUNDS");
+ fprintf(stdout,"\n :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " Corner %2i : ", k+1);
+ fprintf(stdout,"\n Number Index center_lon center_lat area*10^6 :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k+1, k+1);
+ fprintf(stdout, "\n");
+ }
+ area = PolygonArea(ncorner+1, lon_bounds, lat_bounds,lat);
+ fprintf(stdout, " %6i %6i %9.4f %9.4f %9.5f :",
+ nout, i+1, lon, lat, area*pow(10,6));
+
+ int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
+
+ for ( k = 0; k < ncorner_new; k++ )
+ fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
+ for ( k = ncorner_new; k < ncorner; k++ )
+ fprintf(stdout, " ---- ---- : ");
+ fprintf(stdout, "\n");
+ }
+ }
+
+ if ( nout )
+ cdoWarning("%d of %d points out of bounds!", nout, gridsize);
+
+ /* check that all cell bounds have the same orientation */
+
+ nout = 0;
+ for ( i = 0; i < gridsize; ++i )
+ {
+ lon = grid_center_lon[i];
+ lat = grid_center_lat[i];
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ lon_bounds[k] = grid_corner_lon[i*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+ if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
+ }
+ lon_bounds[ncorner] = lon_bounds[0];
+ lat_bounds[ncorner] = lat_bounds[0];
+
+ area = PolygonArea(ncorner+1, lon_bounds, lat_bounds, lat);
+
+ isnegative = area < 0 ? 1 : 0;
+ sumarea += area < 0 ? -area : area;
+
+ if ( isnegative ) nout++;
+
+ if ( isnegative && cdoVerbose )
+ {
+ if ( nout == 1 )
+ {
+ fprintf(stdout,"\n :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " Corner %2i : ", k+1);
+ fprintf(stdout,"\n Number Index center_lon center_lat :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k+1, k+1);
+ fprintf(stdout, "\n");
+ }
+ fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i+1, lon, lat);
+
+ int ncorner_new = check_ncorner(ncorner, lon_bounds, lat_bounds);
+
+ for ( k = 0; k < ncorner_new; k++ )
+ fprintf(stdout, "%9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
+ for ( k = ncorner_new; k < ncorner; k++ )
+ fprintf(stdout, " ---- ---- : ");
+
+ fprintf(stdout, "\n");
+ }
+ }
+
+ if ( nout )
+ cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
+
+ if ( cdoVerbose )
+ fprintf(stdout, "area-error: %9.5f%%\n", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
+
+ if ( fabs(100.*(sumarea - 4.*M_PI)/4.*M_PI) > 0.1)
+ cdoWarning("area-error: %9.5f%%", 100.*(sumarea - 4.*M_PI)/4.*M_PI );
+
+ /* check that all cells are convex */
+
+ nout = 0;
+ for ( i0 = 0; i0 < gridsize; i0++ )
+ {
+ lon = grid_center_lon[i0];
+ lat = grid_center_lat[i0];
+
+ for ( k = 0; k < ncorner; k++ )
+ {
+ lon_bounds[k] = grid_corner_lon[i0*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i0*ncorner+k];
+ /* Find cells that cover left and right border of the grid and adjust
+ coordinates --> they become closed polygons on theta-phi plane! */
+ if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
+ }
+
+ /* Reset found cuts for the current cell before starting the search */
+ for ( i = 0; i < ncorner; i++ )
+ for ( j = 0; j < ncorner; j++ )
+ cuts[i][j] = 0;
+
+ /* Loops cover all combinations between inner lines of the Polygon
+ Check whether each inner line is cut by an other (inner) one at least once.
+ - Only if there is a cut every inner line the Polygon is convex
+ - We assume: Points are in either cyclic or anticyclic order
+ */
+ for ( i = 0; i < ncorner-1; i++ )
+ {
+ /* j = i+2 excludes lines from one corner to an other (j=i+1) and
+ from one point to itself (j=i)*/
+ for ( j = i+2 ; j < ncorner; j++ )
+ {
+ /* Exclude the line between the last and first corner */
+ if ( i == 0 && j == ncorner-1 ) continue;
+
+ /* k = i+1: if starting point is in common lines to different corners
+ do not intersect */
+ for ( k = i+1; k < ncorner - 1; k++ )
+ {
+ if ( i == k ) l0 = j+1;
+ else l0 = k+2;
+
+ for ( l = l0; l < ncorner; l++ )
+ {
+ if ( cuts[k][l] && cuts[i][j] ) continue;
+ /* Exlude the line between the last and first corner
+ Exlude the line itself (l!=i, k!=j)
+ Check if line ij and kl intersect each other.
+ If so increment respective counters for intersections.
+ It is not relevant by which line a line is intersected -
+ it is only relevant if they is itersected! */
+ if ( ! ( k==0 && l == ncorner-1 ) && ( l != j ) && ( k != j ) )
+ {
+ if ( intersect(lon_bounds[i], lat_bounds[i], lon_bounds[j], lat_bounds[j],
+ lon_bounds[k], lat_bounds[k], lon_bounds[l], lat_bounds[l]) )
+ {
+ cuts[i][j]++; cuts[k][l]++; cuts[j][i]++; cuts[l][k]++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ convex = 1;
+ /* The following loop covers all inner lines of the Polygon
+ (The assumption applies that the points are in cyclic order) */
+ for ( i = 0; i < ncorner-1; i++ )
+ for ( j = i+2; j < ncorner; j++)
+ {
+ if ( i == 0 && j == ncorner-1 ) continue;
+ if ( ! cuts[i][j] ) convex = 0;
+ }
+ if ( !convex ) nout++;
+ if ( cdoVerbose && ( !convex ) )
+ {
+ if ( nout == 1 )
+ {
+ fprintf(stdout,"\n NO CONVEX POLYGON");
+ fprintf(stdout,"\n :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " Corner %2i : ", k);
+ fprintf(stdout,"\n Number Index center_lon center_lat :");
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " lon_%2.2i lat_%2.2i : ", k, k);
+ fprintf(stdout, "\n");
+ }
+
+ fprintf(stdout, " %6i %6i %9.4f %9.4f :", nout, i0+1, lon, lat);
+ for ( k = 0; k < ncorner; k++ )
+ fprintf(stdout, " %9.4f %9.4f : ", lon_bounds[k], lat_bounds[k]);
+ fprintf(stdout, "\n");
+ }
+ }
+
+ if ( nout )
+ cdoWarning("%d of %d cells are not Convex!", nout, gridsize);
+
+ if ( check_corners )
+ {
+ /*
+ Check if there is a corner at the same point of
+ an other cell foreach corner of each cell
+ */
+ nout = 0;
+ for ( i = 0; i < gridsize*ncorner; i++ )
+ alone_cell[i] = 1;
+
+ for ( i = 0; i < gridsize*ncorner; i++ )
+ {
+ if ( ! alone_cell[i] ) continue;
+ alone = 1;
+ lon = grid_corner_lon[i];
+ lat = grid_corner_lat[i];
+ for ( j = 0; j < gridsize*ncorner; j++ )
+ if ( j != i &&
+ IS_EQUAL(grid_corner_lat[j], lat) &&
+ IS_EQUAL(grid_corner_lon[j], lon) )
+ { alone = 0; alone_cell[i] = alone_cell[j] = 1; break; }
+ if ( alone )
+ {
+ if ( lon >= 180. ) lon -= 360.;
+ else if ( lon < 180. ) lon += 360.;
+ for ( j = i+1; j < gridsize*ncorner; j++ )
+ if (j != i &&
+ IS_EQUAL(grid_corner_lat[j], lat) &&
+ IS_EQUAL(grid_corner_lon[j], lon) )
+ { alone = 0; alone_cell[i] = alone_cell[j] = 0; break; }
+ }
+ if ( alone )
+ {
+ nout++;
+ if ( cdoVerbose )
+ {
+ if ( nout == 1 )
+ {
+ fprintf(stdout,"\n VERTEX ALONE ON GRID\n");
+ fprintf(stdout," number cell-Index Vert-Index : lon lat\n");
+ }
+ fprintf(stdout, " %6i %6i %6i : %10.4f %10.4f\n",
+ nout, i/ncorner, i, grid_corner_lon[i], grid_corner_lat[i]);
+ }
+ }
+ }
+
+ if ( nout )
+ cdoWarning("%d of %d corners are lonely on the grid!", nout, gridsize*ncorner);
+ }
+
+ Free(alone_cell);
+}
+
+
+void verify_grid_old(int gridsize, int ncorner,
+ double *grid_center_lon, double *grid_center_lat,
+ double *grid_corner_lon, double *grid_corner_lat)
+{
+ int i, k;
+ int nout;
+ int isinside;
+ int isnegative;
+ double area;
+ double lon, lat;
+ double lon_bounds[ncorner], lat_bounds[ncorner];
+
+ /* check that all centers are inside the bounds */
+
+ nout = 0;
+ for ( i = 0; i < gridsize; ++i )
+ {
+ lon = grid_center_lon[i];
+ lat = grid_center_lat[i];
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ lon_bounds[k] = grid_corner_lon[i*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+ }
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ if ( (lon - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - lon) > 270 ) lon_bounds[k] -= 360;
+ }
+
+ lon_bounds[ncorner] = lon_bounds[0];
+ lat_bounds[ncorner] = lat_bounds[0];
+
+ isinside = pnpoly(ncorner+1, lon_bounds, lat_bounds, lon, lat);
+
+ if ( !isinside ) nout++;
+
+ if ( !isinside && cdoVerbose )
+ printf("center: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
+ lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
+ }
+
+ if ( nout > 0 )
+ cdoWarning("%d of %d points out of bounds!", nout, gridsize);
+
+
+ /* check that all cell bounds have the same orientation */
+
+ nout = 0;
+ for ( i = 0; i < gridsize; ++i )
+ {
+ lon = grid_center_lon[i];
+ lat = grid_center_lat[i];
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ lon_bounds[k] = grid_corner_lon[i*ncorner+k];
+ lat_bounds[k] = grid_corner_lat[i*ncorner+k];
+ }
+
+ for ( k = 0; k < ncorner; ++k )
+ {
+ if ( (grid_center_lon[i] - lon_bounds[k]) > 270 ) lon_bounds[k] += 360;
+ if ( (lon_bounds[k] - grid_center_lon[i]) > 270 ) lon_bounds[k] -= 360;
+ }
+
+ lon_bounds[ncorner] = lon_bounds[0];
+ lat_bounds[ncorner] = lat_bounds[0];
+
+ area = PolygonArea_old(ncorner+1, lon_bounds, lat_bounds);
+
+ if ( area < 0 ) isnegative = 1;
+ else isnegative = 0;
+
+ if ( isnegative ) nout++;
+
+
+ if ( isnegative && cdoVerbose )
+ printf("bounds: %d %d %g %g %g %g %g %g %g %g %g %g\n", nout, i, lon, lat, lon_bounds[0], lat_bounds[0],
+ lon_bounds[1], lat_bounds[1], lon_bounds[2], lat_bounds[2], lon_bounds[3], lat_bounds[3]);
+ }
+
+ if ( nout > 0 )
+ cdoWarning("%d of %d grid cells have wrong orientation!", nout, gridsize);
+}
+
+
+static void verify_grid_test(int gridsize, int ncorner, double *grid_center_lon, double *grid_center_lat, double *grid_corner_lon, double *grid_corner_lat){
+
+
+
+ /*
+ This function performs three tests on each cell of a given grid:
+
+ 1) it tests whether all cell bounds have the same orientation, i.e. the corners of the cell are in clockwise or counterclockwise order
+ 2) it tests whether the cell is convex
+ 3) it tests whether the center point is within the bounds of the cell
+
+ It performs these tests after longitude and latitude on the unit circle have been converted first to Cartesian coordinates in Euclidean space and subsequently to two dimensional coordinates on the plane each cell occupies.
+ */
+
+ double center_point_in_Euclidean_space[3];
+
+ /* We are assuming a maximum number of corners of 9. The 10th corner is for closing the cell. */
+
+ double cell_corners_in_Euclidean_space[30];
+ double cell_corner_coordinates[3];
+ double center_point_on_cell_plane[2];
+ double cell_corners_on_cell_plane[20];
+
+ int cell_no;
+ int corner_no;
+
+ int no_of_cells_with_vertices_arranged_in_clockwise_order = 0;
+ int no_of_cells_with_vertices_arranged_in_counterclockwise_order = 0;
+ int no_of_convex_cells = 0;
+ int no_of_degenerate_cells = 0;
+ int no_of_cells_with_center_points_within_their_bounds = 0;
+
+ for (cell_no = 0; cell_no < gridsize; ++cell_no)
+ {
+ printf("Cell Number %d:\n\n", cell_no+1);
+ printf("Euclidean coordinates are:\n\n");
+
+ /*
+ Latitude and longitude are spherical coordinates on a unit circle. Each such coordinate tuple is transformed into a triple of Cartesian coordinates in Euclidean space.
+ This is first done for the presumed center point of the cell and then for all the corners of the cell. LLtoXYZ is defined in clipping/geometry.h
+ */
+
+ LLtoXYZ(grid_center_lon[cell_no], grid_center_lat[cell_no], center_point_in_Euclidean_space);
+
+ for (corner_no = 0; corner_no < ncorner; ++corner_no)
+ {
+ LLtoXYZ(grid_corner_lon[cell_no * ncorner + corner_no], grid_corner_lat[cell_no * ncorner + corner_no], cell_corner_coordinates);
+
+ /* The components of the result vector are appended to the list of cell corner coordinates. */
+
+ for (int vector_component = 0; vector_component < 3; ++vector_component){
+ cell_corners_in_Euclidean_space[(corner_no * 3) + vector_component] = cell_corner_coordinates[vector_component];
+ }
+ printf("(%f, %f, %f) ", cell_corners_in_Euclidean_space[(corner_no * 3) + 0], cell_corners_in_Euclidean_space[(corner_no * 3) + 1], cell_corners_in_Euclidean_space[(corner_no * 3) + 2]);
+ }
+
+ /* We are creating a closed polygon/cell by setting the last corner to be the same as the first one. */
+
+ for (int vector_component = 0; vector_component < 3; ++vector_component){
+ cell_corners_in_Euclidean_space[(ncorner * 3) + vector_component] = cell_corners_in_Euclidean_space[vector_component];
+ }
+
+ printf("\n\n");
+
+
+ /*
+ Each cell corresponds to a two-dimensional polygon now in unknown orientation in three-dimensional space. Each cell and its center point are coplanar. THIS IS A GIVEN.
+ In order to solve the two-dimensional point-in-polygon problem for each cell, the three-dimensional coordinates of the polygon and its center point are projected onto the two-dimensional plane they form.
+
+ This is done in the following steps:
+
+ 1) Compute two vectors that lie on the cell plane. The first three corners of the cell are used to do this. THIS MEANS THAT AT LEAST THREE CORNERS MUST BE GIVEN.
+ Then compute the normal of the cell plane the two vectors are on. The normal is the new z-axis.
+ 2) Compute the new y-axis by computing the cross product of the new z-axis and the old x-axis.
+ 3) Compute the new x-axis by computing the cross product of the new z-axis and the new y-axis.
+ 4) Project every corner point onto the new x- and y-axes by using the dot product.
+
+ The result is a xy tuple for each corner and the presumend center point which is a projection onto the plane the xyz corner points form.
+ */
+
+ struct axis new_z_axis = compute_the_new_z_axis(cell_corners_in_Euclidean_space);
+ struct axis new_y_axis = compute_the_new_y_axis(new_z_axis);
+ struct axis new_x_axis = compute_the_new_x_axis(new_z_axis, new_y_axis);
+
+ project_Euclidean_corner_coordinates_onto_the_cell_plane(new_x_axis, new_y_axis, &cell_corners_in_Euclidean_space, &cell_corners_on_cell_plane, ncorner);
+ project_Euclidean_center_coordinates_onto_the_cell_plane(new_x_axis, new_y_axis, ¢er_point_in_Euclidean_space, ¢er_point_on_cell_plane);
+
+ /* Checking whether the cell has a size greater zero. */
+
+ double twice_the_cell_area = calculate_twice_the_polygon_area(cell_corners_on_cell_plane, ncorner);
+
+ if (twice_the_cell_area == 0){
+ printf("This cell is degenerate. Its area equals zero.\n\n");
+ no_of_degenerate_cells += 1;
+ continue;
+ }
+
+ /* Checking whether the cell corners/polygon vertices are arranged in a clockwise or counterclockwise order. This is done by looking at the sign of the cell area. */
+
+ if (are_polygon_vertices_arranged_in_clockwise_order(twice_the_cell_area) == 1){
+ printf("The cell's corners are arranged in clockwise order.\n\n");
+ no_of_cells_with_vertices_arranged_in_clockwise_order += 1;
+ } else {
+ printf("The cell's corners are arranged in counterclockwise order.\n\n");
+ no_of_cells_with_vertices_arranged_in_counterclockwise_order += 1;
+ }
+
+ /* Convexity of the cell is tested. */
+
+ printf("Checking if the cell is convex ... ");
+
+ if (is_simple_polygon_convex(cell_corners_on_cell_plane, ncorner) == 1){
+ printf("cell is convex!\n\n");
+ no_of_convex_cells += 1;
+ } else {
+ printf("cell is not convex!\n\n");
+ no_of_degenerate_cells += 1;
+ }
+
+ /* The winding numbers algorithm is used to test whether the presumed center point is within the bounds of the cell. */
+
+ int winding_number = winding_numbers_algorithm_without_printfs(cell_corners_on_cell_plane, ncorner, center_point_on_cell_plane);
+
+ if (winding_number == 0){
+ printf("The presumed center point lies OUTSIDE the bounds of the cell.\n\n\n\n");
+ } else {
+ printf("The presumed center point lies INSIDE the bounds of the cell.\n\n\n\n");
+ no_of_cells_with_center_points_within_their_bounds += 1;
+ }
+ }
+
+ printf("There are %u cells in all.\n\n", gridsize );
+ printf("Number of cells with clockwise ordering of vertices: %u\n", no_of_cells_with_vertices_arranged_in_clockwise_order);
+ printf("Number of cells with counterclockwise ordering of vertices: %u\n", no_of_cells_with_vertices_arranged_in_counterclockwise_order);
+ printf("Number of convex cells: %u\n", no_of_convex_cells);
+ printf("Number of nonsimple or degenerate cells: %u\n", no_of_degenerate_cells);
+ printf("Number of cells with presumed center points within their bounds: %u\n", no_of_cells_with_center_points_within_their_bounds);
+
+ /******************* TESTING ********************/
+
+
+ double cell_corners_in_3D[30] = {1.5, 0, 1.5, 0, 1.5, 0, -1.5, 0, -1.5, 0, -1.5, 0, 1.5, 0, -1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ double cell_corners_in_2D[20];
+ double center_point_in_3D[3] = {0.5, 0, 0.5};
+ double center_point_in_2D[2];
+
+ printf("\n\n\n\n\nTesting the projection on the cell plane:\n\n");
+
+ printf("The vertex coordinates in Euclidean space are: (%f, %f, %f), (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n\n", cell_corners_in_3D[0], cell_corners_in_3D[1], cell_corners_in_3D[2], cell_corners_in_3D[3], cell_corners_in_3D[4], cell_corners_in_3D[5], cell_corners_in_3D[6], cell_corners_in_3D[7], cell_corners_in_3D[8], cell_corners_in_3D[9], cell_corners_in_3D[10], cell_corners_in_3D[11]);
+
+ printf("The center point coordinates in Euclidean space are: (%f, %f, %f)\n\n", center_point_in_3D[0], center_point_in_3D[1], center_point_in_3D[2]);
+
+ struct axis z_axis = compute_the_new_z_axis(cell_corners_in_3D);
+
+ printf("The new z-axis is: (%f, %f, %f)\n\n", z_axis.axis_vector[0], z_axis.axis_vector[1], z_axis.axis_vector[2]);
+
+ struct axis y_axis = compute_the_new_y_axis(z_axis);
+
+ printf("The new y-axis is: (%f, %f, %f)\n\n", y_axis.axis_vector[0], y_axis.axis_vector[1], y_axis.axis_vector[2]);
+
+ struct axis x_axis = compute_the_new_x_axis(z_axis, y_axis);
+
+ printf("The new x-axis is: (%f, %f, %f)\n\n", x_axis.axis_vector[0], x_axis.axis_vector[1], x_axis.axis_vector[2] );
+
+ project_Euclidean_corner_coordinates_onto_the_cell_plane(x_axis, y_axis, &cell_corners_in_3D, &cell_corners_in_2D, 4);
+
+ printf("The new vertex coordinates are:(%f, %f), (%f, %f), (%f, %f), (%f, %f)\n\n", cell_corners_in_2D[0], cell_corners_in_2D[1], cell_corners_in_2D[2], cell_corners_in_2D[3], cell_corners_in_2D[4], cell_corners_in_2D[5], cell_corners_in_2D[6], cell_corners_in_2D[7]);
+
+ project_Euclidean_center_coordinates_onto_the_cell_plane(x_axis, y_axis, ¢er_point_in_3D, ¢er_point_in_2D);
+
+ printf("The new center point coordinates are: (%f, %f)\n\n", center_point_in_2D[0], center_point_in_2D[1]);
+
+ double double_the_area = calculate_twice_the_polygon_area(cell_corners_in_2D, 4);
+
+ printf("Are the vertices arranged in clockwise order? %u\n\n", are_polygon_vertices_arranged_in_clockwise_order(double_the_area));
+
+ printf("Is the cell convex? %u\n\n", is_simple_polygon_convex(cell_corners_in_2D, 4));
+
+ int winding_number = winding_numbers_algorithm_without_printfs(cell_corners_in_2D, 4, center_point_in_2D);
+
+ printf("If the winding number is 0 the presumed center point is outside the bounds of the cell. The winding number is: %d\n\n", winding_number);
+
+
+
+}
+
+void *Verifygrid(void *argument)
+{
+ bool lgrid_gen_bounds = false, luse_grid_corner = true;
+ double *grid_corner_lat = NULL, *grid_corner_lon = NULL;
+ char units[CDI_MAX_NAME];
+
+ cdoInitialize(argument);
+
+ int VERIFYGRID = cdoOperatorAdd("verifygrid", 0, 0, NULL);
+ int VERIFYGRIDTEST = cdoOperatorAdd("verifygridtest", 0, 0, NULL);
+
+ int operatorID = cdoOperatorID();
+
+ int streamID = streamOpenRead(cdoStreamName(0));
+
+ int vlistID = streamInqVlist(streamID);
+
+ int gridID = vlistInqVarGrid(vlistID, 0);
+
+ if ( gridInqType(gridID) == GRID_GME ) gridID = gridToUnstructured(gridID, 1);
+
+ if ( gridInqType(gridID) != GRID_UNSTRUCTURED && gridInqType(gridID) != GRID_CURVILINEAR )
+ {
+ gridID = gridToCurvilinear(gridID, 1);
+ lgrid_gen_bounds = TRUE;
+ }
+
+ int gridsize = gridInqSize(gridID);
+ /*
+ if ( gridInqMaskGME(gridID, NULL) )
+ {
+ int *grid_mask = (int*) Malloc(gridsize*sizeof(int));
+ gridInqMaskGME(gridID, grid_mask);
+ free(grid_mask);
+ }
+ */
+ int ncorner = 4;
+ if ( gridInqType(gridID) == GRID_UNSTRUCTURED )
+ ncorner = gridInqNvertex(gridID);
+
+ double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+
+ gridInqYvals(gridID, grid_center_lat);
+ gridInqXvals(gridID, grid_center_lon);
+
+ /* Convert lat/lon units if required */
+ gridInqXunits(gridID, units);
+ grid_to_degree(units, gridsize, grid_center_lon, "grid center lon");
+ gridInqYunits(gridID, units);
+ grid_to_degree(units, gridsize, grid_center_lat, "grid center lat");
+
+ if ( luse_grid_corner )
+ {
+ if ( ncorner == 0 ) cdoAbort("grid corner missing!");
+ int nalloc = ncorner*gridsize;
+ grid_corner_lat = (double*) Realloc(grid_corner_lat, nalloc*sizeof(double));
+ grid_corner_lon = (double*) Realloc(grid_corner_lon, nalloc*sizeof(double));
+
+ if ( gridInqYbounds(gridID, NULL) && gridInqXbounds(gridID, NULL) )
+ {
+ gridInqYbounds(gridID, grid_corner_lat);
+ gridInqXbounds(gridID, grid_corner_lon);
+ }
+ else
+ {
+ if ( lgrid_gen_bounds )
+ {
+ char xunitstr[CDI_MAX_NAME];
+ char yunitstr[CDI_MAX_NAME];
+ gridInqXunits(gridID, xunitstr);
+ gridInqYunits(gridID, yunitstr);
+ }
+ else
+ cdoAbort("Grid corner missing!");
+ }
+
+
+ /* Note: using units from latitude instead from bounds */
+ grid_to_degree(units, ncorner*gridsize, grid_corner_lon, "grid corner lon");
+ grid_to_degree(units, ncorner*gridsize, grid_corner_lat, "grid corner lat");
+
+ }
+
+ streamClose(streamID);
+
+ if ( operatorID == VERIFYGRID )
+ verify_grid(gridsize, ncorner, grid_center_lon, grid_center_lat, grid_corner_lon, grid_corner_lat);
+ else
+ verify_grid_test(gridsize, ncorner, grid_center_lon, grid_center_lat, grid_corner_lon, grid_corner_lat);
+
+ if ( grid_center_lon ) Free(grid_center_lon);
+ if ( grid_center_lat ) Free(grid_center_lat);
+ if ( grid_corner_lon ) Free(grid_corner_lon);
+ if ( grid_corner_lat ) Free(grid_corner_lat);
+
+ cdoFinish();
+
+ return 0;
+}
diff --git a/src/Vertcum.c b/src/Vertcum.c
index 4d8be4a..5b1ba4b 100644
--- a/src/Vertcum.c
+++ b/src/Vertcum.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -39,7 +39,7 @@ void add_vars_mv(int gridsize, double missval, const double *restrict var1, cons
double missval2 = missval;
/*
for ( int i = 0; i < gridsize; ++i )
- var3[i] = ADD(var2[i], var1[i]);
+ var3[i] = ADDMN(var2[i], var1[i]);
*/
for ( int i = 0; i < gridsize; ++i )
{
diff --git a/src/Vertintap.c b/src/Vertintap.c
index 6c06773..5135a0e 100644
--- a/src/Vertintap.c
+++ b/src/Vertintap.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Vertintml.c b/src/Vertintml.c
index 325d16b..5a5087b 100644
--- a/src/Vertintml.c
+++ b/src/Vertintml.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Vertstat.c b/src/Vertstat.c
index a513a7e..fd75f68 100644
--- a/src/Vertstat.c
+++ b/src/Vertstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -25,9 +25,9 @@
Vertstat vertmean Vertical mean
Vertstat vertavg Vertical average
Vertstat vertvar Vertical variance
- Vertstat vertvar1 Vertical variance [Divisor is (n-1)]
+ Vertstat vertvar1 Vertical variance [Normalize by (n-1)]
Vertstat vertstd Vertical standard deviation
- Vertstat vertstd1 Vertical standard deviation [Divisor is (n-1)]
+ Vertstat vertstd1 Vertical standard deviation [Normalize by (n-1)]
*/
@@ -39,7 +39,7 @@
#define IS_SURFACE_LEVEL(zaxisID) (zaxisInqType(zaxisID) == ZAXIS_SURFACE && zaxisInqSize(zaxisID) == 1)
-static
+
int getSurfaceID(int vlistID)
{
int surfID = -1;
@@ -96,7 +96,7 @@ void genLayerBounds(int nlev, double *levels, double *lbounds, double *ubounds)
}
}
-static
+
int getLayerThickness(int genbounds, int index, int zaxisID, int nlev, double *thickness, double *weights)
{
int status = 0;
@@ -191,7 +191,7 @@ void *Vertstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
//int applyWeights = lmean;
@@ -337,7 +337,7 @@ void *Vertstat(void *argument)
if ( levelID == 0 )
{
streamReadRecord(streamID1, vars1[varID].ptr, &nmiss);
- vars1[varID].nmiss = nmiss;
+ vars1[varID].nmiss = (size_t)nmiss;
if ( operatorID == VERTINT && IS_NOT_EQUAL(layer_thickness, 1.0) ) farcmul(&vars1[varID], layer_thickness);
if ( lmean && IS_NOT_EQUAL(layer_weight, 1.0) ) farcmul(&vars1[varID], layer_weight);
@@ -369,7 +369,8 @@ void *Vertstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[varID].grid;
field.missval = vars1[varID].missval;
@@ -440,7 +441,7 @@ void *Vertstat(void *argument)
}
streamDefRecord(streamID2, varID, 0);
- streamWriteRecord(streamID2, vars1[varID].ptr, vars1[varID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID].ptr, (int)vars1[varID].nmiss);
vars1[varID].nsamp = 0;
}
}
diff --git a/src/Vertwind.c b/src/Vertwind.c
index 92c2419..1345415 100644
--- a/src/Vertwind.c
+++ b/src/Vertwind.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Wct.c b/src/Wct.c
index 306e3a2..2f13f1f 100755
--- a/src/Wct.c
+++ b/src/Wct.c
@@ -28,7 +28,7 @@
static const char WCT_NAME[] = "wind_chill_temperature";
-static const char WCT_LONGNAME[] = "Windchill temperature describes the fact that low temperatures are felt to be even lower in case of wind. It is based on the rate of heat loss from exposed skin caused by wind and cold. It is calculated according to the empirical formula: 33 + (T - 33) * (0.478 + 0.237 * (SQRT(ff*3.6) - 0.0124 * ff * 3.6)) with T = air temperature in degree Celsius, ff = 10 m wind speed in m/s. Windchill temperature is only defined for temperatures at or below 33 degr [...]
+static const char WCT_LONGNAME[] = "Windchill temperature describes the fact that low temperatures are felt to be even lower in case of wind. It is based on the rate of heat loss from exposed skin caused by wind and cold. It is calculated according to the empirical formula: 33 + (T - 33) * (0.478 + 0.237 * ( SQRTMN(ff*3.6) - 0.0124 * ff * 3.6)) with T = air temperature in degree Celsius, ff = 10 m wind speed in m/s. Windchill temperature is only defined for temperatures at or below 33 d [...]
static const char WCT_UNITS[] = "Celsius";
static const int FIRST_VAR = 0;
@@ -86,6 +86,7 @@ void *Wct(void *argument)
int gridsize;
int nrecs, nrecs2, recID;
int tsID;
+ int nmiss;
int gridID, zaxisID;
int varID1, varID2, varID3;
int levelID1, levelID2;
@@ -151,10 +152,12 @@ void *Wct(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID1, &levelID1);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
-
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
+
streamInqRecord(streamID2, &varID2, &levelID2);
- streamReadRecord(streamID2, field2.ptr, &field2.nmiss);
+ streamReadRecord(streamID2, field2.ptr, &nmiss);
+ field2.nmiss = (size_t) nmiss;
if ( varID1 != varID2 || levelID1 != levelID2 )
cdoAbort("Input streams have different structure!");
@@ -171,7 +174,7 @@ void *Wct(void *argument)
farexpr(&field1, field2, windchillTemperature);
streamDefRecord(streamID3, varID3, levelID1);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, (int)field1.nmiss);
}
tsID++;
diff --git a/src/Wind.c b/src/Wind.c
index 8b1c2ab..0592310 100644
--- a/src/Wind.c
+++ b/src/Wind.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -164,7 +164,7 @@ void *Wind(void *argument)
gridID1 = vlistInqVarGrid(vlistID1, varID1);
if ( gridInqType(gridID1) != GRID_GAUSSIAN )
- cdoAbort("U-wind is not on gaussian grid!");
+ cdoAbort("U-wind is not on Gaussian grid!");
if ( gridID1 != vlistInqVarGrid(vlistID1, varID2) )
cdoAbort("U and V wind must have the same grid represention!");
diff --git a/src/Writegrid.c b/src/Writegrid.c
index 0fcfa4c..9196236 100644
--- a/src/Writegrid.c
+++ b/src/Writegrid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Writerandom.c b/src/Writerandom.c
index 528bd76..b1b18a9 100644
--- a/src/Writerandom.c
+++ b/src/Writerandom.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -82,7 +82,7 @@ void *Writerandom(void *argument)
for ( rindex = nrecs-1; rindex >= 0; rindex-- )
{
- index = (int) (rindex*1.0*rand()/(RAND_MAX+1.0));
+ index = (int) (rindex*((double)rand())/((double)RAND_MAX));
/* printf("rindex %d %d\n", rindex, index); */
ipos = -1;
for ( recID = 0; recID < nrecs; recID++ )
diff --git a/src/XTimstat.c b/src/XTimstat.c
index d87a9cf..b96f292 100644
--- a/src/XTimstat.c
+++ b/src/XTimstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,45 +24,45 @@
Timstat timmean Time mean
Timstat timavg Time average
Timstat timvar Time variance
- Timstat timvar1 Time variance [Divisor is (n-1)]
+ Timstat timvar1 Time variance [Normalize by (n-1)]
Timstat timstd Time standard deviation
- Timstat timstd1 Time standard deviation [Divisor is (n-1)]
+ Timstat timstd1 Time standard deviation [Normalize by (n-1)]
Hourstat hourmin Hourly minimum
Hourstat hourmax Hourly maximum
Hourstat hoursum Hourly sum
Hourstat hourmean Hourly mean
Hourstat houravg Hourly average
Hourstat hourvar Hourly variance
- Hourstat hourvar1 Hourly variance [Divisor is (n-1)]
+ Hourstat hourvar1 Hourly variance [Normalize by (n-1)]
Hourstat hourstd Hourly standard deviation
- Hourstat hourstd1 Hourly standard deviation [Divisor is (n-1)]
+ Hourstat hourstd1 Hourly standard deviation [Normalize by (n-1)]
Daystat daymin Daily minimum
Daystat daymax Daily maximum
Daystat daysum Daily sum
Daystat daymean Daily mean
Daystat dayavg Daily average
Daystat dayvar Daily variance
- Daystat dayvar1 Daily variance [Divisor is (n-1)]
+ Daystat dayvar1 Daily variance [Normalize by (n-1)]
Daystat daystd Daily standard deviation
- Daystat daystd1 Daily standard deviation [Divisor is (n-1)]
+ Daystat daystd1 Daily standard deviation [Normalize by (n-1)]
Monstat monmin Monthly minimum
Monstat monmax Monthly maximum
Monstat monsum Monthly sum
Monstat monmean Monthly mean
Monstat monavg Monthly average
Monstat monvar Monthly variance
- Monstat monvar1 Monthly variance [Divisor is (n-1)]
+ Monstat monvar1 Monthly variance [Normalize by (n-1)]
Monstat monstd Monthly standard deviation
- Monstat monstd1 Monthly standard deviation [Divisor is (n-1)]
+ Monstat monstd1 Monthly standard deviation [Normalize by (n-1)]
Yearstat yearmin Yearly minimum
Yearstat yearmax Yearly maximum
Yearstat yearsum Yearly sum
Yearstat yearmean Yearly mean
Yearstat yearavg Yearly average
Yearstat yearvar Yearly variance
- Yearstat yearvar1 Yearly variance [Divisor is (n-1)]
+ Yearstat yearvar1 Yearly variance [Normalize by (n-1)]
Yearstat yearstd Yearly standard deviation
- Yearstat yearstd1 Yearly standard deviation [Divisor is (n-1)]
+ Yearstat yearstd1 Yearly standard deviation [Normalize by (n-1)]
*/
@@ -70,13 +70,19 @@
#include "cdo.h"
#include "cdo_int.h"
#include "cdo_task.h"
-//#include "pstream.h"
-#include "pstream_write.h"
+#include "pstream.h"
+//#include "pstream_write.h"
typedef struct {
+ short varID;
+ short levelID;
+} recinfo_t;
+
+typedef struct {
int tsIDnext;
int streamID, nrecs;
+ recinfo_t *recinfo;
field_t **vars;
}
readarg_t;
@@ -89,17 +95,33 @@ void *cdoReadTimestep(void *rarg)
int varID, levelID, nmiss;
readarg_t *readarg = (readarg_t *) rarg;
field_t **input_vars = readarg->vars;
+ recinfo_t *recinfo = readarg->recinfo;
int streamID = readarg->streamID;
int tsIDnext = readarg->tsIDnext;
int nrecs = readarg->nrecs;
+ // timer_start(timer_read);
+
for ( int recID = 0; recID < nrecs; ++recID )
{
streamInqRecord(streamID, &varID, &levelID);
- streamReadRecord(streamID, input_vars[varID][levelID].ptr2, &nmiss);
+
+ if ( tsIDnext == 1 && recinfo )
+ {
+ recinfo[recID].varID = varID;
+ recinfo[recID].levelID = levelID;
+ }
+
+ if ( CDO_Memtype == MEMTYPE_FLOAT )
+ streamReadRecordF(streamID, (float*)input_vars[varID][levelID].ptr2, &nmiss);
+ else
+ streamReadRecord(streamID, (double*)input_vars[varID][levelID].ptr2, &nmiss);
+
input_vars[varID][levelID].nmiss2 = nmiss;
}
+ // timer_stop(timer_read);
+
num_recs = streamInqTimestep(streamID, tsIDnext);
return ((void *) &num_recs);
@@ -108,13 +130,23 @@ void *cdoReadTimestep(void *rarg)
static
void cdoUpdateVars(int nvars, int vlistID, field_t **vars)
{
+ void *tmp = NULL;
+
for ( int varID = 0; varID < nvars; varID++ )
{
int nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
for ( int levelID = 0; levelID < nlevels; levelID++ )
{
- double *tmp = vars[varID][levelID].ptr;
- vars[varID][levelID].ptr = vars[varID][levelID].ptr2;
+ if ( CDO_Memtype == MEMTYPE_FLOAT )
+ {
+ tmp = vars[varID][levelID].ptrf;
+ vars[varID][levelID].ptrf = (float*) vars[varID][levelID].ptr2;
+ }
+ else
+ {
+ tmp = vars[varID][levelID].ptr;
+ vars[varID][levelID].ptr = (double*) vars[varID][levelID].ptr2;
+ }
vars[varID][levelID].ptr2 = tmp;
vars[varID][levelID].nmiss = vars[varID][levelID].nmiss2;
}
@@ -124,18 +156,16 @@ void cdoUpdateVars(int nvars, int vlistID, field_t **vars)
void *XTimstat(void *argument)
{
+ enum {HOUR_LEN=4, DAY_LEN=6, MON_LEN=8, YEAR_LEN=10};
int timestat_date = TIMESTAT_MEAN;
int gridsize;
int vdate = 0, vtime = 0;
int vdate0 = 0, vtime0 = 0;
- int nrecs;
- int varID, levelID;
- long nsets;
- int i;
+ int varID;
+ int nsets;
int streamID3 = -1;
int vlistID3, taxisID3 = -1;
int nmiss;
- int nlevels;
int lvfrac = FALSE;
int nwpv; // number of words per value; real:1 complex:2
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
@@ -144,33 +174,33 @@ void *XTimstat(void *argument)
cdoInitialize(argument);
- cdoOperatorAdd("xtimmin", func_min, DATE_LEN, NULL);
- cdoOperatorAdd("xtimmax", func_max, DATE_LEN, NULL);
- cdoOperatorAdd("xtimsum", func_sum, DATE_LEN, NULL);
- cdoOperatorAdd("xtimmean", func_mean, DATE_LEN, NULL);
- cdoOperatorAdd("xtimavg", func_avg, DATE_LEN, NULL);
- cdoOperatorAdd("xtimvar", func_var, DATE_LEN, NULL);
- cdoOperatorAdd("xtimvar1", func_var1, DATE_LEN, NULL);
- cdoOperatorAdd("xtimstd", func_std, DATE_LEN, NULL);
- cdoOperatorAdd("xtimstd1", func_std1, DATE_LEN, NULL);
- cdoOperatorAdd("xyearmin", func_min, 10, NULL);
- cdoOperatorAdd("xyearmax", func_max, 10, NULL);
- cdoOperatorAdd("xyearsum", func_sum, 10, NULL);
- cdoOperatorAdd("xyearmean", func_mean, 10, NULL);
- cdoOperatorAdd("xyearavg", func_avg, 10, NULL);
- cdoOperatorAdd("xyearvar", func_var, 10, NULL);
- cdoOperatorAdd("xyearvar1", func_var1, 10, NULL);
- cdoOperatorAdd("xyearstd", func_std, 10, NULL);
- cdoOperatorAdd("xyearstd1", func_std1, 10, NULL);
- cdoOperatorAdd("xmonmin", func_min, 8, NULL);
- cdoOperatorAdd("xmonmax", func_max, 8, NULL);
- cdoOperatorAdd("xmonsum", func_sum, 8, NULL);
- cdoOperatorAdd("xmonmean", func_mean, 8, NULL);
- cdoOperatorAdd("xmonavg", func_avg, 8, NULL);
- cdoOperatorAdd("xmonvar", func_var, 8, NULL);
- cdoOperatorAdd("xmonvar1", func_var1, 8, NULL);
- cdoOperatorAdd("xmonstd", func_std, 8, NULL);
- cdoOperatorAdd("xmonstd1", func_std1, 8, NULL);
+ cdoOperatorAdd("xtimmin", func_min, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimmax", func_max, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimsum", func_sum, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimmean", func_mean, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimavg", func_avg, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimvar", func_var, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimvar1", func_var1, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimstd", func_std, DATE_LEN, NULL);
+ cdoOperatorAdd("xtimstd1", func_std1, DATE_LEN, NULL);
+ cdoOperatorAdd("xyearmin", func_min, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearmax", func_max, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearsum", func_sum, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearmean", func_mean, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearavg", func_avg, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearvar", func_var, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearvar1", func_var1, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearstd", func_std, YEAR_LEN, NULL);
+ cdoOperatorAdd("xyearstd1", func_std1, YEAR_LEN, NULL);
+ cdoOperatorAdd("xmonmin", func_min, MON_LEN, NULL);
+ cdoOperatorAdd("xmonmax", func_max, MON_LEN, NULL);
+ cdoOperatorAdd("xmonsum", func_sum, MON_LEN, NULL);
+ cdoOperatorAdd("xmonmean", func_mean, MON_LEN, NULL);
+ cdoOperatorAdd("xmonavg", func_avg, MON_LEN, NULL);
+ cdoOperatorAdd("xmonvar", func_var, MON_LEN, NULL);
+ cdoOperatorAdd("xmonvar1", func_var1, MON_LEN, NULL);
+ cdoOperatorAdd("xmonstd", func_std, MON_LEN, NULL);
+ cdoOperatorAdd("xmonstd1", func_std1, MON_LEN, NULL);
int operatorID = cdoOperatorID();
int operfunc = cdoOperatorF1(operatorID);
@@ -179,7 +209,7 @@ void *XTimstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
if ( operfunc == func_mean )
{
@@ -199,8 +229,8 @@ void *XTimstat(void *argument)
int cmplen = DATE_LEN - comparelen;
- // int streamID1 = streamOpenRead(cdoStreamName(0));
- int streamID1 = streamOpenRead(cdoStreamName(0)->args);
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+ //int streamID1 = streamOpenRead(cdoStreamName(0)->args);
int vlistID1 = streamInqVlist(streamID1);
int vlistID2 = vlistDuplicate(vlistID1);
@@ -218,6 +248,12 @@ void *XTimstat(void *argument)
for ( varID = 0; varID < nvars; ++varID )
vlistDefVarTsteptype(vlistID2, varID, TSTEP_CONSTANT);
+ const char *freq = NULL;
+ if ( comparelen == DAY_LEN ) freq = "day";
+ else if ( comparelen == MON_LEN ) freq = "mon";
+ else if ( comparelen == YEAR_LEN ) freq = "year";
+ if ( freq ) vlistDefAttTxt(vlistID2, CDI_GLOBAL, "frequency", (int)strlen(freq), freq);
+
int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
streamDefVlist(streamID2, vlistID2);
@@ -225,7 +261,6 @@ void *XTimstat(void *argument)
if ( cdoDiag )
{
char filename[8192];
-
strcpy(filename, cdoOperatorName(operatorID));
strcat(filename, "_");
strcat(filename, cdoStreamName(1)->args);
@@ -257,7 +292,9 @@ void *XTimstat(void *argument)
gridsize = vlistGridsizeMax(vlistID1);
if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
- field_t **input_vars = field_malloc(vlistID1, FIELD_PTR | FIELD_PTR2);
+ int FIELD_MEMTYPE = 0;
+ if ( CDO_Memtype == MEMTYPE_FLOAT ) FIELD_MEMTYPE = FIELD_FLT;
+ field_t **input_vars = field_malloc(vlistID1, FIELD_PTR | FIELD_PTR2 | FIELD_MEMTYPE);
field_t **vars1 = field_malloc(vlistID1, FIELD_PTR);
field_t **samp1 = field_malloc(vlistID1, FIELD_NONE);
field_t **vars2 = NULL;
@@ -267,7 +304,7 @@ void *XTimstat(void *argument)
readarg.streamID = streamID1;
readarg.vars = input_vars;
- int lparallelread = TRUE;
+ int lparallelread = CDO_Parallel_Read;
int ltsfirst = TRUE;
void *read_task = NULL;
void *readresult = NULL;
@@ -284,7 +321,10 @@ void *XTimstat(void *argument)
int tsID = 0;
int otsID = 0;
- nrecs = streamInqTimestep(streamID1, tsID);
+ int nrecs = streamInqTimestep(streamID1, tsID);
+ int maxrecs = nrecs;
+ recinfo_t *recinfo = (recinfo_t *) malloc(maxrecs*sizeof(recinfo_t));
+
tsID++;
while ( TRUE )
{
@@ -301,24 +341,13 @@ void *XTimstat(void *argument)
if ( DATE_IS_NEQ(indate1, indate2, cmplen) ) break;
readarg.tsIDnext = tsID;
- readarg.nrecs = nrecs;
+ readarg.nrecs = nrecs;
+ readarg.recinfo = recinfo;
- if ( ltsfirst || lparallelread == FALSE )
+ if ( ltsfirst || lparallelread == FALSE )
{
- if ( lparallelread )
- {
- cdo_task_start(read_task, cdoReadTimestep, &readarg);
- }
- else
- {
- readresult = cdoReadTimestep(&readarg);
- }
-
- if ( lparallelread )
- {
- readresult = cdo_task_wait(read_task);
- }
ltsfirst = FALSE;
+ readresult = cdoReadTimestep(&readarg);
}
else
{
@@ -335,68 +364,93 @@ void *XTimstat(void *argument)
cdo_task_start(read_task, cdoReadTimestep, &readarg);
}
- for ( varID = 0; varID < nvars; varID++ )
+ if ( nsets == 0 )
{
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevels; levelID++ )
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) shared(maxrecs, recinfo, input_vars, vars1, samp1) if(maxrecs>1)
+#endif
+ for ( int recID = 0; recID < maxrecs; recID++ )
{
- nwpv = vars1[varID][levelID].nwpv;
- gridsize = gridInqSize(vars1[varID][levelID].grid);
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pinput_var = &input_vars[varID][levelID];
+
+ int nwpv = pvar1->nwpv;
+ int gridsize = pvar1->size;
+ int nmiss = pinput_var->nmiss;
- if ( nsets == 0 )
+ farcpy(pvar1, *pinput_var);
+ pvar1->nmiss = nmiss;
+ if ( nmiss > 0 || samp1[varID][levelID].ptr )
{
- memcpy(vars1[varID][levelID].ptr, input_vars[varID][levelID].ptr, nwpv*gridsize*sizeof(double));
- nmiss = input_vars[varID][levelID].nmiss;
- vars1[varID][levelID].nmiss = nmiss;
- if ( nmiss > 0 || samp1[varID][levelID].ptr )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- samp1[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
-
- for ( i = 0; i < nwpv*gridsize; i++ )
- if ( DBL_IS_EQUAL(vars1[varID][levelID].ptr[i], vars1[varID][levelID].missval) )
- samp1[varID][levelID].ptr[i] = 0;
- else
- samp1[varID][levelID].ptr[i] = 1;
- }
+ if ( samp1[varID][levelID].ptr == NULL )
+ samp1[varID][levelID].ptr = (double*) malloc(nwpv*gridsize*sizeof(double));
+
+ for ( int i = 0; i < nwpv*gridsize; i++ )
+ if ( DBL_IS_EQUAL(pvar1->ptr[i], pvar1->missval) )
+ samp1[varID][levelID].ptr[i] = 0;
+ else
+ samp1[varID][levelID].ptr[i] = 1;
}
- else
- {
- nmiss = input_vars[varID][levelID].nmiss;
- if ( nmiss > 0 || samp1[varID][levelID].ptr )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- {
- samp1[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
- for ( i = 0; i < nwpv*gridsize; i++ )
- samp1[varID][levelID].ptr[i] = nsets;
- }
-
- for ( i = 0; i < nwpv*gridsize; i++ )
- if ( !DBL_IS_EQUAL(input_vars[varID][levelID].ptr[i], vars1[varID][levelID].missval) )
- samp1[varID][levelID].ptr[i]++;
- }
+ }
+ }
+ else
+ {
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) shared(lvarstd, nsets, maxrecs, recinfo, input_vars, vars1, samp1, vars2, operfunc) if(maxrecs>1)
+#endif
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
- if ( lvarstd )
- {
- farsumq(&vars2[varID][levelID], input_vars[varID][levelID]);
- farsum(&vars1[varID][levelID], input_vars[varID][levelID]);
- }
- else
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pinput_var = &input_vars[varID][levelID];
+
+ int nwpv = pvar1->nwpv;
+ int gridsize = pvar1->size;
+ int nmiss = pinput_var->nmiss;
+
+ if ( nmiss > 0 || samp1[varID][levelID].ptr )
+ {
+ if ( samp1[varID][levelID].ptr == NULL )
{
- farfun(&vars1[varID][levelID], input_vars[varID][levelID], operfunc);
+ samp1[varID][levelID].ptr = (double*) malloc(nwpv*gridsize*sizeof(double));
+ for ( int i = 0; i < nwpv*gridsize; i++ )
+ samp1[varID][levelID].ptr[i] = nsets;
}
+
+ for ( int i = 0; i < nwpv*gridsize; i++ )
+ if ( !DBL_IS_EQUAL(pinput_var->ptr[i], pvar1->missval) )
+ samp1[varID][levelID].ptr[i]++;
}
- }
- }
+
+ if ( lvarstd )
+ {
+ field_t *pvar2 = &vars2[varID][levelID];
+ farsumq(pvar2, *pinput_var);
+ farsum(pvar1, *pinput_var);
+ }
+ else
+ {
+ farfun(pvar1, *pinput_var, operfunc);
+ }
+ }
+ }
if ( nsets == 0 && lvarstd )
- for ( varID = 0; varID < nvars; varID++ )
- {
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pvar2 = &vars2[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevels; levelID++ )
- farmoq(&vars2[varID][levelID], vars1[varID][levelID]);
+
+ farmoq(pvar2, *pvar1);
}
vdate0 = vdate;
@@ -408,42 +462,41 @@ void *XTimstat(void *argument)
if ( nrecs == 0 && nsets == 0 ) break;
if ( lmean )
- for ( varID = 0; varID < nvars; varID++ )
- {
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) shared(vlistID1, nsets, maxrecs, recinfo, vars1, samp1) if(maxrecs>1)
+#endif
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevels; levelID++ )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- farcdiv(&vars1[varID][levelID], (double)nsets);
- else
- {
- // farround(&samp1[varID][levelID]); not necessary
- fardiv(&vars1[varID][levelID], samp1[varID][levelID]);
- }
- }
+
+ if ( samp1[varID][levelID].ptr == NULL )
+ farcdiv(pvar1, (double)nsets);
+ else
+ fardiv(pvar1, samp1[varID][levelID]);
}
else if ( lvarstd )
- for ( varID = 0; varID < nvars; varID++ )
- {
- if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevels; levelID++ )
- {
- if ( samp1[varID][levelID].ptr == NULL )
- {
- if ( lstd )
- farcstd(&vars1[varID][levelID], vars2[varID][levelID], nsets, divisor);
- else
- farcvar(&vars1[varID][levelID], vars2[varID][levelID], nsets, divisor);
- }
- else
- {
- if ( lstd )
- farstd(&vars1[varID][levelID], vars2[varID][levelID], samp1[varID][levelID], divisor);
- else
- farvar(&vars1[varID][levelID], vars2[varID][levelID], samp1[varID][levelID], divisor);
- }
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+ field_t *pvar2 = &vars2[varID][levelID];
+
+ if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
+
+ if ( samp1[varID][levelID].ptr == NULL )
+ {
+ if ( lstd ) farcstd(pvar1, *pvar2, nsets, divisor);
+ else farcvar(pvar1, *pvar2, nsets, divisor);
+ }
+ else
+ {
+ if ( lstd ) farstd(pvar1, *pvar2, samp1[varID][levelID], divisor);
+ else farvar(pvar1, *pvar2, samp1[varID][levelID], divisor);
}
}
@@ -456,35 +509,36 @@ void *XTimstat(void *argument)
}
if ( lvfrac && operfunc == func_mean )
- for ( varID = 0; varID < nvars; varID++ )
- {
+ for ( int recID = 0; recID < maxrecs; recID++ )
+ {
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+
if ( vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID));
- for ( levelID = 0; levelID < nlevels; levelID++ )
- {
- nwpv = vars1[varID][levelID].nwpv;
- gridsize = gridInqSize(vars1[varID][levelID].grid);
- missval = vars1[varID][levelID].missval;
- if ( samp1[varID][levelID].ptr )
- {
- int irun = 0;
- for ( i = 0; i < nwpv*gridsize; ++i )
- {
- if ( (samp1[varID][levelID].ptr[i] / nsets) < vfrac )
- {
- vars1[varID][levelID].ptr[i] = missval;
- irun++;
- }
- }
-
- if ( irun )
- {
- nmiss = 0;
- for ( i = 0; i < nwpv*gridsize; ++i )
- if ( DBL_IS_EQUAL(vars1[varID][levelID].ptr[i], missval) ) nmiss++;
- vars1[varID][levelID].nmiss = nmiss;
- }
- }
+
+ nwpv = pvar1->nwpv;
+ gridsize = gridInqSize(pvar1->grid);
+ missval = pvar1->missval;
+ if ( samp1[varID][levelID].ptr )
+ {
+ int irun = 0;
+ for ( int i = 0; i < nwpv*gridsize; ++i )
+ {
+ if ( (samp1[varID][levelID].ptr[i] / nsets) < vfrac )
+ {
+ pvar1->ptr[i] = missval;
+ irun++;
+ }
+ }
+
+ if ( irun )
+ {
+ nmiss = 0;
+ for ( int i = 0; i < nwpv*gridsize; ++i )
+ if ( DBL_IS_EQUAL(pvar1->ptr[i], missval) ) nmiss++;
+ pvar1->nmiss = nmiss;
+ }
}
}
@@ -497,22 +551,23 @@ void *XTimstat(void *argument)
streamDefTimestep(streamID3, otsID);
}
- for ( varID = 0; varID < nvars; ++varID )
+ for ( int recID = 0; recID < maxrecs; recID++ )
{
+ int varID = recinfo[recID].varID;
+ int levelID = recinfo[recID].levelID;
+ field_t *pvar1 = &vars1[varID][levelID];
+
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
- nlevels = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID));
- for ( levelID = 0; levelID < nlevels; ++ levelID )
+ streamDefRecord(streamID2, varID, levelID);
+ streamWriteRecord(streamID2, pvar1->ptr, pvar1->nmiss);
+
+ if ( cdoDiag )
{
- streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
- if ( cdoDiag )
+ if ( samp1[varID][levelID].ptr )
{
- if ( samp1[varID][levelID].ptr )
- {
- streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, samp1[varID][levelID].ptr, 0);
- }
+ streamDefRecord(streamID3, varID, levelID);
+ streamWriteRecord(streamID3, samp1[varID][levelID].ptr, 0);
}
}
}
@@ -528,6 +583,7 @@ void *XTimstat(void *argument)
if ( lvarstd ) field_free(vars2, vlistID1);
dtlist_delete(dtlist);
+ Free(recinfo);
if ( cdoDiag ) pstreamClose(streamID3);
pstreamClose(streamID2);
diff --git a/src/YAR.c b/src/YAR.c
index 6869fa1..3c20746 100644
--- a/src/YAR.c
+++ b/src/YAR.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/Ydayarith.c b/src/Ydayarith.c
index aab9042..50568a4 100644
--- a/src/Ydayarith.c
+++ b/src/Ydayarith.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -30,24 +30,16 @@
#include "pstream.h"
-#define MAX_DAY 1232
+#define MAX_DOY 373
void *Ydayarith(void *argument)
{
- int operatorID;
- int operfunc;
- int streamID1, streamID2, streamID3;
- int gridsize;
- int nrecs, nvars, nlev, recID;
- int tsID;
+ int nrecs;
int varID, levelID;
- int offset;
- int vlistID1, vlistID2, vlistID3;
- int taxisID1, taxisID2, taxisID3;
- int vdate, year, mon, day;
- field_t field1, field2;
- int **varnmiss2[MAX_DAY];
- double **vardata2[MAX_DAY];
+ int nmiss;
+ int year, month, day;
+ int **varnmiss2[MAX_DOY];
+ double **vardata2[MAX_DOY];
cdoInitialize(argument);
@@ -56,69 +48,74 @@ void *Ydayarith(void *argument)
cdoOperatorAdd("ydaymul", func_mul, 0, NULL);
cdoOperatorAdd("ydaydiv", func_div, 0, NULL);
- operatorID = cdoOperatorID();
- operfunc = cdoOperatorF1(operatorID);
+ int operatorID = cdoOperatorID();
+ int operfunc = cdoOperatorF1(operatorID);
- streamID1 = streamOpenRead(cdoStreamName(0));
- streamID2 = streamOpenRead(cdoStreamName(1));
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+ int streamID2 = streamOpenRead(cdoStreamName(1));
- vlistID1 = streamInqVlist(streamID1);
- vlistID2 = streamInqVlist(streamID2);
- vlistID3 = vlistDuplicate(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = streamInqVlist(streamID2);
+ int vlistID3 = vlistDuplicate(vlistID1);
vlistCompare(vlistID1, vlistID2, CMP_ALL);
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
+ field_t field1, field2;
field_init(&field1);
field_init(&field2);
field1.ptr = (double*) Malloc(gridsize*sizeof(double));
field2.ptr = (double*) Malloc(gridsize*sizeof(double));
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = vlistInqTaxis(vlistID2);
- taxisID3 = taxisDuplicate(taxisID1);
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = vlistInqTaxis(vlistID2);
+ int taxisID3 = taxisDuplicate(taxisID1);
vlistDefTaxis(vlistID3, taxisID3);
- streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
+ int streamID3 = streamOpenWrite(cdoStreamName(2), cdoFiletype());
streamDefVlist(streamID3, vlistID3);
- nvars = vlistNvars(vlistID2);
+ int nvars = vlistNvars(vlistID2);
- for ( day = 0; day < MAX_DAY ; day++ ) vardata2[day] = NULL;
+ for ( int dayoy = 0; dayoy < MAX_DOY ; dayoy++ ) vardata2[dayoy] = NULL;
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID2, tsID)) )
{
- vdate = taxisInqVdate(taxisID2);
+ int vdate = taxisInqVdate(taxisID2);
- cdiDecodeDate(vdate, &year, &mon, &day);
- day += mon*100;
- if ( day < 0 || day >= MAX_DAY ) cdoAbort("Day %d out of range!", day);
+ cdiDecodeDate(vdate, &year, &month, &day);
- if ( vardata2[day] != NULL ) cdoAbort("Day %d already allocatd!", day);
+ int dayoy = 0;
+ if ( month >= 1 && month <= 12 ) dayoy = (month-1)*31 + day;
- vardata2[day] = (double **) Malloc(nvars*sizeof(double *));
- varnmiss2[day] = (int **) Malloc(nvars*sizeof(int *));
+ if ( dayoy < 0 || dayoy >= MAX_DOY )
+ cdoAbort("Day of year %d out of range (date=%d)!", dayoy, vdate);
+
+ if ( vardata2[dayoy] != NULL ) cdoAbort("Day of year %d already allocatd (date=%d)!", dayoy, vdate);
+
+ vardata2[dayoy] = (double **) Malloc(nvars*sizeof(double *));
+ varnmiss2[dayoy] = (int **) Malloc(nvars*sizeof(int *));
for ( varID = 0; varID < nvars; varID++ )
{
- gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
- nlev = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID));
- vardata2[day][varID] = (double*) Malloc(nlev*gridsize*sizeof(double));
- varnmiss2[day][varID] = (int*) Malloc(nlev*sizeof(int));
+ size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
+ size_t nlev = zaxisInqSize(vlistInqVarZaxis(vlistID2, varID));
+ vardata2[dayoy][varID] = (double*) Malloc(nlev*gridsize*sizeof(double));
+ varnmiss2[dayoy][varID] = (int*) Malloc(nlev*sizeof(int));
}
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID2, &varID, &levelID);
- gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
- offset = gridsize*levelID;
+ size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
+ size_t offset = gridsize*levelID;
- streamReadRecord(streamID2, vardata2[day][varID]+offset, &field2.nmiss);
- varnmiss2[day][varID][levelID] = field2.nmiss;
+ streamReadRecord(streamID2, vardata2[dayoy][varID]+offset, &nmiss);
+ varnmiss2[dayoy][varID][levelID] = nmiss;
}
tsID++;
@@ -128,26 +125,31 @@ void *Ydayarith(void *argument)
tsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
- vdate = taxisInqVdate(taxisID1);
+ int vdate = taxisInqVdate(taxisID1);
+
+ cdiDecodeDate(vdate, &year, &month, &day);
+
+ int dayoy = 0;
+ if ( month >= 1 && month <= 12 ) dayoy = (month-1)*31 + day;
- cdiDecodeDate(vdate, &year, &mon, &day);
- day += mon*100;
- if ( day < 0 || day >= MAX_DAY ) cdoAbort("Day %d out of range!", day);
+ if ( dayoy < 0 || dayoy >= MAX_DOY )
+ cdoAbort("Day of year %d out of range (date=%d)!", dayoy, vdate);
taxisCopyTimestep(taxisID3, taxisID1);
streamDefTimestep(streamID3, tsID);
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
- gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
- offset = gridsize*levelID;
- if ( vardata2[day] == NULL ) cdoAbort("Day %d not found!", day);
- memcpy(field2.ptr, vardata2[day][varID]+offset, gridsize*sizeof(double));
- field2.nmiss = varnmiss2[day][varID][levelID];
+ size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
+ size_t offset = gridsize*levelID;
+ if ( vardata2[dayoy] == NULL ) cdoAbort("Day of year %d not found (date=%d)!", dayoy, vdate);
+ memcpy(field2.ptr, vardata2[dayoy][varID]+offset, gridsize*sizeof(double));
+ field2.nmiss = varnmiss2[dayoy][varID][levelID];
field1.grid = vlistInqVarGrid(vlistID1, varID);
field1.missval = vlistInqVarMissval(vlistID1, varID);
@@ -157,8 +159,9 @@ void *Ydayarith(void *argument)
farfun(&field1, field2, operfunc);
+ nmiss = (int) field1.nmiss;
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, nmiss);
}
tsID++;
}
@@ -167,17 +170,17 @@ void *Ydayarith(void *argument)
streamClose(streamID2);
streamClose(streamID1);
- for ( day = 0; day < MAX_DAY ; day++ )
- if ( vardata2[day] )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
+ if ( vardata2[dayoy] )
{
for ( varID = 0; varID < nvars; varID++ )
{
- Free(vardata2[day][varID]);
- Free(varnmiss2[day][varID]);
+ Free(vardata2[dayoy][varID]);
+ Free(varnmiss2[dayoy][varID]);
}
- Free(vardata2[day]);
- Free(varnmiss2[day]);
+ Free(vardata2[dayoy]);
+ Free(varnmiss2[dayoy]);
}
if ( field1.ptr ) Free(field1.ptr);
diff --git a/src/Ydaypctl.c b/src/Ydaypctl.c
index e76b09c..b6239b1 100644
--- a/src/Ydaypctl.c
+++ b/src/Ydaypctl.c
@@ -34,26 +34,19 @@ int getmonthday(int date);
void *Ydaypctl(void *argument)
{
- int gridsize;
int varID;
int recID;
int gridID;
int vdate, vtime;
int year, month, day, dayoy;
- int nrecs, nrecords;
+ int nrecs;
int levelID;
- int tsID;
- int otsID;
- long nsets[NDAY];
- int streamID1, streamID2, streamID3, streamID4;
- int vlistID1, vlistID2, vlistID3, vlistID4, taxisID1, taxisID2, taxisID3, taxisID4;
int nmiss;
- int nvars, nlevels;
- int *recVarID, *recLevelID;
+ int nlevels;
int vdates1[NDAY], vtimes1[NDAY];
- int vdates2[NDAY], vtimes2[NDAY];
+ int vdates2[NDAY];
+ long nsets[NDAY];
field_t **vars1[NDAY];
- field_t field;
HISTOGRAM_SET *hsets[NDAY];
cdoInitialize(argument);
@@ -70,42 +63,44 @@ void *Ydaypctl(void *argument)
nsets[dayoy] = 0;
}
- streamID1 = streamOpenRead(cdoStreamName(0));
- streamID2 = streamOpenRead(cdoStreamName(1));
- streamID3 = streamOpenRead(cdoStreamName(2));
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+ int streamID2 = streamOpenRead(cdoStreamName(1));
+ int streamID3 = streamOpenRead(cdoStreamName(2));
- vlistID1 = streamInqVlist(streamID1);
- vlistID2 = streamInqVlist(streamID2);
- vlistID3 = streamInqVlist(streamID3);
- vlistID4 = vlistDuplicate(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = streamInqVlist(streamID2);
+ int vlistID3 = streamInqVlist(streamID3);
+ int vlistID4 = vlistDuplicate(vlistID1);
vlistCompare(vlistID1, vlistID2, CMP_ALL);
vlistCompare(vlistID1, vlistID3, CMP_ALL);
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = vlistInqTaxis(vlistID2);
- taxisID3 = vlistInqTaxis(vlistID3);
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = vlistInqTaxis(vlistID2);
+ int taxisID3 = vlistInqTaxis(vlistID3);
/* TODO - check that time axes 2 and 3 are equal */
- taxisID4 = taxisDuplicate(taxisID1);
+ int taxisID4 = taxisDuplicate(taxisID1);
if ( taxisHasBounds(taxisID4) ) taxisDeleteBounds(taxisID4);
vlistDefTaxis(vlistID4, taxisID4);
- streamID4 = streamOpenWrite(cdoStreamName(3), cdoFiletype());
+ int streamID4 = streamOpenWrite(cdoStreamName(3), cdoFiletype());
streamDefVlist(streamID4, vlistID4);
- nvars = vlistNvars(vlistID1);
- nrecords = vlistNrecs(vlistID1);
+ int nvars = vlistNvars(vlistID1);
+ int nrecords = vlistNrecs(vlistID1);
- recVarID = (int*) Malloc(nrecords*sizeof(int));
- recLevelID = (int*) Malloc(nrecords*sizeof(int));
+ int *recVarID = (int*) Malloc(nrecords*sizeof(int));
+ int *recLevelID = (int*) Malloc(nrecords*sizeof(int));
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
+
+ field_t field;
field_init(&field);
field.ptr = (double*) Malloc(gridsize*sizeof(double));
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID2, tsID)) )
{
if ( nrecs != streamInqTimestep(streamID3, tsID) )
@@ -114,7 +109,7 @@ void *Ydaypctl(void *argument)
vdate = taxisInqVdate(taxisID2);
vtime = taxisInqVtime(taxisID2);
- if ( vdate != taxisInqVdate(taxisID3) || vtime != taxisInqVtime(taxisID3) )
+ if ( vdate != taxisInqVdate(taxisID3) )
cdoAbort("Verification dates at time step %d of %s and %s differ!", tsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args);
if ( cdoVerbose ) cdoPrint("process timestep: %d %d %d", tsID+1, vdate, vtime);
@@ -130,7 +125,6 @@ void *Ydaypctl(void *argument)
cdoAbort("Day %d out of range!", dayoy);
vdates2[dayoy] = vdate;
- vtimes2[dayoy] = vtime;
if ( vars1[dayoy] == NULL )
{
@@ -210,14 +204,13 @@ void *Ydaypctl(void *argument)
tsID++;
}
- otsID = 0;
+ int otsID = 0;
for ( dayoy = 0; dayoy < NDAY; dayoy++ )
if ( nsets[dayoy] )
{
- if ( vdates1[dayoy] != vdates2[dayoy] )
- cdoAbort("Verification dates for day %d of %s, %s and %s are different!", dayoy, cdoStreamName(1)->args, cdoStreamName(2)->args, cdoStreamName(3)->args);
- if ( vtimes1[dayoy] != vtimes2[dayoy] )
- cdoAbort("Verification times for day %d of %s, %s and %s are different!", dayoy, cdoStreamName(1)->args, cdoStreamName(2)->args, cdoStreamName(3)->args);
+ if ( getmonthday(vdates1[dayoy]) != getmonthday(vdates2[dayoy]) )
+ cdoAbort("Verification dates for the day %d of %s and %s are different!",
+ dayoy, cdoStreamName(0)->args, cdoStreamName(1)->args);
for ( varID = 0; varID < nvars; varID++ )
{
diff --git a/src/Ydaystat.c b/src/Ydaystat.c
index d7edce8..51dfb5f 100644
--- a/src/Ydaystat.c
+++ b/src/Ydaystat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Ydaystat ydaymean Multi-year daily mean
Ydaystat ydayavg Multi-year daily average
Ydaystat ydayvar Multi-year daily variance
- Ydaystat ydayvar1 Multi-year daily variance [Divisor is (n-1)]
+ Ydaystat ydayvar1 Multi-year daily variance [Normalize by (n-1)]
Ydaystat ydaystd Multi-year daily standard deviation
- Ydaystat ydaystd1 Multi-year daily standard deviation [Divisor is (n-1)]
+ Ydaystat ydaystd1 Multi-year daily standard deviation [Normalize by (n-1)]
*/
#include <cdi.h>
@@ -35,23 +35,19 @@
#include "pstream.h"
-#define NDAY 373
+#define MAX_DOY 373
void *Ydaystat(void *argument)
{
- int i;
- int varID;
- int recID;
- int vdate, vtime;
- int year, month, day, dayoy;
+ int varID, levelID;
+ int year, month, day;
int nrecs;
- int levelID;
- long nsets[NDAY];
+ int nsets[MAX_DOY];
int nmiss;
int nlevel;
- int vdates[NDAY], vtimes[NDAY];
- field_t **vars1[NDAY], **vars2[NDAY], **samp1[NDAY];
+ int vdates[MAX_DOY], vtimes[MAX_DOY];
+ field_t **vars1[MAX_DOY], **vars2[MAX_DOY], **samp1[MAX_DOY];
cdoInitialize(argument);
@@ -71,9 +67,9 @@ void *Ydaystat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
- for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
{
vars1[dayoy] = NULL;
vars2[dayoy] = NULL;
@@ -111,20 +107,18 @@ void *Ydaystat(void *argument)
int otsID = 0;
while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
{
- vdate = taxisInqVdate(taxisID1);
- vtime = taxisInqVtime(taxisID1);
+ int vdate = taxisInqVdate(taxisID1);
+ int vtime = taxisInqVtime(taxisID1);
if ( cdoVerbose ) cdoPrint("process timestep: %d %d %d", tsID+1, vdate, vtime);
cdiDecodeDate(vdate, &year, &month, &day);
- if ( month >= 1 && month <= 12 )
- dayoy = (month-1)*31 + day;
- else
- dayoy = 0;
+ int dayoy = 0;
+ if ( month >= 1 && month <= 12 ) dayoy = (month-1)*31 + day;
- if ( dayoy < 0 || dayoy >= NDAY )
- cdoAbort("day of year %d out of range (date=%d)!", dayoy, vdate);
+ if ( dayoy < 0 || dayoy >= MAX_DOY )
+ cdoAbort("Day of year %d out of range (date=%d)!", dayoy, vdate);
vdates[dayoy] = vdate;
vtimes[dayoy] = vtime;
@@ -137,7 +131,7 @@ void *Ydaystat(void *argument)
vars2[dayoy] = field_malloc(vlistID1, FIELD_PTR);
}
- for ( recID = 0; recID < nrecs; recID++ )
+ for ( int recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
@@ -152,14 +146,14 @@ void *Ydaystat(void *argument)
if ( nsets[dayoy] == 0 )
{
streamReadRecord(streamID1, vars1[dayoy][varID][levelID].ptr, &nmiss);
- vars1[dayoy][varID][levelID].nmiss = nmiss;
+ vars1[dayoy][varID][levelID].nmiss = (size_t)nmiss;
if ( nmiss > 0 || samp1[dayoy][varID][levelID].ptr )
{
if ( samp1[dayoy][varID][levelID].ptr == NULL )
samp1[dayoy][varID][levelID].ptr = (double*) Malloc(gridsize*sizeof(double));
- for ( i = 0; i < gridsize; i++ )
+ for ( int i = 0; i < gridsize; i++ )
if ( DBL_IS_EQUAL(vars1[dayoy][varID][levelID].ptr[i],
vars1[dayoy][varID][levelID].missval) )
samp1[dayoy][varID][levelID].ptr[i] = 0;
@@ -169,7 +163,8 @@ void *Ydaystat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[dayoy][varID][levelID].grid;
field.missval = vars1[dayoy][varID][levelID].missval;
@@ -178,11 +173,11 @@ void *Ydaystat(void *argument)
if ( samp1[dayoy][varID][levelID].ptr == NULL )
{
samp1[dayoy][varID][levelID].ptr = (double*) Malloc(gridsize*sizeof(double));
- for ( i = 0; i < gridsize; i++ )
+ for ( int i = 0; i < gridsize; i++ )
samp1[dayoy][varID][levelID].ptr[i] = nsets[dayoy];
}
- for ( i = 0; i < gridsize; i++ )
+ for ( int i = 0; i < gridsize; i++ )
if ( !DBL_IS_EQUAL(field.ptr[i], vars1[dayoy][varID][levelID].missval) )
samp1[dayoy][varID][levelID].ptr[i]++;
}
@@ -214,13 +209,13 @@ void *Ydaystat(void *argument)
// set the year to the minimum of years found on output timestep
int outyear = 1e9;
- for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
if ( nsets[dayoy] )
{
cdiDecodeDate(vdates[dayoy], &year, &month, &day);
if ( year < outyear ) outyear = year;
}
- for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
if ( nsets[dayoy] )
{
cdiDecodeDate(vdates[dayoy], &year, &month, &day);
@@ -228,7 +223,7 @@ void *Ydaystat(void *argument)
// printf("vdates[%d] = %d nsets = %d\n", dayoy, vdates[dayoy], nsets[dayoy]);
}
- for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
if ( nsets[dayoy] )
{
if ( lmean )
@@ -272,7 +267,7 @@ void *Ydaystat(void *argument)
taxisDefVtime(taxisID2, vtimes[dayoy]);
streamDefTimestep(streamID2, otsID);
- for ( recID = 0; recID < nrecords; recID++ )
+ for ( int recID = 0; recID < nrecords; recID++ )
{
varID = recVarID[recID];
levelID = recLevelID[recID];
@@ -281,13 +276,13 @@ void *Ydaystat(void *argument)
streamDefRecord(streamID2, varID, levelID);
streamWriteRecord(streamID2, vars1[dayoy][varID][levelID].ptr,
- vars1[dayoy][varID][levelID].nmiss);
+ (int)vars1[dayoy][varID][levelID].nmiss);
}
otsID++;
}
- for ( dayoy = 0; dayoy < NDAY; dayoy++ )
+ for ( int dayoy = 0; dayoy < MAX_DOY; dayoy++ )
{
if ( vars1[dayoy] != NULL )
{
diff --git a/src/Ydrunpctl.c b/src/Ydrunpctl.c
index 327d705..3d1654c 100644
--- a/src/Ydrunpctl.c
+++ b/src/Ydrunpctl.c
@@ -24,6 +24,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
#include "percentiles_hist.h"
@@ -40,14 +41,11 @@ int getmonthday(int date)
void *Ydrunpctl(void *argument)
{
- int gridsize;
int varID;
int recID;
int gridID;
int nrecs;
int levelID;
- int tsID;
- int otsID;
int inp, its;
int nmiss;
int nlevels;
@@ -58,7 +56,6 @@ void *Ydrunpctl(void *argument)
int vdates2[NDAY] /*, vtimes2[NDAY]*/;
int nsets[NDAY];
int year, month, day, dayoy;
- field_t field;
HISTOGRAM_SET *hsets[NDAY];
cdoInitialize(argument);
@@ -111,7 +108,9 @@ void *Ydrunpctl(void *argument)
int *recVarID = (int*) Malloc(nrecords*sizeof(int));
int *recLevelID = (int*) Malloc(nrecords*sizeof(int));
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
+
+ field_t field;
field_init(&field);
field.ptr = (double*) Malloc(gridsize*sizeof(double));
@@ -124,7 +123,7 @@ void *Ydrunpctl(void *argument)
vars1[its] = field_malloc(vlistID1, FIELD_PTR);
}
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID2, tsID)) )
{
if ( nrecs != streamInqTimestep(streamID3, tsID) )
@@ -133,7 +132,7 @@ void *Ydrunpctl(void *argument)
vdate = taxisInqVdate(taxisID2);
vtime = taxisInqVtime(taxisID2);
- if ( vdate != taxisInqVdate(taxisID3) || vtime != taxisInqVtime(taxisID3) )
+ if ( vdate != taxisInqVdate(taxisID3) )
cdoAbort("Verification dates at time step %d of %s and %s differ!", tsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args);
if ( cdoVerbose ) cdoPrint("process timestep: %d %d %d", tsID+1, vdate, vtime);
@@ -286,13 +285,13 @@ void *Ydrunpctl(void *argument)
vdates1[dayoy] = cdiEncodeDate(outyear, month, day);
}
*/
- otsID = 0;
+ int otsID = 0;
for ( dayoy = 0; dayoy < NDAY; dayoy++ )
if ( nsets[dayoy] )
{
if ( getmonthday(vdates1[dayoy]) != getmonthday(vdates2[dayoy]) )
cdoAbort("Verification dates for day %d of %s, %s and %s are different!",
- dayoy, cdoStreamName(1)->args, cdoStreamName(2)->args, cdoStreamName(3)->args);
+ dayoy, cdoStreamName(0)->args, cdoStreamName(1)->args);
for ( varID = 0; varID < nvars; varID++ )
{
diff --git a/src/Ydrunstat.c b/src/Ydrunstat.c
index 2d00b2a..a4acdc1 100644
--- a/src/Ydrunstat.c
+++ b/src/Ydrunstat.c
@@ -24,14 +24,15 @@
Ydrunstat ydrunmean Multi-year daily running mean
Ydrunstat ydrunavg Multi-year daily running average
Ydrunstat ydrunvar Multi-year daily running variance
- Ydrunstat ydrunvar1 Multi-year daily running variance [Divisor is (n-1)]
+ Ydrunstat ydrunvar1 Multi-year daily running variance [Normalize by (n-1)]
Ydrunstat ydrunstd Multi-year daily running standard deviation
- Ydrunstat ydrunstd1 Multi-year daily running standard deviation [Divisor is (n-1)]
+ Ydrunstat ydrunstd1 Multi-year daily running standard deviation [Normalize by (n-1)]
*/
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
@@ -427,9 +428,7 @@ void ydstatFinalize(YDAY_STATS *stats, int operfunc)
{
int varID, levelID, nvars, nlevels;
int dayoy;
- double divisor;
-
- divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
nvars = vlistNvars(stats->vlist);
diff --git a/src/Yearmonstat.c b/src/Yearmonstat.c
index eb35e3e..f341dbe 100644
--- a/src/Yearmonstat.c
+++ b/src/Yearmonstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "calendar.h"
#include "pstream.h"
@@ -136,7 +137,7 @@ void *Yearmonstat(void *argument)
if ( nsets == 0 )
{
streamReadRecord(streamID1, vars1[varID][levelID].ptr, &nmiss);
- vars1[varID][levelID].nmiss = nmiss;
+ vars1[varID][levelID].nmiss = (size_t) nmiss;
farcmul(&vars1[varID][levelID], dpm);
@@ -154,7 +155,8 @@ void *Yearmonstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t) nmiss;
field.grid = vars1[varID][levelID].grid;
field.missval = vars1[varID][levelID].missval;
@@ -219,7 +221,7 @@ void *Yearmonstat(void *argument)
if ( otsID && vlistInqVarTsteptype(vlistID1, varID) == TSTEP_CONSTANT ) continue;
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, vars1[varID][levelID].ptr, vars1[varID][levelID].nmiss);
+ streamWriteRecord(streamID2, vars1[varID][levelID].ptr, (int)vars1[varID][levelID].nmiss);
}
if ( nrecs == 0 ) break;
diff --git a/src/Yhourarith.c b/src/Yhourarith.c
index 41e080e..2e3f16a 100644
--- a/src/Yhourarith.c
+++ b/src/Yhourarith.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -71,6 +71,7 @@ void *Yhourarith(void *argument)
int vlistID1, vlistID2, vlistID3;
int taxisID1, taxisID2, taxisID3;
int vdate, vtime;
+ int nmiss;
int houroy;
field_t field1, field2;
int **varnmiss2[MAX_HOUR];
@@ -142,8 +143,8 @@ void *Yhourarith(void *argument)
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
- streamReadRecord(streamID2, vardata2[houroy][varID]+offset, &field2.nmiss);
- varnmiss2[houroy][varID][levelID] = field2.nmiss;
+ streamReadRecord(streamID2, vardata2[houroy][varID]+offset, &nmiss);
+ varnmiss2[houroy][varID][levelID] = nmiss;
}
tsID++;
@@ -166,23 +167,22 @@ void *Yhourarith(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
+ field1.grid = vlistInqVarGrid(vlistID1, varID);
+ field1.missval = vlistInqVarMissval(vlistID1, varID);
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
memcpy(field2.ptr, vardata2[houroy][varID]+offset, gridsize*sizeof(double));
field2.nmiss = varnmiss2[houroy][varID][levelID];
-
- field1.grid = vlistInqVarGrid(vlistID1, varID);
- field1.missval = vlistInqVarMissval(vlistID1, varID);
-
field2.grid = vlistInqVarGrid(vlistID2, varID);
field2.missval = vlistInqVarMissval(vlistID2, varID);
farfun(&field1, field2, operfunc);
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, (int)field1.nmiss);
}
tsID++;
diff --git a/src/Yhourstat.c b/src/Yhourstat.c
index 8eddbb0..6b6c939 100644
--- a/src/Yhourstat.c
+++ b/src/Yhourstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Yhourstat yhourmean Multi-year hourly mean
Yhourstat yhouravg Multi-year hourly average
Yhourstat yhourvar Multi-year hourly variance
- Yhourstat yhourvar1 Multi-year hourly variance [Divisor is (n-1)]
+ Yhourstat yhourvar1 Multi-year hourly variance [Normalize by (n-1)]
Yhourstat yhourstd Multi-year hourly standard deviation
- Yhourstat yhourstd1 Multi-year hourly standard deviation [Divisor is (n-1)]
+ Yhourstat yhourstd1 Multi-year hourly standard deviation [Normalize by (n-1)]
*/
#include <cdi.h>
@@ -77,7 +77,7 @@ void *Yhourstat(void *argument)
int levelID;
int tsID;
int otsID;
- long nsets[MAX_HOUR];
+ int nsets[MAX_HOUR];
int streamID1, streamID2;
int vlistID1, vlistID2, taxisID1, taxisID2;
int nmiss;
@@ -85,7 +85,6 @@ void *Yhourstat(void *argument)
int *recVarID, *recLevelID;
int vdates[MAX_HOUR], vtimes[MAX_HOUR];
int lmean = FALSE, lvarstd = FALSE, lstd = FALSE;
- double divisor;
field_t **vars1[MAX_HOUR], **vars2[MAX_HOUR], **samp1[MAX_HOUR];
field_t field;
@@ -107,7 +106,7 @@ void *Yhourstat(void *argument)
lmean = operfunc == func_mean || operfunc == func_avg;
lstd = operfunc == func_std || operfunc == func_std1;
lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
for ( houroy = 0; houroy < MAX_HOUR; ++houroy )
{
@@ -178,7 +177,7 @@ void *Yhourstat(void *argument)
if ( nsets[houroy] == 0 )
{
streamReadRecord(streamID1, vars1[houroy][varID][levelID].ptr, &nmiss);
- vars1[houroy][varID][levelID].nmiss = nmiss;
+ vars1[houroy][varID][levelID].nmiss = (size_t) nmiss;
if ( nmiss > 0 || samp1[houroy][varID][levelID].ptr )
{
@@ -195,7 +194,8 @@ void *Yhourstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t) nmiss;
field.grid = vars1[houroy][varID][levelID].grid;
field.missval = vars1[houroy][varID][levelID].missval;
@@ -291,7 +291,7 @@ void *Yhourstat(void *argument)
streamDefRecord(streamID2, varID, levelID);
streamWriteRecord(streamID2, vars1[houroy][varID][levelID].ptr,
- vars1[houroy][varID][levelID].nmiss);
+ (int)vars1[houroy][varID][levelID].nmiss);
}
otsID++;
diff --git a/src/Ymonarith.c b/src/Ymonarith.c
index 3b4e170..073456a 100644
--- a/src/Ymonarith.c
+++ b/src/Ymonarith.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -44,6 +44,7 @@ void *Ymonarith(void *argument)
int tsID;
int varID, levelID;
int offset;
+ int nmiss;
int vdate, year, mon, day;
field_t field1, field2;
int **varnmiss2[MAX_MON];
@@ -133,8 +134,8 @@ void *Ymonarith(void *argument)
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
- streamReadRecord(streamID2, vardata2[mon][varID]+offset, &field2.nmiss);
- varnmiss2[mon][varID][levelID] = field2.nmiss;
+ streamReadRecord(streamID2, vardata2[mon][varID]+offset, &nmiss);
+ varnmiss2[mon][varID][levelID] = nmiss;
}
tsID++;
@@ -167,24 +168,23 @@ void *Ymonarith(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
-
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
+ field1.grid = vlistInqVarGrid(vlistID1, varID);
+ field1.missval = vlistInqVarMissval(vlistID1, varID);
+
gridsize = gridInqSize(vlistInqVarGrid(vlistID2, varID));
offset = gridsize*levelID;
memcpy(field2.ptr, vardata2[mon][varID]+offset, gridsize*sizeof(double));
field2.nmiss = varnmiss2[mon][varID][levelID];
-
- field1.grid = vlistInqVarGrid(vlistID1, varID);
- field1.missval = vlistInqVarMissval(vlistID1, varID);
-
field2.grid = vlistInqVarGrid(vlistID2, varID);
field2.missval = vlistInqVarMissval(vlistID2, varID);
farfun(&field1, field2, operfunc);
streamDefRecord(streamID3, varID, levelID);
- streamWriteRecord(streamID3, field1.ptr, field1.nmiss);
+ streamWriteRecord(streamID3, field1.ptr, (int)field1.nmiss);
}
tsID++;
}
diff --git a/src/Ymonpctl.c b/src/Ymonpctl.c
index 92b32b0..3ec0c8e 100644
--- a/src/Ymonpctl.c
+++ b/src/Ymonpctl.c
@@ -37,28 +37,21 @@ int getmonth(int date)
return month;
}
+
void *Ymonpctl(void *argument)
{
- int gridsize;
int varID;
int recID;
int gridID;
int vdate, vtime;
int year, month, day;
- int nrecs, nrecords;
int levelID;
- int tsID;
- int otsID;
- long nsets[NMONTH];
- int streamID1, streamID2, streamID3, streamID4;
- int vlistID1, vlistID2, vlistID3, vlistID4, taxisID1, taxisID2, taxisID3, taxisID4;
int nmiss;
- int nvars, nlevels;
- int *recVarID, *recLevelID;
+ int nrecs, nlevels;
int vdates1[NMONTH], vtimes1[NMONTH];
int vdates2[NMONTH];
+ long nsets[NMONTH];
field_t **vars1[NMONTH];
- field_t field;
HISTOGRAM_SET *hsets[NMONTH];
cdoInitialize(argument);
@@ -75,42 +68,44 @@ void *Ymonpctl(void *argument)
nsets[month] = 0;
}
- streamID1 = streamOpenRead(cdoStreamName(0));
- streamID2 = streamOpenRead(cdoStreamName(1));
- streamID3 = streamOpenRead(cdoStreamName(2));
+ int streamID1 = streamOpenRead(cdoStreamName(0));
+ int streamID2 = streamOpenRead(cdoStreamName(1));
+ int streamID3 = streamOpenRead(cdoStreamName(2));
- vlistID1 = streamInqVlist(streamID1);
- vlistID2 = streamInqVlist(streamID2);
- vlistID3 = streamInqVlist(streamID3);
- vlistID4 = vlistDuplicate(vlistID1);
+ int vlistID1 = streamInqVlist(streamID1);
+ int vlistID2 = streamInqVlist(streamID2);
+ int vlistID3 = streamInqVlist(streamID3);
+ int vlistID4 = vlistDuplicate(vlistID1);
vlistCompare(vlistID1, vlistID2, CMP_ALL);
vlistCompare(vlistID1, vlistID3, CMP_ALL);
- taxisID1 = vlistInqTaxis(vlistID1);
- taxisID2 = vlistInqTaxis(vlistID2);
- taxisID3 = vlistInqTaxis(vlistID3);
+ int taxisID1 = vlistInqTaxis(vlistID1);
+ int taxisID2 = vlistInqTaxis(vlistID2);
+ int taxisID3 = vlistInqTaxis(vlistID3);
/* TODO - check that time axes 2 and 3 are equal */
- taxisID4 = taxisDuplicate(taxisID1);
+ int taxisID4 = taxisDuplicate(taxisID1);
if ( taxisHasBounds(taxisID4) ) taxisDeleteBounds(taxisID4);
vlistDefTaxis(vlistID4, taxisID4);
- streamID4 = streamOpenWrite(cdoStreamName(3), cdoFiletype());
+ int streamID4 = streamOpenWrite(cdoStreamName(3), cdoFiletype());
streamDefVlist(streamID4, vlistID4);
- nvars = vlistNvars(vlistID1);
- nrecords = vlistNrecs(vlistID1);
+ int nvars = vlistNvars(vlistID1);
+ int nrecords = vlistNrecs(vlistID1);
- recVarID = (int*) Malloc(nrecords*sizeof(int));
- recLevelID = (int*) Malloc(nrecords*sizeof(int));
+ int *recVarID = (int*) Malloc(nrecords*sizeof(int));
+ int *recLevelID = (int*) Malloc(nrecords*sizeof(int));
- gridsize = vlistGridsizeMax(vlistID1);
+ int gridsize = vlistGridsizeMax(vlistID1);
+
+ field_t field;
field_init(&field);
field.ptr = (double*) Malloc(gridsize*sizeof(double));
- tsID = 0;
+ int tsID = 0;
while ( (nrecs = streamInqTimestep(streamID2, tsID)) )
{
if ( nrecs != streamInqTimestep(streamID3, tsID) )
@@ -119,7 +114,7 @@ void *Ymonpctl(void *argument)
vdate = taxisInqVdate(taxisID2);
vtime = taxisInqVtime(taxisID2);
- if ( vdate != taxisInqVdate(taxisID3) || vtime != taxisInqVtime(taxisID3) )
+ if ( vdate != taxisInqVdate(taxisID3) )
cdoAbort("Verification dates at time step %d of %s and %s differ!", tsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args);
if ( cdoVerbose ) cdoPrint("process timestep: %d %d %d", tsID+1, vdate, vtime);
@@ -202,13 +197,13 @@ void *Ymonpctl(void *argument)
tsID++;
}
- otsID = 0;
+ int otsID = 0;
for ( month = 0; month < NMONTH; month++ )
if ( nsets[month] )
{
if ( getmonth(vdates1[month]) != getmonth(vdates2[month]) )
- cdoAbort("Verification dates for month %d of %s, %s and %s are different!",
- month, cdoStreamName(1)->args, cdoStreamName(2)->args, cdoStreamName(3)->args);
+ cdoAbort("Verification dates for the month %d of %s and %s are different!",
+ month, cdoStreamName(0)->args, cdoStreamName(1)->args);
for ( varID = 0; varID < nvars; varID++ )
{
diff --git a/src/Ymonstat.c b/src/Ymonstat.c
index de72f65..0dd2db4 100644
--- a/src/Ymonstat.c
+++ b/src/Ymonstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Ymonstat ymonmean Multi-year monthly mean
Ymonstat ymonavg Multi-year monthly average
Ymonstat ymonvar Multi-year monthly variance
- Ymonstat ymonvar1 Multi-year monthly variance [Divisor is (n-1)]
+ Ymonstat ymonvar1 Multi-year monthly variance [Normalize by (n-1)]
Ymonstat ymonstd Multi-year monthly standard deviation
- Ymonstat ymonstd1 Multi-year monthly standard deviation [Divisor is (n-1)]
+ Ymonstat ymonstd1 Multi-year monthly standard deviation [Normalize by (n-1)]
*/
@@ -67,7 +67,7 @@ void *Ymonstat(void *argument)
int levelID;
int tsID;
int otsID;
- long nsets[NMONTH];
+ int nsets[NMONTH];
int streamID1, streamID2;
int vlistID1, vlistID2, taxisID1, taxisID2;
int nmiss;
@@ -77,7 +77,6 @@ void *Ymonstat(void *argument)
int mon[NMONTH];
int nmon = 0;
int lmean = FALSE, lvarstd = FALSE, lstd = FALSE;
- double divisor;
field_t **vars1[NMONTH], **vars2[NMONTH], **samp1[NMONTH];
field_t field;
@@ -99,7 +98,7 @@ void *Ymonstat(void *argument)
lmean = operfunc == func_mean || operfunc == func_avg;
lstd = operfunc == func_std || operfunc == func_std1;
lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
for ( month = 0; month < NMONTH; month++ )
{
@@ -174,7 +173,7 @@ void *Ymonstat(void *argument)
if ( nsets[month] == 0 )
{
streamReadRecord(streamID1, vars1[month][varID][levelID].ptr, &nmiss);
- vars1[month][varID][levelID].nmiss = nmiss;
+ vars1[month][varID][levelID].nmiss = (size_t) nmiss;
if ( nmiss > 0 || samp1[month][varID][levelID].ptr )
{
@@ -191,7 +190,8 @@ void *Ymonstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t) nmiss;
field.grid = vars1[month][varID][levelID].grid;
field.missval = vars1[month][varID][levelID].missval;
@@ -315,7 +315,7 @@ void *Ymonstat(void *argument)
streamDefRecord(streamID2, varID, levelID);
streamWriteRecord(streamID2, vars1[month][varID][levelID].ptr,
- vars1[month][varID][levelID].nmiss);
+ (int)vars1[month][varID][levelID].nmiss);
}
otsID++;
diff --git a/src/Yseaspctl.c b/src/Yseaspctl.c
index 5501679..014c697 100644
--- a/src/Yseaspctl.c
+++ b/src/Yseaspctl.c
@@ -40,6 +40,7 @@ void set_date(int vdate_new, int vtime_new, date_time_t *datetime);
int getmonthday(int date);
+
void *Yseaspctl(void *argument)
{
int varID;
@@ -49,9 +50,9 @@ void *Yseaspctl(void *argument)
int year, month, day, seas;
int nrecs;
int levelID;
- long nsets[NSEAS];
int nmiss;
int nlevels;
+ long nsets[NSEAS];
date_time_t datetime1[NSEAS], datetime2[NSEAS];
field_t **vars1[NSEAS];
HISTOGRAM_SET *hsets[NSEAS];
@@ -120,7 +121,7 @@ void *Yseaspctl(void *argument)
vdate = taxisInqVdate(taxisID2);
vtime = taxisInqVtime(taxisID2);
- if ( vdate != taxisInqVdate(taxisID3) || vtime != taxisInqVtime(taxisID3) )
+ if ( vdate != taxisInqVdate(taxisID3) )
cdoAbort("Verification dates at time step %d of %s and %s differ!", tsID+1, cdoStreamName(1)->args, cdoStreamName(2)->args);
if ( cdoVerbose ) cdoPrint("process timestep: %d %d %d", tsID+1, vdate, vtime);
@@ -212,8 +213,8 @@ void *Yseaspctl(void *argument)
if ( nsets[seas] )
{
if ( getmonthday(datetime1[seas].vdate) != getmonthday(datetime2[seas].vdate) )
- cdoAbort("Verification dates for season %d of %s, %s and %s are different!",
- seas, cdoStreamName(1)->args, cdoStreamName(2)->args, cdoStreamName(3)->args);
+ cdoAbort("Verification dates for the season %d of %s and %s are different!",
+ seas, cdoStreamName(0)->args, cdoStreamName(1)->args);
for ( varID = 0; varID < nvars; varID++ )
{
diff --git a/src/Yseasstat.c b/src/Yseasstat.c
index 18559c2..e8795e9 100644
--- a/src/Yseasstat.c
+++ b/src/Yseasstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,9 @@
Yseasstat yseasmean Multi-year seasonally mean
Yseasstat yseasavg Multi-year seasonally average
Yseasstat yseasvar Multi-year seasonally variance
- Yseasstat yseasvar1 Multi-year seasonally variance [Divisor is (n-1)]
+ Yseasstat yseasvar1 Multi-year seasonally variance [Normalize by (n-1)]
Yseasstat yseasstd Multi-year seasonally standard deviation
- Yseasstat yseasstd1 Multi-year seasonally standard deviation [Divisor is (n-1)]
+ Yseasstat yseasstd1 Multi-year seasonally standard deviation [Normalize by (n-1)]
*/
#include <cdi.h>
@@ -68,7 +68,7 @@ void *Yseasstat(void *argument)
int year, month, day, seas;
int nrecs;
int levelID;
- long nsets[NSEAS];
+ int nsets[NSEAS];
int nmiss;
int nlevel;
date_time_t datetime[NSEAS];
@@ -102,7 +102,7 @@ void *Yseasstat(void *argument)
int lmean = operfunc == func_mean || operfunc == func_avg;
int lstd = operfunc == func_std || operfunc == func_std1;
int lvarstd = operfunc == func_std || operfunc == func_var || operfunc == func_std1 || operfunc == func_var1;
- double divisor = operfunc == func_std1 || operfunc == func_var1;
+ int divisor = operfunc == func_std1 || operfunc == func_var1;
int streamID1 = streamOpenRead(cdoStreamName(0));
@@ -165,7 +165,7 @@ void *Yseasstat(void *argument)
if ( nsets[seas] == 0 )
{
streamReadRecord(streamID1, vars1[seas][varID][levelID].ptr, &nmiss);
- vars1[seas][varID][levelID].nmiss = nmiss;
+ vars1[seas][varID][levelID].nmiss = (size_t)nmiss;
if ( nmiss > 0 || samp1[seas][varID][levelID].ptr )
{
@@ -182,7 +182,8 @@ void *Yseasstat(void *argument)
}
else
{
- streamReadRecord(streamID1, field.ptr, &field.nmiss);
+ streamReadRecord(streamID1, field.ptr, &nmiss);
+ field.nmiss = (size_t)nmiss;
field.grid = vars1[seas][varID][levelID].grid;
field.missval = vars1[seas][varID][levelID].missval;
@@ -278,7 +279,7 @@ void *Yseasstat(void *argument)
streamDefRecord(streamID2, varID, levelID);
streamWriteRecord(streamID2, vars1[seas][varID][levelID].ptr,
- vars1[seas][varID][levelID].nmiss);
+ (int)vars1[seas][varID][levelID].nmiss);
}
otsID++;
diff --git a/src/Zonstat.c b/src/Zonstat.c
index 59bec47..cda3eed 100644
--- a/src/Zonstat.c
+++ b/src/Zonstat.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.1
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -25,9 +25,9 @@
Zonstat zonmean Zonal mean
Zonstat zonavg Zonal average
Zonstat zonstd Zonal standard deviation
- Zonstat zonstd1 Zonal standard deviation [Divisor is (n-1)]
+ Zonstat zonstd1 Zonal standard deviation [Normalize by (n-1)]
Zonstat zonvar Zonal variance
- Zonstat zonvar1 Zonal variance [Divisor is (n-1)]
+ Zonstat zonvar1 Zonal variance [Normalize by (n-1)]
Zonstat zonpctl Zonal percentiles
*/
@@ -44,6 +44,7 @@ void *Zonstat(void *argument)
int gridID1 = -1, gridID2 = -1;
int zongridID = -1;
int index;
+ int nmiss;
int recID, nrecs;
int varID, levelID;
@@ -153,8 +154,9 @@ void *Zonstat(void *argument)
for ( recID = 0; recID < nrecs; recID++ )
{
streamInqRecord(streamID1, &varID, &levelID);
- streamReadRecord(streamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(streamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t) nmiss;
field1.grid = vlistInqVarGrid(vlistID1, varID);
field1.missval = vlistInqVarMissval(vlistID1, varID);
field2.missval = vlistInqVarMissval(vlistID1, varID);
@@ -173,7 +175,7 @@ void *Zonstat(void *argument)
}
streamDefRecord(streamID2, varID, levelID);
- streamWriteRecord(streamID2, field2.ptr, field2.nmiss);
+ streamWriteRecord(streamID2, field2.ptr, (int)field2.nmiss);
}
tsID++;
}
diff --git a/src/after_sptrans.c b/src/after_sptrans.c
index 8492960..777feb1 100644
--- a/src/after_sptrans.c
+++ b/src/after_sptrans.c
@@ -18,7 +18,13 @@
#define HAVE_OPENMP4 1
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
void gaussaw(double *pa, double *pw, size_t nlat);
+#if defined (__cplusplus)
+}
+#endif
static
void jspleg1(double *pleg, double plat, int ktrunc, double *work)
diff --git a/libcdi/src/calendar.h b/src/calendar.h
similarity index 80%
copy from libcdi/src/calendar.h
copy to src/calendar.h
index c5836e9..cd7ea77 100644
--- a/libcdi/src/calendar.h
+++ b/src/calendar.h
@@ -1,15 +1,22 @@
#ifndef _CALENDAR_H
#define _CALENDAR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void encode_caldaysec(int calendar, int year, int month, int day, int hour, int minute, int second,
int *julday, int *secofday);
-void decode_caldaysec(int calendar, int julday, int secofday,
+void decode_caldaysec(int calendar, int julday, int secofday,
int *year, int *month, int *day, int *hour, int *minute, int *second);
int calendar_dpy(int calendar);
int days_per_year(int calendar, int year);
int days_per_month(int calendar, int year, int month);
+#if defined (__cplusplus)
+}
+#endif
#endif /* _CALENDAR_H */
/*
diff --git a/src/cdi_uuid.h b/src/cdi_uuid.h
new file mode 100644
index 0000000..6f215ca
--- /dev/null
+++ b/src/cdi_uuid.h
@@ -0,0 +1,42 @@
+#ifndef CDI_UUID_H
+#define CDI_UUID_H
+
+#if defined (HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "cdi.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int cdiUUIDIsNull(const unsigned char uuid[])
+{
+ int isNull = 1;
+ for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
+ isNull &= (uuid[i] == 0);
+ return isNull;
+}
+
+void cdiCreateUUID(unsigned char uuid[CDI_UUID_SIZE]);
+
+void cdiUUID2Str(const unsigned char uuid[], char uuidstr[]);
+int cdiStr2UUID(const char *uuidstr, unsigned char uuid[]);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/cdo.c b/src/cdo.c
index 4105d2e..29a65a3 100644
--- a/src/cdo.c
+++ b/src/cdo.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,12 @@
//#define _XOPEN_SOURCE 600 /* gethostname */
#endif
+#if defined (HAVE_EXECINFO_H)
+#include <execinfo.h>
+#endif
+
+#include <signal.h>
+#include <fenv.h>
#include <ctype.h>
/*#include <malloc.h>*/ /* mallopt and malloc_stats */
#include <sys/stat.h>
@@ -73,6 +79,7 @@ static int numThreads = 0;
static int timer_total;
static int CDO_netcdf_hdr_pad = 0;
static int CDO_Rusage = 0;
+static const char *username;
void gridsearch_set_method(const char *methodstr);
@@ -96,6 +103,59 @@ void gridsearch_set_method(const char *methodstr);
} \
}
+#define ISME (strcmp(username, "\x6d\x32\x31\x34\x30\x30\x33") == 0)
+
+static
+void cdo_stackframe(void)
+{
+#if defined HAVE_EXECINFO_H && defined HAVE_BACKTRACE
+ void *callstack[32];
+ int frames = backtrace(callstack, 32);
+ char **messages = backtrace_symbols(callstack, frames);
+
+ fprintf(stderr, "[bt] Execution path:\n");
+ if ( messages ) {
+ for ( int i = 0; i < frames; ++i )
+ fprintf(stderr, "[bt] %s\n", messages[i]);
+ free(messages);
+ }
+#endif
+}
+
+static
+int cdo_feenableexcept(int excepts)
+{
+#if defined HAVE_FEENABLEEXCEPT
+ int feenableexcept(int);
+ int old_excepts = feenableexcept(excepts);
+ return old_excepts;
+#else
+ static fenv_t fenv;
+ unsigned new_excepts = ((unsigned)excepts) & FE_ALL_EXCEPT;
+ int old_excepts = -1; // previous masks
+
+ if ( fegetenv(&fenv) ) return -1;
+#if defined(HAVE_FENV_T___CONTROL) && defined(HAVE_FENV_T___MXCSR)
+ old_excepts = (int) (fenv.__control & FE_ALL_EXCEPT);
+
+ // unmask
+ fenv.__control &= ~new_excepts;
+ fenv.__mxcsr &= ~(new_excepts << 7);
+#endif
+
+ return ( fesetenv(&fenv) ? -1 : (int)old_excepts );
+#endif
+}
+
+static
+void cdo_sig_handler(int signo)
+{
+ if ( signo == SIGFPE )
+ {
+ cdo_stackframe();
+ cdoAbort("floating-point exception!");
+ }
+}
static
void cdo_version(void)
@@ -143,14 +203,19 @@ void cdo_usage(void)
fprintf(stderr, " -b <nbits> Set the number of bits for the output precision\n");
fprintf(stderr, " (I8/I16/I32/F32/F64 for nc/nc2/nc4/nc4c; F32/F64 for grb2/srv/ext/ieg; P1 - P24 for grb/grb2)\n");
fprintf(stderr, " Add L or B to set the byteorder to Little or Big endian\n");
+ if ( ISME )
+ {
+ fprintf(stderr, " --enableexcept <except>\n");
+ fprintf(stderr, " Set individual floating-point traps (DIVBYZERO, INEXACT, INVALID, OVERFLOW, UNDERFLOW, ALL_EXCEPT)\n");
+ }
fprintf(stderr, " -f, --format <format>\n");
fprintf(stderr, " Format of the output file. (grb/grb2/nc/nc2/nc4/nc4c/srv/ext/ieg)\n");
fprintf(stderr, " -g <grid> Set default grid name or file. Available grids: \n");
fprintf(stderr, " n<N>, t<RES>, tl<RES>, global_<DXY>, r<NX>x<NY>, g<NX>x<NY>, gme<NI>, lon=<LON>/lat=<LAT>\n");
fprintf(stderr, " -h, --help Help information for the operators\n");
- fprintf(stderr, " --history Do not append to netCDF \"history\" global attribute\n");
+ fprintf(stderr, " --history Do not append to NetCDF \"history\" global attribute\n");
fprintf(stderr, " --netcdf_hdr_pad, --hdr_pad, --header_pad <nbr>\n");
- fprintf(stderr, " Pad netCDF output header with nbr bytes\n");
+ fprintf(stderr, " Pad NetCDF output header with nbr bytes\n");
/*
fprintf(stderr, " -i <inst> Institution name/file\n");
fprintf(stderr, " Predefined instituts: ");
@@ -166,19 +231,20 @@ void cdo_usage(void)
fprintf(stderr, " -m <missval> Set the default missing value (default: %g)\n", cdiInqMissval());
fprintf(stderr, " --no_warnings Inhibit warning messages\n");
fprintf(stderr, " -O Overwrite existing output file, if checked\n");
+ fprintf(stderr, " --operators List of all operators\n");
#if defined(_OPENMP)
fprintf(stderr, " -P <nthreads> Set number of OpenMP threads\n");
#endif
fprintf(stderr, " --percentile <method>\n");
fprintf(stderr, " Percentile method: nrank, nist, numpy, numpy_lower, numpy_higher, numpy_nearest\n");
- fprintf(stderr, " -Q Alphanumeric sorting of netCDF parameter names\n");
- fprintf(stderr, " --reduce_dim Reduce netCDF dimensions (module: TIMSTAT, FLDSTAT)\n");
- fprintf(stderr, " -R, --regular Convert GRIB1 data from reduced to regular grid (only with cgribex)\n");
+ fprintf(stderr, " -Q Alphanumeric sorting of NetCDF parameter names\n");
+ fprintf(stderr, " --reduce_dim Reduce NetCDF dimensions (module: TIMSTAT, FLDSTAT)\n");
+ fprintf(stderr, " -R, --regular Convert GRIB1 data from reduced to regular grid (cgribex only)\n");
fprintf(stderr, " -r Generate a relative time axis\n");
fprintf(stderr, " -S Create an extra output stream for the module TIMSTAT. This stream\n");
fprintf(stderr, " contains the number of non missing values for each output period.\n");
fprintf(stderr, " -s, --silent Silent mode\n");
- fprintf(stderr, " -t <partab> Set GRIB1 default parameter table name or file\n");
+ fprintf(stderr, " -t <partab> Set GRIB1 default parameter table name or file (cgribex only)\n");
fprintf(stderr, " Predefined tables: ");
for ( int id = 0; id < tableInqNumber(); id++ )
if ( (name = tableInqNamePtr(id)) )
@@ -190,17 +256,20 @@ void cdo_usage(void)
fprintf(stderr, " -W Print extra warning messages\n");
fprintf(stderr, " -z szip SZIP compression of GRIB1 records\n");
fprintf(stderr, " jpeg JPEG compression of GRIB2 records\n");
- fprintf(stderr, " zip[_1-9] Deflate compression of netCDF4 variables\n");
+ fprintf(stderr, " zip[_1-9] Deflate compression of NetCDF4 variables\n");
reset_text_color(stderr);
fprintf(stderr, "\n");
fprintf(stderr, " Operators:\n");
+ fprintf(stderr, " Use option --operators for a list of all operators.\n");
+ /*
set_text_color(stderr, RESET, GREEN);
operatorPrintAll();
reset_text_color(stderr);
+ */
fprintf(stderr, "\n");
- fprintf(stderr, " CDO version %s, Copyright (C) 2003-2015 Uwe Schulzweida\n", VERSION);
+ fprintf(stderr, " CDO version %s, Copyright (C) 2003-2016 Uwe Schulzweida\n", VERSION);
// fprintf(stderr, " Available from <http://mpimet.mpg.de/cdo>\n");
fprintf(stderr, " This is free software and comes with ABSOLUTELY NO WARRANTY\n");
fprintf(stderr, " Report bugs to <http://mpimet.mpg.de/cdo>\n");
@@ -211,11 +280,11 @@ void cdo_init_is_tty(void)
{
struct stat statbuf;
fstat(0, &statbuf);
- if ( S_ISCHR(statbuf.st_mode) ) stdin_is_tty = 1;
+ if ( S_ISCHR(statbuf.st_mode) ) stdin_is_tty = 1;
fstat(1, &statbuf);
- if ( S_ISCHR(statbuf.st_mode) ) stdout_is_tty = 1;
+ if ( S_ISCHR(statbuf.st_mode) ) stdout_is_tty = 1;
fstat(2, &statbuf);
- if ( S_ISCHR(statbuf.st_mode) ) stderr_is_tty = 1;
+ if ( S_ISCHR(statbuf.st_mode) ) stderr_is_tty = 1;
}
static
@@ -266,7 +335,6 @@ void cdoPrintHelp(const char *phelp[]/*, char *xoperator*/)
}
}
-
static
void cdoSetDebug(int level)
{
@@ -517,43 +585,37 @@ void setDefaultFileType(const char *filetypestr, int labort)
}
}
-#if defined(malloc)
-#undef malloc
-#undef free
-#endif
-
#define NTESTS 11
#include <inttypes.h>
static
int getMemAlignment(void)
{
int ma = -1;
- int i, k;
double *ptr[NTESTS];
int64_t iptr;
size_t tsize[NTESTS] = {1, 3, 5, 9, 17, 33, 69, 121, 251, 510, 1025};
size_t ma_check[4] = {8, 16, 32, 64};
int ma_result[4] = {1, 1, 1, 1};
- for ( i = 0; i < NTESTS; ++i )
+ for ( int i = 0; i < NTESTS; ++i )
{
- ptr[i] = (double*) Malloc(tsize[i]);
+ ptr[i] = (double*) malloc(tsize[i]);
iptr = (int64_t) ptr[i];
- for ( k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0;
+ for ( int k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0;
}
- for ( i = 0; i < NTESTS; ++i ) Free(ptr[i]);
+ for ( int i = 0; i < NTESTS; ++i ) free(ptr[i]);
- for ( i = NTESTS-1; i >= 0; i-- )
+ for ( int i = NTESTS-1; i >= 0; i-- )
{
- ptr[i] = (double*) Malloc(tsize[i]+5);
+ ptr[i] = (double*) malloc(tsize[i]+5);
iptr = (int64_t) ptr[i];
- for ( k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0;
+ for ( int k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0;
}
- for ( i = 0; i < NTESTS; ++i ) Free(ptr[i]);
+ for ( int i = 0; i < NTESTS; ++i ) free(ptr[i]);
- for ( k = 0; k < 4; ++k ) if ( ma_result[k] ) ma = ma_check[k];
+ for ( int k = 0; k < 4; ++k ) if ( ma_result[k] ) ma = ma_check[k];
- return (ma);
+ return ma;
}
@@ -645,6 +707,13 @@ void get_env_vars(void)
{
char *envstr;
+ username = getenv("LOGNAME");
+ if ( username == NULL )
+ {
+ username = getenv("USER");
+ if ( username == NULL ) username = "unknown";
+ }
+
envstr = getenv("CDO_GRID_SEARCH_DIR");
if ( envstr )
{
@@ -777,19 +846,7 @@ void get_env_vars(void)
fprintf(stderr, "CDO_COLOR = %s\n", envstr);
}
}
- else
- {
- if ( CDO_Color == FALSE )
- {
- const char *username = getenv("LOGNAME");
- if ( username == NULL )
- {
- username = getenv("USER");
- if ( username == NULL ) username = "unknown";
- }
- if ( strcmp(username, "\x6d\x32\x31\x34\x30\x30\x33") == 0 ) CDO_Color = TRUE;
- }
- }
+ else if ( CDO_Color == FALSE && ISME ) CDO_Color = TRUE;
}
static
@@ -1005,7 +1062,7 @@ long str_to_int(const char *intstring)
if ( fact ) intval = fact*atol(intstring);
}
- return (intval);
+ return intval;
}
static
@@ -1018,6 +1075,8 @@ int parse_options_long(int argc, char *argv[])
int lgridsearchradius;
int lremap_genweights;
int lpercentile;
+ int lprintoperators = 0;
+ int lenableexcept;
struct cdo_option opt_long[] =
{
@@ -1029,9 +1088,12 @@ int parse_options_long(int argc, char *argv[])
{ "gridsearchnn", required_argument, &lgridsearchnn, 1 },
{ "gridsearchradius", required_argument, &lgridsearchradius, 1 },
{ "remap_genweights", required_argument, &lremap_genweights, 1 },
+ { "enableexcept", required_argument, &lenableexcept, 1 },
{ "cmor", no_argument, &CDO_CMOR_Mode, 1 },
{ "reduce_dim", no_argument, &CDO_Reduce_Dim, 1 },
+ { "float", no_argument, &CDO_Memtype, MEMTYPE_FLOAT },
{ "rusage", no_argument, &CDO_Rusage, 1 },
+ { "operators", no_argument, &lprintoperators, 1 },
{ "no_warnings", no_argument, &_Verbose, 0 },
{ "format", required_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
@@ -1055,8 +1117,9 @@ int parse_options_long(int argc, char *argv[])
lgridsearchnn = 0;
lgridsearchradius = 0;
lremap_genweights = 0;
+ lenableexcept = 0;
- c = cdo_getopt_long(argc, argv, "f:b:e:P:p:g:i:k:l:m:n:t:D:z:aBCcdhLMOQRrsSTuVvWXZ", opt_long, NULL);
+ c = cdo_getopt_long(argc, argv, "f:b:e:P:g:i:k:l:m:n:t:D:z:aBCcdhLMOpQRrsSTuVvWXZ", opt_long, NULL);
if ( c == -1 ) break;
switch (c)
@@ -1081,6 +1144,19 @@ int parse_options_long(int argc, char *argv[])
{
percentile_set_method(CDO_optarg);
}
+ else if ( lenableexcept )
+ {
+ int except = -1;
+ if ( strcmp(CDO_optarg, "DIVBYZERO") == 0 ) except = FE_DIVBYZERO;
+ else if ( strcmp(CDO_optarg, "INEXACT") == 0 ) except = FE_INEXACT;
+ else if ( strcmp(CDO_optarg, "INVALID") == 0 ) except = FE_INVALID;
+ else if ( strcmp(CDO_optarg, "OVERFLOW") == 0 ) except = FE_OVERFLOW;
+ else if ( strcmp(CDO_optarg, "UNDERFLOW") == 0 ) except = FE_UNDERFLOW;
+ else if ( strcmp(CDO_optarg, "ALL_EXCEPT") == 0 ) except = FE_ALL_EXCEPT;
+ if ( except < 0 ) cdoAbort("option --%s: unsupported argument: %s", "enableexcept", CDO_optarg);
+ cdo_feenableexcept((unsigned)except);
+ if ( signal(SIGFPE, cdo_sig_handler) == SIG_ERR ) cdoWarning("can't catch SIGFPE!");
+ }
else if ( luse_fftw )
{
int intarg = parameter2int(CDO_optarg);
@@ -1190,8 +1266,7 @@ int parse_options_long(int argc, char *argv[])
numThreads = atoi(CDO_optarg);
break;
case 'p':
- fprintf(stderr, "CDO option -p is not available anymore, please use -b <bits>!\n");
- //setDefaultDataTypeByte(CDO_optarg);
+ CDO_Parallel_Read = TRUE;
break;
case 'Q':
cdiDefGlobal("SORTNAME", TRUE);
@@ -1239,6 +1314,15 @@ int parse_options_long(int argc, char *argv[])
}
}
+ if ( lprintoperators )
+ {
+ set_text_color(stderr, RESET, GREEN);
+ operatorPrintList();
+ //operatorPrintAll();
+ reset_text_color(stderr);
+ return 1;
+ }
+
return 0;
}
@@ -1304,6 +1388,13 @@ int main(int argc, char *argv[])
if ( Debug || Version ) cdo_version();
+ if ( Debug )
+ {
+ fprintf(stderr, "stdin_is_tty: %d\n", stdin_is_tty);
+ fprintf(stderr, "stdout_is_tty: %d\n", stdout_is_tty);
+ fprintf(stderr, "stderr_is_tty: %d\n", stderr_is_tty);
+ }
+
if ( Debug ) print_system_info();
check_stacksize();
@@ -1351,7 +1442,7 @@ int main(int argc, char *argv[])
if ( numThreads > 0 )
{
fprintf(stderr, "Option -P failed, OpenMP support not compiled in!\n");
- return(-1);
+ return -1;
}
#endif
@@ -1375,7 +1466,7 @@ int main(int argc, char *argv[])
lstop = TRUE;
}
- if ( lstop ) return (status);
+ if ( lstop ) return status;
if ( cdoDefaultTableID != CDI_UNDEFID ) cdiDefTableID(cdoDefaultTableID);
@@ -1395,11 +1486,11 @@ int main(int argc, char *argv[])
{
if ( DebugLevel == 0 ) DebugLevel = 1;
cdoSetDebug(DebugLevel);
- }
+ }
- timer_total = timer_new("total");
- timer_read = timer_new("read");
- timer_write = timer_new("write");
+ timer_total = timer_new("total");
+ timer_read = timer_new("read");
+ timer_write = timer_new("write");
timer_start(timer_total);
@@ -1426,5 +1517,5 @@ int main(int argc, char *argv[])
if ( CDO_Rusage ) cdo_rusage();
- return (status);
+ return status;
}
diff --git a/src/cdo.h b/src/cdo.h
index 569c938..bb6f03c 100644
--- a/src/cdo.h
+++ b/src/cdo.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/cdo_getopt.c b/src/cdo_getopt.c
index b188657..35df1da 100644
--- a/src/cdo_getopt.c
+++ b/src/cdo_getopt.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/cdo_getopt.h b/src/cdo_getopt.h
index 777e2ab..0575bd4 100644
--- a/src/cdo_getopt.h
+++ b/src/cdo_getopt.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/cdo_history.c b/src/cdo_history.c
index 2753385..3c41291 100644
--- a/src/cdo_history.c
+++ b/src/cdo_history.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "cdi_uuid.h"
static char *ghistory = NULL;
static size_t ghistorysize = 0;
@@ -123,18 +124,14 @@ void cdo_def_creation_date(int vlistID)
}
-void create_uuid(unsigned char uuid[CDI_UUID_SIZE]);
-void uuid2str(const unsigned char *uuid, char *uuidstr);
-
-
#define UUIDSTR_SIZE (CDI_UUID_SIZE*2 + 4)
static
void get_uuid(char uuidstr[UUIDSTR_SIZE])
{
unsigned char uuid[CDI_UUID_SIZE];
- create_uuid(uuid);
- uuid2str(uuid, uuidstr);
+ cdiCreateUUID(uuid);
+ cdiUUID2Str(uuid, uuidstr);
}
diff --git a/src/cdo_int.h b/src/cdo_int.h
index e9d490f..94590c7 100644
--- a/src/cdo_int.h
+++ b/src/cdo_int.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -121,10 +121,6 @@ void time2str(int time, char *timestr, int maxlen);
const char * tunit2str(int tunits);
const char * calendar2str(int calendar);
-int days_per_month(int calendar, int year, int month);
-int days_per_year(int calendar, int year);
-int calendar_dpy(int calendar);
-
void defineGrid(const char *gridarg);
void defineInstitution(const char *instarg);
int defineTable(const char *tablearg);
@@ -152,4 +148,24 @@ double parameter2double(const char *string);
int parameter2int(const char *string);
int parameter2intlist(const char *string);
+int referenceToGrid(int gridID1);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cdiDefTableID(int tableID);
+
+void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals);
+void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals);
+
+void gaussaw(double *restrict pa, double *restrict pw, size_t nlat);
+
+int qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
+ double msval, int *kret, int omisng, int operio, int oveggy);
+
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _CDO_INT_H */
diff --git a/src/cdo_pthread.c b/src/cdo_pthread.c
index 591b5f1..44622cc 100644
--- a/src/cdo_pthread.c
+++ b/src/cdo_pthread.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/cdo_vlist.c b/src/cdo_vlist.c
index ff12869..42f13ae 100644
--- a/src/cdo_vlist.c
+++ b/src/cdo_vlist.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -44,9 +44,8 @@ void compare_lat_reg2d(int ysize, int gridID1, int gridID2)
else
{
for ( int i = 0; i < ysize; ++i )
- if ( fabs(yvals1[i] - yvals2[i]) > 1.e-5 )
+ if ( fabs(yvals1[i] - yvals2[i]) > 3.e-5 )
{
- // printf("lat %g %g %g\n", yvals1[i], yvals2[i], yvals1[i] - yvals2[i]);
cdoWarning("Grid latitudes differ!");
break;
}
@@ -69,7 +68,7 @@ void compare_lon_reg2d(int xsize, int gridID1, int gridID2)
gridInqXvals(gridID2, xvals2);
for ( int i = 0; i < xsize; ++i )
- if ( fabs(xvals1[i] - xvals2[i]) > 1.e-5 )
+ if ( fabs(xvals1[i] - xvals2[i]) > 3.e-5 )
{
cdoWarning("Grid longitudes differ!");
break;
@@ -137,7 +136,7 @@ void compareGrids(int gridID1, int gridID2)
compare_grid_unstructured(gridID1, gridID2);
}
}
- else
+ else if ( gridInqSize(gridID1) > 1 )
{
cdoWarning("Grids have different types! First grid: %s; second grid: %s",
gridNamePtr(gridInqType(gridID1)), gridNamePtr(gridInqType(gridID2)));
@@ -197,10 +196,41 @@ void vlistCompare(int vlistID1, int vlistID2, int flag)
if ( flag & CMP_NLEVEL )
{
- if ( zaxisInqSize(vlistInqVarZaxis(vlistID1, varID)) !=
- zaxisInqSize(vlistInqVarZaxis(vlistID2, varID)) )
- cdoAbort("Number of levels of the input parameters do not match!");
- }
+ int zaxisID1 = vlistInqVarZaxis(vlistID1, varID);
+ int zaxisID2 = vlistInqVarZaxis(vlistID2, varID);
+ if ( zaxisID1 != zaxisID2 )
+ {
+ int nlev1 = zaxisInqSize(zaxisID1);
+ int nlev2 = zaxisInqSize(zaxisID2);
+ if ( nlev1 != nlev2 )
+ cdoAbort("Number of levels of the input parameters do not match!");
+
+ double *lev1 = (double*) Malloc(nlev1*sizeof(double));
+ double *lev2 = (double*) Malloc(nlev1*sizeof(double));
+ zaxisInqLevels(zaxisID1, lev1);
+ zaxisInqLevels(zaxisID2, lev2);
+
+ int ldiffer = FALSE;
+ for ( int i = 0; i < nlev1; ++i )
+ if ( IS_NOT_EQUAL(lev1[i], lev2[i]) )
+ { ldiffer = TRUE; break; }
+ if ( ldiffer )
+ {
+ ldiffer = FALSE;
+ for ( int i = 0; i < nlev1; ++i )
+ if ( IS_NOT_EQUAL(lev1[i], lev2[nlev1-1-i]) )
+ { ldiffer = TRUE; break; }
+
+ if ( ldiffer )
+ cdoWarning("Input parameters have different levels!");
+ else
+ cdoWarning("Z-axis orientation differ!");
+ }
+
+ Free(lev1);
+ Free(lev2);
+ }
+ }
}
if ( flag & CMP_GRID )
@@ -227,15 +257,13 @@ void vlistCompare(int vlistID1, int vlistID2, int flag)
if ( strcmp(names1[varID], names2[varID]) != 0 ) break;
if ( varID == nvars )
- cdoPrint("Use the CDO option -Q to sort the parameter names, if you have netCDF input files!");
+ cdoPrint("Use the CDO option -Q to sort the parameter names, if you have NetCDF input files!");
}
}
int vlistCompareX(int vlistID1, int vlistID2, int flag)
{
- int varID;
-
int nvars = vlistNvars(vlistID1);
int nvars2 = vlistNvars(vlistID2);
int nlevels2 = zaxisInqSize(vlistInqVarZaxis(vlistID2, 0));
@@ -243,7 +271,7 @@ int vlistCompareX(int vlistID1, int vlistID2, int flag)
if ( nvars2 != 1 )
cdoAbort("Internal problem, vlistCompareX() called with unexpected vlistID2 argument!");
- for ( varID = 0; varID < nvars; varID++ )
+ for ( int varID = 0; varID < nvars; varID++ )
{
if ( flag & CMP_GRIDSIZE )
{
diff --git a/src/commandline.c b/src/commandline.c
index d1f0889..2d9d43b 100644
--- a/src/commandline.c
+++ b/src/commandline.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/compare.h b/src/compare.h
index 717d7b2..6aeb13a 100644
--- a/src/compare.h
+++ b/src/compare.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/config.h.in b/src/config.h.in
index 574c13c..39c5388 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -12,6 +12,9 @@
/* Define to 1 for DATA support */
#undef ENABLE_DATA
+/* Define to 1 if you have the `backtrace' function. */
+#undef HAVE_BACKTRACE
+
/* Define to 1 if you have the <cmor.h> header file. */
#undef HAVE_CMOR_H
@@ -25,6 +28,18 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if you have the <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the `feenableexcept' function. */
+#undef HAVE_FEENABLEEXCEPT
+
+/* Define to 1 if `__control' is a member of `fenv_t'. */
+#undef HAVE_FENV_T___CONTROL
+
+/* Define to 1 if `__mxcsr' is a member of `fenv_t'. */
+#undef HAVE_FENV_T___MXCSR
+
/* Define to 1 if you have the <fftw3.h> header file. */
#undef HAVE_FFTW3_H
diff --git a/src/dmemory.h b/src/dmemory.h
index d59d136..90ec1f0 100644
--- a/src/dmemory.h
+++ b/src/dmemory.h
@@ -10,6 +10,10 @@
#define WITH_FUNCTION_NAME
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern size_t memTotal(void);
extern void memDebug(int debug);
extern void memExitOnError(void);
@@ -21,6 +25,10 @@ extern void *memCalloc (size_t nmemb, size_t size, const char *file, const cha
extern void *memMalloc (size_t size, const char *file, const char *functionname, int line);
extern void memFree (void *ptr, const char *file, const char *functionname, int line);
+#if defined (__cplusplus)
+}
+#endif
+
#if defined WITH_FUNCTION_NAME
# define Realloc(p, s) memRealloc((p), (s), __FILE__, __func__, __LINE__)
# define Calloc(n, s) memCalloc((n), (s), __FILE__, __func__, __LINE__)
@@ -35,15 +43,6 @@ extern void memFree (void *ptr, const char *file, const char *functionname,
#endif /* DEBUG_MEMORY */
-void *cdiXmalloc(size_t, const char *, const char *, int);
-#define xmalloc(size) cdiXmalloc((size), __FILE__, __func__, __LINE__ )
-
-void *cdiXcalloc(size_t, size_t, const char *, const char *, int);
-#define xcalloc(nmemb,size) cdiXcalloc((nmemb), (size), __FILE__, __func__, __LINE__)
-
-void *cdiXrealloc(void *, size_t, const char *, const char *, int);
-#define xrealloc(p,size) cdiXrealloc((p), (size), __FILE__, __func__, __LINE__)
-
#endif /* _DMEMORY_H */
/*
* Local Variables:
diff --git a/src/ecacore.c b/src/ecacore.c
index a5edf9f..5a43380 100755
--- a/src/ecacore.c
+++ b/src/ecacore.c
@@ -36,6 +36,7 @@ void eca1(const ECA_REQUEST_1 *request)
{
const int operatorID = cdoOperatorID();
+ int nmiss;
int cmplen;
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
int gridsize;
@@ -224,7 +225,8 @@ void eca1(const ECA_REQUEST_1 *request)
if ( IS_SET(request->var2.h3) ) var23[levelID].nmiss = gridsize;
}
- streamReadRecord(istreamID, field1.ptr, &field1.nmiss);
+ streamReadRecord(istreamID, field1.ptr, &nmiss);
+ field1.nmiss = (size_t)nmiss;
field1.grid = var12[levelID].grid;
field1.missval = var12[levelID].missval;
@@ -402,6 +404,7 @@ void eca2(const ECA_REQUEST_2 *request)
{
const int operatorID = cdoOperatorID();
+ int nmiss;
int cmplen;
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
int gridsize;
@@ -611,11 +614,13 @@ void eca2(const ECA_REQUEST_2 *request)
var22[levelID].nmiss = gridsize;
}
- streamReadRecord(istreamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(istreamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t)nmiss;
field1.grid = gridID;
field1.missval = missval1;
- streamReadRecord(istreamID2, field2.ptr, &field2.nmiss);
+ streamReadRecord(istreamID2, field2.ptr, &nmiss);
+ field2.nmiss = (size_t)nmiss;
field2.grid = gridID;
field2.missval = missval2;
@@ -789,6 +794,7 @@ void eca3(const ECA_REQUEST_3 *request)
{
const int operatorID = cdoOperatorID();
+ int nmiss;
int cmplen;
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
int gridsize;
@@ -930,11 +936,13 @@ void eca3(const ECA_REQUEST_3 *request)
var2[levelID].nmiss = gridsize;
}
- streamReadRecord(istreamID1, field1.ptr, &field1.nmiss);
+ streamReadRecord(istreamID1, field1.ptr, &nmiss);
+ field1.nmiss = (size_t)nmiss;
field1.grid = var1[levelID].grid;
field1.missval = var1[levelID].missval;
- streamReadRecord(istreamID2, field2.ptr, &field2.nmiss);
+ streamReadRecord(istreamID2, field2.ptr, &nmiss);
+ field2.nmiss = (size_t)nmiss;
field2.grid = var1[levelID].grid;
field2.missval = var1[levelID].missval;
@@ -994,6 +1002,7 @@ void eca4(const ECA_REQUEST_4 *request)
{
const int operatorID = cdoOperatorID();
+ int nmiss;
int cmplen;
char indate1[DATE_LEN+1], indate2[DATE_LEN+1];
int gridsize, gridtype;
@@ -1171,7 +1180,8 @@ void eca4(const ECA_REQUEST_4 *request)
if ( streamInqTimestep(istreamID2, itsID) )
{
streamInqRecord(istreamID2, &varID, &levelID);
- streamReadRecord(istreamID2, mask.ptr, &mask.nmiss);
+ streamReadRecord(istreamID2, mask.ptr, &nmiss);
+ mask.nmiss = (size_t)nmiss;
mask.grid = gridID;
mask.missval = vlistInqVarMissval(ivlistID2, 0);
@@ -1238,9 +1248,10 @@ void eca4(const ECA_REQUEST_4 *request)
endDateWithHist[1][levelID].nmiss = gridsize;
}
- streamReadRecord(istreamID1, fieldGt.ptr, &fieldGt.nmiss);
+ streamReadRecord(istreamID1, fieldGt.ptr, &nmiss);
+ fieldGt.nmiss = (size_t)nmiss;
memcpy(fieldLt.ptr, fieldGt.ptr, gridsize*sizeof(double));
- fieldLt.nmiss = fieldGt.nmiss;
+ fieldLt.nmiss = fieldGt.nmiss;
fieldGt.grid = startCount[levelID].grid;
fieldGt.missval = startCount[levelID].missval;
fieldLt.grid = startCount[levelID].grid;
diff --git a/src/error.h b/src/error.h
index 02323b4..13a712f 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,6 +1,9 @@
#ifndef _ERROR_H
#define _ERROR_H
+#include <stdarg.h>
+#include <stdlib.h>
+
#ifndef WITH_CALLER_NAME
#define WITH_CALLER_NAME
#endif
@@ -9,6 +12,10 @@
#define _VERBOSE 2 /* Error flag: report errors */
#define _DEBUG 4 /* Error flag: debug */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern int _ExitOnError; /* If set to 1, exit on error (default 1) */
extern int _Verbose; /* If set to 1, errors are reported (default 1) */
extern int _Debug; /* If set to 1, debuggig (default 0) */
@@ -16,6 +23,8 @@ extern int _Debug; /* If set to 1, debuggig (default 0) */
void SysError_(const char *caller, const char *fmt, ...);
void Error_(const char *caller, const char *fmt, ...);
void Warning_(const char *caller, const char *fmt, ...);
+/* delegate used by Warning_ unless mode is PIO */
+void cdiWarning(const char *caller, const char *fmt, va_list ap);
void Message_(const char *caller, const char *fmt, ...);
#if defined WITH_CALLER_NAME
@@ -34,4 +43,44 @@ void Message_(const char *caller, const char *fmt, ...);
# define Message(...) Message_((void *), __VA_ARGS__)
#endif
+/* If we're not using GNU C, elide __attribute__ */
+#ifndef __GNUC__
+# define __attribute__(x) /*NOTHING*/
+#endif
+
+void cdiAbortC(const char *caller, const char *filename,
+ const char *functionname, int line,
+ const char *errorString, ... )
+ __attribute__((noreturn));
+#define xabortC(caller, ...) \
+ cdiAbortC(caller, __FILE__, __func__, __LINE__, __VA_ARGS__ )
+#define xabort(...) \
+ cdiAbortC(NULL, __FILE__, __func__, __LINE__, __VA_ARGS__ )
+#define cdiAbort(file, func, line, ...) \
+ cdiAbortC(NULL, (file), (func), (line), __VA_ARGS__)
+
+#define xassert(arg) do { \
+ if ((arg)) { } else { \
+ xabort("assertion `" #arg "` failed");} \
+ } while(0)
+
+void
+cdiAbortC_serial(const char *caller, const char *filename,
+ const char *functionname, int line,
+ const char *errorString, va_list ap)
+ __attribute__((noreturn));
+
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _ERROR_H */
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/exception.c b/src/exception.c
index 5aa0cf1..1197283 100644
--- a/src/exception.c
+++ b/src/exception.c
@@ -10,6 +10,7 @@
#include "process.h"
#include "error.h"
+void pstreamCloseAll(void);
void cdiOpenError(int cdiErrno, const char *fmt, const char *path)
{
@@ -32,50 +33,38 @@ void cdiOpenError(int cdiErrno, const char *fmt, const char *path)
switch (filetype)
{
case FILETYPE_GRB:
- {
- break;
- }
+ break;
case FILETYPE_GRB2:
- {
- fprintf(stderr, "To create a CDO application with GRIB2 support use: ./configure --with-netcdf=<GRIB_API root directory> ...\n");
- break;
- }
+ fprintf(stderr, "To create a CDO application with GRIB2 support use: ./configure --with-netcdf=<GRIB_API root directory> ...\n");
+ break;
case FILETYPE_SRV:
- {
- break;
- }
+ break;
case FILETYPE_EXT:
- {
- break;
- }
+ break;
case FILETYPE_IEG:
- {
- break;
- }
+ break;
case FILETYPE_NC:
case FILETYPE_NC2:
case FILETYPE_NC4:
case FILETYPE_NC4C:
- {
- const char *ncv = (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) ? "4" : ((filetype == FILETYPE_NC2) ? "2" : "");
+ {
+ const char *ncv = (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) ? "4" : ((filetype == FILETYPE_NC2) ? "2" : "");
#if defined HAVE_LIBNETCDF
- fprintf(stderr, "CDO was build with a netCDF version which doesn't support netCDF%s data!\n", ncv);
+ fprintf(stderr, "CDO was build with a NetCDF version which doesn't support NetCDF%s data!\n", ncv);
#else
- fprintf(stderr, "To create a CDO application with netCDF%s support use: ./configure --with-netcdf=<netCDF%s root directory> ...\n", ncv, ncv);
+ fprintf(stderr, "To create a CDO application with NetCDF%s support use: ./configure --with-netcdf=<NetCDF%s root directory> ...\n", ncv, ncv);
#endif
- break;
- }
+ break;
+ }
default:
- {
- break;
- }
+ break;
}
}
+ if ( _ExitOnError ) pstreamCloseAll();
if ( _ExitOnError ) exit(EXIT_FAILURE);
}
-void pstreamCloseAll(void);
void cdoAbort(const char *fmt, ...)
{
va_list args;
diff --git a/src/expr.c b/src/expr.c
index 6bf2d8f..bea9b41 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1,17 +1,44 @@
+/*
+ This file is part of CDO. CDO is a collection of Operators to
+ manipulate and analyse Climate model Data.
+
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ See COPYING file for copying and redistribution conditions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <ctype.h>
+#include <assert.h>
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
#include "field.h"
#include "expr.h"
+#include "expr_fun.h"
#include "expr_yacc.h"
+
+static const char *ExIn[] = {"expr", "init"};
+static const char *tmpvnm = "_tmp_";
+int pointID = -1;
+int surfaceID = -1;
+
+enum {FT_STD, FT_CONST, FT_FLD, FT_VERT, FT_COORD, FT_1C};
+
#define COMPLT(x,y) ((x) < (y) ? 1 : 0)
#define COMPGT(x,y) ((x) > (y) ? 1 : 0)
#define COMPLE(x,y) ((x) <= (y) ? 1 : 0)
@@ -31,64 +58,154 @@
#define MVCOMPAND(x,y) (DBL_IS_EQUAL((x),missval1) ? missval1 : COMPAND(x,y))
#define MVCOMPOR(x,y) (DBL_IS_EQUAL((x),missval1) ? missval1 : COMPOR(x,y))
-static double f_int(double x) { return ((int)(x)); }
-static double f_nint(double x) { return (round(x)); }
-static double f_sqr(double x) { return (x*x); }
+static double f_int(double x) { return (int)(x); }
+static double f_nint(double x) { return round(x); }
+static double f_sqr(double x) { return x*x; }
+static double f_rad(double x) { return x*M_PI/180.; }
+static double f_deg(double x) { return x*180./M_PI; }
+static double pt_ngp(paramType *p) { return p->ngp; }
+static double pt_nlev(paramType *p) { return p->nlev; }
+static double pt_size(paramType *p) { return p->ngp*p->nlev; }
+static double pt_missval(paramType *p) { return p->missval; }
typedef struct {
int type;
- const char *name; /* function name */
- double (*func)(double); /* pointer to function */
+ int flag;
+ const char *name; // function name
+ void (*func)(); // pointer to function
}
func_t;
static func_t fun_sym_tbl[] =
{
- /* scalar functions */
- {0, "abs", fabs},
- {0, "floor", floor},
- {0, "ceil", ceil},
- {0, "int", f_int},
- {0, "nint", f_nint},
- {0, "sqr", f_sqr},
- {0, "sqrt", sqrt},
- {0, "exp", exp},
- {0, "erf", erf},
- {0, "log", log},
- {0, "log10", log10},
- {0, "sin", sin},
- {0, "cos", cos},
- {0, "tan", tan},
- {0, "sinh", sinh},
- {0, "cosh", cosh},
- {0, "tanh", tanh},
- {0, "asin", asin},
- {0, "acos", acos},
- {0, "atan", atan},
- {0, "asinh", asinh},
- {0, "acosh", acosh},
- {0, "atanh", atanh},
- {0, "gamma", tgamma},
-
- /* array functions
- {1, "min", min},
- {1, "max", max},
- {1, "sum", sum},
- {1, "avg", avg},
- {1, "mean", mean},
- {1, "std", std},
- {1, "var", var},
- */
+ // scalar functions
+ {FT_STD, 0, "abs", (void (*)()) fabs},
+ {FT_STD, 0, "floor", (void (*)()) floor},
+ {FT_STD, 0, "ceil", (void (*)()) ceil},
+ {FT_STD, 0, "int", (void (*)()) f_int},
+ {FT_STD, 0, "nint", (void (*)()) f_nint},
+ {FT_STD, 0, "sqr", (void (*)()) f_sqr},
+ {FT_STD, 0, "sqrt", (void (*)()) sqrt},
+ {FT_STD, 0, "exp", (void (*)()) exp},
+ {FT_STD, 0, "erf", (void (*)()) erf},
+ {FT_STD, 0, "log", (void (*)()) log},
+ {FT_STD, 0, "log10", (void (*)()) log10},
+ {FT_STD, 0, "sin", (void (*)()) sin},
+ {FT_STD, 0, "cos", (void (*)()) cos},
+ {FT_STD, 0, "tan", (void (*)()) tan},
+ {FT_STD, 0, "sinh", (void (*)()) sinh},
+ {FT_STD, 0, "cosh", (void (*)()) cosh},
+ {FT_STD, 0, "tanh", (void (*)()) tanh},
+ {FT_STD, 0, "asin", (void (*)()) asin},
+ {FT_STD, 0, "acos", (void (*)()) acos},
+ {FT_STD, 0, "atan", (void (*)()) atan},
+ {FT_STD, 0, "asinh", (void (*)()) asinh},
+ {FT_STD, 0, "acosh", (void (*)()) acosh},
+ {FT_STD, 0, "atanh", (void (*)()) atanh},
+ {FT_STD, 0, "gamma", (void (*)()) tgamma},
+ {FT_STD, 0, "rad", (void (*)()) f_rad},
+ {FT_STD, 0, "deg", (void (*)()) f_deg},
+
+ // constant functions
+ {FT_CONST, 0, "ngp", (void (*)()) pt_ngp}, // number of horizontal grid points
+ {FT_CONST, 0, "nlev", (void (*)()) pt_nlev}, // number of vertical levels
+ {FT_CONST, 0, "size", (void (*)()) pt_size}, // ngp*nlev
+ {FT_CONST, 0, "missval", (void (*)()) pt_missval}, // Returns the missing value of a variable
+
+ // cdo field functions (Reduce grid to point)
+ {FT_FLD, 0, "fldmin", (void (*)()) fldmin},
+ {FT_FLD, 0, "fldmax", (void (*)()) fldmax},
+ {FT_FLD, 0, "fldsum", (void (*)()) fldsum},
+ {FT_FLD, 1, "fldmean", (void (*)()) fldmean},
+ {FT_FLD, 1, "fldavg", (void (*)()) fldavg},
+ {FT_FLD, 1, "fldstd", (void (*)()) fldstd},
+ {FT_FLD, 1, "fldstd1", (void (*)()) fldstd1},
+ {FT_FLD, 1, "fldvar", (void (*)()) fldvar},
+ {FT_FLD, 1, "fldvar1", (void (*)()) fldvar1},
+
+ // cdo field functions (Reduce level to point)
+ {FT_VERT, 0, "vertmin", (void (*)()) fldmin},
+ {FT_VERT, 0, "vertmax", (void (*)()) fldmax},
+ {FT_VERT, 0, "vertsum", (void (*)()) fldsum},
+ {FT_VERT, 1, "vertmean", (void (*)()) fldmean},
+ {FT_VERT, 1, "vertavg", (void (*)()) fldavg},
+ {FT_VERT, 1, "vertstd", (void (*)()) fldstd},
+ {FT_VERT, 1, "vertstd1", (void (*)()) fldstd1},
+ {FT_VERT, 1, "vertvar", (void (*)()) fldvar},
+ {FT_VERT, 1, "vertvar1", (void (*)()) fldvar1},
+
+ {FT_COORD, 0, "clon", NULL},
+ {FT_COORD, 0, "clat", NULL},
+ {FT_COORD, 0, "clev", NULL},
+ {FT_COORD, 0, "gridarea", NULL},
+ {FT_COORD, 0, "gridweight", NULL},
+
+ {FT_1C, 0, "sellevel", NULL},
+ {FT_1C, 0, "sellevidx", NULL},
};
static int NumFunc = sizeof(fun_sym_tbl) / sizeof(fun_sym_tbl[0]);
static
+void node_data_delete(nodeType *p)
+{
+ if ( p )
+ {
+ if ( p->param.data ) { Free(p->param.data); p->param.data = NULL;}
+ }
+}
+
+static
+void node_delete(nodeType *p)
+{
+ if ( p )
+ {
+ if ( p->type == typeVar ) node_data_delete(p);
+ Free(p);
+ }
+}
+
+static
+int get_funcID(const char *fun)
+{
+ int funcID = -1;
+ for ( int i = 0; i < NumFunc; i++ )
+ if ( strcmp(fun, fun_sym_tbl[i].name) == 0 )
+ {
+ funcID = i;
+ break;
+ }
+
+ if ( funcID == -1 ) cdoAbort("Function >%s< not available!", fun);
+
+ return funcID;
+}
+
+static
+void param_meta_copy(paramType *out, paramType *in)
+{
+ out->gridID = in->gridID;
+ out->zaxisID = in->zaxisID;
+ out->steptype = in->steptype;
+ out->ngp = in->ngp;
+ out->nlev = in->nlev;
+ out->missval = in->missval;
+ out->nmiss = 0;
+ out->coord = 0;
+ out->lmiss = true;
+ out->name = NULL;
+ out->longname = NULL;
+ out->units = NULL;
+ out->data = NULL;
+}
+
+static
nodeType *expr_con_con(int oper, nodeType *p1, nodeType *p2)
{
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
- p->type = typeCon;
+ p->type = typeCon;
+ p->ltmpobj = true;
double cval1 = p1->u.con.value;
double cval2 = p2->u.con.value;
@@ -105,41 +222,41 @@ nodeType *expr_con_con(int oper, nodeType *p1, nodeType *p2)
p->u.con.value = cval1;
- return (p);
+ return p;
}
static
-void oper_expr_con_var(int oper, int nmiss, long n, double missval1, double missval2,
+void oper_expr_con_var(int oper, bool nmiss, size_t n, double missval1, double missval2,
double *restrict odat, double cval, const double *restrict idat)
{
- long i;
+ size_t i;
switch ( oper )
{
case '+':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = ADD(cval, idat[i]);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = ADDMN(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = cval + idat[i];
break;
case '-':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = SUB(cval, idat[i]);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = SUBMN(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = cval - idat[i];
break;
case '*':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MUL(cval, idat[i]);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MULMN(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = cval * idat[i];
break;
case '/':
- for ( i=0; i<n; ++i ) odat[i] = DIV(cval, idat[i]);
+ for ( i=0; i<n; ++i ) odat[i] = DIVMN(cval, idat[i]);
break;
case '^':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = POW(cval, idat[i]);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = POWMN(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = pow(cval, idat[i]);
break;
- case '<':
+ case LT:
if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MVCOMPLT(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = COMPLT(cval, idat[i]);
break;
- case '>':
+ case GT:
if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MVCOMPGT(cval, idat[i]);
else for ( i=0; i<n; ++i ) odat[i] = COMPGT(cval, idat[i]);
break;
@@ -177,38 +294,38 @@ void oper_expr_con_var(int oper, int nmiss, long n, double missval1, double miss
}
static
-void oper_expr_var_con(int oper, int nmiss, long n, double missval1, double missval2,
+void oper_expr_var_con(int oper, bool nmiss, size_t n, double missval1, double missval2,
double *restrict odat, const double *restrict idat, double cval)
{
- long i;
+ size_t i;
switch ( oper )
{
case '+':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = ADD(idat[i], cval);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = ADDMN(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = idat[i] + cval;
break;
case '-':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = SUB(idat[i], cval);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = SUBMN(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = idat[i] - cval;
break;
case '*':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MUL(idat[i], cval);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MULMN(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = idat[i] * cval;
break;
case '/':
- if ( nmiss || IS_EQUAL(cval, 0) ) for ( i=0; i<n; ++i ) odat[i] = DIV(idat[i], cval);
+ if ( nmiss || IS_EQUAL(cval, 0) ) for ( i=0; i<n; ++i ) odat[i] = DIVMN(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = idat[i] / cval;
break;
case '^':
- if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = POW(idat[i], cval);
+ if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = POWMN(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = pow(idat[i], cval);
break;
- case '<':
+ case LT:
if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MVCOMPLT(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = COMPLT(idat[i], cval);
break;
- case '>':
+ case GT:
if ( nmiss ) for ( i=0; i<n; ++i ) odat[i] = MVCOMPGT(idat[i], cval);
else for ( i=0; i<n; ++i ) odat[i] = COMPGT(idat[i], cval);
break;
@@ -241,33 +358,33 @@ void oper_expr_var_con(int oper, int nmiss, long n, double missval1, double miss
else for ( i=0; i<n; ++i ) odat[i] = COMPOR(idat[i], cval);
break;
default:
- cdoAbort("%s: operator %c unsupported!", __func__, oper);
+ cdoAbort("%s: operator '%c' unsupported!", __func__, oper);
break;
}
}
static
-void oper_expr_var_var(int oper, int nmiss, long ngp, double missval1, double missval2,
+void oper_expr_var_var(int oper, bool nmiss, size_t ngp, double missval1, double missval2,
double *restrict odat, const double *restrict idat1, const double *restrict idat2)
{
- long i;
+ size_t i;
switch ( oper )
{
case '+':
- if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = ADD(idat1[i], idat2[i]);
+ if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = ADDMN(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = idat1[i] + idat2[i];
break;
case '-':
- if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = SUB(idat1[i], idat2[i]);
+ if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = SUBMN(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = idat1[i] - idat2[i];
break;
case '*':
- if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = MUL(idat1[i], idat2[i]);
+ if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = MULMN(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = idat1[i] * idat2[i];
break;
case '/':
- if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = DIV(idat1[i], idat2[i]);
+ if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = DIVMN(idat1[i], idat2[i]);
else
{
for ( i = 0; i < ngp; ++i )
@@ -278,14 +395,14 @@ void oper_expr_var_var(int oper, int nmiss, long ngp, double missval1, double mi
}
break;
case '^':
- if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = POW(idat1[i], idat2[i]);
+ if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = POWMN(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = pow(idat1[i], idat2[i]);
break;
- case '<':
+ case LT:
if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = MVCOMPLT(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = COMPLT(idat1[i], idat2[i]);
break;
- case '>':
+ case GT:
if ( nmiss ) for ( i=0; i<ngp; ++i ) odat[i] = MVCOMPGT(idat1[i], idat2[i]);
else for ( i=0; i<ngp; ++i ) odat[i] = COMPGT(idat1[i], idat2[i]);
break;
@@ -318,443 +435,728 @@ void oper_expr_var_var(int oper, int nmiss, long ngp, double missval1, double mi
else for ( i=0; i<ngp; ++i ) odat[i] = COMPOR(idat1[i], idat2[i]);
break;
default:
- cdoAbort("%s: operator %d (%c) unsupported!", __func__, (int)oper, oper);
+ cdoAbort("%s: operator %d (%c) unsupported!", __func__, oper, oper);
break;
}
}
static
-nodeType *expr_con_var(int oper, nodeType *p1, nodeType *p2)
+nodeType *expr_con_var(int init, int oper, nodeType *p1, nodeType *p2)
{
- int gridID = p2->gridID;
- int zaxisID = p2->zaxisID;
- int nmiss = p2->nmiss;
- double missval1 = p2->missval;
- double missval2 = p2->missval;
+ size_t ngp = p2->param.ngp;
+ size_t nlev = p2->param.nlev;
+ size_t nmiss = p2->param.nmiss;
+ double missval1 = p2->param.missval;
+ double missval2 = p2->param.missval;
- int ngp = gridInqSize(gridID);
- int nlev = zaxisInqSize(zaxisID);
- long n = ngp*nlev;
- long i;
+ size_t n = ngp*nlev;
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
- p->gridID = gridID;
- p->zaxisID = zaxisID;
- p->missval = missval1;
-
- p->data = (double*) Malloc(n*sizeof(double));
- double *restrict odat = p->data;
- const double *restrict idat = p2->data;
- double cval = p1->u.con.value;
-
- oper_expr_con_var(oper, nmiss, n, missval1, missval2, odat, cval, idat);
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
+ param_meta_copy(&p->param, &p2->param);
+ p->param.name = p->u.var.nm;
- nmiss = 0;
- for ( i = 0; i < n; i++ )
- if ( DBL_IS_EQUAL(p->data[i], missval1) ) nmiss++;
+ if ( ! init )
+ {
+ p->param.data = (double*) Malloc(n*sizeof(double));
+ double *restrict odat = p->param.data;
+ const double *restrict idat = p2->param.data;
+ double cval = p1->u.con.value;
- p->nmiss = nmiss;
+ oper_expr_con_var(oper, nmiss>0, n, missval1, missval2, odat, cval, idat);
- if ( p2->tmpvar ) Free(p2->data);
+ nmiss = 0;
+ for ( size_t i = 0; i < n; i++ )
+ if ( DBL_IS_EQUAL(odat[i], missval1) ) nmiss++;
- return (p);
+ p->param.nmiss = nmiss;
+ }
+
+ return p;
}
static
-nodeType *expr_var_con(int oper, nodeType *p1, nodeType *p2)
+nodeType *expr_var_con(int init, int oper, nodeType *p1, nodeType *p2)
{
- int gridID = p1->gridID;
- int zaxisID = p1->zaxisID;
- int nmiss = p1->nmiss;
- double missval1 = p1->missval;
- double missval2 = p1->missval;
+ size_t ngp = p1->param.ngp;
+ size_t nlev = p1->param.nlev;
+ size_t nmiss = p1->param.nmiss;
+ double missval1 = p1->param.missval;
+ double missval2 = p1->param.missval;
- int ngp = gridInqSize(gridID);
- int nlev = zaxisInqSize(zaxisID);
- long n = ngp*nlev;
- long i;
+ size_t n = ngp*nlev;
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
- p->gridID = gridID;
- p->zaxisID = zaxisID;
- p->missval = missval1;
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
+ param_meta_copy(&p->param, &p1->param);
+ p->param.name = p->u.var.nm;
- p->data = (double*) Malloc(n*sizeof(double));
- double *restrict odat = p->data;
- const double *restrict idat = p1->data;
- double cval = p2->u.con.value;
-
- oper_expr_var_con(oper, nmiss, n, missval1, missval2, odat, idat, cval);
-
- nmiss = 0;
- for ( i = 0; i < n; i++ )
- if ( DBL_IS_EQUAL(p->data[i], missval1) ) nmiss++;
+ if ( ! init )
+ {
+ p->param.data = (double*) Malloc(n*sizeof(double));
+ double *restrict odat = p->param.data;
+ const double *restrict idat = p1->param.data;
+ double cval = p2->u.con.value;
- p->nmiss = nmiss;
+ oper_expr_var_con(oper, nmiss>0, n, missval1, missval2, odat, idat, cval);
- if ( p1->tmpvar ) Free(p1->data);
+ nmiss = 0;
+ for ( size_t i = 0; i < n; i++ )
+ if ( DBL_IS_EQUAL(odat[i], missval1) ) nmiss++;
- return (p);
+ p->param.nmiss = nmiss;
+ }
+
+ return p;
}
static
-nodeType *expr_var_var(int oper, nodeType *p1, nodeType *p2)
+nodeType *expr_var_var(int init, int oper, nodeType *p1, nodeType *p2)
{
- long i;
- long nlev, k;
- long loff, loff1, loff2;
- int nmiss;
+ nodeType *px = p1;
+ size_t nmiss1 = p1->param.nmiss;
+ size_t nmiss2 = p2->param.nmiss;
+ double missval1 = p1->param.missval;
+ double missval2 = p2->param.missval;
- int nmiss1 = p1->nmiss;
- int nmiss2 = p2->nmiss;
- double missval1 = p1->missval;
- double missval2 = p2->missval;
+ size_t ngp1 = p1->param.ngp;
+ size_t ngp2 = p2->param.ngp;
- long ngp1 = gridInqSize(p1->gridID);
- long ngp2 = gridInqSize(p2->gridID);
+ size_t ngp = ngp1;
- if ( ngp1 != ngp2 && ngp2 != 1 ) cdoAbort("Number of grid points differ. ngp1 = %ld, ngp2 = %ld", ngp1, ngp2);
+ if ( ngp1 != ngp2 )
+ {
+ if ( ngp1 == 1 || ngp2 == 1 )
+ {
+ if ( ngp1 == 1 ) { ngp = ngp2; px = p2; }
+ }
+ else
+ {
+ cdoAbort("%s: Number of grid points differ (%s[%ld] <-> %s[%ld])",
+ __func__, p1->param.name, ngp1, p2->param.name, ngp2);
+ }
+ }
- long ngp = ngp1;
+ size_t nlev1 = p1->param.nlev;
+ size_t nlev2 = p2->param.nlev;
- long nlev1 = zaxisInqSize(p1->zaxisID);
- long nlev2 = zaxisInqSize(p2->zaxisID);
+ size_t nlev = nlev1;
+ if ( nlev1 != nlev2 )
+ {
+ if ( nlev1 == 1 || nlev2 == 1 )
+ {
+ if ( nlev1 == 1 ) { nlev = nlev2; px = p2; }
+ }
+ else
+ {
+ cdoAbort("%s: Number of levels differ (%s[%ld] <-> %s[%ld])",
+ __func__, p1->param.name, nlev1, p2->param.name, nlev2);
+ }
+ }
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
- if ( nlev1 > nlev2 )
- {
- nlev = nlev1;
- p->gridID = p1->gridID;
- p->zaxisID = p1->zaxisID;
- p->missval = p1->missval;
- if ( nlev2 != 1 ) cdoAbort("nlev2 = %d must be 1!", nlev2);
- }
- else if ( nlev2 > nlev1 )
- {
- nlev = nlev2;
- p->gridID = p2->gridID;
- p->zaxisID = p2->zaxisID;
- p->missval = p2->missval;
- if ( nlev1 != 1 ) cdoAbort("nlev1 = %d must be 1!", nlev1);
- }
- else
+ param_meta_copy(&p->param, &px->param);
+
+ int steptype1 = p1->param.steptype;
+ int steptype2 = p2->param.steptype;
+
+ if ( p->param.steptype == TSTEP_CONSTANT )
{
- nlev = nlev1;
- p->gridID = p1->gridID;
- p->zaxisID = p1->zaxisID;
- p->missval = p1->missval;
+ if ( steptype1 != TSTEP_CONSTANT )
+ p->param.steptype = steptype1;
+ else if ( steptype2 != TSTEP_CONSTANT )
+ p->param.steptype = steptype2;
}
- p->data = (double*) Malloc(ngp*nlev*sizeof(double));
+ p->param.name = p->u.var.nm;
+ //printf("%s %s nmiss %ld %ld\n", p->u.var.nm, px->param.name, nmiss1, nmiss2);
- for ( k = 0; k < nlev; k++ )
+ if ( ! init )
{
- loff = k*ngp;
+ p->param.data = (double*) Malloc(ngp*nlev*sizeof(double));
- if ( nlev1 == 1 ) loff1 = 0;
- else loff1 = k*ngp1;
+ for ( size_t k = 0; k < nlev; k++ )
+ {
+ size_t loff1 = 0, loff2 = 0;
+ size_t loff = k*ngp;
- if ( nlev2 == 1 ) loff2 = 0;
- else loff2 = k*ngp2;
+ if ( nlev1 > 1 ) loff1 = k*ngp1;
+ if ( nlev2 > 1 ) loff2 = k*ngp2;
- const double *restrict idat1 = p1->data+loff1;
- const double *restrict idat2 = p2->data+loff2;
- double *restrict odat = p->data+loff;
- int nmiss = nmiss1 > 0 || nmiss2 > 0;
+ const double *restrict idat1 = p1->param.data+loff1;
+ const double *restrict idat2 = p2->param.data+loff2;
+ double *restrict odat = p->param.data+loff;
+ int nmiss = nmiss1 > 0 || nmiss2 > 0;
- if ( ngp2 == 1 )
- oper_expr_var_con(oper, nmiss, ngp, missval1, missval2, odat, idat1, idat2[0]);
- else
- oper_expr_var_var(oper, nmiss, ngp, missval1, missval2, odat, idat1, idat2);
+ if ( ngp1 != ngp2 )
+ {
+ if ( ngp2 == 1 )
+ oper_expr_var_con(oper, nmiss, ngp, missval1, missval2, odat, idat1, idat2[0]);
+ else
+ oper_expr_con_var(oper, nmiss, ngp, missval1, missval2, odat, idat1[0], idat2);
+ }
+ else
+ {
+ oper_expr_var_var(oper, nmiss, ngp, missval1, missval2, odat, idat1, idat2);
+ }
+ }
+
+ size_t nmiss = 0;
+ for ( size_t i = 0; i < ngp*nlev; i++ )
+ if ( DBL_IS_EQUAL(p->param.data[i], missval1) ) nmiss++;
+
+ p->param.nmiss = nmiss;
}
+
+ return p;
+}
+
+static
+void ex_copy_var(int init, nodeType *p2, nodeType *p1)
+{
+ if ( cdoVerbose ) cdoPrint("\t%s\tcopy\t%s[L%lu][N%lu] = %s[L%lu][N%lu]",
+ ExIn[init], p2->param.name, p2->param.nlev, p2->param.ngp, p1->param.name, p2->param.nlev, p2->param.ngp);
+
+ size_t ngp = p1->param.ngp;
+ assert(ngp > 0);
- nmiss = 0;
- for ( i = 0; i < ngp*nlev; i++ )
- if ( DBL_IS_EQUAL(p->data[i], missval1) ) nmiss++;
+ if ( ngp != p2->param.ngp )
+ cdoAbort("%s: Number of grid points differ (%s[%d] = %s[%d])",
+ __func__, p2->param.name, p2->param.ngp, p1->param.name, ngp);
- p->nmiss = nmiss;
+ size_t nlev = p1->param.nlev;
+ assert(nlev > 0);
- if ( p1->tmpvar ) Free(p1->data);
- if ( p2->tmpvar ) Free(p2->data);
+ if ( nlev != p2->param.nlev )
+ cdoAbort("%s: Number of levels differ (%s[%d] = %s[%d])",
+ __func__, p2->param.name, p2->param.nlev, p1->param.name, nlev);
- return (p);
+ if ( ! init )
+ {
+ double *restrict odat = p2->param.data;
+ const double *restrict idat = p1->param.data;
+ for ( size_t i = 0; i < ngp*nlev; ++i ) odat[i] = idat[i];
+
+ p2->param.missval = p1->param.missval;
+ p2->param.nmiss = p1->param.nmiss;
+ }
}
static
-void ex_copy(nodeType *p2, nodeType *p1)
+void ex_copy_con(int init, nodeType *p2, nodeType *p1)
{
- long i;
+ double cval = p1->u.con.value;
- if ( cdoVerbose ) printf("\tcopy %s\n", p1->u.var.nm);
+ if ( cdoVerbose ) cdoPrint("\t%s\tcopy\t%s[L%lu][N%lu] = %g", ExIn[init], p2->param.name, p2->param.nlev, p2->param.ngp, cval);
+
+ size_t ngp = p2->param.ngp;
+ assert(ngp > 0);
- long ngp1 = gridInqSize(p1->gridID);
- long ngp2 = gridInqSize(p2->gridID);
+ size_t nlev = p2->param.nlev;
+ assert(nlev > 0);
- if ( ngp1 != ngp2 )
- cdoAbort("Number of grid points differ. ngp1 = %d, ngp2 = %d", ngp1, ngp2);
-
- long ngp = ngp2;
- long nlev = zaxisInqSize(p2->zaxisID);
+ if ( ! init )
+ {
+ double *restrict odat = p2->param.data;
+ assert(odat != NULL);
- for ( i = 0; i < ngp*nlev; i++ ) p2->data[i] = p1->data[i];
+ for ( size_t i = 0; i < ngp*nlev; ++i ) odat[i] = cval;
+ }
+}
- p2->missval = p1->missval;
- p2->nmiss = p1->nmiss;
+static
+void ex_copy(int init, nodeType *p2, nodeType *p1)
+{
+ if ( p1->type == typeCon )
+ ex_copy_con(init, p2, p1);
+ else
+ ex_copy_var(init, p2, p1);
}
static
-nodeType *expr(int oper, nodeType *p1, nodeType *p2)
+nodeType *expr(int init, int oper, nodeType *p1, nodeType *p2)
{
- nodeType *p = NULL;
+ if ( p1 == NULL || p2 == NULL ) return NULL;
+
+ const char *coper = "???";
- if ( p1->type == typeVar && p2->type == typeVar )
+ if ( cdoVerbose )
{
- p = expr_var_var(oper, p1, p2);
- if ( cdoVerbose )
- printf("\t%s %c %s\n", p1->u.var.nm, oper, p2->u.var.nm);
+ switch ( oper )
+ {
+ case '+': coper = "+"; break;
+ case '-': coper = "-"; break;
+ case '*': coper = "*"; break;
+ case '/': coper = "/"; break;
+ case '^': coper = "^"; break;
+ case LT: coper = ">"; break;
+ case GT: coper = "<"; break;
+ case LE: coper = "<="; break;
+ case GE: coper = ">="; break;
+ case NE: coper = "!="; break;
+ case EQ: coper = "=="; break;
+ case LEG: coper = "<=>"; break;
+ case AND: coper = "&&"; break;
+ case OR: coper = "||"; break;
+ }
}
- else if ( p1->type == typeCon && p2->type == typeCon )
+
+ nodeType *p = NULL;
+
+ if ( p1->type == typeVar && p2->type == typeVar )
{
- p = expr_con_con(oper, p1, p2);
+ p = expr_var_var(init, oper, p1, p2);
if ( cdoVerbose )
- printf("\t%g %c %g\n", p1->u.con.value, oper, p2->u.con.value);
+ cdoPrint("\t%s\tarith\t%s[L%lu][N%lu] = %s %s %s", ExIn[init], p->u.var.nm, p->param.nlev, p->param.ngp, p1->u.var.nm, coper, p2->u.var.nm);
}
else if ( p1->type == typeVar && p2->type == typeCon )
{
- p = expr_var_con(oper, p1, p2);
+ p = expr_var_con(init, oper, p1, p2);
if ( cdoVerbose )
- printf("\t%s %c %g\n", p1->u.var.nm, oper, p2->u.con.value);
+ cdoPrint("\t%s\tarith\t%s[L%lu][N%lu] = %s %s %g", ExIn[init], p->u.var.nm, p->param.nlev, p->param.ngp, p1->u.var.nm, coper, p2->u.con.value);
}
else if ( p1->type == typeCon && p2->type == typeVar )
{
- p = expr_con_var(oper, p1, p2);
+ p = expr_con_var(init, oper, p1, p2);
if ( cdoVerbose )
- printf("\t%g %c %s\n", p1->u.con.value, oper, p2->u.var.nm);
+ cdoPrint("\t%s\tarith\t%s[L%lu][N%lu] = %g %s %s", ExIn[init], p->u.var.nm, p->param.nlev, p->param.ngp, p1->u.con.value, coper, p2->u.var.nm);
+ }
+ else if ( p1->type == typeCon && p2->type == typeCon )
+ {
+ p = expr_con_con(oper, p1, p2);
+ if ( cdoVerbose )
+ cdoPrint("\t%s\tarith\t%g = %g %s %g", ExIn[init], p->u.con.value, p1->u.con.value, coper, p2->u.con.value);
}
else
cdoAbort("Internal problem!");
- return (p);
+ if ( p1->ltmpobj ) node_delete(p1);
+ if ( p2->ltmpobj ) node_delete(p2);
+
+ return p;
}
static
-nodeType *ex_fun_con(char *fun, nodeType *p1)
+nodeType *ex_fun_con(int funcID, nodeType *p1)
{
- int i;
- int funcID = -1;
+ int functype = fun_sym_tbl[funcID].type;
+ if ( functype != FT_STD ) cdoAbort("Function %s not available for constant values!", fun_sym_tbl[funcID].name);
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
- p->type = typeCon;
+ p->type = typeCon;
+ p->ltmpobj = true;
- for ( i = 0; i < NumFunc; i++)
- if ( fun_sym_tbl[i].type == 0 )
- if ( strcmp(fun, fun_sym_tbl[i].name) == 0 )
- {
- funcID = i;
- break;
- }
-
- if ( funcID == -1 )
- cdoAbort("Function >%s< not available!", fun);
+ double (*exprfunc)(double) = (double (*)(double)) fun_sym_tbl[funcID].func;
+ p->u.con.value = exprfunc(p1->u.con.value);
- p->u.con.value = fun_sym_tbl[funcID].func(p1->u.con.value);
+ if ( p1->ltmpobj ) node_delete(p1);
+ else Free(p1);
- return (p);
+ return p;
}
static
-nodeType *ex_fun_var(char *fun, nodeType *p1)
+nodeType *ex_fun_var(int init, int funcID, nodeType *p1)
{
- long i;
- int funcID = -1;
- int gridID = p1->gridID;
- int zaxisID = p1->zaxisID;
- int nmiss = p1->nmiss;
- double missval = p1->missval;
+ const char *funcname = fun_sym_tbl[funcID].name;
+ int functype = fun_sym_tbl[funcID].type;
+ int funcflag = fun_sym_tbl[funcID].flag;
- long ngp = gridInqSize(gridID);
- long nlev = zaxisInqSize(zaxisID);
+ size_t ngp = p1->param.ngp;
+ size_t nlev = p1->param.nlev;
+ size_t nmiss = p1->param.nmiss;
+ double missval = p1->param.missval;
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
- p->gridID = gridID;
- p->zaxisID = zaxisID;
- p->missval = missval;
-
- p->data = (double*) Malloc(ngp*nlev*sizeof(double));
-
- for ( i = 0; i < NumFunc; i++)
- if ( strcmp(fun, fun_sym_tbl[i].name) == 0 )
- {
- funcID = i;
- break;
- }
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
- if ( funcID == -1 )
- cdoAbort("Function >%s< not available!", fun);
+ param_meta_copy(&p->param, &p1->param);
- if ( nmiss > 0 )
+ if ( functype == FT_CONST )
{
- for ( i = 0; i < ngp*nlev; i++ )
- {
- errno = -1;
- p->data[i] = DBL_IS_EQUAL(p1->data[i], missval) ? missval : fun_sym_tbl[funcID].func(p1->data[i]);
- if ( errno == EDOM || errno == ERANGE ) p->data[i] = missval;
- else if ( isnan(p->data[i]) ) p->data[i] = missval;
- }
+ p->type = typeCon;
+ double (*exprfunc)(paramType*) = (double (*)(paramType*)) fun_sym_tbl[funcID].func;
+ p->u.con.value = exprfunc(&p1->param);
}
- else
+ else if ( functype == FT_FLD )
{
- for ( i = 0; i < ngp*nlev; i++ )
- {
- errno = -1;
- p->data[i] = fun_sym_tbl[funcID].func(p1->data[i]);
- if ( errno == EDOM || errno == ERANGE ) p->data[i] = missval;
- else if ( isnan(p->data[i]) ) p->data[i] = missval;
- }
+ p->param.gridID = pointID;
+ p->param.ngp = 1;
+ }
+ else if ( functype == FT_VERT )
+ {
+ p->param.zaxisID = surfaceID;
+ p->param.nlev = 1;
}
- nmiss = 0;
- for ( i = 0; i < ngp*nlev; i++ )
- if ( DBL_IS_EQUAL(p->data[i], missval) ) nmiss++;
+ if ( ! init )
+ {
+ p->param.data = (double*) Malloc(p->param.ngp*p->param.nlev*sizeof(double));
+ double *restrict pdata = p->param.data;
+ double *restrict p1data = p1->param.data;
+
+ if ( functype == FT_STD )
+ {
+ double (*exprfunc)(double) = (double (*)(double)) fun_sym_tbl[funcID].func;
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < ngp*nlev; i++ )
+ {
+ errno = -1;
+ pdata[i] = DBL_IS_EQUAL(p1data[i], missval) ? missval : exprfunc(p1data[i]);
+ if ( errno == EDOM || errno == ERANGE ) pdata[i] = missval;
+ else if ( isnan(pdata[i]) ) pdata[i] = missval;
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < ngp*nlev; i++ )
+ {
+ errno = -1;
+ pdata[i] = exprfunc(p1data[i]);
+ if ( errno == EDOM || errno == ERANGE ) pdata[i] = missval;
+ else if ( isnan(pdata[i]) ) pdata[i] = missval;
+ }
+ }
+ }
+ else if ( functype == FT_FLD )
+ {
+ field_t field;
+ double *weights = NULL;
+ //if ( funcflag == 1 ) weights = fld_weights(p1->param.gridID, ngp);
+ if ( funcflag == 1 )
+ {
+ weights = p1->param.weight;
+ assert(weights!=NULL);
+ }
+
+ double (*exprfunc)(field_t) = (double (*)(field_t)) fun_sym_tbl[funcID].func;
+ for ( size_t k = 0; k < nlev; k++ )
+ {
+ fld_field_init(&field, nmiss, missval, ngp, p1data+k*ngp, weights);
+ pdata[k] = exprfunc(field);
+ }
+ //if ( weights ) Free(weights);
+ }
+ else if ( functype == FT_VERT )
+ {
+ field_t field;
+ double *weights = NULL;
+ if ( funcflag == 1 ) weights = vert_weights(p1->param.zaxisID, nlev);
+ double *array = (double*) Malloc(nlev*sizeof(double));
+ double (*exprfunc)(field_t) = (double (*)(field_t)) fun_sym_tbl[funcID].func;
+ for ( size_t i = 0; i < ngp; i++ )
+ {
+ for ( size_t k = 0; k < nlev; k++ ) array[k] = p1data[k*ngp+i];
+ fld_field_init(&field, nmiss, missval, nlev, array, weights);
+ pdata[i] = exprfunc(field);
+ }
+ if ( array ) Free(array);
+ if ( weights ) Free(weights);
+ }
+ else if ( functype == FT_CONST )
+ {
+ }
+ else
+ cdoAbort("Intermal error, wrong function type (%d) for %s()!", functype, funcname);
- p->nmiss = nmiss;
+ nmiss = 0;
+ for ( size_t i = 0; i < p->param.ngp*p->param.nlev; i++ )
+ if ( DBL_IS_EQUAL(pdata[i], missval) ) nmiss++;
- if ( p1->tmpvar ) Free(p1->data);
+ p->param.nmiss = nmiss;
+ }
- return (p);
+ if ( p1->ltmpobj ) node_delete(p1);
+ else Free(p1);
+
+ return p;
}
static
-nodeType *ex_fun(char *fun, nodeType *p1)
+nodeType *ex_fun(int init, int funcID, nodeType *p1)
{
nodeType *p = NULL;
if ( p1->type == typeVar )
{
- p = ex_fun_var(fun, p1);
- if ( cdoVerbose ) printf("\t%s (%s)\n", fun, p1->u.var.nm);
+ if ( cdoVerbose ) cdoPrint("\t%s\tfunc\t%s (%s)", ExIn[init], fun_sym_tbl[funcID].name, p1->u.var.nm);
+ p = ex_fun_var(init, funcID, p1);
}
else if ( p1->type == typeCon )
{
- p = ex_fun_con(fun, p1);
- if ( cdoVerbose ) printf("\t%s (%g)\n", fun, p1->u.con.value);
+ if ( cdoVerbose ) cdoPrint("\t%s\tfunc\t%s (%g)", ExIn[init], fun_sym_tbl[funcID].name, p1->u.con.value);
+ p = ex_fun_con(funcID, p1);
}
else
cdoAbort("Internal problem!");
- return (p);
+ return p;
}
static
-nodeType *ex_uminus_var(nodeType *p1)
+size_t get_levidx(size_t nlev, const double *data, double value, const char *funcname)
{
- int gridID = p1->gridID;
- int zaxisID = p1->zaxisID;
- int nmiss = p1->nmiss;
- double missval = p1->missval;
+ size_t levidx;
+
+ for ( levidx = 0; levidx < nlev; ++levidx )
+ if ( IS_EQUAL(data[levidx], value) )
+ break;
+ if ( levidx == nlev ) cdoAbort("%s(): level %g not found!", funcname, value);
+
+ return levidx;
+}
+
+static
+nodeType *fun1c(int init, int funcID, nodeType *p1, double value, parse_param_t *parse_arg)
+{
+ const char *funcname = fun_sym_tbl[funcID].name;
+ if ( p1->type != typeVar ) cdoAbort("Parameter of function %s() needs to be a variable!", funcname);
+ if ( p1->ltmpobj ) cdoAbort("Temorary objects not allowed in function %s()!", funcname);
- long ngp = gridInqSize(gridID);
- long nlev = zaxisInqSize(zaxisID);
+ size_t ngp = p1->param.ngp;
+ size_t nlev = p1->param.nlev;
+ size_t nmiss = p1->param.nmiss;
+ double missval = p1->param.missval;
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
- p->gridID = gridID;
- p->zaxisID = zaxisID;
- p->missval = missval;
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
+ param_meta_copy(&p->param, &p1->param);
+ p->param.name = p->u.var.nm;
- p->data = (double*) Malloc(ngp*nlev*sizeof(double));
+ p->param.nlev = 1;
- if ( nmiss > 0 )
+ int zaxisID = p1->param.zaxisID;
+ int coordID = params_get_coordID(parse_arg, 'z', zaxisID);
+ size_t levidx = 0;
+
+ double *data = NULL;
+ if ( init )
{
- for ( long i = 0; i < ngp*nlev; i++ )
- p->data[i] = DBL_IS_EQUAL(p1->data[i], missval) ? missval : -(p1->data[i]);
+ parse_arg->coords[coordID].needed = true;
+
+ data = (double*) malloc(nlev*sizeof(double));
+ zaxisInqLevels(zaxisID, data);
}
else
{
- for ( long i = 0; i < ngp*nlev; i++ )
- p->data[i] = -(p1->data[i]);
+ data = parse_arg->coords[coordID].data;
+ }
+
+ if ( strcmp(funcname, "sellevidx") == 0 )
+ {
+ long ilevidx = lround(value);
+ if ( ilevidx < 1 || ilevidx > (long)nlev )
+ cdoAbort("%s(): level index %ld out of range (range: 1-%lu)!", funcname, ilevidx, nlev);
+ levidx = (size_t) ilevidx - 1;
+ }
+ else if ( strcmp(funcname, "sellevel") == 0 )
+ {
+ levidx = get_levidx(nlev, data, value, funcname);
+ }
+ else
+ cdoAbort("Function %s() not implemented!", funcname);
+
+ if ( init )
+ {
+ double level = data[levidx];
+ int zaxisID2 = zaxisCreate(zaxisInqType(zaxisID), 1);
+ zaxisDefLevels(zaxisID2, &level);
+ p->param.zaxisID = zaxisID2;
+ }
+
+ if ( init ) Free(data);
+
+ if ( ! init )
+ {
+ p->param.data = (double*) Malloc(ngp*sizeof(double));
+ double *restrict pdata = p->param.data;
+ const double *restrict p1data = p1->param.data+ngp*levidx;
+
+ for ( size_t i = 0; i < ngp; i++ ) pdata[i] = p1data[i];
+
+ if ( nmiss > 0 )
+ {
+ nmiss = 0;
+ for ( size_t i = 0; i < ngp; i++ )
+ if ( DBL_IS_EQUAL(pdata[i], missval) ) nmiss++;
+ }
+
+ p->param.nmiss = nmiss;
+ }
+
+ if ( p1->ltmpobj ) node_delete(p1);
+
+ return p;
+}
+
+static
+nodeType *coord_fun(int init, int funcID, nodeType *p1, parse_param_t *parse_arg)
+{
+ const char *funcname = fun_sym_tbl[funcID].name;
+ if ( p1->type != typeVar ) cdoAbort("Parameter of function %s() needs to be a variable!", funcname);
+ if ( p1->ltmpobj ) cdoAbort("Temorary objects not allowed in function %s()!", funcname);
+
+ size_t len = 3 + strlen(p1->u.var.nm);
+ char *cname = (char*) Calloc(len, 1);
+ strcpy(cname, p1->u.var.nm);
+
+ if ( strcmp(funcname, "clon") == 0 ) strcat(cname, ".x");
+ else if ( strcmp(funcname, "clat") == 0 ) strcat(cname, ".y");
+ else if ( strcmp(funcname, "clev") == 0 ) strcat(cname, ".z");
+ else if ( strcmp(funcname, "gridarea") == 0 ) strcat(cname, ".a");
+ else if ( strcmp(funcname, "gridweight") == 0 ) strcat(cname, ".w");
+ else cdoAbort("Implementation missing for function %s!", funcname);
+
+ Free(p1->u.var.nm);
+ p1->u.var.nm = cname;
+
+ nodeType *p = expr_run(p1, parse_arg);
+ p->param.lmiss = false;
+
+ if ( ! init )
+ {
+ /*
+ size_t ngp = p1->param.ngp;
+ size_t nlev = p1->param.nlev;
+ p->param.data = (double*) Malloc(ngp*nlev*sizeof(double));
+ double *restrict pdata = p->param.data;
+ double *restrict p1data = p1->param.data;
+
+ for ( size_t i = 0; i < ngp*nlev; i++ ) pdata[i] = p1data[i];
+ */
}
+ /*
+ Free(cname);
+ Free(p1);
+ */
+ return p;
+}
+
+static
+nodeType *ex_uminus_var(int init, nodeType *p1)
+{
+ size_t ngp = p1->param.ngp;
+ size_t nlev = p1->param.nlev;
+ size_t nmiss = p1->param.nmiss;
+ double missval = p1->param.missval;
+
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
+
+ p->type = typeVar;
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
+ param_meta_copy(&p->param, &p1->param);
+ p->param.name = p->u.var.nm;
+
+ if ( ! init )
+ {
+ p->param.data = (double*) Malloc(ngp*nlev*sizeof(double));
+ double *restrict pdata = p->param.data;
+ const double *restrict p1data = p1->param.data;
- p->nmiss = nmiss;
+ if ( nmiss > 0 )
+ {
+ for ( size_t i = 0; i < ngp*nlev; i++ )
+ pdata[i] = DBL_IS_EQUAL(p1data[i], missval) ? missval : -(p1data[i]);
+ }
+ else
+ {
+ for ( size_t i = 0; i < ngp*nlev; i++ )
+ pdata[i] = -(p1data[i]);
+ }
+
+ p->param.nmiss = nmiss;
+ }
+
+ if ( p1->ltmpobj ) node_delete(p1);
- return (p);
+ return p;
}
static
nodeType *ex_uminus_con(nodeType *p1)
{
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
- p->type = typeCon;
+ p->type = typeCon;
+ p->ltmpobj = true;
p->u.con.value = -(p1->u.con.value);
- return (p);
+ return p;
}
static
-nodeType *ex_uminus(nodeType *p1)
+nodeType *ex_uminus(int init, nodeType *p1)
{
nodeType *p = NULL;
if ( p1->type == typeVar )
{
- p = ex_uminus_var(p1);
- if ( cdoVerbose ) printf("\t- (%s)\n", p1->u.var.nm);
+ if ( cdoVerbose ) cdoPrint("\t%s\tneg\t- (%s)", ExIn[init], p1->u.var.nm);
+ p = ex_uminus_var(init, p1);
}
else if ( p1->type == typeCon )
{
+ if ( cdoVerbose ) cdoPrint("\t%s\tneg\t- (%g)", ExIn[init], p1->u.con.value);
p = ex_uminus_con(p1);
- if ( cdoVerbose ) printf("\t- (%g)\n", p1->u.con.value);
}
else
cdoAbort("Internal problem!");
- return (p);
+ return p;
}
static
-nodeType *ex_ifelse(nodeType *p1, nodeType *p2, nodeType *p3)
+nodeType *ex_ifelse(int init, nodeType *p1, nodeType *p2, nodeType *p3)
{
- if ( cdoVerbose ) printf("\t %s ? %s : %s\n", p1->u.var.nm, p2->u.var.nm, p3->u.var.nm);
-
if ( p1->type == typeCon ) cdoAbort("expr?expr:expr: First expression is a constant but must be a variable!");
- int nmiss1 = p1->nmiss;
- long ngp1 = gridInqSize(p1->gridID);
- long nlev1 = zaxisInqSize(p1->zaxisID);
- double missval1 = p1->missval;
- double *pdata1 = p1->data;
+ if ( cdoVerbose )
+ {
+ fprintf(stderr, "cdo expr:\t%s\tifelse\t%s[L%lu][N%lu] ? ", ExIn[init], p1->u.var.nm, p1->param.nlev, p1->param.ngp);
+ if ( p2->type == typeCon )
+ printf("%g : ", p2->u.con.value);
+ else
+ printf("%s[L%lu][N%lu] : ", p2->u.var.nm, p2->param.nlev, p2->param.ngp);
+ if ( p3->type == typeCon )
+ printf("%g\n", p3->u.con.value);
+ else
+ printf("%s[L%lu][N%lu]\n", p3->u.var.nm, p3->param.nlev, p3->param.ngp);
+ }
+
+ size_t nmiss1 = p1->param.nmiss;
+ size_t ngp1 = p1->param.ngp;
+ size_t nlev1 = p1->param.nlev;
+ double missval1 = p1->param.missval;
- long ngp = ngp1;
- long nlev = nlev1;
+ size_t ngp = ngp1;
+ size_t nlev = nlev1;
nodeType *px = p1;
double missval2 = missval1;
- double *pdata2;
- long ngp2 = 1;
- long nlev2 = 1;
+ double *pdata2 = NULL;
+ size_t ngp2 = 1;
+ size_t nlev2 = 1;
if ( p2->type == typeCon )
{
@@ -762,12 +1164,12 @@ nodeType *ex_ifelse(nodeType *p1, nodeType *p2, nodeType *p3)
}
else
{
- ngp2 = gridInqSize(p2->gridID);
- nlev2 = zaxisInqSize(p2->zaxisID);
- missval2 = p2->missval;
- pdata2 = p2->data;
+ ngp2 = p2->param.ngp;
+ nlev2 = p2->param.nlev;
+ missval2 = p2->param.missval;
+ pdata2 = p2->param.data;
if ( ngp2 > 1 && ngp2 != ngp1 )
- cdoAbort("expr?expr:expr: Number of grid points differ. ngp1 = %ld, ngp2 = %ld", ngp1, ngp2);
+ cdoAbort("expr?expr:expr: Number of grid points differ (ngp1 = %ld, ngp2 = %ld)", ngp1, ngp2);
if ( nlev2 > 1 && nlev2 != nlev )
{
if ( nlev == 1 )
@@ -776,14 +1178,14 @@ nodeType *ex_ifelse(nodeType *p1, nodeType *p2, nodeType *p3)
px = p2;
}
else
- cdoAbort("expr?expr:expr: Number of levels differ. nlev = %ld, nlev2 = %ld", nlev, nlev2);
+ cdoAbort("expr?expr:expr: Number of levels differ (nlev = %ld, nlev2 = %ld)", nlev, nlev2);
}
}
double missval3 = missval1;
- double *pdata3;
- long ngp3 = 1;
- long nlev3 = 1;
+ double *pdata3 = NULL;
+ size_t ngp3 = 1;
+ size_t nlev3 = 1;
if ( p3->type == typeCon )
{
@@ -791,12 +1193,12 @@ nodeType *ex_ifelse(nodeType *p1, nodeType *p2, nodeType *p3)
}
else
{
- ngp3 = gridInqSize(p3->gridID);
- nlev3 = zaxisInqSize(p3->zaxisID);
- missval3 = p3->missval;
- pdata3 = p3->data;
+ ngp3 = p3->param.ngp;
+ nlev3 = p3->param.nlev;
+ missval3 = p3->param.missval;
+ pdata3 = p3->param.data;
if ( ngp3 > 1 && ngp3 != ngp1 )
- cdoAbort("expr?expr:expr: Number of grid points differ. ngp1 = %ld, ngp3 = %ld", ngp1, ngp3);
+ cdoAbort("expr?expr:expr: Number of grid points differ (ngp1 = %ld, ngp3 = %ld)", ngp1, ngp3);
if ( nlev3 > 1 && nlev3 != nlev )
{
if ( nlev == 1 )
@@ -805,73 +1207,86 @@ nodeType *ex_ifelse(nodeType *p1, nodeType *p2, nodeType *p3)
px = p3;
}
else
- cdoAbort("expr?expr:expr: Number of levels differ. nlev = %ld, nlev3 = %ld", nlev, nlev3);
+ cdoAbort("expr?expr:expr: Number of levels differ (nlev = %ld, nlev3 = %ld)", nlev, nlev3);
}
}
- nodeType *p = (nodeType*) Malloc(sizeof(nodeType));
+ nodeType *p = (nodeType*) Calloc(1, sizeof(nodeType));
p->type = typeVar;
- p->tmpvar = 1;
- p->u.var.nm = strdupx("tmp");
+ p->ltmpobj = true;
+ p->u.var.nm = strdup(tmpvnm);
- p->gridID = px->gridID;
- p->zaxisID = px->zaxisID;
- p->missval = px->missval;
+ param_meta_copy(&p->param, &px->param);
+ p->param.name = p->u.var.nm;
- p->data = (double*) Malloc(ngp*nlev*sizeof(double));
+ if ( ! init )
+ {
+ size_t nmiss = 0;
+ double *pdata1 = p1->param.data;
+
+ p->param.data = (double*) Malloc(ngp*nlev*sizeof(double));
- long loff, loff1, loff2, loff3;
+ for ( size_t k = 0; k < nlev; ++k )
+ {
+ size_t loff1, loff2, loff3;
+ size_t loff = k*ngp;
- for ( long k = 0; k < nlev; ++k )
- {
- loff = k*ngp;
+ if ( nlev1 == 1 ) loff1 = 0;
+ else loff1 = k*ngp;
- if ( nlev1 == 1 ) loff1 = 0;
- else loff1 = k*ngp;
+ if ( nlev2 == 1 ) loff2 = 0;
+ else loff2 = k*ngp;
- if ( nlev2 == 1 ) loff2 = 0;
- else loff2 = k*ngp;
+ if ( nlev3 == 1 ) loff3 = 0;
+ else loff3 = k*ngp;
- if ( nlev3 == 1 ) loff3 = 0;
- else loff3 = k*ngp;
+ const double *restrict idat1 = pdata1+loff1;
+ const double *restrict idat2 = pdata2+loff2;
+ const double *restrict idat3 = pdata3+loff3;
+ double *restrict odat = p->param.data+loff;
- const double *restrict idat1 = pdata1+loff1;
- const double *restrict idat2 = pdata2+loff2;
- const double *restrict idat3 = pdata3+loff3;
- double *restrict odat = p->data+loff;
+ double ival2 = idat2[0];
+ double ival3 = idat3[0];
+ for ( size_t i = 0; i < ngp; ++i )
+ {
+ if ( ngp2 > 1 ) ival2 = idat2[i];
+ if ( ngp3 > 1 ) ival3 = idat3[i];
+
+ if ( nmiss1 && DBL_IS_EQUAL(idat1[i], missval1) )
+ odat[i] = missval1;
+ else if ( IS_NOT_EQUAL(idat1[i], 0) )
+ odat[i] = DBL_IS_EQUAL(ival2, missval2) ? missval1 : ival2;
+ else
+ odat[i] = DBL_IS_EQUAL(ival3, missval3) ? missval1 : ival3;
+ }
- double ival2 = idat2[0];
- double ival3 = idat3[0];
- for ( long i = 0; i < ngp; ++i )
- {
- if ( ngp2 > 1 ) ival2 = idat2[i];
- if ( ngp3 > 1 ) ival3 = idat3[i];
+ for ( size_t i = 0; i < ngp; i++ )
+ if ( DBL_IS_EQUAL(odat[i], missval1) ) nmiss++;
+ }
- if ( nmiss1 && DBL_IS_EQUAL(idat1[i], missval1) )
- odat[i] = missval1;
- else if ( IS_NOT_EQUAL(idat1[i], 0) )
- odat[i] = DBL_IS_EQUAL(ival2, missval2) ? missval1 : ival2;
- else
- odat[i] = DBL_IS_EQUAL(ival3, missval3) ? missval1 : ival3;
- }
+ p->param.nmiss = nmiss;
}
- return (p);
-}
+ if ( p1->ltmpobj ) node_delete(p1);
+ if ( p2->ltmpobj ) node_delete(p2);
+ if ( p3->ltmpobj ) node_delete(p3);
-
-int exNode(nodeType *p, parse_parm_t *parse_arg)
+ return p;
+}
+/*
+static
+int exNode(nodeType *p, parse_param_t *parse_arg)
{
- if ( ! p ) return(0);
+ if ( ! p ) return 0;
- /* node is leaf */
+ // node is leaf
if ( p->type == typeCon || p->type == typeVar || p->u.opr.nops == 0 )
{
return 0;
}
- /* node has children */
+ // node has children
for ( int k = 0; k < p->u.opr.nops; k++ )
{
exNode(p->u.opr.op[k], parse_arg);
@@ -879,249 +1294,353 @@ int exNode(nodeType *p, parse_parm_t *parse_arg)
return 0;
}
+*/
-
-nodeType *expr_run(nodeType *p, parse_parm_t *parse_arg)
+static
+int param_search_name(int nparam, paramType *params, const char *name)
{
- int gridID1 = -1, zaxisID1 = -1, tsteptype1 = -1;
- double missval = 0;
- char varname[256];
- int varID, nvars;
- nodeType *rnode = NULL;
-
- if ( ! p ) return (rnode);
+ int varID = -1;
- /* if ( ! parse_arg->init ) { exNode(p, parse_arg); return 0; } */
-
- switch ( p->type )
+ for ( varID = nparam-1; varID >= 0; --varID )
{
- case typeCon:
- if ( parse_arg->init )
- {
- if ( parse_arg->debug )
- printf("\tpush const \t%g\n", p->u.con.value);
- }
- else
- {
- rnode = p;
- }
-
- break;
- case typeVar:
- /* if ( parse_arg->init ) */
- {
- if ( parse_arg->debug )
- printf("\tpush var \t%s\n", p->u.var.nm);
-
- nvars = vlistNvars(parse_arg->vlistID1);
- for ( varID = 0; varID < nvars; varID++ )
- {
- vlistInqVarName(parse_arg->vlistID1, varID, varname);
- if ( strcmp(varname, p->u.var.nm) == 0 ) break;
- }
-
- if ( varID == nvars )
- {
- cdoAbort("Variable >%s< not found!", p->u.var.nm);
- }
- else
- {
- int nlev1, nlev2 = 0;
- if ( varID >= MAX_VARS ) cdoAbort("Too many parameter (limit=%d)!", MAX_VARS);
-
- if ( parse_arg->var_needed[varID] == 0 )
- {
+ if ( strcmp(params[varID].name, name) == 0 ) break;
+ }
- parse_arg->var[varID] = strdupx(p->u.var.nm);
- parse_arg->varID[varID] = varID;
- parse_arg->var_needed[varID] = 1;
- }
+ return varID;
+}
- gridID1 = vlistInqVarGrid(parse_arg->vlistID1, varID);
- zaxisID1 = vlistInqVarZaxis(parse_arg->vlistID1, varID);
- tsteptype1 = vlistInqVarTsteptype(parse_arg->vlistID1, varID);
- missval = vlistInqVarMissval(parse_arg->vlistID1, varID);
- nlev1 = zaxisInqSize(zaxisID1);
- parse_arg->missval2 = missval;
+nodeType *expr_run(nodeType *p, parse_param_t *parse_arg)
+{
+ pointID = parse_arg->pointID;
+ surfaceID = parse_arg->surfaceID;
+ int init = parse_arg->init;
+ paramType *params = parse_arg->params;
+ int varID;
+ nodeType *rnode = NULL;
- if ( parse_arg->gridID2 == -1 )
- parse_arg->gridID2 = gridID1;
+ if ( ! p ) return rnode;
- if ( parse_arg->zaxisID2 != -1 ) nlev2 = zaxisInqSize(parse_arg->zaxisID2);
+ /* if ( ! init ) { exNode(p, parse_arg); return 0; } */
- if ( parse_arg->zaxisID2 == -1 || (nlev1 > 1 && nlev2 == 1) )
- parse_arg->zaxisID2 = zaxisID1;
+ switch ( p->type )
+ {
+ case typeCom:
+ {
+ const char *cname = p->u.com.cname;
+ const char *vname = p->u.com.vname;
+ if ( parse_arg->debug ) cdoPrint("\tstatement\t\t%s(%s)", cname, vname);
+
+ varID = param_search_name(parse_arg->nparams, params, vname);
+ if ( varID == -1 ) cdoAbort("Variable %s not found, needed for statement %s(%s)!", vname, cname, vname);
+
+ if ( init )
+ {
+ if ( strcmp(cname, "remove") == 0 )
+ {
+ params[varID].remove = true;
+ }
+ }
+ else
+ {
+ if ( strcmp(cname, "print") == 0 )
+ {
+ size_t maxout = 100;
+ int vartsID = parse_arg->tsID;
+ int steptype = params[varID].steptype;
+ size_t ngp = params[varID].ngp;
+ size_t nlev = params[varID].nlev;
+ const double *data = params[varID].data;
+ long tsID = lround(params[vartsID].data[0]);
+ for ( size_t k = 0; k < nlev; ++k )
+ for ( size_t i = 0; i < ngp; ++i )
+ {
+ if ( i < maxout || (ngp > maxout && i >= (ngp-maxout)) )
+ {
+ if ( steptype == TIME_CONSTANT )
+ fprintf(stdout, " %s[lev=%lu:gp=%lu] = %g\n", vname, k+1, i+1, data[k*ngp+i]);
+ else
+ fprintf(stdout, " %s[ts=%ld:lev=%lu:gp=%lu] = %g\n", vname, tsID, k+1, i+1, data[k*ngp+i]);
+ }
+ else if ( i == maxout )
+ {
+ fprintf(stdout, " .......\n");
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case typeCon:
+ {
+ if ( parse_arg->debug ) cdoPrint("\tpush\tconst\t%g", p->u.con.value);
- if ( parse_arg->tsteptype2 == -1 || parse_arg->tsteptype2 == TSTEP_CONSTANT )
- parse_arg->tsteptype2 = tsteptype1;
- }
- }
- /* else */
- {
- if ( parse_arg->debug )
- printf("var: %s %d %d %d\n", p->u.var.nm, varID, gridID1, zaxisID1);
- p->gridID = gridID1;
- p->zaxisID = zaxisID1;
- p->missval = missval;
- p->nmiss = 0;
- if ( ! parse_arg->init )
- {
- p->data = parse_arg->vardata1[varID];
- p->nmiss = parse_arg->nmiss[varID];
- }
- p->tmpvar = 0;
- rnode = p;
- }
+ rnode = p;
- break;
+ break;
+ }
+ case typeVar:
+ {
+ const char *vnm = p->u.var.nm;
+ varID = param_search_name(parse_arg->nparams, params, vnm);
+ if ( varID == -1 && init )
+ {
+ size_t len = strlen(vnm);
+ int coord = vnm[len-1];
+ if ( len > 2 && vnm[len-2] == '.' )
+ {
+ if ( coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w' )
+ {
+ char *varname = strdup(vnm);
+ varname[len-2] = 0;
+ varID = param_search_name(parse_arg->nparams, params, varname);
+ free(varname);
+ if ( varID == -1 )
+ {
+ cdoAbort("Coordinate %c: variable >%s< not found!", coord, varname);
+ }
+ else
+ {
+ int nvarID = parse_arg->nparams;
+ if ( nvarID >= parse_arg->maxparams )
+ cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams);
+
+ int coordID = params_get_coordID(parse_arg, coord, params[varID].gridID);
+ parse_arg->coords[coordID].needed = true;
+ const char *units = parse_arg->coords[coordID].units;
+ const char *longname = parse_arg->coords[coordID].longname;
+
+ params[nvarID].coord = coord;
+ params[nvarID].lmiss = false;
+ params[nvarID].name = strdup(vnm);
+ params[nvarID].missval = params[varID].missval;
+ params[nvarID].gridID = params[varID].gridID;
+ params[nvarID].zaxisID = parse_arg->surfaceID;
+ params[nvarID].steptype = TIME_CONSTANT;
+ params[nvarID].ngp = params[varID].ngp;
+ params[nvarID].nlev = 1;
+ if ( units ) params[nvarID].units = strdup(units);
+ if ( longname ) params[nvarID].longname = strdup(longname);
+ parse_arg->nparams++;
+ varID = nvarID;
+ }
+ }
+ else if ( coord == 'z' )
+ {
+ char *varname = strdup(vnm);
+ varname[len-2] = 0;
+ varID = param_search_name(parse_arg->nparams, params, varname);
+ free(varname);
+ if ( varID == -1 )
+ {
+ cdoAbort("Coordinate %c: variable >%s< not found!", coord, varname);
+ }
+ else
+ {
+ int nvarID = parse_arg->nparams;
+ if ( nvarID >= parse_arg->maxparams )
+ cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams);
+
+ int coordID = params_get_coordID(parse_arg, coord, params[varID].zaxisID);
+ parse_arg->coords[coordID].needed = true;
+ const char *units = parse_arg->coords[coordID].units;
+ const char *longname = parse_arg->coords[coordID].longname;
+
+ params[nvarID].coord = coord;
+ params[nvarID].lmiss = false;
+ params[nvarID].name = strdup(vnm);
+ params[nvarID].missval = params[varID].missval;
+ params[nvarID].gridID = parse_arg->pointID;
+ params[nvarID].zaxisID = params[varID].zaxisID;
+ params[nvarID].steptype = TIME_CONSTANT;
+ params[nvarID].ngp = 1;
+ params[nvarID].nlev = params[varID].nlev;
+ if ( units ) params[nvarID].units = strdup(units);
+ if ( longname ) params[nvarID].longname = strdup(longname);
+ parse_arg->nparams++;
+ varID = nvarID;
+ }
+ }
+ }
+ }
+ if ( varID == -1 )
+ {
+ cdoAbort("Variable >%s< not found!", p->u.var.nm);
+ }
+ else if ( init )
+ {
+ if ( varID < parse_arg->nvars1 && parse_arg->needed[varID] == false )
+ {
+ parse_arg->needed[varID] = true;
+ }
+ }
+
+
+ param_meta_copy(&p->param, ¶ms[varID]);
+ p->param.coord = params[varID].coord;
+ p->param.lmiss = params[varID].lmiss;
+ p->param.name = params[varID].name;
+ p->param.longname = params[varID].longname;
+ p->param.units = params[varID].units;
+ p->ltmpobj = false;
+ /*
+ if ( parse_arg->debug )
+ printf("var: u.var.nm=%s name=%s gridID=%d zaxisID=%d ngp=%d nlev=%d varID=%d\n",
+ p->u.var.nm, p->param.name, p->param.gridID, p->param.zaxisID, p->param.ngp, p->param.nlev, varID);
+ */
+ if ( ! init )
+ {
+ p->param.data = params[varID].data;
+ p->param.nmiss = params[varID].nmiss;
+ }
+
+ if ( parse_arg->debug ) cdoPrint("\tpush\tvar\t%s[L%lu][N%lu]", vnm, p->param.nlev, p->param.ngp);
+
+ rnode = p;
+
+ break;
+ }
+ case typeFun1c:
+ {
+ int funcID = get_funcID(p->u.fun1c.name);
+ int functype = fun_sym_tbl[funcID].type;
+
+ nodeType *fnode = expr_run(p->u.fun1c.op, parse_arg);
+
+ if ( functype == FT_1C )
+ {
+ double value = p->u.fun1c.value;
+ rnode = fun1c(init, funcID, fnode, value, parse_arg);
+ }
+
+ break;
+ }
case typeFun:
- if ( parse_arg->init )
- {
- expr_run(p->u.fun.op, parse_arg);
-
- if ( parse_arg->debug )
- printf("\tcall \t%s\n", p->u.fun.name);
- }
- else
- {
- rnode = ex_fun(p->u.fun.name, expr_run(p->u.fun.op, parse_arg));
- }
- break;
+ {
+ int funcID = get_funcID(p->u.fun.name);
+ int functype = fun_sym_tbl[funcID].type;
+
+ nodeType *fnode = expr_run(p->u.fun.op, parse_arg);
+
+ if ( functype == FT_COORD )
+ {
+ rnode = coord_fun(init, funcID, fnode, parse_arg);
+ }
+ else
+ {
+ int functype = fun_sym_tbl[funcID].type;
+ int funcflag = fun_sym_tbl[funcID].flag;
+ if ( functype == FT_FLD && funcflag == 1 )
+ {
+ int coordID = params_get_coordID(parse_arg, 'w', fnode->param.gridID);
+ if ( init )
+ parse_arg->coords[coordID].needed = true;
+ else
+ fnode->param.weight = parse_arg->coords[coordID].data;
+ }
+ rnode = ex_fun(init, funcID, fnode);
+ // if ( fnode->ltmpobj ) node_delete(fnode);
+ // Free(fnode);
+ }
+
+ break;
+ }
case typeOpr:
switch( p->u.opr.oper )
{
case '=':
- parse_arg->gridID2 = -1;
- parse_arg->zaxisID2 = -1;
- parse_arg->tsteptype2 = -1;
-
- rnode = expr_run(p->u.opr.op[1], parse_arg);
-
- if ( parse_arg->init )
- {
- if ( parse_arg->debug )
- printf("\tpop var \t%s\n", p->u.opr.op[0]->u.var.nm);
- /*
- if ( p->u.opr.op[1]->type != typeVar )
- cdoAbort("Operand not variable!");
- */
- if ( parse_arg->gridID2 == -1 || parse_arg->zaxisID2 == -1 || parse_arg->tsteptype2 == -1 )
- cdoAbort("Operand not variable!");
-
- varID = vlistDefVar(parse_arg->vlistID2, parse_arg->gridID2, parse_arg->zaxisID2, parse_arg->tsteptype2);
- const char *varname = p->u.opr.op[0]->u.var.nm;
- vlistDefVarName(parse_arg->vlistID2, varID, varname);
- vlistDefVarMissval(parse_arg->vlistID2, varID, parse_arg->missval2);
- if ( memcmp(varname, "var", 3) == 0 )
- {
- if ( strlen(varname) > 3 && isdigit(varname[3]) )
- {
- int code = atoi(varname+3);
- vlistDefVarCode(parse_arg->vlistID2, varID, code);
- }
- }
- }
- else
- {
- if ( parse_arg->debug )
- printf("\tpop var\t%s\t%s\n", p->u.opr.op[0]->u.var.nm, rnode->u.var.nm);
-
- nvars = vlistNvars(parse_arg->vlistID2);
- for ( varID = nvars-1; varID >= 0; varID-- )
- {
- vlistInqVarName(parse_arg->vlistID2, varID, varname);
- if ( strcmp(varname, p->u.opr.op[0]->u.var.nm) == 0 ) break;
- }
-
- if ( varID < 0 )
- {
- cdoAbort("Variable >%s< not found!", p->u.opr.op[0]->u.var.nm);
- }
- else
- {
- parse_arg->gridID2 = vlistInqVarGrid(parse_arg->vlistID2, varID);
- parse_arg->zaxisID2 = vlistInqVarZaxis(parse_arg->vlistID2, varID);
- parse_arg->tsteptype2 = vlistInqVarTsteptype(parse_arg->vlistID2, varID);
- missval = vlistInqVarMissval(parse_arg->vlistID2, varID);
-
- p->gridID = parse_arg->gridID2;
- p->zaxisID = parse_arg->zaxisID2;
- p->missval = missval;
- p->data = parse_arg->vardata2[varID];
- p->tmpvar = 0;
-
- ex_copy(p, rnode);
-
- if ( rnode->tmpvar ) Free(rnode->data);
- }
- }
-
- break;
- case UMINUS:
- if ( parse_arg->init )
- {
- expr_run(p->u.opr.op[0], parse_arg);
-
- if ( parse_arg->debug )
- printf("\tneg\n");
- }
- else
- {
- rnode = ex_uminus(expr_run(p->u.opr.op[0], parse_arg));
- }
-
- break;
- case '?':
- if ( parse_arg->init )
- {
- expr_run(p->u.opr.op[0], parse_arg);
- expr_run(p->u.opr.op[1], parse_arg);
- expr_run(p->u.opr.op[2], parse_arg);
-
- if ( parse_arg->debug )
- printf("\t?:\n");
- }
- else
- {
- rnode = ex_ifelse(expr_run(p->u.opr.op[0], parse_arg),
- expr_run(p->u.opr.op[1], parse_arg),
- expr_run(p->u.opr.op[2], parse_arg));
- }
-
- break;
+ {
+ rnode = expr_run(p->u.opr.op[1], parse_arg);
+
+ const char *varname2 = p->u.opr.op[0]->u.var.nm;
+
+ if ( parse_arg->debug )
+ {
+ if ( rnode && rnode->type == typeVar)
+ cdoPrint("\tpop\tvar\t%s[L%lu][N%lu]", varname2, rnode->param.nlev, rnode->param.ngp);
+ else
+ cdoPrint("\tpop\tconst\t%s", varname2);
+ }
+
+ if ( init )
+ {
+ varID = param_search_name(parse_arg->nparams, params, varname2);
+ if ( varID >= 0 )
+ {
+ if ( varID < parse_arg->nvars1 )
+ {
+ params[varID].select = true;
+ parse_arg->needed[varID] = true;
+ }
+ else if ( params[varID].coord )
+ cdoAbort("Coordinate variable %s is read only!", varname2);
+ /*
+ else
+ cdoWarning("Variable %s already defined!", varname2);
+ */
+ }
+ else if ( p->u.opr.op[1]->type != typeCon )
+ {
+ varID = parse_arg->nparams;
+ if ( varID >= parse_arg->maxparams )
+ cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams);
+
+ param_meta_copy(¶ms[varID], &rnode->param);
+ params[varID].coord = 0;
+ params[varID].lmiss = rnode->param.lmiss;
+ params[varID].name = strdup(varname2);
+ params[varID].nmiss = rnode->param.nmiss;
+ if ( rnode->param.units ) params[varID].units = strdup(rnode->param.units);
+ if ( rnode->param.longname ) params[varID].longname = strdup(rnode->param.longname);
+ parse_arg->nparams++;
+ }
+ }
+ else
+ {
+ varID = param_search_name(parse_arg->nparams, params, varname2);
+ if ( varID < 0 ) cdoAbort("Variable >%s< not found!", varname2);
+ else if ( params[varID].coord ) cdoAbort("Coordinate variable %s is read only!", varname2);
+ param_meta_copy(&p->param, ¶ms[varID]);
+ p->param.name = params[varID].name;
+ p->param.data = params[varID].data;
+ p->ltmpobj = false;
+
+ ex_copy(init, p, rnode);
+ params[varID].nmiss = p->param.nmiss;
+ }
+
+ if ( rnode && rnode->ltmpobj ) { node_delete(rnode); rnode = NULL; }
+ // else Free(rnode);
+
+ break;
+ }
+ case UMINUS:
+ {
+ rnode = ex_uminus(init, expr_run(p->u.opr.op[0], parse_arg));
+
+ break;
+ }
+ case '?':
+ {
+ rnode = ex_ifelse(init,
+ expr_run(p->u.opr.op[0], parse_arg),
+ expr_run(p->u.opr.op[1], parse_arg),
+ expr_run(p->u.opr.op[2], parse_arg));
+
+ break;
+ }
default:
- if ( parse_arg->init )
- {
- expr_run(p->u.opr.op[0], parse_arg);
- expr_run(p->u.opr.op[1], parse_arg);
- if ( parse_arg->debug )
- switch( p->u.opr.oper )
- {
- case '+': printf("\tadd\n"); break;
- case '-': printf("\tsub\n"); break;
- case '*': printf("\tmul\n"); break;
- case '/': printf("\tdiv\n"); break;
- case '<': printf("\tcompLT\n"); break;
- case '>': printf("\tcompGT\n"); break;
- case LE: printf("\tcompLE\n"); break;
- case GE: printf("\tcompGE\n"); break;
- case NE: printf("\tcompNE\n"); break;
- case EQ: printf("\tcompEQ\n"); break;
- case LEG: printf("\tcompLEG\n"); break;
- case AND: printf("\tcompAND\n"); break;
- case OR: printf("\tcompOR\n"); break;
- }
- }
- else
- {
- rnode = expr(p->u.opr.oper, expr_run(p->u.opr.op[0], parse_arg),
- expr_run(p->u.opr.op[1], parse_arg));
- }
- break;
+ {
+ rnode = expr(init, p->u.opr.oper,
+ expr_run(p->u.opr.op[0], parse_arg),
+ expr_run(p->u.opr.op[1], parse_arg));
+
+ break;
+ }
}
break;
}
- return (rnode);
+ return rnode;
}
diff --git a/src/expr.h b/src/expr.h
index 6d3cebc..f8a013f 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -1,111 +1,162 @@
+/*
+ This file is part of CDO. CDO is a collection of Operators to
+ manipulate and analyse Climate model Data.
+
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ See COPYING file for copying and redistribution conditions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
#include <stdio.h>
+#include <stdbool.h>
+#ifdef __cplusplus
#ifndef register
#define register
#endif
-
-#ifdef __cplusplus
#ifndef fileno
int fileno(FILE *stream);
#endif
#endif
-#ifndef strdupx
-#ifndef strdup
-char *strdup(const char *s);
-#endif
-#define strdupx strdup
-/*
-#define strdupx(s) \
-({ \
- const char *__old = (s); \
- size_t __len = strlen(__old) + 1; \
- char *__new = Malloc(__len); \
- (char *) memcpy(__new, __old, __len); \
-})
-*/
-#endif
+extern int CDO_parser_errorno;
+
+typedef enum { typeCon, typeVar, typeFun, typeFun1c, typeOpr, typeCom } nodeEnum;
-typedef enum { typeCon, typeVar, typeFun, typeOpr } nodeEnum;
+// commands
+typedef struct {
+ char *cname; // command name
+ char *vname; // variable name
+} comNodeType;
-/* constants */
+// constants
typedef struct {
- double value; /* value of constant */
+ double value; // value of constant
} conNodeType;
-/* variables */
+// variables
typedef struct {
- char *nm; /* variable name */
+ char *nm; // variable name
} varNodeType;
-/* functions */
+// 1c functions
typedef struct {
- char *name; /* function name */
- struct nodeTypeTag *op; /* operand */
+ char *name; // function name
+ double value; // value of constant
+ struct nodeTypeTag *op; // operand
+} fun1cNodeType;
+
+// functions
+typedef struct {
+ char *name; // function name
+ struct nodeTypeTag *op; // operand
} funNodeType;
-/* operators */
+// operators
typedef struct {
- int oper; /* operator */
- int nops; /* number of operands */
- struct nodeTypeTag *op[1]; /* operands (expandable) */
+ int oper; // operator
+ int nops; // number of operands
+ struct nodeTypeTag *op[1]; // operands (expandable)
} oprNodeType;
+// parameter
+typedef struct {
+ bool select;
+ bool remove;
+ bool lmiss;
+ int coord;
+ int gridID;
+ int zaxisID;
+ int steptype;
+ size_t ngp;
+ size_t nlev;
+ size_t nmiss;
+ char *name;
+ char *longname;
+ char *units;
+ double missval;
+ double *data;
+ double *weight;
+} paramType;
+
+
typedef struct nodeTypeTag {
- int tmpvar;
- int gridID, zaxisID;
- int nmiss;
- double missval;
- double *data;
- nodeEnum type; /* type of node */
-
- /* union must be last entry in nodeType */
- /* because operNodeType may dynamically increase */
+ bool ltmpobj;
+ paramType param;
+
+ nodeEnum type; // type of node
+
+ // union must be last entry in nodeType
+ // because operNodeType may dynamically increase
union {
- conNodeType con; /* constants */
- varNodeType var; /* variables */
- funNodeType fun; /* functions */
- oprNodeType opr; /* operators */
+ comNodeType com; // commands
+ conNodeType con; // constants
+ varNodeType var; // variables
+ funNodeType fun; // functions
+ fun1cNodeType fun1c; // functions
+ oprNodeType opr; // operators
} u;
} nodeType;
-#define MAX_VARS 1024
-
-typedef struct{ /* prs_sct */
- int vlistID1, vlistID2;
- int nvars1, nvars2;
- int nmiss[MAX_VARS];
- int varID[MAX_VARS];
- int var_needed[MAX_VARS];
- char *var[MAX_VARS];
- int init;
- int debug;
- int gridID2;
- int zaxisID2;
- int tsteptype2;
- double missval2;
- double **vardata1, **vardata2;
-} parse_parm_t;
+
+typedef struct {
+ bool needed;
+ int coord;
+ int cdiID;
+ int size;
+ char *units;
+ char *longname;
+ double *data;
+} coordType;
+
+
+typedef struct {
+ bool init;
+ bool debug;
+ bool *needed;
+ int maxparams;
+ int nparams;
+ int nvars1;
+ int ncoords;
+ int maxcoords;
+ int tsID;
+ int pointID;
+ int surfaceID;
+ coordType *coords;
+ paramType *params;
+} parse_param_t;
typedef union{
- double cvalue; /* constant value */
- char *varnm; /* variable name */
- char *fname; /* function name */
- nodeType *nPtr; /* node pointer */
+ double cvalue; // constant value
+ char *varnm; // variable name
+ char *fname; // function name
+ nodeType *nPtr; // node pointer
} stype_t;
#define YYSTYPE stype_t
-#define YY_EXTRA_TYPE parse_parm_t *
+#define YY_EXTRA_TYPE parse_param_t *
-#define YY_DECL int yylex(YYSTYPE *yylval_param, parse_parm_t *parse_arg, void *yyscanner)
+#define YY_DECL int yylex(YYSTYPE *yylval_param, parse_param_t *parse_arg, void *yyscanner)
YY_DECL;
-int yyparse(parse_parm_t *parse_arg, void*);
+int yyparse(parse_param_t *parse_arg, void*);
void yyerror(void *parse_arg, void *scanner, const char *errstr);
int yylex_init(void **);
int yylex_destroy(void *);
void yyset_extra(YY_EXTRA_TYPE, void *);
+
+nodeType *expr_run(nodeType *p, parse_param_t *parse_arg);
+int params_get_coordID(parse_param_t *parse_arg, int coord, int cdiID);
+
diff --git a/src/expr_fun.c b/src/expr_fun.c
new file mode 100644
index 0000000..ab478e4
--- /dev/null
+++ b/src/expr_fun.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of CDO. CDO is a collection of Operators to
+ manipulate and analyse Climate model Data.
+
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ See COPYING file for copying and redistribution conditions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#include "cdo_int.h"
+#include "grid.h"
+
+
+void fld_field_init(field_t *field, size_t nmiss, double missval, size_t ngp, double *array, double *w)
+{
+ field_init(field);
+
+ field->size = ngp;
+ field->nmiss = nmiss;
+ field->missval = missval;
+ field->ptr = array;
+ field->weight = w;
+}
+
+
+double *fld_weights(int gridID, size_t ngp)
+{
+ static bool lwarn = true;
+ double *weights = (double*) Malloc(ngp*sizeof(double));
+ for ( size_t i = 0; i < ngp; ++i ) weights[i] = 1;
+
+ if ( ngp > 1 )
+ {
+ int wstatus = gridWeights(gridID, weights);
+ if ( wstatus != 0 && lwarn )
+ {
+ lwarn = false;
+ cdoWarning("Grid cell bounds not available, using constant grid cell area weights!");
+ }
+ }
+
+ return weights;
+}
+
+
+int getLayerThickness(int genbounds, int index, int zaxisID, int nlev, double *thickness, double *weights);
+
+double *vert_weights(int zaxisID, size_t nlev)
+{
+ static bool lwarn = true;
+ double *weights = (double*) Malloc(nlev*sizeof(double));
+ double *thickness = (double*) Malloc(nlev*sizeof(double));
+ for ( size_t i = 0; i < nlev; ++i ) weights[i] = 1;
+
+ if ( nlev > 1 )
+ {
+ int wstatus = getLayerThickness(0, 0, zaxisID, nlev, thickness, weights);
+ if ( wstatus != 0 && lwarn && nlev > 1 )
+ {
+ lwarn = false;
+ cdoWarning("Layer bounds not available, using constant vertical weights!");
+ }
+ }
+
+ Free(thickness);
+
+ return weights;
+}
diff --git a/src/cdo.h b/src/expr_fun.h
similarity index 67%
copy from src/cdo.h
copy to src/expr_fun.h
index 569c938..4f48d54 100644
--- a/src/cdo.h
+++ b/src/expr_fun.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -15,9 +15,11 @@
GNU General Public License for more details.
*/
-#ifndef _CDO_H
-#define _CDO_H
+#ifndef _EXPR_FUN_H
+#define _EXPR_FUN_H
-#include "text.h"
+void fld_field_init(field_t *field, size_t nmiss, double missval, size_t ngp, double *array, double *w);
+double *fld_weights(int gridID, size_t ngp);
+double *vert_weights(int zaxisID, size_t nlev);
-#endif /* _CDO_H */
+#endif
diff --git a/src/expr_lex.c b/src/expr_lex.c
index e931959..5572444 100644
--- a/src/expr_lex.c
+++ b/src/expr_lex.c
@@ -8,8 +8,8 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 0
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -159,7 +159,15 @@ typedef void* yyscan_t;
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
/* The state buf must be large enough to hold one state per character in the main buffer.
@@ -181,6 +189,7 @@ typedef size_t yy_size_t;
#define EOB_ACT_LAST_MATCH 2
#define YY_LESS_LINENO(n)
+ #define YY_LINENO_REWIND_TO(ptr)
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
@@ -326,7 +335,7 @@ void yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
-#define yywrap(yyscanner) 1
+#define yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR;
@@ -338,6 +347,9 @@ typedef int yy_state_type;
static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
static int yy_get_next_buffer (yyscan_t yyscanner );
+#if defined(__GNUC__) && __GNUC__ >= 3
+__attribute__((__noreturn__))
+#endif
static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
@@ -350,8 +362,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 22
+#define YY_END_OF_BUFFER 23
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -359,45 +371,51 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_acclist[91] =
+static yyconst flex_int16_t yy_acclist[123] =
{ 0,
- 4, 4, 18, 16, 17, 15, 16, 17, 15, 17,
- 16, 17, 1, 16, 17, 16, 17, 7, 16, 17,
- 4, 7, 16, 17, 4, 16, 17, 7, 16, 17,
- 7, 16, 17, 7, 16, 17, 6, 16, 17,16389,
- 4, 6, 16, 17,16389, 6, 16, 17,16389, 6,
- 16, 17,16389, 16, 17, 15, 12, 1, 13, 4,
- 4, 4, 4, 10, 11, 9, 8197, 6,16389, 4,
- 6,16389, 6,16389, 14, 4, 4, 8, 4, 6,
- 16389, 3, 6,16389, 6,16389, 4, 2, 6,16389
+ 4, 4, 23, 21, 22, 20, 21, 22, 20, 22,
+ 21, 22, 1, 21, 22, 21, 22, 10, 21, 22,
+ 4, 10, 21, 22, 4, 21, 22, 15, 21, 22,
+ 10, 21, 22, 14, 21, 22, 9, 21, 22,16391,
+ 4, 9, 21, 22,16391, 9, 21, 22,16391, 9,
+ 21, 22,16391, 9, 21, 22,16391, 9, 21, 22,
+ 16391, 21, 22, 20, 17, 1, 18, 4, 4, 4,
+ 4, 13, 16, 12, 8199, 8, 9,16391, 4, 9,
+ 16391, 9,16391, 9,16391, 9,16391, 19, 4, 4,
+ 11, 8, 4, 9,16391, 3, 9,16391, 9,16391,
+
+ 9,16391, 9,16391, 4, 2, 9,16391, 9,16391,
+ 9,16391, 9,16391, 9,16391, 6, 8199, 9,16391,
+ 5, 8199
} ;
-static yyconst flex_int16_t yy_accept[52] =
+static yyconst flex_int16_t yy_accept[67] =
{ 0,
1, 2, 3, 4, 6, 9, 11, 13, 16, 18,
21, 25, 28, 31, 34, 37, 41, 46, 50, 54,
- 56, 57, 58, 59, 60, 61, 62, 62, 63, 64,
- 64, 65, 66, 67, 67, 68, 70, 70, 73, 75,
- 76, 76, 77, 78, 79, 82, 85, 87, 88, 91,
- 91
+ 58, 62, 64, 65, 66, 67, 68, 69, 70, 70,
+ 71, 72, 72, 73, 74, 75, 75, 76, 77, 79,
+ 79, 82, 84, 86, 88, 89, 89, 90, 91, 92,
+ 93, 96, 99, 101, 103, 105, 106, 109, 111, 113,
+ 115, 117, 119, 121, 123, 123
} ;
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 4, 5, 1, 6, 1, 1, 7, 1, 8,
- 9, 9, 10, 1, 10, 11, 9, 12, 12, 12,
+ 9, 9, 10, 9, 10, 11, 9, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 9, 9, 13,
14, 15, 9, 1, 16, 16, 16, 17, 18, 16,
16, 16, 19, 16, 16, 17, 20, 16, 16, 21,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
1, 1, 1, 9, 22, 1, 16, 16, 16, 17,
- 23, 16, 16, 16, 16, 16, 16, 17, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 9, 24, 9, 1, 1, 1, 1, 1,
+ 23, 16, 16, 16, 24, 16, 16, 17, 25, 26,
+ 27, 28, 16, 29, 16, 30, 16, 31, 16, 16,
+ 16, 16, 9, 32, 9, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -414,65 +432,82 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[25] =
+static yyconst YY_CHAR yy_meta[33] =
{ 0,
1, 1, 2, 3, 1, 1, 1, 3, 1, 1,
- 1, 3, 1, 1, 1, 3, 3, 3, 3, 3,
- 3, 3, 3, 1
+ 3, 3, 1, 1, 1, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 1
} ;
-static yyconst flex_int16_t yy_base[53] =
+static yyconst flex_uint16_t yy_base[69] =
{ 0,
- 0, 0, 87, 88, 23, 26, 72, 0, 78, 88,
- 19, 32, 70, 69, 68, 30, 31, 52, 37, 57,
- 44, 88, 0, 88, 0, 88, 41, 0, 0, 42,
- 65, 88, 88, 53, 88, 57, 66, 23, 45, 88,
- 65, 53, 56, 88, 53, 49, 50, 88, 36, 88,
- 73, 29
+ 0, 0, 140, 152, 31, 34, 125, 0, 131, 152,
+ 27, 40, 122, 99, 95, 38, 51, 60, 31, 44,
+ 55, 60, 72, 152, 0, 152, 65, 152, 69, 68,
+ 0, 77, 69, 152, 152, 86, 152, 0, 83, 57,
+ 30, 86, 87, 90, 152, 48, 49, 89, 152, 0,
+ 93, 98, 102, 106, 107, 152, 110, 113, 114, 119,
+ 118, 152, 125, 152, 152, 145, 147, 44
} ;
-static yyconst flex_int16_t yy_def[53] =
+static yyconst flex_int16_t yy_def[69] =
{ 0,
- 50, 1, 50, 50, 50, 50, 50, 51, 50, 50,
- 50, 50, 50, 50, 50, 52, 52, 52, 52, 50,
- 50, 50, 51, 50, 11, 50, 50, 11, 12, 50,
- 50, 50, 50, 50, 50, 19, 50, 18, 19, 50,
- 50, 50, 50, 50, 19, 19, 19, 50, 19, 0,
- 50, 50
+ 65, 1, 65, 65, 65, 65, 65, 66, 65, 65,
+ 65, 65, 65, 65, 65, 67, 67, 67, 18, 18,
+ 18, 65, 65, 65, 66, 65, 65, 65, 65, 65,
+ 12, 65, 65, 65, 65, 65, 65, 68, 18, 65,
+ 18, 18, 18, 18, 65, 65, 65, 65, 65, 68,
+ 18, 18, 18, 18, 18, 65, 18, 18, 18, 18,
+ 18, 65, 18, 65, 0, 65, 65, 65
} ;
-static yyconst flex_int16_t yy_nxt[113] =
+static yyconst flex_uint16_t yy_nxt[185] =
{ 0,
4, 5, 6, 5, 7, 8, 9, 10, 10, 10,
11, 12, 13, 14, 15, 16, 17, 18, 16, 19,
- 16, 16, 18, 20, 21, 21, 21, 21, 21, 21,
- 25, 36, 50, 34, 34, 26, 27, 35, 35, 45,
- 34, 27, 28, 29, 35, 21, 21, 21, 26, 30,
- 41, 37, 42, 43, 30, 34, 34, 36, 39, 35,
- 35, 37, 46, 38, 42, 47, 36, 43, 49, 26,
- 36, 36, 48, 23, 36, 23, 42, 43, 36, 44,
- 40, 33, 32, 31, 24, 22, 50, 3, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
-
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50
+ 16, 16, 18, 16, 16, 16, 16, 20, 21, 16,
+ 16, 22, 23, 23, 23, 23, 23, 23, 27, 65,
+ 65, 36, 39, 28, 29, 37, 51, 50, 38, 29,
+ 30, 31, 42, 65, 36, 39, 28, 32, 37, 47,
+ 47, 38, 32, 36, 65, 28, 39, 37, 48, 40,
+ 38, 41, 43, 23, 23, 23, 27, 44, 46, 27,
+ 47, 28, 29, 49, 28, 29, 40, 29, 48, 36,
+ 29, 45, 65, 37, 39, 65, 65, 39, 39, 65,
+
+ 48, 39, 65, 52, 39, 56, 53, 65, 35, 39,
+ 54, 65, 34, 39, 55, 65, 65, 39, 39, 65,
+ 57, 39, 65, 65, 39, 39, 62, 65, 65, 39,
+ 39, 58, 64, 59, 65, 33, 39, 26, 24, 65,
+ 63, 65, 60, 65, 61, 25, 65, 25, 25, 39,
+ 39, 3, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65
} ;
-static yyconst flex_int16_t yy_chk[113] =
+static yyconst flex_int16_t yy_chk[185] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 5, 5, 5, 6, 6, 6,
- 11, 52, 38, 16, 17, 11, 11, 16, 17, 38,
- 19, 11, 12, 12, 19, 21, 21, 21, 12, 12,
- 27, 30, 27, 30, 12, 18, 34, 49, 19, 18,
- 34, 18, 39, 18, 42, 39, 39, 43, 47, 42,
- 46, 47, 43, 51, 45, 51, 41, 37, 36, 31,
- 20, 15, 14, 13, 9, 7, 3, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
-
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 5, 5, 5, 6, 6, 6, 11, 41,
+ 19, 16, 19, 11, 11, 16, 41, 68, 16, 11,
+ 12, 12, 19, 20, 17, 20, 12, 12, 17, 46,
+ 47, 17, 12, 18, 21, 47, 21, 18, 40, 18,
+ 18, 18, 20, 23, 23, 23, 27, 21, 29, 30,
+ 29, 27, 27, 33, 30, 30, 32, 27, 32, 36,
+ 30, 22, 39, 36, 39, 42, 43, 42, 43, 44,
+
+ 48, 44, 51, 42, 51, 48, 42, 52, 15, 52,
+ 43, 53, 14, 53, 44, 54, 55, 54, 55, 57,
+ 53, 57, 58, 59, 58, 59, 60, 61, 60, 61,
+ 60, 54, 63, 55, 63, 13, 63, 9, 7, 3,
+ 61, 0, 58, 0, 59, 66, 0, 66, 66, 67,
+ 67, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 65, 65
} ;
#define YY_TRAILING_MASK 0x2000
@@ -516,7 +551,7 @@ goto find_rule; \
LPH [A-Za-z_] Alphabetic character
LPHDGT [A-Za-z0-9_] Alphanumeric character
XPN [eE][+-]?[0-9]+ Real number Exponent */
-#line 520 "expr_lex.c"
+#line 555 "expr_lex.c"
#define INITIAL 0
@@ -604,11 +639,11 @@ void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *yyget_in (yyscan_t yyscanner );
-void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *yyget_out (yyscan_t yyscanner );
-void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void yyset_out (FILE * _out_str ,yyscan_t yyscanner );
yy_size_t yyget_leng (yyscan_t yyscanner );
@@ -616,11 +651,11 @@ char *yyget_text (yyscan_t yyscanner );
int yyget_lineno (yyscan_t yyscanner );
-void yyset_lineno (int line_number ,yyscan_t yyscanner );
+void yyset_lineno (int _line_number ,yyscan_t yyscanner );
int yyget_column (yyscan_t yyscanner );
-void yyset_column (int column_no ,yyscan_t yyscanner );
+void yyset_column (int _column_no ,yyscan_t yyscanner );
YYSTYPE * yyget_lval (yyscan_t yyscanner );
@@ -638,6 +673,10 @@ extern int yywrap (yyscan_t yyscanner );
#endif
#endif
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
@@ -658,7 +697,12 @@ static int input (yyscan_t yyscanner );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -747,7 +791,7 @@ extern int yylex \
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
#endif
#define YY_RULE_SETUP \
@@ -757,16 +801,11 @@ extern int yylex \
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 36 "expr_lex.l"
-
-
-#line 769 "expr_lex.c"
-
yylval = yylval_param;
if ( !yyg->yy_init )
@@ -801,7 +840,13 @@ YY_DECL
yy_load_buffer_state(yyscanner );
}
- while ( 1 ) /* loops until end-of-file is reached */
+ {
+#line 36 "expr_lex.l"
+
+
+#line 848 "expr_lex.c"
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
yy_cp = yyg->yy_c_buf_p;
@@ -821,18 +866,18 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 51 )
+ if ( yy_current_state >= 66 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
*yyg->yy_state_ptr++ = yy_current_state;
++yy_cp;
}
- while ( yy_base[yy_current_state] != 88 );
+ while ( yy_base[yy_current_state] != 152 );
yy_find_action:
yy_current_state = *--yyg->yy_state_ptr;
@@ -914,79 +959,108 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 60 "expr_lex.l"
+#line 59 "expr_lex.l"
+{ return REMOVE; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 61 "expr_lex.l"
+{ return PRINT; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 63 "expr_lex.l"
{
- yylval->fname = (char *) strdupx(yytext);
+ yylval->fname = strdup(yytext);
return FUNCTION;
} /* end functions */
YY_BREAK
-case 6:
+case 8:
YY_RULE_SETUP
-#line 66 "expr_lex.l"
+#line 68 "expr_lex.l"
{
- yylval->varnm = (char *) strdupx(yytext);
+ /* Recognize coordinates, e.g., var_nm.x (lon of var_nm) */
+ yylval->varnm = strdup(yytext);
return VARIABLE;
}
YY_BREAK
-case 7:
+case 9:
YY_RULE_SETUP
-#line 72 "expr_lex.l"
+#line 74 "expr_lex.l"
+{
+ yylval->varnm = strdup(yytext);
+ return VARIABLE;
+ }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 80 "expr_lex.l"
{
return *yytext;
}
YY_BREAK
-case 8:
+case 11:
YY_RULE_SETUP
-#line 76 "expr_lex.l"
+#line 84 "expr_lex.l"
return LEG;
YY_BREAK
-case 9:
+case 12:
YY_RULE_SETUP
-#line 77 "expr_lex.l"
+#line 85 "expr_lex.l"
return GE;
YY_BREAK
-case 10:
+case 13:
YY_RULE_SETUP
-#line 78 "expr_lex.l"
+#line 86 "expr_lex.l"
return LE;
YY_BREAK
-case 11:
+case 14:
YY_RULE_SETUP
-#line 79 "expr_lex.l"
+#line 87 "expr_lex.l"
+return GT;
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 88 "expr_lex.l"
+return LT;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 89 "expr_lex.l"
return EQ;
YY_BREAK
-case 12:
+case 17:
YY_RULE_SETUP
-#line 80 "expr_lex.l"
+#line 90 "expr_lex.l"
return NE;
YY_BREAK
-case 13:
+case 18:
YY_RULE_SETUP
-#line 81 "expr_lex.l"
+#line 91 "expr_lex.l"
return AND;
YY_BREAK
-case 14:
+case 19:
YY_RULE_SETUP
-#line 82 "expr_lex.l"
+#line 92 "expr_lex.l"
return OR;
YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 20:
+/* rule 20 can match eol */
YY_RULE_SETUP
-#line 84 "expr_lex.l"
+#line 94 "expr_lex.l"
; /* ignore whitespace */
YY_BREAK
-case 16:
+case 21:
YY_RULE_SETUP
-#line 86 "expr_lex.l"
+#line 96 "expr_lex.l"
yyerror(NULL, NULL, "Unknown character");
YY_BREAK
-case 17:
+case 22:
YY_RULE_SETUP
-#line 87 "expr_lex.l"
+#line 97 "expr_lex.l"
ECHO;
YY_BREAK
-#line 990 "expr_lex.c"
+#line 1064 "expr_lex.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1117,6 +1191,7 @@ ECHO;
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
+ } /* end of user's declarations */
} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
@@ -1129,9 +1204,9 @@ ECHO;
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ yy_size_t number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1160,7 +1235,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1234,8 +1309,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
@@ -1245,11 +1320,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 51 )
+ if ( yy_current_state >= 66 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1266,18 +1341,18 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 51 )
+ if ( yy_current_state >= 66 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 50);
+ yy_is_jam = (yy_current_state == 65);
if ( ! yy_is_jam )
*yyg->yy_state_ptr++ = yy_current_state;
@@ -1285,6 +1360,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
return yy_is_jam ? 0 : yy_current_state;
}
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (yyscan_t yyscanner)
@@ -1438,7 +1517,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = size;
+ b->yy_buf_size = (yy_size_t)size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
@@ -1599,7 +1678,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner)
* scanner will even need a stack. We use 2 instead of 1 to avoid an
* immediate realloc on the next call.
*/
- num_to_alloc = 1;
+ num_to_alloc = 1; // After all that talk, this was set to 1 anyways...
yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
@@ -1616,7 +1695,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner)
if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
/* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
@@ -1693,7 +1772,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- int i;
+ yy_size_t i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
@@ -1724,7 +1803,9 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
{
- (void) fprintf( stderr, "%s\n", msg );
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -1830,10 +1911,10 @@ void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
}
/** Set the current line number.
- * @param line_number
+ * @param _line_number line number
* @param yyscanner The scanner object.
*/
-void yyset_lineno (int line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1841,14 +1922,14 @@ void yyset_lineno (int line_number , yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
- yylineno = line_number;
+ yylineno = _line_number;
}
/** Set the current column.
- * @param line_number
+ * @param _column_no column number
* @param yyscanner The scanner object.
*/
-void yyset_column (int column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1856,25 +1937,25 @@ void yyset_column (int column_no , yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "yyset_column called with no buffer" );
- yycolumn = column_no;
+ yycolumn = _column_no;
}
/** Set the input stream. This does not discard the current
* input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
* @param yyscanner The scanner object.
* @see yy_switch_to_buffer
*/
-void yyset_in (FILE * in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
+ yyin = _in_str ;
}
-void yyset_out (FILE * out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
+ yyout = _out_str ;
}
int yyget_debug (yyscan_t yyscanner)
@@ -1883,10 +1964,10 @@ int yyget_debug (yyscan_t yyscanner)
return yy_flex_debug;
}
-void yyset_debug (int bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
+ yy_flex_debug = _bdebug ;
}
/* Accessor methods for yylval and yylloc */
@@ -2045,7 +2126,10 @@ int yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2054,7 +2138,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
@@ -2064,11 +2148,16 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
return (void *) malloc( size );
}
void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
@@ -2081,12 +2170,14 @@ void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
void yyfree (void * ptr , yyscan_t yyscanner)
{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 87 "expr_lex.l"
+#line 97 "expr_lex.l"
diff --git a/src/expr_yacc.c b/src/expr_yacc.c
index 2b69bca..d1a5384 100644
--- a/src/expr_yacc.c
+++ b/src/expr_yacc.c
@@ -69,12 +69,14 @@
#include <string.h>
#include <stdarg.h>
+#include "dmemory.h"
+
#include "expr.h"
#include "expr_yacc.h" /* expr_yacc.h (y.tab.h) is produced from expr_yacc.y by parser generator */
/* Bison manual p. 60 describes how to call yyparse() with arguments */
/* #define YYPARSE_PARAM parse_arg */
-/* #define YYLEX_PARAM ((parse_parm_t *) parse_arg, void *yyscanner) */
+/* #define YYLEX_PARAM ((parse_param_t *) parse_arg, void *yyscanner) */
/* #define YYPURE 1 *//* ??? */
@@ -83,12 +85,13 @@ nodeType *expr_opr(int oper, int nops, ...);
nodeType *expr_var(char *nm);
nodeType *expr_con(double value);
nodeType *expr_fun(char *fname, nodeType *p);
+nodeType *expr_fun1c(char *fname, nodeType *op, double value);
+nodeType *expr_com(const char *cname, char *vname);
void freeNode(nodeType *p);
-int expr_run(nodeType *p, parse_parm_t *parse_arg);
-#line 92 "expr_yacc.c" /* yacc.c:339 */
+#line 95 "expr_yacc.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -103,7 +106,7 @@ int expr_run(nodeType *p, parse_parm_t *parse_arg);
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
-# define YYERROR_VERBOSE 0
+# define YYERROR_VERBOSE 1
#endif
/* In a future release of Bison, this section will be replaced
@@ -126,40 +129,48 @@ extern int yydebug;
CONSTANT = 258,
VARIABLE = 259,
FUNCTION = 260,
- LEG = 261,
- GE = 262,
- LE = 263,
- EQ = 264,
- NE = 265,
- AND = 266,
- OR = 267,
- UMINUS = 268
+ REMOVE = 261,
+ PRINT = 262,
+ AND = 263,
+ OR = 264,
+ LEG = 265,
+ GE = 266,
+ LE = 267,
+ EQ = 268,
+ NE = 269,
+ GT = 270,
+ LT = 271,
+ UMINUS = 272
};
#endif
/* Tokens. */
#define CONSTANT 258
#define VARIABLE 259
#define FUNCTION 260
-#define LEG 261
-#define GE 262
-#define LE 263
-#define EQ 264
-#define NE 265
-#define AND 266
-#define OR 267
-#define UMINUS 268
+#define REMOVE 261
+#define PRINT 262
+#define AND 263
+#define OR 264
+#define LEG 265
+#define GE 266
+#define LE 267
+#define EQ 268
+#define NE 269
+#define GT 270
+#define LT 271
+#define UMINUS 272
/* Value type. */
-int yyparse (parse_parm_t *parse_arg, void *scanner);
+int yyparse (parse_param_t *parse_arg, void *scanner);
#endif /* !YY_YY_EXPR_YACC_H_INCLUDED */
/* Copy the second part of user declarations. */
-#line 163 "expr_yacc.c" /* yacc.c:358 */
+#line 174 "expr_yacc.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -401,21 +412,21 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 182
+#define YYLAST 186
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 29
+#define YYNTOKENS 32
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 6
/* YYNRULES -- Number of rules. */
-#define YYNRULES 31
+#define YYNRULES 35
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 61
+#define YYNSTATES 75
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 268
+#define YYMAXUTOK 272
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -428,15 +439,15 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 27, 28, 15, 13, 2, 14, 2, 16, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 21, 24,
- 12, 19, 11, 20, 2, 2, 2, 2, 2, 2,
+ 30, 27, 19, 17, 31, 18, 2, 20, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 23, 25,
+ 2, 26, 2, 22, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 22, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 24, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 25, 2, 26, 2, 2, 2, 2,
+ 2, 2, 2, 28, 2, 29, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -450,30 +461,31 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 17, 18, 23
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 21
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 53, 53, 57, 58, 62, 63, 64, 65, 66,
- 70, 71, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
- 93, 94
+ 0, 58, 58, 62, 63, 67, 68, 69, 70, 71,
+ 72, 73, 77, 78, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || 1
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "CONSTANT", "VARIABLE", "FUNCTION",
- "LEG", "GE", "LE", "EQ", "NE", "'>'", "'<'", "'+'", "'-'", "'*'", "'/'",
- "AND", "OR", "'='", "'?'", "':'", "'^'", "UMINUS", "';'", "'{'", "'}'",
- "'('", "')'", "$accept", "program", "function", "stmt", "stmt_list",
- "expr", YY_NULLPTR
+ "REMOVE", "PRINT", "AND", "OR", "LEG", "GE", "LE", "EQ", "NE", "GT",
+ "LT", "'+'", "'-'", "'*'", "'/'", "UMINUS", "'?'", "':'", "'^'", "';'",
+ "'='", "')'", "'{'", "'}'", "'('", "','", "$accept", "program",
+ "function", "stmt", "stmt_list", "expr", YY_NULLPTR
};
#endif
@@ -483,15 +495,16 @@ static const char *const yytname[] =
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 62, 60, 43, 45, 42, 47, 266, 267, 61,
- 63, 58, 94, 268, 59, 123, 125, 40, 41
+ 265, 266, 267, 268, 269, 270, 271, 43, 45, 42,
+ 47, 272, 63, 58, 94, 59, 61, 41, 123, 125,
+ 40, 44
};
# endif
-#define YYPACT_NINF -15
+#define YYPACT_NINF -25
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-15)))
+ (!!((Yystate) == (-25)))
#define YYTABLE_NINF -1
@@ -502,13 +515,14 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int16 yypact[] =
{
- -15, 2, 33, -15, -15, 11, -14, 36, -15, 33,
- 36, -15, 104, 36, -15, 36, -15, -15, -15, 29,
- 58, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, -15, 123, 81, -15,
- -15, -15, 152, 152, 152, 152, 152, 152, 152, 160,
- 160, -13, -13, -10, -10, 142, 7, -15, -15, 36,
- -10
+ -25, 5, 36, -25, -25, -16, -24, 7, 8, 33,
+ -25, 36, 33, -25, 103, -25, 33, 33, -13, -12,
+ -25, -20, -25, 28, 83, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ -25, 121, 59, 19, 22, -25, -25, -25, 154, 154,
+ 162, 162, 162, 162, 162, 162, 162, 65, 65, -20,
+ -20, 139, 24, -25, -25, 42, -25, -25, 33, 23,
+ 46, -20, -25, 25, -25
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -516,25 +530,26 @@ static const yytype_int16 yypact[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 4, 0, 2, 1, 12, 13, 0, 0, 5, 0,
- 0, 3, 0, 0, 8, 0, 13, 14, 10, 0,
+ 4, 0, 2, 1, 14, 15, 0, 0, 0, 0,
+ 5, 0, 0, 3, 0, 8, 0, 0, 0, 0,
+ 15, 16, 12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 6, 0, 0, 9,
- 11, 30, 26, 22, 23, 25, 24, 20, 19, 15,
- 16, 17, 18, 27, 28, 0, 21, 7, 31, 0,
- 29
+ 6, 0, 0, 0, 0, 11, 13, 32, 29, 30,
+ 28, 24, 25, 27, 26, 22, 21, 17, 18, 19,
+ 20, 0, 23, 7, 35, 0, 9, 10, 0, 0,
+ 0, 31, 34, 0, 33
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -15, -15, -15, -8, -15, -7
+ -25, -25, -25, -10, -25, -9
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 1, 2, 11, 19, 12
+ -1, 1, 2, 13, 23, 14
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -542,79 +557,80 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 17, 18, 3, 20, 32, 33, 37, 34, 38, 35,
- 34, 40, 35, 15, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 35,
- 13, 0, 4, 5, 6, 14, 4, 5, 6, 4,
- 16, 6, 0, 7, 0, 0, 0, 7, 0, 0,
- 7, 0, 60, 8, 9, 39, 10, 8, 9, 0,
- 10, 0, 0, 10, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 0, 34, 0,
- 35, 0, 0, 0, 0, 0, 41, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 0, 34, 0, 35, 0, 0, 0, 0, 0, 58,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 0, 34, 0, 35, 0, 36, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 0, 34, 0, 35, 0, 57, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
- 33, 0, 34, 59, 35, 28, 29, 30, 31, 32,
- 33, 0, 34, 0, 35, 30, 31, 32, 33, 0,
- 34, 0, 35
+ 21, 22, 38, 24, 39, 3, 17, 41, 42, 15,
+ 16, 18, 19, 46, 43, 44, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 4, 5, 6, 7, 8, 4, 20, 6, 4,
+ 5, 6, 7, 8, 66, 69, 9, 67, 39, 73,
+ 72, 9, 74, 10, 9, 0, 11, 45, 12, 71,
+ 70, 10, 0, 12, 11, 0, 12, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 0, 38, 0, 39, 36, 37, 64, 38, 0, 39,
+ 65, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 0, 38, 0, 39, 0, 0,
+ 47, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 0, 38, 0, 39, 40, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 0, 38, 0, 39, 63, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 0, 38, 68, 39, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 0, 38, 0, 39, 34,
+ 35, 36, 37, 0, 38, 0, 39
};
static const yytype_int8 yycheck[] =
{
- 7, 9, 0, 10, 17, 18, 13, 20, 15, 22,
- 20, 19, 22, 27, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 22,
- 19, -1, 3, 4, 5, 24, 3, 4, 5, 3,
- 4, 5, -1, 14, -1, -1, -1, 14, -1, -1,
- 14, -1, 59, 24, 25, 26, 27, 24, 25, -1,
- 27, -1, -1, 27, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, -1, 20, -1,
- 22, -1, -1, -1, -1, -1, 28, 6, 7, 8,
+ 9, 11, 22, 12, 24, 0, 30, 16, 17, 25,
+ 26, 4, 4, 23, 27, 27, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 3, 4, 5, 6, 7, 3, 4, 5, 3,
+ 4, 5, 6, 7, 25, 3, 18, 25, 24, 3,
+ 27, 18, 27, 25, 18, -1, 28, 29, 30, 68,
+ 18, 25, -1, 30, 28, -1, 30, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ -1, 22, -1, 24, 19, 20, 27, 22, -1, 24,
+ 31, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, -1, 22, -1, 24, -1, -1,
+ 27, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, -1, 22, -1, 24, 25, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- -1, 20, -1, 22, -1, -1, -1, -1, -1, 28,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, -1, 20, -1, 22, -1, 24, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, -1, 20, -1, 22, -1, 24, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, -1, 20, 21, 22, 13, 14, 15, 16, 17,
- 18, -1, 20, -1, 22, 15, 16, 17, 18, -1,
- 20, -1, 22
+ 19, 20, -1, 22, -1, 24, 25, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ -1, 22, 23, 24, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, -1, 22, -1, 24, 17,
+ 18, 19, 20, -1, 22, -1, 24
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 30, 31, 0, 3, 4, 5, 14, 24, 25,
- 27, 32, 34, 19, 24, 27, 4, 34, 32, 33,
- 34, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 20, 22, 24, 34, 34, 26,
- 32, 28, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 24, 28, 21,
- 34
+ 0, 33, 34, 0, 3, 4, 5, 6, 7, 18,
+ 25, 28, 30, 35, 37, 25, 26, 30, 4, 4,
+ 4, 37, 35, 36, 37, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 22, 24,
+ 25, 37, 37, 27, 27, 29, 35, 27, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 25, 27, 31, 25, 25, 23, 3,
+ 18, 37, 27, 3, 27
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 29, 30, 31, 31, 32, 32, 32, 32, 32,
- 33, 33, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34
+ 0, 32, 33, 34, 34, 35, 35, 35, 35, 35,
+ 35, 35, 36, 36, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 1, 2, 0, 1, 2, 4, 2, 3,
- 1, 2, 1, 1, 2, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 5,
- 3, 4
+ 0, 2, 1, 2, 0, 1, 2, 4, 2, 4,
+ 4, 3, 1, 2, 1, 1, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 5, 3, 7, 6, 4
};
@@ -690,7 +706,7 @@ do { \
`----------------------------------------*/
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parse_parm_t *parse_arg, void *scanner)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parse_param_t *parse_arg, void *scanner)
{
FILE *yyo = yyoutput;
YYUSE (yyo);
@@ -711,7 +727,7 @@ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvalue
`--------------------------------*/
static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parse_parm_t *parse_arg, void *scanner)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parse_param_t *parse_arg, void *scanner)
{
YYFPRINTF (yyoutput, "%s %s (",
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
@@ -749,7 +765,7 @@ do { \
`------------------------------------------------*/
static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, parse_parm_t *parse_arg, void *scanner)
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, parse_param_t *parse_arg, void *scanner)
{
unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
@@ -1029,7 +1045,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
`-----------------------------------------------*/
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parse_parm_t *parse_arg, void *scanner)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parse_param_t *parse_arg, void *scanner)
{
YYUSE (yyvaluep);
YYUSE (parse_arg);
@@ -1051,7 +1067,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parse_parm_t *pars
`----------*/
int
-yyparse (parse_parm_t *parse_arg, void *scanner)
+yyparse (parse_param_t *parse_arg, void *scanner)
{
/* The lookahead symbol. */
int yychar;
@@ -1299,181 +1315,205 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 53 "expr_yacc.y" /* yacc.c:1646 */
- { return(0); }
-#line 1305 "expr_yacc.c" /* yacc.c:1646 */
+#line 58 "expr_yacc.y" /* yacc.c:1646 */
+ { return 0; }
+#line 1321 "expr_yacc.c" /* yacc.c:1646 */
break;
case 3:
-#line 57 "expr_yacc.y" /* yacc.c:1646 */
- { expr_run((yyvsp[0].nPtr), (parse_parm_t *) parse_arg); freeNode((yyvsp[0].nPtr)); }
-#line 1311 "expr_yacc.c" /* yacc.c:1646 */
+#line 62 "expr_yacc.y" /* yacc.c:1646 */
+ { expr_run((yyvsp[0].nPtr), (parse_param_t *) parse_arg); freeNode((yyvsp[0].nPtr)); }
+#line 1327 "expr_yacc.c" /* yacc.c:1646 */
break;
case 5:
-#line 62 "expr_yacc.y" /* yacc.c:1646 */
+#line 67 "expr_yacc.y" /* yacc.c:1646 */
{ (yyval.nPtr) = expr_opr(';', 2, NULL, NULL); }
-#line 1317 "expr_yacc.c" /* yacc.c:1646 */
+#line 1333 "expr_yacc.c" /* yacc.c:1646 */
break;
case 6:
-#line 63 "expr_yacc.y" /* yacc.c:1646 */
+#line 68 "expr_yacc.y" /* yacc.c:1646 */
{ (yyval.nPtr) = (yyvsp[-1].nPtr); }
-#line 1323 "expr_yacc.c" /* yacc.c:1646 */
+#line 1339 "expr_yacc.c" /* yacc.c:1646 */
break;
case 7:
-#line 64 "expr_yacc.y" /* yacc.c:1646 */
+#line 69 "expr_yacc.y" /* yacc.c:1646 */
{ (yyval.nPtr) = expr_opr('=', 2, expr_var((yyvsp[-3].varnm)), (yyvsp[-1].nPtr)); }
-#line 1329 "expr_yacc.c" /* yacc.c:1646 */
+#line 1345 "expr_yacc.c" /* yacc.c:1646 */
break;
case 8:
-#line 65 "expr_yacc.y" /* yacc.c:1646 */
+#line 70 "expr_yacc.y" /* yacc.c:1646 */
{ (yyval.nPtr) = expr_opr('=', 2, expr_var((yyvsp[-1].varnm)), expr_var((yyvsp[-1].varnm))); }
-#line 1335 "expr_yacc.c" /* yacc.c:1646 */
+#line 1351 "expr_yacc.c" /* yacc.c:1646 */
break;
case 9:
-#line 66 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = (yyvsp[-1].nPtr); }
-#line 1341 "expr_yacc.c" /* yacc.c:1646 */
+#line 71 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_com("remove", (yyvsp[-2].varnm)); }
+#line 1357 "expr_yacc.c" /* yacc.c:1646 */
break;
case 10:
-#line 70 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = (yyvsp[0].nPtr); }
-#line 1347 "expr_yacc.c" /* yacc.c:1646 */
+#line 72 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_com("print", (yyvsp[-2].varnm)); }
+#line 1363 "expr_yacc.c" /* yacc.c:1646 */
break;
case 11:
-#line 71 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(';', 2, (yyvsp[-1].nPtr), (yyvsp[0].nPtr)); }
-#line 1353 "expr_yacc.c" /* yacc.c:1646 */
+#line 73 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = (yyvsp[-1].nPtr); }
+#line 1369 "expr_yacc.c" /* yacc.c:1646 */
break;
case 12:
-#line 75 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_con((yyvsp[0].cvalue)); }
-#line 1359 "expr_yacc.c" /* yacc.c:1646 */
+#line 77 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = (yyvsp[0].nPtr); }
+#line 1375 "expr_yacc.c" /* yacc.c:1646 */
break;
case 13:
-#line 76 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_var((yyvsp[0].varnm)); }
-#line 1365 "expr_yacc.c" /* yacc.c:1646 */
+#line 78 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(';', 2, (yyvsp[-1].nPtr), (yyvsp[0].nPtr)); }
+#line 1381 "expr_yacc.c" /* yacc.c:1646 */
break;
case 14:
-#line 77 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(UMINUS, 1, (yyvsp[0].nPtr)); }
-#line 1371 "expr_yacc.c" /* yacc.c:1646 */
+#line 82 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_con((yyvsp[0].cvalue)); }
+#line 1387 "expr_yacc.c" /* yacc.c:1646 */
break;
case 15:
-#line 78 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('+', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1377 "expr_yacc.c" /* yacc.c:1646 */
+#line 83 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_var((yyvsp[0].varnm)); }
+#line 1393 "expr_yacc.c" /* yacc.c:1646 */
break;
case 16:
-#line 79 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('-', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1383 "expr_yacc.c" /* yacc.c:1646 */
+#line 84 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(UMINUS, 1, (yyvsp[0].nPtr)); }
+#line 1399 "expr_yacc.c" /* yacc.c:1646 */
break;
case 17:
-#line 80 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('*', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1389 "expr_yacc.c" /* yacc.c:1646 */
+#line 85 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('+', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1405 "expr_yacc.c" /* yacc.c:1646 */
break;
case 18:
-#line 81 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('/', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1395 "expr_yacc.c" /* yacc.c:1646 */
+#line 86 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('-', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1411 "expr_yacc.c" /* yacc.c:1646 */
break;
case 19:
-#line 82 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('<', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1401 "expr_yacc.c" /* yacc.c:1646 */
+#line 87 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('*', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1417 "expr_yacc.c" /* yacc.c:1646 */
break;
case 20:
-#line 83 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('>', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1407 "expr_yacc.c" /* yacc.c:1646 */
+#line 88 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('/', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1423 "expr_yacc.c" /* yacc.c:1646 */
break;
case 21:
-#line 84 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('^', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1413 "expr_yacc.c" /* yacc.c:1646 */
+#line 89 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(LT, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1429 "expr_yacc.c" /* yacc.c:1646 */
break;
case 22:
-#line 85 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(GE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1419 "expr_yacc.c" /* yacc.c:1646 */
+#line 90 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(GT, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1435 "expr_yacc.c" /* yacc.c:1646 */
break;
case 23:
-#line 86 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(LE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1425 "expr_yacc.c" /* yacc.c:1646 */
+#line 91 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('^', 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1441 "expr_yacc.c" /* yacc.c:1646 */
break;
case 24:
-#line 87 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(NE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1431 "expr_yacc.c" /* yacc.c:1646 */
+#line 92 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(GE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1447 "expr_yacc.c" /* yacc.c:1646 */
break;
case 25:
-#line 88 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(EQ, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1437 "expr_yacc.c" /* yacc.c:1646 */
+#line 93 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(LE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1453 "expr_yacc.c" /* yacc.c:1646 */
break;
case 26:
-#line 89 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(LEG, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1443 "expr_yacc.c" /* yacc.c:1646 */
+#line 94 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(NE, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1459 "expr_yacc.c" /* yacc.c:1646 */
break;
case 27:
-#line 90 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(AND, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1449 "expr_yacc.c" /* yacc.c:1646 */
+#line 95 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(EQ, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1465 "expr_yacc.c" /* yacc.c:1646 */
break;
case 28:
-#line 91 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr(OR, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1455 "expr_yacc.c" /* yacc.c:1646 */
+#line 96 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(LEG, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1471 "expr_yacc.c" /* yacc.c:1646 */
break;
case 29:
-#line 92 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = expr_opr('?', 3, (yyvsp[-4].nPtr), (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
-#line 1461 "expr_yacc.c" /* yacc.c:1646 */
+#line 97 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(AND, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1477 "expr_yacc.c" /* yacc.c:1646 */
break;
case 30:
-#line 93 "expr_yacc.y" /* yacc.c:1646 */
- { (yyval.nPtr) = (yyvsp[-1].nPtr); }
-#line 1467 "expr_yacc.c" /* yacc.c:1646 */
+#line 98 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr(OR, 2, (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1483 "expr_yacc.c" /* yacc.c:1646 */
break;
case 31:
-#line 94 "expr_yacc.y" /* yacc.c:1646 */
+#line 99 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_opr('?', 3, (yyvsp[-4].nPtr), (yyvsp[-2].nPtr), (yyvsp[0].nPtr)); }
+#line 1489 "expr_yacc.c" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 100 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = (yyvsp[-1].nPtr); }
+#line 1495 "expr_yacc.c" /* yacc.c:1646 */
+ break;
+
+ case 33:
+#line 101 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_fun1c((yyvsp[-6].fname), (yyvsp[-4].nPtr), - (yyvsp[-1].cvalue)); }
+#line 1501 "expr_yacc.c" /* yacc.c:1646 */
+ break;
+
+ case 34:
+#line 102 "expr_yacc.y" /* yacc.c:1646 */
+ { (yyval.nPtr) = expr_fun1c((yyvsp[-5].fname), (yyvsp[-3].nPtr), (yyvsp[-1].cvalue)); }
+#line 1507 "expr_yacc.c" /* yacc.c:1646 */
+ break;
+
+ case 35:
+#line 103 "expr_yacc.y" /* yacc.c:1646 */
{ (yyval.nPtr) = expr_fun((yyvsp[-3].fname), (yyvsp[-1].nPtr)); }
-#line 1473 "expr_yacc.c" /* yacc.c:1646 */
+#line 1513 "expr_yacc.c" /* yacc.c:1646 */
break;
-#line 1477 "expr_yacc.c" /* yacc.c:1646 */
+#line 1517 "expr_yacc.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1701,7 +1741,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 97 "expr_yacc.y" /* yacc.c:1906 */
+#line 106 "expr_yacc.y" /* yacc.c:1906 */
#define SIZEOF_NODETYPE ((char *)&p->u.con - (char *)p)
@@ -1709,11 +1749,9 @@ yyreturn:
nodeType *expr_con(double value)
{
nodeType *p = NULL;
- size_t nodeSize;
-
/* allocate node */
- nodeSize = SIZEOF_NODETYPE + sizeof(conNodeType);
- if ((p = (nodeType*) malloc(nodeSize)) == NULL)
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(conNodeType);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
yyerror(NULL, NULL, "Out of memory");
/* copy information */
@@ -1726,16 +1764,14 @@ nodeType *expr_con(double value)
nodeType *expr_var(char *nm)
{
nodeType *p = NULL;
- size_t nodeSize;
-
/* allocate node */
- nodeSize = SIZEOF_NODETYPE + sizeof(varNodeType);
- if ((p = (nodeType*) malloc(nodeSize)) == NULL)
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(varNodeType);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
yyerror(NULL, NULL, "Out of memory");
/* copy information */
p->type = typeVar;
- p->u.var.nm = strdupx(nm);
+ p->u.var.nm = strdup(nm);
return p;
}
@@ -1743,39 +1779,67 @@ nodeType *expr_var(char *nm)
nodeType *expr_fun(char *fname, nodeType *op)
{
nodeType *p = NULL;
- size_t nodeSize;
-
/* allocate node */
- nodeSize = SIZEOF_NODETYPE + sizeof(funNodeType);
- if ((p = (nodeType*) malloc(nodeSize)) == NULL)
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(funNodeType);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
yyerror(NULL, NULL, "Out of memory");
/* copy information */
p->type = typeFun;
- p->u.fun.name = strdupx(fname);
+ p->u.fun.name = strdup(fname);
p->u.fun.op = op;
return p;
}
-nodeType *expr_opr(int oper, int nops, ...)
+nodeType *expr_fun1c(char *fname, nodeType *op, double value)
{
- va_list ap;
nodeType *p = NULL;
- size_t nodeSize;
- int i;
+ /* allocate node */
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(fun1cNodeType);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
+ yyerror(NULL, NULL, "Out of memory");
+ /* copy information */
+ p->type = typeFun1c;
+ p->u.fun1c.name = strdup(fname);
+ p->u.fun1c.op = op;
+ p->u.fun1c.value = value;
+
+ return p;
+}
+
+nodeType *expr_com(const char *cname, char *vname)
+{
+ nodeType *p = NULL;
/* allocate node */
- nodeSize = SIZEOF_NODETYPE + sizeof(oprNodeType) + (nops - 1)*sizeof(nodeType*);
- if ((p = (nodeType*) malloc(nodeSize)) == NULL)
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(comNodeType);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
+ yyerror(NULL, NULL, "Out of memory");
+
+ /* copy information */
+ p->type = typeCom;
+ p->u.com.cname = strdup(cname);
+ p->u.com.vname = strdup(vname);
+
+ return p;
+}
+
+nodeType *expr_opr(int oper, int nops, ...)
+{
+ nodeType *p = NULL;
+ /* allocate node */
+ size_t nodeSize = SIZEOF_NODETYPE + sizeof(oprNodeType) + (nops - 1)*sizeof(nodeType*);
+ if ( (p = (nodeType*) Calloc(1, nodeSize)) == NULL )
yyerror(NULL, NULL, "Out of memory");
/* copy information */
p->type = typeOpr;
p->u.opr.oper = oper;
p->u.opr.nops = nops;
+ va_list ap;
va_start(ap, nops);
- for (i = 0; i < nops; i++)
+ for ( int i = 0; i < nops; i++ )
p->u.opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
@@ -1784,22 +1848,23 @@ nodeType *expr_opr(int oper, int nops, ...)
void freeNode(nodeType *p)
{
- int i;
-
- if ( ! p ) return;
+ if ( !p ) return;
- if (p->type == typeOpr)
+ if ( p->type == typeOpr )
{
- for (i = 0; i < p->u.opr.nops; i++)
+ for ( int i = 0; i < p->u.opr.nops; i++ )
freeNode(p->u.opr.op[i]);
}
- free (p);
+ Free(p);
}
+int CDO_parser_errorno = 0;
+
void yyerror(void *parse_arg, void *scanner, const char *errstr)
{
- fprintf(stdout, "%s!\n", errstr);
+ fprintf(stderr, "%s!\n", errstr);
+ CDO_parser_errorno = -1;
}
/*
int main(void)
@@ -1809,7 +1874,7 @@ int main(void)
void *scanner;
int yy_scan_string(const char *str, void *scanner);
- parse_parm_t parse_arg;
+ parse_param_t parse_arg;
printf("%s\n", fexpr);
diff --git a/src/expr_yacc.h b/src/expr_yacc.h
index 5705f8a..0b18e1b 100644
--- a/src/expr_yacc.h
+++ b/src/expr_yacc.h
@@ -48,33 +48,41 @@ extern int yydebug;
CONSTANT = 258,
VARIABLE = 259,
FUNCTION = 260,
- LEG = 261,
- GE = 262,
- LE = 263,
- EQ = 264,
- NE = 265,
- AND = 266,
- OR = 267,
- UMINUS = 268
+ REMOVE = 261,
+ PRINT = 262,
+ AND = 263,
+ OR = 264,
+ LEG = 265,
+ GE = 266,
+ LE = 267,
+ EQ = 268,
+ NE = 269,
+ GT = 270,
+ LT = 271,
+ UMINUS = 272
};
#endif
/* Tokens. */
#define CONSTANT 258
#define VARIABLE 259
#define FUNCTION 260
-#define LEG 261
-#define GE 262
-#define LE 263
-#define EQ 264
-#define NE 265
-#define AND 266
-#define OR 267
-#define UMINUS 268
+#define REMOVE 261
+#define PRINT 262
+#define AND 263
+#define OR 264
+#define LEG 265
+#define GE 266
+#define LE 267
+#define EQ 268
+#define NE 269
+#define GT 270
+#define LT 271
+#define UMINUS 272
/* Value type. */
-int yyparse (parse_parm_t *parse_arg, void *scanner);
+int yyparse (parse_param_t *parse_arg, void *scanner);
#endif /* !YY_YY_EXPR_YACC_H_INCLUDED */
diff --git a/src/features.c b/src/features.c
index 4b91b56..120a601 100644
--- a/src/features.c
+++ b/src/features.c
@@ -90,6 +90,9 @@ void printFeatures(void)
#if defined(HAVE_LIBFFTW3)
fprintf(stderr, " FFTW3");
#endif
+#if defined(HAVE_LIBCMOR)
+ fprintf(stderr, " CMOR");
+#endif
#if defined(__AVX2__)
fprintf(stderr, " AVX2");
#elif defined(__AVX__)
diff --git a/src/field.c b/src/field.c
index 9a81cae..74eaa3f 100644
--- a/src/field.c
+++ b/src/field.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -23,59 +23,28 @@
double crps_det_integrate(double *a, const double d, const size_t n);
-double _FADD_(const double x, const double y, const double missval1, const double missval2)
-{
- return FADD(x,y);
-}
-
-double _FSUB_(const double x, const double y, const double missval1, const double missval2)
-{
- return FSUB(x, y);
-}
-
-double _FMUL_(const double x, const double y, const double missval1, const double missval2)
-{
- return FMUL(x, y);
-}
-
-double _FDIV_(const double x, const double y, const double missval1, const double missval2)
-{
- return FDIV(x, y);
-}
-
-double _FPOW_(const double x, const double y, const double missval1, const double missval2)
-{
- return FPOW(x, y);
-}
-
-double _FSQRT_(const double x, const double missval1)
-{
- return FSQRT(x);
-}
-
-
-double fldfun(field_t field, const int function)
+double fldfun(field_t field, int function)
{
double rval = 0;
- // Why is this not a switch-case statement?
- if ( function == func_min ) rval = fldmin(field);
- else if ( function == func_max ) rval = fldmax(field);
- else if ( function == func_sum ) rval = fldsum(field);
- else if ( function == func_mean ) rval = fldmean(field);
- else if ( function == func_avg ) rval = fldavg(field);
- else if ( function == func_std ) rval = fldstd(field);
- else if ( function == func_std1 ) rval = fldstd1(field);
- else if ( function == func_var ) rval = fldvar(field);
- else if ( function == func_var1 ) rval = fldvar1(field);
+ switch (function)
+ {
+ case func_min: rval = fldmin(field); break;
+ case func_max: rval = fldmax(field); break;
+ case func_sum: rval = fldsum(field); break;
+ case func_mean: rval = fldmean(field); break;
+ case func_avg: rval = fldavg(field); break;
+ case func_std: rval = fldstd(field); break;
+ case func_std1: rval = fldstd1(field); break;
+ case func_var: rval = fldvar(field); break;
+ case func_var1: rval = fldvar1(field); break;
+ case func_crps: rval = fldcrps(field); break;
+ case func_brs: rval = fldbrs(field); break;
+ case func_rank: rval = fldrank(field); break;
+ case func_roc: rval = fldroc(field); break;
+ default: cdoAbort("%s: function %d not implemented!", __func__, function);
+ }
- else if ( function == func_crps ) rval = fldcrps(field);
- else if ( function == func_brs ) rval = fldbrs(field);
-
- else if ( function == func_rank ) rval = fldrank(field);
- else if ( function == func_roc ) rval = fldroc(field);
- else cdoAbort("%s: function %d not implemented!", __func__, function);
-
return rval;
}
@@ -91,7 +60,7 @@ double fldrank(field_t field)
const size_t len = field.size-1;
size_t j;
- if ( nmiss ) return(missval);
+ if ( nmiss ) return missval;
sort_iter_single(len,array, 1);
@@ -136,8 +105,8 @@ double fldcrps(field_t field)
double fldbrs(field_t field)
{
- const size_t len = field.size;
const int nmiss = field.nmiss;
+ const size_t len = field.size;
double *array = field.ptr;
const double missval = field.missval;
@@ -169,17 +138,17 @@ double fldbrs(field_t field)
double fldmin(field_t field)
{
- size_t i;
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval = field.missval;
- const double *restrict array = field.ptr;
- double rmin = 0;
+ const double *restrict array = field.ptr;
+ double rmin = DBL_MAX;
- if ( nmiss > 0 )
+ assert(array!=NULL);
+
+ if ( nmiss )
{
- rmin = DBL_MAX;
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array[i], missval) )
if ( array[i] < rmin ) rmin = array[i];
@@ -188,29 +157,28 @@ double fldmin(field_t field)
}
else
{
- rmin = array[0];
//#pragma simd reduction(min:rmin)
- for ( i = 1; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( array[i] < rmin ) rmin = array[i];
}
- return (rmin);
+ return rmin;
}
double fldmax(field_t field)
{
- size_t i;
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval = field.missval;
- double *array = field.ptr;
- double rmax = 0;
+ const double *restrict array = field.ptr;
+ double rmax = -DBL_MAX;
+
+ assert(array!=NULL);
if ( nmiss > 0 )
{
- rmax = -DBL_MAX;
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array[i], missval) )
if ( array[i] > rmax ) rmax = array[i];
@@ -219,28 +187,29 @@ double fldmax(field_t field)
}
else
{
- rmax = array[0];
- for ( i = 1; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( array[i] > rmax ) rmax = array[i];
}
- return (rmax);
+ return rmax;
}
double fldsum(field_t field)
{
- size_t i;
- size_t nvals = 0;
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval = field.missval;
- double *array = field.ptr;
+ const double *restrict array = field.ptr;
double rsum = 0;
- if ( nmiss > 0 )
+ assert(array!=NULL);
+
+ if ( nmiss )
{
- for ( i = 0; i < len; i++ )
+ size_t nvals = 0;
+
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array[i], missval) )
{
rsum += array[i];
@@ -251,28 +220,30 @@ double fldsum(field_t field)
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
rsum += array[i];
}
- return (rsum);
+ return rsum;
}
double fldmean(field_t field)
{
- size_t i;
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval1 = field.missval;
const double missval2 = field.missval;
- double *array = field.ptr;
- double *w = field.weight;
- double rsum = 0, rsumw = 0, ravg = 0;
+ const double *restrict array = field.ptr;
+ const double *restrict w = field.weight;
+ double rsum = 0, rsumw = 0;
- if ( nmiss > 0 )
+ assert(array!=NULL);
+ assert(w!=NULL);
+
+ if ( nmiss )
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array[i], missval1) && !DBL_IS_EQUAL(w[i], missval1) )
{
rsum += w[i] * array[i];
@@ -281,120 +252,125 @@ double fldmean(field_t field)
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
{
rsum += w[i] * array[i];
rsumw += w[i];
}
}
- ravg = DIV(rsum, rsumw);
+ double ravg = DIVMN(rsum, rsumw);
- return (ravg);
+ return ravg;
}
double fldavg(field_t field)
{
- size_t i;
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval1 = field.missval;
const double missval2 = field.missval;
- double *array = field.ptr;
- double *w = field.weight;
- double rsum = 0, rsumw = 0, ravg = 0;
+ const double *restrict array = field.ptr;
+ const double *restrict w = field.weight;
+ double rsum = 0, rsumw = 0;
- if ( nmiss > 0 )
+ assert(array!=NULL);
+ assert(w!=NULL);
+
+ if ( nmiss )
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(w[i], missval1) )
{
- rsum = ADD(rsum, MUL(w[i], array[i]));
- rsumw = ADD(rsumw, w[i]);
+ rsum = ADDMN(rsum, MULMN(w[i], array[i]));
+ rsumw = ADDMN(rsumw, w[i]);
}
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
{
rsum += w[i] * array[i];
rsumw += w[i];
}
}
- ravg = DIV(rsum, rsumw);
+ double ravg = DIVMN(rsum, rsumw);
- return (ravg);
+ return ravg;
}
static
void prevarsum(const double *restrict array, const double *restrict w, size_t len, int nmiss,
- double missval, double *restrict rsum, double *restrict rsumw, double *restrict rsumq, double *restrict rsumwq)
+ double missval, double *rsum, double *rsumw, double *rsumq, double *rsumwq)
{
- size_t i;
- *rsum = *rsumw = 0;
- *rsumq = *rsumwq = 0;
+ assert(array!=NULL);
+ assert(w!=NULL);
- if ( nmiss > 0 )
+ double xsum = 0, xsumw = 0;
+ double xsumq = 0, xsumwq = 0;
+
+ if ( nmiss )
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array[i], missval) && !DBL_IS_EQUAL(w[i], missval) )
{
- *rsum += w[i] * array[i];
- *rsumq += w[i] * array[i] * array[i];
- *rsumw += w[i];
- *rsumwq += w[i] * w[i];
+ xsum += w[i] * array[i];
+ xsumq += w[i] * array[i] * array[i];
+ xsumw += w[i];
+ xsumwq += w[i] * w[i];
}
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( size_t i = 0; i < len; i++ )
{
- *rsum += w[i] * array[i];
- *rsumq += w[i] * array[i] * array[i];
- *rsumw += w[i];
- *rsumwq += w[i] * w[i];
+ xsum += w[i] * array[i];
+ xsumq += w[i] * array[i] * array[i];
+ xsumw += w[i];
+ xsumwq += w[i] * w[i];
}
}
+
+ *rsum = xsum;
+ *rsumq = xsumq;
+ *rsumw = xsumw;
+ *rsumwq = xsumwq;
}
double fldvar(field_t field)
{
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval = field.missval;
- double *array = field.ptr;
- double *w = field.weight;
double rsum, rsumw;
double rsumq, rsumwq;
- prevarsum(array, w, len, nmiss, missval, &rsum, &rsumw, &rsumq, &rsumwq);
+ prevarsum(field.ptr, field.weight, len, nmiss, missval, &rsum, &rsumw, &rsumq, &rsumwq);
double rvar = IS_NOT_EQUAL(rsumw, 0) ? (rsumq*rsumw - rsum*rsum) / (rsumw*rsumw) : missval;
if ( rvar < 0 && rvar > -1.e-5 ) rvar = 0;
- return (rvar);
+ return rvar;
}
double fldvar1(field_t field)
{
+ const int nmiss = field.nmiss > 0;
const size_t len = field.size;
- const int nmiss = field.nmiss;
const double missval = field.missval;
- double *array = field.ptr;
- double *w = field.weight;
double rsum, rsumw;
double rsumq, rsumwq;
- prevarsum(array, w, len, nmiss, missval, &rsum, &rsumw, &rsumq, &rsumwq);
+ prevarsum(field.ptr, field.weight, len, nmiss, missval, &rsum, &rsumw, &rsumq, &rsumwq);
double rvar = (rsumw*rsumw > rsumwq) ? (rsumq*rsumw - rsum*rsum) / (rsumw*rsumw - rsumwq) : missval;
if ( rvar < 0 && rvar > -1.e-5 ) rvar = 0;
- return (rvar);
+ return rvar;
}
@@ -453,9 +429,9 @@ void fldrms(field_t field, field_t field2, field_t *field3)
for ( i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(w[i], missval1) )
{
- rsum = ADD(rsum, MUL(w[i], MUL(SUB(array2[i], array1[i]),
- SUB(array2[i], array1[i]))));
- rsumw = ADD(rsumw, w[i]);
+ rsum = ADDMN(rsum, MULMN(w[i], MULMN( SUBMN(array2[i], array1[i]),
+ SUBMN(array2[i], array1[i]))));
+ rsumw = ADDMN(rsumw, w[i]);
}
}
/*
@@ -469,7 +445,7 @@ void fldrms(field_t field, field_t field2, field_t *field3)
}
*/
- ravg = SQRT(DIV(rsum, rsumw));
+ ravg = SQRTMN( DIVMN(rsum, rsumw));
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
@@ -507,9 +483,9 @@ void varrms(field_t field, field_t field2, field_t *field3)
for ( i = 0; i < len; i++ )
/* if ( !DBL_IS_EQUAL(w[i], missval1) ) */
{
- rsum = ADD(rsum, MUL(w[i], MUL(SUB(array2[k*len+i], array1[k*len+i]),
- SUB(array2[k*len+i], array1[k*len+i]))));
- rsumw = ADD(rsumw, w[i]);
+ rsum = ADDMN(rsum, MULMN(w[i], MULMN( SUBMN(array2[k*len+i], array1[k*len+i]),
+ SUBMN(array2[k*len+i], array1[k*len+i]))));
+ rsumw = ADDMN(rsumw, w[i]);
}
}
/*
@@ -523,7 +499,7 @@ void varrms(field_t field, field_t field2, field_t *field3)
}
*/
- ravg = SQRT(DIV(rsum, rsumw));
+ ravg = SQRTMN( DIVMN(rsum, rsumw));
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
@@ -613,19 +589,19 @@ double crps_det_integrate(double *a, const double d, const size_t n)
#if defined(_OPENMP)
#pragma omp parallel for if ( n>10000 ) shared(a) private(i) \
reduction(+:area) schedule(static,10000)
-#endif /* **************************** */
- for ( i=1; i<n; i++ ) { /* INTEGRATE CURVE AREA */
- if ( a[i] < d ) /* left of heavyside */
+#endif /* **************************** */
+ for ( i=1; i<n; i++ ) { /* INTEGRATE CURVE AREA */
+ if ( a[i] < d ) /* left of heavyside */
area += (a[i]-a[i-1])*(double)i*i/n/n; /* */
- else if ( a[i-1] > d ) /* right of heavyside */
- area += (a[i]-a[i-1])*(1.-(double)i/n)*(1.-(double)i/n); /* */
- else if ( a[i-1] < d && a[i] > d ) { /* hitting jump pf heavyside */
+ else if ( a[i-1] > d ) /* right of heavyside */
+ area += (a[i]-a[i-1])*(1.-(double)i/n)*(1.-(double)i/n); /* */
+ else if ( a[i-1] < d && a[i] > d ) { /* hitting jump pf heavyside */
area += (d-a[i-1]) * (double)i*i/n/n; /* (occurs exactly once!) */
- area += (a[i]-d) * (1.-(double)i/n)*(1.-(double)i/n); /* **************************** */
+ area += (a[i]-d) * (1.-(double)i/n)*(1.-(double)i/n); /* **************************** */
}
}
- return(area);
+ return area;
}
diff --git a/src/field.h b/src/field.h
index 9f6f8d8..6c07c28 100644
--- a/src/field.h
+++ b/src/field.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,9 @@
#ifndef _FIELD_H
#define _FIELD_H
+#include <math.h>
+#include "compare.h"
+
double var_to_std(double rvar, double missval);
enum field_flag {
@@ -25,46 +28,70 @@ enum field_flag {
FIELD_PTR = 2,
FIELD_WGT = 4,
FIELD_PTR2 = 8,
- FIELD_ALL = FIELD_PTR | FIELD_WGT
+ FIELD_FLT = 16,
+ FIELD_ALL = FIELD_PTR | FIELD_WGT
};
-#define FADD(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)+(y))
-#define FSUB(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)-(y))
-#define FMUL(x,y) (DBL_IS_EQUAL((x),0.)||IS_EQUAL((y),0.) ? 0 : DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
-#define FDIV(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) || DBL_IS_EQUAL((y),0.) ? missval1 : (x)/(y))
-#define FPOW(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : pow((x),(y)))
-#define FSQRT(x) (DBL_IS_EQUAL((x),missval1) || (x)<0 ? missval1 : sqrt(x))
+#define MADDMN(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)+(y))
+#define MSUBMN(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)-(y))
+#define MMULMN(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
+#define MDIVMN(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) || DBL_IS_EQUAL((y),0.) ? missval1 : (x)/(y))
+#define MPOWMN(x,y) (DBL_IS_EQUAL((x),missval1) || DBL_IS_EQUAL((y),missval2) ? missval1 : pow((x),(y)))
+#define MSQRTMN(x) (DBL_IS_EQUAL((x),missval1) || (x)<0 ? missval1 : sqrt(x))
+
+
+#define ADD(x,y) ((x)+(y))
+#define SUB(x,y) ((x)-(y))
+#define MUL(x,y) ((x)*(y))
+#define DIV(x,y) (IS_EQUAL((y),0.) ? missval1 : (x)/(y))
+#define POW(x,y) pow((x),(y))
+#define SQRT(x) sqrt(x)
+
+#define ADDM(x,y) (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)+(y))
+#define SUBM(x,y) (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)-(y))
+#define MULM(x,y) (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : (x)*(y))
+#define DIVM(x,y) (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) || IS_EQUAL((y),0.) ? missval1 : (x)/(y))
+#define POWM(x,y) (IS_EQUAL((x),missval1) || IS_EQUAL((y),missval2) ? missval1 : pow((x),(y)))
+#define SQRTM(x) (IS_EQUAL((x),missval1) || (x)<0 ? missval1 : sqrt(x))
-double _FADD_(const double x, const double y, const double missval1, const double missval2);
-double _FSUB_(const double x, const double y, const double missval1, const double missval2);
-double _FMUL_(const double x, const double y, const double missval1, const double missval2);
-double _FDIV_(const double x, const double y, const double missval1, const double missval2);
-double _FPOW_(const double x, const double y, const double missval1, const double missval2);
-double _FSQRT_(const double x, const double missval1);
+#define ADDMN(x,y) FADDMN(x, y, missval1, missval2)
+#define SUBMN(x,y) FSUBMN(x, y, missval1, missval2)
+#define MULMN(x,y) FMULMN(x, y, missval1, missval2)
+#define DIVMN(x,y) FDIVMN(x, y, missval1, missval2)
+#define POWMN(x,y) FPOWMN(x, y, missval1, missval2)
+#define SQRTMN(x) FSQRTMN(x, missval1)
-#define ADD(x,y) _FADD_(x, y, missval1, missval2)
-#define SUB(x,y) _FSUB_(x, y, missval1, missval2)
-#define MUL(x,y) _FMUL_(x, y, missval1, missval2)
-#define DIV(x,y) _FDIV_(x, y, missval1, missval2)
-#define POW(x,y) _FPOW_(x, y, missval1, missval2)
-#define SQRT(x) _FSQRT_(x, missval1)
+static inline
+double FADDMN(double x, double y, double missval1, double missval2) { return MADDMN(x,y);}
+static inline
+double FSUBMN(double x, double y, double missval1, double missval2) { return MSUBMN(x, y);}
+static inline
+double FMULMN(double x, double y, double missval1, double missval2) { return MMULMN(x, y);}
+static inline
+double FDIVMN(double x, double y, double missval1, double missval2) { return MDIVMN(x, y);}
+static inline
+double FPOWMN(double x, double y, double missval1, double missval2) { return MPOWMN(x, y);}
+static inline
+double FSQRTMN(double x, double missval1) { return MSQRTMN(x);}
typedef struct {
int nwpv; // number of words per value; real:1 complex:2
+ int memtype;
int grid;
int zaxis;
size_t size;
- int nsamp;
- int nmiss;
- int nmiss2;
+ size_t nsamp;
+ size_t nmiss;
+ size_t nmiss2;
double missval;
double *weight;
double *ptr;
- double *ptr2;
+ float *ptrf;
+ void *ptr2;
}
field_t;
@@ -78,7 +105,7 @@ void field_free(field_t **field, const int vlistID);
/* field.c */
-double fldfun(field_t field, const int function);
+double fldfun(field_t field, int function);
double fldmin(field_t field);
double fldmax(field_t field);
double fldsum(field_t field);
@@ -147,8 +174,9 @@ void farround(field_t *field);
/* field2.c */
-void farfun(field_t *field1, field_t field2, const int function);
+void farfun(field_t *field1, field_t field2, int function);
+void farcpy(field_t *field1, field_t field2);
void faradd(field_t *field1, field_t field2);
void farsum(field_t *field1, field_t field2);
void farsumw(field_t *field1, field_t field2, double w);
@@ -160,16 +188,14 @@ void farmul(field_t *field1, field_t field2);
void fardiv(field_t *field1, field_t field2);
void farmin(field_t *field1, field_t field2);
void farmax(field_t *field1, field_t field2);
-void farvar(field_t *field1, field_t field2, field_t field3, const double divisor);
-void farstd(field_t *field1, field_t field2, field_t field3, const double divisor);
-void farcvar(field_t *field1, field_t field2, const double rconst1, const double divisor);
-void farcstd(field_t *field1, field_t field2, const double rconst1, const double divisor);
+void farvar(field_t *field1, field_t field2, field_t field3, int divisor);
+void farstd(field_t *field1, field_t field2, field_t field3, int divisor);
+void farcvar(field_t *field1, field_t field2, int nsets, int divisor);
+void farcstd(field_t *field1, field_t field2, int nsets, int divisor);
void farmoq(field_t *field1, field_t field2);
void farmoqw(field_t *field1, field_t field2, double w);
void faratan2(field_t *field1, field_t field2);
-/* RQ */
void farcount(field_t *field1, field_t field2);
-/* QR */
#endif /* _FIELD_H */
diff --git a/src/field2.c b/src/field2.c
index 40b871d..30a2458 100644
--- a/src/field2.c
+++ b/src/field2.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -15,132 +15,159 @@
GNU General Public License for more details.
*/
+#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
-#include <cdi.h>
-#if 0
-#ifdef __SSE2__
-#include <emmintrin.h>
-#endif
-#endif
-void farfun(field_t *field1, field_t field2, const int function)
+void farfun(field_t *field1, field_t field2, int function)
{
- if ( function == func_add ) faradd(field1, field2);
- else if ( function == func_min ) farmin(field1, field2);
- else if ( function == func_max ) farmax(field1, field2);
- else if ( function == func_sum ) farsum(field1, field2);
- else if ( function == func_mean ) farsum(field1, field2);
- else if ( function == func_avg ) faradd(field1, field2);
- else if ( function == func_sub ) farsub(field1, field2);
- else if ( function == func_mul ) farmul(field1, field2);
- else if ( function == func_div ) fardiv(field1, field2);
- else if ( function == func_atan2 ) faratan2(field1, field2);
- else cdoAbort("%s: function %d not implemented!", __func__, function);
+ switch (function)
+ {
+ case func_add: faradd(field1, field2); break;
+ case func_min: farmin(field1, field2); break;
+ case func_max: farmax(field1, field2); break;
+ case func_sum: farsum(field1, field2); break;
+ case func_mean: farsum(field1, field2); break;
+ case func_avg: faradd(field1, field2); break;
+ case func_sub: farsub(field1, field2); break;
+ case func_mul: farmul(field1, field2); break;
+ case func_div: fardiv(field1, field2); break;
+ case func_atan2: faratan2(field1, field2); break;
+ default: cdoAbort("%s: function %d not implemented!", __func__, function);
+ }
}
static
-void arradd(const size_t n, double * restrict a, const double * restrict b)
+int farsetnmiss(int len, double *restrict array, double missval)
{
- // SSE2 version is 15% faster than the original loop (tested with gcc47)
-#if 0
- //#ifdef __SSE2__ /*__SSE2__*/ // bug in this code!!!
- size_t i;
- const size_t residual = n % 8;
- const size_t ofs = n - residual;
+ int nmiss = 0;
- __m128d *av = (__m128d *) a; // assume 16-byte aligned
- __m128d *bv = (__m128d *) b; // assume 16-byte aligned
- for ( i = 0; i < n/2; i+=4 )
+ if ( DBL_IS_NAN(missval) )
{
- av[i ] = _mm_add_pd(av[i ], bv[i ]);
- av[i+1] = _mm_add_pd(av[i+1], bv[i+1]);
- av[i+2] = _mm_add_pd(av[i+2], bv[i+2]);
- av[i+3] = _mm_add_pd(av[i+3], bv[i+3]);
+ for ( int i = 0; i < len; i++ )
+ if ( DBL_IS_EQUAL(array[i], missval) || array[i] < 0 )
+ {
+ array[i] = missval;
+ nmiss++;
+ }
+ }
+ else
+ {
+ for ( int i = 0; i < len; i++ )
+ if ( IS_EQUAL(array[i], missval) || array[i] < 0 )
+ {
+ array[i] = missval;
+ nmiss++;
+ }
}
- printf("residual, ofs, n %ld %ld %ld\n", residual, ofs, n);
- for ( i = 0; i < residual; i++ ) a[ofs+i] += b[ofs+i];
-
-#else
-
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) shared(a,b)
-#endif
- for ( size_t i = 0; i < n; i++ ) a[i] += b[i];
-#endif
+ return nmiss;
}
-static
-void arraddw(const size_t n, double * restrict a, const double * restrict b, double w)
+
+void farcpy(field_t *field1, field_t field2)
{
-#if defined(_OPENMP)
-#pragma omp parallel for default(none) shared(a,b,w)
-#endif
- for ( size_t i = 0; i < n; i++ ) a[i] += w*b[i];
+ int nwpv = field1->nwpv;
+ int gridsize1 = field1->size;
+ int gridsize2 = field2.size;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ const float *restrict array2f = field2.ptrf;
+
+ if ( gridsize1 == 0 ) gridsize1 = gridInqSize(field1->grid);
+ if ( gridsize2 == 0 ) gridsize2 = gridInqSize(field2.grid);
+
+ if ( nwpv != 2 ) nwpv = 1;
+
+ int len = nwpv*gridsize1;
+
+ if ( len != nwpv*gridsize2 )
+ cdoAbort("Fields have different gridsize (%s)", __func__);
+
+ if ( field2.memtype == MEMTYPE_FLOAT )
+ for ( int i = 0; i < len; i++ ) array1[i] = array2f[i];
+ else
+ for ( int i = 0; i < len; i++ ) array1[i] = array2[i];
}
void faradd(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ const float *restrict array2f = field2.ptrf;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
- array1[i] = ADD(array1[i], array2[i]);
+ for ( int i = 0; i < len; i++ )
+ array1[i] = ADDMN(array1[i], array2[i]);
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- arradd(len, array1, array2);
+ if ( field2.memtype == MEMTYPE_FLOAT )
+ {
+ for ( int i = 0; i < len; i++ ) array1[i] += array2f[i];
+ }
+ else
+ {
+ //#if defined(_OPENMP)
+ //#pragma omp parallel for default(none) shared(a,b)
+ //#endif
+ for ( int i = 0; i < len; i++ ) array1[i] += array2[i];
+ }
}
}
void farsum(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int gridsize1 = field1->size;
+ int gridsize2 = field2.size;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ const float *restrict array2f = field2.ptrf;
+
+ if ( gridsize1 == 0 ) gridsize1 = gridInqSize(field1->grid);
+ if ( gridsize2 == 0 ) gridsize2 = gridInqSize(field2.grid);
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridsize1;
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != nwpv*gridsize2 )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
{
if ( !DBL_IS_EQUAL(array1[i], missval1) )
@@ -150,39 +177,45 @@ void farsum(field_t *field1, field_t field2)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- arradd(len, array1, array2);
+ if ( field2.memtype == MEMTYPE_FLOAT )
+ {
+ for ( int i = 0; i < len; i++ ) array1[i] += array2f[i];
+ }
+ else
+ {
+ for ( int i = 0; i < len; i++ ) array1[i] += array2[i];
+ }
}
}
void farsumw(field_t *field1, field_t field2, double w)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
{
if ( !DBL_IS_EQUAL(array1[i], missval1) )
@@ -192,12 +225,15 @@ void farsumw(field_t *field1, field_t field2, double w)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- arraddw(len, array1, array2, w);
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) shared(array1,array2,w,len)
+#endif
+ for ( int i = 0; i < len; i++ ) array1[i] += w*array2[i];
}
}
@@ -211,15 +247,14 @@ void farsumw(field_t *field1, field_t field2, double w)
*/
void farsumtr(field_t *occur, field_t field, const double refval)
{
- size_t i, len;
double omissval = occur->missval;
- double *oarray = occur->ptr;
double fmissval = field.missval;
- double *farray = field.ptr;
+ double *restrict oarray = occur->ptr;
+ double *restrict farray = field.ptr;
- len = (size_t) gridInqSize(occur->grid);
+ int len = gridInqSize(occur->grid);
- if ( len != (size_t) gridInqSize(field.grid) )
+ if ( len != gridInqSize(field.grid) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( occur->nmiss > 0 || field.nmiss > 0 )
@@ -227,7 +262,7 @@ void farsumtr(field_t *occur, field_t field, const double refval)
#if defined(_OPENMP)
#pragma omp parallel for default(shared) schedule(static)
#endif
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(farray[i], fmissval) )
{
if ( !DBL_IS_EQUAL(oarray[i], omissval) )
@@ -242,7 +277,7 @@ void farsumtr(field_t *occur, field_t field, const double refval)
}
occur->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(oarray[i], omissval) ) occur->nmiss++;
}
else
@@ -250,7 +285,7 @@ void farsumtr(field_t *occur, field_t field, const double refval)
#if defined(_OPENMP)
#pragma omp parallel for default(shared)
#endif
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
oarray[i] = (DBL_IS_EQUAL(farray[i], refval)) ? 0.0 : oarray[i] + 1.0;
}
}
@@ -258,27 +293,27 @@ void farsumtr(field_t *occur, field_t field, const double refval)
void farsumq(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ const float *restrict array2f = field2.ptrf;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
{
if ( !DBL_IS_EQUAL(array1[i], missval1) )
@@ -288,40 +323,45 @@ void farsumq(field_t *field1, field_t field2)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
- array1[i] += array2[i]*array2[i];
+ if ( field2.memtype == MEMTYPE_FLOAT )
+ {
+ for ( int i = 0; i < len; i++ ) array1[i] += ((double)array2f[i])*array2f[i];
+ }
+ else
+ {
+ for ( int i = 0; i < len; i++ ) array1[i] += array2[i]*array2[i];
+ }
}
}
void farsumqw(field_t *field1, field_t field2, double w)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
{
if ( !DBL_IS_EQUAL(array1[i], missval1) )
@@ -331,12 +371,12 @@ void farsumqw(field_t *field1, field_t field2, double w)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] += w*array2[i]*array2[i];
}
}
@@ -344,36 +384,35 @@ void farsumqw(field_t *field1, field_t field2, double w)
void farsub(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
- array1[i] = SUB(array1[i], array2[i]);
+ for ( int i = 0; i < len; i++ )
+ array1[i] = SUBMN(array1[i], array2[i]);
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] -= array2[i];
}
}
@@ -381,36 +420,35 @@ void farsub(field_t *field1, field_t field2)
void farmul(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
- array1[i] = MUL(array1[i], array2[i]);
+ for ( int i = 0; i < len; i++ )
+ array1[i] = MULMN(array1[i], array2[i]);
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] *= array2[i];
}
}
@@ -418,81 +456,78 @@ void farmul(field_t *field1, field_t field2)
void fardiv(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const double missval2 = field2.missval;
double *array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
- for ( i = 0; i < len; i++ )
- array1[i] = DIV(array1[i], array2[i]);
+ for ( int i = 0; i < len; i++ )
+ array1[i] = DIVMN(array1[i], array2[i]);
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
void faratan2(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] = DBL_IS_EQUAL(array1[i],missval1) || DBL_IS_EQUAL(array2[i],missval2) ? missval1 : atan2(array1[i], array2[i]);
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
void farmin(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
{
array1[i] = DBL_IS_EQUAL(array2[i], missval2) ? array1[i] :
DBL_IS_EQUAL(array1[i], missval1) ? array2[i] :
@@ -500,12 +535,12 @@ void farmin(field_t *field1, field_t field2)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] = MIN(array1[i], array2[i]);
}
}
@@ -513,27 +548,26 @@ void farmin(field_t *field1, field_t field2)
void farmax(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
{
array1[i] = DBL_IS_EQUAL(array2[i], missval2) ? array1[i] :
DBL_IS_EQUAL(array1[i], missval1) ? array2[i] :
@@ -541,362 +575,206 @@ void farmax(field_t *field1, field_t field2)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] = MAX(array1[i], array2[i]);
}
}
-// not used
-void farvar0(field_t *field1, field_t field2, field_t field3)
+
+void farvar(field_t *field1, field_t field2, field_t field3, int divisor)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
- const int nmiss3 = field3.nmiss;
- const double missval3 = field3.missval;
- double *array3 = field3.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ const double *restrict array3 = field3.ptr;
+ double temp;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
- if ( nmiss1 > 0 || nmiss2 > 0 || nmiss3 > 0 )
+ if ( (nmiss1 || nmiss2) /*&& (DBL_IS_NAN(missval1) || DBL_IS_NAN(missval2))*/ )
{
- for ( i = 0; i < len; i++ )
- {
- if ( !DBL_IS_EQUAL(array1[i], missval1) && !DBL_IS_EQUAL(array2[i], missval2) && !DBL_IS_EQUAL(array3[i], missval3) )
- {
- array1[i] = array2[i]*array3[i] - (array1[i]*array3[i])*(array1[i]*array3[i]);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
- }
- else
- array1[i] = missval1;
- }
+ for ( int i = 0; i < len; i++ )
+ {
+ temp = DIV( MULMN(array1[i], array1[i]), array3[i]);
+ array1[i] = DIV( SUBMN(array2[i], temp), array3[i]-divisor);
+ if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
+ }
}
else
{
- for ( i = 0; i < len; i++ )
- {
- array1[i] = array2[i]*array3[i] - (array1[i]*array3[i])*(array1[i]*array3[i]);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
- }
+ for ( int i = 0; i < len; i++ )
+ {
+ temp = DIV( MUL(array1[i], array1[i]), array3[i]);
+ array1[i] = DIV( SUB(array2[i], temp), array3[i]-divisor);
+ if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
+ }
}
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
+ field1->nmiss = farsetnmiss(len, array1, missval1);
}
-void farvar(field_t *field1, field_t field2, field_t field3, const double divisor)
+void farstd(field_t *field1, field_t field2, field_t field3, int divisor)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
- double *array3 = field3.ptr;
- double temp;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ double missval1 = field1->missval;
+ double *restrict array1 = field1->ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
- cdoAbort("Fields have different gridsize (%s)", __func__);
-
- for ( i = 0; i < len; i++ )
- {
- temp = DIV( MUL(array1[i], array1[i]), array3[i]);
- array1[i] = DIV( SUB(array2[i], temp), array3[i]-divisor);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
- }
-
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
-}
-
-// not used
-void farstd0(field_t *field1, field_t field2, field_t field3)
-{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- int grid2 = field2.grid;
-
- if ( nwpv != 2 ) nwpv = 1;
-
- len = (size_t) (nwpv*gridInqSize(grid1));
-
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
- cdoAbort("Fields have different gridsize (%s)", __func__);
-
- farvar0(field1, field2, field3);
-
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
- else
- {
- array1[i] = IS_NOT_EQUAL(array1[i], 0) ? sqrt(array1[i]) : 0;
- }
-}
-
-
-void farstd(field_t *field1, field_t field2, field_t field3, const double divisor)
-{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
-
- if ( nwpv != 2 ) nwpv = 1;
-
- len = (size_t) (nwpv*gridInqSize(grid1));
-
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
farvar(field1, field2, field3, divisor);
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ int nmiss = 0;
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
{
array1[i] = missval1;
- field1->nmiss++;
+ nmiss++;
}
else
{
array1[i] = IS_NOT_EQUAL(array1[i], 0) ? sqrt(array1[i]) : 0;
}
+ field1->nmiss = nmiss;
}
-// not used
-void farcvar0(field_t *field1, field_t field2, const double rconst1)
+
+void farcvar(field_t *field1, field_t field2, int nsets, int divisor)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
- int nmiss3 = 0;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ const int nsetx = nsets - divisor;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
+ double temp;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
- if ( DBL_IS_EQUAL(rconst1, missval1) ) nmiss3 = 1;
-
- if ( nmiss1 > 0 || nmiss2 > 0 || nmiss3 > 0 )
+ if ( nsetx == 0 )
{
- for ( i = 0; i < len; i++ )
- {
- if ( !DBL_IS_EQUAL(array1[i], missval1) && !DBL_IS_EQUAL(array2[i], missval2) && nmiss3 == 0 )
- {
- array1[i] = array2[i]*rconst1 - (array1[i]*rconst1)*(array1[i]*rconst1);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
- }
- else
- array1[i] = missval1;
- }
+ for ( int i = 0; i < len; i++ ) array1[i] = missval1;
}
- else
+ else if ( (nmiss1 || nmiss2) /*&& (DBL_IS_NAN(missval1) || DBL_IS_NAN(missval2))*/ )
{
- for ( i = 0; i < len; i++ )
- {
- array1[i] = array2[i]*rconst1 - (array1[i]*rconst1)*(array1[i]*rconst1);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
- }
+ for ( int i = 0; i < len; i++ )
+ {
+ temp = MULMN(array1[i], array1[i]) / nsets;
+ array1[i] = SUBMN(array2[i], temp) / nsetx;
+ if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
+ }
}
-
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
-}
-
-
-void farcvar(field_t *field1, field_t field2, const double rconst1, const double divisor)
-{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
- double temp;
-
- if ( nwpv != 2 ) nwpv = 1;
-
- len = (size_t) (nwpv*gridInqSize(grid1));
-
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
- cdoAbort("Fields have different gridsize (%s)", __func__);
-
- for ( i = 0; i < len; i++ )
+ else
{
- temp = DIV( MUL(array1[i], array1[i]), rconst1);
- array1[i] = DIV( SUB(array2[i], temp), rconst1-divisor);
- if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
+ for ( int i = 0; i < len; i++ )
+ {
+ temp = MUL(array1[i], array1[i]) / nsets;
+ array1[i] = SUB(array2[i], temp) / nsetx;
+ if ( array1[i] < 0 && array1[i] > -1.e-5 ) array1[i] = 0;
+ }
}
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
+ field1->nmiss = farsetnmiss(len, array1, missval1);
}
-// not used
-void farcstd0(field_t *field1, field_t field2, const double rconst1)
-{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
-
- if ( nwpv != 2 ) nwpv = 1;
-
- len = (size_t) (nwpv*gridInqSize(grid1));
-
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
- cdoAbort("Fields have different gridsize (%s)", __func__);
-
- farcvar0(field1, field2, rconst1);
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
- if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
- {
- array1[i] = missval1;
- field1->nmiss++;
- }
- else
- {
- array1[i] = IS_NOT_EQUAL(array1[i], 0) ? sqrt(array1[i]) : 0;
- }
-}
-
-
-void farcstd(field_t *field1, field_t field2, const double rconst1, const double divisor)
+void farcstd(field_t *field1, field_t field2, int nsets, int divisor)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ double missval1 = field1->missval;
+ double *restrict array1 = field1->ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
- farcvar(field1, field2, rconst1, divisor);
+ farcvar(field1, field2, nsets, divisor);
- field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ int nmiss = 0;
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) || array1[i] < 0 )
{
array1[i] = missval1;
- field1->nmiss++;
+ nmiss++;
}
else
{
array1[i] = IS_NOT_EQUAL(array1[i], 0) ? sqrt(array1[i]) : 0;
}
+ field1->nmiss = nmiss;
}
void farmoq(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
array1[i] = array2[i]*array2[i];
else
array1[i] = missval1;
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] = array2[i]*array2[i];
}
}
@@ -904,44 +782,41 @@ void farmoq(field_t *field1, field_t field2)
void farmoqw(field_t *field1, field_t field2, double w)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
array1[i] = w*array2[i]*array2[i];
else
array1[i] = missval1;
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] = w*array2[i]*array2[i];
}
}
-
-/* RQ */
/**
* Counts the number of nonmissing values. The result of the operation
* is computed according to the following rules:
@@ -957,27 +832,26 @@ void farmoqw(field_t *field1, field_t field2, double w)
*/
void farcount(field_t *field1, field_t field2)
{
- size_t i, len;
- int nwpv = field1->nwpv;
- const int grid1 = field1->grid;
- const int nmiss1 = field1->nmiss;
- const double missval1 = field1->missval;
- double *array1 = field1->ptr;
- const int grid2 = field2.grid;
- const int nmiss2 = field2.nmiss;
- const double missval2 = field2.missval;
- double *array2 = field2.ptr;
+ int nwpv = field1->nwpv;
+ int grid1 = field1->grid;
+ int grid2 = field2.grid;
+ int nmiss1 = field1->nmiss;
+ int nmiss2 = field2.nmiss;
+ double missval1 = field1->missval;
+ double missval2 = field2.missval;
+ double *restrict array1 = field1->ptr;
+ const double *restrict array2 = field2.ptr;
if ( nwpv != 2 ) nwpv = 1;
- len = (size_t) (nwpv*gridInqSize(grid1));
+ int len = nwpv*gridInqSize(grid1);
- if ( len != (size_t) (nwpv*gridInqSize(grid2)) )
+ if ( len != (nwpv*gridInqSize(grid2)) )
cdoAbort("Fields have different gridsize (%s)", __func__);
if ( nmiss1 > 0 || nmiss2 > 0 )
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( !DBL_IS_EQUAL(array2[i], missval2) )
{
if ( !DBL_IS_EQUAL(array1[i], missval1) )
@@ -987,13 +861,12 @@ void farcount(field_t *field1, field_t field2)
}
field1->nmiss = 0;
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
if ( DBL_IS_EQUAL(array1[i], missval1) ) field1->nmiss++;
}
else
{
- for ( i = 0; i < len; i++ )
+ for ( int i = 0; i < len; i++ )
array1[i] += 1.0;
}
}
-/* QR */
diff --git a/src/fieldc.c b/src/fieldc.c
index 5ff2f8d..d6846c0 100644
--- a/src/fieldc.c
+++ b/src/fieldc.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -47,7 +47,7 @@ void farcmul(field_t *field, double rconst)
if ( nmiss > 0 )
{
for ( i = 0; i < len; i++ )
- array[i] = MUL(array[i], rconst);
+ array[i] = MULMN(array[i], rconst);
}
else
{
@@ -76,7 +76,7 @@ void farcdiv(field_t *field, double rconst)
if ( nmiss > 0 || IS_EQUAL(rconst, 0) )
{
for ( i = 0; i < len; i++ )
- array[i] = DIV(array[i], rconst);
+ array[i] = DIVMN(array[i], rconst);
if ( IS_EQUAL(rconst, 0) ) field->nmiss = len;
}
@@ -102,7 +102,7 @@ void farcadd(field_t *field, double rconst)
if ( nmiss > 0 )
{
for ( i = 0; i < len; i++ )
- array[i] = ADD(array[i], rconst);
+ array[i] = ADDMN(array[i], rconst);
}
else
{
@@ -129,7 +129,7 @@ void farinv(field_t *field)
len = gridInqSize(grid);
for ( i = 0; i < len; i++ )
- array[i] = DIV(1.0, array[i]);
+ array[i] = DIVMN(1.0, array[i]);
field->nmiss = 0;
for ( i = 0; i < len; i++ )
diff --git a/src/fieldmem.c b/src/fieldmem.c
index 128ee3f..7b65956 100644
--- a/src/fieldmem.c
+++ b/src/fieldmem.c
@@ -3,6 +3,7 @@
#include <cdi.h>
#include <cdo.h>
+#include <cdo_int.h>
#include "dmemory.h"
#include "field.h"
#include "util.h"
@@ -37,9 +38,11 @@ field_t **field_allocate(int vlistID, int ptype, int init)
field[varID][levelID].nwpv = nwpv;
field[varID][levelID].grid = gridID;
+ field[varID][levelID].size = gridsize;
field[varID][levelID].nsamp = 0;
field[varID][levelID].nmiss = 0;
field[varID][levelID].nmiss2 = 0;
+ if ( ptype & FIELD_FLT ) field[varID][levelID].memtype = MEMTYPE_FLOAT;
field[varID][levelID].missval = missval;
field[varID][levelID].ptr = NULL;
field[varID][levelID].ptr2 = NULL;
@@ -47,15 +50,31 @@ field_t **field_allocate(int vlistID, int ptype, int init)
if ( ptype & FIELD_PTR )
{
- field[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
- if ( init ) memset(field[varID][levelID].ptr, 0, nwpv*gridsize*sizeof(double));
- }
+ if ( ptype & FIELD_FLT )
+ {
+ field[varID][levelID].ptrf = (float*) Malloc(nwpv*gridsize*sizeof(float));
+ if ( init ) memset(field[varID][levelID].ptrf, 0, nwpv*gridsize*sizeof(float));
+ }
+ else
+ {
+ field[varID][levelID].ptr = (double*) Malloc(nwpv*gridsize*sizeof(double));
+ if ( init ) memset(field[varID][levelID].ptr, 0, nwpv*gridsize*sizeof(double));
+ }
+ }
if ( ptype & FIELD_PTR2 )
{
- field[varID][levelID].ptr2 = (double*) Malloc(nwpv*gridsize*sizeof(double));
- if ( init ) memset(field[varID][levelID].ptr2, 0, nwpv*gridsize*sizeof(double));
- }
+ if ( ptype & FIELD_FLT )
+ {
+ field[varID][levelID].ptr2 = Malloc(nwpv*gridsize*sizeof(float));
+ if ( init ) memset(field[varID][levelID].ptr2, 0, nwpv*gridsize*sizeof(float));
+ }
+ else
+ {
+ field[varID][levelID].ptr2 = Malloc(nwpv*gridsize*sizeof(double));
+ if ( init ) memset(field[varID][levelID].ptr2, 0, nwpv*gridsize*sizeof(double));
+ }
+ }
if ( ptype & FIELD_WGT )
{
@@ -90,6 +109,7 @@ void field_free(field_t **field, int vlistID)
for ( int levelID = 0; levelID < nlevel; ++levelID )
{
if ( field[varID][levelID].ptr ) Free(field[varID][levelID].ptr);
+ if ( field[varID][levelID].ptrf ) Free(field[varID][levelID].ptrf);
if ( field[varID][levelID].ptr2 ) Free(field[varID][levelID].ptr2);
if ( field[varID][levelID].weight ) Free(field[varID][levelID].weight);
}
diff --git a/src/fieldmer.c b/src/fieldmer.c
index ad65dcd..eb36d56 100644
--- a/src/fieldmer.c
+++ b/src/fieldmer.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -205,7 +205,7 @@ void mermean(field_t field1, field_t *field2)
}
}
- ravg = DIV(rsum, rsumw);
+ ravg = DIVMN(rsum, rsumw);
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
@@ -240,7 +240,7 @@ void meravg(field_t field1, field_t *field2)
for ( j = 0; j < ny; j++ )
if ( !DBL_IS_EQUAL(w[j*nx+i], missval1) )
{
- rsum = ADD(rsum, MUL(w[j*nx+i], array[j*nx+i]));
+ rsum = ADDMN(rsum, MULMN(w[j*nx+i], array[j*nx+i]));
rsumw += w[j*nx+i];
}
}
@@ -253,7 +253,7 @@ void meravg(field_t field1, field_t *field2)
}
}
- ravg = DIV(rsum, rsumw);
+ ravg = DIVMN(rsum, rsumw);
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
diff --git a/src/fieldzon.c b/src/fieldzon.c
index bb8ce2e..1c7415e 100644
--- a/src/fieldzon.c
+++ b/src/fieldzon.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -262,7 +262,7 @@ void zonmean(field_t field1, field_t *field2)
}
}
- ravg = DIV(rsum, rsumw);
+ ravg = DIVMN(rsum, rsumw);
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
@@ -295,7 +295,7 @@ void zonavg(field_t field1, field_t *field2)
{
for ( i = 0; i < nx; i++ )
{
- rsum = ADD(rsum, array[j*nx+i]);
+ rsum = ADDMN(rsum, array[j*nx+i]);
rsumw += 1;
}
}
@@ -308,7 +308,7 @@ void zonavg(field_t field1, field_t *field2)
}
}
- ravg = DIV(rsum, rsumw);
+ ravg = DIVMN(rsum, rsumw);
if ( DBL_IS_EQUAL(ravg, missval1) ) rnmiss++;
diff --git a/src/grid.c b/src/grid.c
index ce90efe..411ea6e 100644
--- a/src/grid.c
+++ b/src/grid.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -35,8 +35,6 @@
#include "error.h"
#include "grid.h"
-int referenceToGrid(int gridID1);
-
static
void scale_vec(double scalefactor, long nvals, double *restrict values)
@@ -120,7 +118,7 @@ int gridToZonal(int gridID1)
Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
}
- return (gridID2);
+ return gridID2;
}
@@ -159,7 +157,7 @@ int gridToMeridional(int gridID1)
Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
}
- return (gridID2);
+ return gridID2;
}
@@ -250,7 +248,7 @@ double genYmin(double y1, double y2)
if ( cdoVerbose )
cdoPrint("genYmin: y1 = %g y2 = %g dy = %g ymin = %g", y1, y2, dy, ymin);
- return (ymin);
+ return ymin;
}
static
@@ -266,7 +264,7 @@ double genYmax(double y1, double y2)
if ( cdoVerbose )
cdoPrint("genYmax: y1 = %g y2 = %g dy = %g ymax = %g", y1, y2, dy, ymax);
- return (ymax);
+ return ymax;
}
@@ -456,7 +454,7 @@ char *gen_param(const char *fmt, ...)
rstr = (char*) Malloc(len*sizeof(char));
memcpy(rstr, str, len*sizeof(char));
- return (rstr);
+ return rstr;
}
static
@@ -690,14 +688,8 @@ void grib_get_reduced_row(long pl,double lon_first,double lon_last,long* npoints
}
if (*ilon_first<0) *ilon_first+=pl;
-
- return;
}
-
-int qu2reg3_double(double *pfield, int *kpoint, int klat, int klon,
- double msval, int *kret, int omisng, int operio, int oveggy);
-
static
int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast,
double *array, int *rowlon, int ny, double missval, int *iret, int lmiss, int lperio, int lveggy)
@@ -787,7 +779,7 @@ int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast,
Free(work);
Free(pwork);
- return (nx);
+ return nx;
}
@@ -803,7 +795,7 @@ void field2regular(int gridID1, int gridID2, double missval, double *array, int
gridtype = gridInqType(gridID1);
- if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced gaussian grid!");
+ if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced Gaussian grid!");
lmiss = nmiss > 0;
lperio = 1;
@@ -849,7 +841,7 @@ int gridToRegular(int gridID1)
gridtype = gridInqType(gridID1);
- if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced gaussian grid!");
+ if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced Gaussian grid!");
ny = gridInqYsize(gridID1);
np = gridInqNP(gridID1);
@@ -906,7 +898,7 @@ int gridToRegular(int gridID1)
Free(xvals);
Free(yvals);
- return (gridID2);
+ return gridID2;
}
static
@@ -914,8 +906,7 @@ void gridCopyMask(int gridID1, int gridID2, long gridsize)
{
if ( gridInqMask(gridID1, NULL) )
{
- int *mask;
- mask = (int*) Malloc(gridsize*sizeof(int));
+ int *mask = (int*) Malloc(gridsize*sizeof(int));
gridInqMask(gridID1, mask);
gridDefMask(gridID2, mask);
Free(mask);
@@ -937,14 +928,13 @@ int check_range(long n, double *vals, double valid_min, double valid_max)
}
}
- return (status);
+ return status;
}
int gridToCurvilinear(int gridID1, int lbounds)
{
long index;
-
int gridtype = gridInqType(gridID1);
size_t gridsize = (size_t) gridInqSize(gridID1);
int gridID2 = gridCreate(GRID_CURVILINEAR, (int) gridsize);
@@ -959,13 +949,10 @@ int gridToCurvilinear(int gridID1, int lbounds)
case GRID_LAEA:
case GRID_SINUSOIDAL:
{
- long i, j;
+ double xscale = 1, yscale = 1;
double *xvals = NULL, *yvals = NULL;
- double *xvals2D, *yvals2D;
double *xbounds = NULL, *ybounds = NULL;
- double *xbounds2D, *ybounds2D;
char xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME];
- double xscale = 1, yscale = 1;
int nx = gridInqXsize(gridID1);
int ny = gridInqYsize(gridID1);
@@ -997,14 +984,14 @@ int gridToCurvilinear(int gridID1, int lbounds)
gridDefXsize(gridID2, nx);
gridDefYsize(gridID2, ny);
- xvals2D = (double*) Malloc(gridsize*sizeof(double));
- yvals2D = (double*) Malloc(gridsize*sizeof(double));
+ double *xvals2D = (double*) Malloc(gridsize*sizeof(double));
+ double *yvals2D = (double*) Malloc(gridsize*sizeof(double));
if ( gridtype == GRID_LCC )
{
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
xvals2D[j*nx+i] = i+1;
yvals2D[j*nx+i] = j+1;
@@ -1014,25 +1001,34 @@ int gridToCurvilinear(int gridID1, int lbounds)
}
else
{
+ /*
if ( ! (gridInqXvals(gridID1, NULL) && gridInqYvals(gridID1, NULL)) )
- Error("Grid has no values");
-
- xvals = (double*) Malloc(nx*sizeof(double));
- yvals = (double*) Malloc(ny*sizeof(double));
-
- gridInqXvals(gridID1, xvals);
- gridInqYvals(gridID1, yvals);
-
+ Error("Grid has no coordinates");
+ */
+ if ( nx == 0 ) nx = 1;
+ if ( ny == 0 ) ny = 1;
+
+ xvals = (double*) Malloc(nx*sizeof(double));
+ yvals = (double*) Malloc(ny*sizeof(double));
+
+ if ( gridInqXvals(gridID1, NULL) )
+ gridInqXvals(gridID1, xvals);
+ else
+ for ( int i = 0; i < nx; ++i ) xvals[i] = 0;
+
+ if ( gridInqYvals(gridID1, NULL) )
+ gridInqYvals(gridID1, yvals);
+ else
+ for ( int i = 0; i < ny; ++i ) yvals[i] = 0;
+
if ( gridIsRotated(gridID1) )
- {
- double xpole, ypole, angle;
+ {
+ double xpole = gridInqXpole(gridID1);
+ double ypole = gridInqYpole(gridID1);
+ double angle = gridInqAngle(gridID1);
- xpole = gridInqXpole(gridID1);
- ypole = gridInqYpole(gridID1);
- angle = gridInqAngle(gridID1);
-
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
xvals2D[j*nx+i] = lamrot_to_lam(yvals[j], xvals[i], ypole, xpole, angle);
yvals2D[j*nx+i] = phirot_to_phi(yvals[j], xvals[i], ypole, angle);
@@ -1040,8 +1036,8 @@ int gridToCurvilinear(int gridID1, int lbounds)
}
else
{
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
xvals2D[j*nx+i] = xscale*xvals[i];
yvals2D[j*nx+i] = yscale*yvals[j];
@@ -1073,11 +1069,11 @@ int gridToCurvilinear(int gridID1, int lbounds)
if ( gridtype == GRID_LCC )
{
- xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
- ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
index = j*4*nx + 4*i;
@@ -1150,8 +1146,8 @@ int gridToCurvilinear(int gridID1, int lbounds)
if ( xbounds && ybounds )
{
- xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
- ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
if ( gridIsRotated(gridID1) )
{
@@ -1163,8 +1159,8 @@ int gridToCurvilinear(int gridID1, int lbounds)
gridtype == GRID_LAEA ||
gridtype == GRID_LCC2 )
{
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
index = j*4*nx + 4*i;
@@ -1233,18 +1229,15 @@ int gridToCurvilinear(int gridID1, int lbounds)
}
}
- return (gridID2);
+ return gridID2;
}
int gridToUnstructured(int gridID1, int lbounds)
{
- int gridID2;
- int gridtype, gridsize;
-
- gridtype = gridInqType(gridID1);
- gridsize = gridInqSize(gridID1);
- gridID2 = gridCreate(GRID_UNSTRUCTURED, gridsize);
+ int gridtype = gridInqType(gridID1);
+ int gridsize = gridInqSize(gridID1);
+ int gridID2 = gridCreate(GRID_UNSTRUCTURED, gridsize);
gridDefPrec(gridID2, DATATYPE_FLT32);
switch (gridtype)
@@ -1252,11 +1245,6 @@ int gridToUnstructured(int gridID1, int lbounds)
case GRID_LONLAT:
case GRID_GAUSSIAN:
{
- long i, j;
- int nx, ny;
- double *xvals, *yvals;
- double *xvals2D, *yvals2D;
-
gridDefXname(gridID2, "lon");
gridDefYname(gridID2, "lat");
gridDefXlongname(gridID2, "longitude");
@@ -1266,31 +1254,29 @@ int gridToUnstructured(int gridID1, int lbounds)
gridDefNvertex(gridID2, 4);
- nx = gridInqXsize(gridID1);
- ny = gridInqYsize(gridID1);
+ int nx = gridInqXsize(gridID1);
+ int ny = gridInqYsize(gridID1);
gridDefXsize(gridID2, gridsize);
gridDefYsize(gridID2, gridsize);
- xvals = (double*) Malloc(nx*sizeof(double));
- yvals = (double*) Malloc(ny*sizeof(double));
+ double *xvals = (double*) Malloc(nx*sizeof(double));
+ double *yvals = (double*) Malloc(ny*sizeof(double));
- xvals2D = (double*) Malloc(gridsize*sizeof(double));
- yvals2D = (double*) Malloc(gridsize*sizeof(double));
+ double *xvals2D = (double*) Malloc(gridsize*sizeof(double));
+ double *yvals2D = (double*) Malloc(gridsize*sizeof(double));
gridInqXvals(gridID1, xvals);
gridInqYvals(gridID1, yvals);
if ( gridIsRotated(gridID1) )
- {
- double xpole, ypole, angle;
-
- xpole = gridInqXpole(gridID1);
- ypole = gridInqYpole(gridID1);
- angle = gridInqAngle(gridID1);
+ {
+ double xpole = gridInqXpole(gridID1);
+ double ypole = gridInqYpole(gridID1);
+ double angle = gridInqAngle(gridID1);
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
xvals2D[j*nx+i] = lamrot_to_lam(yvals[j], xvals[i], ypole, xpole, angle);
yvals2D[j*nx+i] = phirot_to_phi(yvals[j], xvals[i], ypole, angle);
@@ -1298,8 +1284,8 @@ int gridToUnstructured(int gridID1, int lbounds)
}
else
{
- for ( j = 0; j < ny; j++ )
- for ( i = 0; i < nx; i++ )
+ for ( int j = 0; j < ny; j++ )
+ for ( int i = 0; i < nx; i++ )
{
xvals2D[j*nx+i] = xvals[i];
yvals2D[j*nx+i] = yvals[j];
@@ -1315,7 +1301,6 @@ int gridToUnstructured(int gridID1, int lbounds)
if ( lbounds )
{
double *xbounds = NULL, *ybounds = NULL;
- double *xbounds2D, *ybounds2D;
if ( gridInqXbounds(gridID1, NULL) )
{
@@ -1342,8 +1327,8 @@ int gridToUnstructured(int gridID1, int lbounds)
if ( xbounds && ybounds )
{
- xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
- ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+ double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
if ( gridIsRotated(gridID1) )
{
@@ -1383,21 +1368,17 @@ int gridToUnstructured(int gridID1, int lbounds)
}
case GRID_GME:
{
- int nd, ni, ni2, ni3;
- long i, j;
int nv = 6;
- int *imask;
- double *xvals, *yvals;
double *xbounds = NULL, *ybounds = NULL;
- nd = gridInqGMEnd(gridID1);
- ni = gridInqGMEni(gridID1);
- ni2 = gridInqGMEni2(gridID1);
- ni3 = gridInqGMEni3(gridID1);
+ int nd = gridInqGMEnd(gridID1);
+ int ni = gridInqGMEni(gridID1);
+ int ni2 = gridInqGMEni2(gridID1);
+ int ni3 = gridInqGMEni3(gridID1);
- imask = (int*) Malloc(gridsize*sizeof(int));
- xvals = (double*) Malloc(gridsize*sizeof(double));
- yvals = (double*) Malloc(gridsize*sizeof(double));
+ int *imask = (int*) Malloc(gridsize*sizeof(int));
+ double *xvals = (double*) Malloc(gridsize*sizeof(double));
+ double *yvals = (double*) Malloc(gridsize*sizeof(double));
if ( lbounds )
{
xbounds = (double*) Malloc(nv*gridsize*sizeof(double));
@@ -1406,13 +1387,13 @@ int gridToUnstructured(int gridID1, int lbounds)
gme_grid(lbounds, gridsize, xvals, yvals, xbounds, ybounds, imask, ni, nd, ni2, ni3);
- for ( i = 0; i < gridsize; i++ )
+ for ( int i = 0; i < gridsize; i++ )
{
xvals[i] *= RAD2DEG;
yvals[i] *= RAD2DEG;
if ( lbounds )
- for ( j = 0; j < nv; j++ )
+ for ( int j = 0; j < nv; j++ )
{
xbounds[i*nv + j] *= RAD2DEG;
ybounds[i*nv + j] *= RAD2DEG;
@@ -1456,7 +1437,7 @@ int gridToUnstructured(int gridID1, int lbounds)
}
}
- return (gridID2);
+ return gridID2;
}
@@ -1473,7 +1454,7 @@ int gridCurvilinearToRegular(int gridID1)
gridtype = gridInqType(gridID1);
gridsize = gridInqSize(gridID1);
- if ( gridtype != GRID_CURVILINEAR ) return (gridID2);
+ if ( gridtype != GRID_CURVILINEAR ) return gridID2;
nx = gridInqXsize(gridID1);
ny = gridInqYsize(gridID1);
@@ -1538,7 +1519,7 @@ int gridCurvilinearToRegular(int gridID1)
Free(xvals);
Free(yvals);
- return (gridID2);
+ return gridID2;
}
@@ -1585,7 +1566,7 @@ int gridGenWeights(int gridID, double *grid_area, double *grid_wgts)
if ( grid_mask ) Free(grid_mask);
- return (status);
+ return status;
}
@@ -1672,7 +1653,7 @@ int gridWeightsOld(int gridID, double *weights)
}
}
- return (status);
+ return status;
}
@@ -1731,5 +1712,5 @@ int gridWeights(int gridID, double *grid_wgts)
*/
Free(grid_area);
- return (w_status);
+ return w_status;
}
diff --git a/src/grid.h b/src/grid.h
index 6d542d1..aaaeea3 100644
--- a/src/grid.h
+++ b/src/grid.h
@@ -34,12 +34,8 @@ void grid_cell_center_to_bounds_X2D(const char* xunitstr, long xsize, long ysize
void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize,
const double* restrict grid_center_lat, double* restrict grid_corner_lat);
-void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals);
-void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals);
-
int gridWeights(int gridID, double *weights);
int gridGenArea(int gridID, double *area);
-void gaussaw(double pa[], double pw[], size_t nlat);
int referenceToGrid(int gridID);
int gridToZonal(int gridID);
diff --git a/src/grid_area.c b/src/grid_area.c
index 0c8e3ca..fdd3622 100644
--- a/src/grid_area.c
+++ b/src/grid_area.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -56,7 +56,7 @@ double yac_huiliers_area(int num_corners, double *cell_corner_lon, double *cell_
double area = huiliers_area(cell);
area /= (EarthRadius*EarthRadius);
- return (area);
+ return area;
}
*/
static
@@ -166,7 +166,7 @@ double mod_cell_area(int num_corners, double *cell_corner_lon, double *cell_corn
if ( area < 0.0 ) area = 0.0;
}
- return (area);
+ return area;
}
/** area of a spherical triangle based on L'Huilier's Theorem
@@ -206,7 +206,7 @@ double mod_tri_area(const double *restrict u, const double *restrict v, const do
double area = fabs(4.0 * atan(sqrt(fabs(t))));
- return (area);
+ return area;
}
/*
@@ -245,7 +245,7 @@ double mod_huiliers_area(int num_corners, double *cell_corner_lon, double *cell_
if ( i < (num_corners-1) ) { pnt2[0] = pnt3[0]; pnt2[1] = pnt3[1]; pnt2[2] = pnt3[2]; }
}
- return (sum);
+ return sum;
}
static
@@ -279,26 +279,19 @@ double mod_huiliers_area2(int num_corners, double *cell_corner_lon, double *cell
sum += mod_tri_area(pnt1, pnt2, pnt3);
}
- return (sum);
+ return sum;
}
int gridGenArea(int gridID, double* area)
{
int status = 0;
- int gridtype;
int lgrid_gen_bounds = FALSE;
int lgriddestroy = FALSE;
- long i;
- long nv, gridsize;
- int* grid_mask = NULL;
- double* grid_center_lon = NULL;
- double* grid_center_lat = NULL;
- double* grid_corner_lon = NULL;
- double* grid_corner_lat = NULL;
-
- gridsize = gridInqSize(gridID);
- gridtype = gridInqType(gridID);
+ long nv;
+
+ long gridsize = gridInqSize(gridID);
+ int gridtype = gridInqType(gridID);
if ( gridtype != GRID_LONLAT &&
gridtype != GRID_GAUSSIAN &&
@@ -319,8 +312,11 @@ int gridGenArea(int gridID, double* area)
{
lgriddestroy = TRUE;
gridID = gridToUnstructured(gridID, 1);
+ /*
grid_mask = (int*) Malloc(gridsize*sizeof(int));
gridInqMaskGME(gridID, grid_mask);
+ if ( grid_mask ) Free(grid_mask);
+ */
}
else
{
@@ -338,7 +334,7 @@ int gridGenArea(int gridID, double* area)
{
lgriddestroy = TRUE;
gridID = referenceToGrid(gridID);
- if ( gridID == -1 ) return (1);
+ if ( gridID == -1 ) return 1;
}
}
}
@@ -354,14 +350,14 @@ int gridGenArea(int gridID, double* area)
{
cdoWarning("Computation of grid cell area weights failed, grid cell center coordinates missing!");
status = 1;
- return (status);
+ return status;
}
if ( nv == 0 )
{
cdoWarning("Computation of grid cell area weights failed, grid cell corner coordinates missing!");
status = 1;
- return (status);
+ return status;
}
char xunitstr[CDI_MAX_NAME];
@@ -369,14 +365,14 @@ int gridGenArea(int gridID, double* area)
gridInqXunits(gridID, xunitstr);
gridInqYunits(gridID, yunitstr);
- grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
- grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lon = (double*) Malloc(gridsize*sizeof(double));
+ double *grid_center_lat = (double*) Malloc(gridsize*sizeof(double));
gridInqXvals(gridID, grid_center_lon);
gridInqYvals(gridID, grid_center_lat);
- grid_corner_lon = (double*) Malloc(nv*gridsize*sizeof(double));
- grid_corner_lat = (double*) Malloc(nv*gridsize*sizeof(double));
+ double *grid_corner_lon = (double*) Malloc(nv*gridsize*sizeof(double));
+ double *grid_corner_lat = (double*) Malloc(nv*gridsize*sizeof(double));
if ( gridInqYbounds(gridID, NULL) && gridInqXbounds(gridID, NULL) )
{
@@ -398,7 +394,7 @@ int gridGenArea(int gridID, double* area)
else
{
status = 1;
- return (status);
+ return status;
}
}
@@ -418,7 +414,7 @@ int gridGenArea(int gridID, double* area)
#pragma omp parallel for default(none) \
shared(findex,gridsize,area,nv,grid_corner_lon,grid_corner_lat,grid_center_lon,grid_center_lat)
#endif
- for ( int i = 0; i < gridsize; ++i )
+ for ( long i = 0; i < gridsize; ++i )
{
int lprogress = 1;
if ( cdo_omp_get_thread_num() != 0 ) lprogress = 0;
@@ -439,15 +435,23 @@ int gridGenArea(int gridID, double* area)
if ( cdoVerbose )
{
double total_area = 0;
- for ( i = 0; i < gridsize; ++i ) total_area += area[i];
+ for ( long i = 0; i < gridsize; ++i ) total_area += area[i];
cdoPrint("Total area = %g steradians", total_area);
}
+ if ( gridsize < 20 )
+ {
+ double total_area = 0;
+ for ( long i = 0; i < gridsize; ++i ) total_area += area[i];
+ int nzero = 0;
+ for ( long i = 0; i < gridsize; ++i ) if ( IS_EQUAL(area[i], 0.) ) nzero++;
+ if ( IS_EQUAL(total_area, 0.) ) status = 2;
+ }
+
Free(grid_center_lon);
Free(grid_center_lat);
Free(grid_corner_lon);
Free(grid_corner_lat);
- if ( grid_mask ) Free(grid_mask);
- return (status);
+ return status;
}
diff --git a/src/grid_search.c b/src/grid_search.c
index bb66c84..19b1e46 100644
--- a/src/grid_search.c
+++ b/src/grid_search.c
@@ -31,6 +31,14 @@ static inline void LLtoXYZ_f(double lon, double lat, float *restrict xyz)
xyz[2] = sin(lat);
}
+static inline void LLtoXYZ_kd(double lon, double lat, kdata_t *restrict xyz)
+{
+ double cos_lat = cos(lat);
+ xyz[0] = KDATA_SCALE(cos_lat * cos(lon));
+ xyz[1] = KDATA_SCALE(cos_lat * sin(lon));
+ xyz[2] = KDATA_SCALE(sin(lat));
+}
+
static
float square(const float x)
{
@@ -54,17 +62,20 @@ void gridsearch_set_method(const char *methodstr)
}
-struct gridsearch *gridsearch_create_reg2d(unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats)
+struct gridsearch *gridsearch_create_reg2d(unsigned lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats)
{
struct gridsearch *gs = (struct gridsearch *) Calloc(1, sizeof(struct gridsearch));
gs->nx = nx;
gs->ny = ny;
- double *reg2d_center_lon = (double *) Malloc((nx+1)*sizeof(double));
+ unsigned nxm = nx;
+ if ( lcyclic ) nxm++;
+
+ double *reg2d_center_lon = (double *) Malloc(nxm*sizeof(double));
double *reg2d_center_lat = (double *) Malloc(ny*sizeof(double));
- memcpy(reg2d_center_lon, lons, (nx+1)*sizeof(double));
+ memcpy(reg2d_center_lon, lons, nxm*sizeof(double));
memcpy(reg2d_center_lat, lats, ny*sizeof(double));
double *coslon = (double *) Malloc(nx*sizeof(double));
@@ -103,17 +114,17 @@ struct kdNode *gs_create_kdtree(unsigned n, const double *restrict lons, const d
struct kd_point *pointlist = (struct kd_point *) Malloc(n * sizeof(struct kd_point));
// see example_cartesian.c
if ( cdoVerbose ) printf("kdtree lib init 3D: n=%d nthreads=%d\n", n, ompNumThreads);
- float min[3], max[3];
+ kdata_t min[3], max[3];
min[0] = min[1] = min[2] = 1e9;
max[0] = max[1] = max[2] = -1e9;
- float *restrict point;
+ kdata_t *restrict point;
#if defined(HAVE_OPENMP4)
#pragma omp simd
#endif
for ( unsigned i = 0; i < n; i++ )
{
point = pointlist[i].point;
- LLtoXYZ_f(lons[i], lats[i], point);
+ LLtoXYZ_kd(lons[i], lats[i], point);
for ( unsigned j = 0; j < 3; ++j )
{
min[j] = point[j] < min[j] ? point[j] : min[j];
@@ -295,15 +306,16 @@ kdNode *gs_nearest_kdtree(kdNode *kdt, double lon, double lat, double *prange)
if ( kdt == NULL ) return NULL;
float range0 = gs_set_range(prange);
- float range = range0;
+ kdata_t range = KDATA_SCALE(range0);
- float point[3];
- LLtoXYZ_f(lon, lat, point);
+ kdata_t point[3];
+ LLtoXYZ_kd(lon, lat, point);
kdNode *node = kd_nearest(kdt, point, &range, 3);
- if ( !(range < range0) ) node = NULL;
- if ( prange ) *prange = range;
+ float frange = KDATA_INVSCALE(range);
+ if ( !(frange < range0) ) node = NULL;
+ if ( prange ) *prange = frange;
return node;
}
@@ -419,19 +431,20 @@ struct pqueue *gridsearch_qnearest(struct gridsearch *gs, double lon, double lat
{
if ( gs->kdt == NULL ) return NULL;
- float point[3];
+ kdata_t point[3];
float range0 = gs_set_range(prange);
- float range = range0;
+ kdata_t range = KDATA_SCALE(range0);
struct pqueue *result = NULL;
- LLtoXYZ_f(lon, lat, point);
+ LLtoXYZ_kd(lon, lat, point);
if ( gs )
{
result = kd_qnearest(gs->kdt, point, &range, nnn, 3);
// printf("range %g %g %g %p\n", lon, lat, range, node);
- if ( !(range < range0) )
+ float frange = KDATA_INVSCALE(range);
+ if ( !(frange < range0) )
{
if ( result )
{
@@ -442,7 +455,7 @@ struct pqueue *gridsearch_qnearest(struct gridsearch *gs, double lon, double lat
}
result = NULL;
}
- if ( prange ) *prange = range;
+ if ( prange ) *prange = frange;
}
return result;
diff --git a/src/grid_search.h b/src/grid_search.h
index 36e5888..b973c54 100644
--- a/src/grid_search.h
+++ b/src/grid_search.h
@@ -43,7 +43,7 @@ struct gridsearch {
};
-struct gridsearch *gridsearch_create_reg2d(unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats);
+struct gridsearch *gridsearch_create_reg2d(unsigned lcyclic, unsigned nx, unsigned ny, const double *restrict lons, const double *restrict lats);
struct gridsearch *gridsearch_create(unsigned n, const double *restrict lons, const double *restrict lats);
struct gridsearch *gridsearch_create_nn(unsigned n, const double *restrict lons, const double *restrict lats);
void gridsearch_delete(struct gridsearch *gs);
diff --git a/src/griddes.c b/src/griddes.c
index 7f67be2..6e83343 100644
--- a/src/griddes.c
+++ b/src/griddes.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -34,6 +34,7 @@
#include <cdi.h>
#include "cdo.h"
#include "cdo_int.h"
+#include "cdi_uuid.h"
#include "grid.h"
#include "griddes.h"
#include "error.h"
@@ -667,7 +668,6 @@ double readflt(const char *filename, const char *name, const char *pline)
return (val);
}
-void str2uuid(const char *uuidstr, unsigned char *uuid);
int gridFromFile(FILE *gfp, const char *dname)
{
@@ -809,7 +809,7 @@ int gridFromFile(FILE *gfp, const char *dname)
{
char uuidOfHGridStr[256];
strcpy(uuidOfHGridStr, skipSeparator(pline + len));
- str2uuid(uuidOfHGridStr, grid.uuid);
+ cdiStr2UUID(uuidOfHGridStr, grid.uuid);
}
else if ( cmpstrlen(pline, "xsize", len) == 0 )
{
@@ -1878,7 +1878,7 @@ int cdoDefineGrid(const char *gridfile)
if ( cmpstrlen(buffer, "CDF", len) == 0 )
{
- if ( cdoDebug ) cdoPrint("Grid from netCDF file");
+ if ( cdoDebug ) cdoPrint("Grid from NetCDF file");
gridID = gridFromNCfile(filename);
}
@@ -1895,7 +1895,7 @@ int cdoDefineGrid(const char *gridfile)
{
if ( cmpstrlen(buffer+1, "HDF", len) == 0 )
{
- if ( cdoDebug ) cdoPrint("Grid from netCDF4 file");
+ if ( cdoDebug ) cdoPrint("Grid from NetCDF4 file");
gridID = gridFromNCfile(filename);
}
}
diff --git a/src/griddes_nc.c b/src/griddes_nc.c
index 7e21d71..5d185bc 100644
--- a/src/griddes_nc.c
+++ b/src/griddes_nc.c
@@ -19,7 +19,7 @@
static void nce(int istat)
{
/*
- This routine provides a simple interface to netCDF error message routine.
+ This routine provides a simple interface to NetCDF error message routine.
*/
if ( istat != NC_NOERR ) cdoAbort(nc_strerror(istat));
}
@@ -30,7 +30,7 @@ int cdf_openread(const char *filename)
{
int fileID = -1;
#if defined(HAVE_LIBNETCDF)
- int nc_file_id; /* netCDF grid file id */
+ int nc_file_id; /* NetCDF grid file id */
openLock();
int istat = nc_open(filename, NC_NOWRITE, &nc_file_id);
@@ -39,7 +39,7 @@ int cdf_openread(const char *filename)
cdoAbort("Open failed on %s! %s", filename, nc_strerror(istat));
fileID = nc_file_id;
#else
- cdoWarning("netCDF support not compiled in!");
+ cdoWarning("NetCDF support not compiled in!");
#endif
return (fileID);
@@ -50,16 +50,16 @@ int gridFromNCfile(const char *gridfile)
{
int gridID = -1;
#if defined(HAVE_LIBNETCDF)
- int nc_file_id; /* netCDF grid file id */
- int nc_gridsize_id; /* netCDF grid size dim id */
- int nc_gridcorn_id; /* netCDF grid corner dim id */
- int nc_gridrank_id; /* netCDF grid rank dim id */
- int nc_griddims_id; /* netCDF grid dimension size id */
- int nc_gridclat_id; /* netCDF grid corner lat var id */
- int nc_gridclon_id; /* netCDF grid corner lon var id */
- int nc_gridlat_id; /* netCDF grid center lat var id */
- int nc_gridlon_id; /* netCDF grid center lon var id */
- int nc_gridmask_id; /* netCDF grid mask id */
+ int nc_file_id; /* NetCDF grid file id */
+ int nc_gridsize_id; /* NetCDF grid size dim id */
+ int nc_gridcorn_id; /* NetCDF grid corner dim id */
+ int nc_gridrank_id; /* NetCDF grid rank dim id */
+ int nc_griddims_id; /* NetCDF grid dimension size id */
+ int nc_gridclat_id; /* NetCDF grid corner lat var id */
+ int nc_gridclon_id; /* NetCDF grid corner lon var id */
+ int nc_gridlat_id; /* NetCDF grid center lat var id */
+ int nc_gridlon_id; /* NetCDF grid center lon var id */
+ int nc_gridmask_id; /* NetCDF grid mask id */
nc_type xtype;
size_t attlen;
@@ -151,7 +151,7 @@ int gridFromNCfile(const char *gridfile)
nce(nc_close(nc_file_id));
#else
- cdoWarning("netCDF support not compiled in!");
+ cdoWarning("NetCDF support not compiled in!");
#endif
return (gridID);
@@ -161,15 +161,15 @@ int gridFromNCfile(const char *gridfile)
void writeNCgrid(const char *gridfile, int gridID, int *grid_imask)
{
#if defined(HAVE_LIBNETCDF)
- int nc_file_id; /* netCDF grid file id */
- int nc_gridsize_id; /* netCDF grid size dim id */
- int nc_gridcorn_id; /* netCDF grid corner dim id */
- int nc_gridrank_id; /* netCDF grid rank dim id */
- int nc_griddims_id; /* netCDF grid dimension size id */
- int nc_gridclat_id; /* netCDF grid corner lat var id */
- int nc_gridclon_id; /* netCDF grid corner lon var id */
- int nc_gridlat_id; /* netCDF grid center lat var id */
- int nc_gridlon_id; /* netCDF grid center lon var id */
+ int nc_file_id; /* NetCDF grid file id */
+ int nc_gridsize_id; /* NetCDF grid size dim id */
+ int nc_gridcorn_id; /* NetCDF grid corner dim id */
+ int nc_gridrank_id; /* NetCDF grid rank dim id */
+ int nc_griddims_id; /* NetCDF grid dimension size id */
+ int nc_gridclat_id; /* NetCDF grid corner lat var id */
+ int nc_gridclon_id; /* NetCDF grid corner lon var id */
+ int nc_gridlat_id; /* NetCDF grid center lat var id */
+ int nc_gridlon_id; /* NetCDF grid center lon var id */
int nc_gridxsize_id, nc_gridysize_id, nc_grdimask_id;
nc_type xtype;
@@ -211,7 +211,7 @@ void writeNCgrid(const char *gridfile, int gridID, int *grid_imask)
else
cdoWarning("Unknown units supplied for grid!");
- /* create netCDF dataset for this grid */
+ /* create NetCDF dataset for this grid */
nce(nc_create(gridfile, NC_CLOBBER, &nc_file_id));
@@ -331,6 +331,6 @@ void writeNCgrid(const char *gridfile, int gridID, int *grid_imask)
nce(nc_close(nc_file_id));
#else
- Error("netCDF support not compiled in!");
+ Error("NetCDF support not compiled in!");
#endif
}
diff --git a/src/gridreference.c b/src/gridreference.c
index 7a360b0..5c4d049 100644
--- a/src/gridreference.c
+++ b/src/gridreference.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/institution.c b/src/institution.c
index c53edd7..5ceaf5a 100644
--- a/src/institution.c
+++ b/src/institution.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/juldate.c b/src/juldate.c
index 736ec05..54a2154 100644
--- a/src/juldate.c
+++ b/src/juldate.c
@@ -1,11 +1,6 @@
#include <cdi.h>
#include "cdo_int.h"
-
-
-void encode_caldaysec(int calendar, int year, int month, int day, int hour, int minute, int second,
- int *julday, int *secofday);
-void decode_caldaysec(int calendar, int julday, int secofday,
- int *year, int *month, int *day, int *hour, int *minute, int *second);
+#include "calendar.h"
juldate_t juldate_encode(int calendar, int date, int time)
diff --git a/src/kdtreelib/kdtree.h b/src/kdtreelib/kdtree.h
index 398b3f3..ee24ef0 100644
--- a/src/kdtreelib/kdtree.h
+++ b/src/kdtreelib/kdtree.h
@@ -22,10 +22,29 @@
#include <stdio.h>
#include <string.h>
+#define KD_FLOAT 1
+#define KD_INT 2
+
+#define KD_TYPE KD_FLOAT
+
+#if KD_TYPE == KD_INT
+typedef int kdata_t;
+# define KDATA_SFAC 20000.
+# define KDATA_SCALE(x) ((int) (0.5+KDATA_SFAC*(x)))
+# define KDATA_INVSCALE(x) ((x)/KDATA_SFAC)
+# define KDATA_ABS(x) abs(x)
+#else
+typedef float kdata_t;
+# define KDATA_SCALE(x) (x)
+# define KDATA_INVSCALE(x) (x)
+# define KDATA_ABS(x) fabs(x)
+#endif
+
+
#define KD_MAX_DIM 3
typedef struct kd_point {
- float point[KD_MAX_DIM];
+ kdata_t point[KD_MAX_DIM];
unsigned index;
} kd_point;
@@ -34,13 +53,13 @@ typedef struct kd_point {
* \brief kd-tree node structure definition
*/
typedef struct kdNode {
- float location[KD_MAX_DIM]; /*!<vector to the node's location */
- float min[KD_MAX_DIM]; /*!<vector to the min coordinates of the hyperrectangle */
- float max[KD_MAX_DIM]; /*!<vector to the max coordinates of the hyperrectangle */
- int split; /*!<axis along which the tree bifurcates */
- unsigned index; /*!<optional index value */
- struct kdNode *left; /*!<the left child of the tree node */
- struct kdNode *right; /*!<the right child of the tree node */
+ struct kdNode *left; /*!<the left child of the tree node */
+ struct kdNode *right; /*!<the right child of the tree node */
+ kdata_t location[KD_MAX_DIM]; /*!<vector to the node's location */
+ kdata_t min[KD_MAX_DIM]; /*!<vector to the min coordinates of the hyperrectangle */
+ kdata_t max[KD_MAX_DIM]; /*!<vector to the max coordinates of the hyperrectangle */
+ int split; /*!<axis along which the tree bifurcates */
+ unsigned index; /*!<optional index value */
} kdNode;
/*!
@@ -49,7 +68,7 @@ typedef struct kdNode {
*/
typedef struct resItem {
struct kdNode *node; /*!<pointer to a kdNode */
- float dist_sq; /*!<distance squared as the priority */
+ kdata_t dist_sq; /*!<distance squared as the priority */
} resItem;
/*!
@@ -57,10 +76,10 @@ typedef struct resItem {
* \brief priority queue (min-max heap)
*/
typedef struct pqueue {
+ struct resItem **d; /*!<pointer to an array of result items */
uint32_t size; /*!<current length of the queue */
uint32_t avail; /*!<currently allocated queue elements */
uint32_t step; /*!<step size in which new elements are allocated */
- struct resItem **d; /*!<pointer to an array of result items */
} pqueue;
/*!
@@ -68,11 +87,11 @@ typedef struct pqueue {
* \brief arguments passed to the threaded kd-Tree construction
*/
typedef struct kd_thread_data {
- int max_threads;
struct kd_point *points;
+ kdata_t min[KD_MAX_DIM];
+ kdata_t max[KD_MAX_DIM];
unsigned long nPoints;
- float min[KD_MAX_DIM];
- float max[KD_MAX_DIM];
+ int max_threads;
int depth;
int dim;
} kd_thread_data;
@@ -94,14 +113,14 @@ struct resItem **pqpeek_max(struct pqueue *q, struct resItem **d);
void *kd_malloc(size_t size, const char *msg);
int kd_isleaf(struct kdNode *n);
/* Cartesian */
-float kd_sqr(float a);
-float kd_min(float x, float y);
+kdata_t kd_sqr(kdata_t a);
+kdata_t kd_min(kdata_t x, kdata_t y);
/* Spherical */
-float kd_sph_orth_dist(float *p1, float *p2, int split);
-float kd_sph_dist_sq(float *x, float *y);
-float kd_sph_dist(float *x, float *y);
-float kd_sph_bearing(float *p1, float *p2);
-float kd_sph_xtd(float *p1, float *p2, float *p3);
+kdata_t kd_sph_orth_dist(kdata_t *p1, kdata_t *p2, int split);
+kdata_t kd_sph_dist_sq(kdata_t *x, kdata_t *y);
+kdata_t kd_sph_dist(kdata_t *x, kdata_t *y);
+kdata_t kd_sph_bearing(kdata_t *p1, kdata_t *p2);
+kdata_t kd_sph_xtd(kdata_t *p1, kdata_t *p2, kdata_t *p3);
/* helper functions for debugging */
void kd_printNode(struct kdNode *node);
@@ -110,60 +129,60 @@ void kd_printTree(struct kdNode *node);
/* Functions for building and destroying trees */
void kd_freeNode(kdNode * node);
struct kdNode *kd_allocNode(struct kd_point *points, unsigned long pivot,
- float *min, float *max, int dim, int axis);
+ kdata_t *min, kdata_t *max, int dim, int axis);
void kd_destroyTree(struct kdNode *node);
struct kd_thread_data *kd_buildArg(struct kd_point *points,
unsigned long nPoints,
- float *min, float *max,
+ kdata_t *min, kdata_t *max,
int depth, int max_threads,
int dim);
struct kdNode *kd_buildTree(struct kd_point *points, unsigned long nPoints,
- float *min, float *max, int dim, int max_threads);
+ kdata_t *min, kdata_t *max, int dim, int max_threads);
void *kd_doBuildTree(void *threadarg);
struct kdNode *kd_sph_buildTree(struct kd_point *points,
unsigned long nPoints,
- float *min, float *max,
+ kdata_t *min, kdata_t *max,
int max_threads);
void *kd_sph_doBuildTree(void *threadarg);
/* Functions for range searches
* Cartesian
*/
-int kd_isPointInRect(struct kdNode *node, float *min, float *max, int dim);
-int kd_isRectInRect(struct kdNode *node, float *min, float *max, int dim);
-int kd_rectOverlapsRect(struct kdNode *node, float *min, float *max, int dim);
-struct pqueue *kd_ortRangeSearch(struct kdNode *node, float *min, float *max,
+int kd_isPointInRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim);
+int kd_isRectInRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim);
+int kd_rectOverlapsRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim);
+struct pqueue *kd_ortRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max,
int dim);
-int kd_doOrtRangeSearch(struct kdNode *node, float *min, float *max, int dim,
+int kd_doOrtRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max, int dim,
struct pqueue *res);
-struct kdNode *kd_nearest(struct kdNode *node, float *p, float *max_dist_sq,
+struct kdNode *kd_nearest(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int dim);
-struct pqueue *kd_qnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, int dim);
-int kd_doQnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, int dim,
+struct pqueue *kd_qnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, int dim);
+int kd_doQnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, int dim,
struct pqueue *res);
-struct pqueue *kd_range(struct kdNode *node, float *p, float *max_dist_sq,
+struct pqueue *kd_range(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int dim, int ordered);
-int kd_doRange(struct kdNode *node, float *p, float *max_dist_sq,
+int kd_doRange(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int dim, struct pqueue *res, int ordered);
/* spherical */
-int kd_sph_isPointInRect(struct kdNode *node, float *min, float *max);
-int kd_sph_isRectInRect(struct kdNode *node, float *min, float *max);
-int kd_sph_rectOverlapsRect(struct kdNode *node, float *min, float *max);
-struct pqueue *kd_sph_ortRangeSearch(struct kdNode *node, float *min,
- float *max);
-int kd_sph_doOrtRangeSearch(struct kdNode *node, float *min, float *max,
+int kd_sph_isPointInRect(struct kdNode *node, kdata_t *min, kdata_t *max);
+int kd_sph_isRectInRect(struct kdNode *node, kdata_t *min, kdata_t *max);
+int kd_sph_rectOverlapsRect(struct kdNode *node, kdata_t *min, kdata_t *max);
+struct pqueue *kd_sph_ortRangeSearch(struct kdNode *node, kdata_t *min,
+ kdata_t *max);
+int kd_sph_doOrtRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max,
struct pqueue *res);
-struct kdNode *kd_sph_nearest(struct kdNode *node, float *p,
- float *max_dist_sq);
-struct pqueue *kd_sph_qnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q);
-int kd_sph_doQnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, struct pqueue *res);
-struct pqueue *kd_sph_range(struct kdNode *node, float *p, float *max_dist_sq,
+struct kdNode *kd_sph_nearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq);
+struct pqueue *kd_sph_qnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q);
+int kd_sph_doQnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, struct pqueue *res);
+struct pqueue *kd_sph_range(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int ordered);
-int kd_sph_doRange(struct kdNode *node, float *p, float *max_dist_sq,
+int kd_sph_doRange(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
struct pqueue *res, int ordered);
/* Functions for results heaps */
diff --git a/src/kdtreelib/kdtree_cartesian.c b/src/kdtreelib/kdtree_cartesian.c
index 46181a2..11a2be7 100644
--- a/src/kdtreelib/kdtree_cartesian.c
+++ b/src/kdtreelib/kdtree_cartesian.c
@@ -15,35 +15,31 @@
********************************************************************* */
-
static
-float square(const float x)
+kdata_t square(const kdata_t x)
{
return x*x;
}
static
-float kd_dist_sq(const float *restrict a, const float *restrict b, int dim)
+kdata_t kd_dist_sq(const kdata_t *restrict a, const kdata_t *restrict b, int dim)
{
return (square((a[0]-b[0]))+square((a[1]-b[1]))+square((a[2]-b[2])));
}
-inline float
-kd_dist_sq_ori(float *x, float *y, int dim)
+inline kdata_t
+kd_dist_sq_ori(kdata_t *x, kdata_t *y, int dim)
{
- int i;
- float dsq = 0;
-
- if (!x || !y)
- return -1;
+ if (!x || !y) return -1;
- for(i = 0; i < dim; i++)
+ kdata_t dsq = 0;
+ for(int i = 0; i < dim; i++)
dsq += kd_sqr(x[i] - y[i]);
return dsq;
}
-inline float
-kd_min(float x, float y)
+inline kdata_t
+kd_min(kdata_t x, kdata_t y)
{
return x < y ? x : y;
}
@@ -86,7 +82,7 @@ kd_min(float x, float y)
*/
struct kdNode *
kd_buildTree(struct kd_point *points, unsigned long nPoints,
- float *min, float *max, int dim, int max_threads)
+ kdata_t *min, kdata_t *max, int dim, int max_threads)
{
struct kd_thread_data *my_data;
struct kdNode *tree;
@@ -108,7 +104,7 @@ kd_buildTree(struct kd_point *points, unsigned long nPoints,
/* Returns 1 if node is a point in the hyperrectangle defined by
minimum and maximum vectors min and max. */
int
-kd_isPointInRect(struct kdNode *node, float *min, float *max, int dim)
+kd_isPointInRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim)
{
int i;
@@ -126,7 +122,7 @@ kd_isPointInRect(struct kdNode *node, float *min, float *max, int dim)
the HR described by the minimum and maximum vectors min and
max. Returns 0 otherwise. */
int
-kd_isRectInRect(struct kdNode *node, float *min, float *max, int dim)
+kd_isRectInRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim)
{
int i;
@@ -144,7 +140,7 @@ kd_isRectInRect(struct kdNode *node, float *min, float *max, int dim)
the minimum and maximum vectors min and max. Returns 0
otherwise. */
int
-kd_rectOverlapsRect(struct kdNode *node, float *min, float *max, int dim)
+kd_rectOverlapsRect(struct kdNode *node, kdata_t *min, kdata_t *max, int dim)
{
int i;
@@ -175,7 +171,7 @@ kd_rectOverlapsRect(struct kdNode *node, float *min, float *max, int dim)
* \return Pointer to a priority queue, NULL in case of problems.
*/
struct pqueue *
-kd_ortRangeSearch(struct kdNode *node, float *min, float *max, int dim)
+kd_ortRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max, int dim)
{
struct pqueue *res;
uint32_t i;
@@ -196,7 +192,7 @@ kd_ortRangeSearch(struct kdNode *node, float *min, float *max, int dim)
/* This is the orthogonal range search. Returns 1 if okay, 0 in case
of problems. */
int
-kd_doOrtRangeSearch(struct kdNode *node, float *min, float *max,
+kd_doOrtRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max,
int dim, struct pqueue *res)
{
@@ -243,10 +239,10 @@ kd_doOrtRangeSearch(struct kdNode *node, float *min, float *max,
* neigbor.
*/
struct kdNode *
-kd_nearest(struct kdNode *node, float *p, float *max_dist_sq, int dim)
+kd_nearest(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq, int dim)
{
struct kdNode *nearer, *further, *nearest = NULL, *tmp, *tmp_nearest;
- float dist_sq, tmp_dist_sq, dx;
+ kdata_t dist_sq, tmp_dist_sq, dx;
if (!node)
return NULL;
@@ -271,8 +267,8 @@ kd_nearest(struct kdNode *node, float *p, float *max_dist_sq, int dim)
if (!further)
return nearest;
- dx = kd_min(fabs(p[node->split] - further->min[node->split]),
- fabs(p[node->split] - further->max[node->split]));
+ dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
+ KDATA_ABS(p[node->split] - further->max[node->split]));
if (*max_dist_sq > kd_sqr(dx)) {
/*
* some part of the further hyper-rectangle is in the search
@@ -318,8 +314,8 @@ kd_nearest(struct kdNode *node, float *p, float *max_dist_sq, int dim)
* in case of problems.
*/
struct pqueue *
-kd_qnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, int dim)
+kd_qnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, int dim)
{
struct pqueue *res;
uint32_t i;
@@ -348,11 +344,11 @@ kd_qnearest(struct kdNode *node, float *p,
*/
// Uwe Schulzweida: extract kd_check_dist() from kd_doQnearest()
static int
-kd_check_dist(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
+kd_check_dist(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
{
struct resItem *point, *item;
- float dist_sq;
+ kdata_t dist_sq;
dist_sq = kd_dist_sq(node->location, p, dim);
if (dist_sq < *max_dist_sq && kd_isleaf(node)) {
@@ -395,11 +391,11 @@ kd_check_dist(struct kdNode *node, float *p,
}
int
-kd_doQnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
+kd_doQnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q, int dim, struct pqueue *res)
{
struct kdNode *nearer, *further;
- float dx;
+ kdata_t dx;
if (!node) return 1;
@@ -416,8 +412,8 @@ kd_doQnearest(struct kdNode *node, float *p,
if (!further) return 1;
- dx = kd_min(fabs(p[node->split] - further->min[node->split]),
- fabs(p[node->split] - further->max[node->split]));
+ dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
+ KDATA_ABS(p[node->split] - further->max[node->split]));
if (*max_dist_sq > kd_sqr(dx)) {
/*
* some part of the further hyper-rectangle is in the search
@@ -448,7 +444,7 @@ kd_doQnearest(struct kdNode *node, float *p,
* NULL in case of problems.
*/
struct pqueue *
-kd_range(struct kdNode *node, float *p, float *max_dist_sq,
+kd_range(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int dim, int ordered)
{
struct pqueue *res;
@@ -470,13 +466,13 @@ kd_range(struct kdNode *node, float *p, float *max_dist_sq,
/* This is the range search. Returns 1 if okay, 0 in case of problems */
int
-kd_doRange(struct kdNode *node, float *p, float *max_dist_sq,
+kd_doRange(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
int dim, struct pqueue *res, int ordered)
{
struct kdNode *nearer, *further;
struct resItem *point;
- float dist_sq, dx;
+ kdata_t dist_sq, dx;
if (!node)
return 1;
@@ -504,8 +500,8 @@ kd_doRange(struct kdNode *node, float *p, float *max_dist_sq,
if (!further)
return 1;
- dx = kd_min(fabs(p[node->split] - further->min[node->split]),
- fabs(p[node->split] - further->max[node->split]));
+ dx = kd_min(KDATA_ABS(p[node->split] - further->min[node->split]),
+ KDATA_ABS(p[node->split] - further->max[node->split]));
if (*max_dist_sq > kd_sqr(dx)) {
/*
* some part of the further hyper-rectangle is in the search
diff --git a/src/kdtreelib/kdtree_common.c b/src/kdtreelib/kdtree_common.c
index 25c2927..5c1317e 100644
--- a/src/kdtreelib/kdtree_common.c
+++ b/src/kdtreelib/kdtree_common.c
@@ -27,10 +27,10 @@ kd_malloc(size_t size, const char *msg)
return ptr;
}
-float
-kd_sqr(float x)
+kdata_t
+kd_sqr(kdata_t x)
{
- return x == 0.0 ? 0.0 : x * x;
+ return x == 0 ? 0 : x * x;
}
int
@@ -93,15 +93,10 @@ _compPoints0(const void *p1, const void *p2)
struct kd_point *a = (struct kd_point *) p1;
struct kd_point *b = (struct kd_point *) p2;
- if (a->point[0] > b->point[0]) return 1;
- else if (a->point[0] < b->point[0]) return -1;
- else
- {
- if ( a->index > b->index ) return 1;
- else if ( a->index < b->index ) return -1;
+ int ret = (a->point[0] > b->point[0]) ? 1 : (a->point[0] < b->point[0]) ? -1 : 0;
+ if ( ret == 0 ) ret = (a->index > b->index) ? 1 : (a->index < b->index) ? -1 : 0;
- return 0;
- }
+ return ret;
}
static int
@@ -110,15 +105,10 @@ _compPoints1(const void *p1, const void *p2)
struct kd_point *a = (struct kd_point *) p1;
struct kd_point *b = (struct kd_point *) p2;
- if (a->point[1] > b->point[1]) return 1;
- else if (a->point[1] < b->point[1]) return -1;
- else
- {
- if ( a->index > b->index ) return 1;
- else if ( a->index < b->index ) return -1;
+ int ret = (a->point[1] > b->point[1]) ? 1 : (a->point[1] < b->point[1]) ? -1 : 0;
+ if ( ret == 0 ) ret = (a->index > b->index) ? 1 : (a->index < b->index) ? -1 : 0;
- return 0;
- }
+ return ret;
}
static int
@@ -127,15 +117,10 @@ _compPoints2(const void *p1, const void *p2)
struct kd_point *a = (struct kd_point *) p1;
struct kd_point *b = (struct kd_point *) p2;
- if (a->point[2] > b->point[2]) return 1;
- else if (a->point[2] < b->point[2]) return -1;
- else
- {
- if ( a->index > b->index ) return 1;
- else if ( a->index < b->index ) return -1;
+ int ret = (a->point[2] > b->point[2]) ? 1 : (a->point[2] < b->point[2]) ? -1 : 0;
+ if ( ret == 0 ) ret = (a->index > b->index) ? 1 : (a->index < b->index) ? -1 : 0;
- return 0;
- }
+ return ret;
}
void *
@@ -143,11 +128,11 @@ kd_doBuildTree(void *threadarg)
{
int sortaxis;
unsigned long pivot;
- float tmpMinLeft[KD_MAX_DIM], tmpMaxLeft[KD_MAX_DIM], tmpMinRight[KD_MAX_DIM], tmpMaxRight[KD_MAX_DIM];
+ kdata_t tmpMinLeft[KD_MAX_DIM], tmpMaxLeft[KD_MAX_DIM], tmpMinRight[KD_MAX_DIM], tmpMaxRight[KD_MAX_DIM];
struct kdNode *node;
struct kd_point *points;
unsigned long nPoints;
- float *min, *max;
+ kdata_t *min, *max;
int depth, dim, max_threads;
pthread_t threads[2];
pthread_attr_t attr;
@@ -189,8 +174,8 @@ kd_doBuildTree(void *threadarg)
if ((node = kd_allocNode(points, pivot, min, max, sortaxis, dim)) == NULL)
return NULL;
- memcpy(tmpMinLeft, min, dim * sizeof(float));
- memcpy(tmpMaxLeft, max, dim * sizeof(float));
+ memcpy(tmpMinLeft, min, dim * sizeof(kdata_t));
+ memcpy(tmpMaxLeft, max, dim * sizeof(kdata_t));
tmpMaxLeft[sortaxis] = node->location[sortaxis];
argleft =
kd_buildArg(points, pivot, tmpMinLeft, tmpMaxLeft,
@@ -210,8 +195,8 @@ kd_doBuildTree(void *threadarg)
}
}
- memcpy(tmpMinRight, min, dim * sizeof(float));
- memcpy(tmpMaxRight, max, dim * sizeof(float));
+ memcpy(tmpMinRight, min, dim * sizeof(kdata_t));
+ memcpy(tmpMaxRight, max, dim * sizeof(kdata_t));
tmpMinRight[sortaxis] = node->location[sortaxis];
argright = kd_buildArg(&points[pivot], nPoints - pivot,
tmpMinRight, tmpMaxRight, depth + 1,
@@ -255,7 +240,7 @@ kd_freeNode(kdNode *node)
struct kd_thread_data *
kd_buildArg(struct kd_point *points,
unsigned long nPoints,
- float *min, float *max,
+ kdata_t *min, kdata_t *max,
int depth, int max_threads, int dim)
{
struct kd_thread_data *d;
@@ -264,8 +249,8 @@ kd_buildArg(struct kd_point *points,
return NULL;
d->points = points;
d->nPoints = nPoints;
- memcpy(d->min, min, dim*sizeof(float));
- memcpy(d->max, max, dim*sizeof(float));
+ memcpy(d->min, min, dim*sizeof(kdata_t));
+ memcpy(d->max, max, dim*sizeof(kdata_t));
d->depth = depth;
d->max_threads = max_threads;
d->dim = dim;
@@ -275,16 +260,16 @@ kd_buildArg(struct kd_point *points,
struct kdNode *
kd_allocNode(struct kd_point *points, unsigned long pivot,
- float *min, float *max, int axis, int dim)
+ kdata_t *min, kdata_t *max, int axis, int dim)
{
struct kdNode *node;
if ((node = (kdNode *)kd_malloc(sizeof(kdNode), "kd_allocNode (node): ")) == NULL)
return NULL;
node->split = axis;
- memcpy(node->location, points[pivot].point, dim * sizeof(float));
- memcpy(node->min, min, dim * sizeof(float));
- memcpy(node->max, max, dim * sizeof(float));
+ memcpy(node->location, points[pivot].point, dim * sizeof(kdata_t));
+ memcpy(node->min, min, dim * sizeof(kdata_t));
+ memcpy(node->max, max, dim * sizeof(kdata_t));
node->left = node->right = NULL;
node->index = 0;
return node;
diff --git a/src/kdtreelib/kdtree_spherical.c b/src/kdtreelib/kdtree_spherical.c
index 511790b..ff41230 100644
--- a/src/kdtreelib/kdtree_spherical.c
+++ b/src/kdtreelib/kdtree_spherical.c
@@ -11,11 +11,11 @@
general utility functions
********************************************************************* */
-inline float
-kd_sph_dist_sq(float *x, float *y)
+inline kdata_t
+kd_sph_dist_sq(kdata_t *x, kdata_t *y)
{
- float ds;
- /*float arg;*/
+ kdata_t ds;
+ /*kdata_t arg;*/
if (!x || !y)
return -1;
@@ -29,10 +29,10 @@ kd_sph_dist_sq(float *x, float *y)
return kd_sqr(ds);
}
-inline float
-kd_sph_dist(float *x, float *y)
+inline kdata_t
+kd_sph_dist(kdata_t *x, kdata_t *y)
{
- float ds;
+ kdata_t ds;
if (!x || !y)
return -1;
@@ -42,10 +42,10 @@ kd_sph_dist(float *x, float *y)
return ds;
}
-float
-kd_sph_bearing(float *p1, float *p2)
+kdata_t
+kd_sph_bearing(kdata_t *p1, kdata_t *p2)
{
- float x, y;
+ kdata_t x, y;
x = cos(p1[1]) * sin(p2[1]) - sin(p1[1]) * cos(p2[1]) * cos(p2[0] - p1[0]);
y = sin(p2[0] - p1[0]) * cos(p2[1]);
@@ -62,10 +62,10 @@ kd_sph_bearing(float *p1, float *p2)
*
* \return distance of p3 from the great circle connecting p1 and p2.
*/
-float
-kd_sph_xtd(float *p1, float *p2, float *p3)
+kdata_t
+kd_sph_xtd(kdata_t *p1, kdata_t *p2, kdata_t *p3)
{
- float d13, theta13, theta12;
+ kdata_t d13, theta13, theta12;
d13 = kd_sph_dist(p1, p3);
theta13 = kd_sph_bearing(p1, p3);
@@ -74,12 +74,12 @@ kd_sph_xtd(float *p1, float *p2, float *p3)
}
-float
-kd_sph_orth_dist(float *p1, float *p2, int split)
+kdata_t
+kd_sph_orth_dist(kdata_t *p1, kdata_t *p2, int split)
{
- float ra2, dec2;
- float dx;
+ kdata_t ra2, dec2;
+ kdata_t dx;
if (split == 1) {
ra2 = p1[0];
@@ -129,7 +129,7 @@ kd_sph_orth_dist(float *p1, float *p2, int split)
*/
struct kdNode *
kd_sph_buildTree(struct kd_point *points, unsigned long nPoints,
- float *min, float *max, int max_threads)
+ kdata_t *min, kdata_t *max, int max_threads)
{
struct kd_thread_data *my_data;
struct kdNode *tree;
@@ -154,7 +154,7 @@ kd_sph_buildTree(struct kd_point *points, unsigned long nPoints,
/* Returns 1 if node is a point in the hyperrectangle defined by
minimum and maximum vectors min and max. */
int
-kd_sph_isPointInRect(struct kdNode *node, float *min, float *max)
+kd_sph_isPointInRect(struct kdNode *node, kdata_t *min, kdata_t *max)
{
if (node == NULL)
return 0;
@@ -178,7 +178,7 @@ kd_sph_isPointInRect(struct kdNode *node, float *min, float *max)
the HR described by the minimum and maximum vectors min and
max. Returns 0 otherwise. */
int
-kd_sph_isRectInRect(struct kdNode *node, float *min, float *max)
+kd_sph_isRectInRect(struct kdNode *node, kdata_t *min, kdata_t *max)
{
if (node == NULL)
return 0;
@@ -242,7 +242,7 @@ kd_sph_isRectInRect(struct kdNode *node, float *min, float *max)
by the minimum and maximum vectors min and max. Returns 0
otherwise. */
int
-kd_sph_rectOverlapsRect(struct kdNode *node, float *min, float *max)
+kd_sph_rectOverlapsRect(struct kdNode *node, kdata_t *min, kdata_t *max)
{
if (node == NULL)
return 0;
@@ -274,7 +274,7 @@ kd_sph_rectOverlapsRect(struct kdNode *node, float *min, float *max)
* Rectangle must not cross the meridian!
*/
struct pqueue *
-kd_sph_ortRangeSearch(struct kdNode *node, float *min, float *max)
+kd_sph_ortRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max)
{
struct pqueue *res;
uint32_t i;
@@ -296,7 +296,7 @@ kd_sph_ortRangeSearch(struct kdNode *node, float *min, float *max)
/* This is the orthogonal range search. Returns 1 if okay, 0 in case
of problems. */
int
-kd_sph_doOrtRangeSearch(struct kdNode *node, float *min, float *max,
+kd_sph_doOrtRangeSearch(struct kdNode *node, kdata_t *min, kdata_t *max,
struct pqueue *res)
{
@@ -342,11 +342,11 @@ kd_sph_doOrtRangeSearch(struct kdNode *node, float *min, float *max,
* neigbor.
*/
struct kdNode *
-kd_sph_nearest(struct kdNode *node, float *p, float *max_dist_sq)
+kd_sph_nearest(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq)
{
struct kdNode *nearer, *further, *nearest, *tmp, *tmp_nearest;
- float dist_sq, tmp_dist_sq, dx;
- float p1[2], p2[2];
+ kdata_t dist_sq, tmp_dist_sq, dx;
+ kdata_t p1[2], p2[2];
if (!node)
return NULL;
@@ -431,8 +431,8 @@ kd_sph_nearest(struct kdNode *node, float *p, float *max_dist_sq)
* in case of problems.
*/
struct pqueue *
-kd_sph_qnearest(struct kdNode *node, float *p,
- float *max_dist_sq, unsigned int q)
+kd_sph_qnearest(struct kdNode *node, kdata_t *p,
+ kdata_t *max_dist_sq, unsigned int q)
{
struct pqueue *res;
uint32_t i;
@@ -460,13 +460,13 @@ kd_sph_qnearest(struct kdNode *node, float *p,
* return 1 if okay, zero in case of problems
*/
int
-kd_sph_doQnearest(struct kdNode *node, float *p, float *max_dist_sq,
+kd_sph_doQnearest(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
unsigned int q, struct pqueue *res)
{
struct kdNode *nearer, *further;
struct resItem *point, *item;
- float dist_sq, dx;
- float p1[2], p2[2];
+ kdata_t dist_sq, dx;
+ kdata_t p1[2], p2[2];
if (!node)
return 1;
@@ -585,7 +585,7 @@ kd_sph_doQnearest(struct kdNode *node, float *p, float *max_dist_sq,
* NULL in case of problems.
*/
struct pqueue *
-kd_sph_range(struct kdNode *node, float *p, float *max_dist_sq, int ordered)
+kd_sph_range(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq, int ordered)
{
struct pqueue *res;
uint32_t i;
@@ -606,14 +606,14 @@ kd_sph_range(struct kdNode *node, float *p, float *max_dist_sq, int ordered)
/* This is the range search. Returns 1 if okay, 0 in case of problems */
int
-kd_sph_doRange(struct kdNode *node, float *p, float *max_dist_sq,
+kd_sph_doRange(struct kdNode *node, kdata_t *p, kdata_t *max_dist_sq,
struct pqueue *res, int ordered)
{
struct kdNode *nearer, *further;
struct resItem *point;
- float dist_sq, dx;
- float p1[2], p2[2];
+ kdata_t dist_sq, dx;
+ kdata_t p1[2], p2[2];
if (!node)
return 1;
diff --git a/src/kvlist.c b/src/kvlist.c
index 0315c14..f6e5e4a 100644
--- a/src/kvlist.c
+++ b/src/kvlist.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/kvlist.h b/src/kvlist.h
index 3d0ca33..53d8ecd 100644
--- a/src/kvlist.h
+++ b/src/kvlist.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/list.c b/src/list.c
index 3158d76..607d7aa 100644
--- a/src/list.c
+++ b/src/list.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/list.h b/src/list.h
index 49a9fe2..e42a55c 100644
--- a/src/list.h
+++ b/src/list.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/magics_template_parser.c b/src/magics_template_parser.c
index dc4c23e..63759a5 100644
--- a/src/magics_template_parser.c
+++ b/src/magics_template_parser.c
@@ -2,25 +2,34 @@
# include "config.h" /* HAVE_LIBMAGICS */
#endif
+#include "cdo_int.h"
#include "magics_template_parser.h"
#include "StringUtilities.h"
+#if defined(HAVE_LIBXML2)
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
+#if defined(HAVE_LIBMAGICS)
#include "magics_api.h"
+#endif
-#define DBG 0
+#define DBG 0
-extern xmlNode *magics_node;
+extern void *magics_node;
/* Recursive function that sets the Magics parameters from the XML structure */
-int magics_template_parser( xmlNode *a_node )
-
+int magics_template_parser( void *node )
{
+#if defined(HAVE_LIBXML2)
+ xmlNode *a_node = (xmlNode*) node;
int param_set_flag;
xmlNode *cur_node = NULL;
- xmlChar *param_name,*param_type,*param_value,*value;
+ const char *param_name,*param_type,*param_value;
if( a_node == NULL )
return 0;
@@ -29,21 +38,20 @@ int magics_template_parser( xmlNode *a_node )
fprintf( stdout,"Parsing the magics Node \n");
#endif
- if( !strcmp( a_node->name, "magics" ) )
+ if( !strcmp( (const char*)a_node->name, "magics" ) )
{
- value = xmlGetProp( a_node, "version" );
+ const char *value = (const char*) xmlGetProp( a_node, (const xmlChar *)"version" );
- if( value )
+ if( value )
{
- if( DBG )
- printf( "Version %s \n", value );
+ if( DBG )
+ printf( "Version %s \n", value );
- if( atof( value ) > 3.0f )
- {
- return 1;
- }
+ if( atof( value ) > 3.0f )
+ {
+ return 1;
+ }
}
-
}
@@ -73,33 +81,40 @@ int magics_template_parser( xmlNode *a_node )
else
{
- param_name = xmlGetProp( cur_node,"parameter");
- param_type = xmlGetProp(cur_node,"type");
- param_value = xmlGetProp(cur_node,"value");
+ param_name = (const char *)xmlGetProp(cur_node, (const xmlChar *)"parameter");
+ param_type = (const char *)xmlGetProp(cur_node, (const xmlChar *)"type");
+ param_value = (const char *)xmlGetProp(cur_node, (const xmlChar *)"value");
#if 0
printf( "\t\tAttr name: %s Type: %s Value: %s \n", param_name,param_type,param_value);
#endif
- param_set_flag = SetMagicsParameterValue( param_name, param_type, param_value );
+ param_set_flag = SetMagicsParameterValue(param_name, param_type, param_value );
if( param_set_flag )
printf(" Error in Setting the Parameter %s\n",param_name );
}
}
}
- return 0;
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
+
+ return 0;
}
-int SetMagicsParameterValue( char *param_name, char *param_type, char *param_value )
+int SetMagicsParameterValue( const char *param_name, const char *param_type, const char *param_value )
{
- int i, ret_flag = 0;
+ int ret_flag = 0;
+#if defined(HAVE_LIBMAGICS)
+ int i;
int split_str_count = 0;
char **split_str = NULL;
- char *sep_char = ",";
- char *search_char = ";";
+ const char *sep_char = ",";
+ const char *search_char = ";";
double *float_param_list = NULL;
- int *int_param_list = NULL;
if( param_name == NULL )
{
@@ -194,14 +209,14 @@ int SetMagicsParameterValue( char *param_name, char *param_type, char *param_val
split_str_count = StringSplitWithSeperator( param_value, sep_char, &split_str );
if( split_str_count )
{
- int_param_list = (double*) Malloc(sizeof( int ) * split_str_count );
- for( i = 0; i < split_str_count; i++ )
- {
- int_param_list[i] = atoi( split_str[i] );
- }
- mag_set1i( param_name, int_param_list, split_str_count );
- Free( int_param_list );
- Free( split_str );
+ int *int_param_list = (int*) Malloc(sizeof( int ) * split_str_count );
+ for( i = 0; i < split_str_count; i++ )
+ {
+ int_param_list[i] = atoi( split_str[i] );
+ }
+ mag_set1i( param_name, int_param_list, split_str_count );
+ Free( int_param_list );
+ Free( split_str );
}
}
@@ -236,6 +251,7 @@ int SetMagicsParameterValue( char *param_name, char *param_type, char *param_val
ret_flag = 3;
fprintf(stderr, "Unknown Parameter Type\n" );
}
-
+#endif
+
return ret_flag;
}
diff --git a/src/magics_template_parser.h b/src/magics_template_parser.h
index 01192b2..a87999b 100644
--- a/src/magics_template_parser.h
+++ b/src/magics_template_parser.h
@@ -1,15 +1,8 @@
#ifndef MAGICS_TEMPLATE_PARSER_HH
#define MAGICS_TEMPLATE_PARSER_HH
-#endif
-
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
-#include<locale.h>
-#include<libxml/parser.h>
-#include<libxml/tree.h>
+int magics_template_parser( void *node );
-int magics_template_parser( xmlNode * a_node );
+int SetMagicsParameterValue( const char *param_name, const char *param_type, const char *param_value );
-int SetMagicsParameterValue( char *param_name, char *param_type, char *param_value );
+#endif
diff --git a/src/modules.c b/src/modules.c
index aaa413f..861bcf5 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -26,15 +26,16 @@
#include "error.h"
-#define MAX_MOD_OPERATORS 128 /* maximum number of operators for a module */
+#define MAX_MOD_OPERATORS 128 // maximum number of operators for a module
typedef struct {
- void *(*func)(void *); /* Module */
- const char **help; /* Help */
- const char *operators[MAX_MOD_OPERATORS]; /* Operator names */
- short number; /* Allowed number type */
- short streamInCnt; /* Number of input streams */
- short streamOutCnt; /* Number of output streams */
+ void *(*func)(void *); // Module
+ const char **help; // Help
+ const char *operators[MAX_MOD_OPERATORS]; // Operator names
+ short mode; // Module mode: 0:intern 1:extern
+ short number; // Allowed number type
+ short streamInCnt; // Number of input streams
+ short streamOutCnt; // Number of output streams
}
modules_t;
@@ -128,6 +129,7 @@ void *Nmltest(void *argument);
void *Output(void *argument);
void *Outputgmt(void *argument);
void *Pack(void *argument);
+void *Pardup(void *argument);
void *Pinfo(void *argument);
void *Pressure(void *argument);
void *Regres(void *argument);
@@ -180,6 +182,7 @@ void *Test(void *argument);
void *Test2(void *argument);
void *Testdata(void *argument);
void *Tests(void *argument);
+void *Timedt(void *argument);
void *Timsort(void *argument);
void *Timcount(void *argument);
void *Timpctl(void *argument);
@@ -195,7 +198,6 @@ void *Transpose(void *argument);
void *Trend(void *argument);
void *Trms(void *argument);
void *Tstepcount(void *argument);
-void *Vardup(void *argument);
void *Vargen(void *argument);
void *Varrms(void *argument);
void *Vertintml(void *argument);
@@ -203,6 +205,7 @@ void *Vertintap(void *argument);
void *Vertstat(void *argument);
void *Vertcum(void *argument);
void *Vertwind(void *argument);
+void *Verifygrid(void *argument);
void *Wind(void *argument);
void *Writegrid(void *argument);
void *Writerandom(void *argument);
@@ -267,15 +270,13 @@ void *Hurr(void *argument);
//void *Hi(void *argument);
void *Wct(void *argument);
-#if defined(HAVE_LIBMAGICS) && defined(HAVE_LIBXML2)
void *Magplot(void *argument);
void *Magvector(void *argument);
void *Maggraph(void *argument);
-#endif
#define AdisitOperators {"adisit", "adipot"}
-#define AfterburnerOperators {"afterburner", "after"}
+#define AfterburnerOperators {"after"}
#define ArithOperators {"add", "sub", "mul", "div", "min", "max", "atan2"}
#define ArithcOperators {"addc", "subc", "mulc", "divc", "mod"}
#define ArithdaysOperators {"muldpm", "divdpm", "muldpy", "divdpy", "muldoy"}
@@ -309,8 +310,8 @@ void *Maggraph(void *argument);
#define EnlargeOperators {"enlarge"}
#define EnlargegridOperators {"enlargegrid"}
#define EnsstatOperators {"ensmin", "ensmax", "enssum", "ensmean", "ensavg", "ensvar", "ensvar1", "ensstd", "ensstd1", "enspctl"}
-#define Ensstat3Operators {"ensrkhist_space","ensrkhist_time","ensroc"}
-#define EnsvalOperators {"enscrps","ensbrs"}
+#define Ensstat3Operators {"ensrkhistspace", "ensrkhisttime", "ensroc"}
+#define EnsvalOperators {"enscrps", "ensbrs"}
#define EofcoeffOperators {"eofcoeff"}
#define Eofcoeff3dOperators {"eofcoeff3d"}
#define EOFsOperators {"eof", "eofspatial", "eoftime"}
@@ -334,7 +335,7 @@ void *Maggraph(void *argument);
#define HarmonicOperators {"harmonic"}
#define HistogramOperators {"histcount", "histsum", "histmean", "histfreq"}
#define ImportamsrOperators {"import_amsr"}
-#define ImportbinaryOperators {"import_binary", "import_grads"}
+#define ImportbinaryOperators {"import_binary"}
#define ImportcmsafOperators {"import_cmsaf"}
#define ImportobsOperators {"import_obs"}
#define InfoOperators {"info", "infop", "infon", "infoc", "map"}
@@ -368,9 +369,10 @@ void *Maggraph(void *argument);
#define OutputOperators {"output", "outputint", "outputsrv", "outputext", "outputf", "outputts", \
"outputfld", "outputarr", "outputxyz"}
#define OutputtabOperators {"outputtab"}
-#define OutputgmtOperators {"gridverify", "outputcenter", "outputcenter2", "outputcentercpt", "outputbounds", \
+#define OutputgmtOperators {"gmtxyz", "gmtcells", "outputcenter2", "outputcentercpt", \
"outputboundscpt", "outputvector", "outputtri", "outputvrml"}
#define PackOperators {"pack"}
+#define PardupOperators {"pardup", "parmul"}
#define PinfoOperators {"pinfo", "pinfov"}
#define PressureOperators {"pressure_fl", "pressure_hl", "deltap"}
#define RegresOperators {"regres"}
@@ -400,7 +402,7 @@ void *Maggraph(void *argument);
"selzaxis", "selzaxisname", "seltabnum", "delparam", "delcode", "delname", "selltype"}
#define SeloperatorOperators {"seloperator"}
#define SelrecOperators {"selrec"}
-#define SeltimeOperators {"seltimestep", "selyear", "selseas", "selmon", "selday", "selhour", "seldate", \
+#define SeltimeOperators {"seltimestep", "selyear", "selseason", "selmonth", "selday", "selhour", "seldate", \
"seltime", "selsmon"}
#define SetOperators {"setcode", "setparam", "setname", "setunit", "setlevel", "setltype", "settabnum"}
#define SetboxOperators {"setclonlatbox", "setcindexbox"}
@@ -438,6 +440,7 @@ void *Maggraph(void *argument);
#define Test2Operators {"test2"}
#define TestdataOperators {"testdata"}
#define TestsOperators {"normal", "studentt", "chisquare", "beta", "fisher"}
+#define TimedtOperators {"timedt"}
#define TimsortOperators {"timsort"}
#define TimcountOperators {"timcount"}
#define YearcountOperators {"yearcount"}
@@ -468,7 +471,6 @@ void *Maggraph(void *argument);
#define TrendOperators {"trend"}
#define TrmsOperators {"trms"}
#define TstepcountOperators {"tstepcount"}
-#define VardupOperators {"pardup", "parmul"}
#define VargenOperators {"random", "const", "sincos", "coshill", "for", "topo", "temp", "mask", "stdatm"}
#define VarrmsOperators {"varrms"}
#define VertintmlOperators {"ml2pl", "ml2hl", "ml2plx", "ml2hlx", "ml2pl_lp", "ml2hl_lp", "ml2plx_lp", "ml2hlx_lp"}
@@ -476,6 +478,7 @@ void *Maggraph(void *argument);
#define VertstatOperators {"vertmin", "vertmax", "vertsum", "vertint", "vertmean", "vertavg", "vertstd", "vertstd1", "vertvar", "vertvar1"}
#define VertcumOperators {"vertcum", "vertcumhl"}
#define VertwindOperators {"vertwind"}
+#define VerifygridOperators {"verifygrid", "verifygridtest"}
#define WindOperators {"uv2dv", "uv2dvl", "dv2uv", "dv2uvl", "dv2ps"}
#define WritegridOperators {"writegrid"}
#define WriterandomOperators {"writerandom"}
@@ -546,327 +549,329 @@ void *Maggraph(void *argument);
#define HiOperators {"hi"}
#define WctOperators {"wct"}
-#if defined(HAVE_LIBMAGICS) && defined(HAVE_LIBXML2)
#define MagplotOperators {"contour", "shaded", "grfill"}
-#define MagvectorOperators {"vector", "stream"}
+#define MagvectorOperators {"vector"}
#define MaggraphOperators {"graph"}
-#endif
static modules_t Modules[] =
{
- /* stream out -1 means usage of obase */
+ // stream in -1 means: unlimited number of input streams
+ // stream out -1 means: usage of obase
/*
- function help function operator names number num streams
- type in out
+ function help function operator names mode number num streams
+ type in out
*/
- { Adisit, AdisitHelp, AdisitOperators, CDI_REAL, 1, 1 },
- { Afterburner, AfterburnerHelp, AfterburnerOperators, CDI_REAL, -1, 1 },
- { Arith, ArithHelp, ArithOperators, CDI_REAL, 2, 1 },
- { Arithc, ArithcHelp, ArithcOperators, CDI_REAL, 1, 1 },
- { Arithdays, ArithdaysHelp, ArithdaysOperators, CDI_REAL, 1, 1 },
- { Arithlat, NULL, ArithlatOperators, CDI_REAL, 1, 1 },
- { Cat, CopyHelp, CatOperators, CDI_REAL, -1, 1 },
- { CDItest, NULL, CDItestOperators, CDI_REAL, 1, 1 },
- { CDIread, NULL, CDIreadOperators, CDI_REAL, 1, 0 },
- { CDIwrite, NULL, CDIwriteOperators, CDI_REAL, 0, 1 },
- { Change, ChangeHelp, ChangeOperators, CDI_REAL, 1, 1 },
- { Change_e5slm, NULL, Change_e5slmOperators, CDI_REAL, 1, 1 },
- { Cloudlayer, NULL, CloudlayerOperators, CDI_REAL, 1, 1 },
- { CMOR, NULL, CMOROperators, CDI_REAL, 1, 0 },
- { Collgrid, CollgridHelp, CollgridOperators, CDI_REAL, -1, 1 },
- { Command, NULL, CommandOperators, CDI_REAL, 1, 0 },
- { Comp, CompHelp, CompOperators, CDI_REAL, 2, 1 },
- { Compc, CompcHelp, CompcOperators, CDI_REAL, 1, 1 },
- { Complextorect, NULL, ComplextorectOperators, CDI_COMP, 1, 2 },
- { Cond, CondHelp, CondOperators, CDI_REAL, 2, 1 },
- { Cond2, Cond2Help, Cond2Operators, CDI_REAL, 3, 1 },
- { Condc, CondcHelp, CondcOperators, CDI_REAL, 1, 1 },
- { Consecstat, ConsecstatHelp, ConsecstatOperators, CDI_REAL, 1, 1 },
- { Copy, CopyHelp, CopyOperators, CDI_REAL, -1, 1 },
- { Deltime, NULL, DeltimeOperators, CDI_REAL, 1, 1 },
- { Derivepar, DeriveparHelp, DeriveparOperators, CDI_REAL, 1, 1 },
- { Detrend, DetrendHelp, DetrendOperators, CDI_REAL, 1, 1 },
- { Diff, DiffHelp, DiffOperators, CDI_REAL, 2, 0 },
- { Distgrid, DistgridHelp, DistgridOperators, CDI_REAL, 1, 1 },
- { Duplicate, DuplicateHelp, DuplicateOperators, CDI_REAL, 1, 1 },
- { Echam5ini, NULL, Echam5iniOperators, CDI_REAL, 1, 1 },
- { Enlarge, EnlargeHelp, EnlargeOperators, CDI_REAL, 1, 1 },
- { Enlargegrid, NULL, EnlargegridOperators, CDI_REAL, 1, 1 },
- { Ensstat, EnsstatHelp, EnsstatOperators, CDI_REAL, -1, 1 },
- { Ensstat3, Ensstat2Help, Ensstat3Operators, CDI_REAL, -1, 1 },
- { Ensval, EnsvalHelp, EnsvalOperators, CDI_REAL, -1, 1 },
- { Eofcoeff, EofcoeffHelp, EofcoeffOperators, CDI_REAL, 2, -1 },
- { Eofcoeff3d, EofcoeffHelp, Eofcoeff3dOperators, CDI_REAL, 2, -1 },
- { EOFs, EOFsHelp, EOFsOperators, CDI_REAL, 1, 2 },
- { EOF3d, EOFsHelp, EOF3dOperators, CDI_REAL, 1, 2 },
- { Expr, ExprHelp, ExprOperators, CDI_REAL, 1, 1 },
- { FC, NULL, FCOperators, CDI_REAL, 1, 1 },
- { Filedes, FiledesHelp, FiledesOperators, CDI_BOTH, 1, 0 },
- { Fillmiss, NULL, FillmissOperators, CDI_REAL, 1, 1 },
- { Filter, FilterHelp, FilterOperators, CDI_REAL, 1, 1 },
- { Fldrms, NULL, FldrmsOperators, CDI_REAL, 2, 1 },
- { Fldstat, FldstatHelp, FldstatOperators, CDI_REAL, 1, 1 },
- { Fldstat2, FldcorHelp, FldcorOperators, CDI_REAL, 2, 1 },
- { Fldstat2, FldcovarHelp, FldcovarOperators, CDI_REAL, 2, 1 },
- { Fourier, NULL, FourierOperators, CDI_COMP, 1, 1 },
- { Gengrid, NULL, GengridOperators, CDI_REAL, 2, 1 },
- { Gradsdes, GradsdesHelp, GradsdesOperators, CDI_REAL, 1, 0 },
- { Gridboxstat, GridboxstatHelp, GridboxstatOperators, CDI_REAL, 1, 1 },
- { Gridcell, GridcellHelp, GridcellOperators, CDI_REAL, 1, 1 },
- { Gridsearch, NULL, GridsearchOperators, CDI_REAL, 0, 0 },
- { Harmonic, NULL, HarmonicOperators, CDI_REAL, 1, 1 },
- { Histogram, HistogramHelp, HistogramOperators, CDI_REAL, 1, 1 },
- { Importamsr, ImportamsrHelp, ImportamsrOperators, CDI_REAL, 1, 1 },
- { Importbinary, ImportbinaryHelp, ImportbinaryOperators, CDI_REAL, 1, 1 },
- { Importcmsaf, ImportcmsafHelp, ImportcmsafOperators, CDI_REAL, 1, 1 },
- { Importobs, NULL, ImportobsOperators, CDI_REAL, 1, 1 },
- { Info, InfoHelp, InfoOperators, CDI_BOTH, -1, 0 },
- { Input, InputHelp, InputOperators, CDI_REAL, 0, 1 },
- { Intgrid, NULL, IntgridOperators, CDI_REAL, 1, 1 },
- { Intgridtraj, NULL, IntgridtrajOperators, CDI_REAL, 1, 1 },
- { Intlevel, IntlevelHelp, IntlevelOperators, CDI_REAL, 1, 1 },
- { Intlevel3d, Intlevel3dHelp, Intlevel3dOperators, CDI_REAL, 2, 1 },
- { Inttime, InttimeHelp, InttimeOperators, CDI_REAL, 1, 1 },
- { Intntime, InttimeHelp, IntntimeOperators, CDI_REAL, 1, 1 },
- { Intyear, IntyearHelp, IntyearOperators, CDI_REAL, 2, -1 },
- { Invert, InvertHelp, InvertOperators, CDI_REAL, 1, 1 },
- { Invertlev, InvertlevHelp, InvertlevOperators, CDI_REAL, 1, 1 },
- { Isosurface, NULL, IsosurfaceOperators, CDI_REAL, 1, 1 },
- { Kvl, NULL, KvlOperators, CDI_REAL, 0, 0 },
- { Log, NULL, LogOperators, CDI_REAL, 1, 0 },
- { Maskbox, MaskboxHelp, MaskboxOperators, CDI_REAL, 1, 1 },
- { Maskbox, MaskregionHelp, MaskregionOperators, CDI_REAL, 1, 1 },
- { Mastrfu, MastrfuHelp, MastrfuOperators, CDI_REAL, 1, 1 },
- { Math, MathHelp, MathOperators, CDI_BOTH, 1, 1 },
- { Merge, MergeHelp, MergeOperators, CDI_REAL, -1, 1 },
- { Mergetime, MergeHelp, MergetimeOperators, CDI_REAL, -1, 1 },
- { Mergegrid, MergegridHelp, MergegridOperators, CDI_REAL, 2, 1 },
- { Merstat, MerstatHelp, MerstatOperators, CDI_REAL, 1, 1 },
- { Monarith, MonarithHelp, MonarithOperators, CDI_REAL, 2, 1 },
- { Mrotuv, NULL, MrotuvOperators, CDI_REAL, 1, 2 },
- { Mrotuvb, NULL, MrotuvbOperators, CDI_REAL, 2, 1 },
- { Ninfo, NinfoHelp, NinfoOperators, CDI_BOTH, 1, 0 },
- { Nmltest, NULL, NmltestOperators, CDI_REAL, 0, 0 },
- { Output, OutputHelp, OutputOperators, CDI_REAL, -1, 0 },
- { Output, OutputtabHelp, OutputtabOperators, CDI_REAL, -1, 0 },
- { Outputgmt, NULL, OutputgmtOperators, CDI_REAL, 1, 0 },
- { Pack, NULL, PackOperators, CDI_REAL, 1, 1 },
- { Pinfo, NULL, PinfoOperators, CDI_REAL, 1, 1 },
- { Pressure, NULL, PressureOperators, CDI_REAL, 1, 1 },
- { Regres, RegresHelp, RegresOperators, CDI_REAL, 1, 1 },
- { Remap, RemapHelp, RemapOperators, CDI_REAL, 1, 1 },
- { Remap, RemapbilHelp, RemapbilOperators, CDI_REAL, 1, 1 },
- { Remap, RemapbicHelp, RemapbicOperators, CDI_REAL, 1, 1 },
- { Remap, RemapnnHelp, RemapnnOperators, CDI_REAL, 1, 1 },
- { Remap, RemapdisHelp, RemapdisOperators, CDI_REAL, 1, 1 },
- { Remap, RemapyconHelp, RemapyconOperators, CDI_REAL, 1, 1 },
- { Remap, RemapconHelp, RemapconOperators, CDI_REAL, 1, 1 },
- { Remap, Remapcon2Help, Remapcon2Operators, CDI_REAL, 1, 1 },
- { Remap, RemaplafHelp, RemaplafOperators, CDI_REAL, 1, 1 },
- { Remap, NULL, RemapgridOperators, CDI_REAL, 1, 1 },
- { Remapeta, RemapetaHelp, RemapetaOperators, CDI_REAL, 1, 1 },
- { Replace, ReplaceHelp, ReplaceOperators, CDI_REAL, 2, 1 },
- { Replacevalues, ReplacevaluesHelp, ReplacevaluesOperators, CDI_REAL, 1, 1 },
- { Rhopot, RhopotHelp, RhopotOperators, CDI_REAL, 1, 1 },
- { Rotuv, RotuvbHelp, RotuvOperators, CDI_REAL, 1, 1 },
- { Runpctl, RunpctlHelp, RunpctlOperators, CDI_REAL, 1, 1 },
- { Runstat, RunstatHelp, RunstatOperators, CDI_REAL, 1, 1 },
- { Seascount, NULL, SeascountOperators, CDI_BOTH, 1, 1 },
- { Seaspctl, SeaspctlHelp, SeaspctlOperators, CDI_REAL, 3, 1 },
- { Seasstat, SeasstatHelp, SeasstatOperators, CDI_REAL, 1, 1 },
- { Selbox, SelboxHelp, SelboxOperators, CDI_BOTH, 1, 1 },
- { Select, SelectHelp, SelectOperators, CDI_BOTH, -1, 1 },
- { Selvar, SelvarHelp, SelvarOperators, CDI_BOTH, 1, 1 },
- { Selrec, SelvarHelp, SelrecOperators, CDI_BOTH, 1, 1 },
- { Seloperator, NULL, SeloperatorOperators, CDI_REAL, 1, 1 },
- { Seltime, SeltimeHelp, SeltimeOperators, CDI_BOTH, 1, 1 },
- { Set, SetHelp, SetOperators, CDI_BOTH, 1, 1 },
- { Setbox, SetboxHelp, SetboxOperators, CDI_REAL, 1, 1 },
- { Setgatt, SetgattHelp, SetgattOperators, CDI_BOTH, 1, 1 },
- { Setgrid, SetgridHelp, SetgridOperators, CDI_BOTH, 1, 1 },
- { Sethalo, SethaloHelp, SethaloOperators, CDI_REAL, 1, 1 },
- { Setmiss, SetmissHelp, SetmissOperators, CDI_REAL, 1, 1 },
- { Fillmiss, SetmissHelp, SetmisstonnOperators, CDI_REAL, 1, 1 },
- { Setpartab, SetHelp, Setpartab0Operators, CDI_REAL, 1, 1 },
- { Setpartab, SetpartabHelp, SetpartabOperators, CDI_REAL, 1, 1 },
- { Setrcaname, NULL, SetrcanameOperators, CDI_REAL, 1, 1 },
- { Settime, SettimeHelp, SettimeOperators, CDI_BOTH, 1, 1 },
- { Setzaxis, SetzaxisHelp, SetzaxisOperators, CDI_BOTH, 1, 1 },
- { Showinfo, ShowinfoHelp, ShowinfoOperators, CDI_BOTH, 1, 0 },
- { Sinfo, SinfoHelp, SinfoOperators, CDI_BOTH, -1, 0 },
- { Smooth9, Smooth9Help, Smooth9Operators, CDI_REAL, 1, 1 },
- { Sort, NULL, SortOperators, CDI_REAL, 1, 1 },
- { Sorttimestamp, NULL, SorttimestampOperators, CDI_REAL, -1, 1 },
- { Specinfo, NULL, SpecinfoOperators, CDI_REAL, 0, 0 },
- { Spectral, SpectralHelp, SpectralOperators, CDI_REAL, 1, 1 },
- { Spectrum, NULL, SpectrumOperators, CDI_REAL, 1, 1 },
- { Split, SplitHelp, SplitOperators, CDI_BOTH, 1, -1 },
- { Splitrec, SplitHelp, SplitrecOperators, CDI_BOTH, 1, -1 },
- { Splitsel, SplitselHelp, SplitselOperators, CDI_BOTH, 1, -1 },
- { Splittime, SplittimeHelp, SplittimeOperators, CDI_BOTH, 1, -1 },
- { Splityear, SplittimeHelp, SplityearOperators, CDI_BOTH, 1, -1 },
- { SSOpar, NULL, SSOparOperators, CDI_REAL, 1, 1 },
- { Subtrend, SubtrendHelp, SubtrendOperators, CDI_REAL, 3, 1 },
- { Template1, NULL, Template1Operators, CDI_REAL, 1, 1 },
- { Tee, NULL, TeeOperators, CDI_REAL, 2, 1 },
- { Template2, NULL, Template2Operators, CDI_REAL, 1, 1 },
- { Test, NULL, TestOperators, CDI_REAL, 1, 1 },
- { Test2, NULL, Test2Operators, CDI_REAL, 2, 1 },
- { Testdata, NULL, TestdataOperators, CDI_REAL, 1, 1 },
- { Tests, NULL, TestsOperators, CDI_REAL, 1, 1 },
- { Timcount, NULL, TimcountOperators, CDI_BOTH, 1, 1 },
- { Timcount, NULL, YearcountOperators, CDI_BOTH, 1, 1 },
- { Timcount, NULL, MoncountOperators, CDI_BOTH, 1, 1 },
- { Timcount, NULL, DaycountOperators, CDI_BOTH, 1, 1 },
- { Timcount, NULL, HourcountOperators, CDI_BOTH, 1, 1 },
- { Timpctl, TimpctlHelp, TimpctlOperators, CDI_REAL, 3, 1 },
- { Timpctl, YearpctlHelp, YearpctlOperators, CDI_REAL, 3, 1 },
- { Timpctl, MonpctlHelp, MonpctlOperators, CDI_REAL, 3, 1 },
- { Timpctl, DaypctlHelp, DaypctlOperators, CDI_REAL, 3, 1 },
- { Timpctl, HourpctlHelp, HourpctlOperators, CDI_REAL, 3, 1 },
- { Timselpctl, TimselpctlHelp, TimselpctlOperators, CDI_REAL, 3, 1 },
- { Timsort, TimsortHelp, TimsortOperators, CDI_REAL, 1, 1 },
- { Timselstat, TimselstatHelp, TimselstatOperators, CDI_REAL, 1, 1 },
- { XTimstat, NULL, XTimstatOperators, CDI_BOTH, 1, 1 },
- { Timstat, TimstatHelp, TimstatOperators, CDI_BOTH, 1, 1 },
- { Timstat, YearstatHelp, YearstatOperators, CDI_BOTH, 1, 1 },
- { Timstat, MonstatHelp, MonstatOperators, CDI_BOTH, 1, 1 },
- { Timstat, DaystatHelp, DaystatOperators, CDI_BOTH, 1, 1 },
- { Timstat, HourstatHelp, HourstatOperators, CDI_BOTH, 1, 1 },
- { Timstat2, TimcorHelp, TimcorOperators, CDI_REAL, 2, 1 },
- { Timstat2, TimcovarHelp, TimcovarOperators, CDI_REAL, 2, 1 },
- { Timstat3, NULL, Timstat3Operators, CDI_REAL, 2, 1 },
- { Tinfo, NULL, TinfoOperators, CDI_BOTH, 1, 0 },
- { Tocomplex, NULL, TocomplexOperators, CDI_REAL, 1, 1 },
- { Transpose, NULL, TransposeOperators, CDI_REAL, 1, 1 },
- { Trend, TrendHelp, TrendOperators, CDI_REAL, 1, 2 },
- { Trms, NULL, TrmsOperators, CDI_REAL, 2, 1 },
- { Tstepcount, NULL, TstepcountOperators, CDI_REAL, 1, 1 },
- { Vardup, NULL, VardupOperators, CDI_REAL, 1, 1 },
- { Vargen, VargenHelp, VargenOperators, CDI_REAL, 0, 1 },
- { Varrms, NULL, VarrmsOperators, CDI_REAL, 2, 1 },
- { Vertintml, VertintmlHelp, VertintmlOperators, CDI_REAL, 1, 1 },
- { Vertintap, VertintapHelp, VertintapOperators, CDI_REAL, 1, 1 },
- { Vertstat, VertstatHelp, VertstatOperators, CDI_REAL, 1, 1 },
- { Vertcum, NULL, VertcumOperators, CDI_REAL, 1, 1 },
- { Vertwind, NULL, VertwindOperators, CDI_REAL, 1, 1 },
- { Wind, WindHelp, WindOperators, CDI_REAL, 1, 1 },
- { Writegrid, NULL, WritegridOperators, CDI_REAL, 1, 1 }, /* no cdi output */
- { Writerandom, NULL, WriterandomOperators, CDI_REAL, 1, 1 },
- { YAR, NULL, YAROperators, CDI_REAL, 1, 1 },
- { Yearmonstat, YearmonstatHelp, YearmonstatOperators, CDI_REAL, 1, 1 },
- { Ydayarith, YdayarithHelp, YdayarithOperators, CDI_REAL, 2, 1 },
- { Ydaypctl, YdaypctlHelp, YdaypctlOperators, CDI_REAL, 3, 1 },
- { Ydaystat, YdaystatHelp, YdaystatOperators, CDI_REAL, 1, 1 },
- { Ydrunpctl, YdrunpctlHelp, YdrunpctlOperators, CDI_REAL, 3, 1 },
- { Ydrunstat, YdrunstatHelp, YdrunstatOperators, CDI_REAL, 1, 1 },
- { Yhourarith, YhourarithHelp, YhourarithOperators, CDI_REAL, 2, 1 },
- { Yhourstat, YhourstatHelp, YhourstatOperators, CDI_REAL, 1, 1 },
- { Ymonarith, YmonarithHelp, YmonarithOperators, CDI_REAL, 2, 1 },
- { Ymonarith, YseasarithHelp, YseasarithOperators, CDI_REAL, 2, 1 },
- { Ymonpctl, YmonpctlHelp, YmonpctlOperators, CDI_REAL, 3, 1 },
- { Ymonstat, YmonstatHelp, YmonstatOperators, CDI_REAL, 1, 1 },
- { Yseaspctl, YseaspctlHelp, YseaspctlOperators, CDI_REAL, 3, 1 },
- { Yseasstat, YseasstatHelp, YseasstatOperators, CDI_REAL, 1, 1 },
- { Zonstat, ZonstatHelp, ZonstatOperators, CDI_REAL, 1, 1 },
- { EcaCfd, EcaCfdHelp, EcaCfdOperators, CDI_REAL, 1, 1 },
- { EcaCsu, EcaCsuHelp, EcaCsuOperators, CDI_REAL, 1, 1 },
- { EcaCwdi, EcaCwdiHelp, EcaCwdiOperators, CDI_REAL, 2, 1 },
- { EcaCwfi, EcaCwfiHelp, EcaCwfiOperators, CDI_REAL, 2, 1 },
- { EcaEtr, EcaEtrHelp, EcaEtrOperators, CDI_REAL, 2, 1 },
- { EcaFd, EcaFdHelp, EcaFdOperators, CDI_REAL, 1, 1 },
- { EcaGsl, EcaGslHelp, EcaGslOperators, CDI_REAL, 2, 1 },
- { EcaHd, EcaHdHelp, EcaHdOperators, CDI_REAL, 1, 1 },
- { EcaHwdi, EcaHwdiHelp, EcaHwdiOperators, CDI_REAL, 2, 1 },
- { EcaHwfi, EcaHwfiHelp, EcaHwfiOperators, CDI_REAL, 2, 1 },
- { EcaId, EcaIdHelp, EcaIdOperators, CDI_REAL, 1, 1 },
- { EcaSu, EcaSuHelp, EcaSuOperators, CDI_REAL, 1, 1 },
- { EcaTr, EcaTrHelp, EcaTrOperators, CDI_REAL, 1, 1 },
- { EcaTg10p, EcaTg10pHelp, EcaTg10pOperators, CDI_REAL, 2, 1 },
- { EcaTg90p, EcaTg90pHelp, EcaTg90pOperators, CDI_REAL, 2, 1 },
- { EcaTn10p, EcaTn10pHelp, EcaTn10pOperators, CDI_REAL, 2, 1 },
- { EcaTn90p, EcaTn90pHelp, EcaTn90pOperators, CDI_REAL, 2, 1 },
- { EcaTx10p, EcaTx10pHelp, EcaTx10pOperators, CDI_REAL, 2, 1 },
- { EcaTx90p, EcaTx90pHelp, EcaTx90pOperators, CDI_REAL, 2, 1 },
- { EcaCdd, EcaCddHelp, EcaCddOperators, CDI_REAL, 1, 1 },
- { EcaCwd, EcaCwdHelp, EcaCwdOperators, CDI_REAL, 1, 1 },
- { EcaRr1, EcaRr1Help, EcaRr1Operators, CDI_REAL, 1, 1 },
- { EcaPd, EcaPdHelp, EcaPdOperators, CDI_REAL, 1, 1 },
- { EcaR75p, EcaR75pHelp, EcaR75pOperators, CDI_REAL, 2, 1 },
- { EcaR75ptot, EcaR75ptotHelp, EcaR75ptotOperators, CDI_REAL, 2, 1 },
- { EcaR90p, EcaR90pHelp, EcaR90pOperators, CDI_REAL, 2, 1 },
- { EcaR90ptot, EcaR90ptotHelp, EcaR90ptotOperators, CDI_REAL, 2, 1 },
- { EcaR95p, EcaR95pHelp, EcaR95pOperators, CDI_REAL, 2, 1 },
- { EcaR95ptot, EcaR95ptotHelp, EcaR95ptotOperators, CDI_REAL, 2, 1 },
- { EcaR99p, EcaR99pHelp, EcaR99pOperators, CDI_REAL, 2, 1 },
- { EcaR99ptot, EcaR99ptotHelp, EcaR99ptotOperators, CDI_REAL, 2, 1 },
- { EcaRx1day, EcaRx1dayHelp, EcaRx1dayOperators, CDI_REAL, 1, 1 },
- { EcaRx5day, EcaRx5dayHelp, EcaRx5dayOperators, CDI_REAL, 1, 1 },
- { EcaSdii, EcaSdiiHelp, EcaSdiiOperators, CDI_REAL, 1, 1 },
- { Fdns, FdnsHelp, FdnsOperators, CDI_REAL, 2, 1 },
- { Strwin, StrwinHelp, StrwinOperators, CDI_REAL, 1, 1 },
- { Strbre, StrbreHelp, StrbreOperators, CDI_REAL, 1, 1 },
- { Strgal, StrgalHelp, StrgalOperators, CDI_REAL, 1, 1 },
- { Hurr, HurrHelp, HurrOperators, CDI_REAL, 1, 1 },
- /* { Hi, NULL, HiOperators, CDI_REAL, 3, 1 }, */
- { Wct, WctHelp, WctOperators, CDI_REAL, 2, 1 },
-#if defined(HAVE_LIBMAGICS) && defined(HAVE_LIBXML2)
- { Magplot, NULL, MagplotOperators, CDI_REAL, 1, 1 },
- { Magvector, NULL, MagvectorOperators, CDI_REAL, 1, 1 },
- { Maggraph, NULL, MaggraphOperators, CDI_REAL, -1, 1 },
-#endif
+ { Adisit, AdisitHelp, AdisitOperators, 1, CDI_REAL, 1, 1 },
+ { Afterburner, AfterburnerHelp, AfterburnerOperators, 1, CDI_REAL, -1, 1 },
+ { Arith, ArithHelp, ArithOperators, 1, CDI_REAL, 2, 1 },
+ { Arithc, ArithcHelp, ArithcOperators, 1, CDI_REAL, 1, 1 },
+ { Arithdays, ArithdaysHelp, ArithdaysOperators, 1, CDI_REAL, 1, 1 },
+ { Arithlat, NULL, ArithlatOperators, 1, CDI_REAL, 1, 1 },
+ { Cat, CopyHelp, CatOperators, 1, CDI_REAL, -1, 1 },
+ { CDItest, NULL, CDItestOperators, 1, CDI_REAL, 1, 1 },
+ { CDIread, NULL, CDIreadOperators, 1, CDI_REAL, 1, 0 },
+ { CDIwrite, NULL, CDIwriteOperators, 1, CDI_REAL, 0, 1 },
+ { Change, ChangeHelp, ChangeOperators, 1, CDI_REAL, 1, 1 },
+ { Change_e5slm, NULL, Change_e5slmOperators, 0, CDI_REAL, 1, 1 },
+ { Cloudlayer, NULL, CloudlayerOperators, 1, CDI_REAL, 1, 1 },
+ { CMOR, NULL, CMOROperators, 1, CDI_REAL, 1, 0 },
+ { Collgrid, CollgridHelp, CollgridOperators, 1, CDI_REAL, -1, 1 },
+ { Command, NULL, CommandOperators, 0, CDI_REAL, 1, 0 },
+ { Comp, CompHelp, CompOperators, 1, CDI_REAL, 2, 1 },
+ { Compc, CompcHelp, CompcOperators, 1, CDI_REAL, 1, 1 },
+ { Complextorect, NULL, ComplextorectOperators, 1, CDI_COMP, 1, 2 },
+ { Cond, CondHelp, CondOperators, 1, CDI_REAL, 2, 1 },
+ { Cond2, Cond2Help, Cond2Operators, 1, CDI_REAL, 3, 1 },
+ { Condc, CondcHelp, CondcOperators, 1, CDI_REAL, 1, 1 },
+ { Consecstat, ConsecstatHelp, ConsecstatOperators, 1, CDI_REAL, 1, 1 },
+ { Copy, CopyHelp, CopyOperators, 1, CDI_REAL, -1, 1 },
+ { Deltime, NULL, DeltimeOperators, 1, CDI_REAL, 1, 1 },
+ { Derivepar, DeriveparHelp, DeriveparOperators, 1, CDI_REAL, 1, 1 },
+ { Detrend, DetrendHelp, DetrendOperators, 1, CDI_REAL, 1, 1 },
+ { Diff, DiffHelp, DiffOperators, 1, CDI_REAL, 2, 0 },
+ { Distgrid, DistgridHelp, DistgridOperators, 1, CDI_REAL, 1, 1 },
+ { Duplicate, DuplicateHelp, DuplicateOperators, 1, CDI_REAL, 1, 1 },
+ { Echam5ini, NULL, Echam5iniOperators, 1, CDI_REAL, 1, 1 },
+ { Enlarge, EnlargeHelp, EnlargeOperators, 1, CDI_REAL, 1, 1 },
+ { Enlargegrid, NULL, EnlargegridOperators, 0, CDI_REAL, 1, 1 },
+ { Ensstat, EnsstatHelp, EnsstatOperators, 1, CDI_REAL, -1, 1 },
+ { Ensstat3, Ensstat2Help, Ensstat3Operators, 1, CDI_REAL, -1, 1 },
+ { Ensval, EnsvalHelp, EnsvalOperators, 1, CDI_REAL, -1, 1 },
+ { Eofcoeff, EofcoeffHelp, EofcoeffOperators, 1, CDI_REAL, 2, -1 },
+ { Eofcoeff3d, EofcoeffHelp, Eofcoeff3dOperators, 1, CDI_REAL, 2, -1 },
+ { EOFs, EOFsHelp, EOFsOperators, 1, CDI_REAL, 1, 2 },
+ { EOF3d, EOFsHelp, EOF3dOperators, 1, CDI_REAL, 1, 2 },
+ { Expr, ExprHelp, ExprOperators, 1, CDI_REAL, 1, 1 },
+ { FC, NULL, FCOperators, 1, CDI_REAL, 1, 1 },
+ { Filedes, FiledesHelp, FiledesOperators, 1, CDI_BOTH, 1, 0 },
+ { Fillmiss, NULL, FillmissOperators, 1, CDI_REAL, 1, 1 },
+ { Filter, FilterHelp, FilterOperators, 1, CDI_REAL, 1, 1 },
+ { Fldrms, NULL, FldrmsOperators, 1, CDI_REAL, 2, 1 },
+ { Fldstat, FldstatHelp, FldstatOperators, 1, CDI_REAL, 1, 1 },
+ { Fldstat2, FldcorHelp, FldcorOperators, 1, CDI_REAL, 2, 1 },
+ { Fldstat2, FldcovarHelp, FldcovarOperators, 1, CDI_REAL, 2, 1 },
+ { Fourier, NULL, FourierOperators, 1, CDI_COMP, 1, 1 },
+ { Gengrid, NULL, GengridOperators, 1, CDI_REAL, 2, 1 },
+ { Gradsdes, GradsdesHelp, GradsdesOperators, 1, CDI_REAL, 1, 0 },
+ { Gridboxstat, GridboxstatHelp, GridboxstatOperators, 1, CDI_REAL, 1, 1 },
+ { Gridcell, GridcellHelp, GridcellOperators, 1, CDI_REAL, 1, 1 },
+ { Gridsearch, NULL, GridsearchOperators, 0, CDI_REAL, 0, 0 },
+ { Harmonic, NULL, HarmonicOperators, 1, CDI_REAL, 1, 1 },
+ { Histogram, HistogramHelp, HistogramOperators, 1, CDI_REAL, 1, 1 },
+ { Importamsr, ImportamsrHelp, ImportamsrOperators, 1, CDI_REAL, 1, 1 },
+ { Importbinary, ImportbinaryHelp, ImportbinaryOperators, 1, CDI_REAL, 1, 1 },
+ { Importcmsaf, ImportcmsafHelp, ImportcmsafOperators, 1, CDI_REAL, 1, 1 },
+ { Importobs, NULL, ImportobsOperators, 1, CDI_REAL, 1, 1 },
+ { Info, InfoHelp, InfoOperators, 1, CDI_BOTH, -1, 0 },
+ { Input, InputHelp, InputOperators, 1, CDI_REAL, 0, 1 },
+ { Intgrid, NULL, IntgridOperators, 1, CDI_REAL, 1, 1 },
+ { Intgridtraj, NULL, IntgridtrajOperators, 1, CDI_REAL, 1, 1 },
+ { Intlevel, IntlevelHelp, IntlevelOperators, 1, CDI_REAL, 1, 1 },
+ { Intlevel3d, Intlevel3dHelp, Intlevel3dOperators, 1, CDI_REAL, 2, 1 },
+ { Inttime, InttimeHelp, InttimeOperators, 1, CDI_REAL, 1, 1 },
+ { Intntime, InttimeHelp, IntntimeOperators, 1, CDI_REAL, 1, 1 },
+ { Intyear, IntyearHelp, IntyearOperators, 1, CDI_REAL, 2, -1 },
+ { Invert, InvertHelp, InvertOperators, 1, CDI_REAL, 1, 1 },
+ { Invertlev, InvertlevHelp, InvertlevOperators, 1, CDI_REAL, 1, 1 },
+ { Isosurface, NULL, IsosurfaceOperators, 1, CDI_REAL, 1, 1 },
+ { Kvl, NULL, KvlOperators, 1, CDI_REAL, 0, 0 },
+ { Log, NULL, LogOperators, 0, CDI_REAL, 1, 0 },
+ { Maskbox, MaskboxHelp, MaskboxOperators, 1, CDI_REAL, 1, 1 },
+ { Maskbox, MaskregionHelp, MaskregionOperators, 1, CDI_REAL, 1, 1 },
+ { Mastrfu, MastrfuHelp, MastrfuOperators, 1, CDI_REAL, 1, 1 },
+ { Math, MathHelp, MathOperators, 1, CDI_BOTH, 1, 1 },
+ { Merge, MergeHelp, MergeOperators, 1, CDI_REAL, -1, 1 },
+ { Mergetime, MergeHelp, MergetimeOperators, 1, CDI_REAL, -1, 1 },
+ { Mergegrid, MergegridHelp, MergegridOperators, 1, CDI_REAL, 2, 1 },
+ { Merstat, MerstatHelp, MerstatOperators, 1, CDI_REAL, 1, 1 },
+ { Monarith, MonarithHelp, MonarithOperators, 1, CDI_REAL, 2, 1 },
+ { Mrotuv, NULL, MrotuvOperators, 1, CDI_REAL, 1, 2 },
+ { Mrotuvb, NULL, MrotuvbOperators, 1, CDI_REAL, 2, 1 },
+ { Ninfo, NinfoHelp, NinfoOperators, 1, CDI_BOTH, 1, 0 },
+ { Nmltest, NULL, NmltestOperators, 0, CDI_REAL, 0, 0 },
+ { Output, OutputHelp, OutputOperators, 1, CDI_REAL, -1, 0 },
+ { Output, OutputtabHelp, OutputtabOperators, 1, CDI_REAL, -1, 0 },
+ { Outputgmt, OutputgmtHelp, OutputgmtOperators, 1, CDI_REAL, 1, 0 },
+ { Pack, NULL, PackOperators, 1, CDI_REAL, 1, 1 },
+ { Pardup, NULL, PardupOperators, 1, CDI_REAL, 1, 1 },
+ { Pinfo, NULL, PinfoOperators, 1, CDI_REAL, 1, 1 },
+ { Pressure, NULL, PressureOperators, 1, CDI_REAL, 1, 1 },
+ { Regres, RegresHelp, RegresOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapHelp, RemapOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapbilHelp, RemapbilOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapbicHelp, RemapbicOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapnnHelp, RemapnnOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapdisHelp, RemapdisOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapyconHelp, RemapyconOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemapconHelp, RemapconOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, Remapcon2Help, Remapcon2Operators, 1, CDI_REAL, 1, 1 },
+ { Remap, RemaplafHelp, RemaplafOperators, 1, CDI_REAL, 1, 1 },
+ { Remap, NULL, RemapgridOperators, 1, CDI_REAL, 1, 1 },
+ { Remapeta, RemapetaHelp, RemapetaOperators, 1, CDI_REAL, 1, 1 },
+ { Replace, ReplaceHelp, ReplaceOperators, 1, CDI_REAL, 2, 1 },
+ { Replacevalues, ReplacevaluesHelp, ReplacevaluesOperators, 1, CDI_REAL, 1, 1 },
+ { Rhopot, RhopotHelp, RhopotOperators, 1, CDI_REAL, 1, 1 },
+ { Rotuv, RotuvbHelp, RotuvOperators, 1, CDI_REAL, 1, 1 },
+ { Runpctl, RunpctlHelp, RunpctlOperators, 1, CDI_REAL, 1, 1 },
+ { Runstat, RunstatHelp, RunstatOperators, 1, CDI_REAL, 1, 1 },
+ { Seascount, NULL, SeascountOperators, 1, CDI_BOTH, 1, 1 },
+ { Seaspctl, SeaspctlHelp, SeaspctlOperators, 1, CDI_REAL, 3, 1 },
+ { Seasstat, SeasstatHelp, SeasstatOperators, 1, CDI_REAL, 1, 1 },
+ { Selbox, SelboxHelp, SelboxOperators, 1, CDI_BOTH, 1, 1 },
+ { Select, SelectHelp, SelectOperators, 1, CDI_BOTH, -1, 1 },
+ { Selvar, SelvarHelp, SelvarOperators, 1, CDI_BOTH, 1, 1 },
+ { Selrec, SelvarHelp, SelrecOperators, 1, CDI_BOTH, 1, 1 },
+ { Seloperator, NULL, SeloperatorOperators, 1, CDI_REAL, 1, 1 },
+ { Seltime, SeltimeHelp, SeltimeOperators, 1, CDI_BOTH, 1, 1 },
+ { Set, SetHelp, SetOperators, 1, CDI_BOTH, 1, 1 },
+ { Setbox, SetboxHelp, SetboxOperators, 1, CDI_REAL, 1, 1 },
+ { Setgatt, SetgattHelp, SetgattOperators, 1, CDI_BOTH, 1, 1 },
+ { Setgrid, SetgridHelp, SetgridOperators, 1, CDI_BOTH, 1, 1 },
+ { Sethalo, SethaloHelp, SethaloOperators, 1, CDI_REAL, 1, 1 },
+ { Setmiss, SetmissHelp, SetmissOperators, 1, CDI_REAL, 1, 1 },
+ { Fillmiss, SetmissHelp, SetmisstonnOperators, 1, CDI_REAL, 1, 1 },
+ { Setpartab, SetHelp, Setpartab0Operators, 1, CDI_REAL, 1, 1 },
+ { Setpartab, SetpartabHelp, SetpartabOperators, 1, CDI_REAL, 1, 1 },
+ { Setrcaname, NULL, SetrcanameOperators, 1, CDI_REAL, 1, 1 },
+ { Settime, SettimeHelp, SettimeOperators, 1, CDI_BOTH, 1, 1 },
+ { Setzaxis, SetzaxisHelp, SetzaxisOperators, 1, CDI_BOTH, 1, 1 },
+ { Showinfo, ShowinfoHelp, ShowinfoOperators, 1, CDI_BOTH, 1, 0 },
+ { Sinfo, SinfoHelp, SinfoOperators, 1, CDI_BOTH, -1, 0 },
+ { Smooth9, Smooth9Help, Smooth9Operators, 1, CDI_REAL, 1, 1 },
+ { Sort, NULL, SortOperators, 1, CDI_REAL, 1, 1 },
+ { Sorttimestamp, NULL, SorttimestampOperators, 1, CDI_REAL, -1, 1 },
+ { Specinfo, NULL, SpecinfoOperators, 1, CDI_REAL, 0, 0 },
+ { Spectral, SpectralHelp, SpectralOperators, 1, CDI_REAL, 1, 1 },
+ { Spectrum, NULL, SpectrumOperators, 1, CDI_REAL, 1, 1 },
+ { Split, SplitHelp, SplitOperators, 1, CDI_BOTH, 1, -1 },
+ { Splitrec, SplitHelp, SplitrecOperators, 1, CDI_BOTH, 1, -1 },
+ { Splitsel, SplitselHelp, SplitselOperators, 1, CDI_BOTH, 1, -1 },
+ { Splittime, SplittimeHelp, SplittimeOperators, 1, CDI_BOTH, 1, -1 },
+ { Splityear, SplittimeHelp, SplityearOperators, 1, CDI_BOTH, 1, -1 },
+ { SSOpar, NULL, SSOparOperators, 0, CDI_REAL, 1, 1 },
+ { Subtrend, SubtrendHelp, SubtrendOperators, 1, CDI_REAL, 3, 1 },
+ { Tee, NULL, TeeOperators, 1, CDI_REAL, 2, 1 },
+ { Template1, NULL, Template1Operators, 0, CDI_REAL, 1, 1 },
+ { Template2, NULL, Template2Operators, 0, CDI_REAL, 1, 1 },
+ { Test, NULL, TestOperators, 0, CDI_REAL, 1, 1 },
+ { Test2, NULL, Test2Operators, 0, CDI_REAL, 2, 1 },
+ { Testdata, NULL, TestdataOperators, 0, CDI_REAL, 1, 1 },
+ { Tests, NULL, TestsOperators, 0, CDI_REAL, 1, 1 },
+ { Timcount, NULL, TimcountOperators, 1, CDI_BOTH, 1, 1 },
+ { Timcount, NULL, YearcountOperators, 1, CDI_BOTH, 1, 1 },
+ { Timcount, NULL, MoncountOperators, 1, CDI_BOTH, 1, 1 },
+ { Timcount, NULL, DaycountOperators, 1, CDI_BOTH, 1, 1 },
+ { Timcount, NULL, HourcountOperators, 1, CDI_BOTH, 1, 1 },
+ { Timpctl, TimpctlHelp, TimpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timpctl, YearpctlHelp, YearpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timpctl, MonpctlHelp, MonpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timpctl, DaypctlHelp, DaypctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timpctl, HourpctlHelp, HourpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timselpctl, TimselpctlHelp, TimselpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Timedt, NULL, TimedtOperators, 1, CDI_REAL, 1, 1 },
+ { Timsort, TimsortHelp, TimsortOperators, 1, CDI_REAL, 1, 1 },
+ { Timselstat, TimselstatHelp, TimselstatOperators, 1, CDI_REAL, 1, 1 },
+ { XTimstat, NULL, XTimstatOperators, 0, CDI_BOTH, 1, 1 },
+ { Timstat, TimstatHelp, TimstatOperators, 1, CDI_BOTH, 1, 1 },
+ { Timstat, YearstatHelp, YearstatOperators, 1, CDI_BOTH, 1, 1 },
+ { Timstat, MonstatHelp, MonstatOperators, 1, CDI_BOTH, 1, 1 },
+ { Timstat, DaystatHelp, DaystatOperators, 1, CDI_BOTH, 1, 1 },
+ { Timstat, HourstatHelp, HourstatOperators, 1, CDI_BOTH, 1, 1 },
+ { Timstat2, TimcorHelp, TimcorOperators, 1, CDI_REAL, 2, 1 },
+ { Timstat2, TimcovarHelp, TimcovarOperators, 1, CDI_REAL, 2, 1 },
+ { Timstat3, NULL, Timstat3Operators, 1, CDI_REAL, 2, 1 },
+ { Tinfo, NULL, TinfoOperators, 1, CDI_BOTH, 1, 0 },
+ { Tocomplex, NULL, TocomplexOperators, 1, CDI_REAL, 1, 1 },
+ { Transpose, NULL, TransposeOperators, 1, CDI_REAL, 1, 1 },
+ { Trend, TrendHelp, TrendOperators, 1, CDI_REAL, 1, 2 },
+ { Trms, NULL, TrmsOperators, 0, CDI_REAL, 2, 1 },
+ { Tstepcount, NULL, TstepcountOperators, 1, CDI_REAL, 1, 1 },
+ { Vargen, VargenHelp, VargenOperators, 1, CDI_REAL, 0, 1 },
+ { Varrms, NULL, VarrmsOperators, 0, CDI_REAL, 2, 1 },
+ { Vertintml, VertintmlHelp, VertintmlOperators, 1, CDI_REAL, 1, 1 },
+ { Vertintap, VertintapHelp, VertintapOperators, 1, CDI_REAL, 1, 1 },
+ { Vertstat, VertstatHelp, VertstatOperators, 1, CDI_REAL, 1, 1 },
+ { Vertcum, NULL, VertcumOperators, 1, CDI_REAL, 1, 1 },
+ { Vertwind, NULL, VertwindOperators, 1, CDI_REAL, 1, 1 },
+ { Verifygrid, NULL, VerifygridOperators, 1, CDI_REAL, 1, 0 },
+ { Wind, WindHelp, WindOperators, 1, CDI_REAL, 1, 1 },
+ { Writegrid, NULL, WritegridOperators, 1, CDI_REAL, 1, 1 }, /* no cdi output */
+ { Writerandom, NULL, WriterandomOperators, 1, CDI_REAL, 1, 1 },
+ { YAR, NULL, YAROperators, 0, CDI_REAL, 1, 1 },
+ { Yearmonstat, YearmonstatHelp, YearmonstatOperators, 1, CDI_REAL, 1, 1 },
+ { Ydayarith, YdayarithHelp, YdayarithOperators, 1, CDI_REAL, 2, 1 },
+ { Ydaypctl, YdaypctlHelp, YdaypctlOperators, 1, CDI_REAL, 3, 1 },
+ { Ydaystat, YdaystatHelp, YdaystatOperators, 1, CDI_REAL, 1, 1 },
+ { Ydrunpctl, YdrunpctlHelp, YdrunpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Ydrunstat, YdrunstatHelp, YdrunstatOperators, 1, CDI_REAL, 1, 1 },
+ { Yhourarith, YhourarithHelp, YhourarithOperators, 1, CDI_REAL, 2, 1 },
+ { Yhourstat, YhourstatHelp, YhourstatOperators, 1, CDI_REAL, 1, 1 },
+ { Ymonarith, YmonarithHelp, YmonarithOperators, 1, CDI_REAL, 2, 1 },
+ { Ymonarith, YseasarithHelp, YseasarithOperators, 1, CDI_REAL, 2, 1 },
+ { Ymonpctl, YmonpctlHelp, YmonpctlOperators, 1, CDI_REAL, 3, 1 },
+ { Ymonstat, YmonstatHelp, YmonstatOperators, 1, CDI_REAL, 1, 1 },
+ { Yseaspctl, YseaspctlHelp, YseaspctlOperators, 1, CDI_REAL, 3, 1 },
+ { Yseasstat, YseasstatHelp, YseasstatOperators, 1, CDI_REAL, 1, 1 },
+ { Zonstat, ZonstatHelp, ZonstatOperators, 1, CDI_REAL, 1, 1 },
+ { EcaCfd, EcaCfdHelp, EcaCfdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaCsu, EcaCsuHelp, EcaCsuOperators, 1, CDI_REAL, 1, 1 },
+ { EcaCwdi, EcaCwdiHelp, EcaCwdiOperators, 1, CDI_REAL, 2, 1 },
+ { EcaCwfi, EcaCwfiHelp, EcaCwfiOperators, 1, CDI_REAL, 2, 1 },
+ { EcaEtr, EcaEtrHelp, EcaEtrOperators, 1, CDI_REAL, 2, 1 },
+ { EcaFd, EcaFdHelp, EcaFdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaGsl, EcaGslHelp, EcaGslOperators, 1, CDI_REAL, 2, 1 },
+ { EcaHd, EcaHdHelp, EcaHdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaHwdi, EcaHwdiHelp, EcaHwdiOperators, 1, CDI_REAL, 2, 1 },
+ { EcaHwfi, EcaHwfiHelp, EcaHwfiOperators, 1, CDI_REAL, 2, 1 },
+ { EcaId, EcaIdHelp, EcaIdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaSu, EcaSuHelp, EcaSuOperators, 1, CDI_REAL, 1, 1 },
+ { EcaTr, EcaTrHelp, EcaTrOperators, 1, CDI_REAL, 1, 1 },
+ { EcaTg10p, EcaTg10pHelp, EcaTg10pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaTg90p, EcaTg90pHelp, EcaTg90pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaTn10p, EcaTn10pHelp, EcaTn10pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaTn90p, EcaTn90pHelp, EcaTn90pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaTx10p, EcaTx10pHelp, EcaTx10pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaTx90p, EcaTx90pHelp, EcaTx90pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaCdd, EcaCddHelp, EcaCddOperators, 1, CDI_REAL, 1, 1 },
+ { EcaCwd, EcaCwdHelp, EcaCwdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaRr1, EcaRr1Help, EcaRr1Operators, 1, CDI_REAL, 1, 1 },
+ { EcaPd, EcaPdHelp, EcaPdOperators, 1, CDI_REAL, 1, 1 },
+ { EcaR75p, EcaR75pHelp, EcaR75pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR75ptot, EcaR75ptotHelp, EcaR75ptotOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR90p, EcaR90pHelp, EcaR90pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR90ptot, EcaR90ptotHelp, EcaR90ptotOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR95p, EcaR95pHelp, EcaR95pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR95ptot, EcaR95ptotHelp, EcaR95ptotOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR99p, EcaR99pHelp, EcaR99pOperators, 1, CDI_REAL, 2, 1 },
+ { EcaR99ptot, EcaR99ptotHelp, EcaR99ptotOperators, 1, CDI_REAL, 2, 1 },
+ { EcaRx1day, EcaRx1dayHelp, EcaRx1dayOperators, 1, CDI_REAL, 1, 1 },
+ { EcaRx5day, EcaRx5dayHelp, EcaRx5dayOperators, 1, CDI_REAL, 1, 1 },
+ { EcaSdii, EcaSdiiHelp, EcaSdiiOperators, 1, CDI_REAL, 1, 1 },
+ { Fdns, FdnsHelp, FdnsOperators, 1, CDI_REAL, 2, 1 },
+ { Strwin, StrwinHelp, StrwinOperators, 1, CDI_REAL, 1, 1 },
+ { Strbre, StrbreHelp, StrbreOperators, 1, CDI_REAL, 1, 1 },
+ { Strgal, StrgalHelp, StrgalOperators, 1, CDI_REAL, 1, 1 },
+ { Hurr, HurrHelp, HurrOperators, 1, CDI_REAL, 1, 1 },
+ /* { Hi, NULL, HiOperators, 1, CDI_REAL, 3, 1 }, */
+ { Wct, WctHelp, WctOperators, 1, CDI_REAL, 2, 1 },
+ { Magplot, MagplotHelp, MagplotOperators, 1, CDI_REAL, 1, 1 },
+ { Magvector, MagvectorHelp, MagvectorOperators, 1, CDI_REAL, 1, 1 },
+ { Maggraph, MaggraphHelp, MaggraphOperators, 1, CDI_REAL, -1, 1 },
};
static int NumModules = sizeof(Modules) / sizeof(Modules[0]);
static const char *opalias[][2] =
{
- {"anomaly", "ymonsub" },
- {"deltap_fl", "deltap" },
- {"diffv", "diffn" },
- {"covar0", "timcovar" },
- {"covar0r", "fldcovar" },
- {"gather", "collgrid" },
- {"geopotheight", "gheight" },
- {"ggstat", "info" },
- {"ggstats", "sinfo" },
- {"globavg", "fldavg" },
- {"infos", "sinfo" },
- {"infov", "infon" },
- {"intgrid", "intgridbil" },
- {"log", "ln" },
- {"lmean", "ymonmean" },
- {"lmmean", "ymonmean" },
- {"lmavg", "ymonavg" },
- {"lmstd", "ymonstd" },
- {"lsmean", "yseasmean" },
- {"chvar", "chname" },
- {"ncode", "npar" },
- {"nvar", "npar" },
- {"outputkey", "outputtab" },
- {"vardes", "pardes" },
- {"delvar", "delname" },
- {"vardup", "pardup" },
- {"varmul", "parmul" },
- {"read_e5ml", "import_e5ml"},
- {"remapcon1", "remaplaf" },
- {"remapdis1", "remapnn" },
- {"scatter", "distgrid" },
- {"showvar", "showname" },
- {"selgridname", "selgrid" },
- {"selvar", "selname" },
- {"setvar", "setname" },
- {"setpartabv", "setpartabn" },
- {"sinfov", "sinfon" },
- {"sortvar", "sortname" },
- {"splitvar", "splitname" },
- {"sort", "timsort" },
- {"write_e5ml", "export_e5ml"},
- {"eca_r1mm", "eca_rr1" },
+ {"afterburner", "after"},
+ {"anomaly", "ymonsub"},
+ {"deltap_fl", "deltap"},
+ {"diffv", "diffn"},
+ {"covar0", "timcovar"},
+ {"covar0r", "fldcovar"},
+ {"gather", "collgrid"},
+ {"geopotheight", "gheight"},
+ {"ggstat", "info"},
+ {"ggstats", "sinfo"},
+ {"globavg", "fldavg"},
+ {"import_grads", "import_binary"},
+ {"infos", "sinfo"},
+ {"infov", "infon"},
+ {"intgrid", "intgridbil"},
+ {"log", "ln"},
+ {"lmean", "ymonmean"},
+ {"lmmean", "ymonmean"},
+ {"lmavg", "ymonavg"},
+ {"lmstd", "ymonstd"},
+ {"lsmean", "yseasmean"},
+ {"chvar", "chname"},
+ {"ncode", "npar"},
+ {"nvar", "npar"},
+ {"outputkey", "outputtab"},
+ {"vardes", "pardes"},
+ {"selvar", "selname"},
+ {"delvar", "delname"},
+ {"remapcon1", "remaplaf"},
+ {"remapdis1", "remapnn"},
+ {"scatter", "distgrid"},
+ {"showvar", "showname"},
+ {"selgridname", "selgrid"},
+ {"setvar", "setname"},
+ {"setpartabv", "setpartabn"},
+ {"sinfov", "sinfon"},
+ {"sortvar", "sortname"},
+ {"splitvar", "splitname"},
+ {"sort", "timsort"},
+ {"eca_r1mm", "eca_rr1"},
{"fpressure", "pressure_fl"},
{"hpressure", "pressure_hl"},
- {"ensrkhistspace", "ensrkhist_space"},
- {"ensrkhisttime", "ensrkhist_time"}
+ {"ensrkhist_space", "ensrkhistspace"},
+ {"ensrkhist_time", "ensrkhisttime"},
+ {"gridverify", "verifygrid"},
+ {"outputcenter", "gmtxyz"},
+ {"outputbounds", "gmtcells"},
+ {"selseas", "selseason"},
+ {"selmon", "selmonth"},
};
static int nopalias = sizeof(opalias) / (2*sizeof(opalias[0][0]));
@@ -1045,15 +1050,15 @@ void operatorPrintAll(void)
for ( i = 0; i < NumModules; i++ )
{
- j = 0;
- while ( Modules[i].operators[j] )
- {
- opernames[nop++] = Modules[i].operators[j++];
+ if ( Modules[i].mode )
+ {
+ j = 0;
+ while ( Modules[i].operators[j] )
+ opernames[nop++] = Modules[i].operators[j++];
}
}
- /*
- * Add operator aliases
- */
+
+ // Add operator aliases
for ( i = 0; i < nopalias; i++ )
{
opernames[nop++] = opalias[i][0];
@@ -1073,3 +1078,112 @@ void operatorPrintAll(void)
}
fprintf(pout, "\n");
}
+
+
+void operatorPrintList(void)
+{
+ int i, j, nbyte, nop = 0;
+ const char *opernames[4096];
+ FILE *pout = stdout;
+
+ for ( i = 0; i < NumModules; i++ )
+ {
+ if ( Modules[i].mode )
+ {
+ j = 0;
+ while ( Modules[i].operators[j] )
+ opernames[nop++] = Modules[i].operators[j++];
+ }
+ }
+
+ // Add operator aliases
+ for ( i = 0; i < nopalias; i++ )
+ {
+ opernames[nop++] = opalias[i][0];
+ }
+
+ qsort(opernames, nop, sizeof(char *), cmpname);
+
+ for ( i = 0; i < nop; i++ )
+ {
+ int iname = -1;
+ int ialias = -1;
+ size_t operlen = strlen(opernames[i]);
+ const char *pdes = NULL;
+ const char **phelp = NULL;
+ const char **help = NULL;
+
+ for ( j = 0; j < nopalias; j++ )
+ {
+ if ( strcmp(opernames[i], opalias[j][0]) == 0 )
+ {
+ ialias = j;
+ break;
+ }
+ }
+
+ if ( ialias == -1 ) help = operatorHelp((char *)opernames[i]);
+
+ phelp = help;
+ if ( phelp )
+ {
+ int loper = FALSE;
+ int index = 0;
+ while ( *phelp )
+ {
+ if ( loper )
+ {
+ if ( *phelp[0] == '\0' ) break;
+ const char *ph = *phelp;
+ while ( *ph != '\0' )
+ {
+ if ( *ph != ' ' ) break;
+ ph++;
+ }
+ if ( *ph != '\0' && strncmp(ph, opernames[i], operlen) == 0 && ph[operlen] == ' ' )
+ {
+ ph += operlen;
+ while ( *ph != '\0' )
+ {
+ if ( *ph != ' ' ) break;
+ ph++;
+ }
+ if ( *ph != '\0' ) pdes = ph;
+ }
+ }
+
+ if ( strcmp(*phelp, "NAME") == 0 ) iname = index+1;
+ if ( strcmp(*phelp, "OPERATORS") == 0 ) loper = TRUE;
+ index++;
+ phelp++;
+ }
+ }
+
+ phelp = help;
+ if ( phelp && pdes == NULL && iname >= 0 )
+ {
+ const char *ph = phelp[iname];
+ while ( *ph != '\0' )
+ {
+ if ( *ph != ' ' ) break;
+ ph++;
+ }
+ if ( *ph != '\0' && strncmp(ph, opernames[i], operlen) == 0 && ph[operlen] == ' ' )
+ {
+ ph += operlen;
+ while ( *ph != '\0' )
+ {
+ if ( *ph != ' ' && *ph != '-' ) break;
+ ph++;
+ }
+ if ( *ph != '\0' ) pdes = ph;
+ }
+ }
+
+ nbyte = fprintf(pout, "%s ", opernames[i]);
+ for ( int i = nbyte; i <= 16; ++i ) fprintf(pout, " ");
+ if ( pdes ) fprintf(pout, "%s", pdes);
+ else if ( ialias >= 0 ) fprintf(pout, "--> %s", opalias[ialias][1]);
+ fprintf(pout, "\n");
+ }
+}
diff --git a/src/modules.h b/src/modules.h
index 6021381..1820184 100644
--- a/src/modules.h
+++ b/src/modules.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -27,5 +27,6 @@ int operatorStreamOutCnt(char *operatorName);
int operatorStreamNumber(char *operatorName);
void operatorPrintAll(void);
+void operatorPrintList(void);
#endif /* _MODULES_H */
diff --git a/src/namelist.c b/src/namelist.c
index 8cb3c04..9f10466 100644
--- a/src/namelist.c
+++ b/src/namelist.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/namelist.h b/src/namelist.h
index 57a82e5..60b5017 100644
--- a/src/namelist.h
+++ b/src/namelist.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/operator_help.h b/src/operator_help.h
index 94c7c16..f509516 100644
--- a/src/operator_help.h
+++ b/src/operator_help.h
@@ -226,10 +226,10 @@ static const char *DuplicateHelp[] = {
"",
"DESCRIPTION",
" This operator duplicates the contents of ifile and writes the result to ofile.",
- " The optional parameter sets the number of duplicates, the default is 1.",
+ " The optional parameter sets the number of duplicates, the default is 2.",
"",
"PARAMETER",
- " ndup INTEGER Number of duplicates, default is 1.",
+ " ndup INTEGER Number of duplicates, default is 2.",
NULL
};
@@ -436,10 +436,10 @@ static const char *CollgridHelp[] = {
" This operator collects the data of the input files to one output file. ",
" All input files need to have the same variables and the same number of timesteps on a different",
" horizonal grid region. A source region must be a structured longitude/latitude grid box.",
- " The parameter nx needs to be specified only for curvilinear grids.",
+ " The parameter nx needs to be specified only non regular lon/lat grids.",
"",
"PARAMETER",
- " nx INTEGER Number of regions in x direction, only needed for curvilinear grids",
+ " nx INTEGER Number of regions in x direction [default: number of input files]",
" names STRING Comma separated list of variable names [default: all variables]",
"",
"NOTE",
@@ -472,9 +472,14 @@ static const char *SelectHelp[] = {
" name STRING Comma separated list of variable names.",
" param STRING Comma separated list of parameter identifiers.",
" code INTEGER Comma separated list of code numbers.",
- " ltype INTEGER Comma separated list of GRIB level types.",
- " levidx INTEGER Comma separated list of index of levels.",
" level FLOAT Comma separated list of vertical levels.",
+ " levidx INTEGER Comma separated list of index of levels.",
+ " zaxisname STRING Comma separated list of zaxis names.",
+ " zaxisnum INTEGER Comma separated list of zaxis numbers.",
+ " ltype INTEGER Comma separated list of GRIB level types.",
+ " gridname STRING Comma separated list of grid names.",
+ " gridnum INTEGER Comma separated list of grid numbers.",
+ " steptype STRING Comma separated list of timestep types.",
" date STRING Comma separated list of dates (format YYYY-MM-DDThh:mm:ss).",
" startdate STRING Start date (format YYYY-MM-DDThh:mm:ss).",
" enddate STRING End date (format YYYY-MM-DDThh:mm:ss).",
@@ -482,8 +487,9 @@ static const char *SelectHelp[] = {
" hour INTEGER Comma separated list of hours.",
" day INTEGER Comma separated list of days.",
" month INTEGER Comma separated list of months.",
+ " season STRING Comma separated list of seasons (substring of DJFMAMJJASOND or ANN).",
" year INTEGER Comma separated list of years.",
- " timestep INTEGER Comma separated list of timesteps. Negative values selects timesteps from the end (netCDF only).",
+ " timestep INTEGER Comma separated list of timesteps. Negative values selects timesteps from the end (NetCDF only).",
" timestep_of_year INTEGER Comma separated list of timesteps of year.",
NULL
};
@@ -559,7 +565,7 @@ static const char *SelvarHelp[] = {
static const char *SeltimeHelp[] = {
"NAME",
- " seltimestep, seltime, selhour, selday, selmon, selyear, selseas, seldate, ",
+ " seltimestep, seltime, selhour, selday, selmonth, selyear, selseason, seldate, ",
" selsmon - Select timesteps",
"",
"SYNOPSIS",
@@ -567,9 +573,9 @@ static const char *SeltimeHelp[] = {
" seltime,times ifile ofile",
" selhour,hours ifile ofile",
" selday,days ifile ofile",
- " selmon,months ifile ofile",
+ " selmonth,months ifile ofile",
" selyear,years ifile ofile",
- " selseas,seasons ifile ofile",
+ " selseason,seasons ifile ofile",
" seldate,date1[,date2] ifile ofile",
" selsmon,month[,nts1[,nts2]] ifile ofile",
"",
@@ -586,11 +592,11 @@ static const char *SeltimeHelp[] = {
" Selects all timesteps with a hour in a user given list.",
" selday Select days",
" Selects all timesteps with a day in a user given list.",
- " selmon Select months",
+ " selmonth Select months",
" Selects all timesteps with a month in a user given list.",
" selyear Select years",
" Selects all timesteps with a year in a user given list.",
- " selseas Select seasons",
+ " selseason Select seasons",
" Selects all timesteps with a month of a season in a user given list.",
" seldate Select dates",
" Selects all timesteps with a date in a user given range.",
@@ -598,13 +604,13 @@ static const char *SeltimeHelp[] = {
" Selects a month and optional an arbitrary number of timesteps before and after this month.",
"",
"PARAMETER",
- " timesteps INTEGER Comma separated list of timesteps. Negative values selects timesteps from the end (netCDF only).",
+ " timesteps INTEGER Comma separated list of timesteps. Negative values selects timesteps from the end (NetCDF only).",
" times STRING Comma separated list of times (format hh:mm:ss).",
" hours INTEGER Comma separated list of hours.",
" days INTEGER Comma separated list of days.",
" months INTEGER Comma separated list of months.",
" years INTEGER Comma separated list of years.",
- " seasons STRING Comma separated list of seasons (DJF, MAM, JJA, SON).",
+ " seasons STRING Comma separated list of seasons (substring of DJFMAMJJASOND or ANN).",
" date1 STRING Start date (format YYYY-MM-DDThh:mm:ss).",
" date2 STRING End date (format YYYY-MM-DDThh:mm:ss) [default: date1].",
" nts1 INTEGER Number of timesteps before the selected month [default: 0].",
@@ -842,7 +848,7 @@ static const char *SetpartabHelp[] = {
" convert & INTEGER & Set to 1 to convert the unit if necessary",
" ",
" The search key for the variable depends on the operator. Use setpartabn to search variables by the name.",
- " This is typically used for netCDF datasets. The operator setpartabp searches variables by the parameter ID.",
+ " This is typically used for NetCDF datasets. The operator setpartabp searches variables by the parameter ID.",
"",
"OPERATORS",
" setpartabp Set parameter table",
@@ -950,7 +956,7 @@ static const char *SettimeHelp[] = {
" units STRING Base units of the time axis (seconds, minutes, hours, days, months, years)",
" date STRING Date (format: YYYY-MM-DD)",
" time STRING Time (format: hh:mm:ss)",
- " inc STRING Optional increment (seconds, minutes, hours, days, months, years) [default: 0hour]",
+ " inc STRING Optional increment (seconds, minutes, hours, days, months, years) [default: 1hour]",
" calendar STRING Calendar (standard, proleptic_gregorian, 360_day, 365_day, 366_day)",
" sval STRING Shift value (e.g. -3hour)",
NULL
@@ -1089,7 +1095,7 @@ static const char *SetgattHelp[] = {
" attfile STRING File name which contains global text attributes",
"",
"NOTE",
- " Besides netCDF none of the supported data formats supports global attributes.",
+ " Besides NetCDF none of the supported data formats supports global attributes.",
NULL
};
@@ -1299,6 +1305,9 @@ static const char *ExprHelp[] = {
"DESCRIPTION",
" This module arithmetically processes every timestep of the input dataset.",
" Each individual assignment statement have to end with a semi-colon.",
+ " Unlike regular variables, temporary variables are never written to the output stream.",
+ " To define a temporary variable simply prefix the variable name with an underscore (e.g. _varname)",
+ " when the variable is declared.",
" ",
" The following operators are supported:",
" ",
@@ -1309,18 +1318,21 @@ static const char *ExprHelp[] = {
" * & multiplication & x * y & Product of x and y ",
" / & division & x / y & Quotient of x and y",
" ^ & exponentiation & x ^ y & Exponentiates x with y ",
- " == & equal to & x == y & 1, if x equal to y; else 0",
- " != & not equal to & x != y & 1, if x not equal to y; else 0",
- " > & greater than & x > y & 1, if x greater than y; else 0",
- " < & less than & x < y & 1, if x less than y; else 0",
- " >= & greater equal & x >= y & 1, if x greater equal y; else 0",
- " <= & less equal & x <= y & 1, if x less equal y; else 0",
+ " == & equal to & x == y & 1, if x equal to y; else 0",
+ " != & not equal to & x != y & 1, if x not equal to y; else 0",
+ " > & greater than & x > y & 1, if x greater than y; else 0",
+ " < & less than & x < y & 1, if x less than y; else 0",
+ " >= & greater equal & x >= y & 1, if x greater equal y; else 0",
+ " <= & less equal & x <= y & 1, if x less equal y; else 0",
" <=> & less equal greater & x <=> y & -1, if x less y; 1, if x greater y; else 0 ",
- " && & logical AND & x && y & 1, if x and y not equal 0; else 0",
- " || & logical OR & x || y & 1, if x or y not equal 0; else 0",
+ " && & logical AND & x && y & 1, if x and y not equal 0; else 0",
+ " || & logical OR & x || y & 1, if x or y not equal 0; else 0",
" ?: & ternary conditional & x ? y : z & y, if x not equal 0, else z ",
" ",
- " The following intrinsic functions are available:",
+ " The following functions are supported:",
+ " ",
+ " Math intrinsics:",
+ " ",
" abs(x) " " Absolute value of x",
" floor(x)" " Round to largest integral value not greater than x",
" ceil(x) " " Round to smallest integral value not less than x",
@@ -1337,6 +1349,37 @@ static const char *ExprHelp[] = {
" asin(x) " " Arc-sine of x, where x is specified in radians",
" acos(x) " " Arc-cosine of x, where x is specified in radians",
" atan(x) " " Arc-tangent of x, where x is specified in radians",
+ " rad(x) " " Convert x from degrees to radians",
+ " deg(x) " " Convert x from radians to degrees",
+ " ",
+ " Coordinates:",
+ " ",
+ " clon(x) " " Longitude coordinate of x (available only if x has geographical coordinates) ",
+ " clat(x) " " Latitude coordinate of x (available only if x has geographical coordinates) ",
+ " gridarea(x)" " Grid cell area of x (available only if x has geographical coordinates) ",
+ " clev(x) " " Level coordinate of x (0, if x is a 2D surface variable)",
+ " ",
+ " Constants:",
+ " ",
+ " ngp(x) " " Number of horizontal grid points",
+ " nlev(x) " " Number of vertical levels",
+ " size(x) " " Total number of elements (ngp(x)*nlev(x))",
+ " missval(x)" " Returns the missing value of variable x",
+ " ",
+ " Statistical values over a field:",
+ " ",
+ " fldmin(x), fldmax(x), fldsum(x), fldmean(x), fldavg(x), fldstd(x), fldstd1(x), fldvar(x), fldvar1(x)",
+ " ",
+ " Vertical statistical values:",
+ " ",
+ " vertmin(x), vertmax(x), vertsum(x), vertmean(x), vertavg(x), vertstd(x), vertstd1(x), vertvar(x), vertvar1(x)",
+ " ",
+ " Miscellaneous:",
+ " ",
+ " sellevel(x,k) " " Select level k of variable x",
+ " sellevidx(x,k)" " Select level index k of variable x",
+ " remove(x) " " Remove variable x from output stream",
+ " ",
"",
"OPERATORS",
" expr Evaluate expressions",
@@ -1357,7 +1400,7 @@ static const char *ExprHelp[] = {
static const char *MathHelp[] = {
"NAME",
" abs, int, nint, pow, sqr, sqrt, exp, ln, log10, sin, cos, tan, asin, acos, ",
- " reci - Mathematical functions",
+ " atan, reci - Mathematical functions",
"",
"SYNOPSIS",
" <operator> ifile ofile",
@@ -1395,6 +1438,8 @@ static const char *MathHelp[] = {
" o(t,x) = asin(i(t,x))",
" acos Arc cosine",
" o(t,x) = acos(i(t,x))",
+ " atan Arc tangent",
+ " o(t,x) = atan(i(t,x))",
" reci Reciprocal value",
" o(t,x) = 1 / i(t,x)",
NULL
@@ -1673,19 +1718,19 @@ static const char *EnsstatHelp[] = {
" ensavg Ensemble average",
" o(t,x) = avg{i1(t,x), i2(t,x), ..., in(t,x)}",
" ensstd Ensemble standard deviation",
- " Divisor is n.",
+ " Normalize by n.",
" ",
" o(t,x) = std{i1(t,x), i2(t,x), ..., in(t,x)}",
- " ensstd1 Ensemble standard deviation",
- " Divisor is (n-1).",
+ " ensstd1 Ensemble standard deviation (n-1)",
+ " Normalize by (n-1).",
" ",
" o(t,x) = std1{i1(t,x), i2(t,x), ..., in(t,x)}",
" ensvar Ensemble variance",
- " Divisor is n.",
+ " Normalize by n.",
" ",
" o(t,x) = var{i1(t,x), i2(t,x), ..., in(t,x)}",
- " ensvar1 Ensemble variance",
- " Divisor is (n-1).",
+ " ensvar1 Ensemble variance (n-1)",
+ " Normalize by (n-1).",
" ",
" o(t,x) = var1{i1(t,x), i2(t,x), ..., in(t,x)}",
" enspctl Ensemble percentiles",
@@ -1837,22 +1882,22 @@ static const char *FldstatHelp[] = {
" o(t,1) = avg{i(t,x'), x_1<x'<=x_n}",
" weighted by area weights obtained by the input field.",
" fldstd Field standard deviation",
- " Divisor is n. For every gridpoint x_1, ..., x_n of the same field it is:",
+ " Normalize by n. For every gridpoint x_1, ..., x_n of the same field it is:",
" ",
" o(t,1) = std{i(t,x'), x_1<x'<=x_n}",
" weighted by area weights obtained by the input field.",
- " fldstd1 Field standard deviation",
- " Divisor is (n-1). For every gridpoint x_1, ..., x_n of the same field it is:",
+ " fldstd1 Field standard deviation (n-1)",
+ " Normalize by (n-1). For every gridpoint x_1, ..., x_n of the same field it is:",
" ",
" o(t,1) = std1{i(t,x'), x_1<x'<=x_n}",
" weighted by area weights obtained by the input field.",
" fldvar Field variance",
- " Divisor is n. For every gridpoint x_1, ..., x_n of the same field it is:",
+ " Normalize by n. For every gridpoint x_1, ..., x_n of the same field it is:",
" ",
" o(t,1) = var{i(t,x'), x_1<x'<=x_n}",
" weighted by area weights obtained by the input field.",
- " fldvar1 Field variance",
- " Divisor is (n-1). For every gridpoint x_1, ..., x_n of the same field it is:",
+ " fldvar1 Field variance (n-1)",
+ " Normalize by (n-1). For every gridpoint x_1, ..., x_n of the same field it is:",
" ",
" o(t,1) = var1{i(t,x'), x_1<x'<=x_n}",
" weighted by area weights obtained by the input field.",
@@ -1893,13 +1938,13 @@ static const char *ZonstatHelp[] = {
" zonavg Zonal average",
" For every latitude the average over all longitudes is computed.",
" zonstd Zonal standard deviation",
- " For every latitude the standard deviation over all longitudes is computed. Divisor is n.",
- " zonstd1 Zonal standard deviation",
- " For every latitude the standard deviation over all longitudes is computed. Divisor is (n-1). ",
+ " For every latitude the standard deviation over all longitudes is computed. Normalize by n.",
+ " zonstd1 Zonal standard deviation (n-1)",
+ " For every latitude the standard deviation over all longitudes is computed. Normalize by (n-1). ",
" zonvar Zonal variance",
- " For every latitude the variance over all longitudes is computed. Divisor is n.",
- " zonvar1 Zonal variance",
- " For every latitude the variance over all longitudes is computed. Divisor is (n-1).",
+ " For every latitude the variance over all longitudes is computed. Normalize by n.",
+ " zonvar1 Zonal variance (n-1)",
+ " For every latitude the variance over all longitudes is computed. Normalize by (n-1).",
" zonpctl Zonal percentiles",
" For every latitude the pth percentile over all longitudes is computed.",
"",
@@ -1935,13 +1980,13 @@ static const char *MerstatHelp[] = {
" meravg Meridional average",
" For every longitude the area weighted average over all latitudes is computed.",
" merstd Meridional standard deviation",
- " For every longitude the standard deviation over all latitudes is computed. Divisor is n.",
- " merstd1 Meridional standard deviation",
- " For every longitude the standard deviation over all latitudes is computed. Divisor is (n-1).",
+ " For every longitude the standard deviation over all latitudes is computed. Normalize by n.",
+ " merstd1 Meridional standard deviation (n-1)",
+ " For every longitude the standard deviation over all latitudes is computed. Normalize by (n-1).",
" mervar Meridional variance",
- " For every longitude the variance over all latitudes is computed. Divisor is n.",
- " mervar1 Meridional variance",
- " For every longitude the variance over all latitudes is computed. Divisor is (n-1).",
+ " For every longitude the variance over all latitudes is computed. Normalize by n.",
+ " mervar1 Meridional variance (n-1)",
+ " For every longitude the variance over all latitudes is computed. Normalize by (n-1).",
" merpctl Meridional percentiles",
" For every longitude the pth percentile over all latitudes is computed.",
"",
@@ -1976,13 +2021,13 @@ static const char *GridboxstatHelp[] = {
" gridboxavg Gridbox average",
" Average of the selected grid boxes.",
" gridboxstd Gridbox standard deviation",
- " Standard deviation of the selected grid boxes. Divisor is n.",
- " gridboxstd1 Gridbox standard deviation",
- " Standard deviation of the selected grid boxes. Divisor is (n-1).",
+ " Standard deviation of the selected grid boxes. Normalize by n.",
+ " gridboxstd1 Gridbox standard deviation (n-1)",
+ " Standard deviation of the selected grid boxes. Normalize by (n-1).",
" gridboxvar Gridbox variance",
- " Variance of the selected grid boxes. Divisor is n.",
- " gridboxvar1 Gridbox variance",
- " Variance of the selected grid boxes. Divisor is (n-1).",
+ " Variance of the selected grid boxes. Normalize by n.",
+ " gridboxvar1 Gridbox variance (n-1)",
+ " Variance of the selected grid boxes. Normalize by (n-1).",
"",
"PARAMETER",
" nx INTEGER Number of grid boxes in x direction",
@@ -2015,13 +2060,13 @@ static const char *VertstatHelp[] = {
" vertavg Vertical average",
" For every gridpoint the layer weighted average over all levels is computed.",
" vertstd Vertical standard deviation",
- " For every gridpoint the standard deviation over all levels is computed. Divisor is n.",
- " vertstd1 Vertical standard deviation",
- " For every gridpoint the standard deviation over all levels is computed. Divisor is (n-1).",
+ " For every gridpoint the standard deviation over all levels is computed. Normalize by n.",
+ " vertstd1 Vertical standard deviation (n-1)",
+ " For every gridpoint the standard deviation over all levels is computed. Normalize by (n-1).",
" vertvar Vertical variance",
- " For every gridpoint the variance over all levels is computed. Divisor is n.",
- " vertvar1 Vertical variance",
- " For every gridpoint the variance over all levels is computed. Divisor is (n-1).",
+ " For every gridpoint the variance over all levels is computed. Normalize by n.",
+ " vertvar1 Vertical variance (n-1)",
+ " For every gridpoint the variance over all levels is computed. Normalize by (n-1).",
NULL
};
@@ -2066,22 +2111,22 @@ static const char *TimselstatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t1 < t' <= tn}",
" timselstd Time range standard deviation",
- " Divisor is n. For every adjacent sequence t1, ...., tn of timesteps of the same ",
+ " Normalize by n. For every adjacent sequence t1, ...., tn of timesteps of the same ",
" selected time range it is",
" ",
" o(t,x) = std{i(t',x), t1 < t' <= tn}",
- " timselstd1 Time range standard deviation",
- " Divisor is (n-1). For every adjacent sequence t1, ...., tn of timesteps of the same ",
+ " timselstd1 Time range standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t1, ...., tn of timesteps of the same ",
" selected time range it is",
" ",
" o(t,x) = std1{i(t',x), t1 < t' <= tn}",
" timselvar Time range variance",
- " Divisor is n. For every adjacent sequence t1, ...., tn of timesteps of the same ",
+ " Normalize by n. For every adjacent sequence t1, ...., tn of timesteps of the same ",
" selected time range it is",
" ",
" o(t,x) = var{i(t',x), t1 < t' <= tn}",
- " timselvar1 Time range variance",
- " Divisor is (n-1). For every adjacent sequence t1, ...., tn of timesteps of the same ",
+ " timselvar1 Time range variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t1, ...., tn of timesteps of the same ",
" selected time range it is",
" ",
" o(t,x) = var1{i(t',x), t1 < t' <= tn}",
@@ -2150,19 +2195,19 @@ static const char *RunstatHelp[] = {
" runavg Running average",
" o(t+(nts-1)/2,x) = avg{i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
" runstd Running standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(t+(nts-1)/2,x) = std{i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
- " runstd1 Running standard deviation",
- " Divisor is (n-1). ",
+ " runstd1 Running standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(t+(nts-1)/2,x) = std1{i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
" runvar Running variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(t+(nts-1)/2,x) = var{i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
- " runvar1 Running variance",
- " Divisor is (n-1). ",
+ " runvar1 Running variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(t+(nts-1)/2,x) = var1{i(t,x), i(t+1,x), ..., i(t+nts-1,x)}",
"",
@@ -2220,19 +2265,19 @@ static const char *TimstatHelp[] = {
" timavg Time average",
" o(1,x) = avg{i(t',x), t_1<t'<=t_n}",
" timstd Time standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(1,x) = std{i(t',x), t_1<t'<=t_n}",
- " timstd1 Time standard deviation",
- " Divisor is (n-1). ",
+ " timstd1 Time standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(1,x) = std1{i(t',x), t_1<t'<=t_n}",
" timvar Time variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(1,x) = var{i(t',x), t_1<t'<=t_n}",
- " timvar1 Time variance",
- " Divisor is (n-1). ",
+ " timvar1 Time variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(1,x) = var1{i(t',x), t_1<t'<=t_n}",
NULL
@@ -2300,19 +2345,19 @@ static const char *HourstatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t_1<t'<=t_n}",
" hourstd Hourly standard deviation",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
" ",
" o(t,x) = std{i(t',x), t_1<t'<=t_n}",
- " hourstd1 Hourly standard deviation",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
+ " hourstd1 Hourly standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
" ",
" o(t,x) = std1{i(t',x), t_1<t'<=t_n}",
" hourvar Hourly variance",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
" ",
" o(t,x) = var{i(t',x), t_1<t'<=t_n}",
- " hourvar1 Hourly variance",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
+ " hourvar1 Hourly variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same hour it is:",
" ",
" o(t,x) = var1{i(t',x), t_1<t'<=t_n}",
NULL
@@ -2383,19 +2428,19 @@ static const char *DaystatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t_1<t'<=t_n}",
" daystd Daily standard deviation",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
" ",
" o(t,x) = std{i(t',x), t_1<t'<=t_n}",
- " daystd1 Daily standard deviation",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
+ " daystd1 Daily standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
" ",
" o(t,x) = std1{i(t',x), t_1<t'<=t_n}",
" dayvar Daily variance",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
" ",
" o(t,x) = var{i(t',x), t_1<t'<=t_n}",
- " dayvar1 Daily variance",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
+ " dayvar1 Daily variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same day it is",
" ",
" o(t,x) = var1{i(t',x), t_1<t'<=t_n}",
NULL
@@ -2466,19 +2511,19 @@ static const char *MonstatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t_1<t'<=t_n}",
" monstd Monthly standard deviation",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
" ",
" o(t,x) = std{i(t',x), t_1 < t' <= t_n}",
- " monstd1 Monthly standard deviation",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
+ " monstd1 Monthly standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
" ",
" o(t,x) = std1{i(t',x), t_1 < t' <= t_n}",
" monvar Monthly variance",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
" ",
" o(t,x) = var{i(t',x), t_1 < t' <= t_n}",
- " monvar1 Monthly variance",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
+ " monvar1 Monthly variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same month it is",
" ",
" o(t,x) = var1{i(t',x), t_1 < t' <= t_n}",
NULL
@@ -2571,19 +2616,19 @@ static const char *YearstatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t_1<t'<=t_n}",
" yearstd Yearly standard deviation",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
" ",
" o(t,x) = std{i(t',x), t_1 < t' <= t_n}",
- " yearstd1 Yearly standard deviation",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
+ " yearstd1 Yearly standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
" ",
" o(t,x) = std1{i(t',x), t_1 < t' <= t_n}",
" yearvar Yearly variance",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
" ",
" o(t,x) = var{i(t',x), t_1 < t' <= t_n}",
- " yearvar1 Yearly variance",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
+ " yearvar1 Yearly variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same year it is",
" ",
" o(t,x) = var1{i(t',x), t_1 < t' <= t_n}",
"",
@@ -2634,7 +2679,7 @@ static const char *SeasstatHelp[] = {
" Depending on the chosen operator the minimum, maximum, sum, average, variance",
" or standard deviation of timesteps of the same season is written to ofile.",
" The time stamp in ofile is from the middle contributing timestep of ifile.",
- " Be careful about the first and the last output timestep , they may be incorrect values ",
+ " Be careful about the first and the last output timestep, they may be incorrect values ",
" if the seasons have incomplete timesteps.",
"",
"OPERATORS",
@@ -2659,19 +2704,19 @@ static const char *SeasstatHelp[] = {
" ",
" o(t,x) = avg{i(t',x), t1 < t' <= tn}",
" seasstd Seasonal standard deviation",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
" ",
" o(t,x) = std{i(t',x), t1 < t' <= tn}",
- " seasstd1 Seasonal standard deviation",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
+ " seasstd1 Seasonal standard deviation (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
" ",
" o(t,x) = std1{i(t',x), t1 < t' <= tn}",
" seasvar Seasonal variance",
- " Divisor is n. For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
+ " Normalize by n. For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
" ",
" o(t,x) = var{i(t',x), t1 < t' <= tn}",
- " seasvar1 Seasonal variance",
- " Divisor is (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
+ " seasvar1 Seasonal variance (n-1)",
+ " Normalize by (n-1). For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
" ",
" o(t,x) = var1{i(t',x), t1 < t' <= tn}",
NULL
@@ -2691,7 +2736,7 @@ static const char *SeaspctlHelp[] = {
" the environment variable CDO_PCTL_NBINS to a different value. The files ifile2 and ",
" ifile3 should be the result of corresponding seasmin and seasmax operations, respectively.",
" The time stamp in ofile is from the middle contributing timestep of ifile1.",
- " Be careful about the first and the last output timestep , they may be incorrect values ",
+ " Be careful about the first and the last output timestep, they may be incorrect values ",
" if the seasons have incomplete timesteps.",
" For every adjacent sequence t_1, ...,t_n of timesteps of the same season it is",
" ",
@@ -2742,25 +2787,25 @@ static const char *YhourstatHelp[] = {
" ...",
" o(8784,x) = avg{i(t,x), day(i(t)) = 8784}",
" yhourstd Multi-year hourly standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(0001,x) = std{i(t,x), day(i(t)) = 0001}",
" ...",
" o(8784,x) = std{i(t,x), day(i(t)) = 8784}",
- " yhourstd1 Multi-year hourly standard deviation",
- " Divisor is (n-1). ",
+ " yhourstd1 Multi-year hourly standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(0001,x) = std1{i(t,x), day(i(t)) = 0001}",
" ...",
" o(8784,x) = std1{i(t,x), day(i(t)) = 8784}",
" yhourvar Multi-year hourly variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(0001,x) = var{i(t,x), day(i(t)) = 0001}",
" ...",
" o(8784,x) = var{i(t,x), day(i(t)) = 8784}",
- " yhourvar1 Multi-year hourly variance",
- " Divisor is (n-1). ",
+ " yhourvar1 Multi-year hourly variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(0001,x) = var1{i(t,x), day(i(t)) = 0001}",
" ...",
@@ -2804,25 +2849,25 @@ static const char *YdaystatHelp[] = {
" ...",
" o(366,x) = avg{i(t,x), day(i(t)) = 366}",
" ydaystd Multi-year daily standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(001,x) = std{i(t,x), day(i(t)) = 001}",
" ...",
" o(366,x) = std{i(t,x), day(i(t)) = 366}",
- " ydaystd1 Multi-year daily standard deviation",
- " Divisor is (n-1). ",
+ " ydaystd1 Multi-year daily standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(001,x) = std1{i(t,x), day(i(t)) = 001}",
" ...",
" o(366,x) = std1{i(t,x), day(i(t)) = 366}",
" ydayvar Multi-year daily variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(001,x) = var{i(t,x), day(i(t)) = 001}",
" ...",
" o(366,x) = var{i(t,x), day(i(t)) = 366}",
- " ydayvar1 Multi-year daily variance",
- " Divisor is (n-1). ",
+ " ydayvar1 Multi-year daily variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(001,x) = var1{i(t,x), day(i(t)) = 001}",
" ...",
@@ -2895,25 +2940,25 @@ static const char *YmonstatHelp[] = {
" ...",
" o(12,x) = avg{i(t,x), month(i(t)) = 12}",
" ymonstd Multi-year monthly standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(01,x) = std{i(t,x), month(i(t)) = 01}",
" ...",
" o(12,x) = std{i(t,x), month(i(t)) = 12}",
- " ymonstd1 Multi-year monthly standard deviation",
- " Divisor is (n-1). ",
+ " ymonstd1 Multi-year monthly standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(01,x) = std1{i(t,x), month(i(t)) = 01}",
" ...",
" o(12,x) = std1{i(t,x), month(i(t)) = 12}",
" ymonvar Multi-year monthly variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(01,x) = var{i(t,x), month(i(t)) = 01}",
" ...",
" o(12,x) = var{i(t,x), month(i(t)) = 12}",
- " ymonvar1 Multi-year monthly variance",
- " Divisor is (n-1). ",
+ " ymonvar1 Multi-year monthly variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(01,x) = var1{i(t,x), month(i(t)) = 01}",
" ...",
@@ -2997,7 +3042,7 @@ static const char *YseasstatHelp[] = {
" o(2,x) = std{i(t,x), month(i(t)) = 03, 04, 05}",
" o(3,x) = std{i(t,x), month(i(t)) = 06, 07, 08}",
" o(4,x) = std{i(t,x), month(i(t)) = 09, 10, 11}",
- " yseasstd1 Multi-year seasonal standard deviation",
+ " yseasstd1 Multi-year seasonal standard deviation (n-1)",
" o(1,x) = std1{i(t,x), month(i(t)) = 12, 01, 02}",
" o(2,x) = std1{i(t,x), month(i(t)) = 03, 04, 05}",
" o(3,x) = std1{i(t,x), month(i(t)) = 06, 07, 08}",
@@ -3007,7 +3052,7 @@ static const char *YseasstatHelp[] = {
" o(2,x) = var{i(t,x), month(i(t)) = 03, 04, 05}",
" o(3,x) = var{i(t,x), month(i(t)) = 06, 07, 08}",
" o(4,x) = var{i(t,x), month(i(t)) = 09, 10, 11}",
- " yseasvar1 Multi-year seasonal variance",
+ " yseasvar1 Multi-year seasonal variance (n-1)",
" o(1,x) = var1{i(t,x), month(i(t)) = 12, 01, 02}",
" o(2,x) = var1{i(t,x), month(i(t)) = 03, 04, 05}",
" o(3,x) = var1{i(t,x), month(i(t)) = 06, 07, 08}",
@@ -3090,25 +3135,25 @@ static const char *YdrunstatHelp[] = {
" ...",
" o(366,x) = avg{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[(i(t+(nts-1)/2)] = 366}",
" ydrunstd Multi-year daily running standard deviation",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(001,x) = std{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[i(t+(nts-1)/2)] = 001}",
" ...",
" o(366,x) = std{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[i(t+(nts-1)/2)] = 366}",
- " ydrunstd1 Multi-year daily running standard deviation",
- " Divisor is (n-1). ",
+ " ydrunstd1 Multi-year daily running standard deviation (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(001,x) = std1{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[i(t+(nts-1)/2)] = 001}",
" ...",
" o(366,x) = std1{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[i(t+(nts-1)/2)] = 366}",
" ydrunvar Multi-year daily running variance",
- " Divisor is n. ",
+ " Normalize by n. ",
" ",
" o(001,x) = var{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[(i(t+(nts-1)/2)] = 001}",
" ...",
" o(366,x) = var{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[(i(t+(nts-1)/2)] = 366}",
- " ydrunvar1 Multi-year daily running variance",
- " Divisor is (n-1). ",
+ " ydrunvar1 Multi-year daily running variance (n-1)",
+ " Normalize by (n-1). ",
" ",
" o(001,x) = var1{i(t,x), i(t+1,x), ..., i(t+nts-1,x); day[(i(t+(nts-1)/2)] = 001}",
" ...",
@@ -3411,7 +3456,7 @@ static const char *RemapbilHelp[] = {
" Performs a bilinear interpolation on all input fields.",
" genbil Generate bilinear interpolation weights",
" Generates bilinear interpolation weights for the first input field and writes the",
- " result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3442,7 +3487,7 @@ static const char *RemapbicHelp[] = {
" Performs a bicubic interpolation on all input fields.",
" genbic Generate bicubic interpolation weights",
" Generates bicubic interpolation weights for the first input field and writes the",
- " result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3471,7 +3516,7 @@ static const char *RemapnnHelp[] = {
" Performs a nearest neighbor remapping on all input fields.",
" gennn Generate nearest neighbor remap weights",
" Generates nearest neighbor remapping weights for the first input field and writes the result to a file.",
- " The format of this file is netCDF following the SCRIP convention.",
+ " The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3507,7 +3552,7 @@ static const char *RemapdisHelp[] = {
" gendis Generate distance-weighted average remap weights",
" Generates distance-weighted average remapping weights of the four nearest neighbor",
" values for the first input field and writes the result to a file.",
- " The format of this file is netCDF following the SCRIP convention.",
+ " The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3542,7 +3587,7 @@ static const char *RemapyconHelp[] = {
" Performs a first order conservative remapping on all input fields.",
" genycon Generate 1st order conservative remap weights",
" Generates first order conservative remapping weights for the first input field and",
- " writes the result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " writes the result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3581,7 +3626,7 @@ static const char *RemapconHelp[] = {
" Performs a first order conservative remapping on all input fields.",
" gencon Generate 1st order conservative remap weights",
" Generates first order conservative remapping weights for the first input field and",
- " writes the result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " writes the result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3610,8 +3655,7 @@ static const char *Remapcon2Help[] = {
" remapcon2, gencon2 - Second order conservative remapping",
"",
"SYNOPSIS",
- " remapcon2,grid ifile ofile",
- " gencon2,grid2 ifile ofile",
+ " <operator>,grid ifile ofile",
"",
"DESCRIPTION",
" This module contains operators for a second order conservative remapping of fields between grids in spherical coordinates.",
@@ -3625,7 +3669,7 @@ static const char *Remapcon2Help[] = {
" Performs a second order conservative remapping on all input fields.",
" gencon2 Generate 2nd order conservative remap weights",
" Generates second order conservative remapping weights for the first input field and",
- " writes the result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " writes the result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3667,7 +3711,7 @@ static const char *RemaplafHelp[] = {
" Performs a largest area fraction remapping on all input fields.",
" genlaf Generate largest area fraction remap weights",
" Generates largest area fraction remapping weights for the first input field and",
- " writes the result to a file. The format of this file is netCDF following the SCRIP convention.",
+ " writes the result to a file. The format of this file is NetCDF following the SCRIP convention.",
" Use the operator remap to apply this remapping weights to a data file with the same source grid.",
"",
"PARAMETER",
@@ -3694,14 +3738,14 @@ static const char *RemapHelp[] = {
" Firstly the generation of the interpolation weights, which is the most time-consuming part.",
" These interpolation weights can be reused for every remapping process with the operator remap.",
" This operator remaps all input fields to a new horizontal grid. The remap type and ",
- " the interpolation weights of one input grid are read from a netCDF file. More weights ",
- " are computed if the input fields are on different grids. The netCDF file with the ",
+ " the interpolation weights of one input grid are read from a NetCDF file. More weights ",
+ " are computed if the input fields are on different grids. The NetCDF file with the ",
" weights should follow the SCRIP convention. Normally these weights come from a previous",
" call to one of the genXXX operators (e.g. genbil) or were created by the original SCRIP package.",
"",
"PARAMETER",
" grid STRING Target grid description file or name",
- " weights STRING Interpolation weights (SCRIP netCDF file)",
+ " weights STRING Interpolation weights (SCRIP NetCDF file)",
"",
"ENVIRONMENT",
" CDO_REMAP_NORM ",
@@ -3765,7 +3809,7 @@ static const char *RemapetaHelp[] = {
"",
"NOTE",
" The code numbers or the variable names of the required parameter have to follow the ECHAM convention.",
- " Presently, the vertical coordinate definition of a netCDF file has also to follow the ECHAM convention.",
+ " Presently, the vertical coordinate definition of a NetCDF file has also to follow the ECHAM convention.",
" This means:",
" - the dimension of the full level coordinate and the corresponding variable is called mlev,",
" - the dimension of the half level coordinate and the corresponding variable is called ilev (ilev must have one element more than mlev)",
@@ -3794,7 +3838,7 @@ static const char *VertintmlHelp[] = {
" The input file should contain the log. surface pressure or the surface pressure.",
" To interpolate the temperature, the surface geopotential is also needed.",
" The pressure, temperature, and surface geopotential are identified by their GRIB1 code number",
- " or netCDF CF standard name.",
+ " or NetCDF CF standard name.",
" Supported parameter tables are: WMO standard table number 2 and ECMWF local table number 128.",
" Use the alias ml2plx/ml2hlx or the environment variable EXTRAPOLATE",
" to extrapolate missing values. This operator requires all variables on the same horizontal grid.",
@@ -3829,14 +3873,14 @@ static const char *VertintapHelp[] = {
"DESCRIPTION",
" Interpolate 3D variables on hybrid sigma height coordinates to pressure levels.",
" The input file must contain the 3D air pressure. The air pressure is identified",
- " by the netCDF CF standard name air_pressure.",
+ " by the NetCDF CF standard name air_pressure.",
" This operator requires all variables on the same horizontal grid.",
"",
"PARAMETER",
" plevels FLOAT Pressure levels in pascal",
"",
"NOTE",
- " This is a specific implementation for netCDF files from the ICON model, it may not work with data from other sources.",
+ " This is a specific implementation for NetCDF files from the ICON model, it may not work with data from other sources.",
NULL
};
@@ -4238,6 +4282,28 @@ static const char *OutputtabHelp[] = {
NULL
};
+static const char *OutputgmtHelp[] = {
+ "NAME",
+ " gmtxyz, gmtcells - GMT output",
+ "",
+ "SYNOPSIS",
+ " <operator> ifile",
+ "",
+ "DESCRIPTION",
+ " This module prints the first field of the input dataset to standard output.",
+ " The output can be used to generate 2D Lon/Lat plots with GMT.",
+ " The format of the output depends on the chosen operator.",
+ "",
+ "OPERATORS",
+ " gmtxyz GMT xyz format",
+ " The operator exports the first field to the GMT xyz ASCII format.",
+ " The output can be used to create contour plots with the GMT module pscontour.",
+ " gmtcells GMT multiple segment format",
+ " The operator exports the first field to the GMT multiple segment ASCII format.",
+ " The output can be used to create shaded gridfill plots with the GMT module psxy.",
+ NULL
+};
+
static const char *GradsdesHelp[] = {
"NAME",
" gradsdes - GrADS data descriptor file",
@@ -4246,7 +4312,7 @@ static const char *GradsdesHelp[] = {
" gradsdes[,mapversion] ifile",
"",
"DESCRIPTION",
- " Creates a GrADS data descriptor file. Supported file formats are GRIB1, netCDF, SERVICE, ",
+ " Creates a GrADS data descriptor file. Supported file formats are GRIB1, NetCDF, SERVICE, ",
" EXTRA and IEG. For GRIB1 files the GrADS map file is also generated. For SERVICE and EXTRA",
" files the grid have to be specified with the CDO option '-g <grid>'. This module takes ifile",
" in order to create filenames for the descriptor (ifile.ctl) and the map (ifile.gmp) file.",
@@ -4266,7 +4332,7 @@ static const char *AfterburnerHelp[] = {
" after - ECHAM standard post processor",
"",
"SYNOPSIS",
- " after ifiles ofile",
+ " after[,vct] ifiles ofile",
"",
"DESCRIPTION",
" The \"afterburner\" is the standard post processor for ECHAM data which provides the following operations:",
@@ -4351,6 +4417,9 @@ static const char *AfterburnerHelp[] = {
" 0/10/11 & 152 LnPs & 0",
" 0/10/11 & 155 divergence & 0",
" >11 & all codes & 0/1",
+ "",
+ "PARAMETER",
+ " vct STRING File with VCT in ASCII format",
NULL
};
@@ -4813,6 +4882,162 @@ static const char *HurrHelp[] = {
NULL
};
+static const char *MagplotHelp[] = {
+ "NAME",
+ " contour, shaded, grfill - Lat/Lon plot",
+ "",
+ "SYNOPSIS",
+ " <operator>,params ifile obase",
+ "",
+ "DESCRIPTION",
+ " The operators in this module generates 2D Lon/Lat plots.",
+ " The data for the plot is read from ifile.",
+ " Only data on rectilinear Lon/Lat grids are supported.",
+ " The output file will be named <obase>_<param>.<device> where param is the parameter name and",
+ " device is the device name. The default output file format is postscript,",
+ " this can be changed with the device parameter.",
+ " The type of the plot depends on the choosen operator.",
+ " ",
+ " Here is a list of all common plot parameters:",
+ " ",
+ " Keyname & Type & Description ",
+ " device & STRING & Output device (ps, eps, pdf, png, gif, gif_animation, jpeg, svg, kml)",
+ " projection & STRING & Projection (cylindrical, polar_stereographic, robinson, mercator)",
+ " style & STRING & Contour line style (solid, dash, dot, chain_dash, chain_dot)",
+ " min & FLOAT & Minimum value",
+ " max & FLOAT & Maximum value",
+ " lon_max & FLOAT & Maximum longitude of the image",
+ " lon_min & FLOAT & Minimum longitude of the image",
+ " lat_max & FLOAT & Maximum latitude of the image",
+ " lat_min & FLOAT & Minimum latitude of the image",
+ " count & INTEGER & Number of Contour levels / Colour bands ",
+ " interval & FLOAT & Interval in data units between two bands lines",
+ " list & INTEGER & List of levels to be plotted",
+ " RGB & STRING & TRUE or FALSE, to indicate, if the input colour is in RGB format",
+ " step_freq & INTEGER & Frequency of time steps to be considered for making the animation",
+ " & & (device=gif_animation). Default value is \"1\" (all time steps).",
+ " & & Will be ignored if input file has multiple variables.",
+ " file_split & STRING & TRUE or FALSE, to split the output file for each variable, if input has",
+ " & & multiple variables. Default value is \"FALSE\". Valid only for \"PS\" format.",
+ "",
+ "OPERATORS",
+ " contour Contour plot",
+ " The operator contour generates the discrete contour lines of the input field values.",
+ " The following additional parameters are valid for contour operator,",
+ " module in addition to the common plot parameters:",
+ " ",
+ " Keyname & Type & Description ",
+ " colour & STRING & Colour for drawing the contours",
+ " thickness & FLOAT & Thickness of the contour line",
+ " style & STRING & Line Style can be \"SOLID\", \"DASH\", \"DOT\", \"CHAIN_DASH\",",
+ " & & \"CHAIN_DOT\"",
+ " shaded Shaded contour plot",
+ " The operator shaded generates the filled contours of the given input field values.",
+ " The following additional parameters are valid for shaded contour and gridfill operator,",
+ " in addition to the common plot parameters.",
+ " ",
+ " Keyname & Type & Description ",
+ " colour_min & STRING & Colour for the Minimum colour band",
+ " colour_max & STRING & Colour for the Minimum colour band",
+ " colour_triad & STRING & Direction of colour sequencing for shading \"CW\" or \"ACW\",",
+ " & & to denote \"clockwise\" and \"anticlockwise\" respectively.",
+ " & & To be used in conjunction with \"colour_min\", \"colour_max\"",
+ " & & options. Default is \"ACW\"",
+ " colour_table & STRING & File with user specified colours with the format as",
+ " ",
+ " Example file for 6 colours in RGB format:",
+ " 6",
+ " RGB(0.0;0.0;1.0)",
+ " RGB(0.0;0.0;0.5)",
+ " RGB(0.0;0.5;0.5)",
+ " RGB(0.0;1.0;0.0)",
+ " RGB(0.5;0.5;0.0)",
+ " RGB(1.0;0.0;0.0)",
+ " ",
+ " grfill Shaded gridfill plot",
+ " The operator grfill is similar to satellite imaging and shades each cell (pixel) according",
+ " to the value of the field at that cell.",
+ "",
+ "PARAMETER",
+ " params STRING Comma separated list of plot parameters",
+ "",
+ "NOTE",
+ " All colour parameter can be either standard name or in RGB format.",
+ " The valid standard name strings for \"colour\" are:",
+ " ",
+ " \"red\", \"green\", \"blue\", \"yellow\", \"cyan\", \"magenta\", \"black\", \"avocado\", \"beige\",",
+ " \"brick\", \"brown\", \"burgundy\", \"charcoal\", \"chestnut\", \"coral\", \"cream\", \"evergreen\",",
+ " \"gold\", \"grey\", \"khaki\", \"kellygreen\", \"lavender\", \"mustard\", \"navy\", \"ochre\",",
+ " \"olive\", \"peach\", \"pink\", \"rose\", \"rust\", \"sky\", \"tan\", \"tangerine\", \"turquoise\",",
+ " \"violet\", \"reddishpurple\", \"purplered\", \"purplishred\", \"orangishred\", \"redorange\",",
+ " \"reddishorange\", \"orange\", \"yellowishorange\", \"orangeyellow\", \"orangishyellow\",",
+ " \"greenishyellow\", \"yellowgreen\", \"yellowishgreen\", \"bluishgreen\", \"bluegreen\",",
+ " \"greenishblue\", \"purplishblue\", \"bluepurple\", \"bluishpurple\", \"purple\", \"white\"",
+ NULL
+};
+
+static const char *MagvectorHelp[] = {
+ "NAME",
+ " vector - Lat/Lon vector plot",
+ "",
+ "SYNOPSIS",
+ " vector,params ifile obase",
+ "",
+ "DESCRIPTION",
+ " This operator generates 2D Lon/Lat vector plots.",
+ " The data for the plot is read from ifile. The input is expected to contain two velocity",
+ " components. Only data on rectilinear Lon/Lat grids are supported.",
+ " The output file will be named <obase>.<device> where device is the device name. ",
+ " The default output file format is postscript, this can be changed with the device parameter.",
+ " ",
+ " Here is a list of all vector plot parameters:",
+ " ",
+ " Keyname & Type & Description ",
+ " device & STRING & Output device (ps, eps, pdf, png, gif, gif_animation, jpeg, svg, kml)",
+ " projection & STRING & Projection (cylindrical, polar_stereographic, robinson, mercator)",
+ " thin_fac & FLOAT & Controls the actual number of wind arrows or flags plotted (default 2).",
+ " unit_vec & FLOAT & Wind speed in m/s represented by a unit vector (1.0cm)",
+ " step_freq & INTEGER & Frequency of time steps to be considered for making the animation",
+ " & & (device=gif_animation). Default value is \"1\" (all time steps).",
+ " & & Will be ignored if input file has multiple variables.",
+ "",
+ "PARAMETER",
+ " params STRING Comma separated list of plot parameters",
+ NULL
+};
+
+static const char *MaggraphHelp[] = {
+ "NAME",
+ " graph - Line graph plot",
+ "",
+ "SYNOPSIS",
+ " graph,params ifiles ofile",
+ "",
+ "DESCRIPTION",
+ " This operator generates line graph plots.",
+ " The data for the plot is read from ifiles. The result is written to ofile.",
+ " The default output file format is postscript, this can be changed with the device parameter.",
+ " ",
+ " Here is a list of all graph plot parameters:",
+ " ",
+ " Keyname & Type & Description ",
+ " device & STRING & Output device (ps, eps, pdf, png, gif, gif_animation, jpeg, svg, kml)",
+ " ymin & FLOAT & Minimum value of the y-axis data ",
+ " ymax & FLOAT & Maximum value of the y-axis data ",
+ " stat & STRING & \"TRUE\" or \"FALSE\", to switch on the mean computation. Default is \"FALSE\".",
+ " & & Will be overridden to \"FALSE\", if input files have unequal number of time",
+ " & & steps or different start/end times. ",
+ " sigma & FLOAT & Standard deviation value for generating shaded back ground around the mean value.",
+ " & & To be used in conjunction with 'stat=\"TRUE\"' ",
+ " obsv & STRING & To indicate if the input files have an observation data, by setting to \"TRUE\".",
+ " & & Default value is \"FALSE\". The observation data should be the first file in the",
+ " & & input file list. The observation data is always plotted in black colour. ",
+ "",
+ "PARAMETER",
+ " params STRING Comma separated list of plot parameters",
+ NULL
+};
+
static const char *EcaCddHelp[] = {
"NAME",
" eca_cdd - Consecutive dry days index per time period",
diff --git a/src/pipe.c b/src/pipe.c
index 8ca8f67..44120cb 100644
--- a/src/pipe.c
+++ b/src/pipe.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/pipe.h b/src/pipe.h
index 8bb7891..964878f 100644
--- a/src/pipe.h
+++ b/src/pipe.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/printinfo.h b/src/printinfo.h
index c68c2ec..4b5055f 100644
--- a/src/printinfo.h
+++ b/src/printinfo.h
@@ -3,18 +3,6 @@
#define DATE_FORMAT "%5.4d-%2.2d-%2.2d"
#define TIME_FORMAT "%2.2d:%2.2d:%2.2d"
-void uuid2str(const unsigned char uuid[CDI_UUID_SIZE], char *uuidstr);
-
-static inline
-int cdiUUIDIsNull(const unsigned char uuid[CDI_UUID_SIZE])
-{
- int isNull = 1;
- for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
- isNull &= (uuid[i] == 0);
- return isNull;
-}
-
-
void datetime2str(int date, int time, char *datetimestr, int maxlen)
{
int year, month, day;
@@ -63,16 +51,16 @@ void printFiletype(int streamID, int vlistID)
printf("GRIB2");
break;
case FILETYPE_NC:
- printf("netCDF");
+ printf("NetCDF");
break;
case FILETYPE_NC2:
- printf("netCDF2");
+ printf("NetCDF2");
break;
case FILETYPE_NC4:
- printf("netCDF4");
+ printf("NetCDF4");
break;
case FILETYPE_NC4C:
- printf("netCDF4 classic");
+ printf("NetCDF4 classic");
break;
case FILETYPE_SRV:
printf("SERVICE");
@@ -385,7 +373,7 @@ void printGridInfo(int vlistID)
if ( !cdiUUIDIsNull(uuidOfHGrid) )
{
char uuidOfHGridStr[37];
- uuid2str(uuidOfHGrid, uuidOfHGridStr);
+ cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr);
if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 )
{
fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr);
@@ -502,7 +490,7 @@ void printZaxisInfo(int vlistID)
if ( !cdiUUIDIsNull(uuidOfVGrid) )
{
char uuidOfVGridStr[37];
- uuid2str(uuidOfVGrid, uuidOfVGridStr);
+ cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr);
if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 )
{
fprintf(stdout, "%33s : ", "uuid");
diff --git a/src/process.c b/src/process.c
index a6b4af6..19410e0 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -352,10 +352,11 @@ argument_t *glob_pattern(const char *restrict string)
char **p;
wordexp_t glob_results;
+ glob_results.we_wordc = 0;
argument_t *argument = NULL;
// glob the input argument or do even more shell magic
- wordexp(string, &glob_results, flags);
+ int status = wordexp(string, &glob_results, flags);
// How much space do we need?
for ( p = glob_results.we_wordv, cnt = glob_results.we_wordc; cnt; p++, cnt-- )
@@ -374,7 +375,7 @@ argument_t *glob_pattern(const char *restrict string)
if ( cnt < glob_results.we_wordc-1 ) strcat(argument->args, " ");
}
- wordfree(&glob_results);
+ if ( status == 0 ) wordfree(&glob_results);
return argument;
}
diff --git a/src/process.h b/src/process.h
index 5b0e830..e4ff3cb 100644
--- a/src/process.h
+++ b/src/process.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/pstream.c b/src/pstream.c
index 9c222e5..d66055a 100644
--- a/src/pstream.c
+++ b/src/pstream.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -141,7 +141,7 @@ pstream_t *pstream_to_pointer(int idx)
else
Error("pstream index %d undefined!", idx);
- return (pstreamptr);
+ return pstreamptr;
}
/* Create an index from a pointer */
@@ -173,7 +173,7 @@ int pstream_from_pointer(pstream_t *ptr)
else
Error("Internal problem (pointer %p undefined)", ptr);
- return (idx);
+ return idx;
}
static
@@ -210,7 +210,7 @@ pstream_t *pstream_new_entry(void)
if ( pstreamptr ) pstream_init_entry(pstreamptr);
- return (pstreamptr);
+ return pstreamptr;
}
static
@@ -274,7 +274,7 @@ int pstreamFindID(const char *name)
if ( pstreamID == _pstream_max ) pstreamID = -1;
- return (pstreamID);
+ return pstreamID;
}
@@ -282,7 +282,7 @@ int pstreamIsPipe(int pstreamID)
{
pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
- return (pstreamptr->ispipe);
+ return pstreamptr->ispipe;
}
@@ -524,8 +524,12 @@ int pstreamOpenRead(const argument_t *argument)
pthread_mutex_lock(&streamOpenReadMutex);
#endif
int fileID = streamOpenRead(filename);
- if ( fileID < 0 ) cdiOpenError(fileID, "Open failed on >%s<", filename);
-
+ if ( fileID < 0 )
+ {
+ pstreamptr->isopen = FALSE;
+ cdiOpenError(fileID, "Open failed on >%s<", filename);
+ }
+
if ( cdoDefaultFileType == CDI_UNDEFID )
cdoDefaultFileType = streamInqFiletype(fileID);
/*
@@ -547,7 +551,7 @@ int pstreamOpenRead(const argument_t *argument)
if ( pstreamID < 0 ) cdiOpenError(pstreamID, "Open failed on >%s<", argument->args);
- return (pstreamID);
+ return pstreamID;
}
static
@@ -698,13 +702,13 @@ int pstreamOpenWrite(const argument_t *argument, int filetype)
if ( cdoCompType == COMPRESS_SZIP &&
(filetype != FILETYPE_GRB && filetype != FILETYPE_GRB2 && filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
- cdoWarning("SZIP compression not available for non GRIB/netCDF4 data!");
+ cdoWarning("SZIP compression not available for non GRIB/NetCDF4 data!");
if ( cdoCompType == COMPRESS_JPEG && filetype != FILETYPE_GRB2 )
cdoWarning("JPEG compression not available for non GRIB2 data!");
if ( cdoCompType == COMPRESS_ZIP && (filetype != FILETYPE_NC4 && filetype != FILETYPE_NC4C) )
- cdoWarning("Deflate compression not available for non netCDF4 data!");
+ cdoWarning("Deflate compression not available for non NetCDF4 data!");
}
/*
if ( cdoDefaultInstID != CDI_UNDEFID )
@@ -718,7 +722,7 @@ int pstreamOpenWrite(const argument_t *argument, int filetype)
pstreamptr->filetype = filetype;
}
- return (pstreamID);
+ return pstreamID;
}
@@ -771,7 +775,7 @@ int pstreamOpenAppend(const argument_t *argument)
pstreamptr->fileID = fileID;
}
- return (pstreamID);
+ return pstreamID;
}
@@ -1157,6 +1161,34 @@ void pstreamReadRecord(int pstreamID, double *data, int *nmiss)
}
+void pstreamReadRecordF(int pstreamID, float *data, int *nmiss)
+{
+ if ( data == NULL ) cdoAbort("Data pointer not allocated (pstreamReadRecord)!");
+
+ pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
+
+#if defined(HAVE_LIBPTHREAD)
+ if ( pstreamptr->ispipe )
+ {
+ cdoAbort("pipeReadRecord not implemented for memtype float!");
+ // pipeReadRecord(pstreamptr, data, nmiss);
+ }
+ else
+#endif
+ {
+ if ( processNums() == 1 && ompNumThreads == 1 ) timer_start(timer_read);
+#if defined(HAVE_LIBPTHREAD)
+ if ( cdoLockIO ) pthread_mutex_lock(&streamMutex);
+#endif
+ streamReadRecordF(pstreamptr->fileID, data, nmiss);
+#if defined(HAVE_LIBPTHREAD)
+ if ( cdoLockIO ) pthread_mutex_unlock(&streamMutex);
+#endif
+ if ( processNums() == 1 && ompNumThreads == 1 ) timer_stop(timer_read);
+ }
+}
+
+
void pstreamCheckDatarange(pstream_t *pstreamptr, int varID, double *array, int nmiss)
{
long i;
@@ -1383,7 +1415,7 @@ int pstreamInqTimestep(int pstreamID, int tsID)
pstreamptr->tsID = tsID;
}
- return (nrecs);
+ return nrecs;
}
@@ -1645,7 +1677,7 @@ int pstreamInqFiletype(int pstreamID)
#endif
filetype = streamInqFiletype(pstreamptr->fileID);
- return (filetype);
+ return filetype;
}
@@ -1662,9 +1694,10 @@ int pstreamInqByteorder(int pstreamID)
#endif
byteorder = streamInqByteorder(pstreamptr->fileID);
- return (byteorder);
+ return byteorder;
}
+
void pstreamInqGRIBinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum)
{
pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
@@ -1673,6 +1706,14 @@ void pstreamInqGRIBinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum
}
+int pstreamFileID(int pstreamID)
+{
+ pstream_t *pstreamptr = pstream_to_pointer(pstreamID);
+
+ return pstreamptr->fileID;
+}
+
+
void cdoVlistCopyFlag(int vlistID2, int vlistID1)
{
#if defined(HAVE_LIBPTHREAD)
diff --git a/src/pstream.h b/src/pstream.h
index 4550d4b..59b5c06 100644
--- a/src/pstream.h
+++ b/src/pstream.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -36,6 +36,7 @@
#define streamInqRecord pstreamInqRecord
#define streamReadRecord pstreamReadRecord
+#define streamReadRecordF pstreamReadRecordF
#define streamCopyRecord pstreamCopyRecord
@@ -58,10 +59,13 @@ int pstreamInqTimestep(int pstreamID, int tsID);
int pstreamInqRecord(int pstreamID, int *varID, int *levelID);
void pstreamReadRecord(int pstreamID, double *data, int *nmiss);
+void pstreamReadRecordF(int pstreamID, float *data, int *nmiss);
void pstreamCopyRecord(int pstreamIDdest, int pstreamIDsrc);
void pstreamInqGRIBinfo(int pstreamID, int *intnum, float *fltnum, off_t *bignum);
+int pstreamFileID(int pstreamID);
+
void cdoVlistCopyFlag(int vlistID2, int vlistID1);
#endif /* _PSTREAM_H */
diff --git a/src/pstream_int.h b/src/pstream_int.h
index daa5f49..72e5501 100644
--- a/src/pstream_int.h
+++ b/src/pstream_int.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/pstream_write.h b/src/pstream_write.h
index 3feb228..fb1a595 100644
--- a/src/pstream_write.h
+++ b/src/pstream_write.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/readline.c b/src/readline.c
index 4bfdfb0..b2d0e20 100644
--- a/src/readline.c
+++ b/src/readline.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/remap.h b/src/remap.h
index d85435d..92a979f 100644
--- a/src/remap.h
+++ b/src/remap.h
@@ -236,4 +236,7 @@ int rect_grid_search(long *ii, long *jj, double x, double y, long nxm, long nym,
void remapgrid_get_lonlat(remapgrid_t *grid, unsigned cell_add, double *plon, double *plat);
+void remapCheckArea(int grid_size, double *restrict cell_area, const char *name);
+void remapCheckWeights(long num_links, int num_wts, int norm_opt, int *src_cell_add, int *tgt_cell_add, double *wts);
+
#endif /* _REMAP_H */
diff --git a/src/remap_conserv.c b/src/remap_conserv.c
index 85b3bf3..7055407 100644
--- a/src/remap_conserv.c
+++ b/src/remap_conserv.c
@@ -4,6 +4,100 @@
#include "remap.h"
#include "remap_store_link.h"
+#include "clipping/clipping.h"
+#include "clipping/area.h"
+#include "clipping/geometry.h"
+
+//#define STIMER
+
+#ifdef STIMER
+#include <time.h>
+#endif
+
+typedef struct {
+ enum yac_edge_type *src_edge_type;
+ long srch_corners;
+ long max_srch_cells;
+ double *partial_areas;
+ double *partial_weights;
+ struct grid_cell *src_grid_cells;
+ struct grid_cell *overlap_buffer;
+} search_t;
+
+static
+void search_realloc(long num_srch_cells, search_t *search)
+{
+ long max_srch_cells = search->max_srch_cells;
+ double *partial_areas = search->partial_areas;
+ double *partial_weights = search->partial_weights;
+ struct grid_cell *overlap_buffer = search->overlap_buffer;
+ struct grid_cell *src_grid_cells = search->src_grid_cells;
+
+ if ( num_srch_cells > max_srch_cells )
+ {
+ partial_areas = (double*) realloc(partial_areas, num_srch_cells*sizeof(double));
+ partial_weights = (double*) realloc(partial_weights, num_srch_cells*sizeof(double));
+ overlap_buffer = (struct grid_cell*) realloc(overlap_buffer, num_srch_cells*sizeof(struct grid_cell));
+ src_grid_cells = (struct grid_cell*) realloc(src_grid_cells, num_srch_cells*sizeof(struct grid_cell));
+
+ for ( long n = max_srch_cells; n < num_srch_cells; ++n )
+ {
+ overlap_buffer[n].array_size = 0;
+ overlap_buffer[n].num_corners = 0;
+ overlap_buffer[n].edge_type = NULL;
+ overlap_buffer[n].coordinates_x = NULL;
+ overlap_buffer[n].coordinates_y = NULL;
+ overlap_buffer[n].coordinates_xyz = NULL;
+ }
+
+ for ( long n = max_srch_cells; n < num_srch_cells; ++n )
+ {
+ src_grid_cells[n].array_size = search->srch_corners;
+ src_grid_cells[n].num_corners = search->srch_corners;
+ src_grid_cells[n].edge_type = search->src_edge_type;
+ src_grid_cells[n].coordinates_x = (double*) malloc(search->srch_corners*sizeof(double));
+ src_grid_cells[n].coordinates_y = (double*) malloc(search->srch_corners*sizeof(double));
+ src_grid_cells[n].coordinates_xyz = (double*) malloc(3*search->srch_corners*sizeof(double));
+ }
+
+ max_srch_cells = num_srch_cells;
+
+ search->max_srch_cells = max_srch_cells;
+ search->partial_areas = partial_areas;
+ search->partial_weights = partial_weights;
+ search->overlap_buffer = overlap_buffer;
+ search->src_grid_cells = src_grid_cells;
+ }
+}
+
+static
+void search_free(search_t *search)
+{
+ long max_srch_cells = search->max_srch_cells;
+ double *partial_areas = search->partial_areas;
+ double *partial_weights = search->partial_weights;
+ struct grid_cell *overlap_buffer = search->overlap_buffer;
+ struct grid_cell *src_grid_cells = search->src_grid_cells;
+
+ for ( long n = 0; n < max_srch_cells; n++ )
+ {
+ if ( overlap_buffer[n].array_size > 0 )
+ {
+ Free(overlap_buffer[n].coordinates_x);
+ Free(overlap_buffer[n].coordinates_y);
+ if ( overlap_buffer[n].coordinates_xyz ) Free(overlap_buffer[n].coordinates_xyz);
+ if ( overlap_buffer[n].edge_type ) Free(overlap_buffer[n].edge_type);
+ }
+
+ Free(src_grid_cells[n].coordinates_x);
+ Free(src_grid_cells[n].coordinates_y);
+ Free(src_grid_cells[n].coordinates_xyz);
+ }
+
+ Free(partial_areas);
+ Free(partial_weights);
+}
+
int rect_grid_search2(long *imin, long *imax, double xmin, double xmax, long nxm, const double *restrict xm);
@@ -108,7 +202,7 @@ long get_srch_cells_reg2d(const int *restrict src_grid_dims,
if ( debug ) printf(" -> num_srch_cells: %ld\n", num_srch_cells);
- return (num_srch_cells);
+ return num_srch_cells;
}
static
@@ -250,9 +344,6 @@ void boundbox_from_corners1r(long ic, long nc, const double *restrict corner_lon
}
//#if defined(HAVE_LIBYAC)
-#include "clipping/clipping.h"
-#include "clipping/area.h"
-#include "clipping/geometry.h"
static
double gridcell_area(struct grid_cell cell)
@@ -261,12 +352,12 @@ double gridcell_area(struct grid_cell cell)
}
static
-void cdo_compute_overlap_areas(unsigned N,
- struct grid_cell *overlap_buffer,
- struct grid_cell *source_cells,
- struct grid_cell target_cell,
- double *partial_areas)
+void cdo_compute_overlap_areas(unsigned N, search_t *search, struct grid_cell target_cell)
{
+ double *partial_areas = search->partial_areas;
+ struct grid_cell *overlap_buffer = search->overlap_buffer;
+ struct grid_cell *source_cells = search->src_grid_cells;
+
/* Do the clipping and get the cell for the overlapping area */
yac_cell_clipping(N, source_cells, target_cell, overlap_buffer);
@@ -325,14 +416,13 @@ static enum cell_type get_cell_type(struct grid_cell target_cell) {
}
*/
static
-void cdo_compute_concave_overlap_areas(unsigned N,
- struct grid_cell *overlap_buffer,
- struct grid_cell *source_cell,
- struct grid_cell target_cell,
- double target_node_x,
- double target_node_y,
- double * partial_areas)
+void cdo_compute_concave_overlap_areas(unsigned N, search_t *search, struct grid_cell target_cell,
+ double target_node_x, double target_node_y)
{
+ double *partial_areas = search->partial_areas;
+ struct grid_cell *overlap_buffer = search->overlap_buffer;
+ struct grid_cell *source_cell = search->src_grid_cells;
+
/*
enum cell_type target_cell_type = UNDEF_CELL;
@@ -490,18 +580,18 @@ int get_lonlat_circle_index(remapgrid_t *remap_grid)
//printf("lonlat_circle_index %d\n", lonlat_circle_index);
- return (lonlat_circle_index);
+ return lonlat_circle_index;
}
static
-void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv)
+void remapNormalizeWeights(remapgrid_t *tgt_grid, remapvars_t *rv)
{
- /* Include centroids in weights and normalize using destination area if requested */
- long num_wts = rv->num_wts;
+ // Include centroids in weights and normalize using destination area if requested
long num_links = rv->num_links;
- long tgt_cell_add; /* current linear address for target grid cell */
- double norm_factor = 0; /* factor for normalizing wts */
+ int num_wts = rv->num_wts;
+ int tgt_cell_add; // current linear address for target grid cell
+ double norm_factor = 0; // factor for normalizing wts
if ( rv->norm_opt == NORM_OPT_DESTAREA )
{
@@ -510,7 +600,7 @@ void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv)
#endif
#if defined(_OPENMP)
#pragma omp parallel for default(none) \
- shared(num_wts, num_links, rv, tgt_grid) \
+ shared(num_wts, num_links, rv, tgt_grid) \
private(tgt_cell_add, norm_factor)
#endif
for ( long n = 0; n < num_links; ++n )
@@ -532,7 +622,7 @@ void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv)
#endif
#if defined(_OPENMP)
#pragma omp parallel for default(none) \
- shared(num_wts, num_links, rv, tgt_grid) \
+ shared(num_wts, num_links, rv, tgt_grid) \
private(tgt_cell_add, norm_factor)
#endif
for ( long n = 0; n < num_links; ++n )
@@ -552,53 +642,94 @@ void normalize_weights(remapgrid_t *tgt_grid, remapvars_t *rv)
}
}
+static
+void set_yac_coordinates(int remap_grid_type, int cell_add, int num_cell_corners, remapgrid_t *remap_grid, struct grid_cell *yac_grid_cell)
+{
+ if ( remap_grid_type == REMAP_GRID_TYPE_REG2D )
+ {
+ int nx = remap_grid->dims[0];
+ int iy = cell_add/nx;
+ int ix = cell_add - iy*nx;
+ const double *restrict reg2d_corner_lon = remap_grid->reg2d_corner_lon;
+ const double *restrict reg2d_corner_lat = remap_grid->reg2d_corner_lat;
+ double *restrict coordinates_x = yac_grid_cell->coordinates_x;
+ double *restrict coordinates_y = yac_grid_cell->coordinates_y;
+
+ coordinates_x[0] = reg2d_corner_lon[ix ];
+ coordinates_y[0] = reg2d_corner_lat[iy ];
+ coordinates_x[1] = reg2d_corner_lon[ix+1];
+ coordinates_y[1] = reg2d_corner_lat[iy ];
+ coordinates_x[2] = reg2d_corner_lon[ix+1];
+ coordinates_y[2] = reg2d_corner_lat[iy+1];
+ coordinates_x[3] = reg2d_corner_lon[ix ];
+ coordinates_y[3] = reg2d_corner_lat[iy+1];
+ }
+ else
+ {
+ const double *restrict cell_corner_lon = remap_grid->cell_corner_lon;
+ const double *restrict cell_corner_lat = remap_grid->cell_corner_lat;
+ double *restrict coordinates_x = yac_grid_cell->coordinates_x;
+ double *restrict coordinates_y = yac_grid_cell->coordinates_y;
+ for ( int ic = 0; ic < num_cell_corners; ++ic )
+ {
+ coordinates_x[ic] = cell_corner_lon[cell_add*num_cell_corners+ic];
+ coordinates_y[ic] = cell_corner_lat[cell_add*num_cell_corners+ic];
+ }
+ }
+
+ const double *restrict coordinates_x = yac_grid_cell->coordinates_x;
+ const double *restrict coordinates_y = yac_grid_cell->coordinates_y;
+ double *restrict coordinates_xyz = yac_grid_cell->coordinates_xyz;
+ for ( int ic = 0; ic < num_cell_corners; ++ic )
+ LLtoXYZ(coordinates_x[ic], coordinates_y[ic], coordinates_xyz+ic*3);
+}
+
+static
+void reg2d_bound_box(remapgrid_t *remap_grid, double *grid_bound_box)
+{
+ int nx = remap_grid->dims[0];
+ int ny = remap_grid->dims[1];
+ const double *restrict reg2d_corner_lon = remap_grid->reg2d_corner_lon;
+ const double *restrict reg2d_corner_lat = remap_grid->reg2d_corner_lat;
+
+ grid_bound_box[0] = reg2d_corner_lat[0];
+ grid_bound_box[1] = reg2d_corner_lat[ny];
+ if ( grid_bound_box[0] > grid_bound_box[1] )
+ {
+ grid_bound_box[0] = reg2d_corner_lat[ny];
+ grid_bound_box[1] = reg2d_corner_lat[0];
+ }
+ grid_bound_box[2] = reg2d_corner_lon[0];
+ grid_bound_box[3] = reg2d_corner_lon[nx];
+}
+
void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapvars_t *rv)
{
- /* local variables */
-
- int lcheck = TRUE;
-
- long ioffset;
- long src_num_cell_corners;
- long tgt_num_cell_corners;
- long src_cell_add; /* current linear address for source grid cell */
- long k; /* generic counters */
- long nbins;
- long num_wts;
- long max_srch_cells; /* num cells in restricted search arrays */
- long num_srch_cells; /* num cells in restricted search arrays */
- long srch_corners; /* num of corners of srch cells */
- int* srch_add; /* global address of cells in srch arrays */
- int i;
+ int lcheck = TRUE;
+ int srch_corners; // num of corners of srch cells
/* Variables necessary if segment manages to hit pole */
- long nx = 0, ny = 0;
int src_remap_grid_type = src_grid->remap_grid_type;
int tgt_remap_grid_type = tgt_grid->remap_grid_type;
- double src_grid_bound_box[4];
- int lyac = FALSE;
extern int timer_remap_con;
if ( cdoVerbose ) cdoPrint("Called %s()", __func__);
progressInit();
- nbins = src_grid->num_srch_bins;
- num_wts = rv->num_wts;
-
if ( cdoTimer ) timer_start(timer_remap_con);
- long src_grid_size = src_grid->size;
- long tgt_grid_size = tgt_grid->size;
+ int src_grid_size = src_grid->size;
+ int tgt_grid_size = tgt_grid->size;
- src_num_cell_corners = src_grid->num_cell_corners;
- tgt_num_cell_corners = tgt_grid->num_cell_corners;
+ int src_num_cell_corners = src_grid->num_cell_corners;
+ int tgt_num_cell_corners = tgt_grid->num_cell_corners;
int max_num_cell_corners = src_num_cell_corners;
if ( tgt_num_cell_corners > max_num_cell_corners ) max_num_cell_corners = tgt_num_cell_corners;
- enum yac_edge_type great_circle_type[32];
+ enum yac_edge_type great_circle_type[max_num_cell_corners];
for ( int i = 0; i < max_num_cell_corners; ++i ) great_circle_type[i] = GREAT_CIRCLE;
enum yac_edge_type lonlat_circle_type[] = {LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE, LAT_CIRCLE, LON_CIRCLE};
@@ -627,14 +758,12 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
if ( !(tgt_num_cell_corners < 4 || target_cell_type == LON_LAT_CELL) )
{
if ( tgt_grid->cell_center_lon == NULL || tgt_grid->cell_center_lat == NULL )
- cdoAbort("Internal problem (remap_weights_conserv): missing target point coordinates!");
+ cdoAbort("Internal problem (%s): missing target point coordinates!", __func__);
}
- double tgt_area;
- struct grid_cell* tgt_grid_cell;
- struct grid_cell* tgt_grid_cell2[ompNumThreads];
- for ( i = 0; i < ompNumThreads; ++i )
+ struct grid_cell *tgt_grid_cell2[ompNumThreads];
+ for ( int i = 0; i < ompNumThreads; ++i )
{
tgt_grid_cell2[i] = (struct grid_cell*) Malloc(sizeof(struct grid_cell));
tgt_grid_cell2[i]->array_size = tgt_num_cell_corners;
@@ -645,76 +774,52 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
tgt_grid_cell2[i]->coordinates_xyz = (double*) Malloc(3*tgt_num_cell_corners*sizeof(double));
}
- struct grid_cell* src_grid_cells;
- struct grid_cell* overlap_buffer;
- struct grid_cell* src_grid_cells2[ompNumThreads];
- struct grid_cell* overlap_buffer2[ompNumThreads];
- for ( i = 0; i < ompNumThreads; ++i )
- {
- src_grid_cells2[i] = NULL;
- overlap_buffer2[i] = NULL;
- }
-
- double* partial_areas;
- double* partial_weights;
- double* partial_areas2[ompNumThreads];
- double* partial_weights2[ompNumThreads];
- for ( i = 0; i < ompNumThreads; ++i )
+ search_t search[ompNumThreads];
+ for ( int i = 0; i < ompNumThreads; ++i )
{
- partial_areas2[i] = NULL;
- partial_weights2[i] = NULL;
+ search[i].srch_corners = src_num_cell_corners;
+ search[i].src_edge_type = src_edge_type;
+ search[i].max_srch_cells = 0;
+ search[i].partial_areas = NULL;
+ search[i].partial_weights = NULL;
+ search[i].src_grid_cells = NULL;
+ search[i].overlap_buffer = NULL;
}
- long max_srch_cells2[ompNumThreads];
- for ( i = 0; i < ompNumThreads; ++i )
- max_srch_cells2[i] = 0;
-
- int* srch_add2[ompNumThreads];
- for ( i = 0; i < ompNumThreads; ++i )
+ int *srch_add2[ompNumThreads];
+ for ( int i = 0; i < ompNumThreads; ++i )
srch_add2[i] = (int*) Malloc(src_grid_size*sizeof(int));
srch_corners = src_num_cell_corners;
+ double src_grid_bound_box[4];
if ( src_remap_grid_type == REMAP_GRID_TYPE_REG2D )
- {
- nx = src_grid->dims[0];
- ny = src_grid->dims[1];
-
- src_grid_bound_box[0] = src_grid->reg2d_corner_lat[0];
- src_grid_bound_box[1] = src_grid->reg2d_corner_lat[ny];
- if ( src_grid_bound_box[0] > src_grid_bound_box[1] )
- {
- src_grid_bound_box[0] = src_grid->reg2d_corner_lat[ny];
- src_grid_bound_box[1] = src_grid->reg2d_corner_lat[0];
- }
- src_grid_bound_box[2] = src_grid->reg2d_corner_lon[0];
- src_grid_bound_box[3] = src_grid->reg2d_corner_lon[nx];
- //printf("src_grid lon: %g %g lat: %g %g\n", RAD2DEG*src_grid_bound_box[2],RAD2DEG*src_grid_bound_box[3],RAD2DEG*src_grid_bound_box[0],RAD2DEG*src_grid_bound_box[1] );
- }
+ reg2d_bound_box(src_grid, src_grid_bound_box);
weightlinks_t *weightlinks = (weightlinks_t *) Malloc(tgt_grid_size*sizeof(weightlinks_t));
double findex = 0;
- int sum_srch_cells = 0;
- int sum_srch_cells2 = 0;
+ long sum_srch_cells = 0;
+ long sum_srch_cells2 = 0;
+#ifdef STIMER
+ double stimer = 0;
+#endif
/* Loop over destination grid */
#if defined(_OPENMP)
#pragma omp parallel for schedule(dynamic) default(none) \
- shared(ompNumThreads, lyac, nbins, num_wts, src_remap_grid_type, tgt_remap_grid_type, src_grid_bound_box, \
- src_edge_type, tgt_edge_type, partial_areas2, partial_weights2, \
- rv, cdoVerbose, max_srch_cells2, tgt_num_cell_corners, target_cell_type, \
- weightlinks, \
- srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, nx, \
- overlap_buffer2, src_grid_cells2, srch_add2, tgt_grid_cell2, findex, sum_srch_cells, sum_srch_cells2) \
- private(srch_add, tgt_grid_cell, tgt_area, k, num_srch_cells, max_srch_cells, \
- partial_areas, partial_weights, overlap_buffer, src_grid_cells, src_cell_add, ioffset)
+ shared(ompNumThreads, src_remap_grid_type, tgt_remap_grid_type, src_grid_bound_box, \
+ rv, cdoVerbose, tgt_num_cell_corners, target_cell_type, \
+ weightlinks, srch_corners, src_grid, tgt_grid, tgt_grid_size, src_grid_size, \
+ search, srch_add2, tgt_grid_cell2, findex, sum_srch_cells, sum_srch_cells2)
#endif
for ( long tgt_cell_add = 0; tgt_cell_add < tgt_grid_size; ++tgt_cell_add )
{
double partial_weight;
+ long src_cell_add; /* current linear address for source grid cell */
+ long num_srch_cells;
long n, num_weights, num_weights_old;
int ompthID = cdo_omp_get_thread_num();
@@ -726,19 +831,20 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
weightlinks[tgt_cell_add].nlinks = 0;
- srch_add = srch_add2[ompthID];
- tgt_grid_cell = tgt_grid_cell2[ompthID];
+ int *srch_add = srch_add2[ompthID];
+ struct grid_cell *tgt_grid_cell = tgt_grid_cell2[ompthID];
/* Get search cells */
-
+#ifdef STIMER
+ clock_t start = clock();
+#endif
+
if ( src_remap_grid_type == REMAP_GRID_TYPE_REG2D && tgt_remap_grid_type == REMAP_GRID_TYPE_REG2D )
{
double tgt_cell_bound_box[4];
boundbox_from_corners_reg2d(tgt_cell_add, tgt_grid->dims, tgt_grid->reg2d_corner_lon, tgt_grid->reg2d_corner_lat, tgt_cell_bound_box);
restrict_boundbox(src_grid_bound_box, tgt_cell_bound_box);
- if ( 0 && cdoVerbose )
- printf("bound_box %ld lon: %g %g lat: %g %g\n",
- tgt_cell_add, RAD2DEG*tgt_cell_bound_box[2],RAD2DEG*tgt_cell_bound_box[3],RAD2DEG*tgt_cell_bound_box[0],RAD2DEG*tgt_cell_bound_box[1] );
+
num_srch_cells = get_srch_cells_reg2d(src_grid->dims, src_grid->reg2d_corner_lat, src_grid->reg2d_corner_lon,
tgt_cell_bound_box, srch_add);
@@ -751,9 +857,7 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
double tgt_cell_bound_box[4];
boundbox_from_corners1(tgt_cell_add, tgt_num_cell_corners, tgt_grid->cell_corner_lon, tgt_grid->cell_corner_lat, tgt_cell_bound_box);
restrict_boundbox(src_grid_bound_box, tgt_cell_bound_box);
- if ( 0 && cdoVerbose )
- printf("bound_box %ld lon: %g %g lat: %g %g\n",
- tgt_cell_add, RAD2DEG*tgt_cell_bound_box[2],RAD2DEG*tgt_cell_bound_box[3],RAD2DEG*tgt_cell_bound_box[0],RAD2DEG*tgt_cell_bound_box[1] );
+
num_srch_cells = get_srch_cells_reg2d(src_grid->dims, src_grid->reg2d_corner_lat, src_grid->reg2d_corner_lon,
tgt_cell_bound_box, srch_add);
@@ -766,9 +870,14 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
restr_t tgt_cell_bound_box_r[4];
boundbox_from_corners1r(tgt_cell_add, tgt_num_cell_corners, tgt_grid->cell_corner_lon, tgt_grid->cell_corner_lat, tgt_cell_bound_box_r);
+ long nbins = src_grid->num_srch_bins;
num_srch_cells = get_srch_cells(tgt_cell_add, nbins, tgt_grid->bin_addr, src_grid->bin_addr,
tgt_cell_bound_box_r, src_grid->cell_bound_box, src_grid_size, srch_add);
}
+#ifdef STIMER
+ clock_t finish = clock();
+ stimer += ((double)(finish-start))/CLOCKS_PER_SEC;
+#endif
if ( 0 && cdoVerbose ) sum_srch_cells += num_srch_cells;
@@ -777,202 +886,41 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
if ( num_srch_cells == 0 ) continue;
- if ( tgt_remap_grid_type == REMAP_GRID_TYPE_REG2D )
- {
- long nx = tgt_grid->dims[0];
- long iy = tgt_cell_add/nx;
- long ix = tgt_cell_add - iy*nx;
-
- tgt_grid_cell->coordinates_x[0] = tgt_grid->reg2d_corner_lon[ix ];
- tgt_grid_cell->coordinates_y[0] = tgt_grid->reg2d_corner_lat[iy ];
- tgt_grid_cell->coordinates_x[1] = tgt_grid->reg2d_corner_lon[ix+1];
- tgt_grid_cell->coordinates_y[1] = tgt_grid->reg2d_corner_lat[iy ];
- tgt_grid_cell->coordinates_x[2] = tgt_grid->reg2d_corner_lon[ix+1];
- tgt_grid_cell->coordinates_y[2] = tgt_grid->reg2d_corner_lat[iy+1];
- tgt_grid_cell->coordinates_x[3] = tgt_grid->reg2d_corner_lon[ix ];
- tgt_grid_cell->coordinates_y[3] = tgt_grid->reg2d_corner_lat[iy+1];
- }
- else
- {
- for ( int ic = 0; ic < tgt_num_cell_corners; ++ic )
- {
- tgt_grid_cell->coordinates_x[ic] = tgt_grid->cell_corner_lon[tgt_cell_add*tgt_num_cell_corners+ic];
- tgt_grid_cell->coordinates_y[ic] = tgt_grid->cell_corner_lat[tgt_cell_add*tgt_num_cell_corners+ic];
- }
- }
-
- for ( int ic = 0; ic < tgt_num_cell_corners; ++ic )
- LLtoXYZ(tgt_grid_cell->coordinates_x[ic], tgt_grid_cell->coordinates_y[ic], tgt_grid_cell->coordinates_xyz+ic*3);
-
- //printf("target: %ld\n", tgt_cell_add);
- if ( lyac )
- if ( tgt_cell_add == 174752 )
- {
- for ( int n = 0; n < tgt_num_cell_corners; ++n )
- {
- printf(" TargetCell.coordinates_x[%d] = %g*rad;\n", n, tgt_grid_cell->coordinates_x[n]/DEG2RAD);
- printf(" TargetCell.coordinates_y[%d] = %g*rad;\n", n, tgt_grid_cell->coordinates_y[n]/DEG2RAD);
- }
- /*
- printf("> -Z1\n");
- for ( int n = 0; n < tgt_num_cell_corners; ++n )
- printf(" %g %g\n", tgt_grid_cell->coordinates_x[n]/DEG2RAD, tgt_grid_cell->coordinates_y[n]/DEG2RAD);
- printf(" %g %g\n", tgt_grid_cell->coordinates_x[0]/DEG2RAD, tgt_grid_cell->coordinates_y[0]/DEG2RAD);
- */
- }
-
- /* Create search arrays */
-
- max_srch_cells = max_srch_cells2[ompthID];
- partial_areas = partial_areas2[ompthID];
- partial_weights = partial_weights2[ompthID];
- overlap_buffer = overlap_buffer2[ompthID];
- src_grid_cells = src_grid_cells2[ompthID];
+ set_yac_coordinates(tgt_remap_grid_type, tgt_cell_add, tgt_num_cell_corners, tgt_grid, tgt_grid_cell);
- if ( num_srch_cells > max_srch_cells )
- {
- partial_areas = (double*) realloc(partial_areas, num_srch_cells*sizeof(double));
- partial_weights = (double*) realloc(partial_weights, num_srch_cells*sizeof(double));
- overlap_buffer = (struct grid_cell*) realloc(overlap_buffer, num_srch_cells*sizeof(struct grid_cell));
- src_grid_cells = (struct grid_cell*) realloc(src_grid_cells, num_srch_cells*sizeof(struct grid_cell));
+ /* Create search arrays */
- for ( n = max_srch_cells; n < num_srch_cells; ++n )
- {
- overlap_buffer[n].array_size = 0;
- overlap_buffer[n].num_corners = 0;
- overlap_buffer[n].edge_type = NULL;
- overlap_buffer[n].coordinates_x = NULL;
- overlap_buffer[n].coordinates_y = NULL;
- overlap_buffer[n].coordinates_xyz = NULL;
- }
+ search_realloc(num_srch_cells, &search[ompthID]);
- for ( n = max_srch_cells; n < num_srch_cells; ++n )
- {
- src_grid_cells[n].array_size = srch_corners;
- src_grid_cells[n].num_corners = srch_corners;
- src_grid_cells[n].edge_type = src_edge_type;
- src_grid_cells[n].coordinates_x = (double*) malloc(srch_corners*sizeof(double));
- src_grid_cells[n].coordinates_y = (double*) malloc(srch_corners*sizeof(double));
- src_grid_cells[n].coordinates_xyz = (double*) malloc(3*srch_corners*sizeof(double));
- }
-
- max_srch_cells = num_srch_cells;
-
- max_srch_cells2[ompthID] = max_srch_cells;
- partial_areas2[ompthID] = partial_areas;
- partial_weights2[ompthID] = partial_weights;
- overlap_buffer2[ompthID] = overlap_buffer;
- src_grid_cells2[ompthID] = src_grid_cells;
- }
+ double *partial_areas = search[ompthID].partial_areas;
+ double *partial_weights = search[ompthID].partial_weights;
+ struct grid_cell *src_grid_cells = search[ompthID].src_grid_cells;
- // printf(" int ii = 0;\n");
for ( n = 0; n < num_srch_cells; ++n )
{
- long srch_corners_new = srch_corners;
-
+ int srch_corners_new = srch_corners;
src_cell_add = srch_add[n];
-
- if ( src_remap_grid_type == REMAP_GRID_TYPE_REG2D )
- {
- int ix, iy;
-
- iy = src_cell_add/nx;
- ix = src_cell_add - iy*nx;
-
- src_grid_cells[n].coordinates_x[0] = src_grid->reg2d_corner_lon[ix ];
- src_grid_cells[n].coordinates_y[0] = src_grid->reg2d_corner_lat[iy ];
- src_grid_cells[n].coordinates_x[1] = src_grid->reg2d_corner_lon[ix+1];
- src_grid_cells[n].coordinates_y[1] = src_grid->reg2d_corner_lat[iy ];
- src_grid_cells[n].coordinates_x[2] = src_grid->reg2d_corner_lon[ix+1];
- src_grid_cells[n].coordinates_y[2] = src_grid->reg2d_corner_lat[iy+1];
- src_grid_cells[n].coordinates_x[3] = src_grid->reg2d_corner_lon[ix ];
- src_grid_cells[n].coordinates_y[3] = src_grid->reg2d_corner_lat[iy+1];
- /*
- printf("source1: %ld %ld", num_srch_cells, n);
- for ( k = 0; k < srch_corners; ++k )
- printf(" %g %g", src_grid_cells[n].coordinates_x[k]/DEG2RAD, src_grid_cells[n].coordinates_y[k]/DEG2RAD);
- printf("\n");
- */
- }
- else
- {
- ioffset = src_cell_add*srch_corners;
- /*
- for ( k = srch_corners-1; k > 0; --k )
- {
- if ( IS_NOT_EQUAL(src_grid->cell_corner_lon[ioffset+k], src_grid->cell_corner_lon[ioffset+k-1]) ||
- IS_NOT_EQUAL(src_grid->cell_corner_lat[ioffset+k], src_grid->cell_corner_lat[ioffset+k-1]) )
- break;
- }
- if ( k != srch_corners-1 ) printf("%ld %ld %ld %ld\n", tgt_cell_add, n, srch_corners, k+1);
-
- if ( k != srch_corners-1 )
- {
- srch_corners_new = k+1;
- src_grid_cells[n].num_corners = srch_corners_new;
- }
- */
- for ( k = 0; k < srch_corners_new; ++k )
- {
- src_grid_cells[n].coordinates_x[k] = src_grid->cell_corner_lon[ioffset+k];
- src_grid_cells[n].coordinates_y[k] = src_grid->cell_corner_lat[ioffset+k];
- }
- /*
- for ( k = 0; k < srch_corners_new; ++k )
- {
- printf(" SourceCell[ii].coordinates_x[%ld] = %g*rad;\n", k, src_grid_cells[n].coordinates_x[k]/DEG2RAD);
- printf(" SourceCell[ii].coordinates_y[%ld] = %g*rad;\n", k, src_grid_cells[n].coordinates_y[k]/DEG2RAD);
- }
- */
- /*
- printf("source2: %ld %ld", num_srch_cells, n);
- for ( k = 0; k < srch_corners_new; ++k )
- printf(" %g %g", src_grid_cells[n].coordinates_x[k]/DEG2RAD, src_grid_cells[n].coordinates_y[k]/DEG2RAD);
- printf("\n");
- */
- }
-
- for ( int ic = 0; ic < srch_corners_new; ++ic )
- LLtoXYZ(src_grid_cells[n].coordinates_x[ic], src_grid_cells[n].coordinates_y[ic], src_grid_cells[n].coordinates_xyz+ic*3);
-
- if ( lyac )
- if ( tgt_cell_add == 174752 )
- {
- // printf("n %d\n", (int)n);
- for ( k = 0; k < srch_corners_new; ++k )
- {
- printf(" SourceCell[ii].coordinates_x[%ld] = %g*rad;\n", k, src_grid_cells[n].coordinates_x[k]/DEG2RAD);
- printf(" SourceCell[ii].coordinates_y[%ld] = %g*rad;\n", k, src_grid_cells[n].coordinates_y[k]/DEG2RAD);
- }
- printf(" ii++;\n");
- /*
- printf("> -Z1\n");
- for ( k = 0; k < srch_corners_new; ++k )
- printf(" %g %g\n", src_grid_cells[n].coordinates_x[k]/DEG2RAD, src_grid_cells[n].coordinates_y[k]/DEG2RAD);
- printf(" %g %g\n", src_grid_cells[n].coordinates_x[0]/DEG2RAD, src_grid_cells[n].coordinates_y[0]/DEG2RAD);
- */
- }
+ set_yac_coordinates(src_remap_grid_type, src_cell_add, srch_corners_new, src_grid, &src_grid_cells[n]);
}
if ( tgt_num_cell_corners < 4 || target_cell_type == LON_LAT_CELL )
{
- cdo_compute_overlap_areas(num_srch_cells, overlap_buffer, src_grid_cells, *tgt_grid_cell, partial_areas);
+ cdo_compute_overlap_areas(num_srch_cells, &search[ompthID], *tgt_grid_cell);
}
else
{
double cell_center_lon = tgt_grid->cell_center_lon[tgt_cell_add];
double cell_center_lat = tgt_grid->cell_center_lat[tgt_cell_add];
- cdo_compute_concave_overlap_areas(num_srch_cells, overlap_buffer, src_grid_cells, *tgt_grid_cell, cell_center_lon, cell_center_lat, partial_areas);
+ cdo_compute_concave_overlap_areas(num_srch_cells, &search[ompthID], *tgt_grid_cell, cell_center_lon, cell_center_lat);
}
- tgt_area = gridcell_area(*tgt_grid_cell);
- // tgt_area = cell_area(tgt_grid_cell);
+ double tgt_area = gridcell_area(*tgt_grid_cell);
+ // double tgt_area = cell_area(tgt_grid_cell);
for ( num_weights = 0, n = 0; n < num_srch_cells; ++n )
{
if ( partial_areas[n] > 0 )
{
- //printf(">>>> %d %d %g %g\n", (int)tgt_cell_add, srch_add[n], tgt_area, partial_areas[n]);
partial_areas[num_weights] = partial_areas[n];
srch_add[num_weights] = srch_add[n];
num_weights++;
@@ -989,16 +937,12 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
for ( n = 0; n < num_weights; ++n )
partial_weights[n] *= tgt_area;
- //#endif
num_weights_old = num_weights;
- for ( num_weights = 0, n = 0; n < num_weights_old; ++n )
+ num_weights = 0;
+ for ( n = 0; n < num_weights_old; ++n )
{
src_cell_add = srch_add[n];
-
- if ( 0 && cdoVerbose )
- printf("tgt_cell_add %ld, src_cell_add %ld, partial_weights[n] %g, tgt_area %g\n", tgt_cell_add, src_cell_add, partial_weights[n], tgt_area);
-
if ( partial_weights[n] <= 0. ) src_cell_add = -1;
if ( src_cell_add != -1 )
{
@@ -1011,7 +955,6 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
for ( n = 0; n < num_weights; ++n )
{
partial_weight = partial_weights[n];
-
src_cell_add = srch_add[n];
#if defined(_OPENMP)
@@ -1056,101 +999,61 @@ void remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapva
tgt_grid->cell_area[tgt_cell_add] = tgt_area;
// printf("area %d %g %g\n", tgt_cell_add, tgt_grid->cell_area[tgt_cell_add], tgt_area);
- }
+ }
+
+#ifdef STIMER
+printf("stime = %gs\n", stimer);
+#endif
if ( 0 && cdoVerbose )
{
- printf("sum_srch_cells : %d\n", sum_srch_cells);
- printf("sum_srch_cells2: %d\n", sum_srch_cells2);
+ printf("sum_srch_cells : %ld\n", sum_srch_cells);
+ printf("sum_srch_cells2: %ld\n", sum_srch_cells2);
}
/* Finished with all cells: deallocate search arrays */
- long n;
- for ( i = 0; i < ompNumThreads; ++i )
+ for ( int ompthID = 0; ompthID < ompNumThreads; ++ompthID )
{
- for ( n = 0; n < max_srch_cells2[i]; n++ )
- {
- if ( overlap_buffer2[i][n].array_size > 0 )
- {
- Free(overlap_buffer2[i][n].coordinates_x);
- Free(overlap_buffer2[i][n].coordinates_y);
- if ( overlap_buffer2[i][n].coordinates_xyz ) Free(overlap_buffer2[i][n].coordinates_xyz);
- if ( overlap_buffer2[i][n].edge_type ) Free(overlap_buffer2[i][n].edge_type);
- }
-
- Free(src_grid_cells2[i][n].coordinates_x);
- Free(src_grid_cells2[i][n].coordinates_y);
- Free(src_grid_cells2[i][n].coordinates_xyz);
- }
- Free(src_grid_cells2[i]);
- Free(overlap_buffer2[i]);
+ search_free(&search[ompthID]);
- Free(partial_areas2[i]);
- Free(partial_weights2[i]);
+ Free(tgt_grid_cell2[ompthID]->coordinates_x);
+ Free(tgt_grid_cell2[ompthID]->coordinates_y);
+ Free(tgt_grid_cell2[ompthID]->coordinates_xyz);
+ Free(tgt_grid_cell2[ompthID]);
- Free(tgt_grid_cell2[i]->coordinates_x);
- Free(tgt_grid_cell2[i]->coordinates_y);
- Free(tgt_grid_cell2[i]->coordinates_xyz);
- Free(tgt_grid_cell2[i]);
-
- Free(srch_add2[i]);
+ Free(srch_add2[ompthID]);
}
-
+
weightlinks2remaplinks(1, tgt_grid_size, weightlinks, rv);
if ( weightlinks ) Free(weightlinks);
- /* Normalize using destination area if requested */
- normalize_weights(tgt_grid, rv);
-
- long num_links = rv->num_links;
+ // Normalize weights using destination area if requested
+ remapNormalizeWeights(tgt_grid, rv);
- if ( cdoVerbose )
- cdoPrint("Total number of links = %ld", rv->num_links);
+ if ( cdoVerbose ) cdoPrint("Total number of links = %ld", rv->num_links);
- for ( n = 0; n < src_grid_size; ++n )
+ for ( int n = 0; n < src_grid_size; ++n )
if ( IS_NOT_EQUAL(src_grid->cell_area[n], 0) ) src_grid->cell_frac[n] /= src_grid->cell_area[n];
- for ( n = 0; n < tgt_grid_size; ++n )
+ for ( int n = 0; n < tgt_grid_size; ++n )
if ( IS_NOT_EQUAL(tgt_grid->cell_area[n], 0) ) tgt_grid->cell_frac[n] /= tgt_grid->cell_area[n];
- /* Perform some error checking on final weights */
-
+ // Perform some error checking on final weights
if ( lcheck )
{
- for ( n = 0; n < src_grid_size; ++n )
- {
- if ( src_grid->cell_area[n] < -.01 )
- cdoPrint("Source grid area error: %d %g", n, src_grid->cell_area[n]);
- }
+ remapCheckArea(src_grid_size, src_grid->cell_area, "Source");
+ remapCheckArea(tgt_grid_size, tgt_grid->cell_area, "Target");
- for ( n = 0; n < tgt_grid_size; ++n )
- {
- if ( tgt_grid->cell_area[n] < -.01 )
- cdoPrint("Target grid area error: %d %g", n, tgt_grid->cell_area[n]);
- }
-
- for ( n = 0; n < num_links; ++n )
- {
- src_cell_add = rv->src_cell_add[n];
- long tgt_cell_add = rv->tgt_cell_add[n];
-
- if ( rv->wts[n*num_wts] < -0.01 )
- cdoPrint("Map weight < 0! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
- src_cell_add, tgt_cell_add, n, rv->wts[n*num_wts]);
-
- if ( rv->norm_opt != NORM_OPT_NONE && rv->wts[n*num_wts] > 1.01 )
- cdoPrint("Map weight > 1! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
- src_cell_add, tgt_cell_add, n, rv->wts[n*num_wts]);
- }
- } // lcheck
+ remapCheckWeights(rv->num_links, rv->num_wts, rv->norm_opt, rv->src_cell_add, rv->tgt_cell_add, rv->wts);
+ }
if ( cdoTimer ) timer_stop(timer_remap_con);
-} /* remap_weights_conserv */
+} // remap_weights_conserv
void remap_conserv(remapgrid_t *src_grid, remapgrid_t *tgt_grid, const double* restrict src_array, double* restrict tgt_array, double missval)
{
-} /* remap_conserv */
+} // remap_conserv
diff --git a/src/remap_conserv_scrip.c b/src/remap_conserv_scrip.c
index 7dee2ea..9ecfa3f 100644
--- a/src/remap_conserv_scrip.c
+++ b/src/remap_conserv_scrip.c
@@ -1895,11 +1895,11 @@ void scrip_remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
if ( lcheck )
{
+ remapCheckArea(src_grid_size, src_grid->cell_area, "Source");
+ remapCheckArea(tgt_grid_size, tgt_grid->cell_area, "Target");
+
for ( n = 0; n < src_grid_size; ++n )
{
- if ( src_grid->cell_area[n] < -.01 )
- cdoPrint("Source grid area error: %d %g", n, src_grid->cell_area[n]);
-
if ( src_centroid_lat[n] < -PIH-.01 || src_centroid_lat[n] > PIH+.01 )
cdoPrint("Source grid centroid lat error: %d %g", n, src_centroid_lat[n]);
@@ -1909,8 +1909,6 @@ void scrip_remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
for ( n = 0; n < tgt_grid_size; ++n )
{
- if ( tgt_grid->cell_area[n] < -.01 )
- cdoPrint("Target grid area error: %d %g", n, tgt_grid->cell_area[n]);
if ( tgt_centroid_lat[n] < -PIH-.01 || tgt_centroid_lat[n] > PIH+.01 )
cdoPrint("Target grid centroid lat error: %d %g", n, tgt_centroid_lat[n]);
@@ -1918,19 +1916,7 @@ void scrip_remap_conserv_weights(remapgrid_t *src_grid, remapgrid_t *tgt_grid, r
tgt_centroid_lon[n] = 0;
}
- for ( n = 0; n < num_links; ++n )
- {
- src_cell_add = rv->src_cell_add[n];
- tgt_cell_add = rv->tgt_cell_add[n];
-
- if ( rv->wts[3*n] < -0.01 )
- cdoPrint("Map weight < 0! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
- src_cell_add, tgt_cell_add, n, rv->wts[3*n]);
-
- if ( rv->norm_opt != NORM_OPT_NONE && rv->wts[3*n] > 1.01 )
- cdoPrint("Map weight > 1! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
- src_cell_add, tgt_cell_add, n, rv->wts[3*n]);
- }
+ remapCheckWeights(num_links, 3, rv->norm_opt, rv->src_cell_add, rv->tgt_cell_add, rv->wts);
for ( n = 0; n < num_links; ++n )
{
diff --git a/src/remap_distwgt.c b/src/remap_distwgt.c
index e5b0f9c..4bfbcf6 100644
--- a/src/remap_distwgt.c
+++ b/src/remap_distwgt.c
@@ -377,6 +377,7 @@ void remap_distwgt_weights(unsigned num_neighbors, remapgrid_t *src_grid, remapg
unsigned tgt_grid_size = tgt_grid->size;
unsigned nx = src_grid->dims[0];
unsigned ny = src_grid->dims[1];
+ unsigned lcyclic = src_grid->is_cyclic;
weightlinks_t *weightlinks = (weightlinks_t *) Malloc(tgt_grid_size*sizeof(weightlinks_t));
weightlinks[0].addweights = (addweight_t *) Malloc(num_neighbors*tgt_grid_size*sizeof(addweight_t));
@@ -394,7 +395,7 @@ void remap_distwgt_weights(unsigned num_neighbors, remapgrid_t *src_grid, remapg
struct gridsearch *gs = NULL;
if ( remap_grid_type == REMAP_GRID_TYPE_REG2D )
- gs = gridsearch_create_reg2d(nx, ny, src_grid->reg2d_center_lon, src_grid->reg2d_center_lat);
+ gs = gridsearch_create_reg2d(lcyclic, nx, ny, src_grid->reg2d_center_lon, src_grid->reg2d_center_lat);
else if ( num_neighbors == 1 )
gs = gridsearch_create_nn(src_grid_size, src_grid->cell_center_lon, src_grid->cell_center_lat);
else
@@ -484,6 +485,7 @@ void remap_distwgt(unsigned num_neighbors, remapgrid_t *src_grid, remapgrid_t *t
unsigned tgt_grid_size = tgt_grid->size;
unsigned nx = src_grid->dims[0];
unsigned ny = src_grid->dims[1];
+ unsigned lcyclic = src_grid->is_cyclic;
int nbr_mask[num_neighbors]; // mask at nearest neighbors
int nbr_add[num_neighbors]; // source address at nearest neighbors
@@ -496,7 +498,7 @@ void remap_distwgt(unsigned num_neighbors, remapgrid_t *src_grid, remapgrid_t *t
struct gridsearch *gs = NULL;
if ( src_remap_grid_type == REMAP_GRID_TYPE_REG2D )
- gs = gridsearch_create_reg2d(nx, ny, src_grid->reg2d_center_lon, src_grid->reg2d_center_lat);
+ gs = gridsearch_create_reg2d(lcyclic, nx, ny, src_grid->reg2d_center_lon, src_grid->reg2d_center_lat);
else if ( num_neighbors == 1 )
gs = gridsearch_create_nn(src_grid_size, src_grid->cell_center_lon, src_grid->cell_center_lat);
else
diff --git a/src/remap_scrip_io.c b/src/remap_scrip_io.c
index 951b05d..372576f 100644
--- a/src/remap_scrip_io.c
+++ b/src/remap_scrip_io.c
@@ -23,10 +23,7 @@ void remapgrid_alloc(int map_type, remapgrid_t *grid);
static
void nce(int istat)
{
- /*
- This routine provides a simple interface to netCDF error message routine.
- */
-
+ // This routine provides a simple interface to NetCDF error message routine.
if ( istat != NC_NOERR ) cdoAbort(nc_strerror(istat));
}
#endif
@@ -35,20 +32,17 @@ void nce(int istat)
void write_remap_scrip(const char *interp_file, int map_type, int submap_type, int num_neighbors,
int remap_order, remapgrid_t src_grid, remapgrid_t tgt_grid, remapvars_t rv)
{
- /*
- Writes remap data to a netCDF file using SCRIP conventions
- */
+ // Writes remap data to a NetCDF file using SCRIP conventions
/*
Input variables:
interp_file ! filename for remap data
*/
-
#if defined(HAVE_LIBNETCDF)
- /* Local variables */
+ // Local variables
- int nc_file_id; /* id for netCDF file */
+ int nc_file_id; /* id for NetCDF file */
int nc_srcgrdsize_id; /* id for source grid size */
int nc_dstgrdsize_id; /* id for destination grid size */
int nc_srcgrdcorn_id = 0; /* id for number of source grid corners */
@@ -77,7 +71,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
int nc_dstadd_id; /* id for map destination address */
int nc_rmpmatrix_id; /* id for remapping matrix */
- int nc_dims2_id[2]; /* netCDF ids for 2d array dims */
+ int nc_dims2_id[2]; /* NetCDF ids for 2d array dims */
const char *map_name = "SCRIP remapping with CDO";
char normalize_opt[64] = "unknown";
@@ -87,7 +81,6 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
char tgt_grid_name[64] = "dest grid";
const char *src_grid_units = "radians";
const char *tgt_grid_units = "radians";
- long i;
int lgridarea = FALSE;
int writemode = NC_CLOBBER;
@@ -146,9 +139,10 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
break;
}
+ /*
if ( rv.num_links == 0 )
cdoAbort("Number of remap links is 0, no remap weights found!");
-
+ */
{
size_t nele1 = 4*8 + 4;
size_t nele2 = 4*8 + 4;
@@ -161,7 +155,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
if ( cdoVerbose )
cdoPrint("Filesize for remap weights: ~%lu", (unsigned long) filesize);
- if ( filesize > 0x7FFFFC00 ) /* 2**31 - 1024 (<2GB) */
+ if ( filesize > 0x7FFFFC00 ) // 2**31 - 1024 (<2GB)
{
#if defined(NC_64BIT_OFFSET)
writemode = NC_CLOBBER | NC_64BIT_OFFSET;
@@ -171,34 +165,34 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
}
}
- /* Create netCDF file for mapping and define some global attributes */
+ // Create NetCDF file for mapping and define some global attributes
nce(nc_create(interp_file, writemode, &nc_file_id));
- /* Map name */
+ // Map name
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "title", strlen(map_name), map_name));
- /* Normalization option */
+ // Normalization option
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "normalization", strlen(normalize_opt), normalize_opt));
- /* Map method */
+ // Map method
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "map_method", strlen(map_method), map_method));
- /* Remap order */
+ // Remap order
if ( map_type == MAP_TYPE_CONSERV && submap_type == SUBMAP_TYPE_NONE )
nce(nc_put_att_int(nc_file_id, NC_GLOBAL, "remap_order", NC_INT, 1L, &remap_order));
- /* File convention */
+ // File convention
strcpy(tmp_string, "SCRIP");
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "conventions", strlen(tmp_string), tmp_string));
- /* Source and destination grid names */
+ // Source and destination grid names
gridName(gridInqType(src_grid.gridID), src_grid_name);
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "source_grid", strlen(src_grid_name), src_grid_name));
gridName(gridInqType(tgt_grid.gridID), tgt_grid_name);
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "dest_grid", strlen(tgt_grid_name), tgt_grid_name));
- /* History */
+ // History
time_t date_and_time_in_sec = time(NULL);
if ( date_and_time_in_sec != -1 )
{
@@ -212,41 +206,41 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
if ( CDO_Version_Info )
nce(nc_put_att_text(nc_file_id, NC_GLOBAL, "CDO", (int)strlen(cdoComment())+1, cdoComment()));
- /* Prepare netCDF dimension info */
+ // Prepare NetCDF dimension info
- /* Define grid size dimensions */
+ // Define grid size dimensions
nce(nc_def_dim(nc_file_id, "src_grid_size", src_grid.size, &nc_srcgrdsize_id));
nce(nc_def_dim(nc_file_id, "dst_grid_size", tgt_grid.size, &nc_dstgrdsize_id));
- /* Define grid corner dimension */
+ // Define grid corner dimension
if ( src_grid.lneed_cell_corners )
nce(nc_def_dim(nc_file_id, "src_grid_corners", src_grid.num_cell_corners, &nc_srcgrdcorn_id));
if ( tgt_grid.lneed_cell_corners )
nce(nc_def_dim(nc_file_id, "dst_grid_corners", tgt_grid.num_cell_corners, &nc_dstgrdcorn_id));
- /* Define grid rank dimension */
+ // Define grid rank dimension
nce(nc_def_dim(nc_file_id, "src_grid_rank", src_grid.rank, &nc_srcgrdrank_id));
nce(nc_def_dim(nc_file_id, "dst_grid_rank", tgt_grid.rank, &nc_dstgrdrank_id));
- /* Define map size dimensions */
+ // Define map size dimensions
nce(nc_def_dim(nc_file_id, "num_links", rv.num_links, &nc_numlinks_id));
nce(nc_def_dim(nc_file_id, "num_wgts", rv.num_wts, &nc_numwgts_id));
- /* Define grid dimensions */
+ // Define grid dimensions
nce(nc_def_var(nc_file_id, "src_grid_dims", NC_INT, 1, &nc_srcgrdrank_id, &nc_srcgrddims_id));
nce(nc_def_var(nc_file_id, "dst_grid_dims", NC_INT, 1, &nc_dstgrdrank_id, &nc_dstgrddims_id));
- /* Define all arrays for netCDF descriptors */
+ // Define all arrays for NetCDF descriptors
- /* Define grid center latitude array */
+ // Define grid center latitude array
nce(nc_def_var(nc_file_id, "src_grid_center_lat", NC_DOUBLE, 1, &nc_srcgrdsize_id, &nc_srcgrdcntrlat_id));
nce(nc_def_var(nc_file_id, "dst_grid_center_lat", NC_DOUBLE, 1, &nc_dstgrdsize_id, &nc_dstgrdcntrlat_id));
- /* Define grid center longitude array */
+ // Define grid center longitude array
nce(nc_def_var(nc_file_id, "src_grid_center_lon", NC_DOUBLE, 1, &nc_srcgrdsize_id, &nc_srcgrdcntrlon_id));
nce(nc_def_var(nc_file_id, "dst_grid_center_lon", NC_DOUBLE, 1, &nc_dstgrdsize_id, &nc_dstgrdcntrlon_id));
- /* Define grid corner lat/lon arrays */
+ // Define grid corner lat/lon arrays
nc_dims2_id[0] = nc_srcgrdsize_id;
nc_dims2_id[1] = nc_srcgrdcorn_id;
@@ -266,7 +260,8 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_def_var(nc_file_id, "dst_grid_corner_lon", NC_DOUBLE, 2, nc_dims2_id, &nc_dstgrdcrnrlon_id));
}
- /* Define units for all coordinate arrays */
+ // Define units for all coordinate arrays
+
nce(nc_put_att_text(nc_file_id, nc_srcgrdcntrlat_id, "units", strlen(src_grid_units), src_grid_units));
nce(nc_put_att_text(nc_file_id, nc_dstgrdcntrlat_id, "units", strlen(tgt_grid_units), tgt_grid_units));
nce(nc_put_att_text(nc_file_id, nc_srcgrdcntrlon_id, "units", strlen(src_grid_units), src_grid_units));
@@ -282,7 +277,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_put_att_text(nc_file_id, nc_dstgrdcrnrlon_id, "units", strlen(tgt_grid_units), tgt_grid_units));
}
- /* Define grid mask */
+ // Define grid mask
nce(nc_def_var(nc_file_id, "src_grid_imask", NC_INT, 1, &nc_srcgrdsize_id, &nc_srcgrdimask_id));
nce(nc_put_att_text(nc_file_id, nc_srcgrdimask_id, "units", 8, "unitless"));
@@ -290,7 +285,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_def_var(nc_file_id, "dst_grid_imask", NC_INT, 1, &nc_dstgrdsize_id, &nc_dstgrdimask_id));
nce(nc_put_att_text(nc_file_id, nc_dstgrdimask_id, "units", 8, "unitless"));
- /* Define grid area arrays */
+ // Define grid area arrays
if ( lgridarea )
{
@@ -301,7 +296,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_put_att_text(nc_file_id, nc_dstgrdarea_id, "units", 14, "square radians"));
}
- /* Define grid fraction arrays */
+ // Define grid fraction arrays
nce(nc_def_var(nc_file_id, "src_grid_frac", NC_DOUBLE, 1, &nc_srcgrdsize_id, &nc_srcgrdfrac_id));
nce(nc_put_att_text(nc_file_id, nc_srcgrdfrac_id, "units", 8, "unitless"));
@@ -309,7 +304,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_def_var(nc_file_id, "dst_grid_frac", NC_DOUBLE, 1, &nc_dstgrdsize_id, &nc_dstgrdfrac_id));
nce(nc_put_att_text(nc_file_id, nc_dstgrdfrac_id, "units", 8, "unitless"));
- /* Define mapping arrays */
+ // Define mapping arrays
nce(nc_def_var(nc_file_id, "src_address", NC_INT, 1, &nc_numlinks_id, &nc_srcadd_id));
nce(nc_def_var(nc_file_id, "dst_address", NC_INT, 1, &nc_numlinks_id, &nc_dstadd_id));
@@ -319,12 +314,12 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_def_var(nc_file_id, "remap_matrix", NC_DOUBLE, 2, nc_dims2_id, &nc_rmpmatrix_id));
- /* End definition stage */
+ // End definition stage
nce(nc_enddef(nc_file_id));
- /* Write mapping data */
+ // Write mapping data
nce(nc_put_var_int(nc_file_id, nc_srcgrddims_id, src_grid.dims));
nce(nc_put_var_int(nc_file_id, nc_dstgrddims_id, tgt_grid.dims));
@@ -365,7 +360,7 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_put_var_double(nc_file_id, nc_dstgrdfrac_id, tgt_grid.cell_frac));
- for ( i = 0; i < rv.num_links; i++ )
+ for ( long i = 0; i < rv.num_links; i++ )
{
rv.src_cell_add[i]++;
rv.tgt_cell_add[i]++;
@@ -379,19 +374,17 @@ void write_remap_scrip(const char *interp_file, int map_type, int submap_type, i
nce(nc_close(nc_file_id));
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
-} /* write_remap_scrip */
+} // write_remap_scrip
/*****************************************************************************/
void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *map_type, int *submap_type, int *num_neighbors,
int *remap_order, remapgrid_t *src_grid, remapgrid_t *tgt_grid, remapvars_t *rv)
{
- /*
- The routine reads a netCDF file to extract remapping info in SCRIP format
- */
+ // The routine reads a NetCDF file to extract remapping info in SCRIP format
/*
Input variables
@@ -399,11 +392,11 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
*/
#if defined(HAVE_LIBNETCDF)
- /* Local variables */
+ // Local variables
int lgridarea = FALSE;
int status;
- int nc_file_id; /* id for netCDF file */
+ int nc_file_id; /* id for NetCDF file */
int nc_srcgrdsize_id; /* id for source grid size */
int nc_dstgrdsize_id; /* id for destination grid size */
int nc_srcgrdcorn_id; /* id for number of source grid corners */
@@ -432,8 +425,6 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
int nc_dstadd_id; /* id for map destination address */
int nc_rmpmatrix_id; /* id for remapping matrix */
- long i; /* dummy index */
-
char map_name[1024];
char map_method[64]; /* character string for map_type */
char normalize_opt[64]; /* character string for normalization option */
@@ -446,13 +437,12 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
int gridID1_gme_c = -1;
+ // Open file and read some global information
- /* Open file and read some global information */
-
- /* nce(nc_open(interp_file, NC_NOWRITE, &nc_file_id)); */
+ // nce(nc_open(interp_file, NC_NOWRITE, &nc_file_id));
nc_file_id = cdf_openread(interp_file);
- /* Map name */
+ // Map name
nce(nc_get_att_text(nc_file_id, NC_GLOBAL, "title", map_name));
nce(nc_inq_attlen(nc_file_id, NC_GLOBAL, "title", &attlen));
@@ -464,8 +454,7 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
cdoPrint("From file: %s", interp_file);
}
- /* Normalization option */
-
+ // Normalization option
nce(nc_get_att_text(nc_file_id, NC_GLOBAL, "normalization", normalize_opt));
nce(nc_inq_attlen(nc_file_id, NC_GLOBAL, "normalization", &attlen));
normalize_opt[attlen] = 0;
@@ -487,8 +476,7 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
if ( cdoVerbose )
cdoPrint("normalize_opt = %s", normalize_opt);
- /* Map method */
-
+ // Map method
nce(nc_get_att_text (nc_file_id, NC_GLOBAL, "map_method", map_method));
nce(nc_inq_attlen(nc_file_id, NC_GLOBAL, "map_method", &attlen));
map_method[attlen] = 0;
@@ -537,8 +525,7 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
*map_type = rv->map_type;
- /* File convention */
-
+ // File convention
nce(nc_get_att_text (nc_file_id, NC_GLOBAL, "conventions", convention));
nce(nc_inq_attlen(nc_file_id, NC_GLOBAL, "conventions", &attlen));
convention[attlen] = 0;
@@ -552,9 +539,9 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
cdoAbort("Unknown file convention!");
}
- /* Read some additional global attributes */
+ // Read some additional global attributes
- /* Source and destination grid names */
+ // Source and destination grid names
nce(nc_get_att_text (nc_file_id, NC_GLOBAL, "source_grid", src_grid_name));
nce(nc_inq_attlen(nc_file_id, NC_GLOBAL, "source_grid", &attlen));
@@ -567,11 +554,11 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
if ( cdoVerbose )
cdoPrint("Remapping between: %s and %s", src_grid_name, tgt_grid_name);
- /* Initialize remapgrid structure */
+ // Initialize remapgrid structure
remapgrid_init(src_grid);
remapgrid_init(tgt_grid);
- /* Read dimension information */
+ // Read dimension information
nce(nc_inq_dimid(nc_file_id, "src_grid_size", &nc_srcgrdsize_id));
nce(nc_inq_dimlen(nc_file_id, nc_srcgrdsize_id, &dimlen));
@@ -616,10 +603,10 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
nce(nc_inq_dimid(nc_file_id, "num_links", &nc_numlinks_id));
nce(nc_inq_dimlen(nc_file_id, nc_numlinks_id, &dimlen));
rv->num_links = dimlen;
-
+ /*
if ( rv->num_links == 0 )
cdoAbort("Number of remap links is 0, no remap weights found!");
-
+ */
nce(nc_inq_dimid(nc_file_id, "num_wgts", &nc_numwgts_id));
nce(nc_inq_dimlen(nc_file_id, nc_numwgts_id, &dimlen));
rv->num_wts = dimlen;
@@ -645,14 +632,20 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
rv->resize_increment = (int) (0.1 * MAX(src_grid->size, tgt_grid->size));
- /* Allocate address and weight arrays for mapping 1 */
+ // Allocate address and weight arrays for mapping 1
- rv->src_cell_add = (int*) Malloc(rv->num_links*sizeof(int));
- rv->tgt_cell_add = (int*) Malloc(rv->num_links*sizeof(int));
+ rv->src_cell_add = NULL;
+ rv->tgt_cell_add = NULL;
+ rv->wts = NULL;
+ if ( rv->num_links > 0 )
+ {
+ rv->src_cell_add = (int*) Malloc(rv->num_links*sizeof(int));
+ rv->tgt_cell_add = (int*) Malloc(rv->num_links*sizeof(int));
- rv->wts = (double*) Malloc(rv->num_wts*rv->num_links*sizeof(double));
+ rv->wts = (double*) Malloc(rv->num_wts*rv->num_links*sizeof(double));
+ }
- /* Get variable ids */
+ // Get variable ids
nce(nc_inq_varid(nc_file_id, "src_grid_dims", &nc_srcgrddims_id));
nce(nc_inq_varid(nc_file_id, "src_grid_imask", &nc_srcgrdimask_id));
@@ -688,7 +681,7 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
nce(nc_inq_varid(nc_file_id, "dst_address", &nc_dstadd_id));
nce(nc_inq_varid(nc_file_id, "remap_matrix", &nc_rmpmatrix_id));
- /* Read all variables */
+ // Read all variables
nce(nc_get_var_int(nc_file_id, nc_srcgrddims_id, src_grid->dims));
@@ -754,23 +747,26 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
nce(nc_get_var_double(nc_file_id, nc_dstgrdfrac_id, tgt_grid->cell_frac));
- nce(nc_get_var_int(nc_file_id, nc_srcadd_id, rv->src_cell_add));
- nce(nc_get_var_int(nc_file_id, nc_dstadd_id, rv->tgt_cell_add));
-
- for ( i = 0; i < rv->num_links; i++ )
+ if ( rv->num_links > 0 )
{
- rv->src_cell_add[i]--;
- rv->tgt_cell_add[i]--;
- }
+ nce(nc_get_var_int(nc_file_id, nc_srcadd_id, rv->src_cell_add));
+ nce(nc_get_var_int(nc_file_id, nc_dstadd_id, rv->tgt_cell_add));
+
+ for ( long i = 0; i < rv->num_links; i++ )
+ {
+ rv->src_cell_add[i]--;
+ rv->tgt_cell_add[i]--;
+ }
- nce(nc_get_var_double(nc_file_id, nc_rmpmatrix_id, rv->wts));
+ nce(nc_get_var_double(nc_file_id, nc_rmpmatrix_id, rv->wts));
+ }
- /* Close input file */
+ // Close input file
nce(nc_close(nc_file_id));
#else
- cdoAbort("netCDF support not compiled in!");
+ cdoAbort("NetCDF support not compiled in!");
#endif
rv->links.option = FALSE;
@@ -780,4 +776,4 @@ void read_remap_scrip(const char *interp_file, int gridID1, int gridID2, int *ma
rv->links.src_add = NULL;
rv->links.dst_add = NULL;
rv->links.w_index = NULL;
-} /* read_remap_scrip */
+} // read_remap_scrip
diff --git a/src/remaplib.c b/src/remaplib.c
index dfb8321..1c45eb2 100644
--- a/src/remaplib.c
+++ b/src/remaplib.c
@@ -1852,3 +1852,28 @@ void reorder_links(remapvars_t *rv)
printf("loop %ld nlinks %ld\n", j+1, nlinks);
}
}
+
+
+void remapCheckArea(int grid_size, double *restrict cell_area, const char *name)
+{
+ for ( int n = 0; n < grid_size; ++n )
+ {
+ if ( cell_area[n] < -.01 )
+ cdoPrint("%s grid area error: %d %g", name, n, cell_area[n]);
+ }
+}
+
+
+void remapCheckWeights(long num_links, int num_wts, int norm_opt, int *src_cell_add, int *tgt_cell_add, double *wts)
+{
+ for ( long n = 0; n < num_links; ++n )
+ {
+ if ( wts[n*num_wts] < -0.01 )
+ cdoPrint("Map weight < 0! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
+ src_cell_add[n], tgt_cell_add[n], n, wts[n*num_wts]);
+
+ if ( norm_opt != NORM_OPT_NONE && wts[n*num_wts] > 1.01 )
+ cdoPrint("Map weight > 1! grid1idx=%d grid2idx=%d nlink=%d wts=%g",
+ src_cell_add[n], tgt_cell_add[n], n, wts[n*num_wts]);
+ }
+}
diff --git a/src/results_template_parser.c b/src/results_template_parser.c
index c8872f0..c68ba70 100644
--- a/src/results_template_parser.c
+++ b/src/results_template_parser.c
@@ -1,52 +1,62 @@
+#if defined(HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "cdo_int.h"
#include "template_parser.h"
#include "magics_template_parser.h"
#include "results_template_parser.h"
-#define DBG_MSG 0
+#if defined(HAVE_LIBXML2)
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
-/* extern int GetMagicsParameterInfo( const char *user_name, char **magics_name, char **magics_type ); */
+#define DBG_MSG 0
-extern int GetMagicsParameterInfo( char *user_name, xmlChar *param_value );
+/* extern int GetMagicsParameterInfo( const char *user_name, char **magics_name, char **magics_type ); */
-extern xmlNode *results_node;
+extern int GetMagicsParameterInfo( const char *user_name, char *param_value );
/* Recursive function that sets the results parameters from the XML structure */
-int results_template_parser( xmlNode * a_node, const char *varname )
-
+int results_template_parser( void * node, const char *varname )
{
+#if defined(HAVE_LIBXML2)
+ xmlNode *a_node = (xmlNode*) node;
xmlNode *cur_node = NULL;
xmlAttrPtr attr = NULL;
- xmlChar *param_name,*param_value,*value;
- char *param_type;
+ xmlChar *param_value;
- if( a_node == NULL )
- return 1;
+ if ( a_node == NULL )
+ return 1;
- if( !strcmp( a_node->name, "results" ) )
+ if ( !strcmp( (const char*)a_node->name, "results" ) )
{
- value = xmlGetProp( a_node, "version" );
+ const char *value = (const char*) xmlGetProp( a_node, (const xmlChar *)"version" );
- if( value )
+ if ( value )
{
- if( DBG_MSG )
- printf( "Version %s \n", value );
+ if ( DBG_MSG )
+ printf( "Version %s \n", value );
- if( atof( value ) > 3.0f )
- {
- return 1;
- }
+ if ( atof( value ) > 3.0f )
+ {
+ return 1;
+ }
}
}
for ( cur_node = a_node->children; cur_node; cur_node = cur_node->next )
{
- param_name = NULL;
- param_type = NULL;
+#if 0
+ xmlChar *param_name = NULL;
+ char *param_type = NULL;
+#endif
param_value = NULL;
if ( cur_node->type == XML_ELEMENT_NODE )
@@ -73,7 +83,7 @@ int results_template_parser( xmlNode * a_node, const char *varname )
printf( "Finding varname = %s result_name = %s\n", varname, xmlGetProp( cur_node,"name") );
#endif
- if ( strcmp( varname, xmlGetProp( cur_node,"name" ) ) == 0 )
+ if ( strcmp( varname, (const char*)xmlGetProp( cur_node,(xmlChar *)"name" ) ) == 0 )
{
#if 0
printf( "Found varname = %s result_name = %s\n", varname, xmlGetProp( cur_node,"name") );
@@ -87,7 +97,7 @@ int results_template_parser( xmlNode * a_node, const char *varname )
param_value = xmlNodeGetContent( attr->children );
/* if( !GetMagicsParameterInfo( attr->name, &magics_param_name, ¶m_type ) ) */
- if( !GetMagicsParameterInfo( (char *) attr->name, param_value ) )
+ if( !GetMagicsParameterInfo( (const char *) attr->name, (char *) param_value ) )
{
#if 0
@@ -117,5 +127,11 @@ int results_template_parser( xmlNode * a_node, const char *varname )
}
}
}
- return 0;
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
+
+ return 0;
}
diff --git a/src/results_template_parser.h b/src/results_template_parser.h
index 09eeb6a..2d73a0e 100644
--- a/src/results_template_parser.h
+++ b/src/results_template_parser.h
@@ -1,13 +1,6 @@
#ifndef RESULTS_TEMPLATE_PARSER_HH
#define RESULTS_TEMPLATE_PARSER_HH
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
-
-#include<libxml/parser.h>
-#include<libxml/tree.h>
-
- int results_template_parser( xmlNode * a_node, const char *varname );
+int results_template_parser( void *node, const char *varname );
#endif
diff --git a/src/table.c b/src/table.c
index f506f96..0b92d76 100644
--- a/src/table.c
+++ b/src/table.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/template_parser.c b/src/template_parser.c
index f6b4617..cab207c 100644
--- a/src/template_parser.c
+++ b/src/template_parser.c
@@ -1,134 +1,165 @@
+#if defined(HAVE_CONFIG_H)
+# include "config.h"
+#endif
+
+#include "cdo_int.h"
#include "template_parser.h"
#include "magics_template_parser.h"
#include "results_template_parser.h"
-#define DBG_MSG 0
-
+#if defined(HAVE_LIBXML2)
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+xmlNode *root_node;
+xmlDoc *param_doc;
+#endif
-extern xmlNode *root_node, *magics_node, *results_node;
-extern xmlDoc *param_doc;
-extern int magics_template_parser();
-extern int results_template_parser();
+#define DBG_MSG 0
+void *magics_node, *results_node;
+// not used
+static
int template_parser( char *Filename, const char *varname )
-
{
- xmlDoc *doc = NULL;
- xmlNode *root_element = NULL;
+#if defined(HAVE_LIBXML2)
+ xmlDoc *doc = NULL;
+ xmlNode *root_element = NULL;
+
+ doc = xmlReadFile( Filename, NULL, 0 );
+ if ( doc == NULL )
+ {
+ printf( "Error: Could not parse the file \"%s\"\n", Filename );
+ return (1);
+ }
+ else
+ {
+ /*
+ Get the name of the root element node
+ If "magics" , call "magics" parser
+ If "results", call "results" parser
+ */
- doc = xmlReadFile( Filename, NULL, 0 );
- if ( doc == NULL )
+ root_element = xmlDocGetRootElement( doc );
+
+ if( !strcmp( (const char*)root_element->name, "magics" ) )
{
- printf( "Error: Could not parse the file \"%s\"\n", Filename );
- return (1);
+ if ( magics_template_parser( root_element ) == 1 )
+ {
+ printf( "Un-Supported version of Magics++! \n" );
+ return (2);
+ }
}
- else
+ else if( !strcmp( (const char*)root_element->name, "results" ) )
{
- /*
- Get the name of the root element node
- If "magics" , call "magics" parser
- If "results", call "results" parser
- */
-
- root_element = xmlDocGetRootElement( doc );
-
- if( !strcmp( root_element->name, "magics" ) )
- {
- if ( magics_template_parser( root_element ) == 1 )
- {
- printf( "Un-Supported version of Magics++! \n" );
- return (2);
- }
- }
- else if( !strcmp( root_element->name, "results" ) )
- {
- results_template_parser( root_element, varname );
- /* Needs some error handling */
- }
-
- /*** free the document ***/
- xmlFreeDoc( doc );
+ results_template_parser( root_element, varname );
+ /* Needs some error handling */
}
- /*** Free the global variables that may
- * have been allocated by the parser.
- ***/
-
- xmlCleanupParser();
+ /*** free the document ***/
+ xmlFreeDoc( doc );
+ }
+
+ /*** Free the global variables that may
+ * have been allocated by the parser.
+ ***/
+
+ xmlCleanupParser();
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
- return 0;
+ return 0;
}
int init_XMLtemplate_parser( char *Filename )
-
{
- param_doc = xmlReadFile( Filename, NULL, 0 );
- if ( param_doc == NULL )
- {
- printf( "Error: Could not parse the file \"%s\"\n", Filename );
- return (1);
- }
- else
- {
- fprintf( stderr, "XML file %s being parsed \n", Filename );
- root_node = xmlDocGetRootElement( param_doc );
- }
- return 0;
-}
+#if defined(HAVE_LIBXML2)
+ param_doc = xmlReadFile( Filename, NULL, 0 );
+ if ( param_doc == NULL )
+ {
+ printf( "Error: Could not parse the file \"%s\"\n", Filename );
+ return (1);
+ }
+ else
+ {
+ fprintf( stderr, "XML file %s being parsed \n", Filename );
+ root_node = xmlDocGetRootElement( param_doc );
+ }
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
+ return 0;
+}
-int updatemagics_and_results_nodes( )
+int updatemagics_and_results_nodes(void)
{
- xmlNode *cur_node = NULL;
+#if defined(HAVE_LIBXML2)
+ xmlNode *cur_node = NULL;
- if( root_node == NULL )
+ if( root_node == NULL )
{
- printf( "Invalid Root Node\n" );
- return 0;
+ printf( "Invalid Root Node\n" );
+ return 0;
}
- for ( cur_node = root_node->children; cur_node; cur_node = cur_node->next )
+ for ( cur_node = root_node->children; cur_node; cur_node = cur_node->next )
{
- if ( cur_node->type == XML_ELEMENT_NODE )
+ if ( cur_node->type == XML_ELEMENT_NODE )
{
-
-#if 0
- fprintf( stdout, "Node Name: %s \n", cur_node->name );
+#if DBG_MSG
+ fprintf( stdout, "Node Name: %s \n", cur_node->name );
#endif
- if( !strcmp( cur_node->name, "magics" ) )
+ if( !strcmp( (const char*)cur_node->name, "magics" ) )
{
- magics_node = cur_node;
-#if 0
- fprintf( stdout, "Node Name: %s \n", cur_node->name );
+ magics_node = (void*) cur_node;
+#if DBG_MSG
+ fprintf( stdout, "Node Name: %s \n", cur_node->name );
#endif
}
- if( !strcmp( cur_node->name, "results" ) )
+ if( !strcmp( (const char*)cur_node->name, "results" ) )
{
- results_node = cur_node;
-#if 0
- fprintf( stdout, "Node Name: %s \n", cur_node->name );
+ results_node = (void*) cur_node;
+#if DBG_MSG
+ fprintf( stdout, "Node Name: %s \n", cur_node->name );
#endif
}
}
}
- return 0;
-}
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
+ return 0;
+}
-int quit_XMLtemplate_parser( )
+int quit_XMLtemplate_parser(void)
{
- xmlFreeDoc( param_doc );
- xmlCleanupParser( );
- if( param_doc == NULL )
- printf( "Cleaned XML parser\n" );
-#if 0
- fprintf( stdout, "Cleaned XML parser\n" );
+#if defined(HAVE_LIBXML2)
+ xmlFreeDoc( param_doc );
+ xmlCleanupParser( );
+ if( param_doc == NULL )
+ printf( "Cleaned XML parser\n" );
+#if DBG_MSG
+ fprintf( stdout, "Cleaned XML parser\n" );
#endif
- return 0;
+#else
+
+ cdoAbort("XML2 support not compiled in!");
+
+#endif
+
+ return 0;
}
diff --git a/src/template_parser.h b/src/template_parser.h
index 42b4dba..88b2dd3 100644
--- a/src/template_parser.h
+++ b/src/template_parser.h
@@ -1,22 +1,8 @@
#ifndef TEMPLATE_PARSER_HH
#define TEMPLATE_PARSER_HH
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
-
-#if defined(HAVE_LIBXML2)
-#include<libxml/parser.h>
-#include<libxml/tree.h>
-
-
-int template_parser( char *Filename, const char *varname );
int init_XMLtemplate_parser( char *Filename );
-int updatemagics_and_results_nodes( );
-int quit_XMLtemplate_parser( );
-
-
-#endif
+int updatemagics_and_results_nodes(void);
+int quit_XMLtemplate_parser(void);
#endif
diff --git a/src/timebase.h b/src/timebase.h
index 716bb60..2f750df 100644
--- a/src/timebase.h
+++ b/src/timebase.h
@@ -3,6 +3,10 @@
#include <inttypes.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* date format: YYYYMMDD */
/* time format: hhmmss */
@@ -22,4 +26,18 @@ double julday_sub(int julday1, int secofday1, int julday2, int secofday2, int *d
void encode_juldaysec(int calendar, int year, int month, int day, int hour, int minute, int second, int *julday, int *secofday);
void decode_juldaysec(int calendar, int julday, int secofday, int *year, int *month, int *day, int *hour, int *minute, int *second);
+#if defined (__cplusplus)
+}
+#endif
+
#endif /* _TIMEBASE_H */
+
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/src/timer.c b/src/timer.c
index 2d82828..f1d32bd 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/src/util.c b/src/util.c
index 4339f61..d07e3e4 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -85,6 +85,9 @@ int CDO_CMOR_Mode = FALSE;
int cdoDiag = FALSE;
+int CDO_Memtype = MEMTYPE_DOUBLE;
+int CDO_Parallel_Read = FALSE;
+
int CDO_Reduce_Dim = FALSE;
int CDO_Append_History = TRUE;
int CDO_Reset_History = FALSE;
@@ -516,27 +519,30 @@ int fileExists(const char *restrict filename)
int userFileOverwrite(const char *restrict filename)
{
- int status = 0, len;
- char line[1024], *pline;
+ int status = 0;
- fprintf(stderr, "File %s already exists, overwrite? (yes/no): ", filename);
- readline(stdin, line, 1024);
- pline = line;
- while ( isspace((int) *pline) ) pline++;
- len = strlen(pline);
- if ( len == 3 )
+ if ( stdin_is_tty && stderr_is_tty )
{
- if ( pline[0] == 'y' && pline[1] == 'e' && pline[2] == 's' )
- status = 1;
- else if ( pline[0] == 'Y' && pline[1] == 'E' && pline[2] == 'S' )
- status = 1;
- }
- else if ( len == 1 )
- {
- if ( pline[0] == 'y' ) status = 1;
+ fprintf(stderr, "File %s already exists, overwrite? (yes/no): ", filename);
+ char line[1024];
+ readline(stdin, line, 1024);
+ char *pline = line;
+ while ( isspace((int) *pline) ) pline++;
+ int len = (int) strlen(pline);
+ if ( len == 3 )
+ {
+ if ( pline[0] == 'y' && pline[1] == 'e' && pline[2] == 's' )
+ status = 1;
+ else if ( pline[0] == 'Y' && pline[1] == 'E' && pline[2] == 'S' )
+ status = 1;
+ }
+ else if ( len == 1 )
+ {
+ if ( pline[0] == 'y' || pline[0] == 'Y' ) status = 1;
+ }
}
- return (status);
+ return status;
}
diff --git a/src/util.h b/src/util.h
index 33444c8..e3cbddc 100644
--- a/src/util.h
+++ b/src/util.h
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
@@ -45,6 +45,8 @@
extern char *Progname;
extern char *cdoGridSearchDir;
extern int CDO_Reduce_Dim;
+extern int CDO_Memtype;
+extern int CDO_Parallel_Read;
extern int CDO_Append_History;
extern int CDO_Reset_History;
extern int timer_read, timer_write; // refactor: both pstream.c and CDIread.c CDIwrite.c defined in cdo.c
@@ -198,7 +200,6 @@ void cdoGenFileSuffix(char *filesuffix, size_t maxlen, int filetype, int vlistID
void writeNCgrid(const char *gridfile, int gridID, int *imask);
void defineZaxis(const char *zaxisarg);
-void cdiDefTableID(int tableID);
int gridFromName(const char *gridname);
int zaxisFromName(const char *zaxisname);
diff --git a/src/zaxis.c b/src/zaxis.c
index 68e1b3b..8478317 100644
--- a/src/zaxis.c
+++ b/src/zaxis.c
@@ -2,7 +2,7 @@
This file is part of CDO. CDO is a collection of Operators to
manipulate and analyse Climate model Data.
- Copyright (C) 2003-2015 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+ Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
See COPYING file for copying and redistribution conditions.
This program is free software; you can redistribute it and/or modify
diff --git a/test/Copy_netcdf.test.in b/test/Collgrid.test.in
similarity index 60%
copy from test/Copy_netcdf.test.in
copy to test/Collgrid.test.in
index 98b4525..06c6470 100644
--- a/test/Copy_netcdf.test.in
+++ b/test/Collgrid.test.in
@@ -1,5 +1,5 @@
#! @SHELL@
-echo 1..1 # Number of tests to be executed.
+echo 1..9 # Number of tests to be executed.
#
test -n "$CDO" || CDO=cdo
test -n "$DATAPATH" || DATAPATH=./data
@@ -7,21 +7,32 @@ test -n "$DATAPATH" || DATAPATH=./data
CDOOUT=cout
CDOERR=cerr
#
+GRIDTYPES="regular generic curvilinear"
+DISTS="4,3 12,1 1,6"
+#
NTEST=1
#
-for OPERATOR in copy; do
- for FILE in testfile01c.nc; do
+for GRIDTYPE in $GRIDTYPES; do
+ for DIST in $DISTS; do
RSTAT=0
+ GT=$(echo $GRIDTYPE | cut -c1)
+ FILE=data${GT}.nc
IFILE=$DATAPATH/${FILE}
OFILE=${OPERATOR}_${FILE}
- CDOTEST="$OPERATOR $FILE"
- CDOCOMMAND="$CDO $OPERATOR $IFILE $OFILE"
+ CDOTEST="$GRIDTYPE $DIST"
if [ "@ENABLE_NETCDF@" = yes ] ; then
+ nx=$(echo $DIST | sed 's/,.*//')
+ NX=""
+ if [ $FILE != datar.nc ] ; then NX=",$nx" ; fi
+ CDOCOMMAND="$CDO collgrid$NX xxx* $OFILE"
echo "Running test: $NTEST"
echo "$CDOCOMMAND"
+ $CDO distgrid,$DIST $IFILE xxx
+ test $? -eq 0 || let RSTAT+=1
+
$CDOCOMMAND
test $? -eq 0 || let RSTAT+=1
@@ -29,6 +40,8 @@ for OPERATOR in copy; do
test $? -eq 0 || let RSTAT+=1
test -s $CDOOUT && let RSTAT+=1
cat $CDOOUT $CDOERR
+
+ rm -f $OFILE xxx*
test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
@@ -37,7 +50,6 @@ for OPERATOR in copy; do
fi
let NTEST+=1
- rm -f $OFILE
done
done
#
diff --git a/test/Copy_netcdf.test.in b/test/Copy_netcdf.test.in
index 98b4525..5bdc4be 100644
--- a/test/Copy_netcdf.test.in
+++ b/test/Copy_netcdf.test.in
@@ -1,5 +1,5 @@
#! @SHELL@
-echo 1..1 # Number of tests to be executed.
+echo 1..5 # Number of tests to be executed.
#
test -n "$CDO" || CDO=cdo
test -n "$DATAPATH" || DATAPATH=./data
@@ -7,10 +7,12 @@ test -n "$DATAPATH" || DATAPATH=./data
CDOOUT=cout
CDOERR=cerr
#
+FILES="datar.nc datag.nc datac.nc datau.nc testfile01c.nc"
+#
NTEST=1
#
for OPERATOR in copy; do
- for FILE in testfile01c.nc; do
+ for FILE in $FILES; do
RSTAT=0
IFILE=$DATAPATH/${FILE}
OFILE=${OPERATOR}_${FILE}
diff --git a/test/Expr.test.in b/test/Expr.test.in
new file mode 100644
index 0000000..db9accd
--- /dev/null
+++ b/test/Expr.test.in
@@ -0,0 +1,64 @@
+#! @SHELL@
+echo 1..2 # Number of tests to be executed.
+#
+test -n "$CDO" || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+CDOOUT=cout
+CDOERR=cerr
+FORMAT="-f srv -b 32"
+#
+IFILE=$DATAPATH/pl_data
+NTEST=1
+#
+FINSTR=finstr
+#
+function testfunc()
+{
+ RSTAT=0
+
+ CDOTEST="instruction set $NTEST"
+ echo "Running test: $NTEST - $CDOTEST"
+
+ for EXPR in expr aexpr; do
+ RFILE=$DATAPATH/${EXPR}${NTEST}_ref
+ OFILE=${EXPR}${NTEST}_res
+
+ for FILE in "" "f"; do
+
+ if [ "$FILE" = "f" ] ; then
+ echo $INSTR > $FINSTR
+ CDOCOMMAND="$CDO $FORMAT $EXPR${FILE},$FINSTR $IFILE $OFILE"
+ else
+ CDOCOMMAND="$CDO $FORMAT $EXPR,$INSTR $IFILE $OFILE"
+ fi
+
+ echo "$CDOCOMMAND"
+
+ $CDOCOMMAND
+ test $? -eq 0 || let RSTAT+=1
+
+ $CDO diff $RFILE $OFILE > $CDOOUT 2> $CDOERR
+ test $? -eq 0 || let RSTAT+=1
+ test -s $CDOOUT && let RSTAT+=1
+ cat $CDOOUT $CDOERR
+
+ rm -f $OFILE $FINSTR
+ done
+ done
+
+ test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+ test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+
+ let NTEST+=1
+}
+#
+INSTR="_clev=clev(var130);pottemp=var130*((100000/_clev)^0.287);"
+testfunc
+#
+INSTR="var1=(var129>0)?(var130-273.15):var152;"
+testfunc
+#
+rm -f $CDOOUT $CDOERR
+#
+exit 0
diff --git a/test/Makefile.am b/test/Makefile.am
index 2c543bc..50e2f7c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,9 +11,10 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/config/tap-driver.sh
# tests which should pass
-TESTS = File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
+TESTS = threads.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
- Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Gradsdes.test wildcard.test
+ Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Expr.test \
+ Gradsdes.test Collgrid.test
# tests which should fail
XFAIL_TESTS =
diff --git a/test/Makefile.in b/test/Makefile.in
index 3d6bc8d..3de2043 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -90,8 +90,9 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/Fldstat.test.in $(srcdir)/Fldpctl.test.in \
$(srcdir)/Ensstat.test.in $(srcdir)/Enspctl.test.in \
$(srcdir)/Afterburner.test.in $(srcdir)/Detrend.test.in \
- $(srcdir)/Arith.test.in $(srcdir)/Gradsdes.test.in \
- $(srcdir)/wildcard.test.in README
+ $(srcdir)/Arith.test.in $(srcdir)/Expr.test.in \
+ $(srcdir)/Gradsdes.test.in $(srcdir)/Collgrid.test.in \
+ $(srcdir)/threads.test.in $(srcdir)/wildcard.test.in README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/acx_options.m4 \
$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
@@ -107,7 +108,8 @@ CONFIG_CLEAN_FILES = File.test Read_grib.test Read_netcdf.test \
Remap.test Select.test Spectral.test Timstat.test Vertint.test \
Ymonstat.test Fldstat.test Fldpctl.test Ensstat.test \
Enspctl.test Afterburner.test Detrend.test Arith.test \
- Gradsdes.test wildcard.test
+ Expr.test Gradsdes.test Collgrid.test threads.test \
+ wildcard.test
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_ at AM_V@)
am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -367,6 +369,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_CDI_LIB = @ENABLE_CDI_LIB@
ENABLE_CGRIBEX = @ENABLE_CGRIBEX@
+ENABLE_CXX = @ENABLE_CXX@
ENABLE_DATA = @ENABLE_DATA@
ENABLE_EXTRA = @ENABLE_EXTRA@
ENABLE_GRIB = @ENABLE_GRIB@
@@ -377,6 +380,7 @@ ENABLE_NC4 = @ENABLE_NC4@
ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
ENABLE_NETCDF = @ENABLE_NETCDF@
ENABLE_SERVICE = @ENABLE_SERVICE@
+ENABLE_THREADS = @ENABLE_THREADS@
EXEEXT = @EXEEXT@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
@@ -516,9 +520,10 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
# tests which should pass
-TESTS = File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
+TESTS = threads.test wildcard.test File.test Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test Detrend.test \
Genweights.test Remap.test Select.test Spectral.test Ymonstat.test Timstat.test Ensstat.test \
- Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Gradsdes.test wildcard.test
+ Enspctl.test Fldstat.test Fldpctl.test Vertint.test Afterburner.test Arith.test Expr.test \
+ Gradsdes.test Collgrid.test
# $(top_srcdir)/test/test_Remap.sh \
@@ -607,8 +612,14 @@ Detrend.test: $(top_builddir)/config.status $(srcdir)/Detrend.test.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
Arith.test: $(top_builddir)/config.status $(srcdir)/Arith.test.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+Expr.test: $(top_builddir)/config.status $(srcdir)/Expr.test.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
Gradsdes.test: $(top_builddir)/config.status $(srcdir)/Gradsdes.test.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+Collgrid.test: $(top_builddir)/config.status $(srcdir)/Collgrid.test.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+threads.test: $(top_builddir)/config.status $(srcdir)/threads.test.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
wildcard.test: $(top_builddir)/config.status $(srcdir)/wildcard.test.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
diff --git a/test/data/Makefile.am b/test/data/Makefile.am
index ed23996..0a32f15 100644
--- a/test/data/Makefile.am
+++ b/test/data/Makefile.am
@@ -1,5 +1,6 @@
INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data pl_data.grb detrend_data \
- grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc
+ grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
+ datar.nc datac.nc datau.nc datag.nc
FILE_REF = file_F32_srv_ref
GRIB_REF = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref
@@ -15,6 +16,8 @@ REMAP_REF = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_
n32_bic_ref n32_bil_ref n32_con_ref n32_ycon_ref n32_laf_ref n32_nn_ref n32_dis_ref
SELECT_REF = select1_ref select2_ref select3_ref select4_ref select5_ref
DETREND_REF = detrend_ref
+EXPR_REF = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
+THREAD_REF = thread1_ref
GRADSDES_REF = pl_data.ctl pl_data.gmp
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(GRADSDES_REF)
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF)
diff --git a/test/data/Makefile.in b/test/data/Makefile.in
index b74aa9d..5ae555f 100644
--- a/test/data/Makefile.in
+++ b/test/data/Makefile.in
@@ -149,6 +149,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_CDI_LIB = @ENABLE_CDI_LIB@
ENABLE_CGRIBEX = @ENABLE_CGRIBEX@
+ENABLE_CXX = @ENABLE_CXX@
ENABLE_DATA = @ENABLE_DATA@
ENABLE_EXTRA = @ENABLE_EXTRA@
ENABLE_GRIB = @ENABLE_GRIB@
@@ -159,6 +160,7 @@ ENABLE_NC4 = @ENABLE_NC4@
ENABLE_NC4HDF5 = @ENABLE_NC4HDF5@
ENABLE_NETCDF = @ENABLE_NETCDF@
ENABLE_SERVICE = @ENABLE_SERVICE@
+ENABLE_THREADS = @ENABLE_THREADS@
EXEEXT = @EXEEXT@
FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
@@ -286,7 +288,8 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
INPUTDATA = ts_mm_5years hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data pl_data.grb detrend_data \
- grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc
+ grib_testfile01.grb grib_testfile02.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
+ datar.nc datac.nc datau.nc datag.nc
FILE_REF = file_F32_srv_ref
GRIB_REF = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref
@@ -303,8 +306,10 @@ REMAP_REF = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_nn_
SELECT_REF = select1_ref select2_ref select3_ref select4_ref select5_ref
DETREND_REF = detrend_ref
+EXPR_REF = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
+THREAD_REF = thread1_ref
GRADSDES_REF = pl_data.ctl pl_data.gmp
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(GRADSDES_REF)
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(YMONSTAT_REF) $(TIMSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF)
all: all-am
.SUFFIXES:
diff --git a/test/data/aexpr1_ref b/test/data/aexpr1_ref
new file mode 100644
index 0000000..dd5af96
Binary files /dev/null and b/test/data/aexpr1_ref differ
diff --git a/test/data/aexpr2_ref b/test/data/aexpr2_ref
new file mode 100644
index 0000000..ae26e64
Binary files /dev/null and b/test/data/aexpr2_ref differ
diff --git a/test/data/datac.nc b/test/data/datac.nc
new file mode 100644
index 0000000..0a330ed
Binary files /dev/null and b/test/data/datac.nc differ
diff --git a/test/data/datag.nc b/test/data/datag.nc
new file mode 100644
index 0000000..75ab4d5
Binary files /dev/null and b/test/data/datag.nc differ
diff --git a/test/data/datar.nc b/test/data/datar.nc
new file mode 100644
index 0000000..d0313db
Binary files /dev/null and b/test/data/datar.nc differ
diff --git a/test/data/datau.nc b/test/data/datau.nc
new file mode 100644
index 0000000..db33c57
Binary files /dev/null and b/test/data/datau.nc differ
diff --git a/test/data/expr1_ref b/test/data/expr1_ref
new file mode 100644
index 0000000..64f3700
Binary files /dev/null and b/test/data/expr1_ref differ
diff --git a/test/data/expr2_ref b/test/data/expr2_ref
new file mode 100644
index 0000000..cf28d14
Binary files /dev/null and b/test/data/expr2_ref differ
diff --git a/test/data/grib_testfile01_sinfo_ref b/test/data/grib_testfile01_sinfo_ref
index fe92662..ab59641 100644
--- a/test/data/grib_testfile01_sinfo_ref
+++ b/test/data/grib_testfile01_sinfo_ref
@@ -1,5 +1,5 @@
File format : GRIB
- -1 : Institut Source Ttype Levels Num Points Num Dtype : Parameter ID
+ -1 : Institut Source Steptype Levels Num Points Num Dtype : Parameter ID
1 : unknown unknown instant 1 1 2592 1 P16 : 1
Grid coordinates :
1 : lonlat : points=2592 (72x36)
diff --git a/test/data/grib_testfile02_sinfo_ref b/test/data/grib_testfile02_sinfo_ref
index cebd3b5..ef42506 100644
--- a/test/data/grib_testfile02_sinfo_ref
+++ b/test/data/grib_testfile02_sinfo_ref
@@ -1,5 +1,5 @@
File format : GRIB
- -1 : Institut Source Ttype Levels Num Points Num Dtype : Parameter ID
+ -1 : Institut Source Steptype Levels Num Points Num Dtype : Parameter ID
1 : unknown unknown instant 1 1 1 1 P0 : 1
Grid coordinates :
1 : lonlat : points=1 (1x1)
diff --git a/test/data/netcdf_testfile01_sinfon_ref b/test/data/netcdf_testfile01_sinfon_ref
index f575024..1b77b6c 100644
--- a/test/data/netcdf_testfile01_sinfon_ref
+++ b/test/data/netcdf_testfile01_sinfon_ref
@@ -1,5 +1,5 @@
- File format : netCDF
- -1 : Institut Source Ttype Levels Num Points Num Dtype : Parameter name
+ File format : NetCDF
+ -1 : Institut Source Steptype Levels Num Points Num Dtype : Parameter name
1 : unknown unknown instant 1 1 2592 1 I16 : tem
Grid coordinates :
1 : lonlat : points=2592 (72x36)
diff --git a/test/data/netcdf_testfile02_sinfon_ref b/test/data/netcdf_testfile02_sinfon_ref
index 5111e1f..3a5fa76 100644
--- a/test/data/netcdf_testfile02_sinfon_ref
+++ b/test/data/netcdf_testfile02_sinfon_ref
@@ -1,5 +1,5 @@
- File format : netCDF
- -1 : Institut Source Ttype Levels Num Points Num Dtype : Parameter name
+ File format : NetCDF
+ -1 : Institut Source Steptype Levels Num Points Num Dtype : Parameter name
1 : unknown unknown instant 1 1 1 1 F32 : for
Grid coordinates :
1 : lonlat : points=1 (1x1)
diff --git a/test/data/thread1_ref b/test/data/thread1_ref
new file mode 100644
index 0000000..4707c1e
Binary files /dev/null and b/test/data/thread1_ref differ
diff --git a/test/threads.test.in b/test/threads.test.in
new file mode 100644
index 0000000..dae35d1
--- /dev/null
+++ b/test/threads.test.in
@@ -0,0 +1,55 @@
+#! @SHELL@
+echo 1..1 # Number of tests to be executed.
+#
+test -n "$CDO" || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+CDOOUT=cout
+CDOERR=cerr
+FORMAT="-f srv -b 32"
+#
+IFILE=$DATAPATH/pl_data
+NTEST=1
+#
+function testfunc()
+{
+ RSTAT=0
+
+ CDOTEST="chaining set $NTEST"
+ echo "Running test: $NTEST - $CDOTEST"
+
+ RFILE=$DATAPATH/thread${NTEST}_ref
+ OFILE=thread${NTEST}_res
+
+ CDOCOMMAND="$CDO $FORMAT $INSTR $IFILE $OFILE"
+
+ echo "$CDOCOMMAND"
+
+ if [ "@ENABLE_THREADS@" = yes ] ; then
+
+ $CDOCOMMAND
+ test $? -eq 0 || let RSTAT+=1
+
+ $CDO diff $RFILE $OFILE > $CDOOUT 2> $CDOERR
+ test $? -eq 0 || let RSTAT+=1
+ test -s $CDOOUT && let RSTAT+=1
+ cat $CDOOUT $CDOERR
+
+ rm -f $OFILE
+
+ test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+ test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+ else
+ test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST # SKIP threads not enabled"
+ fi
+
+ let NTEST+=1
+ rm -f $OFILE
+}
+#
+INSTR="-fldmean -timmean -select,code=129,130,152"
+testfunc
+#
+rm -f $CDOOUT $CDOERR
+#
+exit 0
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cdo.git
More information about the debian-science-commits
mailing list