1
/*============================================================================
2
* Base functions for writing Kernel I/O files.
3
*============================================================================*/
6
This file is part of Code_Saturne, a general-purpose CFD tool.
8
Copyright (C) 1998-2011 EDF S.A.
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
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
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.
26
#include "cs_config.h"
28
/*----------------------------------------------------------------------------
29
* Standard C library headers
30
*----------------------------------------------------------------------------*/
38
/*----------------------------------------------------------------------------
40
*----------------------------------------------------------------------------*/
46
/*----------------------------------------------------------------------------
47
* Headers for the current file
48
*----------------------------------------------------------------------------*/
52
/*----------------------------------------------------------------------------*/
57
} /* Fake brace to force Emacs auto-indentation back to column 0 */
59
#endif /* __cplusplus */
61
/*=============================================================================
63
*============================================================================*/
65
/*=============================================================================
66
* Local type definitions
67
*============================================================================*/
69
/*----------------------------------------------------------------------------
70
* Structure defining an output writer
71
*----------------------------------------------------------------------------*/
75
char *name; /* Writer name */
77
ecs_file_t *f; /* Associated file structure pointer */
79
size_t header_size; /* Header default size */
80
size_t header_align; /* Header alignment */
81
size_t body_align; /* Body alignment */
83
size_t cur_pos; /* Current position in file */
87
/*============================================================================
88
* Local function defintions
89
*============================================================================*/
91
/*----------------------------------------------------------------------------
92
* Write padding zeroes to ensure following alignement if necessary
93
*----------------------------------------------------------------------------*/
96
_write_pad(ecs_comm_t *comm,
99
size_t pad_size = (alignment - (comm->cur_pos % alignment)) % alignment;
103
char padding[128] = "";
104
size_t rem_size = pad_size;
106
memset(padding, 0, sizeof(padding));
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;
114
comm->cur_pos += pad_size;
118
/*----------------------------------------------------------------------------
119
* Write a record to the interface file
120
*----------------------------------------------------------------------------*/
123
_write_rec(ecs_comm_t *comm,
130
assert(comm != NULL);
133
/* Determine size associated with type */
136
case ECS_TYPE_ecs_int_t:
137
t_size = sizeof(ecs_int_t);
139
case ECS_TYPE_ecs_coord_t:
140
t_size = sizeof(ecs_coord_t);
142
case ECS_TYPE_ecs_size_t:
143
t_size = sizeof(ecs_size_t);
146
t_size = sizeof(char);
148
case ECS_TYPE_size_t:
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);
159
/* write record to file */
160
/*----------------------*/
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;
167
else { /* if (datatype == ECS_TYPE_size_t && sizeof(size_t) != 8) */
171
assert(sizeof(unsigned long long) == 8);
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);
184
/*----------------------------------------------------------------------------
185
* Open output file and write base file description headers
186
*----------------------------------------------------------------------------*/
189
_file_open(ecs_comm_t *comm,
190
const char *file_name)
192
char header[64] = "";
193
size_t sizes[3] = {comm->header_size,
197
memset(header, 0, 64);
199
/* BE stands for big-endian, allowing for future
200
native file mode generation, using BE/LE */
202
strncpy(header, "Code_Saturne I/O, BE, R0", 63);
206
comm->f = ecs_file_open(file_name,
208
ECS_FILE_TYPE_BINARY);
210
ecs_file_set_big_endian(comm->f);
212
/* Write header and comment information */
214
_write_rec(comm, header, 64, ECS_TYPE_char);
216
memset(header, 0, 64);
217
strncpy(header, "Face-based mesh definition, R0", 63);
219
_write_rec(comm, header, 64, ECS_TYPE_char);
221
_write_rec(comm, sizes, 3, ECS_TYPE_size_t);
224
/*----------------------------------------------------------------------------
225
* Echo section output data
226
*----------------------------------------------------------------------------*/
229
_echo_header(const char *name,
231
const char *datatype_name)
233
char name_pad[33] = "";
234
char type_pad[3] = "";
236
if (strlen(name) < 32) {
237
memset(name_pad, ' ', sizeof(name_pad));
238
name_pad[32 - strlen(name)] = '\0';
240
if (strlen(datatype_name) < 2) {
241
type_pad[0] = ' '; type_pad[1] = ' ';
242
type_pad[2 - strlen(datatype_name)] = '\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);
251
printf(_(" Wrote: \"%s\"\n"),
257
/*============================================================================
258
* Public function definitions
259
*============================================================================*/
262
ecs_comm_initialize(const char *file_name)
264
ecs_comm_t * comm = NULL;
266
/* Create structure */
268
ECS_MALLOC(comm, 1, ecs_comm_t);
270
ECS_MALLOC(comm->name, strlen(file_name) + 1, char);
272
strcpy(comm->name, file_name);
274
/* Initialize other fields */
276
comm->header_size = 96;
277
comm->header_align = 64;
278
comm->body_align = 64;
283
/* Jump a line in log file */
287
/* Info on interface creation */
289
printf(_(" Opening file: %s\n"),
296
/* Create file descriptor */
298
_file_open(comm, file_name);
303
/*----------------------------------------------------------------------------
307
* comm <-- pointer to writer structure pointer
308
*----------------------------------------------------------------------------*/
311
ecs_comm_finalize(ecs_comm_t **comm)
313
ecs_comm_t *_comm = *comm;
317
printf(_(" Closing file: %s\n"),
320
if (_comm->f != NULL)
321
_comm->f = ecs_file_free(_comm->f);
323
ECS_FREE(_comm->name);
330
/*----------------------------------------------------------------------------
331
* Write a section to the Kernel I/O file.
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.
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
*----------------------------------------------------------------------------*/
353
ecs_comm_write_section(const char *name,
357
size_t n_location_values,
360
ecs_type_t value_type,
363
/* Section is defined by:
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
373
size_t header_sizes[6] = {56, /* 6*8 +8 */
379
size_t name_size = 0;
380
size_t name_pad_size = 0;
381
size_t data_size = 0;
382
char datatype_name[8];
385
assert(comm != NULL);
386
assert(name != NULL);
390
memset(datatype_name, 0, sizeof(datatype_name));
391
memset(name_pad, 0, sizeof(name_pad));
395
name_size = strlen(name);
396
name_pad_size = 8-(name_size%8); /* At least 1 NULL
397
character with this rule */
399
header_sizes[0] += (name_size + name_pad_size);
400
header_sizes[5] = (name_size + name_pad_size);
402
/* Value type name */
408
case ECS_TYPE_ecs_int_t:
410
switch(sizeof(ecs_int_t)) {
412
strcpy(datatype_name, "i4");
415
strcpy(datatype_name, "i8");
418
assert(sizeof(ecs_int_t) == 4 || sizeof(ecs_int_t) == 8);
422
case ECS_TYPE_ecs_coord_t:
424
switch(sizeof(ecs_coord_t)) {
426
strcpy(datatype_name, "r4");
429
strcpy(datatype_name, "r8");
432
assert(sizeof(ecs_coord_t) == 4 || sizeof(ecs_coord_t) == 8);
436
case ECS_TYPE_ecs_size_t:
438
switch(sizeof(ecs_size_t)) {
440
strcpy(datatype_name, "u4");
443
strcpy(datatype_name, "u8");
446
assert(sizeof(ecs_size_t) == 4 || sizeof(ecs_size_t) == 8);
450
case ECS_TYPE_size_t:
452
strcpy(datatype_name, "u8");
457
strcpy(datatype_name, "c ");
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);
469
} /* End of switch on value_type */
475
datatype_name[7] = 'e';
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;
482
data_size = n_values;
484
header_sizes[0] += data_size;
488
/* Only output data if file exists */
490
if (comm->f != NULL) {
492
/* Align if necessary */
494
_write_pad(comm, comm->header_align);
498
_write_rec(comm, header_sizes, 6, ECS_TYPE_size_t);
500
/* Type information */
502
_write_rec(comm, datatype_name, 8, ECS_TYPE_char);
506
_write_rec(comm, name, name_size, ECS_TYPE_char);
507
_write_rec(comm, name_pad, name_pad_size, ECS_TYPE_char);
509
/* Embedded values */
511
if (n_values > 0 && embed == true)
512
_write_rec(comm, values, n_values, value_type);
514
/* Ensure header is at least the size of the basic header block size,
515
as reads may read at least this much data */
517
if (header_sizes[0] < comm->header_size) {
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;
529
/* If values are not embedded, handle separate value block */
531
if (n_values > 0 && embed == false) {
533
_write_pad(comm, comm->body_align);
534
_write_rec(comm, values, n_values, value_type);
542
_echo_header(name, n_values, datatype_name);
545
/*----------------------------------------------------------------------------*/
549
#endif /* __cplusplus */