pio_write.c 7.8 KB
Newer Older
1
2
3
4
5
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <errno.h>
6
#include <inttypes.h>
7
#include <limits.h>
8
#include <stdarg.h>
9
#include <stdbool.h>
Thomas Jahns's avatar
Thomas Jahns committed
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <sys/time.h>
14
15
16
17
#include <unistd.h>

#ifdef USE_MPI
#include <mpi.h>
18
#include <yaxt.h>
19
20
#else
typedef int MPI_Comm;
21
22
23
#endif

#include "cdi.h"
24
#include "dmemory.h"
25
#include "pio_write.h"
26
27
#ifdef USE_MPI
#include "cdipio.h"
28
#include "pio_util.h"
29
#endif
30

31
static const struct model_config default_setup
32
33
34
#ifdef __cplusplus
= { 12, 6, 3, 5, 5, FILETYPE_GRB, DATATYPE_PACK24,1,"grb"};
#else
35
  = { .nlon = 12, .nts = 3, .nlat = 6, .nvars = 5,
36
      .filetype = FILETYPE_GRB, .datatype = DATATYPE_PACK24,
37
      .compute_checksum = 1,
38
39
      .suffix = "grb",
      .max_nlev = 5,
40
};
41
#endif
42
43
44
45
46
47
48
49
50
51
52
53
54
55

static const struct {
  char suffix[4];
  int type, defaultDT, defaultGrid;
} suffix2type[] = {
  { "nc", FILETYPE_NC, DATATYPE_FLT64, GRID_LONLAT },
  { "grb",  FILETYPE_GRB, DATATYPE_PACK24, GRID_LONLAT },
  { "nc2", FILETYPE_NC2, DATATYPE_FLT64, GRID_LONLAT },
  { "nc4", FILETYPE_NC4, DATATYPE_FLT64, GRID_LONLAT },
  { "ext", FILETYPE_EXT, DATATYPE_FLT64, GRID_GENERIC, },
  { "svc", FILETYPE_SRV, DATATYPE_FLT64, GRID_GENERIC, },
  { "ieg", FILETYPE_IEG, DATATYPE_FLT64, GRID_LONLAT },
};

56
57
58
59
60
61
62
63
64
static void
invalidOptionDie(const char *format, ...)
{
  va_list ap;
  va_start(ap, format);
  vfprintf(stderr, format, ap);
  exit(EXIT_FAILURE);
}

65
66
67
68
69
70
71
72
73
74
75
static int
parse_intarg(const char msg[])
{
  char *end;
  long temp = strtol(optarg, &end, 0);
  if ((errno == ERANGE && (temp == LONG_MAX || temp == LONG_MIN))
      || (errno != 0 && temp == 0)) {
    perror(msg);
    exit(EXIT_FAILURE);
  }
  if (temp > INT_MAX || temp < INT_MIN)
76
    invalidOptionDie("range error: %ld\n", temp);
77
78
79
  return (int)temp;
}

80
81
82
83
84
85
86
87
88
89
90
91
static unsigned
parse_unsignedarg(const char msg[])
{
  char *end;
  unsigned long temp = strtoul(optarg, &end, 0);
  if ((errno == ERANGE && (temp == ULONG_MAX))
      || (errno != 0 && temp == 0))
    {
      perror(msg);
      exit(EXIT_FAILURE);
    }
  if (temp > UINT_MAX)
92
    invalidOptionDie("range error: %ld\n", temp);
93
94
95
  return (unsigned)temp;
}

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
static void
parse_long_option(int pioConfHandle, const char *str)
{
  static const char cacheRedistStr[] = "cache-redists";
  if (!strncmp(str, cacheRedistStr, sizeof (cacheRedistStr) - 1))
    {
#ifdef USE_MPI
      if (str[sizeof (cacheRedistStr) - 1] == '\0'
          || !strcmp(str + sizeof (cacheRedistStr) - 1, "=true"))
        cdiPioConfSetRedistCache(pioConfHandle, 1);
      else if (!strcmp(str + sizeof (cacheRedistStr) - 1, "=false"))
        cdiPioConfSetRedistCache(pioConfHandle, 0);
      else
        invalidOptionDie("invalid option argument to -qcache-redists: %s\n",
                         optarg + sizeof (cacheRedistStr) - 1);
#else
      invalidOptionDie("CDI-PIO option -q%s ignored in non-MPI mode\n",
                       cacheRedistStr);
#endif
    }
  else
    invalidOptionDie("unknown long option: %s\n", str);
}


