sandbox/acastillo/output_fields/vtu/output_vtu_facets.h
#ifndef OUTPUT_VTU_FACETS_H
#define OUTPUT_VTU_FACETS_Houtput_facets_vtu(): Exports the VOF interface.
This function writes a surface from field data using the built-in VOF PLIC surface. The file also stores a scalar field at the cell center of an unstructured grid with the following structure:
|
|
|
|
|
This extends the routines in output_surfaces.h.
by Oystein Lande in two points: one, this is extended to write a single
.vtu file when using MPI; and two, heavy data is stored in raw binary
format.
The arguments and their default values are:
- c
- vof scalar field.
- s
- scalar field to store, for instance, curvature.
- subname
- subname to be used for the output file.
Example Usage
scalar kappa[];
curvature (f, kappa);
output_facets_vtu(f, kappa, "Interface");see, also example.
#include "output_vtu_helpers.h"
// Function prototypes
void output_facets_pid(scalar c, scalar s, char *subname);
#ifdef _MPI
void output_facets_pvtu(scalar c, scalar s, char *subname);
#endif
trace
void output_facets_vtu(scalar c, scalar s, char *subname){
// Check if MPI is defined
@ if _MPI
// If MPI is defined, call output_pvtu to handle parallel VTU output
output_facets_pvtu(c, s, subname);
@ else
// If MPI is not defined, call output_vtu_pid to handle serial VTU output
output_facets_pid(c, s, subname);
@endif
}output_facets_pid():
writes one .vtu file for the current process
void output_facets_pid(scalar c, scalar kappa, char *subname)
{
#if defined(_OPENMP)
// Save current number of OpenMP threads and set it to 1 for this function
int num_omp = omp_get_max_threads();
omp_set_num_threads(1);
#endifConstruct the filename and open the file for writing
Obtain the number of vertices (points) and assets (cells)
long nverts = 0, nfacets = 0;
count_vertices_and_facets(c, &nverts, &nfacets);Declare arrays to store vertex coordinates and facet offsets
double *pt_array_x = malloc(nverts * sizeof(double));
double *pt_array_y = malloc(nverts * sizeof(double));
#if dimension <= 2
double *pt_array_z = NULL;
#else
double *pt_array_z = malloc(nverts * sizeof(double));
#endif
long *offsets = malloc(nfacets * sizeof(long));Populate the arrays with vertex coordinates and facet offsets
populate_vertex_and_offset_arrays(c, nverts, nfacets, pt_array_x, pt_array_y, pt_array_z, offsets);Populate the arrays with the curvature kappa
double *fc_array_kappa = malloc(nfacets * sizeof(double));
populate_facet_arrays(c, kappa, nverts, nfacets, fc_array_kappa);Set cell type: VTK_POLY_LINE for 2D, VTK_POLYGON for 3D
#if dimension <= 2
char type = 4; // VTK_POLY_LINE (=4)
#else
char type = 7; // VTK_POLYGON (=7)
#endifCounter to keep track of the byte offsets in the VTK file
long count = 0.;Write the light data
write_vtu_header(fp, nverts, nfacets); // Write the VTU file header
write_points_light_data(fp, &count, nverts); // Write points data array
write_cells_light_data(fp, &count, nfacets, nverts); // Write cells data arrays
write_scalar_light_data(fp, {kappa}, NULL, &count, nfacets); // Write scalar data arrays
write_vtu_appended(fp); // Write the VTU appended data sectionWrite the points (vertices) data to the VTK file
write_points_heavy_data_array(fp, nverts, pt_array_x, pt_array_y, pt_array_z); // Write points data
write_cell_offsets2(fp, nfacets, offsets); // Write cell offsets
write_cell_types(fp, nfacets, type); // Write cell types
write_cell_offsets3(fp, nverts); // Write cell offsets
write_scalar_heavy_data_array(fp, nfacets, fc_array_kappa); // Write cell curvatureand close the file
fputs("\t\n", fp);
fputs("\t </AppendedData>\n", fp);
fputs("</VTKFile>\n", fp);
fflush(fp); // Flush the file buffer
fclose(fp); // Close the VTU file
free(offsets);
free(pt_array_x);
free(pt_array_y);
#if dimension == 3
free(pt_array_z);
#endif
free(fc_array_kappa);
#if defined(_OPENMP)
omp_set_num_threads(num_omp);
#endif
}output_facets_pvtu():
if MPI, writes one .pvtu and .vtu for each
process
@ if _MPI
void output_facets_pvtu(scalar c, scalar kappa, char *subname){
#if defined(_OPENMP)
// Save current number of OpenMP threads and set it to 1 for this function
int num_omp = omp_get_max_threads();
omp_set_num_threads(1);
#endifObtain the number of vertices (points) and assets (cells)
long nverts_long = 0, nfacets_long = 0;
count_vertices_and_facets(c, &nverts_long, &nfacets_long);
int nverts = (int)nverts_long, nfacets = (int)nfacets_long;Declare arrays to store vertex coordinates and facet offsets
double *pt_array_x = malloc(nverts * sizeof(double));
double *pt_array_y = malloc(nverts * sizeof(double));
#if dimension <= 2
double *pt_array_z = NULL;
#else
double *pt_array_z = malloc(nverts * sizeof(double));
#endif
long *offsets = malloc(nfacets * sizeof(long));Populate the arrays with vertex coordinates and facet offsets
populate_vertex_and_offset_arrays(c, nverts_long, nfacets_long, pt_array_x, pt_array_y, pt_array_z, offsets);Populate the arrays with the curvature kappa
double *fc_array_kappa = malloc(nfacets * sizeof(double));
populate_facet_arrays(c, kappa, nverts, nfacets, fc_array_kappa);Global variables to store the total number of vertices and facets across all processes
long glob_nverts = 0, glob_nfacets = 0;
MPI_Allreduce(&nverts_long, &glob_nverts, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce(&nfacets_long, &glob_nfacets, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);Arrays to store the number of vertices and facets per process
int list_nverts[npe()], pos_nverts[npe()];
int list_nfacets[npe()], pos_nfacets[npe()];Gather the number of vertices and facets from all processes
MPI_Allgather(&nverts, 1, MPI_INT, list_nverts, 1, MPI_INT, MPI_COMM_WORLD);
MPI_Allgather(&nfacets, 1, MPI_INT, list_nfacets, 1, MPI_INT, MPI_COMM_WORLD);Calculate the starting positions for vertices and facets for each process
pos_nverts[0] = 0;
pos_nfacets[0] = 0;
for (int i = 1; i < npe(); i++){
pos_nverts[i] = pos_nverts[i - 1] + list_nverts[i - 1];
pos_nfacets[i] = pos_nfacets[i - 1] + list_nfacets[i - 1];
}Adjust facet offsets for the current process
for (int i = 0; i < nfacets; i++)
offsets[i] = offsets[i] + pos_nverts[pid()];
// Pointers for global arrays (only used by the root process)
long *glob_offsets = NULL;
double *glob_pt_array_x = NULL;
double *glob_pt_array_y = NULL;
double *glob_pt_array_z = NULL;
double *glob_fc_array_kappa = NULL;Gather the data from each process
const int root = 0;
if (pid() == root){
// Allocate memory for global arrays on the root process
glob_offsets = malloc(glob_nfacets * sizeof(long));
glob_pt_array_x = malloc(glob_nverts * sizeof(double));
glob_pt_array_y = malloc(glob_nverts * sizeof(double));
#if dimension == 3
glob_pt_array_z = malloc(glob_nverts * sizeof(double));
#endif
glob_fc_array_kappa = malloc(glob_nfacets * sizeof(double));
}
// Gather vertex and facet data from all processes to the root process
MPI_Gatherv(offsets, nfacets, MPI_LONG, glob_offsets, list_nfacets, pos_nfacets, MPI_LONG, root, MPI_COMM_WORLD);
MPI_Gatherv(pt_array_x, nverts, MPI_DOUBLE, glob_pt_array_x, list_nverts, pos_nverts, MPI_DOUBLE, root, MPI_COMM_WORLD);
MPI_Gatherv(pt_array_y, nverts, MPI_DOUBLE, glob_pt_array_y, list_nverts, pos_nverts, MPI_DOUBLE, root, MPI_COMM_WORLD);
#if dimension == 3
MPI_Gatherv(pt_array_z, nverts, MPI_DOUBLE, glob_pt_array_z, list_nverts, pos_nverts, MPI_DOUBLE, root, MPI_COMM_WORLD);
#endif
MPI_Gatherv(fc_array_kappa, nfacets, MPI_DOUBLE, glob_fc_array_kappa, list_nfacets, pos_nfacets, MPI_DOUBLE, root, MPI_COMM_WORLD);
// Free local arrays
free(offsets);
free(pt_array_x);
free(pt_array_y);
#if dimension == 3
free(pt_array_z);
#endif
free(fc_array_kappa);Only the root process writes the data to the VTK file
if (pid() == root){
#if dimension <= 2
char type = 4; // VTK_POLY_LINE (=4)
#else
char type = 7; // VTK_POLYGON (=7)
#endif
// Construct the filename and open the file for writing
char name[99];
sprintf(name, "%s.vtu", subname);
FILE *fp = fopen(name, "w");
// Counter to keep track of the byte offsets in the VTK file
long count = 0;
write_vtu_header(fp, glob_nverts, glob_nfacets); // Write the VTU file header
write_points_light_data(fp, &count, glob_nverts); // Write points data array
write_cells_light_data(fp, &count, glob_nfacets, glob_nverts); // Write cells data arrays
write_scalar_light_data(fp, {kappa}, NULL, &count, nfacets); // Write scalar data arrays
write_vtu_appended(fp); // Write the VTU appended data section
// Write the points (vertices) data to the VTK file
write_points_heavy_data_array(fp, glob_nverts, glob_pt_array_x, glob_pt_array_y, glob_pt_array_z);
write_cell_offsets2(fp, glob_nfacets, glob_offsets); // Write cell offsets
write_cell_types(fp, glob_nfacets, type); // Write cell types
write_cell_offsets3(fp, glob_nverts); // Write cell offsets
write_scalar_heavy_data_array(fp, glob_nfacets, glob_fc_array_kappa); // Write cell curvature
fputs("\t\n", fp);
fputs("\t </AppendedData>\n", fp);
fputs("</VTKFile>\n", fp);
fflush(fp); // Flush the file buffer
fclose(fp); // Close the VTU file
// Free allocated memory
free(glob_offsets);
free(glob_pt_array_x);
free(glob_pt_array_y);
#if dimension == 3
free(glob_pt_array_z);
#endif
free(glob_fc_array_kappa);
}
#if defined(_OPENMP)
omp_set_num_threads(num_omp);
#endif
}
@endif
#endif
