Skip to content

Commit e5e125f

Browse files
authored
Merge pull request #363 from esmf-org/netcdf_attribute_type
Use correct NetCDF types when writing attributes
2 parents 5df19ab + b227459 commit e5e125f

File tree

8 files changed

+422
-119
lines changed

8 files changed

+422
-119
lines changed

src/Infrastructure/IO/include/ESMCI_IO_NetCDF.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
#include "netcdf.h"
4646
typedef int NcFile;
4747
typedef int NcDim;
48-
#define NC_UNSPECIFIED ((nc_type)0)
4948
#endif
5049

5150
namespace ESMCI
@@ -106,10 +105,6 @@ namespace ESMCI
106105
// < declare private interface methods here >
107106

108107
#ifdef ESMF_NETCDF
109-
int ncerrToEsmcRc (int ncerr);
110-
ESMC_TypeKind_Flag ncToEsmcType(nc_type ncTypeVal);
111-
nc_type esmcToNcType(ESMC_TypeKind_Flag esmcTypeVal);
112-
113108
Array* readArray(NcFile netCdfFile,
114109
int varIndex,
115110
int *rc);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// $Id$
2+
//
3+
// Earth System Modeling Framework
4+
// Copyright (c) 2002-2025, University Corporation for Atmospheric Research,
5+
// Massachusetts Institute of Technology, Geophysical Fluid Dynamics
6+
// Laboratory, University of Michigan, National Centers for Environmental
7+
// Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
8+
// NASA Goddard Space Flight Center.
9+
// Licensed under the University of Illinois-NCSA License.
10+
//
11+
// ESMCI NetCDF utility functions header file
12+
//
13+
//-----------------------------------------------------------------------------
14+
//
15+
16+
#ifndef ESMCI_IO_NetCDF_Utils_H
17+
#define ESMCI_IO_NetCDF_Utils_H
18+
19+
#include "ESMCI_Macros.h"
20+
#include "ESMC_Util.h"
21+
22+
#if defined(ESMF_PNETCDF)
23+
#include <pnetcdf.h>
24+
#elif defined(ESMF_NETCDF)
25+
#include <netcdf.h>
26+
#else
27+
// Some definitions needed to allow things to work without either ESMF_PNETCDF or
28+
// ESMF_NETCDF (to avoid needing an overly-complex set of ifdefs elsewhere).
29+
typedef int nc_type;
30+
#define NC_NOERR 0
31+
#endif
32+
33+
#define NC_UNSPECIFIED ((nc_type)0)
34+
35+
namespace ESMCI{
36+
// Convert a NetCDF error code to an ESMC error code
37+
int ncerrToEsmcRc(int ncerr);
38+
39+
// Convert a NetCDF data type code to an ESMC data type code
40+
ESMC_TypeKind_Flag ncToEsmcType(nc_type ncTypeVal);
41+
42+
// Convert an ESMC data type code to a NetCDF data type code
43+
nc_type esmcToNcType(ESMC_TypeKind_Flag esmcTypeVal);
44+
}
45+
46+
#endif // ESMCI_IO_NetCDF_Utils_H

src/Infrastructure/IO/src/ESMCI_IO_NetCDF.C

Lines changed: 14 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "ESMCI_ArraySpec.h"
3737
#include "ESMCI_LocalArray.h"
3838
#include "ESMCI_Array.h"
39+
#include "ESMCI_IO_NetCDF_Utils.h"
3940

