htmie

Optical properties of water droplets
git clone git://git.meso-star.fr/htmie.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 1+
Msrc/htmie.c | 221+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Asrc/test_htmie_load.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
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; +} +