commit d375ca7222a77bcf9b34f7e3523f1238a923de44
parent 8670933a63421a7abb15983c2bc752c28e800196
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 29 Jun 2018 15:11:17 +0200
Begin the loading of the Mie data
Diffstat:
3 files changed, 267 insertions(+), 3 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -84,6 +84,7 @@ if(NOT NO_TEST)
endfunction()
new_test(test_htmie)
+ new_test(test_htmie_load)
endif()
################################################################################
diff --git a/src/htmie.c b/src/htmie.c
@@ -15,6 +15,7 @@
#include "htmie.h"
+#include <rsys/dynamic_array_double.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
@@ -33,6 +34,12 @@
} (void)0
struct htmie {
+ struct darray_double wavelengths; /* In nano-meters */
+ struct darray_double xsections_absorption;
+ struct darray_double xsections_scattering;
+
+ double rmod; /* Modal mean radius in micro-meters */
+
int verbose; /* Verbosity level */
struct logger* logger;
struct mem_allocator* allocator;
@@ -42,7 +49,7 @@ struct htmie {
/*******************************************************************************
* Helper functions
******************************************************************************/
-static void
+static INLINE void
log_msg
(const struct htmie* htmie,
const enum log_type stream,
@@ -57,7 +64,7 @@ log_msg
}
}
-static void
+static INLINE void
log_err(const struct htmie* htmie, const char* msg, ...)
{
va_list vargs_list;
@@ -67,6 +74,24 @@ log_err(const struct htmie* htmie, const char* msg, ...)
va_end(vargs_list);
}
+static INLINE void
+log_warn(const struct htmie* htmie, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(htmie && msg);
+ va_start(vargs_list, msg);
+ log_msg(htmie, LOG_WARNING, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+static INLINE int
+cmp_dbl(const void* a, const void* b)
+{
+ const double d0 = *((const double*)a);
+ const double d1 = *((const double*)b);
+ return d0 < d1 ? -1 : (d0 > d1 ? 1 : 0);
+}
+
static INLINE const char*
ncerr_to_str(const int ncerr)
{
@@ -87,12 +112,196 @@ ncerr_to_str(const int ncerr)
return str;
}
+static INLINE const char*
+nctype_to_str(const nc_type type)
+{
+ const char* str = "NC_TYPE_<UNKNOWN>";
+ switch(type) {
+ case NC_NAT: str = "NC_NAT"; break;
+ case NC_BYTE: str = "NC_BYTE"; break;
+ case NC_CHAR: str = "NC_CHAR"; break;
+ case NC_SHORT: str = "NC_SHORT"; break;
+ case NC_LONG: str = "NC_LONG"; break;
+ case NC_FLOAT: str = "NC_FLOAT"; break;
+ case NC_DOUBLE: str = "NC_DOUBLE"; break;
+ case NC_UBYTE: str = "NC_UBYTE"; break;
+ case NC_USHORT: str = "NC_USHORT"; break;
+ case NC_UINT: str = "NC_UINT"; break;
+ case NC_INT64: str = "NC_INT64"; break;
+ case NC_UINT64: str = "NC_UINT64"; break;
+ case NC_STRING: str = "NC_STRING"; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ return str;
+}
+
+static INLINE size_t
+sizeof_nctype(const nc_type type)
+{
+ size_t sz;
+ switch(type) {
+ case NC_BYTE:
+ case NC_CHAR:
+ case NC_UBYTE:
+ sz = 1; break;
+ case NC_SHORT:
+ case NC_USHORT:
+ sz = 2; break;
+ case NC_FLOAT:
+ case NC_INT:
+ case NC_UINT:
+ sz = 4; break;
+ case NC_DOUBLE:
+ case NC_INT64:
+ case NC_UINT64:
+ sz = 8; break;
+ default: FATAL("Unreachable cde.\n"); break;
+ }
+ return sz;
+}
+
+static res_T
+load_wavelengths(struct htmie* htmie, const int nc)
+{
+ size_t len;
+ size_t start;
+ size_t i;
+ int id;
+ int ndims;
+ int dimid;
+ int err= NC_NOERR;
+ int type;
+ res_T res = RES_OK;
+ ASSERT(htmie);
+
+ err = nc_inq_varid(nc, "lambda", &id);
+ if(err != NC_NOERR) {
+ log_err(htmie, "Could not inquire the 'lambda' variable -- %s\n",
+ ncerr_to_str(err));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ NC(inq_varndims(nc, id, &ndims));
+ if(ndims != 1) {
+ log_err(htmie, "The dimension of the 'lambda' variable must be 1.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ NC(inq_vardimid(nc, id, &dimid));
+ NC(inq_dimlen(nc, dimid, &len));
+ NC(inq_vartype(nc, id, &type));
+
+ if(type != NC_DOUBLE && type != NC_FLOAT) {
+ log_err(htmie,
+ "Type type of the 'lambda' variable cannot be %s. "
+ "Expecting floating point data.\n",
+ nctype_to_str(type));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = darray_double_resize(&htmie->wavelengths, len);
+ if(res != RES_OK) {
+ log_err(htmie, "Could not allocate the list of wavelengths.\n");
+ goto error;
+ }
+
+ start = 0;
+ NC(get_vara_double(nc, id, &start, &len,
+ darray_double_data_get(&htmie->wavelengths)));
+
+ FOR_EACH(i, 1, len) {
+ if(darray_double_cdata_get(&htmie->wavelengths)[i-1]
+ > darray_double_cdata_get(&htmie->wavelengths)[i-0]) {
+ break;
+ }
+ }
+
+ if(i < len) { /* Wavelengths are not sorted */
+ log_warn(htmie, "Unordered wavelengths.\n");
+ qsort
+ (darray_double_data_get(&htmie->wavelengths),
+ darray_double_size_get(&htmie->wavelengths),
+ sizeof(double),
+ cmp_dbl);
+ }
+
+exit:
+ return res;
+error:
+ darray_double_clear(&htmie->wavelengths);
+ goto exit;
+}
+
+static res_T
+load_modal_mean_radius(struct htmie* htmie, const int nc)
+{
+ size_t len;
+ size_t start;
+ int id;
+ int ndims;
+ int dimid;
+ int err = NC_NOERR;
+ int type;
+ res_T res = RES_OK;
+ ASSERT(htmie);
+
+ err = nc_inq_varid(nc, "rmod", &id);
+ if(err != NC_NOERR) {
+ log_err(htmie, "Could not inquiere the 'rmod' variable -- %s\n",
+ ncerr_to_str(err));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ NC(inq_varndims(nc, id, &ndims));
+ if(ndims != 1) {
+ log_err(htmie, "The dimension of the 'rmod' variable must be 1.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ NC(inq_vardimid(nc, id, &dimid));
+
+ NC(inq_dimlen(nc, dimid, &len));
+ if(len != 1) {
+ log_err(htmie,
+ "Only 1 distribution is currently supported while the #distributions is "
+ "%lu\n", (unsigned long)len);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ NC(inq_vartype(nc, id, &type));
+ if(type != NC_DOUBLE && type != NC_FLOAT) {
+ log_err(htmie,
+ "Type type of the 'rmod' variable cannot be %s. "
+ "Expecting floating point data.\n",
+ nctype_to_str(type));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ start = 0;
+ NC(get_vara_double(nc, id, &start, &len, &htmie->rmod));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
static void
release_htmie(ref_T* ref)
{
struct htmie* htmie;
ASSERT(ref);
htmie = CONTAINER_OF(ref, struct htmie, ref);
+ darray_double_release(&htmie->wavelengths);
+ darray_double_release(&htmie->xsections_absorption);
+ darray_double_release(&htmie->xsections_scattering);
MEM_RM(htmie->allocator, htmie);
}
@@ -132,6 +341,9 @@ htmie_create
htmie->allocator = allocator;
htmie->logger = logger;
htmie->verbose = verbose;
+ darray_double_init(htmie->allocator, &htmie->wavelengths);
+ darray_double_init(htmie->allocator, &htmie->xsections_absorption);
+ darray_double_init(htmie->allocator, &htmie->xsections_scattering);
exit:
if(out_htmie) *out_htmie = htmie;
@@ -179,7 +391,10 @@ htmie_load(struct htmie* htmie, const char* path)
goto error;
}
- /* TODO load data */
+ res = load_wavelengths(htmie, nc);
+ if(res != RES_OK) goto error;
+ res = load_modal_mean_radius(htmie, nc);
+ if(res != RES_OK) goto error;
exit:
if(nc != INVALID_NC_ID) NC(close(nc));
diff --git a/src/test_htmie_load.c b/src/test_htmie_load.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com)
+ *
+* 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "htmie.h"
+#include "test_htmie_utils.h"
+
+int
+main(int argc, char** argv)
+{
+ struct htmie* htmie = NULL;
+ const char* filename = NULL;
+ struct mem_allocator allocator;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s NETCDF\n", argv[0]);
+ return -1;
+ }
+
+ filename = argv[1];
+
+ CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
+ CHK(htmie_create(NULL, &allocator, 1, &htmie) == RES_OK);
+
+ CHK(htmie_load(NULL, NULL) == RES_BAD_ARG);
+ CHK(htmie_load(htmie, NULL) == RES_BAD_ARG);
+ CHK(htmie_load(NULL, filename) == RES_BAD_ARG);
+ CHK(htmie_load(htmie, filename) == RES_OK);
+
+ CHK(htmie_ref_put(htmie) == RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
+