4041
using namespace std;
4142
using json = nlohmann::json;
@@ -585,110 +586,6 @@ void IO_NetCDF::destruct(void) {
585586

586587
#ifdef ESMF_NETCDF
587588

588-
int IO_NetCDF::ncerrToEsmcRc (int ncerror)
589-
{
590-
591-
#undef ESMC_METHOD
592-
#define ESMC_METHOD "IO_NetCDF::ncerrToEsmcRc"
593-
594-
if (ncerror == NC_NOERR)
595-
return ESMF_SUCCESS;
596-
else
597-
return ESMF_FAILURE;
598-
} // end ncerrToEsmcRc
599-
600-
ESMC_TypeKind_Flag IO_NetCDF::ncToEsmcType(nc_type ncTypeVal)
601-
{
602-
603-
#undef ESMC_METHOD
604-
#define ESMC_METHOD "IO_NetCDF::ncToEsmcType"
605-
606-
ESMC_TypeKind_Flag esmcTypeVal = ESMF_NOKIND;
607-
608-
switch (ncTypeVal)
609-
{
610-
case NC_BYTE:
611-
esmcTypeVal = ESMC_TYPEKIND_I1;
612-
break;
613-
case NC_CHAR:
614-
esmcTypeVal = ESMC_TYPEKIND_CHARACTER;
615-
break;
616-
case NC_SHORT:
617-
esmcTypeVal = ESMC_TYPEKIND_I2;
618-
break;
619-
case NC_INT:
620-
esmcTypeVal = ESMC_TYPEKIND_I4;
621-
break;
622-
//case NC_LONG: // TODO?: deprecated in netCDF - same as NC_INT
623-
// esmcTypeVal = ESMC_TYPEKIND_I8;
624-
//break;
625-
case NC_FLOAT:
626-
esmcTypeVal = ESMC_TYPEKIND_R4;
627-
break;
628-
case NC_DOUBLE:
629-
esmcTypeVal = ESMC_TYPEKIND_R8;
630-
break;
631-
default:
632-
break;
633-
}
634-
635-
return esmcTypeVal;
636-
}
637-
638-
639-
//-------------------------------------------------------------------------
640-
641-
nc_type IO_NetCDF::esmcToNcType(ESMC_TypeKind_Flag esmcTypeVal)
642-
{
643-
644-
#undef ESMC_METHOD
645-
#define ESMC_METHOD "IO_NetCDF::esmcToNcType"
646-
647-
nc_type ncTypeVal = NC_UNSPECIFIED;
648-
649-
switch (esmcTypeVal)
650-
{
651-
case ESMC_TYPEKIND_I1:
652-
ncTypeVal = NC_BYTE;
653-
break;
654-
case ESMC_TYPEKIND_I2:
655-
ncTypeVal = NC_SHORT;
656-
break;
657-
case ESMC_TYPEKIND_I4:
658-
ncTypeVal = NC_INT;
659-
break;
660-
case ESMC_TYPEKIND_I8:
661-
ncTypeVal = NC_LONG; // TODO?: deprecated in netCDF - same ncInt
662-
break;
663-
case ESMC_TYPEKIND_R4:
664-
ncTypeVal = NC_FLOAT;
665-
break;
666-
case ESMC_TYPEKIND_R8:
667-
ncTypeVal = NC_DOUBLE;
668-
break;
669-
case ESMF_C8:
670-
ncTypeVal = NC_UNSPECIFIED;
671-
// TODO: ncTypeVal = netCDF 8 byte complex type?
672-
break;
673-
case ESMF_C16:
674-
ncTypeVal = NC_UNSPECIFIED;
675-
// TODO: ncTypeVal = netCDF 16 byte complex type?
676-
break;
677-
case ESMC_TYPEKIND_LOGICAL:
678-
ncTypeVal = NC_BYTE;
679-
break;
680-
case ESMC_TYPEKIND_CHARACTER:
681-
ncTypeVal = NC_CHAR;
682-
break;
683-
default:
684-
break;
685-
}
686-
687-
return ncTypeVal;
688-
}
689-
690-
691-
692589
//-------------------------------------------------------------------------
693590

694591
Array* IO_NetCDF::readArray(NcFile netCdfFile,
@@ -744,6 +641,11 @@ void IO_NetCDF::destruct(void) {
744641
}
745642

746643
ESMC_TypeKind_Flag arrayType = ncToEsmcType(nctype);
644+
if (arrayType == ESMF_NOKIND) {
645+
string errstr = string(": problem converting NetCDF type to ESMF type");
646+
ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_VALUE, errstr, ESMC_CONTEXT, rc);
647+
return thisArray;
648+
}
747649

748650
if (trace)
749651
std::cerr << ESMC_METHOD << ": allocating values buffer, numValues = " << numValues << std::endl;
@@ -981,6 +883,11 @@ void IO_NetCDF::destruct(void) {
981883
ESMC_TypeKind_Flag esmcType = thisArray->getTypekind();
982884
//printf("ESMC Type: %d\n", esmcType);
983885
nc_type ncType = esmcToNcType(esmcType);
886+
if (ncType == NC_UNSPECIFIED) {
887+
string errstr = string(": problem converting ESMF type to NetCDF type");
888+
ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_VALUE, errstr, ESMC_CONTEXT, &localrc);
889+
return localrc;
890+
}
984891

985892
int thisVar;
986893

@@ -1085,7 +992,9 @@ void IO_NetCDF::destruct(void) {
1085992
break;
1086993

1087994
default:
1088-
break;
995+
string errstr = string(": unhandled NetCDF type");
996+
ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, errstr, ESMC_CONTEXT, &localrc);
997+
return localrc;
1089998
}
1090999

