~ubuntu-branches/ubuntu/precise/code-saturne/precise

« back to all changes in this revision

Viewing changes to preprocessor/util/ecs_comm.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2011-11-24 00:00:08 UTC
  • mfrom: (6.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20111124000008-2vo99e38267942q5
Tags: 2.1.0-3
Install a missing file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*============================================================================
 
2
 * Base functions for writing Kernel I/O files.
 
3
 *============================================================================*/
 
4
 
 
5
/*
 
6
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
7
 
 
8
  Copyright (C) 1998-2011 EDF S.A.
 
9
 
 
10
  This program is free software; you can redistribute it and/or modify it under
 
11
  the terms of the GNU General Public License as published by the Free Software
 
12
  Foundation; either version 2 of the License, or (at your option) any later
 
13
  version.
 
14
 
 
15
  This program is distributed in the hope that it will be useful, but WITHOUT
 
16
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
17
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
18
  details.
 
19
 
 
20
  You should have received a copy of the GNU General Public License along with
 
21
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
22
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
23
*/
 
24
 
 
25
 
 
26
#include "cs_config.h"
 
27
 
 
28
/*----------------------------------------------------------------------------
 
29
 * Standard C library headers
 
30
 *----------------------------------------------------------------------------*/
 
31
 
 
32
#include <assert.h>
 
33
#include <errno.h>
 
34
#include <stdio.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
 
 
38
/*----------------------------------------------------------------------------
 
39
 *  Local headers
 
40
 *----------------------------------------------------------------------------*/
 
41
 
 
42
#include "ecs_def.h"
 
43
#include "ecs_file.h"
 
44
#include "ecs_mem.h"
 
45
 
 
46
/*----------------------------------------------------------------------------
 
47
 *  Headers for the current file
 
48
 *----------------------------------------------------------------------------*/
 
49
 
 
50
#include "ecs_comm.h"
 
51
 
 
52
/*----------------------------------------------------------------------------*/
 
53
 
 
54
#ifdef __cplusplus
 
55
extern "C" {
 
56
#if 0
 
57
} /* Fake brace to force Emacs auto-indentation back to column 0 */
 
58
#endif
 
59
#endif /* __cplusplus */
 
60
 
 
61
/*=============================================================================
 
62
 * Macro definitions
 
63
 *============================================================================*/
 
64
 
 
65
/*=============================================================================
 
66
 * Local type definitions
 
67
 *============================================================================*/
 
68
 
 
69
/*----------------------------------------------------------------------------
 
70
 * Structure defining an output writer
 
71
 *----------------------------------------------------------------------------*/
 
72
 
 
73
struct _ecs_comm_t {
 
74
 
 
75
  char           *name;             /* Writer name */
 
76
 
 
77
  ecs_file_t     *f;                /* Associated file structure pointer */
 
78
 
 
79
  size_t          header_size;      /* Header default size */
 
80
  size_t          header_align;     /* Header alignment */
 
81
  size_t          body_align;       /* Body alignment */
 
82
 
 
83
  size_t          cur_pos;          /* Current position in file */
 
84
 
 
85
};
 
86
 
 
87
/*============================================================================
 
88
 * Local function defintions
 
89
 *============================================================================*/
 
90
 
 
91
/*----------------------------------------------------------------------------
 
92
 * Write padding zeroes to ensure following alignement if necessary
 
93
 *----------------------------------------------------------------------------*/
 
94
 
 
95
static void
 
96
_write_pad(ecs_comm_t  *comm,
 
97
           size_t       alignment)
 
98
{
 
99
  size_t pad_size = (alignment - (comm->cur_pos % alignment)) % alignment;
 
100
 
 
101
  if (pad_size > 0) {
 
102
 
 
103
    char padding[128] = "";
 
104
    size_t rem_size = pad_size;
 
105
 
 
106
    memset(padding, 0, sizeof(padding));
 
107
 
 
108
    while (rem_size > 0) {
 
109
      size_t write_size = ECS_MIN(rem_size, sizeof(padding));
 
110
      ecs_file_write(padding, 1, write_size, comm->f);
 
111
      rem_size -= write_size;
 
112
    }
 
113
 
 
114
    comm->cur_pos += pad_size;
 
115
  }
 
116
}
 
117
 
 
118
/*----------------------------------------------------------------------------
 
119
 * Write a record to the interface file
 
120
 *----------------------------------------------------------------------------*/
 
121
 
 
122
static void
 
123
_write_rec(ecs_comm_t  *comm,
 
124
           const void  *rec,
 
125
           size_t       n_elts,
 
126
           ecs_type_t   datatype)
 
127
{
 
128
  size_t t_size = 0;
 
129
 
 
130
  assert(comm != NULL);
 
131
  assert(rec  != NULL);
 
132
 
 
133
  /* Determine size associated with type */
 
134
 
 
135
  switch (datatype) {
 
136
  case ECS_TYPE_ecs_int_t:
 
137
    t_size = sizeof(ecs_int_t);
 
138
    break;
 
139
  case ECS_TYPE_ecs_coord_t:
 
140
    t_size = sizeof(ecs_coord_t);
 
141
    break;
 
142
  case ECS_TYPE_ecs_size_t:
 
143
    t_size = sizeof(ecs_size_t);
 
144
    break;
 
145
  case ECS_TYPE_char:
 
146
    t_size = sizeof(char);
 
147
    break;
 
148
  case ECS_TYPE_size_t:
 
149
    t_size = 8;
 
150
    break;
 
151
  default:
 
152
    assert(   datatype == ECS_TYPE_ecs_int_t
 
153
           || datatype == ECS_TYPE_ecs_coord_t
 
154
           || datatype == ECS_TYPE_ecs_size_t
 
155
           || datatype == ECS_TYPE_size_t
 
156
           || datatype == ECS_TYPE_char);
 
157
  }
 
158
 
 
159
  /* write record to file */
 
160
  /*----------------------*/
 
161
 
 
162
  if (datatype != ECS_TYPE_size_t || sizeof(size_t) == 8) {
 
163
    ecs_file_write(rec, t_size, n_elts, comm->f);
 
164
    comm->cur_pos += n_elts*t_size;
 
165
  }
 
166
 
 
167
  else { /* if (datatype == ECS_TYPE_size_t && sizeof(size_t) != 8) */
 
168
 
 
169
    size_t i;
 
170
 
 
171
    assert(sizeof(unsigned long long) == 8);
 
172
 
 
173
    for (i = 0; i < n_elts; i++) {
 
174
      const unsigned char *rp = rec;
 
175
      unsigned long long _rec = *((const size_t *)(rp + i*sizeof(size_t)));
 
176
      assert(sizeof(long long) == 8);
 
177
      ecs_file_write(&_rec, 8, 1, comm->f);
 
178
      comm->cur_pos += 8;
 
179
    }
 
180
 
 
181
  }
 
182
}
 
183
 
 
184
/*----------------------------------------------------------------------------
 
185
 * Open output file and write base file description headers
 
186
 *----------------------------------------------------------------------------*/
 
187
 
 
188
static void
 
189
_file_open(ecs_comm_t  *comm,
 
190
           const char  *file_name)
 
191
{
 
192
  char header[64] = "";
 
193
  size_t sizes[3] = {comm->header_size,
 
194
                     comm->header_align,
 
195
                     comm->body_align};
 
196
 
 
197
  memset(header, 0, 64);
 
198
 
 
199
  /* BE stands for big-endian, allowing for future
 
200
     native file mode generation, using BE/LE */
 
201
 
 
202
  strncpy(header, "Code_Saturne I/O, BE, R0", 63);
 
203
 
 
204
  /* Open file */
 
205
 
 
206
  comm->f = ecs_file_open(file_name,
 
207
                          ECS_FILE_MODE_WRITE,
 
208
                          ECS_FILE_TYPE_BINARY);
 
209
 
 
210
  ecs_file_set_big_endian(comm->f);
 
211
 
 
212
  /* Write header and comment information */
 
213
 
 
214
  _write_rec(comm, header, 64, ECS_TYPE_char);
 
215
 
 
216
  memset(header, 0, 64);
 
217
  strncpy(header, "Face-based mesh definition, R0", 63);
 
218
 
 
219
  _write_rec(comm, header, 64, ECS_TYPE_char);
 
220
 
 
221
  _write_rec(comm, sizes, 3, ECS_TYPE_size_t);
 
222
}
 
223
 
 
224
/*----------------------------------------------------------------------------
 
225
 * Echo section output data
 
226
 *----------------------------------------------------------------------------*/
 
227
 
 
228
static void
 
229
_echo_header(const char   *name,
 
230
             size_t        n_values,
 
231
             const char   *datatype_name)
 
232
{
 
233
  char name_pad[33] = "";
 
234
  char type_pad[3] = "";
 
235
 
 
236
  if (strlen(name) < 32) {
 
237
    memset(name_pad, ' ', sizeof(name_pad));
 
238
    name_pad[32 - strlen(name)] = '\0';
 
239
  }
 
240
  if (strlen(datatype_name) < 2) {
 
241
    type_pad[0] = ' '; type_pad[1] = ' ';
 
242
    type_pad[2 - strlen(datatype_name)] = '\0';
 
243
  }
 
244
 
 
245
  if (n_values > 0)
 
246
    printf(_("  Wrote: \"%s\"%s; Type: \"%s\"%s; Size: %lu\n"),
 
247
           name, name_pad, datatype_name, type_pad,
 
248
           (unsigned long)n_values);
 
249
 
 
250
  else
 
251
    printf(_("  Wrote: \"%s\"\n"),
 
252
           name);
 
253
 
 
254
  fflush(stdout);
 
255
}
 
256
 
 
257
/*============================================================================
 
258
 * Public function definitions
 
259
 *============================================================================*/
 
260
 
 
261
ecs_comm_t *
 
262
ecs_comm_initialize(const char  *file_name)
 
263
{
 
264
  ecs_comm_t  * comm = NULL;
 
265
 
 
266
  /* Create structure */
 
267
 
 
268
  ECS_MALLOC(comm, 1, ecs_comm_t);
 
269
 
 
270
  ECS_MALLOC(comm->name, strlen(file_name) + 1, char);
 
271
 
 
272
  strcpy(comm->name, file_name);
 
273
 
 
274
  /* Initialize other fields */
 
275
 
 
276
  comm->header_size = 96;
 
277
  comm->header_align = 64;
 
278
  comm->body_align = 64;
 
279
  comm->cur_pos = 0;
 
280
 
 
281
  comm->f  = NULL;
 
282
 
 
283
  /* Jump a line in log file */
 
284
 
 
285
  printf("\n");
 
286
 
 
287
  /* Info on interface creation */
 
288
 
 
289
  printf(_("  Opening file: %s\n"),
 
290
         comm->name);
 
291
 
 
292
  printf("\n");
 
293
 
 
294
  fflush(stdout);
 
295
 
 
296
  /* Create file descriptor */
 
297
 
 
298
  _file_open(comm, file_name);
 
299
 
 
300
  return comm;
 
301
}
 
302
 
 
303
/*----------------------------------------------------------------------------
 
304
 * Close writer.
 
305
 *
 
306
 * arguments:
 
307
 *   comm <-- pointer to writer structure pointer
 
308
 *----------------------------------------------------------------------------*/
 
309
 
 
310
void
 
311
ecs_comm_finalize(ecs_comm_t **comm)
 
312
{
 
313
  ecs_comm_t *_comm = *comm;
 
314
 
 
315
  printf("\n");
 
316
 
 
317
  printf(_("  Closing file: %s\n"),
 
318
         _comm->name);
 
319
 
 
320
  if (_comm->f != NULL)
 
321
    _comm->f = ecs_file_free(_comm->f);
 
322
 
 
323
  ECS_FREE(_comm->name);
 
324
 
 
325
  ECS_FREE(_comm);
 
326
 
 
327
  *comm = _comm;
 
328
}
 
329
 
 
330
/*----------------------------------------------------------------------------
 
331
 * Write a section to the Kernel I/O file.
 
332
 *
 
333
 * Grid locations and possibly indexes may be assigned to a section by
 
334
 * specifying a location id; the first time a given location id appears in
 
335
 * the file is considered a declaration. In the same manner, an index id
 
336
 * may be specified. Values of zero indicate no location or index base
 
337
 * is used. It is up to the calling code to ensure that total number of
 
338
 * values, location size, and number of values per location are consistent,
 
339
 * as this my be important for code reading the file.
 
340
 *
 
341
 * arguments:
 
342
 *   name              <-- section name
 
343
 *   location_id       <-- id of associated location
 
344
 *   index_id          <-- id of associated index
 
345
 *   n_location_values <-- number of values per location
 
346
 *   embed             <-- embed values in header
 
347
 *   values            <-- values to write
 
348
 *   value_type        <-- type of value to write
 
349
 *   comm              <-- Kernel I/O file output structure
 
350
 *----------------------------------------------------------------------------*/
 
351
 
 
352
void
 
353
ecs_comm_write_section(const char  *name,
 
354
                       size_t       n_values,
 
355
                       size_t       location_id,
 
356
                       size_t       index_id,
 
357
                       size_t       n_location_values,
 
358
                       bool         embed,
 
359
                       const void  *values,
 
360
                       ecs_type_t   value_type,
 
361
                       ecs_comm_t  *comm)
 
362
{
 
363
  /* Section is defined by:
 
364
 
 
365
     section size (in bytes): 8 bytes
 
366
     n_elts, location_id, index_id, n_location_values: 4*8 bytes
 
367
     name_size (including padding to 8 byte alignment): 8 bytes
 
368
     datatype_name: 8 bytes (bit 6 = '\0', bit 7 = embed flag)
 
369
     section name: strlen(name) + 1 + padding to 8 bytes
 
370
     optional embedded data: n_values*value_type_size
 
371
  */
 
372
 
 
373
  size_t header_sizes[6] = {56,       /* 6*8 +8 */
 
374
                            n_values,
 
375
                            location_id,
 
376
                            index_id,
 
377
                            n_location_values,
 
378
                            0};
 
379
  size_t name_size = 0;
 
380
  size_t name_pad_size = 0;
 
381
  size_t data_size = 0;
 
382
  char   datatype_name[8];
 
383
  char   name_pad[8];
 
384
 
 
385
  assert(comm != NULL);
 
386
  assert(name != NULL);
 
387
 
 
388
  /* Initialization */
 
389
 
 
390
  memset(datatype_name, 0, sizeof(datatype_name));
 
391
  memset(name_pad, 0, sizeof(name_pad));
 
392
 
 
393
  /* Section name */
 
394
 
 
395
  name_size = strlen(name);
 
396
  name_pad_size = 8-(name_size%8); /* At least 1 NULL
 
397
                                      character with this rule */
 
398
 
 
399
  header_sizes[0] += (name_size + name_pad_size);
 
400
  header_sizes[5] = (name_size + name_pad_size);
 
401
 
 
402
  /* Value type name */
 
403
 
 
404
  if (n_values > 0) {
 
405
 
 
406
    switch(value_type) {
 
407
 
 
408
    case ECS_TYPE_ecs_int_t:
 
409
 
 
410
      switch(sizeof(ecs_int_t)) {
 
411
      case 4:
 
412
        strcpy(datatype_name, "i4");
 
413
        break;
 
414
      case 8:
 
415
        strcpy(datatype_name, "i8");
 
416
        break;
 
417
      default:
 
418
        assert(sizeof(ecs_int_t) == 4 || sizeof(ecs_int_t) == 8);
 
419
      }
 
420
      break;
 
421
 
 
422
    case ECS_TYPE_ecs_coord_t:
 
423
 
 
424
      switch(sizeof(ecs_coord_t)) {
 
425
      case 4:
 
426
        strcpy(datatype_name, "r4");
 
427
        break;
 
428
      case 8:
 
429
        strcpy(datatype_name, "r8");
 
430
        break;
 
431
      default:
 
432
        assert(sizeof(ecs_coord_t) == 4 || sizeof(ecs_coord_t) == 8);
 
433
      }
 
434
      break;
 
435
 
 
436
    case ECS_TYPE_ecs_size_t:
 
437
 
 
438
      switch(sizeof(ecs_size_t)) {
 
439
      case 4:
 
440
        strcpy(datatype_name, "u4");
 
441
        break;
 
442
      case 8:
 
443
        strcpy(datatype_name, "u8");
 
444
        break;
 
445
      default:
 
446
        assert(sizeof(ecs_size_t) == 4 || sizeof(ecs_size_t) == 8);
 
447
      }
 
448
      break;
 
449
 
 
450
    case ECS_TYPE_size_t:
 
451
 
 
452
      strcpy(datatype_name, "u8");
 
453
      break;
 
454
 
 
455
    case ECS_TYPE_char:
 
456
 
 
457
      strcpy(datatype_name, "c ");
 
458
      break;
 
459
 
 
460
    default:
 
461
 
 
462
      assert(   value_type == ECS_TYPE_ecs_int_t
 
463
             || value_type == ECS_TYPE_ecs_coord_t
 
464
             || value_type == ECS_TYPE_ecs_size_t
 
465
             || value_type == ECS_TYPE_size_t
 
466
             || value_type == ECS_TYPE_char);
 
467
 
 
468
 
 
469
    } /* End of switch on value_type */
 
470
 
 
471
  }
 
472
 
 
473
  if (embed == true) {
 
474
 
 
475
    datatype_name[7] = 'e';
 
476
 
 
477
    if (datatype_name[1] == '4')
 
478
      data_size = 4*n_values;
 
479
    else if (datatype_name[1] == '8')
 
480
      data_size = 8*n_values;
 
481
    else
 
482
      data_size = n_values;
 
483
 
 
484
    header_sizes[0] += data_size;
 
485
 
 
486
  }
 
487
 
 
488
  /* Only output data if file exists */
 
489
 
 
490
  if (comm->f != NULL) {
 
491
 
 
492
    /* Align if necessary */
 
493
 
 
494
    _write_pad(comm, comm->header_align);
 
495
 
 
496
    /* Write sizes */
 
497
 
 
498
    _write_rec(comm, header_sizes, 6, ECS_TYPE_size_t);
 
499
 
 
500
    /* Type information */
 
501
 
 
502
    _write_rec(comm, datatype_name, 8, ECS_TYPE_char);
 
503
 
 
504
    /* Section name */
 
505
 
 
506
    _write_rec(comm, name, name_size, ECS_TYPE_char);
 
507
    _write_rec(comm, name_pad, name_pad_size, ECS_TYPE_char);
 
508
 
 
509
    /* Embedded values */
 
510
 
 
511
    if (n_values > 0 && embed == true)
 
512
      _write_rec(comm, values, n_values, value_type);
 
513
 
 
514
    /* Ensure header is at least the size of the basic header block size,
 
515
       as reads may read at least this much data */
 
516
 
 
517
    if (header_sizes[0] < comm->header_size) {
 
518
      char   header_pad[64];
 
519
      size_t header_pad_size = comm->header_size - header_sizes[0];
 
520
      memset(header_pad, 0, sizeof(header_pad));
 
521
      while (header_pad_size > 0) {
 
522
        size_t write_size = ECS_MIN(header_pad_size, sizeof(header_pad));
 
523
        ecs_file_write(header_pad, 1, write_size, comm->f);
 
524
        header_pad_size -= write_size;
 
525
        comm->cur_pos += write_size;
 
526
      }
 
527
    }
 
528
 
 
529
    /* If values are not embedded, handle separate value block */
 
530
 
 
531
    if (n_values > 0 && embed == false) {
 
532
 
 
533
      _write_pad(comm, comm->body_align);
 
534
      _write_rec(comm, values, n_values, value_type);
 
535
 
 
536
    }
 
537
 
 
538
  }
 
539
 
 
540
  /* Print message */
 
541
 
 
542
  _echo_header(name, n_values, datatype_name);
 
543
}
 
544
 
 
545
/*----------------------------------------------------------------------------*/
 
546
 
 
547
#ifdef __cplusplus
 
548
}
 
549
#endif /* __cplusplus */
 
550