const char *tecplot_cell_type[4] = {"", "lineseg", "quadrilateral", "brick"};
-#ifdef DEAL_II_HAVE_TECPLOT
- const unsigned int tecplot_binary_cell_type[4] = {0, 0, 1, 3};
-#endif
-
-
/**
* Return the tuple (vtk cell type, number of cells, number of nodes)
* for a patch.
if (format_name == "tecplot")
return tecplot;
- if (format_name == "tecplot_binary")
- return tecplot_binary;
-
if (format_name == "vtk")
return vtk;
std::string
get_output_format_names()
{
- return "none|dx|ucd|gnuplot|povray|eps|gmv|tecplot|tecplot_binary|vtk|vtu|hdf5|svg|deal.II intermediate";
+ return "none|dx|ucd|gnuplot|povray|eps|gmv|tecplot|vtk|vtu|hdf5|svg|deal.II intermediate";
}
return ".gmv";
case tecplot:
return ".dat";
- case tecplot_binary:
- return ".plt";
case vtk:
return ".vtk";
case vtu:
- //---------------------------------------------------------------------------
- // Macros for handling Tecplot API data
-
-#ifdef DEAL_II_HAVE_TECPLOT
-
- namespace
- {
- class TecplotMacros
- {
- public:
- TecplotMacros(const unsigned int n_nodes = 0,
- const unsigned int n_vars = 0,
- const unsigned int n_cells = 0,
- const unsigned int n_vert = 0);
- ~TecplotMacros();
- float &
- nd(const unsigned int i, const unsigned int j);
- int &
- cd(const unsigned int i, const unsigned int j);
- std::vector<float> nodalData;
- std::vector<int> connData;
-
- private:
- unsigned int n_nodes;
- unsigned int n_vars;
- unsigned int n_cells;
- unsigned int n_vert;
- };
-
-
- inline TecplotMacros::TecplotMacros(const unsigned int n_nodes,
- const unsigned int n_vars,
- const unsigned int n_cells,
- const unsigned int n_vert)
- : n_nodes(n_nodes)
- , n_vars(n_vars)
- , n_cells(n_cells)
- , n_vert(n_vert)
- {
- nodalData.resize(n_nodes * n_vars);
- connData.resize(n_cells * n_vert);
- }
-
-
-
- inline TecplotMacros::~TecplotMacros()
- {}
-
-
-
- inline float &
- TecplotMacros::nd(const unsigned int i, const unsigned int j)
- {
- return nodalData[i * n_nodes + j];
- }
-
-
-
- inline int &
- TecplotMacros::cd(const unsigned int i, const unsigned int j)
- {
- return connData[i + j * n_vert];
- }
-
- } // namespace
-
-
-#endif
- //---------------------------------------------------------------------------
-
-
-
- template <int dim, int spacedim>
- void
- write_tecplot_binary(
- const std::vector<Patch<dim, spacedim>> &patches,
- const std::vector<std::string> & data_names,
- const std::vector<
- std::tuple<unsigned int,
- unsigned int,
- std::string,
- DataComponentInterpretation::DataComponentInterpretation>>
- & nonscalar_data_ranges,
- const TecplotFlags &flags,
- std::ostream & out)
- {
- // The FEBLOCK or FEPOINT formats of tecplot only allows full elements (e.g.
- // triangles), not single points. Other tecplot format allow point output,
- // but they are currently not implemented.
- AssertThrow(dim > 0, ExcNotImplemented());
-
-#ifndef DEAL_II_HAVE_TECPLOT
-
- // simply call the ASCII output function if the Tecplot API isn't present
- write_tecplot(patches, data_names, nonscalar_data_ranges, flags, out);
- return;
-
-#else
-
- // Tecplot binary output only good for 2d & 3d
- if (dim == 1)
- {
- write_tecplot(patches, data_names, nonscalar_data_ranges, flags, out);
- return;
- }
-
- // if the user hasn't specified a file name we should call the ASCII
- // function and use the ostream @p{out} instead of doing something silly
- // later
- char *file_name = (char *)flags.tecplot_binary_file_name;
-
- if (file_name == nullptr)
- {
- // At least in debug mode we should tell users why they don't get
- // tecplot binary output
- Assert(false,
- ExcMessage("Specify the name of the tecplot_binary"
- " file through the TecplotFlags interface."));
- write_tecplot(patches, data_names, nonscalar_data_ranges, flags, out);
- return;
- }
-
-
- AssertThrow(out.fail() == false, ExcIO());
-
-# ifndef DEAL_II_WITH_MPI
- // verify that there are indeed patches to be written out. most of the
- // times, people just forget to call build_patches when there are no
- // patches, so a warning is in order. that said, the assertion is disabled
- // if we support MPI since then it can happen that on the coarsest mesh, a
- // processor simply has no cells it actually owns, and in that case it is
- // legit if there are no patches
- Assert(patches.size() > 0, ExcNoPatches());
-# else
- if (patches.size() == 0)
- return;
-# endif
-
- const unsigned int n_data_sets = data_names.size();
- // check against # of data sets in first patch. checks against all other
- // patches are made in write_gmv_reorder_data_vectors
- Assert((patches[0].data.n_rows() == n_data_sets &&
- !patches[0].points_are_available) ||
- (patches[0].data.n_rows() == n_data_sets + spacedim &&
- patches[0].points_are_available),
- ExcDimensionMismatch(patches[0].points_are_available ?
- (n_data_sets + spacedim) :
- n_data_sets,
- patches[0].data.n_rows()));
-
- // first count the number of cells and cells for later use
- unsigned int n_nodes;
- unsigned int n_cells;
- std::tie(n_nodes, n_cells) = count_nodes_and_cells(patches);
- // local variables only needed to write Tecplot binary output files
- const unsigned int vars_per_node = (spacedim + n_data_sets),
- nodes_per_cell = GeometryInfo<dim>::vertices_per_cell;
-
- TecplotMacros tm(n_nodes, vars_per_node, n_cells, nodes_per_cell);
-
- int is_double = 0, tec_debug = 0, cell_type = tecplot_binary_cell_type[dim];
-
- std::string tec_var_names;
- switch (spacedim)
- {
- case 2:
- tec_var_names = "x y";
- break;
- case 3:
- tec_var_names = "x y z";
- break;
- default:
- Assert(false, ExcNotImplemented());
- }
-
- for (unsigned int data_set = 0; data_set < n_data_sets; ++data_set)
- {
- tec_var_names += " ";
- tec_var_names += data_names[data_set];
- }
-
- // For the format we write here, we need to write all node values relating
- // to one variable at a time. We could in principle do this by looping
- // over all patches and extracting the values corresponding to the one
- // variable we're dealing with right now, and then start the process over
- // for the next variable with another loop over all patches.
- //
- // An easier way is to create a global table that for each variable
- // lists all values. This copying of data vectors can be done in the
- // background while we're already working on vertices and cells,
- // so do this on a separate task and when wanting to write out the
- // data, we wait for that task to finish.
- Threads::Task<std::unique_ptr<Table<2, double>>>
- create_global_data_table_task = Threads::new_task(
- [&patches]() { return create_global_data_table(patches); });
-
- //-----------------------------
- // first make up a list of used vertices along with their coordinates
- for (unsigned int d = 1; d <= spacedim; ++d)
- {
- unsigned int entry = 0;
-
- for (const auto &patch : patches)
- {
- const unsigned int n_subdivisions = patch.n_subdivisions;
-
- switch (dim)
- {
- case 2:
- {
- for (unsigned int j = 0; j < n_subdivisions + 1; ++j)
- for (unsigned int i = 0; i < n_subdivisions + 1; ++i)
- {
- const double x_frac = i * 1. / n_subdivisions,
- y_frac = j * 1. / n_subdivisions;
-
- tm.nd((d - 1), entry) = static_cast<float>(
- (((patch.vertices[1](d - 1) * x_frac) +
- (patch.vertices[0](d - 1) * (1 - x_frac))) *
- (1 - y_frac) +
- ((patch.vertices[3](d - 1) * x_frac) +
- (patch.vertices[2](d - 1) * (1 - x_frac))) *
- y_frac));
- entry++;
- }
- break;
- }
-
- case 3:
- {
- for (unsigned int j = 0; j < n_subdivisions + 1; ++j)
- for (unsigned int k = 0; k < n_subdivisions + 1; ++k)
- for (unsigned int i = 0; i < n_subdivisions + 1; ++i)
- {
- const double x_frac = i * 1. / n_subdivisions,
- y_frac = k * 1. / n_subdivisions,
- z_frac = j * 1. / n_subdivisions;
-
- // compute coordinates for this patch point
- tm.nd((d - 1), entry) = static_cast<float>(
- ((((patch.vertices[1](d - 1) * x_frac) +
- (patch.vertices[0](d - 1) * (1 - x_frac))) *
- (1 - y_frac) +
- ((patch.vertices[3](d - 1) * x_frac) +
- (patch.vertices[2](d - 1) * (1 - x_frac))) *
- y_frac) *
- (1 - z_frac) +
- (((patch.vertices[5](d - 1) * x_frac) +
- (patch.vertices[4](d - 1) * (1 - x_frac))) *
- (1 - y_frac) +
- ((patch.vertices[7](d - 1) * x_frac) +
- (patch.vertices[6](d - 1) * (1 - x_frac))) *
- y_frac) *
- z_frac));
- entry++;
- }
- break;
- }
-
- default:
- Assert(false, ExcNotImplemented());
- }
- }
- }
-
-
- //-------------------------------------
- // Wait for the reordering to be done and retrieve the reordered data:
- const Table<2, double> data_vectors =
- std::move(*create_global_data_table_task.return_value());
-
- // then write data.
- for (unsigned int data_set = 0; data_set < n_data_sets; ++data_set)
- for (unsigned int entry = 0; entry < data_vectors[data_set].size();
- entry++)
- tm.nd((spacedim + data_set), entry) =
- static_cast<float>(data_vectors[data_set][entry]);
-
-
-
- //-------------------------------
- // now for the cells. note that vertices are counted from 1 onwards
- unsigned int first_vertex_of_patch = 0;
- unsigned int elem = 0;
-
- for (const auto &patch : patches)
- {
- const unsigned int n_subdivisions = patch.n_subdivisions;
- const unsigned int n = n_subdivisions + 1;
- const unsigned int d1 = 1;
- const unsigned int d2 = n;
- const unsigned int d3 = n * n;
- // write out the cells making up this patch
- switch (dim)
- {
- case 2:
- {
- for (unsigned int i2 = 0; i2 < n_subdivisions; ++i2)
- for (unsigned int i1 = 0; i1 < n_subdivisions; ++i1)
- {
- tm.cd(0, elem) =
- first_vertex_of_patch + (i1)*d1 + (i2)*d2 + 1;
- tm.cd(1, elem) =
- first_vertex_of_patch + (i1 + 1) * d1 + (i2)*d2 + 1;
- tm.cd(2, elem) = first_vertex_of_patch + (i1 + 1) * d1 +
- (i2 + 1) * d2 + 1;
- tm.cd(3, elem) =
- first_vertex_of_patch + (i1)*d1 + (i2 + 1) * d2 + 1;
-
- elem++;
- }
- break;
- }
-
- case 3:
- {
- for (unsigned int i3 = 0; i3 < n_subdivisions; ++i3)
- for (unsigned int i2 = 0; i2 < n_subdivisions; ++i2)
- for (unsigned int i1 = 0; i1 < n_subdivisions; ++i1)
- {
- // note: vertex indices start with 1!
-
-
- tm.cd(0, elem) = first_vertex_of_patch + (i1)*d1 +
- (i2)*d2 + (i3)*d3 + 1;
- tm.cd(1, elem) = first_vertex_of_patch + (i1 + 1) * d1 +
- (i2)*d2 + (i3)*d3 + 1;
- tm.cd(2, elem) = first_vertex_of_patch + (i1 + 1) * d1 +
- (i2 + 1) * d2 + (i3)*d3 + 1;
- tm.cd(3, elem) = first_vertex_of_patch + (i1)*d1 +
- (i2 + 1) * d2 + (i3)*d3 + 1;
- tm.cd(4, elem) = first_vertex_of_patch + (i1)*d1 +
- (i2)*d2 + (i3 + 1) * d3 + 1;
- tm.cd(5, elem) = first_vertex_of_patch + (i1 + 1) * d1 +
- (i2)*d2 + (i3 + 1) * d3 + 1;
- tm.cd(6, elem) = first_vertex_of_patch + (i1 + 1) * d1 +
- (i2 + 1) * d2 + (i3 + 1) * d3 + 1;
- tm.cd(7, elem) = first_vertex_of_patch + (i1)*d1 +
- (i2 + 1) * d2 + (i3 + 1) * d3 + 1;
-
- elem++;
- }
- break;
- }
-
- default:
- Assert(false, ExcNotImplemented());
- }
-
-
- // finally update the number of the first vertex of this patch
- first_vertex_of_patch += Utilities::fixed_power<dim>(n);
- }
-
-
- {
- int ierr = 0, num_nodes = static_cast<int>(n_nodes),
- num_cells = static_cast<int>(n_cells);
-
- char dot[2] = {'.', 0};
- // Unfortunately, TECINI takes a char *, but c_str() gives a const char *.
- // As we don't do anything else with tec_var_names following const_cast is
- // ok
- char *var_names = const_cast<char *>(tec_var_names.c_str());
- ierr = TECINI(nullptr, var_names, file_name, dot, &tec_debug, &is_double);
-
- Assert(ierr == 0, ExcErrorOpeningTecplotFile(file_name));
-
- char FEBLOCK[] = {'F', 'E', 'B', 'L', 'O', 'C', 'K', 0};
- ierr =
- TECZNE(nullptr, &num_nodes, &num_cells, &cell_type, FEBLOCK, nullptr);
-
- Assert(ierr == 0, ExcTecplotAPIError());
-
- int total = (vars_per_node * num_nodes);
-
- ierr = TECDAT(&total, tm.nodalData.data(), &is_double);
-
- Assert(ierr == 0, ExcTecplotAPIError());
-
- ierr = TECNOD(tm.connData.data());
-
- Assert(ierr == 0, ExcTecplotAPIError());
-
- ierr = TECEND();
-
- Assert(ierr == 0, ExcTecplotAPIError());
- }
-#endif
- }
-
-
-
template <int dim, int spacedim>
void
write_vtk(