10911000
delete[] counts;
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// $Id$
2+
//
3+
// Earth System Modeling Framework
4+
// Copyright (c) 2002-2025, University Corporation for Atmospheric Research,
5+
// Massachusetts Institute of Technology, Geophysical Fluid Dynamics
6+
// Laboratory, University of Michigan, National Centers for Environmental
7+
// Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
8+
// NASA Goddard Space Flight Center.
9+
// Licensed under the University of Illinois-NCSA License.
10+
//
11+
//==============================================================================
12+
#define ESMC_FILENAME "ESMCI_IO_NetCDF_Utils.C"
13+
//==============================================================================
14+
15+
// single blank line to make protex happy.
16+
// BOP
17+
18+
// EOP
19+
//-----------------------------------------------------------------------------
20+
//
21+
// !DESCRIPTION:
22+
//
23+
// The code in this file implements utility functions for NetCDF.
24+
//
25+
//-----------------------------------------------------------------------------
26+
27+
// associated header file
28+
#include "ESMCI_IO_NetCDF_Utils.h"
29+
30+
using namespace std;
31+
32+
//-----------------------------------------------------------------------------
33+
// leave the following line as-is; it will insert the cvs ident string
34+
// into the object file for tracking purposes.
35+
static const char *const version = "$Id$";
36+
//-----------------------------------------------------------------------------
37+
38+
//-----------------------------------------------------------------------------
39+
#undef ESMC_METHOD
40+
#define ESMC_METHOD "ESMCI::ncerrToEsmcRc"
41+
//BOPI
42+
// !IROUTINE: ESMCI::ncerrToEsmcRc
43+
//
44+
// !INTERFACE:
45+
int ESMCI::ncerrToEsmcRc(
46+
//
47+
// !RETURN VALUE:
48+
// int ESMC error code
49+
//
50+
// !ARGUMENTS:
51+
int ncerror // (in) NetCDF error code
52+
){
53+
// !DESCRIPTION:
54+
// Convert a NetCDF error code to an ESMC error code.
55+
//EOPI
56+
//-----------------------------------------------------------------------------
57+
if (ncerror == NC_NOERR)
58+
return ESMF_SUCCESS;
59+
else
60+
return ESMF_FAILURE;
61+
}
62+
//-----------------------------------------------------------------------------
63+
64+
//-----------------------------------------------------------------------------
65+
#undef ESMC_METHOD
66+
#define ESMC_METHOD "ESMCI::ncToEsmcType"
67+
//BOPI
68+
// !IROUTINE: ESMCI::ncToEsmcType
69+
//
70+
// !INTERFACE:
71+
ESMC_TypeKind_Flag ESMCI::ncToEsmcType(
72+
//
73+
// !RETURN VALUE:
74+
// ESMC_TypeKind_Flag ESMC data type code
75+
//
76+
// !ARGUMENTS:
77+
nc_type ncTypeVal // (in) NetCDF data type code
78+
){
79+
// !DESCRIPTION:
80+
// Convert a NetCDF data type code to an ESMC data type code.
81+
//EOPI
82+
//-----------------------------------------------------------------------------
83+
ESMC_TypeKind_Flag esmcTypeVal = ESMF_NOKIND;
84+
85+
#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)
86+
switch (ncTypeVal)
87+
{
88+
case NC_BYTE:
89+
esmcTypeVal = ESMC_TYPEKIND_I1;
90+
break;
91+
case NC_CHAR:
92+
esmcTypeVal = ESMC_TYPEKIND_CHARACTER;
93+
break;
94+
case NC_SHORT:
95+
esmcTypeVal = ESMC_TYPEKIND_I2;
96+
break;
97+
case NC_INT:
98+
esmcTypeVal = ESMC_TYPEKIND_I4;
99+
break;
100+
// case NC_LONG: // TODO?: deprecated in netCDF - same as NC_INT
101+
// esmcTypeVal = ESMC_TYPEKIND_I8;
102+
// break;
103+
case NC_FLOAT:
104+
esmcTypeVal = ESMC_TYPEKIND_R4;
105+
break;
106+
case NC_DOUBLE:
107+
esmcTypeVal = ESMC_TYPEKIND_R8;
108+
break;
109+
default:
110+
break;
111+
}
112+
#endif
113+
114+
return esmcTypeVal;
115+
}
116+
117+
//-----------------------------------------------------------------------------
118+
#undef ESMC_METHOD
119+
#define ESMC_METHOD "ESMCI::esmcToNcType"
120+
//BOPI
121+
// !IROUTINE: ESMCI::esmcToNcType
122+
//
123+
// !INTERFACE:
124+
nc_type ESMCI::esmcToNcType(
125+
//
126+
// !RETURN VALUE:
127+
// nc_type NetCDF data type code
128+
//
129+
// !ARGUMENTS:
130+
ESMC_TypeKind_Flag esmcTypeVal // (in) ESMC data type code
131+
){
132+
// !DESCRIPTION:
133+
// Convert an ESMC data type code to a NetCDF data type code.
134+
//EOPI
135+
//-----------------------------------------------------------------------------
136+
nc_type ncTypeVal = NC_UNSPECIFIED;
137+
138+
#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)
139+
switch (esmcTypeVal)
140+
{
141+
case ESMC_TYPEKIND_I1:
142+
ncTypeVal = NC_BYTE;
143+
break;
144+
case ESMC_TYPEKIND_I2:
145+
ncTypeVal = NC_SHORT;
146+
break;
147+
case ESMC_TYPEKIND_I4:
148+
ncTypeVal = NC_INT;
149+
break;
150+
case ESMC_TYPEKIND_I8:
151+
ncTypeVal = NC_LONG; // TODO?: deprecated in netCDF - same ncInt
152+
break;
153+
case ESMC_TYPEKIND_R4:
154+
ncTypeVal = NC_FLOAT;
155+
break;
156+
case ESMC_TYPEKIND_R8:
157+
ncTypeVal = NC_DOUBLE;
158+
break;
159+
case ESMF_C8:
160+
ncTypeVal = NC_UNSPECIFIED;
161+
// TODO: ncTypeVal = netCDF 8 byte complex type?
162+
break;
163+
case ESMF_C16:
164+
ncTypeVal = NC_UNSPECIFIED;
165+
// TODO: ncTypeVal = netCDF 16 byte complex type?
166+
break;
167+
case ESMC_TYPEKIND_LOGICAL:
168+
ncTypeVal = NC_BYTE;
169+
break;
170+
case ESMC_TYPEKIND_CHARACTER:
171+
ncTypeVal = NC_CHAR;
172+
break;
173+
default:
174+
break;
175+
}
176+
#endif
177+
178+
return ncTypeVal;
179+
}

0 commit comments

Comments
 (0)