1 /*============================================================================
2 * Handle export of mesh and fields.
3 *============================================================================*/
4
5 /*
6 This file is part of Code_Saturne, a general-purpose CFD tool.
7
8 Copyright (C) 1998-2021 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
27 #include "cs_defs.h"
28
29 /*----------------------------------------------------------------------------
30 * Standard C library headers
31 *----------------------------------------------------------------------------*/
32
33 #include <assert.h>
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #if defined(HAVE_DLOPEN)
40 #include <dlfcn.h>
41 #endif
42
43 /*----------------------------------------------------------------------------
44 * Local headers
45 *----------------------------------------------------------------------------*/
46
47 #include "bft_mem.h"
48 #include "bft_error.h"
49 #include "bft_printf.h"
50
51 #include "fvm_nodal.h"
52 #include "fvm_nodal_priv.h"
53
54 #include "cs_base.h"
55 #include "cs_file.h"
56 #include "cs_fp_exception.h"
57 #include "cs_timer.h"
58
59 /*----------------------------------------------------------------------------
60 * Header for the current file
61 *----------------------------------------------------------------------------*/
62
63 #include "fvm_writer.h"
64 #include "fvm_writer_priv.h"
65
66 /* Headers for available writers (could be replaced by plugin system) */
67
68 #include "fvm_to_ccm.h"
69 #include "fvm_to_cgns.h"
70 #include "fvm_to_med.h"
71 #include "fvm_to_ensight.h"
72 #include "fvm_to_histogram.h"
73 #include "fvm_to_plot.h"
74 #include "fvm_to_time_plot.h"
75
76 #if defined(HAVE_CATALYST) && !defined(HAVE_PLUGIN_CATALYST)
77 #include "fvm_to_catalyst.h"
78 #endif
79
80 #if defined(HAVE_MELISSA) && !defined(HAVE_PLUGIN_MELISSA)
81 #include "fvm_to_melissa.h"
82 #endif
83
84 /*----------------------------------------------------------------------------*/
85
86 BEGIN_C_DECLS
87
88 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
89
90 /*============================================================================
91 * Local Type Definitions
92 *============================================================================*/
93
94 /*============================================================================
95 * Local macro definitions
96 *============================================================================*/
97
98 /* Directory name separator
99 (historically, '/' for Unix/Linux, '\' for Windows, ':' for Mac
100 but '/' should work for all on modern systems) */
101
102 #define DIR_SEPARATOR '/'
103
104 /*============================================================================
105 * Static and constant variables
106 *============================================================================*/
107
108 /* Number and status of defined formats */
109
110 static const int _fvm_writer_n_formats = 10;
111
112 static fvm_writer_format_t _fvm_writer_format_list[10] = {
113
114 /* Built-in EnSight Gold writer */
115 {
116 "EnSight Gold",
117 "7.4 +",
118 ( FVM_WRITER_FORMAT_HAS_POLYGON
119 | FVM_WRITER_FORMAT_HAS_POLYHEDRON),
120 FVM_WRITER_TRANSIENT_CONNECT,
121 0, /* dynamic library count */
122 NULL, /* dynamic library */
123 NULL, /* dynamic library name */
124 NULL, /* dynamic library prefix */
125 NULL, /* n_version_strings_func */
126 NULL, /* version_string_func */
127 fvm_to_ensight_init_writer, /* init_func */
128 fvm_to_ensight_finalize_writer, /* finalize_func */
129 fvm_to_ensight_set_mesh_time, /* set_mesh_time_func */
130 fvm_to_ensight_needs_tesselation, /* needs_tesselation_func */
131 fvm_to_ensight_export_nodal, /* export_nodal_func */
132 fvm_to_ensight_export_field, /* export_field_func */
133 NULL /* flush_func */
134 },
135
136 /* MED writer */
137 {
138 "MED",
139 "3.0 +",
140 ( FVM_WRITER_FORMAT_USE_EXTERNAL
141 | FVM_WRITER_FORMAT_HAS_POLYGON
142 | FVM_WRITER_FORMAT_HAS_POLYHEDRON),
143 FVM_WRITER_FIXED_MESH,
144 0, /* dynamic library count */
145 NULL, /* dynamic library */
146 NULL, /* dynamic library name */
147 NULL, /* dynamic library prefix */
148 #if defined(HAVE_MED)
149 fvm_to_med_n_version_strings, /* n_version_strings_func */
150 fvm_to_med_version_string, /* version_string_func */
151 fvm_to_med_init_writer, /* init_func */
152 fvm_to_med_finalize_writer, /* finalize_func */
153 fvm_to_med_set_mesh_time, /* set_mesh_time_func */
154 fvm_to_med_needs_tesselation, /* needs_tesselation_func */
155 fvm_to_med_export_nodal, /* export_nodal_func */
156 fvm_to_med_export_field, /* export_field_func */
157 NULL /* flush_func */
158 #else
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL
168 #endif
169 },
170
171 /* CGNS writer */
172 {
173 "CGNS",
174 "3.1 +",
175 ( FVM_WRITER_FORMAT_USE_EXTERNAL
176 | FVM_WRITER_FORMAT_HAS_POLYGON),
177 FVM_WRITER_TRANSIENT_COORDS,
178 0, /* dynamic library count */
179 NULL, /* dynamic library */
180 NULL, /* dynamic library name */
181 NULL, /* dynamic library prefix */
182 #if defined(HAVE_CGNS)
183 fvm_to_cgns_n_version_strings, /* n_version_strings_func */
184 fvm_to_cgns_version_string, /* version_string_func */
185 fvm_to_cgns_init_writer, /* init_func */
186 fvm_to_cgns_finalize_writer, /* finalize_func */
187 fvm_to_cgns_set_mesh_time, /* set_mesh_time_func */
188 fvm_to_cgns_needs_tesselation, /* needs_tesselation_func */
189 fvm_to_cgns_export_nodal, /* export_nodal_func */
190 fvm_to_cgns_export_field, /* export_field_func */
191 NULL /* flush_func */
192 #else
193 NULL,
194 NULL,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 NULL,
201 NULL
202 #endif
203 },
204
205 /* Catalyst (VTK) writer (plugin) */
206 {
207 "Catalyst",
208 "4.2 +",
209 ( FVM_WRITER_FORMAT_USE_EXTERNAL
210 | FVM_WRITER_FORMAT_HAS_POLYGON
211 | FVM_WRITER_FORMAT_HAS_POLYHEDRON
212 | FVM_WRITER_FORMAT_NO_SEPARATE_MESHES),
213 FVM_WRITER_TRANSIENT_CONNECT,
214 #if !defined(HAVE_CATALYST) || defined(HAVE_PLUGIN_CATALYST)
215 0, /* dynamic library count */
216 NULL, /* dynamic library */
217 #if defined(HAVE_CATALYST)
218 "fvm_catalyst", /* dynamic library name */
219 "fvm_to_catalyst_", /* dynamic library prefix */
220 #else
221 NULL,
222 NULL,
223 #endif
224 NULL,
225 NULL,
226 NULL,
227 NULL,
228 NULL,
229 NULL,
230 NULL,
231 NULL,
232 NULL
233 #else
234 0, /* dynamic library count */
235 NULL, /* dynamic library */
236 NULL, /* dynamic library name */
237 NULL, /* dynamic library prefix */
238 NULL, /* n_version_strings_func */
239 NULL, /* version_string_func */
240 fvm_to_catalyst_init_writer, /* init_func */
241 fvm_to_catalyst_finalize_writer, /* finalize_func */
242 fvm_to_catalyst_set_mesh_time, /* set_mesh_time_func */
243 NULL, /* needs_tesselation_func */
244 fvm_to_catalyst_export_nodal, /* export_nodal_func */
245 fvm_to_catalyst_export_field, /* export_field_func */
246 fvm_to_catalyst_flush /* flush_func */
247 #endif
248 },
249
250 /* MEDCoupling writer (plugin) */
251 {
252 "MEDCoupling",
253 "6.3 +",
254 ( FVM_WRITER_FORMAT_USE_EXTERNAL
255 | FVM_WRITER_FORMAT_HAS_POLYGON),
256 FVM_WRITER_TRANSIENT_CONNECT,
257 0, /* dynamic library count */
258 NULL, /* dynamic library */
259 #if defined(HAVE_MEDCOUPLING)
260 "fvm_medcoupling", /* dynamic library name */
261 "fvm_to_medcoupling_", /* dynamic library prefix */
262 #else
263 NULL,
264 NULL,
265 #endif
266 NULL,
267 NULL,
268 NULL,
269 NULL,
270 NULL,
271 NULL,
272 NULL,
273 NULL,
274 NULL
275 },
276
277 /* Built-in Melissa writer */
278 {
279 "Melissa",
280 "",
281 ( FVM_WRITER_FORMAT_USE_EXTERNAL
282 | FVM_WRITER_FORMAT_HAS_POLYGON
283 | FVM_WRITER_FORMAT_HAS_POLYHEDRON),
284 FVM_WRITER_TRANSIENT_COORDS,
285 #if !defined(HAVE_MELISSA) || defined(HAVE_PLUGIN_MELISSA)
286 0, /* dynamic library count */
287 NULL, /* dynamic library */
288 #if defined(HAVE_MELISSA)
289 "fvm_melissa", /* dynamic library name */
290 "fvm_to_melissa_", /* dynamic library prefix */
291 #else
292 NULL,
293 NULL,
294 #endif
295 NULL,
296 NULL,
297 NULL,
298 NULL,
299 NULL,
300 NULL,
301 NULL,
302 NULL,
303 NULL
304 #else
305 0, /* dynamic library count */
306 NULL, /* dynamic library */
307 NULL, /* dynamic library name */
308 NULL, /* dynamic library prefix */
309 NULL, /* n_version_strings_func */
310 NULL, /* version_string_func */
311 fvm_to_melissa_init_writer, /* init_func */
312 fvm_to_melissa_finalize_writer, /* finalize_func */
313 fvm_to_melissa_set_mesh_time, /* set_mesh_time_func */
314 NULL, /* needs_tesselation_func */
315 fvm_to_melissa_export_nodal, /* export_nodal_func */
316 fvm_to_melissa_export_field, /* export_field_func */
317 NULL /* flush_func */
318 #endif
319 },
320
321 /* Built-in histogram writer */
322 {
323 "histogram",
324 "",
325 ( FVM_WRITER_FORMAT_HAS_POLYGON
326 | FVM_WRITER_FORMAT_HAS_POLYHEDRON
327 | FVM_WRITER_FORMAT_SEPARATE_MESHES
328 | FVM_WRITER_FORMAT_NAME_IS_OPTIONAL),
329 FVM_WRITER_TRANSIENT_CONNECT,
330 0, /* dynamic library count */
331 NULL, /* dynamic library */
332 NULL, /* dynamic library name */
333 NULL, /* dynamic library prefix */
334 NULL, /* n_version_strings_func */
335 NULL, /* version_string_func */
336 fvm_to_histogram_init_writer, /* init_func */
337 fvm_to_histogram_finalize_writer, /* finalize_func */
338 fvm_to_histogram_set_mesh_time, /* set_mesh_time_func */
339 NULL, /* needs_tesselation_func */
340 NULL, /* export_nodal_func */
341 fvm_to_histogram_export_field, /* export_field_func */
342 fvm_to_histogram_flush /* flush_func */
343 },
344
345 /* Built-in plot writer */
346 {
347 "plot",
348 "",
349 ( FVM_WRITER_FORMAT_HAS_POLYGON
350 | FVM_WRITER_FORMAT_HAS_POLYHEDRON
351 | FVM_WRITER_FORMAT_SEPARATE_MESHES
352 | FVM_WRITER_FORMAT_NAME_IS_OPTIONAL),
353 FVM_WRITER_TRANSIENT_CONNECT,
354 0, /* dynamic library count */
355 NULL, /* dynamic library */
356 NULL, /* dynamic library name */
357 NULL, /* dynamic library prefix */
358 NULL, /* n_version_strings_func */
359 NULL, /* version_string_func */
360 fvm_to_plot_init_writer, /* init_func */
361 fvm_to_plot_finalize_writer, /* finalize_func */
362 fvm_to_plot_set_mesh_time, /* set_mesh_time_func */
363 NULL, /* needs_tesselation_func */
364 fvm_to_plot_export_nodal, /* export_nodal_func */
365 fvm_to_plot_export_field, /* export_field_func */
366 fvm_to_plot_flush /* flush_func */
367 },
368
369 /* Built-in time plot writer */
370 {
371 "time_plot",
372 "",
373 ( FVM_WRITER_FORMAT_HAS_POLYGON
374 | FVM_WRITER_FORMAT_HAS_POLYHEDRON
375 | FVM_WRITER_FORMAT_SEPARATE_MESHES
376 | FVM_WRITER_FORMAT_NAME_IS_OPTIONAL),
377 FVM_WRITER_FIXED_MESH,
378 0, /* dynamic library count */
379 NULL, /* dynamic library */
380 NULL, /* dynamic library name */
381 NULL, /* dynamic library prefix */
382 NULL, /* n_version_strings_func */
383 NULL, /* version_string_func */
384 fvm_to_time_plot_init_writer, /* init_func */
385 fvm_to_time_plot_finalize_writer, /* finalize_func */
386 fvm_to_time_plot_set_mesh_time, /* set_mesh_time_func */
387 NULL, /* needs_tesselation_func */
388 fvm_to_time_plot_export_nodal, /* export_nodal_func */
389 fvm_to_time_plot_export_field, /* export_field_func */
390 NULL /* flush_func */
391 },
392
393 /* CCM-IO writer */
394 {
395 "CCM-IO",
396 "2.6.1+",
397 ( FVM_WRITER_FORMAT_USE_EXTERNAL
398 | FVM_WRITER_FORMAT_HAS_POLYGON
399 | FVM_WRITER_FORMAT_HAS_POLYHEDRON),
400 FVM_WRITER_FIXED_MESH,
401 0, /* dynamic library count */
402 NULL, /* dynamic library */
403 NULL, /* dynamic library name */
404 NULL, /* dynamic library prefix */
405 #if defined(HAVE_CCM)
406 fvm_to_ccm_n_version_strings, /* n_version_strings_func */
407 fvm_to_ccm_version_string, /* version_string_func */
408 fvm_to_ccm_init_writer, /* init_func */
409 fvm_to_ccm_finalize_writer, /* finalize_func */
410 fvm_to_ccm_set_mesh_time, /* set_mesh_time_func */
411 NULL, /* needs_tesselation_func */
412 fvm_to_ccm_export_nodal, /* export_nodal_func */
413 fvm_to_ccm_export_field, /* export_field_func */
414 NULL /* flush_func */
415 #else
416 NULL,
417 NULL,
418 NULL,
419 NULL,
420 NULL,
421 NULL,
422 NULL,
423 NULL,
424 NULL
425 #endif
426 }
427
428 };
429
430 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
431
432 /*============================================================================
433 * Static global variables
434 *============================================================================*/
435
436 /* Names of time dependency enumeration values */
437
438 const char *fvm_writer_time_dep_name[] = {N_("fixed mesh"),
439 N_("transient coordinates"),
440 N_("transient connectivity")};
441
442 const char _empty_string[] = "";
443
444 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
445
446 /*============================================================================
447 * Private function definitions
448 *============================================================================*/
449
450 /*----------------------------------------------------------------------------
451 * Transform a string containing a list of options to lowercase with
452 * whitespace separators.
453 * The new list is dynamically allocated, and should be freed when no
454 * longer needed.
455 *
456 * parameters:
457 * option_list <-- options string (case-independent, whitespace,
458 * semicolon, or comma separated list)
459 *
460 * returns:
461 * single-whitespace separated option string in lowercase.
462 *----------------------------------------------------------------------------*/
463
464 static char *
_fvm_writer_option_list(const char * const option_list)465 _fvm_writer_option_list(const char *const option_list)
466 {
467 char *ret_list;
468 int i, j, l;
469
470 if (option_list == NULL)
471 return NULL;
472
473 l = strlen(option_list);
474
475 BFT_MALLOC(ret_list, l + 1, char);
476
477 /* Transform format name to lowercase, single whitespace separated */
478
479 for (i = 0, j = 0 ; i < l ; i++) {
480 ret_list[j] = tolower(option_list[i]);
481 if (ret_list[j] == ',' || ret_list[j] == ';' || ret_list[j] == '\t')
482 ret_list[j] = ' ';
483 if (ret_list[j] != ' ' || (j > 0 && ret_list[j-1] != ' '))
484 j++;
485 }
486 if (j > 0 && ret_list[j-1] == ' ')
487 j--;
488
489 ret_list[j] = '\0';
490
491 return ret_list;
492 }
493
494 #if defined(HAVE_DLOPEN)
495
496 /*----------------------------------------------------------------------------
497 * Get a shared library function pointer for a writer plugin
498 *
499 * parameters:
500 * wf <-- pointer to writer format structure
501 * name <-- name of function symbol in library
502 * errors_are_fatal <-- abort if true, silently ignore if false
503 *
504 * returns:
505 * pointer to function in shared library
506 *----------------------------------------------------------------------------*/
507
508 static void *
_get_dl_function_pointer(fvm_writer_format_t * wf,const char * name,bool errors_are_fatal)509 _get_dl_function_pointer(fvm_writer_format_t *wf,
510 const char *name,
511 bool errors_are_fatal)
512 {
513 void *retval = NULL;
514
515 assert(wf != NULL);
516 assert(wf->dl_lib != NULL);
517
518 if (wf->dl_name == NULL)
519 retval = cs_base_get_dl_function_pointer(wf->dl_lib,
520 name,
521 errors_are_fatal);
522 else {
523 char *_name;
524 BFT_MALLOC(_name, strlen(wf->dl_prefix) + strlen(name) + 1, char);
525 sprintf(_name, "%s%s", wf->dl_prefix, name);
526 retval = cs_base_get_dl_function_pointer(wf->dl_lib,
527 _name,
528 errors_are_fatal);
529 BFT_FREE(_name);
530 }
531
532 return retval;
533 }
534
535 /*----------------------------------------------------------------------------
536 * Load Plugin writer.
537 *
538 * parameters:
539 * wf <-> pointer to library format writer.
540 *----------------------------------------------------------------------------*/
541
542 static void
_load_plugin(fvm_writer_format_t * wf)543 _load_plugin(fvm_writer_format_t *wf)
544 {
545 /* Open from shared library */
546
547 wf->dl_lib = cs_base_dlopen_plugin(wf->dl_name);
548
549 /* Increment reference count */
550
551 wf->dl_count += 1;
552
553 /* Load symbols from shared library */
554
555 /* Function pointers need to be double-casted so as to first convert
556 a (void *) type to a memory address and then convert it back to the
557 original type. Otherwise, the compiler may issue a warning.
558 This is a valid ISO C construction. */
559
560 wf->n_version_strings_func = (fvm_writer_n_version_strings_t *) (intptr_t)
561 _get_dl_function_pointer(wf, "n_version_strings", false);
562
563 wf->version_string_func = (fvm_writer_version_string_t *) (intptr_t)
564 _get_dl_function_pointer(wf, "version_string", false);
565
566 wf->init_func = (fvm_writer_init_t *) (intptr_t)
567 _get_dl_function_pointer(wf, "init_writer", true);
568
569 wf->finalize_func = (fvm_writer_finalize_t *) (intptr_t)
570 _get_dl_function_pointer(wf, "finalize_writer", true);
571
572 wf->set_mesh_time_func = (fvm_writer_set_mesh_time_t *) (intptr_t)
573 _get_dl_function_pointer(wf, "set_mesh_time", true);
574
575 wf->needs_tesselation_func = (fvm_writer_needs_tesselation_t *) (intptr_t)
576 _get_dl_function_pointer(wf, "needs_tesselation", false);
577
578 wf->export_nodal_func = (fvm_writer_export_nodal_t *) (intptr_t)
579 _get_dl_function_pointer(wf, "export_nodal", true);
580
581 wf->export_field_func = (fvm_writer_export_field_t *) (intptr_t)
582 _get_dl_function_pointer(wf, "export_field", true);
583
584 wf->flush_func = (fvm_writer_flush_t *) (intptr_t)
585 _get_dl_function_pointer(wf, "flush", false);
586 }
587
588 /*----------------------------------------------------------------------------
589 * Unload Plugin writer.
590 *
591 * parameters:
592 * wf <-> pointer to library format writer.
593 *----------------------------------------------------------------------------*/
594
595 static void
_close_plugin(fvm_writer_format_t * wf)596 _close_plugin(fvm_writer_format_t *wf)
597 {
598 /* Open from shared library */
599
600 if (wf->dl_lib == NULL)
601 return;
602
603 cs_base_dlclose(wf->name, wf->dl_lib);
604
605 wf->dl_lib = NULL;
606
607 /* Decrement reference count */
608
609 wf->dl_count -= 1;
610
611 /* Reset pointers */
612
613 if (wf->dl_count == 0) {
614 wf->n_version_strings_func = NULL;
615 wf->version_string_func = NULL;
616 wf->init_func = NULL;
617 wf->finalize_func = NULL;
618 wf->set_mesh_time_func = NULL;
619 wf->needs_tesselation_func = NULL;
620 wf->export_nodal_func = NULL;
621 wf->export_field_func = NULL;
622 wf->flush_func = NULL;
623 }
624 }
625
626 #endif /* defined(HAVE_DLOPEN)*/
627
628 /*----------------------------------------------------------------------------
629 * Initialize specific format writer based on writer and optional
630 * mesh name info.
631 *
632 * parameters:
633 * this_writer <-- pointer to mesh and field output writer
634 * mesh_name <-- optional mesh name, or NULL
635 *
636 * returns:
637 * pointer to mesh and field output writer
638 *----------------------------------------------------------------------------*/
639
640 static void *
_format_writer_init(fvm_writer_t * this_writer,const char * mesh_name)641 _format_writer_init(fvm_writer_t *this_writer,
642 const char *mesh_name)
643 {
644 const char empty[] = "";
645 const char untitled[] = "[untitled]";
646
647 char local_dir[] = ".";
648 char *tmp_path = NULL, *tmp_name = NULL;
649
650 void *format_writer = NULL;
651
652 /* Determine path and create directory if needed */
653
654 const char *path = local_dir;
655
656 if (this_writer->path != NULL) {
657
658 int l = strlen(this_writer->path);
659
660 if (l > 0) {
661 BFT_MALLOC(tmp_path, l + 2, char);
662 strcpy(tmp_path, this_writer->path);
663 if (tmp_path[l - 1] == DIR_SEPARATOR)
664 tmp_path[l - 1] = '\0';
665 int dir_err = 0;
666 if (cs_glob_rank_id < 1)
667 dir_err = cs_file_mkdir_default(this_writer->path);
668 #if defined(HAVE_MPI)
669 if (cs_glob_n_ranks > 1)
670 MPI_Bcast(&dir_err, 1, MPI_INT, 0, cs_glob_mpi_comm);
671 #endif
672 if (dir_err == 1)
673 tmp_path[0] = '\0';
674 else {
675 l = strlen(tmp_path);
676 tmp_path[l] = DIR_SEPARATOR;
677 tmp_path[l+1] = '\0';
678 }
679 path = tmp_path;
680 }
681
682 }
683
684 const char *name = this_writer->name;
685
686 if (name != NULL) {
687 size_t lw = strlen(this_writer->name);
688 if (lw == 0)
689 name = mesh_name;
690 else if (mesh_name != NULL) {
691 if (strlen(mesh_name) > 0) {
692 size_t l = lw + 1 + strlen(mesh_name);
693 BFT_MALLOC(tmp_name, l + 1, char);
694 sprintf(tmp_name, "%s_%s", this_writer->name, mesh_name);
695 for (size_t i = lw + 1, j = 0; i < l; i++, j++) {
696 if (tmp_name[i] == ' ')
697 tmp_name[i] = '_';
698 }
699 name = tmp_name;
700 }
701 }
702 }
703 else
704 name = mesh_name;
705
706 if (name == NULL) {
707 if (this_writer->format->info_mask & FVM_WRITER_FORMAT_NAME_IS_OPTIONAL)
708 name = empty;
709 else
710 name = untitled;
711 }
712
713 /* Initialize format-specific writer */
714
715 fvm_writer_init_t *init_func = this_writer->format->init_func;
716
717 if (init_func != NULL) {
718
719 cs_fp_exception_disable_trap();
720
721 #if defined(HAVE_MPI)
722 format_writer = init_func(name,
723 path,
724 this_writer->options,
725 this_writer->time_dep,
726 cs_glob_mpi_comm);
727 #else
728 format_writer = init_func(name,
729 path,
730 this_writer->options,
731 this_writer->time_dep);
732 #endif
733
734 cs_fp_exception_restore_trap();
735
736 }
737
738 BFT_FREE(tmp_name);
739 BFT_FREE(tmp_path);
740
741 /* Return pointer to initialized writer */
742
743 return format_writer;
744 }
745
746 /*----------------------------------------------------------------------------
747 * Find or add a specific format writer based on writer and optional
748 * mesh name info.
749 *
750 * parameters:
751 * this_writer <-- pointer to mesh and field output writer
752 * mesh_name <-- optional mesh name, or NULL
753 *
754 * returns:
755 * pointer to mesh and field output writer
756 *----------------------------------------------------------------------------*/
757
758 static void*
_find_or_add_format_writer(fvm_writer_t * this_writer,const fvm_nodal_t * mesh)759 _find_or_add_format_writer(fvm_writer_t *this_writer,
760 const fvm_nodal_t *mesh)
761 {
762 void *format_writer = NULL;
763
764 assert(this_writer != NULL);
765 assert(this_writer->format != NULL);
766
767 /* Find or add single-mesh writer if required */
768
769 if ( this_writer->n_format_writers == 0
770 || this_writer->mesh_names != NULL) {
771 int i;
772 const char empty[] = "";
773 const char *name = (mesh->name != NULL) ? mesh->name : empty;
774 for (i = 0; i < this_writer->n_format_writers; i++) {
775 if (strcmp(this_writer->mesh_names[i], name) == 0)
776 break;
777 }
778 if (i >= this_writer->n_format_writers) {
779 BFT_REALLOC(this_writer->format_writer, i + 1, void *);
780 BFT_REALLOC(this_writer->mesh_names, i + 1, char *);
781 BFT_MALLOC(this_writer->mesh_names[i], strlen(name) + 1, char);
782 strcpy(this_writer->mesh_names[i], name);
783 this_writer->format_writer[i] = _format_writer_init(this_writer, name);
784 this_writer->n_format_writers += 1;
785 }
786 format_writer = this_writer->format_writer[i];
787 }
788 else
789 format_writer = this_writer->format_writer[0];
790
791 return format_writer;
792 }
793
794 /*============================================================================
795 * Semi-private function definitions (prototypes in fvm_writer_priv.h)
796 *============================================================================*/
797
798 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
799
800 /*============================================================================
801 * Public function definitions
802 *============================================================================*/
803
804 /*----------------------------------------------------------------------------
805 * Find the format matching a name,
806 *
807 * parameters:
808 * format_name <-- name of desired format
809 *
810 * returns:
811 * index of the format matching the given name, or -1 if none matches.
812 *----------------------------------------------------------------------------*/
813
814 int
fvm_writer_get_format_id(const char * format_name)815 fvm_writer_get_format_id(const char *format_name)
816 {
817 char tmp_name[32], closest_name[32];
818 int i, l;
819
820 if (format_name == NULL)
821 return _fvm_writer_n_formats;
822
823 l = strlen(format_name);
824
825 /* Transform format name to lowercase, whitespace as underscore */
826
827 strncpy(tmp_name, format_name, 32);
828 tmp_name[31] = '\0';
829 for (i = 0 ; i < l ; i++) {
830 tmp_name[i] = tolower(tmp_name[i]);
831 if (tmp_name[i] == ' ' || tmp_name[i] == '\t')
832 tmp_name[i] = '_';
833 }
834
835 /* Try "known" names */
836
837 if (strncmp(tmp_name, "ensight", 7) == 0)
838 strcpy(closest_name, "EnSight Gold");
839 else if (strncmp(tmp_name, "medcoupling", 11) == 0)
840 strcpy(closest_name, "MEDCoupling");
841 else if (strncmp(tmp_name, "med", 3) == 0)
842 strcpy(closest_name, "MED");
843 else if (strncmp(tmp_name, "cgns", 4) == 0)
844 strcpy(closest_name, "CGNS");
845 else if (strncmp(tmp_name, "catalyst", 8) == 0)
846 strcpy(closest_name, "Catalyst");
847 else if (strncmp(tmp_name, "ccm", 3) == 0)
848 strcpy(closest_name, "CCM-IO");
849 else if (strncmp(tmp_name, "melissa", 7) == 0)
850 strcpy(closest_name, "Melissa");
851 else
852 strcpy(closest_name, tmp_name);
853
854 /* Find name in list */
855
856 for (i = 0 ; i < _fvm_writer_n_formats ; i++)
857 if (strcmp(closest_name, _fvm_writer_format_list[i].name) == 0)
858 break;
859
860 return i;
861 }
862
863 /*----------------------------------------------------------------------------
864 * Returns number of known formats.
865 *----------------------------------------------------------------------------*/
866
867 int
fvm_writer_n_formats(void)868 fvm_writer_n_formats(void)
869 {
870 return _fvm_writer_n_formats;
871 }
872
873 /*----------------------------------------------------------------------------
874 * Returns name of a known format.
875 *
876 * parameters:
877 * format_index <-- index of format in known format list (0 to n-1)
878 *
879 * returns:
880 * pointer to constant string containing the format's name
881 *----------------------------------------------------------------------------*/
882
883 const char *
fvm_writer_format_name(int format_index)884 fvm_writer_format_name(int format_index)
885 {
886 if (format_index >= 0 && format_index < _fvm_writer_n_formats)
887 return _fvm_writer_format_list[format_index].name;
888
889 else
890 return NULL;
891 }
892
893 /*----------------------------------------------------------------------------
894 * Returns availability of a known format.
895 *
896 * parameters:
897 * format_index <-- index of format in known format list (0 to n-1)
898 *
899 * returns:
900 * 1 if the format is available, 0 otherwise.
901 *----------------------------------------------------------------------------*/
902
903 int
fvm_writer_format_available(int format_index)904 fvm_writer_format_available(int format_index)
905 {
906 int retval = 0;
907
908 if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
909
910 if (_fvm_writer_format_list[format_index].init_func != NULL)
911 retval = 1;
912
913 #if defined(HAVE_DLOPEN)
914 else if (_fvm_writer_format_list[format_index].dl_name != NULL)
915 retval = 1;
916 #endif
917
918 }
919 return retval;
920 }
921
922 /*----------------------------------------------------------------------------
923 * Returns number of library version strings associated with a given format.
924 *
925 * For writers requiring an external library, the first associated
926 * version string should correspond to that library, with possible
927 * additional version strings for its dependencies.
928 *
929 * For writers only requiring standard libraries (libc, MPI, MPI-IO),
930 * this function should return 0.
931 *
932 * parameters:
933 * format_index <-- index of format in known format list (0 to n-1)
934 *
935 * returns:
936 * number of library version strings associated with a given format.
937 *----------------------------------------------------------------------------*/
938
939 int
fvm_writer_n_version_strings(int format_index)940 fvm_writer_n_version_strings(int format_index)
941 {
942 int retval = 0;
943 fvm_writer_n_version_strings_t *n_version_strings_func = NULL;
944
945 if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
946 n_version_strings_func
947 = _fvm_writer_format_list[format_index].n_version_strings_func;
948 if (n_version_strings_func != NULL)
949 retval = n_version_strings_func();
950 }
951 return retval;
952 }
953
954 /*----------------------------------------------------------------------------
955 * Returns a library version string associated with a given format.
956 *
957 * We must have string_index < fvm_writer_n_version_strings(format_index).
958 *
959 * In certain cases, when using dynamic libraries, fvm may be compiled
960 * with one library version, and linked with another. If both run-time
961 * and compile-time version information is available, this function
962 * will return the run-time version string by default.
963 *
964 * Setting the compile_time flag to 1, the compile-time version string
965 * will be returned if this is different from the run-time version.
966 * If the version is the same, or only one of the 2 version strings are
967 * available, a NULL character string will be returned with this flag set.
968 *
969 * parameters:
970 * format_index <-- index of format in known format list (0 to n-1)
971 * string_index <-- index in format's version string list (0 to n-1)
972 * compile_time <-- 0 by default, 1 if we want the compile-time version
973 * string, if different from the run-time version.
974 *
975 * returns:
976 * pointer to constant string containing the library's version.
977 *----------------------------------------------------------------------------*/
978
979 const char *
fvm_writer_version_string(int format_index,int string_index,int compile_time_version)980 fvm_writer_version_string(int format_index,
981 int string_index,
982 int compile_time_version)
983 {
984 const char * retval = NULL;
985 fvm_writer_version_string_t *version_string_func = NULL;
986
987 if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
988 version_string_func
989 = _fvm_writer_format_list[format_index].version_string_func;
990 if (version_string_func != NULL)
991 retval = version_string_func(string_index,
992 compile_time_version);
993 }
994 return retval;
995 }
996
997 /*----------------------------------------------------------------------------
998 * Remove a given option from a format options list if present.
999 *
1000 * The possible separators are also transformed to whitespace and merged.
1001 *
1002 * parameters:
1003 * format_options <-> options for the selected format (case-independent,
1004 * whitespace or comma separated list)
1005 * exclude_option <-- option to be excluded
1006 *----------------------------------------------------------------------------*/
1007
1008 void
fvm_writer_filter_option(char * format_options,const char * exclude_option)1009 fvm_writer_filter_option(char *format_options,
1010 const char *exclude_option)
1011 {
1012 char *tmp_options = NULL;
1013
1014 size_t l = strlen(exclude_option);
1015
1016 /* Find corresponding format and check coherency */
1017
1018 tmp_options = _fvm_writer_option_list(format_options);
1019
1020 /* Parse top-level options (consuming those handled here);
1021 the options string now contains options separated by a single
1022 whitespace. */
1023
1024 if (tmp_options != NULL) {
1025
1026 int i0 = 0, i1;
1027
1028 while (tmp_options[i0] != '\0') {
1029
1030 for (i1 = i0; tmp_options[i1] != '\0' && tmp_options[i1] != ' '; i1++);
1031 size_t l_opt = i1 - i0;
1032
1033 if ( (l_opt == l)
1034 && (strncmp(tmp_options + i0, exclude_option, l_opt) == 0)) {
1035 if (tmp_options[i1] == ' ')
1036 strcpy(tmp_options + i0, tmp_options + i1 + 1);
1037 else {
1038 if (i0 > 1) {
1039 assert(tmp_options[i0-1] == ' ');
1040 i0--;
1041 }
1042 tmp_options[i0] = '\0';
1043 }
1044 }
1045 else {
1046 i0 = i1;
1047 if (tmp_options[i0] == ' ')
1048 i0++;
1049 }
1050
1051 i1 = strlen(tmp_options);
1052 BFT_REALLOC(tmp_options, i1+1, char);
1053
1054 }
1055
1056 }
1057
1058 strcpy(format_options, tmp_options);
1059
1060 BFT_FREE(tmp_options);
1061 }
1062
1063 /*----------------------------------------------------------------------------
1064 * Initialize FVM mesh and field output writer.
1065 *
1066 * Allowed options depend on what is applicable to a given format. Those
1067 * not relevant to a given writer are ignored. Possible options include:
1068 * text output text files
1069 * binary output binary files (default)
1070 * big_endian force binary files to big-endian
1071 * discard_polygons do not output polygons or related values
1072 * discard_polyhedra do not output polyhedra or related values
1073 * divide_polygons tesselate polygons with triangles
1074 * divide_polyhedra tesselate polyhedra with tetrahedra and pyramids
1075 * (adding a vertex near each polyhedron's center)
1076 * separate_meshes use a different writer for each mesh
1077 *
1078 * parameters:
1079 * name <-- base name of output
1080 * path <-- optional directory name for output
1081 * (directory automatically created if necessary)
1082 * format_name <-- name of selected format (case-independent)
1083 * format_options <-- options for the selected format (case-independent,
1084 * whitespace or comma separated list)
1085 * time_dependency <-- indicates if and how meshes will change with time
1086 *
1087 * returns:
1088 * pointer to mesh and field output writer
1089 *----------------------------------------------------------------------------*/
1090
1091 fvm_writer_t *
fvm_writer_init(const char * name,const char * path,const char * format_name,const char * format_options,fvm_writer_time_dep_t time_dependency)1092 fvm_writer_init(const char *name,
1093 const char *path,
1094 const char *format_name,
1095 const char *format_options,
1096 fvm_writer_time_dep_t time_dependency)
1097 {
1098 int i;
1099 char *tmp_options = NULL;
1100 fvm_writer_t *this_writer = NULL;
1101 bool separate_meshes = false;
1102
1103 /* Find corresponding format and check coherency */
1104
1105 for (i = 0 ; i < _fvm_writer_n_formats ; i++)
1106 if (strcmp(format_name, _fvm_writer_format_list[i].name) == 0)
1107 break;
1108
1109 if (i >= _fvm_writer_n_formats)
1110 i = fvm_writer_get_format_id(format_name);
1111
1112 if (i < 0)
1113 bft_error(__FILE__, __LINE__, 0,
1114 _("Format type \"%s\" required for case \"%s\" is unknown"),
1115 format_name, name);
1116
1117 if (!fvm_writer_format_available(i))
1118 bft_error(__FILE__, __LINE__, 0,
1119 _("Format type \"%s\" required for case \"%s\" is not available"),
1120 format_name, name);
1121
1122 tmp_options = _fvm_writer_option_list(format_options);
1123
1124 /* Parse top-level options (consuming those handled here);
1125 the options string now contains options separated by a single
1126 whitespace. */
1127
1128 if (tmp_options != NULL) {
1129
1130 int i0 = 0, i1;
1131
1132 while (tmp_options[i0] != '\0') {
1133
1134 for (i1 = i0; tmp_options[i1] != '\0' && tmp_options[i1] != ' '; i1++);
1135 int l_opt = i1 - i0;
1136
1137 if ( (l_opt == 15)
1138 && (strncmp(tmp_options + i0, "separate_meshes", l_opt) == 0)) {
1139 separate_meshes = true;
1140 if (tmp_options[i1] == ' ')
1141 strcpy(tmp_options + i0, tmp_options + i1 + 1);
1142 else {
1143 if (i0 > 1) {
1144 assert(tmp_options[i0-1] == ' ');
1145 i0--;
1146 }
1147 tmp_options[i0] = '\0';
1148 }
1149 }
1150 else {
1151 i0 = i1;
1152 if (tmp_options[i0] == ' ')
1153 i0++;
1154 }
1155
1156 i1 = strlen(tmp_options);
1157 if (i1 > 0)
1158 BFT_REALLOC(tmp_options, i1+1, char);
1159 else {
1160 BFT_FREE(tmp_options);
1161 break;
1162 }
1163
1164 }
1165
1166 }
1167
1168 /* Initialize writer */
1169
1170 BFT_MALLOC(this_writer, 1, fvm_writer_t);
1171
1172 BFT_MALLOC(this_writer->name, strlen(name) + 1, char);
1173 strcpy(this_writer->name, name);
1174
1175 this_writer->format = &(_fvm_writer_format_list[i]);
1176
1177 /* Load plugin if required */
1178
1179 #if defined(HAVE_DLOPEN)
1180 if (this_writer->format->dl_name != NULL)
1181 _load_plugin(this_writer->format);
1182 #endif
1183
1184 if (path) {
1185 BFT_MALLOC(this_writer->path, strlen(path) + 1, char);
1186 strcpy(this_writer->path, path);
1187 }
1188 else
1189 this_writer->path = NULL;
1190
1191 this_writer->options = tmp_options;
1192 tmp_options = NULL;
1193
1194 this_writer->time_dep = CS_MIN(time_dependency,
1195 this_writer->format->max_time_dep);
1196
1197 CS_TIMER_COUNTER_INIT(this_writer->mesh_time);
1198 CS_TIMER_COUNTER_INIT(this_writer->field_time);
1199 CS_TIMER_COUNTER_INIT(this_writer->flush_time);
1200
1201 if (this_writer->format->info_mask & FVM_WRITER_FORMAT_SEPARATE_MESHES)
1202 separate_meshes = true;
1203 else if ( this_writer->format->info_mask
1204 & FVM_WRITER_FORMAT_NO_SEPARATE_MESHES)
1205 separate_meshes = false;
1206
1207 if (separate_meshes)
1208 this_writer->n_format_writers = 0; /* Delay construction */
1209 else
1210 this_writer->n_format_writers = 1;
1211
1212 this_writer->mesh_names = NULL;
1213
1214 /* Initialize format-specific writer */
1215
1216 if (this_writer->n_format_writers > 0) {
1217 BFT_MALLOC(this_writer->format_writer, 1, void *);
1218 this_writer->format_writer[0] = _format_writer_init(this_writer,
1219 NULL);
1220 }
1221 else
1222 this_writer->format_writer = NULL;
1223
1224 /* Return pointer to initialized writer */
1225
1226 return this_writer;
1227 }
1228
1229 /*----------------------------------------------------------------------------
1230 * Finalize FVM mesh and field output writer.
1231 *
1232 * parameters:
1233 * this_writer <-- pointer to mesh and field output writer
1234 *
1235 * returns:
1236 * NULL pointer
1237 *----------------------------------------------------------------------------*/
1238
1239 fvm_writer_t *
fvm_writer_finalize(fvm_writer_t * this_writer)1240 fvm_writer_finalize(fvm_writer_t *this_writer)
1241 {
1242 fvm_writer_finalize_t *finalize_func = NULL;
1243
1244 assert(this_writer != NULL);
1245 assert(this_writer->format != NULL);
1246
1247 BFT_FREE(this_writer->name);
1248 BFT_FREE(this_writer->path);
1249 BFT_FREE(this_writer->options);
1250
1251 finalize_func = this_writer->format->finalize_func;
1252
1253 if (finalize_func != NULL) {
1254 cs_fp_exception_disable_trap();
1255 for (int i = 0; i < this_writer->n_format_writers; i++)
1256 finalize_func(this_writer->format_writer[i]);
1257 cs_fp_exception_restore_trap();
1258 }
1259 else
1260 this_writer->format_writer = NULL;
1261 BFT_FREE(this_writer->format_writer);
1262
1263 if (this_writer->mesh_names != NULL) {
1264 for (int i = 0; i < this_writer->n_format_writers; i++)
1265 BFT_FREE(this_writer->mesh_names[i]);
1266 }
1267 BFT_FREE(this_writer->mesh_names);
1268
1269 /* Unload plugin if required */
1270
1271 #if defined(HAVE_DLOPEN)
1272 if (this_writer->format->dl_lib != NULL)
1273 _close_plugin(this_writer->format);
1274 #endif
1275
1276 BFT_FREE(this_writer);
1277
1278 return NULL;
1279 }
1280
1281 /*----------------------------------------------------------------------------
1282 * Return a writer's name.
1283 *
1284 * parameters:
1285 * this_writer <-- pointer to mesh and field output writer
1286 *
1287 * returns:
1288 * pointer to base name of output associated with the writer
1289 *----------------------------------------------------------------------------*/
1290
1291 const char *
fvm_writer_get_name(const fvm_writer_t * this_writer)1292 fvm_writer_get_name(const fvm_writer_t *this_writer)
1293 {
1294 return this_writer->name;
1295 }
1296
1297 /*----------------------------------------------------------------------------
1298 * Return a writer's associated format name.
1299 *
1300 * parameters:
1301 * this_writer <-- pointer to mesh and field output writer
1302 *
1303 * returns:
1304 * pointer to output format name associated with the writer
1305 *----------------------------------------------------------------------------*/
1306
1307 const char *
fvm_writer_get_format(const fvm_writer_t * this_writer)1308 fvm_writer_get_format(const fvm_writer_t *this_writer)
1309 {
1310 return this_writer->format->name;
1311 }
1312
1313 /*----------------------------------------------------------------------------
1314 * Return a writer's associated format options.
1315 *
1316 * parameters:
1317 * this_writer <-- pointer to mesh and field output writer
1318 *
1319 * returns:
1320 * pointer to output format options associated with the writer
1321 *----------------------------------------------------------------------------*/
1322
1323 const char *
fvm_writer_get_options(const fvm_writer_t * this_writer)1324 fvm_writer_get_options(const fvm_writer_t *this_writer)
1325 {
1326 const char *retval = _empty_string;
1327 if (this_writer->options != NULL)
1328 retval = this_writer->options;
1329 return retval;
1330 }
1331
1332 /*----------------------------------------------------------------------------
1333 * Return a writer's associated output directory.
1334 *
1335 * parameters:
1336 * this_writer <-- pointer to mesh and field output writer
1337 *
1338 * returns:
1339 * pointer to output format options associated with the writer
1340 *----------------------------------------------------------------------------*/
1341
1342 const char *
fvm_writer_get_path(const fvm_writer_t * this_writer)1343 fvm_writer_get_path(const fvm_writer_t *this_writer)
1344 {
1345 const char *retval = _empty_string;
1346 if (this_writer->path != NULL)
1347 retval = this_writer->path;
1348 return retval;
1349 }
1350
1351 /*----------------------------------------------------------------------------
1352 * Return geometry time dependency status of a writer.
1353 *
1354 * parameters:
1355 * this_writer <-- pointer to mesh and field output writer
1356 *
1357 * returns:
1358 * time dependency status
1359 *----------------------------------------------------------------------------*/
1360
1361 fvm_writer_time_dep_t
fvm_writer_get_time_dep(const fvm_writer_t * this_writer)1362 fvm_writer_get_time_dep(const fvm_writer_t *this_writer)
1363 {
1364 return this_writer->time_dep;
1365 }
1366
1367 /*----------------------------------------------------------------------------
1368 * Associate new time step with a mesh.
1369 *
1370 * parameters:
1371 * this_writer_p <-- pointer to associated writer
1372 * time_step <-- time step number
1373 * time_value <-- time_value number
1374 *----------------------------------------------------------------------------*/
1375
1376 void
fvm_writer_set_mesh_time(fvm_writer_t * this_writer,int time_step,double time_value)1377 fvm_writer_set_mesh_time(fvm_writer_t *this_writer,
1378 int time_step,
1379 double time_value)
1380 {
1381 fvm_writer_set_mesh_time_t *set_mesh_time_func = NULL;
1382
1383 assert(this_writer != NULL);
1384 assert(this_writer->format != NULL);
1385
1386 set_mesh_time_func = this_writer->format->set_mesh_time_func;
1387
1388 if (set_mesh_time_func != NULL) {
1389 cs_fp_exception_disable_trap();
1390 for (int i = 0; i < this_writer->n_format_writers; i++)
1391 set_mesh_time_func(this_writer->format_writer[i],
1392 time_step,
1393 time_value);
1394 cs_fp_exception_restore_trap();
1395 }
1396 }
1397
1398 /*----------------------------------------------------------------------------
1399 * Query if elements of a given type will need to be tesselated
1400 * for use of a nodal mesh with an output writer.
1401 *
1402 * This function should be called before any fvm_writer_export_...()
1403 *
1404 * parameters:
1405 * this_writer <-- pointer to mesh and field output writer
1406 * mesh <-- pointer to nodal mesh
1407 * element_type <-- type of element
1408 *
1409 * returns:
1410 * 0 if no tesselation is necessary, 1 if tesselation is necessary.
1411 *----------------------------------------------------------------------------*/
1412
1413 int
fvm_writer_needs_tesselation(fvm_writer_t * this_writer,const fvm_nodal_t * mesh,fvm_element_t element_type)1414 fvm_writer_needs_tesselation(fvm_writer_t *this_writer,
1415 const fvm_nodal_t *mesh,
1416 fvm_element_t element_type)
1417 {
1418 int retval = 0;
1419 fvm_writer_needs_tesselation_t *needs_tesselation_func = NULL;
1420
1421 void *format_writer = _find_or_add_format_writer(this_writer, mesh);
1422
1423 needs_tesselation_func = this_writer->format->needs_tesselation_func;
1424 if (needs_tesselation_func != NULL)
1425 retval = needs_tesselation_func(format_writer,
1426 mesh,
1427 element_type);
1428 return retval;
1429 }
1430
1431 /*----------------------------------------------------------------------------
1432 * Export FVM nodal mesh.
1433 *
1434 * parameters:
1435 * this_writer <-- pointer to mesh and field output writer
1436 * mesh <-- pointer to nodal mesh
1437 *----------------------------------------------------------------------------*/
1438
1439 void
fvm_writer_export_nodal(fvm_writer_t * this_writer,const fvm_nodal_t * mesh)1440 fvm_writer_export_nodal(fvm_writer_t *this_writer,
1441 const fvm_nodal_t *mesh)
1442 {
1443 cs_timer_t t0, t1;
1444
1445 fvm_writer_export_nodal_t *export_nodal_func = NULL;
1446
1447 assert(this_writer != NULL);
1448 assert(this_writer->format != NULL);
1449
1450 void *format_writer = _find_or_add_format_writer(this_writer, mesh);
1451
1452 t0 = cs_timer_time();
1453
1454 export_nodal_func = this_writer->format->export_nodal_func;
1455
1456 if (export_nodal_func != NULL) {
1457 cs_fp_exception_disable_trap();
1458 export_nodal_func(format_writer, mesh);
1459 cs_fp_exception_restore_trap();
1460 }
1461
1462 t1 = cs_timer_time();
1463
1464 cs_timer_counter_add_diff(&(this_writer->mesh_time), &t0, &t1);
1465 }
1466
1467 /*----------------------------------------------------------------------------
1468 * Export field associated with a nodal mesh.
1469 *
1470 * Assigning a negative value to the time step indicates a time-independent
1471 * field (in which case the time_value argument is unused).
1472 *
1473 * parameters:
1474 * this_writer <-- pointer to mesh and field output writer
1475 * mesh <-- pointer to associated nodal mesh structure
1476 * name <-- variable name
1477 * location <-- variable definition location (nodes or elements)
1478 * dimension <-- variable dimension (0: constant, 1: scalar,
1479 * 3: vector, 6: sym. tensor, 9: asym. tensor)
1480 * interlace <-- indicates if variable in memory is interlaced
1481 * n_parent_lists <-- indicates if variable values are to be obtained
1482 * directly through the local entity index (when 0) or
1483 * through the parent entity numbers (when 1 or more)
1484 * parent_num_shift <-- parent number to value array index shifts;
1485 * size: n_parent_lists
1486 * datatype <-- indicates the data type of (source) field values
1487 * time_step <-- number of the current time step
1488 * time_value <-- associated time value
1489 * field_values <-- array of associated field value arrays
1490 *----------------------------------------------------------------------------*/
1491
1492 void
fvm_writer_export_field(fvm_writer_t * this_writer,const fvm_nodal_t * mesh,const char * name,fvm_writer_var_loc_t location,int dimension,cs_interlace_t interlace,int n_parent_lists,const cs_lnum_t parent_num_shift[],cs_datatype_t datatype,int time_step,double time_value,const void * const field_values[])1493 fvm_writer_export_field(fvm_writer_t *this_writer,
1494 const fvm_nodal_t *mesh,
1495 const char *name,
1496 fvm_writer_var_loc_t location,
1497 int dimension,
1498 cs_interlace_t interlace,
1499 int n_parent_lists,
1500 const cs_lnum_t parent_num_shift[],
1501 cs_datatype_t datatype,
1502 int time_step,
1503 double time_value,
1504 const void *const field_values[])
1505 {
1506 cs_timer_t t0, t1;
1507
1508 fvm_writer_export_field_t *export_field_func = NULL;
1509
1510 assert(this_writer != NULL);
1511 assert(this_writer->format != NULL);
1512
1513 void *format_writer = _find_or_add_format_writer(this_writer, mesh);
1514
1515 t0 = cs_timer_time();
1516
1517 export_field_func = this_writer->format->export_field_func;
1518
1519 if (export_field_func != NULL) {
1520 cs_fp_exception_disable_trap();
1521 export_field_func(format_writer,
1522 mesh,
1523 name,
1524 location,
1525 dimension,
1526 interlace,
1527 n_parent_lists,
1528 parent_num_shift,
1529 datatype,
1530 time_step,
1531 time_value,
1532 field_values);
1533
1534 cs_fp_exception_restore_trap();
1535 }
1536
1537 t1 = cs_timer_time();
1538
1539 cs_timer_counter_add_diff(&(this_writer->field_time), &t0, &t1);
1540 }
1541
1542 /*----------------------------------------------------------------------------
1543 * Flush files associated with a given writer.
1544 *
1545 * parameters:
1546 * this_writer <-- pointer to mesh and field output writer
1547 *----------------------------------------------------------------------------*/
1548
1549 void
fvm_writer_flush(fvm_writer_t * this_writer)1550 fvm_writer_flush(fvm_writer_t *this_writer)
1551 {
1552
1553 fvm_writer_flush_t *flush_func = NULL;
1554
1555 assert(this_writer != NULL);
1556 assert(this_writer->format != NULL);
1557
1558 flush_func = this_writer->format->flush_func;
1559
1560 if (flush_func != NULL) {
1561
1562 cs_timer_t t0, t1;
1563
1564 t0 = cs_timer_time();
1565
1566 cs_fp_exception_disable_trap();
1567
1568 for (int i = 0; i < this_writer->n_format_writers; i++)
1569 flush_func(this_writer->format_writer[i]);
1570
1571 cs_fp_exception_restore_trap();
1572
1573 t1 = cs_timer_time();
1574
1575 cs_timer_counter_add_diff(&(this_writer->flush_time), &t0, &t1);
1576
1577 }
1578 }
1579
1580 /*----------------------------------------------------------------------------
1581 * Return accumulated times associated with output for a given writer.
1582 *
1583 * parameters:
1584 * this_writer <-- pointer to mesh and field output writer
1585 * mesh_time --> Meshes output time (or NULL)
1586 * field_time --> Fields output time (or NULL)
1587 * flush_time --> remaining (applying output) time (or NULL)
1588 *----------------------------------------------------------------------------*/
1589
1590 void
fvm_writer_get_times(fvm_writer_t * this_writer,cs_timer_counter_t * mesh_time,cs_timer_counter_t * field_time,cs_timer_counter_t * flush_time)1591 fvm_writer_get_times(fvm_writer_t *this_writer,
1592 cs_timer_counter_t *mesh_time,
1593 cs_timer_counter_t *field_time,
1594 cs_timer_counter_t *flush_time)
1595 {
1596 assert(this_writer != NULL);
1597
1598 if (mesh_time != NULL)
1599 *mesh_time = this_writer->mesh_time;
1600 if (field_time != NULL)
1601 *field_time = this_writer->field_time;
1602 if (flush_time != NULL)
1603 *flush_time = this_writer->flush_time;
1604 }
1605
1606 /*----------------------------------------------------------------------------*/
1607
1608 END_C_DECLS
1609