1 #pragma once // Ensure that file is included only once in a single compilation.
123 const std::string& option,
124 std::string value =
"")
128 else if (option ==
"outputDir")
130 else if (option ==
"fileName")
132 else if (option ==
"fileEnding")
137 hy_assert(
false,
"You have chosen an invalid file type!");
139 else if (option ==
"fileNumber")
141 else if (option ==
"printFileNumber")
143 else if (option ==
"incrementFileNumber")
145 else if (option ==
"plotEdges")
146 plot_options.
plot_edges = (value ==
"true" || value ==
"1");
147 else if (option ==
"plotEdgeBoundaries")
149 else if (option ==
"boundaryScale")
151 else if (option ==
"scale")
152 plot_options.
scale = stof(value);
154 hy_assert(
false,
"This plot option has not been defined (yet).");
156 std::string return_value;
157 if (option ==
"outputDir")
159 else if (option ==
"fileName")
160 return_value = plot_options.
fileName;
161 else if (option ==
"fileEnding")
163 else if (option ==
"fileNumber")
164 return_value = std::to_string(plot_options.
fileNumber);
165 else if (option ==
"printFileNumber")
167 else if (option ==
"incrementFileNumber")
169 else if (option ==
"plotEdges")
170 return_value = std::to_string(plot_options.
plot_edges);
171 else if (option ==
"plotEdgeBoundaries")
173 else if (option ==
"scale")
174 return_value = std::to_string(plot_options.
scale);
175 else if (option ==
"boundaryScale")
178 hy_assert(
false,
"This plot option has not been defined (yet).");
207 template <
typename HyperGraphT,
typename LocalSolverT,
typename LargeVecT,
typename floatT =
float>
208 void plot(HyperGraphT& hyper_graph,
210 const LargeVecT& lambda,
212 const floatT time = 0.);
238 case PlotOptions::fileType::vtu:
241 hy_assert(
false,
"File type seems to be invalid.");
249 std::ofstream myfile;
253 filename +=
"." + std::to_string(plot_options.
fileNumber);
255 if (std::filesystem::create_directory(plot_options.
outputDir))
256 std::cout <<
"Directory \"" << plot_options.
outputDir <<
"\" has been created." << std::endl;
259 myfile.open(filename, std::ios_base::app);
261 myfile.open(filename, std::ios_base::out);
263 "The file has not been created. Most likely, the filesystem could not"
264 <<
" create the output directory, since std::filesystem has not been available."
266 <<
"Please, try to create the output directoy manually and run the code again.");
287 template <
unsigned int dim,
typename pt_index_t>
290 if constexpr (dim == 0)
291 for (
unsigned int i = 0; i < n - 1; ++i)
292 output << offset + i <<
"\n";
293 else if constexpr (dim == 1)
294 for (
unsigned int i = 0; i < n - 1; ++i)
295 output << offset + i <<
' ' << offset + i + 1 <<
"\n";
296 else if constexpr (dim == 2)
297 for (
unsigned int i = 0; i < n - 1; ++i)
298 for (
unsigned int j = 0; j < n - 1; ++j)
299 output << offset + i * n + j <<
' ' << offset + i * n + j + 1 <<
' '
300 << offset + i * n + j + n <<
' ' << offset + i * n + j + n + 1 <<
"\n";
301 else if constexpr (dim == 3)
303 const unsigned int nn = n * n;
304 for (
unsigned int i = 0; i < n - 1; ++i)
305 for (
unsigned int j = 0; j < n - 1; ++j)
306 for (
unsigned int k = 0; k < n - 1; ++k)
307 output << offset + (i * n + j) * n + k <<
' ' << offset + (i * n + j) * n + k + 1 <<
' '
308 << offset + (i * n + j) * n + k + n <<
' ' << offset + (i * n + j) * n + k + n + 1
309 <<
' ' << offset + (i * n + j) * n + k + nn <<
' '
310 << offset + (i * n + j) * n + k + nn + 1 <<
' '
311 << offset + (i * n + j) * n + k + nn + n <<
' '
312 << offset + (i * n + j) * n + k + nn + n + 1 <<
"\n";
329 template <
class HyperGraphT,
330 unsigned int n_subpoints,
331 typename hyEdge_index_t =
unsigned int,
332 typename pt_index_t =
unsigned int>
334 HyperGraphT& hyper_graph,
339 constexpr
unsigned int edge_dim = HyperGraphT::hyEdge_dim();
340 constexpr
unsigned int space_dim = HyperGraphT::space_dim();
342 const hyEdge_index_t n_edges = hyper_graph.n_hyEdges();
349 const hyEdge_index_t n_boundaries_per_edge = 2 * edge_dim;
350 const hyEdge_index_t n_edge_boundaries = n_edges * n_boundaries_per_edge;
352 const pt_index_t n_plot_boundaries =
359 const pt_index_t n_plot_points =
360 (plot_options.
plot_edges ? (points_per_edge * n_edges) : 0) +
362 const pt_index_t n_plot_cells = (plot_options.
plot_edges ? n_plot_edges : 0) +
366 static_assert(edge_dim <= 3);
367 unsigned int element_id;
368 if constexpr (edge_dim == 1)
370 else if constexpr (edge_dim == 2)
372 else if constexpr (edge_dim == 3)
374 unsigned int boundary_element_id = 0;
375 if constexpr (edge_dim == 1)
376 boundary_element_id = 1;
377 else if constexpr (edge_dim == 2)
378 boundary_element_id = 3;
379 else if constexpr (edge_dim == 3)
380 boundary_element_id = 8;
382 output <<
" <Piece NumberOfPoints=\"" << n_plot_points <<
"\" NumberOfCells= \""
383 << n_plot_cells <<
"\">" << std::endl;
384 output <<
" <Points>" << std::endl;
385 output <<
" <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">"
390 for (hyEdge_index_t he_number = 0; he_number < n_edges; ++he_number)
392 auto edge = hyper_graph.hyEdge_geometry(he_number);
394 for (
unsigned int pt_number = 0; pt_number < points_per_edge; ++pt_number)
398 (
Point<space_dim>)edge.template lexicographic<n_subpoints>(pt_number, sub_points);
399 for (
unsigned int dim = 0; dim < space_dim; ++dim)
400 output <<
" " << std::fixed << std::scientific << std::setprecision(3) << point[dim];
401 for (
unsigned int dim = space_dim; dim < 3; ++dim)
410 for (hyEdge_index_t he_number = 0; he_number < n_edges; ++he_number)
412 auto edge = hyper_graph.hyEdge_geometry(he_number);
413 for (hyEdge_index_t boundary = 0; boundary < n_boundaries_per_edge; ++boundary)
415 for (
unsigned int pt_number = 0; pt_number < points_per_boundary; ++pt_number)
420 pt_number, boundary, plot_options.
boundary_scale, boundary_sub_points);
423 for (
unsigned int dim = 0; dim < space_dim; ++dim)
425 output <<
" " << std::fixed << std::scientific << std::setprecision(3) << point[dim];
428 for (
unsigned int dim = 0; dim < space_dim; ++dim)
430 output <<
" " << std::fixed << std::scientific << std::setprecision(3) << point[dim];
432 for (
unsigned int dim = space_dim; dim < 3; ++dim)
440 output <<
" </DataArray>" << std::endl;
441 output <<
" </Points>" << std::endl;
442 output <<
" <Cells>" << std::endl;
443 output <<
" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">"
446 pt_index_t offset = 0;
448 for (hyEdge_index_t he_number = 0; he_number < n_edges; ++he_number)
450 vtu_sub_cube_connectivity<edge_dim>(output, n_subpoints, offset);
451 offset += points_per_edge;
454 for (pt_index_t i = 0; i < n_edge_boundaries; ++i)
457 offset += points_per_boundary;
460 hy_assert(offset == n_plot_points,
"We did not write the right number of connectivity data");
462 output <<
" </DataArray>" << std::endl;
463 output <<
" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << std::endl;
465 int start_number = 0;
468 for (hyEdge_index_t he_number = 1; he_number <= n_plot_edges; ++he_number)
476 for (hyEdge_index_t bdr_number = 1; bdr_number <= n_plot_boundaries; ++bdr_number)
481 output <<
" </DataArray>" << std::endl;
482 output <<
" <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << std::endl;
486 for (hyEdge_index_t he_number = 0; he_number < n_plot_edges; ++he_number)
487 output <<
" " << element_id;
491 for (hyEdge_index_t bdr_number = 1; bdr_number <= n_plot_boundaries; ++bdr_number)
492 output <<
" " << boundary_element_id;
496 output <<
" </DataArray>" << std::endl;
497 output <<
" </Cells>" << std::endl;
504 template <
unsigned int edge_dim,
class HyperGraphT,
typename hyEdge_index_t,
typename LargeVecT>
505 std::array<std::array<
typename LargeVecT::value_type, HyperGraphT::n_dofs_per_node()>, 2 * edge_dim>
508 std::array<std::array<
typename LargeVecT::value_type, HyperGraphT::n_dofs_per_node()>,
512 hyEdge_hyNodes = hyper_graph.hyEdge_topology(edge_index).get_hyNode_indices();
513 for (
unsigned int hyNode = 0; hyNode < hyEdge_hyNodes.
size(); ++hyNode)
515 hyEdge_dofs[hyNode] = hyper_graph.hyNode_factory().get_dof_values(hyEdge_hyNodes[hyNode],
516 lambda, hyEdge_dofs[hyNode]);
524 template <
class HyperGraphT,
528 unsigned int n_subdivisions = 1,
529 typename hyEdge_index_t =
unsigned int>
532 const LargeVecT& lambda,
533 std::ofstream& myfile,
537 using dof_value_t =
typename LargeVecT::value_type;
538 constexpr
unsigned int edge_dim = HyperGraphT::hyEdge_dim();
540 const hyEdge_index_t n_edges = hyper_graph.n_hyEdges();
541 std::array<std::array<dof_value_t, HyperGraphT::n_dofs_per_node()>, 2 * edge_dim> hyEdge_dofs;
543 for (hyEdge_index_t he_number = 0; he_number < n_edges; ++he_number)
545 hyEdge_dofs = get_edge_dof_values<edge_dim, HyperGraphT, hyEdge_index_t, LargeVecT>(
546 hyper_graph, he_number, lambda);
548 std::array<dof_value_t,
Hypercube<HyperGraphT::hyEdge_dim()>::pow(n_subdivisions + 1)>,
549 LocalSolverT::system_dimension()>
551 if constexpr (PlotFunctions::has_bulk_values<LocalSolverT,
552 decltype(local_values)(decltype(abscissas.
data())&,
553 decltype(hyEdge_dofs)&,
554 decltype(time))>::value)
555 local_values =
local_solver.bulk_values(abscissas.
data(), hyEdge_dofs, time);
556 else if constexpr (PlotFunctions::has_bulk_values<
557 LocalSolverT, decltype(local_values)(
558 decltype(abscissas.
data())&, decltype(hyEdge_dofs)&,
559 decltype(hyper_graph[he_number])&, decltype(time))>::value)
561 auto geometry = hyper_graph[he_number];
565 hy_assert(
false,
"Function seems not to be implemented!");
568 for (
unsigned int corner = 0; corner < Hypercube<edge_dim>::n_vertices(); ++corner)
571 for (
unsigned int d = 0; d < LocalSolverT::system_dimension(); ++d)
572 myfile <<
" " << local_values[d][corner];
573 for (
unsigned int d = LocalSolverT::system_dimension();
574 d < LocalSolverT::node_system_dimension(); ++d)
584 template <
unsigned int index,
typename functions>
587 static_assert(
index <= std::tuple_size<functions>(),
"Index is too large!");
588 if constexpr (
index == 0)
591 return std::tuple_element<index - 1, functions>::n_fun() +
first_dof<
index - 1>();
596 template <
unsigned int component,
597 typename LocalSolverT,
598 typename dof_value_t,
603 __attribute__((unused))
const hd_t& hyEdge_dofs,
604 __attribute__((unused))
const pt_t& point,
605 __attribute__((unused))
const unsigned int k,
606 __attribute__((unused))
const unsigned int bdr_index)
608 if constexpr (component == LocalSolverT::node_system_dimension())
614 std::tuple_element<component, typename LocalSolverT::node_element::functions>::type::n_fun()>
616 for (
unsigned int k = 0; k < helper_arr.size(); ++k)
618 hyEdge_dofs[bdr_index]
619 [first_dof<component, typename LocalSolverT::node_element::functions>() + k];
621 local_values[component][k] =
622 std::tuple_element<component, typename LocalSolverT::node_element::functions>::type::
623 template lin_comb_fct_val<float>(
SmallVec<helper_arr.
size(), dof_value_t>(helper_arr),
625 fancy_recursion<component + 1, LocalSolverT, dof_value_t>(local_values, hyEdge_dofs, point, k,
632 template <
class HyperGraphT,
635 unsigned int n_subdivisions = 1,
636 typename hyEdge_index_t =
unsigned int>
638 const LargeVecT& lambda,
639 std::ofstream& myfile,
642 using dof_value_t =
typename LargeVecT::value_type;
643 constexpr
unsigned int hyEdge_dim = HyperGraphT::hyEdge_dim();
645 const hyEdge_index_t n_edges = hyper_graph.n_hyEdges();
646 std::array<std::array<dof_value_t, HyperGraphT::n_dofs_per_node()>, 2 * hyEdge_dim> hyEdge_dofs;
648 std::array<dof_value_t,
Hypercube<HyperGraphT::hyEdge_dim() - 1>::pow(n_subdivisions + 1)>,
649 LocalSolverT::node_system_dimension()>
651 for (
unsigned int i = 0; i < local_values.size(); ++i)
652 local_values[i].fill(0.);
654 for (hyEdge_index_t edge_index = 0; edge_index < n_edges; ++edge_index)
656 hyEdge_dofs = get_edge_dof_values<hyEdge_dim, HyperGraphT, hyEdge_index_t, LargeVecT>(
657 hyper_graph, edge_index, lambda);
658 for (
unsigned int bdr_index = 0; bdr_index < hyEdge_dim * 2; ++bdr_index)
662 for (
unsigned int lval = 0; lval < local_values.size(); ++lval)
663 fancy_recursion<0, LocalSolverT, dof_value_t>(
664 local_values, hyEdge_dofs,
670 for (
unsigned int d = 0; d < LocalSolverT::node_system_dimension(); ++d)
671 myfile <<
" " << local_values[d][corner];
673 for (
unsigned int d = LocalSolverT::node_system_dimension();
674 d < LocalSolverT::system_dimension(); ++d)
684 template <
class HyperGraphT,
688 unsigned int n_subdivisions = 1,
689 typename hyEdge_index_t =
unsigned int>
692 const LargeVecT& lambda,
694 const floatT time = 0.)
696 constexpr
unsigned int edge_dim = HyperGraphT::hyEdge_dim();
698 const hyEdge_index_t n_edges = hyper_graph.n_hyEdges();
699 const hyEdge_index_t n_edge_boundaries = n_edges * 2 * edge_dim;
703 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
704 boundary_abscissas[i] =
707 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
708 abscissas[i] = plot_options.
scale * (1. * i / n_subdivisions - 0.5) + 0.5;
710 static_assert(edge_dim <= 3,
"Plotting hyperedges with dimensions larger than 3 is hard.");
714 myfile <<
"<?xml version=\"1.0\"?>" << std::endl;
715 myfile <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\" "
716 <<
"compressor=\"vtkZLibDataCompressor\">" << std::endl;
717 myfile <<
" <UnstructuredGrid>" << std::endl;
722 myfile <<
" <CellData>" << std::endl;
725 myfile <<
" <DataArray type=\"Int32\" Name=\"index\" NumberOfComponents=\"1\" "
726 <<
"format=\"ascii\">\n";
729 for (hyEdge_index_t he_number = 0; he_number < n_edges; ++he_number)
730 for (
unsigned int i = 0; i < Hypercube<edge_dim>::pow(n_subdivisions); ++i)
731 myfile <<
' ' << he_number;
735 for (hyEdge_index_t bdr_number = 1; bdr_number <= n_edge_boundaries; ++bdr_number)
736 for (
unsigned int i = 0; i < Hypercube<edge_dim>::pow(n_subdivisions); ++i)
737 myfile <<
" " << bdr_number;
740 myfile <<
" </DataArray>";
742 myfile <<
" </CellData>" << std::endl;
744 myfile <<
" <PointData>" << std::endl;
745 if (LocalSolverT::system_dimension() != 0)
747 myfile <<
" <DataArray type=\"Float32\" Name=\"values"
748 <<
"\" NumberOfComponents=\""
749 << std::max(LocalSolverT::system_dimension(), LocalSolverT::node_system_dimension())
750 <<
"\" format=\"ascii\">" << std::endl;
753 plot_edge_values<HyperGraphT, LocalSolverT, LargeVecT, floatT, n_subdivisions,
754 hyEdge_index_t>(hyper_graph,
local_solver, lambda, myfile, abscissas, time);
758 plot_boundary_values<HyperGraphT, LocalSolverT, LargeVecT, n_subdivisions, hyEdge_index_t>(
759 hyper_graph, lambda, myfile, boundary_abscissas);
761 myfile <<
" </DataArray>" << std::endl;
763 myfile <<
" </PointData>" << std::endl;
764 myfile <<
" </Piece>" << std::endl;
765 myfile <<
" </UnstructuredGrid>" << std::endl;
766 myfile <<
"</VTKFile>" << std::endl;
769 std::cout <<
"." << plot_options.
fileNumber <<
" was written\n";
777 template <
typename HyperGraphT,
typename LocalSolverT,
typename LargeVecT,
typename floatT>
778 void plot(HyperGraphT& hyper_graph,
780 const LargeVecT& lambda,
785 "Only file ending vtu is supported at the moment. Your choice has been "
786 << plot_options.
fileEnding <<
", which is invalid.");