diff --git a/obs2ioda-v2/src/cxx/CMakeLists.txt b/obs2ioda-v2/src/cxx/CMakeLists.txt index 29dd1a5..1f1419b 100644 --- a/obs2ioda-v2/src/cxx/CMakeLists.txt +++ b/obs2ioda-v2/src/cxx/CMakeLists.txt @@ -3,6 +3,7 @@ set(obs2ioda_cxx_SOURCES netcdf_file.cc netcdf_group.cc netcdf_dimension.cc + netcdf_variable.cc ) set(obs2ioda_cxx_LIBRARIES NetCDF::NetCDF_CXX diff --git a/obs2ioda-v2/src/cxx/netcdf_variable.cc b/obs2ioda-v2/src/cxx/netcdf_variable.cc new file mode 100644 index 0000000..8a4cba8 --- /dev/null +++ b/obs2ioda-v2/src/cxx/netcdf_variable.cc @@ -0,0 +1,220 @@ +#include "netcdf_variable.h" +#include "netcdf_file.h" +#include "netcdf_error.h" + +namespace Obs2Ioda { + int netcdfAddVar( + int netcdfID, + const char *groupName, + const char *varName, + nc_type netcdfDataType, + int numDims, + const char **dimNames + ) { + try { + auto file = FileMap::getInstance().getFile(netcdfID); + const auto group = !groupName + ? file + : std::make_shared< + netCDF::NcGroup>( + file->getGroup( + groupName)); + std::vector dims; + dims.reserve(numDims); + for (int i = 0; i < numDims; i++) { + dims.push_back(file->getDim(dimNames[i]));; + } + auto var = group->addVar( + varName, + netCDF::NcType(netcdfDataType), + dims + ); + return 0; + } catch (netCDF::exceptions::NcException &e) { + return netcdfErrorMessage( + e, + __LINE__, + __FILE__ + ); + } + } + + template + int netcdfPutVar( + int netcdfID, + const char *groupName, + const char *varName, + const T *values + ) { + try { + auto file = FileMap::getInstance().getFile(netcdfID); + const auto group = !groupName + ? file + : std::make_shared< + netCDF::NcGroup>( + file->getGroup( + groupName)); + auto var = group->getVar(varName); + var.putVar(values); + return 0; + } catch (netCDF::exceptions::NcException &e) { + return netcdfErrorMessage( + e, + __LINE__, + __FILE__ + ); + } + } + + int netcdfPutVarInt( + int netcdfID, + const char *groupName, + const char *varName, + const int *values + ) { + return netcdfPutVar( + netcdfID, + groupName, + varName, + values + ); + } + + int netcdfPutVarInt64( + int netcdfID, + const char *groupName, + const char *varName, + const long long *values + ) { + return netcdfPutVar( + netcdfID, + groupName, + varName, + values + ); + } + + int netcdfPutVarReal( + int netcdfID, + const char *groupName, + const char *varName, + const float *values + ) { + return netcdfPutVar( + netcdfID, + groupName, + varName, + values + ); + } + + int netcdfPutVarString( + int netcdfID, + const char *groupName, + const char *varName, + const char **values + ) { + return netcdfPutVar( + netcdfID, + groupName, + varName, + values + ); + } + + template + int netcdfSetFill( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + T fillValue + ) { + try { + auto file = FileMap::getInstance().getFile(netcdfID); + const auto group = !groupName + ? file + : std::make_shared< + netCDF::NcGroup>( + file->getGroup( + groupName)); + auto var = group->getVar(varName); + var.setFill( + fillMode, + fillValue + ); + return 0; + } catch (netCDF::exceptions::NcException &e) { + return netcdfErrorMessage( + e, + __LINE__, + __FILE__ + ); + } + } + + int netcdfSetFillInt( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + int fillValue + ) { + return netcdfSetFill( + netcdfID, + groupName, + varName, + fillMode, + fillValue + ); + } + + int netcdfSetFillReal( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + float fillValue + ) { + return netcdfSetFill( + netcdfID, + groupName, + varName, + fillMode, + fillValue + ); + } + + int netcdfSetFillInt64( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + long long fillValue + ) { + return netcdfSetFill( + netcdfID, + groupName, + varName, + fillMode, + fillValue + ); + } + + int netcdfSetFillString( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + const char *fillValue + ) { + return netcdfSetFill( + netcdfID, + groupName, + varName, + fillMode, + fillValue + + ); + } +} diff --git a/obs2ioda-v2/src/cxx/netcdf_variable.h b/obs2ioda-v2/src/cxx/netcdf_variable.h new file mode 100644 index 0000000..47f4b7e --- /dev/null +++ b/obs2ioda-v2/src/cxx/netcdf_variable.h @@ -0,0 +1,118 @@ +#ifndef NETCDF_VARIABLE_H +#define NETCDF_VARIABLE_H +#include + +namespace Obs2Ioda { + + extern "C" { + /** + * @brief Adds a variable to a NetCDF file. + * + * @param netcdfID The identifier of the NetCDF file where the variable will be added. + * @param groupName The name of the group in which the variable should be created. + * If nullptr, the variable is added to the root group. + * @param varName The name of the variable to be created. + * @param netcdfDataType The NetCDF data type of the variable (e.g., NC_INT, NC_FLOAT). + * @param numDims The number of dimensions associated with the variable. + * @param dimNames An array of dimension names specifying the shape of the variable. + * @return int A status code indicating the outcome of the operation: + * - 0: Success. + * - Non-zero: Failure, with an error message logged. + */ + int netcdfAddVar( + int netcdfID, + const char *groupName, + const char *varName, + nc_type netcdfDataType, + int numDims, + const char **dimNames + ); + + /** + * @brief Writes data to a variable in a NetCDF file. + * + * @param netcdfID The identifier of the NetCDF file where the data will be written. + * @param groupName The name of the group containing the variable. If nullptr, the variable is assumed to be in the root group. + * @param varName The name of the variable to which data will be written. + * @param values A pointer to the data to be written to the variable. + * @return int A status code indicating the outcome of the operation: + * - 0: Success. + * - Non-zero: Failure, with an error message logged. + */ + int netcdfPutVarInt( + int netcdfID, + const char *groupName, + const char *varName, + const int *values + ); + + int netcdfPutVarInt64( + int netcdfID, + const char *groupName, + const char *varName, + const long long *values + ); + + int netcdfPutVarReal( + int netcdfID, + const char *groupName, + const char *varName, + const float *values + ); + + int netcdfPutVarString( + int netcdfID, + const char *groupName, + const char *varName, + const char **values + ); + + /** + * @brief Sets the fill mode and fill value for a variable in a NetCDF file. + * + * @param netcdfID The identifier of the NetCDF file containing the variable. + * @param groupName The name of the group containing the variable. If nullptr, the variable is assumed to be in the root group. + * @param varName The name of the variable for which the fill mode is set. + * @param fillMode The fill mode to be applied: + * - 0: Disable fill mode (use uninitialized values). + * - 1: Enable fill mode (use the specified fill value). + * @param fillValue The fill value to be applied when fill mode is enabled. Must match the data type of the variable. + * @return int A status code indicating the outcome of the operation: + * - 0: Success. + * - Non-zero: Failure, with an error message logged. + */ + int netcdfSetFillInt( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + int fillValue + ); + + int netcdfSetFillReal( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + float fillValue + ); + + int netcdfSetFillInt64( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + long long fillValue + ); + + int netcdfSetFillString( + int netcdfID, + const char *groupName, + const char *varName, + int fillMode, + const char *fillValue + ); + } +} + +#endif //NETCDF_VARIABLE_H diff --git a/obs2ioda-v2/src/netcdf_cxx_i_mod.f90 b/obs2ioda-v2/src/netcdf_cxx_i_mod.f90 index 2242845..10563f3 100644 --- a/obs2ioda-v2/src/netcdf_cxx_i_mod.f90 +++ b/obs2ioda-v2/src/netcdf_cxx_i_mod.f90 @@ -1,5 +1,5 @@ module netcdf_cxx_i_mod - use iso_c_binding, only : c_int, c_ptr + use iso_c_binding, only : c_int, c_ptr, c_float, c_long implicit none public @@ -112,6 +112,193 @@ function c_netcdfAddDim(& integer(c_int) :: c_netcdfAddDim end function c_netcdfAddDim + ! c_netcdfAddVar: + ! Adds a new variable to a NetCDF file, specifying its name, type, and associated dimensions. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file where the variable will be created. + ! - groupName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the group name. If `c_null_ptr`, + ! the variable is added as a global variable. + ! - varName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the variable name. + ! - netcdfDataType (integer(c_int), intent(in), value): + ! The NetCDF data type of the variable (e.g., `NF90_INT`, `NF90_REAL`). + ! - numDims (integer(c_int), intent(in), value): + ! The number of dimensions associated with the variable. + ! - dimNames (type(c_ptr), intent(in), value): + ! A C pointer to an array of null-terminated strings representing the dimension names. + ! + ! Returns: + ! - integer(c_int): Status code indicating the result of the operation: + ! - 0: Success. + ! - Non-zero: Failure. + ! + ! Notes: + ! - This function assumes that `netcdfID` corresponds to a valid NetCDF file. + ! - All strings must be null-terminated and passed as C pointers. + function c_netcdfAddVar(& + netcdfID, groupName, varName, netcdfDataType, numDims, dimNames) & + bind(C, name = "netcdfAddVar") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + integer(c_int), value, intent(in) :: netcdfDataType + integer(c_int), value, intent(in) :: numDims + type(c_ptr), value, intent(in) :: dimNames + integer(c_int) :: c_netcdfAddVar + end function c_netcdfAddVar + + ! c_netcdfPutVar: + ! Writes integer data to a NetCDF variable in the specified group or as a global variable. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file. + ! - groupName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the group name. If `c_null_ptr`, + ! the variable is assumed to be a global variable. + ! - varName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the variable name. + ! - values (type(c_ptr), intent(in), value): + ! A C pointer to the array of integer data to be written. + ! + ! Returns: + ! - integer(c_int): Status code indicating the result of the operation: + ! - 0: Success. + ! - Non-zero: Failure. + function c_netcdfPutVarInt(& + netcdfID, groupName, varName, values) & + bind(C, name = "netcdfPutVarInt") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + type(c_ptr), value, intent(in) :: values + integer(c_int) :: c_netcdfPutVarInt + end function c_netcdfPutVarInt + + ! See documentation for `c_netcdfPutVarInt`. + function c_netcdfPutVarInt64(& + netcdfID, groupName, varName, values) & + bind(C, name = "netcdfPutVarInt64") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + type(c_ptr), value, intent(in) :: values + integer(c_int) :: c_netcdfPutVarInt64 + end function c_netcdfPutVarInt64 + + ! See documentation for `c_netcdfPutVarInt`. + function c_netcdfPutVarReal(& + netcdfID, groupName, varName, values) & + bind(C, name = "netcdfPutVarReal") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + type(c_ptr), value, intent(in) :: values + integer(c_int) :: c_netcdfPutVarReal + end function c_netcdfPutVarReal + + ! See documentation for `c_netcdfPutVarInt`. + function c_netcdfPutVarString(& + netcdfID, groupName, varName, values) & + bind(C, name = "netcdfPutVarString") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + type(c_ptr), value, intent(in) :: values + integer(c_int) :: c_netcdfPutVarString + end function c_netcdfPutVarString + + ! c_netcdfSetFillInt: + ! Sets the fill mode and fill value for an integer NetCDF variable in the specified group + ! or as a global variable. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file. + ! - groupName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the group name. If `c_null_ptr`, + ! the variable is assumed to be a global variable. + ! - varName (type(c_ptr), intent(in), value): + ! A C pointer to a null-terminated string specifying the variable name. + ! - fillMode (integer(c_int), intent(in), value): + ! The fill mode flag, typically `NC_FILL` (enable fill) or `NC_NOFILL` (disable fill). + ! - fillValue (integer(c_int), intent(in), value): + ! The integer fill value to be used if fill mode is enabled. + ! + ! Returns: + ! - integer(c_int): Status code indicating the result of the operation: + ! - 0: Success. + ! - Non-zero: Failure. + function c_netcdfSetFillInt(& + netcdfID, groupName, varName, fillMode, fillValue) & + bind(C, name = "netcdfSetFillInt") + import :: c_int + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + integer(c_int), value, intent(in) :: fillMode + integer(c_int), value, intent(in) :: fillValue + integer(c_int) :: c_netcdfSetFillInt + end function c_netcdfSetFillInt + + ! See documentation for `c_netcdfSetFillInt`. + function c_netcdfSetFillInt64(& + netcdfID, groupName, varName, fillMode, fillValue) & + bind(C, name = "netcdfSetFillInt64") + import :: c_int + import :: c_long + import :: c_ptr + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + integer(c_int), value, intent(in) :: fillMode + integer(c_long), value, intent(in) :: fillValue + integer(c_int) :: c_netcdfSetFillInt64 + end function c_netcdfSetFillInt64 + + ! See documentation for `c_netcdfSetFillInt`. + function c_netcdfSetFillReal(& + netcdfID, groupName, varName, fillMode, fillValue) & + bind(C, name = "netcdfSetFillReal") + import :: c_int + import :: c_ptr + import :: c_float + real(c_float), value, intent(in) :: fillValue + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + integer(c_int), value, intent(in) :: fillMode + integer(c_int) :: c_netcdfSetFillReal + end function c_netcdfSetFillReal + + ! See documentation for `c_netcdfSetFillInt`. + function c_netcdfSetFillString(& + netcdfID, groupName, varName, fillMode, fillValue) & + bind(C, name = "netcdfSetFillString") + import :: c_int + import :: c_ptr + type(c_ptr), value, intent(in) :: fillValue + integer(c_int), value, intent(in) :: netcdfID + type(c_ptr), value, intent(in) :: groupName + type(c_ptr), value, intent(in) :: varName + integer(c_int), value, intent(in) :: fillMode + integer(c_int) :: c_netcdfSetFillString + end function c_netcdfSetFillString + end interface end module netcdf_cxx_i_mod diff --git a/obs2ioda-v2/src/netcdf_cxx_mod.f90 b/obs2ioda-v2/src/netcdf_cxx_mod.f90 index 1ce059b..7303b83 100644 --- a/obs2ioda-v2/src/netcdf_cxx_mod.f90 +++ b/obs2ioda-v2/src/netcdf_cxx_mod.f90 @@ -1,8 +1,10 @@ module netcdf_cxx_mod - use iso_c_binding, only : c_int, c_ptr, c_null_ptr + use iso_c_binding, only : c_int, c_ptr, c_null_ptr, c_loc, c_float, c_long use f_c_string_t_mod, only : f_c_string_t - use netcdf_cxx_i_mod, only : c_netcdfCreate, c_netcdfClose, c_netcdfAddGroup, c_netcdfAddDim - use netcdf, only : NF90_INT, NF90_REAL + use f_c_string_1D_t_mod, only : f_c_string_1D_t + use netcdf_cxx_i_mod, only : c_netcdfCreate, c_netcdfClose, c_netcdfAddGroup, c_netcdfAddDim, & + c_netcdfAddVar, c_netcdfPutVarInt, c_netcdfPutVarInt64, c_netcdfPutVarReal, c_netcdfPutVarString, & + c_netcdfSetFillInt, c_netcdfSetFillInt64, c_netcdfSetFillReal, c_netcdfSetFillString implicit none public @@ -135,4 +137,184 @@ function netcdfAddDim(netcdfID, dimName, len, groupName) end function netcdfAddDim + ! netcdfAddVar: + ! Adds a new variable to a NetCDF file, specifying its name, type, dimensions, and target group. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file to which the variable will be added. + ! - varName (character(len=*), intent(in)): + ! The name of the new variable to be created. + ! - netcdfDataType (integer(c_int), intent(in), value): + ! The NetCDF data type of the variable (e.g., `NF90_INT`, `NF90_REAL`). + ! - numDims (integer(c_int), intent(in), value): + ! The number of dimensions associated with the variable. + ! - dimNames (character(len=*), dimension(numDims), intent(in)): + ! An array of dimension names that define the variable's shape. + ! - groupName (character(len=*), intent(in), optional): + ! The name of the group in which the variable will be created. + ! If not provided, the variable will be added as a global variable. + ! + ! Returns: + ! - integer(c_int): A status code indicating the outcome of the operation: + ! - 0: Success. + ! - Non-zero: Failure. + function netcdfAddVar(netcdfID, varName, netcdfDataType, numDims, dimNames, groupName) + integer(c_int), value, intent(in) :: netcdfID + character(len = *), intent(in) :: varName + integer(c_int), value, intent(in) :: netcdfDataType + integer(c_int), value, intent(in) :: numDims + character(len = *), dimension(numDims), intent(in) :: dimNames + character(len = *), optional, intent(in) :: groupName + integer(c_int) :: netcdfAddVar + type(c_ptr) :: c_groupName + type(c_ptr) :: c_varName + type(c_ptr) :: c_dimNames + type(f_c_string_t) :: f_c_string_groupName + type(f_c_string_t) :: f_c_string_varName + type(f_c_string_1D_t) :: f_c_string_1D_dimNames + + if (present(groupName)) then + c_groupName = f_c_string_groupName%to_c(groupName) + else + c_groupName = c_null_ptr + end if + c_varName = f_c_string_varName%to_c(varName) + c_dimNames = f_c_string_1D_dimNames%to_c(dimNames) + netcdfAddVar = c_netcdfAddVar(netcdfID, c_groupName, c_varName, & + netcdfDataType, numDims, c_dimNames) + end function netcdfAddVar + + ! netcdfPutVar: + ! Writes data to a variable in a NetCDF file. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file where the data will be written. + ! - varName (character(len=*), intent(in)): + ! The name of the variable to which data will be written. + ! - values (class(*), dimension(:), intent(in)): + ! The data to be written to the variable. + ! - groupName (character(len=*), intent(in), optional): + ! The name of the group containing the variable. + ! If not provided, the variable is assumed to be a global variable. + ! + ! Returns: + ! - integer(c_int): A status code indicating the outcome of the operation: + ! - 0: Success. + ! - -1: NetCDF operation returned an error, but the error code was 0. + ! - -2: Unsupported type passed for values. + ! - Other nonzero values: Specific NetCDF error codes. + function netcdfPutVar(netcdfID, varName, values, groupName) + integer(c_int), value, intent(in) :: netcdfID + character(len = *), intent(in) :: varName + class(*), dimension(:), intent(in) :: values + character(len = *), optional, intent(in) :: groupName + integer(c_int) :: netcdfPutVar + type(f_c_string_t) :: f_c_string_groupName + type(f_c_string_t) :: f_c_string_varName + type(c_ptr) :: c_groupName + type(c_ptr) :: c_varName + type(c_ptr) :: c_values + type(f_c_string_1D_t) :: f_c_string_1D_values + + if (present(groupName)) then + c_groupName = f_c_string_groupName%to_c(groupName) + else + c_groupName = c_null_ptr + end if + c_varName = f_c_string_varName%to_c(varName) + + select type (values) + type is (integer(c_int)) + c_values = c_loc(values) + netcdfPutVar = c_netcdfPutVarInt(netcdfID, c_groupName, & + c_varName, c_values) + + type is (integer(c_long)) + c_values = c_loc(values) + netcdfPutVar = c_netcdfPutVarInt64(netcdfID, c_groupName, & + c_varName, c_values) + + type is (real(c_float)) + c_values = c_loc(values) + netcdfPutVar = c_netcdfPutVarReal(netcdfID, c_groupName, & + c_varName, c_values) + + type is (character(len = *)) + c_values = f_c_string_1D_values%to_c(values) + netcdfPutVar = c_netcdfPutVarString(netcdfID, c_groupName, & + c_varName, c_values) + class default + netcdfPutVar = -2 + end select + end function netcdfPutVar + + ! netcdfSetFill: + ! Sets the fill mode and fill value for a variable in a NetCDF file. + ! + ! Arguments: + ! - netcdfID (integer(c_int), intent(in), value): + ! The identifier of the NetCDF file containing the variable. + ! - varName (character(len=*), intent(in)): + ! The name of the variable for which the fill mode is set. + ! - fillMode (integer(c_int), intent(in), value): + ! The fill mode to be applied: + ! - 0: Turn off fill mode (use uninitialized values). + ! - 1: Turn on fill mode (use specified fill value). + ! - fillValue (class(*), intent(in)): + ! The fill value to be applied when fill mode is enabled. + ! Must match the data type of the variable. + ! - groupName (character(len=*), intent(in), optional): + ! The name of the group containing the variable. + ! If not provided, the variable is assumed to be a global variable. + ! + ! Returns: + ! - integer(c_int): A status code indicating the outcome of the operation: + ! - 0: Success. + ! - -1: NetCDF operation returned an error, but the error code was 0. + ! - -2: Unsupported type passed for fillValue. + ! - Other nonzero values: Specific NetCDF error codes. + function netcdfSetFill(netcdfID, varName, fillMode, fillValue, groupName) + integer(c_int), value, intent(in) :: netcdfID + character(len = *), intent(in) :: varName + integer(c_int), value, intent(in) :: fillMode + class(*), intent(in) :: fillValue + character(len = *), optional, intent(in) :: groupName + integer(c_int) :: netcdfSetFill + type(f_c_string_t) :: f_c_string_groupName + type(f_c_string_t) :: f_c_string_varName + type(c_ptr) :: c_groupName + type(c_ptr) :: c_varName + type(f_c_string_t) :: f_c_string_fillValue + + if (present(groupName)) then + c_groupName = f_c_string_groupName%to_c(groupName) + else + c_groupName = c_null_ptr + end if + c_varName = f_c_string_varName%to_c(varName) + + select type (fillValue) + type is (integer(c_int)) + netcdfSetFill = c_netcdfSetFillInt(netcdfID, c_groupName, & + c_varName, fillMode, fillValue) + + type is (integer(c_long)) + netcdfSetFill = c_netcdfSetFillInt64(netcdfID, c_groupName, & + c_varName, fillMode, fillValue) + + type is (real(c_float)) + netcdfSetFill = c_netcdfSetFillReal(netcdfID, c_groupName, & + c_varName, fillMode, fillValue) + + type is (character(len = *)) + netcdfSetFill = c_netcdfSetFillString(netcdfID, c_groupName, & + c_varName, fillMode, & + f_c_string_fillValue%to_c(fillValue)) + class default + netcdfSetFill = -2 + end select + end function netcdfSetFill + end module netcdf_cxx_mod