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