/*============================================================================
* Handle export of mesh and fields.
*============================================================================*/
/*
This file is part of the "Finite Volume Mesh" library, intended to provide
finite volume mesh and associated fields I/O and manipulation services.
Copyright (C) 2004-2006 EDF
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*----------------------------------------------------------------------------
* Standard C library headers
*----------------------------------------------------------------------------*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*----------------------------------------------------------------------------
* BFT library headers
*----------------------------------------------------------------------------*/
#include <bft_mem.h>
#include <bft_error.h>
#include <bft_file.h>
#include <bft_printf.h>
#include <bft_timer.h>
/*----------------------------------------------------------------------------
* Local headers
*----------------------------------------------------------------------------*/
#include <fvm_config_defs.h>
#include <fvm_defs.h>
#include <fvm_nodal.h>
#include <fvm_nodal_priv.h>
#include <fvm_parall.h>
/*----------------------------------------------------------------------------
* Header for the current file
*----------------------------------------------------------------------------*/
#include <fvm_writer.h>
#include <fvm_writer_priv.h>
/* Headers for available writers (could be replaced by plugin system) */
#include <fvm_to_cgns.h>
#include <fvm_to_med.h>
#include <fvm_to_ensight.h>
#include <fvm_to_text.h>
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#if 0
} /* Fake brace to force back Emacs auto-indentation back to column 0 */
#endif
#endif /* __cplusplus */
/*============================================================================
* Local Type Definitions
*============================================================================*/
/*============================================================================
* Static and constant variables
*============================================================================*/
/* Number and status of defined formats */
static const int _fvm_writer_n_formats = 4;
static fvm_writer_format_t _fvm_writer_format_list[4] = {
/* Built-in text writer */
{
"text",
FVM_VERSION,
( FVM_WRITER_FORMAT_HAS_POLYGON
| FVM_WRITER_FORMAT_HAS_POLYHEDRON),
FVM_WRITER_TRANSIENT_CONNECT,
NULL, /* n_version_strings_func */
NULL, /* version_string_func */
fvm_to_text_init_writer, /* init_func */
fvm_to_text_finalize_writer, /* finalize_func */
NULL, /* set_mesh_time_func */
NULL, /* needs_tesselation_func */
fvm_to_text_export_nodal, /* export_nodal_func */
NULL, /* export_field_func */
NULL /* flush_func */
},
/* Built-in EnSight Gold writer */
{
"EnSight Gold",
"7.4 +",
( FVM_WRITER_FORMAT_HAS_POLYGON
| FVM_WRITER_FORMAT_HAS_POLYHEDRON),
FVM_WRITER_TRANSIENT_CONNECT,
NULL, /* n_version_strings_func */
NULL, /* version_string_func */
fvm_to_ensight_init_writer, /* init_func */
fvm_to_ensight_finalize_writer, /* finalize_func */
fvm_to_ensight_set_mesh_time, /* set_mesh_time_func */
fvm_to_ensight_needs_tesselation, /* needs_tesselation_func */
fvm_to_ensight_export_nodal, /* export_nodal_func */
fvm_to_ensight_export_field, /* export_field_func */
NULL /* flush_func */
},
/* MED_fichier 2.2 - 3.1 writer */
{
"MED_fichier",
"2.2 +",
( FVM_WRITER_FORMAT_USE_EXTERNAL
| FVM_WRITER_FORMAT_HAS_POLYGON
| FVM_WRITER_FORMAT_HAS_POLYHEDRON),
FVM_WRITER_FIXED_MESH,
#if defined (HAVE_MED)
NULL, /* n_version_strings_func */
NULL, /* version_string_func */
fvm_to_med_init_writer, /* init_func */
fvm_to_med_finalize_writer, /* finalize_func */
fvm_to_med_set_mesh_time, /* set_mesh_time_func */
fvm_to_med_needs_tesselation, /* needs_tesselation_func */
fvm_to_med_export_nodal, /* export_nodal_func */
fvm_to_med_export_field, /* export_field_func */
NULL /* flush_func */
#else
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
#endif
},
/* CGNS writer */
{
"CGNS",
"2.4 +",
( FVM_WRITER_FORMAT_USE_EXTERNAL
| FVM_WRITER_FORMAT_HAS_POLYGON),
FVM_WRITER_FIXED_MESH,
#if defined (HAVE_CGNS)
NULL, /* n_version_strings_func */
NULL, /* version_string_func */
fvm_to_cgns_init_writer, /* init_func */
fvm_to_cgns_finalize_writer, /* finalize_func */
fvm_to_cgns_set_mesh_time, /* set_mesh_time_func */
fvm_to_cgns_needs_tesselation, /* needs_tesselation_func */
fvm_to_cgns_export_nodal, /* export_nodal_func */
fvm_to_cgns_export_field, /* export_field_func */
NULL /* flush_func */
#else
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
#endif
}
};
/*============================================================================
* Private function definitions
*============================================================================*/
/*----------------------------------------------------------------------------
* Find the format with the closest name to the argument,
*
* parameters:
* format_name <-- name of desired format
*
* returns:
* index of the format with the closest name to the argument,
* or _fvm_writer_n_formats if no name is similar enough.
*----------------------------------------------------------------------------*/
static int
_fvm_writer_format_closest_name(const char *const format_name)
{
char tmp_name[32], closest_name[32];
int i, l;
if (format_name == NULL)
return _fvm_writer_n_formats;
l = strlen(format_name);
/* Transform format name to lowercase, whitespace as underscore */
strncpy(tmp_name, format_name, 32);
tmp_name[31] = '\0';
for (i = 0 ; i < l ; i++) {
tmp_name[i] = tolower(tmp_name[i]);
if (tmp_name[i] == ' ' || tmp_name[i] == '\t')
tmp_name[i] = '_';
}
/* Try "known" names */
if (strncmp(tmp_name, "ensight", 7) == 0)
strcpy(closest_name, "EnSight Gold");
else if (strncmp(tmp_name, "med_mem", 7) == 0)
strcpy(closest_name, "MED_memory");
else if (strncmp(tmp_name, "med", 3) == 0)
strcpy(closest_name, "MED_fichier");
else if (strncmp(tmp_name, "cgns", 4) == 0)
strcpy(closest_name, "CGNS");
/* Find name in list */
for (i = 0 ; i < _fvm_writer_n_formats ; i++)
if (strcmp(closest_name, _fvm_writer_format_list[i].name) == 0)
break;
return i;
}
/*----------------------------------------------------------------------------
* Transform a string containing a list of options to lowercase with
* whitespace separators.
* The new list is dynamically allocated, and should be freed when no
* longer needed.
*
* parameters:
* option_list <-- options string (case-independent, whitespace,
* semicolon, or comma separated list)
*
* returns:
* single-whitespace separated option string in lowercase.
*----------------------------------------------------------------------------*/
static char *
_fvm_writer_option_list(const char *const option_list)
{
char *ret_list;
int i, j, l;
if (option_list == NULL)
return NULL;
l = strlen(option_list);
BFT_MALLOC(ret_list, l + 1, char);
/* Transform format name to lowercase, single whitespace separated */
for (i = 0, j = 0 ; i < l ; i++) {
ret_list[j] = tolower(option_list[i]);
if (ret_list[j] == ',' || ret_list[j] == ';' || ret_list[j] == '\t')
ret_list[j] = ' ';
if (ret_list[j] != ' ' || (j > 0 && ret_list[j-1] != ' '))
j++;
}
if (j > 0 && ret_list[j-1] == ' ')
j--;
ret_list[j] = '\0';
return ret_list;
}
/*============================================================================
* Semi-private function definitions (prototypes in fvm_writer_priv.h)
*============================================================================*/
/*----------------------------------------------------------------------------
* Compute recommended buffer sizes to input or output a nodal mesh
* definition by slices. This is especially useful when gathering the mesh for
* output by slices using standard I/O in parallel mode.
*
* The global number of vertices and elements of each slice may also
* be returned, if the pointers n_g_vertices and n_g_elements_section
* are non-NULL respectively.
*
* The number of slices indicated is a minimum, and only a target;
* computation is based primarily on cell and face connectivity, and the
* target should be met for strided connectivities on those types of elements
* only. Using an "optimistic" (i.e. small) mean number of vertices per
* polyhedra or polygon will typically lead to requiring more slices, as
* the connectivity slice size returned will be smaller than that truly
* required for the corresponding slice size.
* Slice sizes required for edges connectivity will meet the target only
* when the global numbers of cells and faces given are zero, so as to
* avoid generating too large connectivity slice sizes for cells should a mesh
* contain both (as for example a hexahedral connectivity slice is 8 times
* larger than the corresponding slice size, while an edges connectivity is
* only 2 times as large).
*
* parameters:
* this_nodal <-- pointer to nodal mesh structure
* n_slices <-- target number of slices required
* n_polyhedron_vertices_mean <-- estimate of the mean number of vertices
* per polyhedron
* n_polygon_vertices_mean <-- estimate of the mean number of vertices
* per polygon
* n_g_vertices --> global number of vertices (or NULL)
* n_g_elements_section --> array for global number of elements per
* section (or NULL)
* global_s_size --> maximum number of entities defined per slice
* global_connect_s_size --> maximum number of connectivity values
* per slice
*----------------------------------------------------------------------------*/
void
fvm_writer_def_nodal_buf_size(const fvm_nodal_t *this_nodal,
int n_slices,
int n_polyhedron_vertices_mean,
int n_polygon_vertices_mean,
fvm_gnum_t *n_g_vertices,
fvm_gnum_t n_g_elements_section[],
fvm_gnum_t *global_s_size,
fvm_gnum_t *global_connect_s_size)
{
int i;
fvm_gnum_t n_g_elements;
fvm_gnum_t n_g_cells = 0, n_g_faces = 0, n_g_edges = 0;
fvm_gnum_t _n_g_vertices = 0;
fvm_gnum_t connect_size;
fvm_gnum_t *_n_g_elements_section = NULL;
const fvm_nodal_section_t *section = NULL;
assert(this_nodal != NULL);
if (n_g_elements_section == NULL)
BFT_MALLOC(_n_g_elements_section, this_nodal->n_sections, fvm_gnum_t);
else
_n_g_elements_section = n_g_elements_section;
/* Vertices */
if (this_nodal->global_vertex_num != NULL)
_n_g_vertices = fvm_io_num_get_global_count(this_nodal->global_vertex_num);
else
_n_g_vertices = this_nodal->n_vertices;
if (n_g_vertices != NULL)
*n_g_vertices = _n_g_vertices;
/* Edges, faces, and cells */
for (i = 0; i < this_nodal->n_sections; i++) {
section = this_nodal->sections[i];
n_g_elements = fvm_nodal_section_n_g_elements(section);
switch(section->entity_dim) {
case 1:
n_g_edges += n_g_elements;
break;
case 2:
n_g_faces += n_g_elements;
break;
default:
n_g_cells += n_g_elements;
}
_n_g_elements_section[i] = n_g_elements;
}
/* Define global slice size as (global_size / n_ranks) + 1 */
*global_s_size = FVM_MAX(n_g_cells, n_g_faces);
if (*global_s_size == 0)
*global_s_size = n_g_edges;
if (*global_s_size == 0) /* Should the mesh contain only vertices */
*global_s_size = _n_g_vertices;
*global_s_size = (*global_s_size / n_slices) + 1;
/* Now compute best size for connectivity buffer,
using estimated "mean" numbers of nodes per polyhedron and per polygon */
*global_connect_s_size = 0;
for (i = 0; i < this_nodal->n_sections; i++) {
section = this_nodal->sections[i];
switch(section->type) {
case FVM_FACE_POLY:
case FVM_CELL_POLY:
if (section->type == FVM_FACE_POLY)
connect_size = FVM_MIN(_n_g_elements_section[i], *global_s_size)
* n_polygon_vertices_mean;
else if (section->type == FVM_CELL_POLY)
connect_size = FVM_MIN(_n_g_elements_section[i], *global_s_size)
* n_polyhedron_vertices_mean;
if (section->tesselation != NULL) {
int i_type;
const fvm_tesselation_t *tesselation = section->tesselation;
const int n_sub_types = fvm_tesselation_n_sub_types(tesselation);
for (i_type = 0; i_type < n_sub_types; i_type++) {
int stride;
fvm_lnum_t n_sub_elements_max;
fvm_element_t sub_type = fvm_tesselation_sub_type(tesselation,
i_type);
fvm_tesselation_get_global_size(tesselation,
sub_type,
NULL,
&n_sub_elements_max);
stride = fvm_nodal_n_vertices_element[sub_type];
connect_size = FVM_MAX(connect_size,
(fvm_gnum_t)n_sub_elements_max * stride);
}
}
break;
break;
default:
connect_size = FVM_MIN(_n_g_elements_section[i], *global_s_size)
* section->stride;
}
/* Buffer size is that required for the entity type
requiring the largest buffer size */
*global_connect_s_size = FVM_MAX(*global_connect_s_size,
connect_size);
}
if (n_g_elements_section != _n_g_elements_section)
BFT_FREE(_n_g_elements_section);
}
/*============================================================================
* Public function definitions
*============================================================================*/
/*----------------------------------------------------------------------------
* Returns number of known formats.
*----------------------------------------------------------------------------*/
int
fvm_writer_n_formats(void)
{
return _fvm_writer_n_formats;
}
/*----------------------------------------------------------------------------
* Returns name of a known format.
*
* parameters:
* format_index <-- index of format in known format list (0 to n-1)
*
* returns:
* pointer to constant string containing the format's name
*----------------------------------------------------------------------------*/
const char *
fvm_writer_format_name(int format_index)
{
if (format_index >= 0 && format_index < _fvm_writer_n_formats)
return _fvm_writer_format_list[format_index].name;
else
return NULL;
}
/*----------------------------------------------------------------------------
* Returns availability of a known format.
*
* parameters:
* format_index <-- index of format in known format list (0 to n-1)
*
* returns:
* 1 if the format is available, 0 otherwise.
*----------------------------------------------------------------------------*/
int
fvm_writer_format_available(int format_index)
{
int retval = 0;
if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
if (_fvm_writer_format_list[format_index].init_func != NULL)
retval = 1;
}
return retval;
}
/*----------------------------------------------------------------------------
* Returns number of library version strings associated with a given format.
*
* For writers requiring an external library, the first associated
* version string should correspond to that library, with possible
* additional version strings for its dependencies.
*
* For writers only requiring standard libraries (libc, MPI, MPI-IO),
* this function should return 0.
*
* parameters:
* format_index <-- index of format in known format list (0 to n-1)
*
* returns:
* number of library version strings associated with a given format.
*----------------------------------------------------------------------------*/
int
fvm_writer_n_version_strings(int format_index)
{
int retval = 0;
fvm_writer_n_version_strings_t *n_version_strings_func = NULL;
if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
n_version_strings_func
= _fvm_writer_format_list[format_index].n_version_strings_func;
if (n_version_strings_func != NULL)
retval = n_version_strings_func(format_index);
}
return retval;
}
/*----------------------------------------------------------------------------
* Returns a library version string associated with a given format.
*
* We must have string_index < fvm_writer_n_version_strings(format_index).
*
* In certain cases, when using dynamic libraries, fvm may be compiled
* with one library version, and linked with another. If both run-time
* and compile-time version information is available, this function
* will return the run-time version string by default.
*
* Setting the compile_time flag to 1, the compile-time version string
* will be returned if this is different from the run-time version.
* If the version is the same, or only one of the 2 version strings are
* available, a NULL character string will be returned with this flag set.
*
* parameters:
* format_index <-- index of format in known format list (0 to n-1)
* string_index <-- index in format's version string list (0 to n-1)
* compile_time <-- 0 by default, 1 if we want the compile-time version
* string, if different from the run-time version.
*
* returns:
* pointer to constant string containing the library's version.
*----------------------------------------------------------------------------*/
const char *
fvm_writer_version_string(int format_index,
int string_index,
int compile_time_version)
{
const char * retval = NULL;
fvm_writer_version_string_t *version_string_func = NULL;
if (format_index >= 0 && format_index < _fvm_writer_n_formats) {
version_string_func
= _fvm_writer_format_list[format_index].version_string_func;
if (version_string_func != NULL)
retval = version_string_func(format_index,
string_index,
compile_time_version);
}
return retval;
}
/*----------------------------------------------------------------------------
* Initialize FVM mesh and field output writer.
*
* Allowed options depend on what is applicable to a given format. Those
* not relevant to a given writer are ignored. Possible options include:
* text output text files
* binary output binary files (default)
* big_endian force binary files to big-endian
* discard_polygons do not output polygons or related values
* discard_polyhedra do not output polyhedra or related values
* divide_polygons tesselate polygons with triangles
* divide_polyhedra tesselate polyhedra with tetrahedra and pyramids
* (adding a vertex near each polyhedron's center)
* split_tensors write tensor values as separate scalars
*
* parameters:
* name <-- base name of output
* path <-- optional directory name for output
* (directory automatically created if necessary)
* format_name <-- name of selected format (case-independent)
* format_options <-- options for the selected format (case-independent,
* whitespace or comma separated list)
* time_dependency <-- indicates if and how meshes will change with time
*
* returns:
* pointer to mesh and field output writer
*----------------------------------------------------------------------------*/
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)
{
int i;
char local_dir[] = ".";
char *tmp_path = NULL;
char *tmp_options = NULL;
fvm_writer_t *this_writer = NULL;
fvm_writer_init_t *init_func = NULL;
/* Find corresponding format and check coherency */
for (i = 0 ; i < _fvm_writer_n_formats ; i++)
if (strcmp(format_name, _fvm_writer_format_list[i].name) == 0)
break;
if (i >= _fvm_writer_n_formats)
i = _fvm_writer_format_closest_name(format_name);
if (i >= _fvm_writer_n_formats)
bft_error(__FILE__, __LINE__, 0,
_("Format type \"%s\" required for case \"%s\" is unknown"),
format_name, name);
if (!fvm_writer_format_available(i))
bft_error(__FILE__, __LINE__, 0,
_("Format type \"%s\" required for case \"%s\" is not available"),
format_name, name);
/* Create directory */
if (path != NULL) {
int l = strlen(path);
if (l > 0) {
BFT_MALLOC(tmp_path, l + 2, char);
strcpy(tmp_path, path);
if (tmp_path[l - 1] == FVM_DIR_SEPARATOR)
tmp_path[l - 1] = '\0';
if (bft_file_mkdir_default(path) == 1)
tmp_path[0] = '\0';
else {
l = strlen(tmp_path);
tmp_path[l] = FVM_DIR_SEPARATOR;
tmp_path[l+1] = '\0';
}
}
}
else
tmp_path = local_dir;
tmp_options = _fvm_writer_option_list(format_options);
/* Initialize writer */
BFT_MALLOC(this_writer, 1, fvm_writer_t);
BFT_MALLOC(this_writer->name, strlen(name) + 1, char);
strcpy(this_writer->name, name);
this_writer->format = &(_fvm_writer_format_list[i]);
this_writer->time_dep = FVM_MIN(time_dependency,
this_writer->format->max_time_dep);
this_writer->mesh_wtime = 0.;
this_writer->mesh_cpu_time = 0.;
this_writer->field_wtime = 0.;
this_writer->field_cpu_time = 0.;
/* Initialize format-specific writer */
init_func = this_writer->format->init_func;
if (init_func != NULL) {
#if defined(FVM_HAVE_MPI)
this_writer->format_writer = init_func(name,
tmp_path,
tmp_options,
this_writer->time_dep,
fvm_parall_get_mpi_comm());
#else
this_writer->format_writer = init_func(name,
tmp_path,
tmp_options,
this_writer->time_dep);
#endif
}
else
this_writer->format_writer = NULL;
if (tmp_options != NULL)
BFT_FREE(tmp_options);
if (tmp_path != local_dir)
BFT_FREE(tmp_path);
/* Return pointer to initialized writer */
return this_writer;
}
/*----------------------------------------------------------------------------
* Finalize FVM mesh and field output writer.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
*
* returns:
* NULL pointer
*----------------------------------------------------------------------------*/
fvm_writer_t *
fvm_writer_finalize(fvm_writer_t *this_writer)
{
fvm_writer_finalize_t *finalize_func = NULL;
assert(this_writer != NULL);
assert(this_writer->format != NULL);
BFT_FREE(this_writer->name);
finalize_func = this_writer->format->finalize_func;
if (finalize_func != NULL)
this_writer->format_writer = finalize_func(this_writer->format_writer);
else
this_writer->format_writer = NULL;
BFT_FREE(this_writer);
return NULL;
}
/*----------------------------------------------------------------------------
* Return a writer's name.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
*
* returns:
* pointer to base name of output associated with the writer
*----------------------------------------------------------------------------*/
const char *
fvm_writer_get_name(const fvm_writer_t *this_writer)
{
return this_writer->name;
}
/*----------------------------------------------------------------------------
* Return a writer's associated format name.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
*
* returns:
* pointer to output format name associated with the writer
*----------------------------------------------------------------------------*/
const char *
fvm_writer_get_format(const fvm_writer_t *this_writer)
{
return this_writer->format->name;
}
/*----------------------------------------------------------------------------
* Return geometry time dependency status of a writer.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
*
* returns:
* time dependency status
*----------------------------------------------------------------------------*/
fvm_writer_time_dep_t
fvm_writer_get_time_dep(const fvm_writer_t *this_writer)
{
return this_writer->time_dep;
}
/*----------------------------------------------------------------------------
* Associate new time step with a mesh.
*
* parameters:
* this_writer_p <-- pointer to associated writer
* time_step <-- time step number
* time_value <-- time_value number
*----------------------------------------------------------------------------*/
void
fvm_writer_set_mesh_time(fvm_writer_t *this_writer,
int time_step,
double time_value)
{
fvm_writer_set_mesh_time_t *set_mesh_time_func = NULL;
assert(this_writer != NULL);
assert(this_writer->format != NULL);
set_mesh_time_func = this_writer->format->set_mesh_time_func;
if (set_mesh_time_func != NULL)
set_mesh_time_func(this_writer->format_writer,
time_step,
time_value);
}
/*----------------------------------------------------------------------------
* Query if elements of a given type will need to be tesselated
* for use of a nodal mesh with an output writer.
*
* This function should be called before any fvm_writer_export_...()
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
* mesh <-- pointer to nodal mesh
* element_type <-- type of element
*
* returns:
* 0 if no tesselation is necessary, 1 if tesselation is necessary.
*----------------------------------------------------------------------------*/
int
fvm_writer_needs_tesselation(fvm_writer_t *this_writer,
const fvm_nodal_t *mesh,
fvm_element_t element_type)
{
int retval = 0;
fvm_writer_needs_tesselation_t *needs_tesselation_func = NULL;
needs_tesselation_func = this_writer->format->needs_tesselation_func;
if (needs_tesselation_func != NULL)
retval = needs_tesselation_func(this_writer->format_writer,
mesh,
element_type);
return retval;
}
/*----------------------------------------------------------------------------
* Export FVM nodal mesh.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
* mesh <-- pointer to nodal mesh
*----------------------------------------------------------------------------*/
void
fvm_writer_export_nodal(fvm_writer_t *this_writer,
const fvm_nodal_t *mesh)
{
double w_start, w_end, cpu_start, cpu_end;
fvm_writer_export_nodal_t *export_nodal_func = NULL;
assert(this_writer != NULL);
assert(this_writer->format != NULL);
w_start = bft_timer_wtime();
cpu_start = bft_timer_cpu_time();
export_nodal_func = this_writer->format->export_nodal_func;
if (export_nodal_func != NULL)
export_nodal_func(this_writer->format_writer,
mesh);
w_end = bft_timer_wtime();
cpu_end = bft_timer_cpu_time();
this_writer->mesh_wtime += (w_end - w_start);
this_writer->mesh_cpu_time += (cpu_end - cpu_start);
}
/*----------------------------------------------------------------------------
* Export field associated with a nodal mesh.
*
* Assigning a negative value to the time step indicates a time-independent
* field (in which case the time_value argument is unused).
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
* mesh <-- pointer to associated nodal mesh structure
* name <-- variable name
* location <-- variable definition location (nodes or elements)
* dimension <-- variable dimension (0: constant, 1: scalar,
* 3: vector, 6: sym. tensor, 9: asym. tensor)
* interlace <-- indicates if variable in memory is interlaced
* n_parent_lists <-- indicates if variable values are to be obtained
* directly through the local entity index (when 0) or
* through the parent entity numbers (when 1 or more)
* parent_num_shift <-- parent number to value array index shifts;
* size: n_parent_lists
* datatype <-- indicates the data type of (source) field values
* time_step <-- number of the current time step
* time_value <-- associated time value
* field_values <-- array of associated field value arrays
*----------------------------------------------------------------------------*/
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,
fvm_interlace_t interlace,
int n_parent_lists,
const fvm_lnum_t parent_num_shift[],
fvm_datatype_t datatype,
int time_step,
double time_value,
const void *const field_values[])
{
double w_start, w_end, cpu_start, cpu_end;
fvm_writer_export_field_t *export_field_func = NULL;
assert(this_writer != NULL);
assert(this_writer->format != NULL);
w_start = bft_timer_wtime();
cpu_start = bft_timer_cpu_time();
export_field_func = this_writer->format->export_field_func;
if (export_field_func != NULL)
export_field_func(this_writer->format_writer,
mesh,
name,
location,
dimension,
interlace,
n_parent_lists,
parent_num_shift,
datatype,
time_step,
time_value,
field_values);
w_end = bft_timer_wtime();
cpu_end = bft_timer_cpu_time();
this_writer->field_wtime += (w_end - w_start);
this_writer->field_cpu_time += (cpu_end - cpu_start);
}
/*----------------------------------------------------------------------------
* Flush files associated with a given writer.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
*----------------------------------------------------------------------------*/
void
fvm_writer_flush(fvm_writer_t *this_writer)
{
fvm_writer_flush_t *flush_func = NULL;
assert(this_writer != NULL);
assert(this_writer->format != NULL);
flush_func = this_writer->format->flush_func;
if (flush_func != NULL)
flush_func(this_writer->format_writer);
}
/*----------------------------------------------------------------------------
* Return accumulated wall-clock and CPU times associated with mesh and
* field exports for a given writer.
*
* parameters:
* this_writer <-- pointer to mesh and field output writer
* mesh_wtime --> Meshes output Wall-clock time (or NULL)
* mesh_cpu_time --> Meshes output CPU time (or NULL)
* field_wtime --> Fields output Wall-clock time (or NULL)
* field_cpu_time --> Fields output CPU time (or NULL)
*----------------------------------------------------------------------------*/
void
fvm_writer_get_times(fvm_writer_t *this_writer,
double *mesh_wtime,
double *mesh_cpu_time,
double *field_wtime,
double *field_cpu_time)
{
assert(this_writer != NULL);
if (mesh_wtime != NULL)
*mesh_wtime = this_writer->mesh_wtime;
if (mesh_cpu_time != NULL)
*mesh_cpu_time = this_writer->mesh_cpu_time;
if (field_wtime != NULL)
*field_wtime = this_writer->field_wtime;
if (field_cpu_time != NULL)
*field_cpu_time = this_writer->field_cpu_time;
}
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
syntax highlighted by Code2HTML, v. 0.9.1