From 8fc91402c81f74cfa71ea3bb1784151f84d793b0 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 12 Sep 2023 12:48:58 -0600 Subject: [PATCH] Initial release --- data/config/UGridConfig_default | 33 + src/libcode/vx_data2d_ugrid/Makefile.am | 20 + src/libcode/vx_data2d_ugrid/Makefile.in | 679 +++++++++++++ src/libcode/vx_data2d_ugrid/data2d_ugrid.cc | 706 ++++++++++++++ src/libcode/vx_data2d_ugrid/data2d_ugrid.h | 125 +++ src/libcode/vx_data2d_ugrid/ugrid_file.cc | 902 ++++++++++++++++++ src/libcode/vx_data2d_ugrid/ugrid_file.h | 172 ++++ src/libcode/vx_data2d_ugrid/var_info_ugrid.cc | 470 +++++++++ src/libcode/vx_data2d_ugrid/var_info_ugrid.h | 101 ++ src/libcode/vx_grid/unstructured_grid.cc | 388 ++++++++ src/libcode/vx_grid/unstructured_grid.h | 97 ++ src/libcode/vx_grid/unstructured_grid_defs.h | 64 ++ 12 files changed, 3757 insertions(+) create mode 100644 data/config/UGridConfig_default create mode 100644 src/libcode/vx_data2d_ugrid/Makefile.am create mode 100644 src/libcode/vx_data2d_ugrid/Makefile.in create mode 100644 src/libcode/vx_data2d_ugrid/data2d_ugrid.cc create mode 100644 src/libcode/vx_data2d_ugrid/data2d_ugrid.h create mode 100644 src/libcode/vx_data2d_ugrid/ugrid_file.cc create mode 100644 src/libcode/vx_data2d_ugrid/ugrid_file.h create mode 100644 src/libcode/vx_data2d_ugrid/var_info_ugrid.cc create mode 100644 src/libcode/vx_data2d_ugrid/var_info_ugrid.h create mode 100644 src/libcode/vx_grid/unstructured_grid.cc create mode 100644 src/libcode/vx_grid/unstructured_grid.h create mode 100644 src/libcode/vx_grid/unstructured_grid_defs.h diff --git a/data/config/UGridConfig_default b/data/config/UGridConfig_default new file mode 100644 index 0000000000..0fd8b355c7 --- /dev/null +++ b/data/config/UGridConfig_default @@ -0,0 +1,33 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Unstructured Grid configuration file. +// +// For additional information, please see the MET User's Guide. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Default mapping for Metadata. +// +metadata_map = [ + { key = "dim_face"; val = "nCells,nMesh2d_face"; }, + { key = "dim_node"; val = "nVertices,nMesh2d_node"; }, + { key = "dim_edge"; val = "nEdges,nMesh2d_edge"; }, + { key = "dim_time"; val = "Time,time_counter"; }, + { key = "dim_vert"; val = "nVertLevels"; }, + { key = "cell_id"; val = "indexToCellID,"; }, + { key = "lat_face"; val = "latCell,Mesh2d_face_y"; }, + { key = "lon_face"; val = "lonCell,Mesh2d_face_x"; }, + { key = "vert_face"; val = "zCell"; }, + { key = "lat_edge"; val = "latEdge,Mesh2d_edge_y"; }, + { key = "lon_edge"; val = "lonEdge,Mesh2d_edge_x"; }, + { key = "lat_node"; val = "latVertex,Mesh2d_node_y"; }, + { key = "lon_node"; val = "lonVertex,Mesh2d_node_x"; }, + { key = "time"; val = "xtime,time_centered"; } +]; + +//////////////////////////////////////////////////////////////////////////////// + +version = "V12.0.0"; + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d_ugrid/Makefile.am b/src/libcode/vx_data2d_ugrid/Makefile.am new file mode 100644 index 0000000000..98c2814a20 --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/Makefile.am @@ -0,0 +1,20 @@ +## @start 1 +## Makefile.am -- Process this file with automake to produce Makefile.in +## @end 1 + +MAINTAINERCLEANFILES = Makefile.in + +# Include the project definitions + +include ${top_srcdir}/Make-include + +# The library + +noinst_LIBRARIES = libvx_data2d_ugrid.a +libvx_data2d_ugrid_a_SOURCES = \ + ugrid_file.cc ugrid_file.h \ + var_info_ugrid.cc var_info_ugrid.h \ + data2d_ugrid.cc data2d_ugrid.h \ + vx_data2d_ugrid.h +libvx_data2d_ugrid_a_CPPFLAGS = ${MET_CPPFLAGS} + diff --git a/src/libcode/vx_data2d_ugrid/Makefile.in b/src/libcode/vx_data2d_ugrid/Makefile.in new file mode 100644 index 0000000000..4a5123003e --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/Makefile.in @@ -0,0 +1,679 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcode/vx_data2d_ugrid +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libvx_data2d_ugrid_a_AR = $(AR) $(ARFLAGS) +libvx_data2d_ugrid_a_LIBADD = +am_libvx_data2d_ugrid_a_OBJECTS = \ + libvx_data2d_ugrid_a-ugrid_file.$(OBJEXT) \ + libvx_data2d_ugrid_a-var_info_ugrid.$(OBJEXT) \ + libvx_data2d_ugrid_a-data2d_ugrid.$(OBJEXT) +libvx_data2d_ugrid_a_OBJECTS = $(am_libvx_data2d_ugrid_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + ./$(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po \ + ./$(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po \ + ./$(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libvx_data2d_ugrid_a_SOURCES) +DIST_SOURCES = $(libvx_data2d_ugrid_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUFRLIB_NAME = @BUFRLIB_NAME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FC_LIBS = @FC_LIBS@ +FFLAGS = @FFLAGS@ +FLIBS = @FLIBS@ +GREP = @GREP@ +GRIB2CLIB_NAME = @GRIB2CLIB_NAME@ +GRIB2_LIBS = @GRIB2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MET_BUFR = @MET_BUFR@ +MET_BUFRLIB = @MET_BUFRLIB@ +MET_CAIRO = @MET_CAIRO@ +MET_CAIROINC = @MET_CAIROINC@ +MET_CAIROLIB = @MET_CAIROLIB@ +MET_FREETYPE = @MET_FREETYPE@ +MET_FREETYPEINC = @MET_FREETYPEINC@ +MET_FREETYPELIB = @MET_FREETYPELIB@ +MET_GRIB2C = @MET_GRIB2C@ +MET_GRIB2CINC = @MET_GRIB2CINC@ +MET_GRIB2CLIB = @MET_GRIB2CLIB@ +MET_GSL = @MET_GSL@ +MET_GSLINC = @MET_GSLINC@ +MET_GSLLIB = @MET_GSLLIB@ +MET_HDF = @MET_HDF@ +MET_HDF5 = @MET_HDF5@ +MET_HDF5INC = @MET_HDF5INC@ +MET_HDF5LIB = @MET_HDF5LIB@ +MET_HDFEOS = @MET_HDFEOS@ +MET_HDFEOSINC = @MET_HDFEOSINC@ +MET_HDFEOSLIB = @MET_HDFEOSLIB@ +MET_HDFINC = @MET_HDFINC@ +MET_HDFLIB = @MET_HDFLIB@ +MET_NETCDF = @MET_NETCDF@ +MET_NETCDFINC = @MET_NETCDFINC@ +MET_NETCDFLIB = @MET_NETCDFLIB@ +MET_PYTHON_BIN_EXE = @MET_PYTHON_BIN_EXE@ +MET_PYTHON_CC = @MET_PYTHON_CC@ +MET_PYTHON_LD = @MET_PYTHON_LD@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +OPENMP_CFLAGS = @OPENMP_CFLAGS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON_LIBS = @PYTHON_LIBS@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in + +# The library +noinst_LIBRARIES = libvx_data2d_ugrid.a +libvx_data2d_ugrid_a_SOURCES = \ + ugrid_file.cc ugrid_file.h \ + var_info_ugrid.cc var_info_ugrid.h \ + data2d_ugrid.cc data2d_ugrid.h \ + vx_data2d_ugrid.h + +libvx_data2d_ugrid_a_CPPFLAGS = ${MET_CPPFLAGS} -I/d1/personal/hsoh/third_party/install/atlas/include -I/d1/personal/hsoh/third_party/install/eckit/include +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libcode/vx_data2d_ugrid/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/libcode/vx_data2d_ugrid/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libvx_data2d_ugrid.a: $(libvx_data2d_ugrid_a_OBJECTS) $(libvx_data2d_ugrid_a_DEPENDENCIES) $(EXTRA_libvx_data2d_ugrid_a_DEPENDENCIES) + $(AM_V_at)-rm -f libvx_data2d_ugrid.a + $(AM_V_AR)$(libvx_data2d_ugrid_a_AR) libvx_data2d_ugrid.a $(libvx_data2d_ugrid_a_OBJECTS) $(libvx_data2d_ugrid_a_LIBADD) + $(AM_V_at)$(RANLIB) libvx_data2d_ugrid.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +libvx_data2d_ugrid_a-ugrid_file.o: ugrid_file.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-ugrid_file.o -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Tpo -c -o libvx_data2d_ugrid_a-ugrid_file.o `test -f 'ugrid_file.cc' || echo '$(srcdir)/'`ugrid_file.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ugrid_file.cc' object='libvx_data2d_ugrid_a-ugrid_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-ugrid_file.o `test -f 'ugrid_file.cc' || echo '$(srcdir)/'`ugrid_file.cc + +libvx_data2d_ugrid_a-ugrid_file.obj: ugrid_file.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-ugrid_file.obj -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Tpo -c -o libvx_data2d_ugrid_a-ugrid_file.obj `if test -f 'ugrid_file.cc'; then $(CYGPATH_W) 'ugrid_file.cc'; else $(CYGPATH_W) '$(srcdir)/ugrid_file.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ugrid_file.cc' object='libvx_data2d_ugrid_a-ugrid_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-ugrid_file.obj `if test -f 'ugrid_file.cc'; then $(CYGPATH_W) 'ugrid_file.cc'; else $(CYGPATH_W) '$(srcdir)/ugrid_file.cc'; fi` + +libvx_data2d_ugrid_a-var_info_ugrid.o: var_info_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-var_info_ugrid.o -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Tpo -c -o libvx_data2d_ugrid_a-var_info_ugrid.o `test -f 'var_info_ugrid.cc' || echo '$(srcdir)/'`var_info_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='var_info_ugrid.cc' object='libvx_data2d_ugrid_a-var_info_ugrid.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-var_info_ugrid.o `test -f 'var_info_ugrid.cc' || echo '$(srcdir)/'`var_info_ugrid.cc + +libvx_data2d_ugrid_a-var_info_ugrid.obj: var_info_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-var_info_ugrid.obj -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Tpo -c -o libvx_data2d_ugrid_a-var_info_ugrid.obj `if test -f 'var_info_ugrid.cc'; then $(CYGPATH_W) 'var_info_ugrid.cc'; else $(CYGPATH_W) '$(srcdir)/var_info_ugrid.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='var_info_ugrid.cc' object='libvx_data2d_ugrid_a-var_info_ugrid.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-var_info_ugrid.obj `if test -f 'var_info_ugrid.cc'; then $(CYGPATH_W) 'var_info_ugrid.cc'; else $(CYGPATH_W) '$(srcdir)/var_info_ugrid.cc'; fi` + +libvx_data2d_ugrid_a-data2d_ugrid.o: data2d_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-data2d_ugrid.o -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Tpo -c -o libvx_data2d_ugrid_a-data2d_ugrid.o `test -f 'data2d_ugrid.cc' || echo '$(srcdir)/'`data2d_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data2d_ugrid.cc' object='libvx_data2d_ugrid_a-data2d_ugrid.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-data2d_ugrid.o `test -f 'data2d_ugrid.cc' || echo '$(srcdir)/'`data2d_ugrid.cc + +libvx_data2d_ugrid_a-data2d_ugrid.obj: data2d_ugrid.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libvx_data2d_ugrid_a-data2d_ugrid.obj -MD -MP -MF $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Tpo -c -o libvx_data2d_ugrid_a-data2d_ugrid.obj `if test -f 'data2d_ugrid.cc'; then $(CYGPATH_W) 'data2d_ugrid.cc'; else $(CYGPATH_W) '$(srcdir)/data2d_ugrid.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Tpo $(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data2d_ugrid.cc' object='libvx_data2d_ugrid_a-data2d_ugrid.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvx_data2d_ugrid_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libvx_data2d_ugrid_a-data2d_ugrid.obj `if test -f 'data2d_ugrid.cc'; then $(CYGPATH_W) 'data2d_ugrid.cc'; else $(CYGPATH_W) '$(srcdir)/data2d_ugrid.cc'; fi` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-data2d_ugrid.Po + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-ugrid_file.Po + -rm -f ./$(DEPDIR)/libvx_data2d_ugrid_a-var_info_ugrid.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-noinstLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Include the project definitions + +include ${top_srcdir}/Make-include + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcode/vx_data2d_ugrid/data2d_ugrid.cc b/src/libcode/vx_data2d_ugrid/data2d_ugrid.cc new file mode 100644 index 0000000000..3a1582d0e6 --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/data2d_ugrid.cc @@ -0,0 +1,706 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + + +#include +#include +#include +#include + +#include + +#include "data2d_ugrid.h" +#include "vx_math.h" +#include "vx_log.h" + +using namespace std; +using namespace netCDF; + +//////////////////////////////////////////////////////////////////////// + +static const int error_code_no_error = 0; +static const int error_code_no_time_dim = 1; +static const int error_code_missing_time_value = 2; +static const int error_code_missing_time_values = 3; +static const int error_code_missing_time_offsets = 4; +static const int error_code_empty_times = 5; +static const int error_code_bad_increment = 6; +static const int error_code_bad_offset = 7; +static const int error_code_unknown = 999; + +//////////////////////////////////////////////////////////////////////// +// +// Code for class MetUGridDataFile +// +//////////////////////////////////////////////////////////////////////// + +MetUGridDataFile::MetUGridDataFile() { + + ugrid_init_from_scratch(); + +} + +//////////////////////////////////////////////////////////////////////// + +MetUGridDataFile::~MetUGridDataFile() { + + close(); +} + +//////////////////////////////////////////////////////////////////////// + +MetUGridDataFile::MetUGridDataFile(const MetUGridDataFile &) { + + mlog << Error << "\nMetUGridDataFile::MetUGridDataFile(const MetUGridDataFile &) -> " + << "should never be called!\n\n"; + exit(1); +} + +//////////////////////////////////////////////////////////////////////// + +MetUGridDataFile & MetUGridDataFile::operator=(const MetUGridDataFile &) { + + mlog << Error << "\nMetUGridDataFile::operator=(const MetUGridDataFile &) -> " + << "should never be called!\n\n"; + exit(1); +} + +//////////////////////////////////////////////////////////////////////// + +void MetUGridDataFile::ugrid_init_from_scratch() { + + _file = (UGridFile *) nullptr; + _cur_time_index = -1; + + close(); + + return; +} + +//////////////////////////////////////////////////////////////////////// +/* +NcVarInfo *MetUGridDataFile::find_first_data_var() { + NcVarInfo *first_data_var = nullptr; + // Store the name of the first data variable + for (int i = 0; i < _file->Nvars; ++i) { + if (is_nc_unit_time(_file->Var[i].units_att.c_str()) || + is_nc_unit_longitude(_file->Var[i].units_att.c_str()) || + is_nc_unit_latitude(_file->Var[i].units_att.c_str()) || + _file->get_time_var_info() == &_file->Var[i] + ) continue; + + if (strcmp(_file->Var[i].name.c_str(), ugrid_lat_var_name) != 0 && + strcmp(_file->Var[i].name.c_str(), ugrid_lon_var_name) != 0) { + first_data_var = &(_file->Var[i]); + break; + } + } + return first_data_var; +} +*/ +//////////////////////////////////////////////////////////////////////// + +void MetUGridDataFile::close() { + + if(_file) { delete _file; _file = (UGridFile *) nullptr; } + + return; +} + +//////////////////////////////////////////////////////////////////////// + +bool MetUGridDataFile::open(const char * _filename) { + + close(); + + _file = new UGridFile; + + if(!_file->open(_filename)) { + mlog << Error << "\nMetUGridDataFile::open(const char *) -> " + << "unable to open NetCDF file \"" << _filename << "\"\n\n"; + close(); + + return false; + } + + Filename = _filename; + + return true; +} + +//////////////////////////////////////////////////////////////////////// + +bool MetUGridDataFile::open_metadata(const char * _filename) { + const char *method_name = "MetUGridDataFile::open_metadata(const char *) -> "; + + if (! _file) { + mlog << Error << "\n" << method_name + << "UGridFile is not initiated to handle \"" << _filename << "\"\n\n"; + close(); + return false; + } + + if (!_file->open_metadata(_filename)) { + mlog << Error << "\n" << method_name + << "unable to open NetCDF file \"" << _filename << "\"\n\n"; + close(); + return false ; + } + + meta_filename = _filename; + + Raw_Grid = new Grid; + + (*Raw_Grid) = _file->grid; + //Raw_Grid->set(*_file->grid.info().us); + + Dest_Grid = new Grid; + + (*Dest_Grid) = (*Raw_Grid); + //Dest_Grid->set(*_file->grid.info().us); + + return(true); +} + +//////////////////////////////////////////////////////////////////////// + +void MetUGridDataFile::dump(ostream & out, int depth) const { + + if(_file) _file->dump(out, depth); + + return; +} + +//////////////////////////////////////////////////////////////////////// + +bool MetUGridDataFile::data_plane(VarInfo &vinfo, DataPlane &plane) +{ + // Not sure why we do this + + NcVarInfo *data_var = (NcVarInfo *)nullptr; + VarInfoUGrid *vinfo_nc = (VarInfoUGrid *)&vinfo; + static const string method_name + = "MetUGridDataFile::data_plane(VarInfo &, DataPlane &) -> "; + + // Initialize the data plane + + plane.clear(); + + // Check for NA in the requested name + if ( vinfo_nc->req_name() == na_str ) + { + // Store the name of the first data variable +cout << " FIXME MetUGridDataFile::data_plane(VarInfo &vinfo, DataPlane &plane) calling find_first_data_var()\n"; +// data_var = find_first_data_var(); +// if (nullptr != data_var) vinfo_nc->set_req_name(data_var->name.c_str()); + } + + int zdim_slot = bad_data_int; + int time_dim_slot = bad_data_int; + long org_time_offset = bad_data_int; + long org_z_offset = bad_data_int; + NumArray dim_value = vinfo_nc->dim_value(); + LongArray dimension = vinfo_nc->dimension(); + BoolArray is_offset = vinfo_nc->is_offset(); + + data_var = _file->find_var_name(vinfo_nc->req_name().c_str()); +/* + if (nullptr != data_var) { + time_dim_slot = data_var->t_slot; + for (int idx=0; idxValidTime.n(); + long time_threshold_cnt = 10000000; + org_time_offset = dim_offset; + long time_offset = org_time_offset; + if (time_offset == range_flag) time_offset = _cur_time_index; // from data_plane_array() + else if (!is_offset[idx]) { + long time_value = dim_value[idx]; + time_offset = convert_time_to_offset(time_value); + if ((0 > time_offset) || (time_offset >= time_cnt)) { + if (time_value > time_threshold_cnt) // from time string (yyyymmdd_hh) + mlog << Warning << "\n" << method_name << "the requested time " + << unix_to_yyyymmdd_hhmmss(time_value) << " for \"" + << vinfo.req_name() << "\" variable does not exist (" + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[0]) << " and " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[time_cnt-1]) << ").\n\n"; + else + mlog << Warning << "\n" << method_name << "the requested time value " + << time_value << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; + + return false; + } + } + else if ((0 > time_offset) || (time_offset >= time_cnt)) { + time_offset = convert_time_to_offset(time_offset); + } + if ((0 > time_offset) || (time_offset >= time_cnt)) { + mlog << Error << "\n" << method_name << "the requested time offset " + << time_offset << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (time_cnt-1) << ").\n\n"; + return false; + } + dimension[time_dim_slot] = time_offset; + } + else { + long z_cnt = (long)_file->vlevels.n(); + if (z_cnt > 0) { + + zdim_slot = idx; + org_z_offset = dim_offset; + long z_offset = dim_offset; + string z_dim_name; + if (0 <= data_var->z_slot) { + NcDim z_dim = get_nc_dim(data_var->var, data_var->z_slot); + if (IS_VALID_NC(z_dim)) z_dim_name = GET_NC_NAME(z_dim); + } + if (!is_offset[idx]) { + // convert the value to index for slicing + z_offset = convert_value_to_offset(dim_value[idx], z_dim_name); + } + if ((z_offset >= 0) && (z_offset < z_cnt)) + dimension[idx] = long(z_offset); + else { + if (is_offset[idx]) + mlog << Error << "\n" << method_name << "the requested vertical offset " + << dim_offset << " for \"" << vinfo.req_name() << "\" variable " + << "is out of range (between 0 and " << (z_cnt-1) << ").\n\n"; + else + mlog << Error << "\n" << method_name << "the requested vertical value " + << dim_value[idx] << " for \"" << vinfo.req_name() << "\" variable " + << "does not exist (data size = " << z_cnt << ").\n\n"; + return false; + } + } + } + } + } +*/ + + // Read the data + NcVarInfo *info = (NcVarInfo *) 0; + + bool status = _file->getData(vinfo_nc->req_name().c_str(), + dimension, + plane, info); + + if (org_time_offset != bad_data_int && 0 <= time_dim_slot) + dimension[time_dim_slot] = org_time_offset; + if (org_z_offset != bad_data_int && 0 <= zdim_slot) + dimension[zdim_slot] = org_z_offset; + + // Check that the times match those requested + + if (status) + { + // Check that the valid time matches the request + + if (vinfo.valid() > 0 && vinfo.valid() != plane.valid()) + { + // Compute time strings + + ConcatString req_time_str = unix_to_yyyymmdd_hhmmss(vinfo.valid()); + ConcatString data_time_str = unix_to_yyyymmdd_hhmmss(plane.valid()); + + mlog << Warning << "\n" << method_name + << "for \"" << vinfo.req_name() << "\" variable, the valid " + << "time does not match the requested valid time: (" + << data_time_str << " != " << req_time_str << ")\n\n"; + status = false; + } + + // Check that the lead time matches the request + + if (vinfo.lead() > 0 && vinfo.lead() != plane.lead()) + { + // Compute time strings + + ConcatString req_time_str = sec_to_hhmmss(vinfo.lead()); + ConcatString data_time_str = sec_to_hhmmss(plane.lead()); + + mlog << Warning << "\n" << method_name + << "for \"" << vinfo.req_name() << "\" variable, the lead " + << "time does not match the requested lead time: (" + << data_time_str << " != " << req_time_str << ")\n\n"; + status = false; + } + + status = process_data_plane(&vinfo, plane); + + // Set the VarInfo object's name, long_name, level, and units strings + + if (info->name_att.length() > 0) + vinfo.set_name(info->name_att); + else + vinfo.set_name(info->name); + + if (info->long_name_att.length() > 0) + vinfo.set_long_name(info->long_name_att.c_str()); + + if (info->level_att.length() > 0) + vinfo.set_level_name(info->level_att.c_str()); + + if (info->units_att.length() > 0) + vinfo.set_units(info->units_att.c_str()); + } + + return status; +} + +//////////////////////////////////////////////////////////////////////// + +int MetUGridDataFile::data_plane_array(VarInfo &vinfo, + DataPlaneArray &plane_array) { + int n_rec = 0; + DataPlane plane; + bool status = false; + static const string method_name + = "MetUGridDataFile::data_plane_array(VarInfo &, DataPlaneArray &) -> "; + + // Initialize + plane_array.clear(); + + VarInfoUGrid *vinfo_nc = (VarInfoUGrid *)&vinfo; + if ( vinfo_nc->req_name() == na_str ) { + // Store the name of the first data variable +cout << " FIXME MetUGridDataFile::data_plane_array() calling find_first_data_var()\n"; +// NcVarInfo *data_var = find_first_data_var(); +// if (nullptr != data_var) vinfo_nc->set_req_name(data_var->name.c_str()); + } + + LongArray time_offsets = collect_time_offsets(vinfo); + if (0 < time_offsets.n_elements()) { + LevelInfo level = vinfo.level(); + long time_lower = bad_data_int; + long time_upper = bad_data_int; + if (level.type() == LevelType_Time) { + time_lower = level.lower(); + time_upper = level.upper(); + } + + for (int idx=0; idx= debug_level) { + for (int idx=0; idx< time_offsets.n_elements(); idx++ ) { + mlog << Debug(debug_level) << method_name << "time: " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[time_offsets[idx]]) + << " from index " << time_offsets[idx] << "\n"; + } + } + } + + return(n_rec); +} + +//////////////////////////////////////////////////////////////////////// + +LongArray MetUGridDataFile::collect_time_offsets(VarInfo &vinfo) { + int n_rec = 0; + bool status = false; + VarInfoUGrid *vinfo_nc = (VarInfoUGrid *)&vinfo; + static const string method_name + = "MetUGridDataFile::collect_time_offsets(VarInfo &) -> "; + + LongArray time_offsets; + NcVarInfo *info = _file->find_var_name(vinfo_nc->req_name().c_str()); + + // Check for variable not found + if(!info) { + mlog << Warning << "\n" << method_name + << "can't find NetCDF variable \"" << vinfo_nc->req_name() + << "\" in file \"" << Filename << "\".\n\n"; + return(time_offsets); + } + + int time_dim_slot = info->t_slot; + int time_dim_size = _file->ValidTime.n_elements(); + if (0 < time_dim_size && time_dim_slot < 0) { + // The time dimension does not exist at the variable and the time + // variable exists. Stop time slicing and set the time offset to 0. + time_offsets.add(0); + return(time_offsets); + } + + double time_lower = bad_data_double; + double time_upper = bad_data_double; + int error_code = error_code_no_error; + LevelInfo level = vinfo.level(); + LongArray dimension = vinfo_nc->dimension(); + bool is_time_range = (level.type() == LevelType_Time); + bool time_as_value = !level.is_offset(); + + long dim_offset = (time_dim_slot >= 0) ? dimension[time_dim_slot] : -1; + bool include_all_times = (dim_offset == vx_data2d_star); + + int idx; + TimeArray missing_times; + if (include_all_times) { + for (idx=0; idxValidTime[idx] < time_lower) continue; + next_offset = idx; + if (_file->ValidTime[idx] != time_lower) + missing_times.add(time_lower); + else { + mlog << Debug(9) << method_name << " found the lower time " + << unix_to_yyyymmdd_hhmmss(time_lower) << "\n"; + time_offsets.add(idx); + next_offset++; + } + break; + } + + if (0 > next_offset) error_code = error_code_missing_time_values; + else if (0 > time_inc) error_code = error_code_bad_increment; + else if (0 == time_inc) { // no increment configuration + for (idx=next_offset; idxValidTime[idx] > time_upper) break; + time_offsets.add(idx); + mlog << Debug(9) << method_name << " found the time " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[idx]) << "\n"; + } + } + else { + long next_time; + next_time = time_lower + time_inc; + for (idx=next_offset; idxValidTime[idx] > time_upper) break; + else if (_file->ValidTime[idx] < next_time) continue; + else if (_file->ValidTime[idx] == next_time) { + time_offsets.add(idx); + mlog << Debug(9) << method_name << " found the time " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[idx]) << "\n"; + next_time += time_inc; + } + else { // next_time < _file->ValidTime[idx] + while (next_time < _file->ValidTime[idx]) { + missing_times.add(next_time); + next_time += time_inc; + } + if (_file->ValidTime[idx] == next_time) { + time_offsets.add(idx); + mlog << Debug(9) << method_name << " found the time " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[idx]) << "\n"; + next_time += time_inc; + } + } + if (next_time > time_upper) break; + } + } + } + else if (time_lower < time_dim_size) { + int inc_offset = (time_inc <= 0) ? 1 : time_inc; + int max_time_offset = time_upper; + if (max_time_offset == time_dim_size) + missing_times.add(time_dim_size); + else if (max_time_offset > time_dim_size) { + for (idx=time_dim_size; idx<=max_time_offset; idx++) + missing_times.add(idx); + } + for (idx=time_lower; idxValidTime[0]) << " and " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime[time_dim_size-1]) << "\n"; + else { + mlog << Warning << method_name << "Not found time out of " + << time_dim_size << ".\n"; + if (include_all_times) error_code = error_code_empty_times; + else if (is_time_range) { + error_code = time_as_value ? error_code_missing_time_values + : error_code_missing_time_offsets; + } + } + + // Handling error code + if (error_code > error_code_no_error) { + ConcatString log_msg; + log_msg << "variable \"" << vinfo_nc->req_name() << "\" "; + if (error_code == error_code_no_time_dim) { + log_msg << "does not support the range of times because the time dimension is " + << time_dim_size; + } + else if (error_code == error_code_missing_time_values) { + log_msg << "does not have the matching time ranges between " + << unix_to_yyyymmdd_hhmmss(time_lower) << " and " + << unix_to_yyyymmdd_hhmmss(time_upper); + if (0 < time_dim_size) { + log_msg << " from [" + << unix_to_yyyymmdd_hhmmss(_file->ValidTime.min()) << " and " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime.max()) << "]"; + } + } + else if (error_code == error_code_missing_time_offsets) { + log_msg << "does not have the matching time offsets between " + << nint(time_lower) << " and " << nint(time_upper); + if (0 < time_dim_size) { + log_msg << " [0 <= offset < " << time_dim_size << "]"; + } + } + else if (error_code == error_code_empty_times) { + log_msg << "does not have the time values"; + } + else if (error_code == error_code_bad_increment) { + log_msg << "was configured with bad increment"; + } + else if (error_code == error_code_bad_offset) { + log_msg << "was configured with the bad time offset" + << " (0 <= offset < " << time_dim_size << ")"; + } + else if (error_code == error_code_missing_time_value) { + long time_value = (time_as_value ? dim_offset : -1); + log_msg << "does not have the matching time " + << unix_to_yyyymmdd_hhmmss(time_value) << " [" + << unix_to_yyyymmdd_hhmmss(_file->ValidTime.min()) << " and " + << unix_to_yyyymmdd_hhmmss(_file->ValidTime.max()) << "]"; + } + else { + log_msg.clear(); + log_msg << "variable \"" << vinfo_nc->req_name() + << "\" has unknown error (" << error_code << ")"; + } + mlog << Error << "\n" << method_name << log_msg << ".\n\n"; + exit(1); + } + + return(time_offsets); +} + + +//////////////////////////////////////////////////////////////////////// + +int MetUGridDataFile::index(VarInfo &vinfo){ + + if( nullptr == _file->find_var_name( vinfo.name().c_str() ) ) return -1; + + if( ( vinfo.valid() != 0 && _file->ValidTime[0] != vinfo.valid() ) || + ( vinfo.init() != 0 && _file->InitTime != vinfo.init() ) || + ( !is_bad_data(vinfo.lead()) && _file->lead_time() != vinfo.lead() ) ) + return -1; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +long MetUGridDataFile::convert_time_to_offset(long time_value) { + bool found = false; + bool found_value = false; + long time_offset = bad_data_int; + int dim_size = _file->ValidTime.n(); + static const string method_name + = "MetUGridDataFile::convert_time_to_offset() -> "; + + for (int idx=0; idxValidTime[idx] == time_value) { + time_offset = idx; + found = true; + break; + } + } + + if (!found) { + dim_size = _file->raw_times.n(); + for (int idx=0; idxraw_times[idx] == time_value) { + time_offset = idx; + found_value = true; + break; + } + } + } + + if (found) + mlog << Debug(7) << method_name << " Found " + << unix_to_yyyymmdd_hhmmss(time_value) + << " at index " << time_offset << " from time value\n"; + else if (found_value) + mlog << Debug(7) << method_name << " Found " << time_value + << " at index " << time_offset << " from time value\n"; + else + mlog << Warning << "\n" << method_name << time_value + << " does not exist at time variable\n\n"; + + return time_offset; +} + +//////////////////////////////////////////////////////////////////////// + +long MetUGridDataFile::convert_value_to_offset(double z_value, string z_dim_name) { + bool found = false; + long z_offset = bad_data_int; + int dim_size = _file->vlevels.n(); + static const string method_name + = "MetUGridDataFile::convert_value_to_offset() -> "; + + for (int idx=0; idxvlevels[idx], z_value)) { + found = true; + z_offset = idx; + break; + } + } + + if (!found && 0 < z_dim_name.length()) { + NcVarInfo *var_info = find_var_info_by_dim_name(_file->Var, z_dim_name, _file->Nvars); + if (var_info) { + long new_offset = get_index_at_nc_data(var_info->var, z_value, z_dim_name); + if (new_offset != bad_data_int) z_offset = new_offset; + } + } + + return z_offset; +} + +//////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_data2d_ugrid/data2d_ugrid.h b/src/libcode/vx_data2d_ugrid/data2d_ugrid.h new file mode 100644 index 0000000000..473254b660 --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/data2d_ugrid.h @@ -0,0 +1,125 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + + +#ifndef __MET_VX_DATA_2D_UGRID_H__ +#define __MET_VX_DATA_2D_UGRID_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include "data_plane.h" +#include "data_class.h" +#include "var_info_ugrid.h" +#include "ugrid_file.h" +#include "two_to_one.h" + + +//////////////////////////////////////////////////////////////////////// + + +class MetUGridDataFile : public Met2dDataFile { + + private: + + void ugrid_init_from_scratch(); + //NcVarInfo *find_first_data_var(); + long convert_time_to_offset(long time_value); + long convert_value_to_offset(double z_value, std::string z_dim_name); + LongArray collect_time_offsets(VarInfo &vinfo); + + MetUGridDataFile(const MetUGridDataFile &); + MetUGridDataFile & operator=(const MetUGridDataFile &); + + // + // NetCDF file + // + + UGridFile * _file; // allocated + long _cur_time_index; // current time index to get the data plane (for array of data_plane) + + protected: + + ConcatString meta_filename; + + public: + + MetUGridDataFile(); + ~MetUGridDataFile(); + + virtual int nx() const + { + if (_file == 0) + return 0; + + return _file->getNx(); + } + + + virtual int ny() const + { + return 1; + } + + + // + // set stuff + // + + // + // get stuff + // + + GrdFileType file_type() const; + + // retrieve the first matching data plane + + bool data_plane(VarInfo &, DataPlane &); + + // retrieve all matching data planes + + int data_plane_array(VarInfo &, DataPlaneArray &); + + // retrieve the index of the first matching record + + int index(VarInfo &); + + + // + // do stuff + // + + bool open (const char * filename); + bool open_metadata(const char * filename); + + void close (); + + void dump(std::ostream &, int = 0) const; + +}; + + +//////////////////////////////////////////////////////////////////////// + + +inline GrdFileType MetUGridDataFile::file_type () const { return ( FileType_UGrid ); } + + +//////////////////////////////////////////////////////////////////////// + + +#endif /* __MET_VX_DATA_2D_UGRID_H__ */ + + +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/libcode/vx_data2d_ugrid/ugrid_file.cc b/src/libcode/vx_data2d_ugrid/ugrid_file.cc new file mode 100644 index 0000000000..2c6a2c8dd1 --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/ugrid_file.cc @@ -0,0 +1,902 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "vx_math.h" +#include "vx_cal.h" +#include "vx_log.h" +#include "config_util.h" + +#include "ugrid_file.h" + +using namespace std; +using namespace netCDF; + + +//////////////////////////////////////////////////////////////////////// + +static const char *default_config_filename = + "MET_BASE/config/UGridConfig_default"; + +array DIM_KEYS = { + "dim_face", "dim_node", "dim_edge", "dim_time", "dim_vert" +}; + +array COORD_VAR_KEYS = { + "time", "lat_face", "lon_face", "vert_face", "lat_edge", + "lon_edge", "lat_node", "lon_node", "cell_id" +}; + +static double get_nc_var_att_double(const NcVar *nc_var, const char *att_name, + bool is_required=true); + +#define USE_BUFFER 1 + +//////////////////////////////////////////////////////////////////////// + + + // + // Code for class UGridFile + // + + +//////////////////////////////////////////////////////////////////////// + + +UGridFile::UGridFile() +{ + init_from_scratch(); +} + + +//////////////////////////////////////////////////////////////////////// + + +UGridFile::~UGridFile() +{ + close(); +} + + +//////////////////////////////////////////////////////////////////////// + + +void UGridFile::init_from_scratch() + +{ + // Initialize the pointers + + _ncFile = (NcFile *) nullptr; + _ncMetaFile = (NcFile *) nullptr; + Var = (NcVarInfo *) nullptr; + _time_var_info = (NcVarInfo *)nullptr; + + _faceDim = (NcDim *)nullptr; + _edgeDim = (NcDim *)nullptr; + _nodeDim = (NcDim *)nullptr; + _virtDim = (NcDim *)nullptr; + _tDim = (NcDim *)nullptr; + _latVar = (NcVar *)nullptr; + _lonVar = (NcVar *)nullptr; + _xCoordVar = (NcVar *)nullptr; + _yCoordVar = (NcVar *)nullptr; + + // Close any existing file + + close(); + + return; +} + + +//////////////////////////////////////////////////////////////////////// + + +void UGridFile::close() +{ + + // Reclaim the file pointer + + if (_ncFile) { + delete _ncFile; + _ncFile = (NcFile *)nullptr; + } + + if (_ncMetaFile) { + delete _ncMetaFile; + _ncMetaFile = (NcFile *)nullptr; + } + + // Reclaim the dimension pointers + + _numDims = 0; + + _dimNames.clear(); + metadata_map.clear(); + metadata_names.clear(); + + _faceDim = _edgeDim = _tDim = (NcDim *)nullptr; + + // Reclaim the variable pointers + + if (Var) { + delete [] Var; + Var = (NcVarInfo *)nullptr; + } + + Nvars = 0; + + // Reset the time values + + ValidTime.clear(); + raw_times.clear(); + vlevels.clear(); + InitTime = (unixtime)0; + AccumTime = (unixtime)0; + + face_count = 0; + + // done + + return; +} + + +//////////////////////////////////////////////////////////////////////// + + +bool UGridFile::open(const char * filepath) +{ + const char *method_name = "UGridFile::open() -> "; + + + // Close any open files and clear out the associated members + close(); + read_config(); + + if (_ncFile) { + delete _ncFile; + _ncFile = (NcFile *) nullptr; + } + + // Open the file + _ncFile = open_ncfile(filepath); + + if (IS_INVALID_NC_P(_ncFile)) + { + close(); + return false; + } + + // Pull out the variables + + NcDim dim; + int meta_count = 0; + int max_dim_count = 0; + ConcatString att_value; + StringArray var_names; + + Nvars = get_var_names(_ncFile, &var_names); + for (int j=0; j max_dim_count) max_dim_count = dim_count; + + Var[j].Dims = new NcDim * [dim_count]; + + // parse the variable attributes + get_att_str( Var[j], long_name_att_name, Var[j].long_name_att ); + get_att_str( Var[j], units_att_name, Var[j].units_att ); + + } // for j + + // done + + return true; +} + + +//////////////////////////////////////////////////////////////////////// + + +bool UGridFile::open_metadata(const char * filepath) +{ + unixtime ut; + int sec_per_unit; + const char *method_name = "UGridFile::open_metadata() -> "; + + // FIXME: Commented out with NetCDF4 enabling + // NcError err(NcError::silent_nonfatal); + + // Open the file + _ncMetaFile = open_ncfile(filepath); + + if (IS_INVALID_NC_P(_ncMetaFile)) { + close(); + return false; + } + + NcDim dim; + string meta_name; + StringArray dim_names; + StringArray meta_names; + + get_dim_names(_ncMetaFile, &dim_names); + + // Face (cell) dimension + meta_name = find_metadata_name(DIM_KEYS[0], dim_names); + if (0 < meta_name.length()) { + dim = get_nc_dim(_ncMetaFile, meta_name.c_str()); + face_count = get_dim_size(&dim); + _faceDim = new NcDim(dim); + } + + // Node (vertex) dimension + meta_name = find_metadata_name(DIM_KEYS[1], dim_names); + if (0 < meta_name.length()) { + dim = get_nc_dim(_ncMetaFile, meta_name.c_str()); + _nodeDim = new NcDim(dim); + } + + // Edge dimension + meta_name = find_metadata_name(DIM_KEYS[2], dim_names); + if (0 < meta_name.length()) { + dim = get_nc_dim(_ncMetaFile, meta_name.c_str()); + _edgeDim = new NcDim(dim); + } + + // Time dimension + meta_name = find_metadata_name(DIM_KEYS[3], dim_names); + if (0 < meta_name.length()) { + dim = get_nc_dim(_ncMetaFile, meta_name.c_str()); + _tDim = new NcDim(dim); + } + + // Vertical dimension + meta_name = find_metadata_name(DIM_KEYS[4], dim_names); + if (0 < meta_name.length()) { + dim = get_nc_dim(_ncMetaFile, meta_name.c_str()); + _virtDim = new NcDim(dim); + } + + int max_dim_count = 0; + StringArray var_names; + ConcatString att_value; + NcVar *z_var = (NcVar *)nullptr; + NcVar *valid_time_var = (NcVar *)nullptr; + + get_var_names(_ncMetaFile, &var_names); + + for (int j=0; j max_dim_count) max_dim_count = dim_count; + + // parse the variable attributes + get_att_str( MetaVar[j], long_name_att_name, MetaVar[j].long_name_att ); + get_att_str( MetaVar[j], units_att_name, MetaVar[j].units_att ); + + if (0 == j) { + valid_time_var = MetaVar[j].var; + _time_var_info = &MetaVar[j]; + } + else if (1== j) { + _latVar = MetaVar[j].var; + } + else if (2 == j) { + _lonVar = MetaVar[j].var; + } + else if (3 == j) { + z_var = MetaVar[j].var; + } + } + + } // for j + + StringArray meta_time_names = get_metadata_names(COORD_VAR_KEYS[0]); + for (int j=0; j 1 ) { + double latest_time = bad_data_double; + for(int i=0; i 0) { + unix_to_mdyhms(AccumTime, month, day, year, hour, minute, second); + snprintf(junk, sizeof(junk), "%2d:%02d:%02d (%d seconds)", + hour, minute, second, (int)AccumTime); + out << prefix << "Accum Time = "; + out << junk << "\n"; + out << prefix << "\n"; + } + + out << prefix << "\n"; + + out << prefix << "Nvars = " << Nvars << "\n"; + + for (int j = 0; j < Nvars; ++j) + { + out << p2 << "Var # " << j << " = " << (Var[j].name) << " ("; + + for (int k = 0; k < Var[j].Ndims; ++k) + { + if (Var[j].Dims[k] == _faceDim) + out << 'X'; + else if (Var[j].Dims[k] == _edgeDim) + out << 'Y'; + else if (Var[j].Dims[k] == _tDim) + out << 'T'; + else + out << GET_NC_NAME_P(Var[j].Dims[k]); + + if (k < Var[j].Ndims - 1) + out << ", "; + } // for k + + out << ")\n"; + + out << p2 << "\n"; + + } // for j + + // done + + out.flush(); + + return; +} + + +//////////////////////////////////////////////////////////////////////// + +std::string UGridFile::find_metadata_name(std::string &key, StringArray &available_names) { + string meta_name = ""; + StringArray meta_names = get_metadata_names(key); + + for (int idx=0; idx found " << meta_name + // << " for " << key << "\n"; + break; + } + } + return meta_name; +} + +//////////////////////////////////////////////////////////////////////// + + +NcVarInfo* UGridFile::find_var_name(const char * var_name) const +{ + cout << "UGridFile::find_var_name() Nvars=" << Nvars << ", " << var_name << "\n"; + for (int i = 0; i < Nvars; i++) + { + cout << "UGridFile::find_var_name() " << Var[i].name << " VS " << var_name << "\n"; + if (Var[i].name == var_name) + return &Var[i]; + } + return nullptr; +} + + +//////////////////////////////////////////////////////////////////////// + + +double UGridFile::getData(NcVar * var, const LongArray & a) const +{ + clock_t start_clock = clock(); + static const string method_name + = "UGridFile::getData(NcVar *, const LongArray &) -> "; + if (!args_ok(a)) + { + mlog << Error << "\n" << method_name + << "bad arguments:\n"; + a.dump(cerr); + exit(1); + } + + int dim_count = get_dim_count(var); + if (dim_count != a.n_elements()) + { + mlog << Error << "\n" << method_name + << "needed " << (dim_count) << " arguments for variable " + << (GET_NC_NAME_P(var)) << ", got " << (a.n_elements()) << "\n\n"; + exit(1); + } + + + for (int k=0; kgetDim(k).getSize(); + if (dim_size < a[k]) { + mlog << Error << "\n" << method_name + << "offset (" << a[k] << ") at " << k + << "th dimension (" << long(dim_size) << ") is too big for variable \"" + << GET_NC_NAME_P(var) << "\"\n\n"; + exit ( 1 ); + } + } + + bool status = false; + double d = bad_data_double; + + double fill_value; + double missing_value = get_var_missing_value(var); + get_var_fill_value(var, fill_value); + + status = get_nc_data(var, &d, a); + + if (!status) + { + mlog << Error << "\nUGridFile::getData(NcVar *, const LongArray &) const -> " + << "bad status for var->get()\n\n"; + exit(1); + } + + // done + + mlog << Debug(6) << method_name << "took " + << (clock()-start_clock)/double(CLOCKS_PER_SEC) << " seconds\n"; + + return d; +} + + +//////////////////////////////////////////////////////////////////////// + + +bool UGridFile::getData(NcVar * v, const LongArray & a, DataPlane & plane) const +{ + clock_t start_clock = clock(); + static const string method_name_short + = "UGridFile::getData(NcVar*, LongArray&, DataPlane&) "; + static const string method_name + = "UGridFile::getData(NcVar *, const LongArray &, DataPlane &) const -> "; + + if (!args_ok(a)) + { + mlog << Error << "\n" << method_name + << "bad arguments:\n"; + a.dump(cerr); + exit(1); + } + + int dim_count = get_dim_count(v); + if (dim_count != a.n_elements()) + { + mlog << Error << "\n" << method_name + << "needed " << (dim_count) << " arguments for variable " + << (GET_NC_NAME_P(v)) << ", got " << (a.n_elements()) << "\n\n"; + exit(1); + } + + // find varinfo's + + bool found = false; + NcVarInfo *var = (NcVarInfo *)nullptr; + + for (int j = 0; j < Nvars; ++j) + { + if (Var[j].var == v) + { + found = true; + var = Var + j; + break; + } + } + + if (!found) + { + mlog << Error << "\n" << method_name + << "variable " << (GET_NC_NAME_P(v)) << " not found!\n\n"; + exit(1); + } + + // check star positions and count + + // + // get the bad data values + // + + double fill_value; + double missing_value = get_var_missing_value(v); + get_var_fill_value(v, fill_value); + + // set up the DataPlane object + + const int nx = grid.nx(); + const int ny = grid.ny(); + + plane.clear(); + plane.set_size(nx, ny); + + // get the data + int *i; + short *s; + float *f; + const int plane_size = nx * ny; + double *d = new double[plane_size]; + + //get_nc_data(v, d, lengths, offsets); + get_nc_data(v, d); + + int offset = 0; + for (int x = 0; x< nx; ++x) { + double value = d[x]; + if( is_eq(value, missing_value) || is_eq(value, fill_value) ) { + value = bad_data_double; + } + + plane.set(value, x, 0); + + } // for x + + delete [] d; + + // done + mlog << Debug(6) << method_name << "took " + << (clock()-start_clock)/double(CLOCKS_PER_SEC) << " seconds\n"; + + return true; +} + + +//////////////////////////////////////////////////////////////////////// + + +bool UGridFile::getData(const char *var_name, + const LongArray &a, DataPlane &plane, + NcVarInfo *&info) const +{ + info = find_var_name(var_name); + if (info == nullptr) + return false; + + bool found = getData(info->var, a, plane); + + // store the times + unixtime valid_ut; + if(info->t_slot >= 0) valid_ut = ValidTime[a[info->t_slot]]; + else valid_ut = ValidTime[0]; + + // if unset, set the init time to the valid time + unixtime init_ut = InitTime; + if(init_ut == 0 && valid_ut != 0) { + mlog << Debug(4) << "UGridFile::getData() -> " + << "setting the unset init time to the valid time of " + << unix_to_yyyymmdd_hhmmss(valid_ut) << ".\n"; + init_ut = valid_ut; + } + + unixtime accum_time = info->AccumTime; + if ((0 == accum_time) && (AccumTime>0)) accum_time = AccumTime; + + plane.set_init(init_ut); + plane.set_valid(valid_ut); + plane.set_lead(valid_ut - init_ut); + plane.set_accum(accum_time); + + // done + + return found; +} + + +//////////////////////////////////////////////////////////////////////// + + +StringArray UGridFile::get_metadata_names(std::string &key) { + StringArray empty; + auto search = metadata_map.find(key); + return search == metadata_map.end() ? empty : metadata_map[key]; +} + + +//////////////////////////////////////////////////////////////////////// + + +int UGridFile::lead_time() const +{ + unixtime dt = ValidTime[0] - InitTime; + + return (int) dt; +} + + +//////////////////////////////////////////////////////////////////////// + + +void UGridFile::read_config() { + const char *method_name = "UGridFile::read_config()"; + MetConfig conf; + + // Read the default config file + conf.read(replace_path(default_config_filename).c_str()); + + metadata_map = parse_conf_metadata_map(&conf); + metadata_names.clear(); + for (std::map::iterator it=metadata_map.begin(); + it!=metadata_map.end(); ++it) { + metadata_names.add(it->second); + } + + mlog << Debug(4) << method_name + << " map size: " << metadata_map.size() << ", dims_vars_count = " << metadata_names.n() << "\n"; + +} + +//////////////////////////////////////////////////////////////////////// + + +void UGridFile::read_netcdf_grid() +{ + // Loop through the variables looking for the first gridded variable. We + // will use this variable to pull out the grid information. The CF + // description allows for different fields in the same file to have different + // grids, but with how the gridded information is used in MET, I'm making the + // assumption that all fields are on the same grid. + + ConcatString units_value; + const char *method_name = "UGridFile::read_netcdf_grid() -> "; + + double *_lat = new double[face_count]; + double *_lon = new double[face_count]; + + if (IS_INVALID_NC_P(_latVar)) { + mlog << Error << "\n" << method_name << "latitude variable is missing\n\n"; + exit(1); + } + else if (!get_nc_data(_latVar,_lat)) { + mlog << Error << "\n" << method_name << "fail to read latitude values\n\n"; + exit(1); + } + + if (IS_INVALID_NC_P(_lonVar)) { + mlog << Error << "\n" << method_name << "longitude variable is missing\n\n"; + exit(1); + } + else if (!get_nc_data(_lonVar,_lon)) { + mlog << Error << "\n" << method_name << "fail to read latitude values\n\n"; + exit(1); + } + + if (get_var_units(_latVar, units_value)) { + if (units_value == "rad" || units_value == "radian") { + mlog << Debug(6) << method_name << " convert lat (" < + +#include "vx_grid.h" +#include "nc_utils.h" +#include "data_plane.h" +#include "long_array.h" +#include "nc_var_info.h" + + +//////////////////////////////////////////////////////////////////////// + + +static const int UG_DIM_COUNT = 5; +static const int UG_META_VAR_COUNT = 9; + + +//////////////////////////////////////////////////////////////////////// + + +class UGridFile { + + public: + + UGridFile(); + ~UGridFile(); + + bool open(const char *filename); + bool open_metadata(const char *filename); + + void close(); + + void dump(std::ostream &, int = 0) const; + + + int getNx() const { + return (_faceDim == nullptr) ? 0 : GET_NC_SIZE_P(_faceDim); + } + + int getNy() const { + return 1; + } + + NcVarInfo *get_time_var_info() const { return _time_var_info; } + + // + // time + // + + TimeArray ValidTime; + NumArray raw_times; + NumArray vlevels; + + unixtime InitTime; + unixtime AccumTime; + + int lead_time () const; // seconds + + + // + // variables + // + + int Nvars; + + NcVarInfo *Var; // allocated + std::arrayMetaVar; + + // + // Grid + // + + Grid grid; + UnstructuredData grid_data; + + // + // data + // + + double getData(netCDF::NcVar *, const LongArray &) const; + + bool getData(netCDF::NcVar *, const LongArray &, DataPlane &) const; + + bool getData(const char *, const LongArray &, DataPlane &, NcVarInfo *&) const; + + NcVarInfo* find_var_name(const char * var_name) const; + + private: + + static const double DELTA_TOLERANCE; + + netCDF::NcFile * _ncFile; // allocated + netCDF::NcFile * _ncMetaFile; // allocated + + std::map metadata_map; + StringArray metadata_names; + + // + // dimensions + // + + int _numDims; + + //std::array _dims; // allocated + + StringArray _dimNames; + + // Pointers to the X/Y and time dimensions and the associated coordinate + // variables. Note that these are pointers into the _dims and Var + // arrays so should not be deleted. + + netCDF::NcDim *_faceDim; + netCDF::NcDim *_edgeDim; + netCDF::NcDim *_nodeDim; + netCDF::NcDim *_virtDim; + netCDF::NcDim *_tDim; + + netCDF::NcVar *_latVar; + netCDF::NcVar *_lonVar; + netCDF::NcVar *_xCoordVar; + netCDF::NcVar *_yCoordVar; + NcVarInfo *_time_var_info; + + int face_count; + //double *_lat; + //double *_lon; + + void init_from_scratch(); + + UGridFile(const UGridFile &); + UGridFile & operator=(const UGridFile &); + + // Determine the file times from the filename + + // Read the grid information from the netCDF file and fill in the + // grid member with that information. + + std::string find_metadata_name(std::string &key, StringArray &available_names); + StringArray get_metadata_names(std::string &key); + void read_config(); + void read_netcdf_grid(); + +}; + + +//////////////////////////////////////////////////////////////////////// + + +#endif /* __UGRID_FILE_H__ */ + + +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/libcode/vx_data2d_ugrid/var_info_ugrid.cc b/src/libcode/vx_data2d_ugrid/var_info_ugrid.cc new file mode 100644 index 0000000000..7b1da7e5ab --- /dev/null +++ b/src/libcode/vx_data2d_ugrid/var_info_ugrid.cc @@ -0,0 +1,470 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + +/////////////////////////////////////////////////////////////////////////////// +// +// Filename: var_info_ugrid.cc +// +// Description: +// +// Mod# Date Name Description +// ---- ---- ---- ----------- +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "var_info.h" +#include "var_info_ugrid.h" + +#include "vx_math.h" +#include "util_constants.h" +#include "vx_log.h" +#include "grib_strings.h" + +using namespace std; + + +/////////////////////////////////////////////////////////////////////////////// + +static bool is_grib_code_abbr_match(const ConcatString &, int); + +/////////////////////////////////////////////////////////////////////////////// +// +// Code for class VarInfoUGrid +// +/////////////////////////////////////////////////////////////////////////////// + +VarInfoUGrid::VarInfoUGrid() { + + init_from_scratch(); +} + +/////////////////////////////////////////////////////////////////////////////// + +VarInfoUGrid::~VarInfoUGrid() { + + clear(); +} + +/////////////////////////////////////////////////////////////////////////////// + +VarInfoUGrid::VarInfoUGrid(const VarInfoUGrid &f) { + + init_from_scratch(); + + assign(f); +} + +/////////////////////////////////////////////////////////////////////////////// + +VarInfoUGrid & VarInfoUGrid::operator=(const VarInfoUGrid &f) { + + if ( this == &f ) return ( *this ); + + assign(f); + + return ( *this ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void VarInfoUGrid::init_from_scratch() { + + // First call the parent's initialization + VarInfo::init_from_scratch(); + + clear(); + + return; +} + +/////////////////////////////////////////////////////////////////////////////// + +void VarInfoUGrid::assign(const VarInfoUGrid &v) { + int i; + + // First call the parent's assign + VarInfo::assign(v); + + // Copy + clear_dimension(); + for(i=0; i +#include +#include +#include +#include +#include + +#include "vx_math.h" +#include "vx_util.h" +#include "vx_log.h" +#include "unstructured_grid.h" + +#include "atlas/grid/Grid.h" // PointLonLat +#include "atlas/util/Geometry.h" +#include "atlas/util/KDTree.h" + +using namespace std; + +using PointLonLat = atlas::PointLonLat; +using Geometry = atlas::Geometry; +using IndexKDTree = atlas::util::IndexKDTree; + +//////////////////////////////////////////////////////////////////////// + + +static atlas::Geometry atlas_geometry; + +//////////////////////////////////////////////////////////////////////// + + + // + // Code for class UnstructuredGrid + // + + +//////////////////////////////////////////////////////////////////////// + + +UnstructuredGrid::UnstructuredGrid() { + clear(); +} + + +//////////////////////////////////////////////////////////////////////// + + +UnstructuredGrid::~UnstructuredGrid() { + clear(); +} + + +//////////////////////////////////////////////////////////////////////// + + +void UnstructuredGrid::clear() { + + Name.clear(); + + Nx = 0; + wrapLon = false; + + Data.clear(); + return; + +} + + +//////////////////////////////////////////////////////////////////////// + + +UnstructuredGrid::UnstructuredGrid(const UnstructuredData & data) { + + set_from_data(data); + +} + + +//////////////////////////////////////////////////////////////////////// + +void UnstructuredGrid::set_from_data(const UnstructuredData &data) { + + Data.clear(); + + if (data.name) Name = data.name; + Nx = data.Nface;; + + Data.Nface = Nx; + Data.Nedge = data.Nedge; + Data.Nnode = data.Nnode; + + Data.set_points(Nx, data.pointLonLat); + + return; + +} + +//////////////////////////////////////////////////////////////////////// + + +void UnstructuredGrid::latlon_to_xy(double lat, double lon, double &x, double &y) const { + + PointLonLat _pointLonLat(lon, lat); + y = 0; + + IndexKDTree::ValueList neighbor = Data.kdtree->closestPoints(_pointLonLat, 1); + size_t index(neighbor[0].payload()); + x = index; + + mlog << Debug(7) << "UnstructuredGrid::latlon_to_xy() " + << "(" << lon << ", " << lat << ") ==> (" << x << ", " << y << ")\n"; + +} + + +//////////////////////////////////////////////////////////////////////// + + +void UnstructuredGrid::xy_to_latlon(double x, double y, double &lat, double &lon) const { + + lat = Data.pointLonLat[x].y(); + lon = Data.pointLonLat[x].x(); + + mlog << Debug(7) << "UnstructuredGrid::xy_to_latlon() " + << "(" << x << ", " << y << ") ==> (" << lon << ", " << lat << ").\n"; + +} + + +//////////////////////////////////////////////////////////////////////// + +double UnstructuredGrid::calc_area(int x, int y) const { + + double area = 0.; + + return ( area ); + +} + +//////////////////////////////////////////////////////////////////////// + + +int UnstructuredGrid::nx() const { + + return Nx; + +} + + +//////////////////////////////////////////////////////////////////////// + + +int UnstructuredGrid::ny() const { + + return 1; + +} + + +//////////////////////////////////////////////////////////////////////// + + +ConcatString UnstructuredGrid::name() const { + + return Name; + +} + + +//////////////////////////////////////////////////////////////////////// + + +void UnstructuredGrid::dump(ostream & out, int depth) const { + +Indent prefix(depth); + +out << prefix << "Name = "; + +if ( Name.length() > 0 ) out << '\"' << Name << '\"'; +else out << "(nul)\n"; + +out << '\n'; + +out << prefix << "Nface = " << Nx << "\n"; + + // + // done + // +out.flush(); + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + +ConcatString UnstructuredGrid::serialize(const char *sep) const { + +ConcatString a; +char junk[256]; + + +a << "Projection: UnstructuredGrid" << sep; + +a << "Nface: " << Nx << sep; + // + // done + // + +return a; + +} + + +//////////////////////////////////////////////////////////////////////// + + +GridInfo UnstructuredGrid::info() const { + +GridInfo i; + +i.set( Data ); + +return i; + +} + + +//////////////////////////////////////////////////////////////////////// + +double UnstructuredGrid::rot_grid_to_earth(int x, int y) const + +{ + +// +// The rotation angle from grid relative to earth relative is zero +// for the PlateCarreeGrids that are defined north and east. This may +// need to be changed when support is added for GRIB2. +// + +return 0.0; + +} + +//////////////////////////////////////////////////////////////////////// + +void UnstructuredGrid::shift_right(int N) +{ + + mlog << Warning << "\nUnstructuredGrid::shift_right(int) -> not implemented\n\n"; + +} + +//////////////////////////////////////////////////////////////////////// + + +GridRep * UnstructuredGrid::copy() const { + + UnstructuredGrid *p = new UnstructuredGrid (Data); + + p->Name = Name; + + return p; + +} + + +//////////////////////////////////////////////////////////////////////// + + + // + // Code for misc functions + // + + +//////////////////////////////////////////////////////////////////////// + + +Grid::Grid(const UnstructuredData &data) { + + init_from_scratch(); + + set(data); + +} + + +//////////////////////////////////////////////////////////////////////// + + +void Grid::set(const UnstructuredData &data) { + clear(); + + rep = new UnstructuredGrid ( data ); + if ( !rep ) { + mlog << Error << "\nGrid::set(const Unstructured &) -> memory allocation error\n\n"; + exit ( 1 ); + } +} + + +//////////////////////////////////////////////////////////////////////// + + +UnstructuredData::UnstructuredData() { + kdtree = nullptr; + clear(); +} + +//////////////////////////////////////////////////////////////////////// + +UnstructuredData::~UnstructuredData() { + clear(); +} + +//////////////////////////////////////////////////////////////////////// + +void UnstructuredData::build_tree() { + + atlas::idx_t n = 0; + kdtree = new IndexKDTree(atlas_geometry); + for (int i=0; iinsert(pointLL, n++); + } + + kdtree->build(); + +} + +//////////////////////////////////////////////////////////////////////// + +void UnstructuredData::set_points(int count, double *_lon, double *_lat) { + + clear(); + + Nface = count; + pointLonLat.reserve(Nface); + for (int i=0; i &_pointLonLat) { + + clear(); + + Nface = count; + pointLonLat.reserve(Nface); + + for (int i=0; i &) (" + << pointLonLat[0].x() << ", " << pointLonLat[0].y() << ") and (" + << pointLonLat[count-1].x() << ", " << pointLonLat[count-1].y() << ") from (" + << _pointLonLat[0].x() << ", " << _pointLonLat[0].y() << ") and (" + << _pointLonLat[count-1].x() << ", " << _pointLonLat[count-1].y() << ")\n"; + + build_tree(); + +} + +//////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_grid/unstructured_grid.h b/src/libcode/vx_grid/unstructured_grid.h new file mode 100644 index 0000000000..bf377b1d13 --- /dev/null +++ b/src/libcode/vx_grid/unstructured_grid.h @@ -0,0 +1,97 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + + +#ifndef __UNSTRUCTURTED_GRID_H__ +#define __UNSTRUCTURTED_GRID_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include "grid_base.h" + + +//////////////////////////////////////////////////////////////////////// + + +class UnstructuredGrid : public GridRep { + + friend class Grid; + + protected: + + UnstructuredGrid(); + ~UnstructuredGrid(); + UnstructuredGrid(const UnstructuredData &); + + + int Nx; + + + bool wrapLon; + + ConcatString Name; + + UnstructuredData Data; + + void clear(); + + void set_from_data(const UnstructuredData &); + + // + // grid interface + // + + virtual void latlon_to_xy(double lat, double lon, double & x, double & y) const; + + virtual void xy_to_latlon(double x, double y, double & lat, double & lon) const; + + virtual double calc_area(int x, int y) const; + + virtual int nx() const; + virtual int ny() const; + + double scale_km() const; + + virtual ConcatString name() const; + + void dump(std::ostream &, int = 0) const; + + ConcatString serialize(const char *sep=" ") const; + + GridInfo info() const; + + double rot_grid_to_earth(int x, int y) const; + + bool wrap_lon() const; + + void shift_right(int); + + GridRep * copy() const; + +}; + + +//////////////////////////////////////////////////////////////////////// + + +inline double UnstructuredGrid::scale_km() const { return ( -1.0 ); } +inline bool UnstructuredGrid::wrap_lon() const { return ( wrapLon ); } + + +//////////////////////////////////////////////////////////////////////// + + +#endif // __UNSTRUCTURTED_GRID_H__ + + +//////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_grid/unstructured_grid_defs.h b/src/libcode/vx_grid/unstructured_grid_defs.h new file mode 100644 index 0000000000..b95d5df001 --- /dev/null +++ b/src/libcode/vx_grid/unstructured_grid_defs.h @@ -0,0 +1,64 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + + +#ifndef __UNSTRUCTURTED_GRID_DEFINITIONS_H__ +#define __UNSTRUCTURTED_GRID_DEFINITIONS_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include + +#include "atlas/grid/Grid.h" // PointLonLat +#include "atlas/util/Geometry.h" +#include "atlas/util/KDTree.h" + + +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// + + + + +struct UnstructuredData { + + const char * name; // not allocated + + int Nface; + int Nedge; + int Nnode; + + std::vector pointLonLat; + atlas::util::IndexKDTree *kdtree; + + UnstructuredData(); + ~UnstructuredData(); + + void build_tree(); + void set_points(int count, double *_lon, double *_lat); + void set_points(int count, const std::vector &); + void clear(); + + void dump() const; +}; + + +//////////////////////////////////////////////////////////////////////// + + +#endif /* __UNSTRUCTURTED_GRID_DEFINITIONS_H__ */ + + +////////////////////////////////////////////////////////////////////////