sandbox/oystelan/output_htg.h
HyperTreeGrid (.htg) This function writes basilisk scalar and vector field data to a hyperTreegrid file (.htg), which can be loaded into the later versions of Paraview (>v5.6.0). Hypertree is an octree storage format similar to Basilisks, using x-ordering in oppose to Basilisks z-ordering. This means that the exported x and z axis will swap when exporting to this format. Using hypertree instead of vtu allows for the use of the latest hypertree filters, which support octree meshes and among other things support the generation of seamless contour meshes. The function does currently NOT support mpi.
Author: Arne Bockmann, Oystein Lande Date: July, 2019
int nlcount;
Some recursive subfunctions necessary for grid traversal
void traverse_children_to_leaf_scalar(FILE * fp, Point point, scalar f, int lvl, int ii, int jj, int kk) {
.i = ii;
point.j = jj;
point.k = kk;
point
.level = lvl + 1;
pointfor (int di = 0; di < 2; di++) {
for (int dj = 0; dj < 2; dj++) {
for (int dk = 0; dk < 2; dk++) {
.i = 2*ii - GHOSTS + di;
point.j = 2*jj - GHOSTS + dj;
point.k = 2*kk - GHOSTS + dk;
pointif is_leaf(cell) {
fprintf (fp, "%g ", f[]); // print real value
//fprintf (fp, "%d ", point.level); // print real value
} else {
fprintf (fp, "0 "); // print dummy value
}
++;
nlcountif (nlcount%6 == 0)
fprintf(fp,"\n");
}
}
}
for (int di = 0; di < 2; di++) {
for (int dj = 0; dj < 2; dj++) {
for (int dk = 0; dk < 2; dk++) {
// Her er de manglende tre linjene med kode som var kritisk for at traverseringen skulle bli riktig
.i = 2*ii - GHOSTS + di;
point.j = 2*jj - GHOSTS + dj;
point.k = 2*kk - GHOSTS + dk;
point
if is_leaf(cell) {
} else {
traverse_children_to_leaf_scalar(fp, point, f, lvl+1, 2*ii-GHOSTS+di, 2*jj-GHOSTS+dj, 2*kk-GHOSTS+dk);
}
}
}
}
}
void traverse_children_to_leaf_vector(FILE * fp, Point point, vector v, int lvl, int ii, int jj, int kk) {
.i = ii;
point.j = jj;
point.k = kk;
point
.level = lvl + 1;
pointfor (int di = 0; di < 2; di++) {
for (int dj = 0; dj < 2; dj++) {
for (int dk = 0; dk < 2; dk++) {
.i = 2*ii - GHOSTS + di;
point.j = 2*jj - GHOSTS + dj;
point.k = 2*kk - GHOSTS + dk;
pointif is_leaf(cell) {
fprintf (fp, "%g %g %g ", v.x[], v.y[], v.z[]); // print real value
//fprintf (fp, "%d ", point.level); // print real value
} else {
fprintf (fp, "0 0 0 "); // print dummy value
}
++;
nlcountif (nlcount%6 == 0)
fprintf(fp,"\n");
}
}
}
for (int di = 0; di < 2; di++) {
for (int dj = 0; dj < 2; dj++) {
for (int dk = 0; dk < 2; dk++) {
// Her er de manglende tre linjene med kode som var kritisk for at traverseringen skulle bli riktig
.i = 2*ii - GHOSTS + di;
point.j = 2*jj - GHOSTS + dj;
point.k = 2*kk - GHOSTS + dk;
point
if is_leaf(cell) {
} else {
traverse_children_to_leaf_vector(fp, point, v, lvl+1, 2*ii-GHOSTS+di, 2*jj-GHOSTS+dj, 2*kk-GHOSTS+dk);
}
}
}
}
}
This is the function you want to call. Writes scalar and vector data to .htg format
void output_htg (scalar * list, vector * vlist, FILE * fp){
#if defined(_OPENMP)
int num_omp = omp_get_max_threads();
(1);
omp_set_num_threads#endif
;
Point point
// Define the xml header of vtkHyperTreeGrid
("<VTKFile type=\"HyperTreeGrid\" version=\"0.1\" byte_order=\"LittleEndian\" header_type=\"UInt32\">\n",fp);
fputs fprintf (fp, "\t<HyperTreeGrid Dimension=\"3\" BranchFactor=\"2\" TransposedRootIndexing=\"0\" GridSize=\"1 1 1\" GridOrigin=\"0 0 0\" GridScale=\"1 1 1\">\n");
("\t\t<Coordinates>\n",fp);
fputs ("\t\t\t<DataArray type=\"Float64\" Name=\"XCoordinates\" NumberOfTuples=\"2\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n",fp);
fputs fprintf (fp, "\t\t\t%g %g\n",X0,L0+X0);
("\t\t\t</DataArray>\n",fp);
fputs ("\t\t\t<DataArray type=\"Float64\" Name=\"YCoordinates\" NumberOfTuples=\"2\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n",fp);
fputs fprintf (fp, "\t\t\t%g %g\n",Y0,L0+Y0);
("\t\t\t</DataArray>\n",fp);
fputs ("\t\t\t<DataArray type=\"Float64\" Name=\"ZCoordinates\" NumberOfTuples=\"2\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n",fp);
fputs fprintf (fp, "\t\t\t%g %g\n",Z0,L0+Z0);
("\t\t\t</DataArray>\n",fp);
fputs ("\t\t</Coordinates>\n",fp);
fputs ("\t\t<Topology>\n",fp);
fputs ("\t\t\t<DataArray type=\"Int64\" Name=\"MaterialMaskIndex\" NumberOfTuples=\"1\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"0\">\n",fp);
fputs ("\t\t\t0\n",fp);
fputs ("\t\t\t</DataArray>\n",fp);
fputs // Find number of cells (excluding halo cells)
= 0;
nlcount for (int lvl = 0; lvl <= depth(); lvl++) {
(lvl) {
foreach_level++;
nlcount }
}
fprintf(fp, "\t\t\t<DataArray type=\"Bit\" Name=\"Descriptor\" NumberOfTuples=\"%d\" format=\"ascii\" RangeMin=\"0\" RangeMax=\"1\">\n",nlcount);
// Set bit
= 0;
nlcount for (int lvl = 0; lvl <= depth(); lvl++) {
(lvl) {
foreach_levelif (is_leaf(cell)) {
("0 ", fp);
fputs}
else {
("1 ", fp);
fputs}
++;
nlcountif (nlcount%6 == 0)
("\n", fp); // line break every 6th number
fputs}
}
if (nlcount%6 != 0)
("\n", fp); // line break every 6th number
fputs
("\t\t\t</DataArray>\n",fp);
fputs ("\t\t</Topology>\n",fp);
fputs
// insert pointdata arrays
("\t\t<PointData>\n",fp);
fputs = 1;
nlcount for (scalar s in list) {
fprintf(fp,"\t\t\t<DataArray type=\"Float64\" Name=\"%s\" format=\"ascii\">\n",s.name);
fprintf(fp, "-1 ");
traverse_children_to_leaf_scalar(fp, point, s, 0, GHOSTS, GHOSTS, GHOSTS);
("\n\t\t\t</DataArray>\n",fp);
fputs }
for (vector v in vlist) {
char *vname = strtok(v.x.name, ".");
fprintf (fp, "\t\t\t<DataArray type=\"Float64\" NumberOfComponents=\"3\" Name=\"%s\" format=\"ascii\">\n",vname);
fprintf (fp, "-1 -1 -1 ");
traverse_children_to_leaf_vector(fp, point, v, 0, GHOSTS, GHOSTS, GHOSTS);
("\n\t\t\t</DataArray>\n",fp);
fputs }
("\t\t</PointData>\n",fp);
fputs ("\t</HyperTreeGrid>\n",fp);
fputs ("</VTKFile>\n",fp);
fputs
#if defined(_OPENMP)
(num_omp);
omp_set_num_threads#endif
}