121
int main(int argc, char *argv[])
122
123
124
{
  struct model_config setup = default_setup;

125
  MPI_Comm commModel;
126
  int pioConfHandle = 0;
127
#ifdef USE_MPI
128
  MPI_Comm commGlob;
129
130
131
132
133
134
  int sizeGlob;
  int rankGlob;
  int IOMode = PIO_MPI;
  int nProcsIO = 2;

  xmpi ( MPI_Init ( &argc, &argv));
135
  commGlob = MPI_COMM_WORLD;
136
  xt_initialize(commGlob);
137
138
139
  xmpi ( MPI_Comm_set_errhandler ( commGlob, MPI_ERRORS_RETURN ));
  xmpi ( MPI_Comm_size ( commGlob, &sizeGlob ));
  xmpi ( MPI_Comm_rank ( commGlob, &rankGlob ));
140

141
  pioConfHandle = cdiPioConfCreate();
142
143
#endif

144
  /* seed random generator */
145
  unsigned randSeed;
146
147
148
149
150
151
152
153
154
155
156
157
  {
#ifdef USE_MPI
    if (rankGlob == 0)
#endif
      {
        struct timeval tv;
        int status = gettimeofday(&tv, NULL);
        if (status != 0)
          {
            perror("failed seed generation!");
            exit(1);
          }
158
        randSeed = (unsigned)(tv.tv_sec ^ tv.tv_usec);
159
160
161
      }
  }

162
163
  {
    int opt;
164
    while ((opt = getopt(argc, argv, "f:m:n:z:t:y:cs:q:"
165
166
167
168
169
170
171
#ifdef USE_MPI
                         "p:w:"
#endif
                         )) != -1)
      switch (opt) {
#ifdef USE_MPI
      case 'p':
172
173
174
175
176
177
        IOMode = cdiPioStr2IOMode(optarg);
        if (IOMode < 0)
          {
            fprintf(stderr, "Unsupported PIO mode requested: %s\n", optarg);
            exit(EXIT_FAILURE);
          }
178
179
        break;
      case 'w':
180
181
182
183
184
185
186
187
188
        {
          long temp = strtol(optarg, NULL, 0);
          if (temp < 0 || temp > INT_MAX/2)
            {
              fprintf(stderr, "Unsupported number of I/O servers: %ld\n", temp);
              exit(EXIT_FAILURE);
            }
          nProcsIO = (int)temp;
        }
189
190
        break;
#endif
191
192
193
      case 'q':
        parse_long_option(pioConfHandle, optarg);
        break;
194
195
      case 'f':
        {
196
197
          int found = 0;
          for (size_t i = 0;
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
               i < sizeof (suffix2type) / sizeof (suffix2type[0]);
               ++i)
            if (!strcmp(optarg, suffix2type[i].suffix))
              {
                found = 1;
                setup.filetype = suffix2type[i].type;
                setup.suffix = suffix2type[i].suffix;
                setup.datatype = suffix2type[i].defaultDT;
                break;
              }
          if (!found)
            {
              fprintf(stderr, "Unsupported format requested: %s\n", optarg);
              exit(EXIT_FAILURE);
            }
        }
        break;
      case 'm':
        setup.nlon = parse_intarg("error parsing number of longitudes");
        break;
      case 'n':
        setup.nlat = parse_intarg("error parsing number of latitudes");
        break;
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
      case 'y':
        setup.nvars = parse_intarg("error parsing number of variables");
        if (setup.nvars < 1)
          {
            fputs("number of levels must be greater than zero!\n",
                  stderr);
            exit(EXIT_FAILURE);
          }
        if (setup.nvars > 127)
          {
            fputs("number of variables must not exceed 127!\n",
                  stderr);
            exit(EXIT_FAILURE);
          }
        break;
236
237
238
239
240
241
242
243
244
      case 'z':
        setup.max_nlev = parse_intarg("error parsing number of levels");
        if (setup.max_nlev < 1)
          {
            fputs("number of levels must be greater than zero!\n",
                  stderr);
            exit(EXIT_FAILURE);
          }
        break;
245
246
247
      case 't':
        setup.nts = parse_intarg("error parsing number of timesteps");
        break;
248
249
250
      case 'c':
        setup.compute_checksum = 0;
        break;
251
      case 's':
252
        randSeed = parse_unsignedarg("error parsing random seed");
253
        break;
254
255
      default: /* '?' */
        fprintf(stderr, "Usage: %s "
256
                "[-m nlon] [-n nlat] [-z nlev] [-t nts] [-y num_vars]"
257
#ifdef USE_MPI
258
                " [-p PIO_MODE] [-w NIOSERVERS] [-c]"
259
260
261
262
263
264
265
#endif
                "\n", argv[0]);
        exit(EXIT_FAILURE);
      }

  }

266
267
268
269
270
271
272
273
274
#ifdef USE_MPI
  MPI_Bcast(&randSeed, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);
#endif
  srandom(randSeed);
#ifdef USE_MPI
  if (rankGlob == 0)
#endif
    fprintf(stderr, "random seed=%u\n", randSeed);

275
#ifdef USE_MPI
Thomas Jahns's avatar
Thomas Jahns committed
276
  int pioNamespace;
277
278
279
280
281
282
  cdiPioConfSetIOMode(pioConfHandle, IOMode);
  cdiPioConfSetCSRole(pioConfHandle, cdiPioCSRLastN(commGlob, IOMode,
                                                    nProcsIO));
  cdiPioConfSetPartInflate(pioConfHandle, 1.0f);
  int initNamespace = namespaceGetActive();
  commModel = cdiPioInit(commGlob, pioConfHandle, &pioNamespace);
283
284
  if (commModel != MPI_COMM_NULL)
    {
285
      namespaceSetActive(pioNamespace);
286
#else
287
      commModel = -1;
288
289
#endif

290
      modelRun (setup, commModel);
291
292

#ifdef USE_MPI
293
    }
294
295
  namespaceSetActive(initNamespace);
  cdiPioConfDestroy(pioConfHandle);
296
  pioFinalize ();
297
  xt_finalize();
298
299
300
301
302
  MPI_Finalize ();
#endif
  return 0;
}

303

304
305
306
307
308
309
310
311
312
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */