Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
writebasis.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_WRITEBASIS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_WRITEBASIS_HH
9
10#include <type_traits>
11#include <variant>
12#include <string>
13#include <algorithm>
14
18
20
21#if DUNE_VERSION_GTE(DUNE_FUNCTIONS, 2, 11)
23#else
24#include <dune/typetree/traversal.hh>
25#endif
26
27
32
33#include <dune/vtk/vtkwriter.hh>
34#include <dune/vtk/datacollectors/discontinuouslagrangedatacollector.hh>
35
37
38namespace Dune::Fufem {
39
58 template<class Range=double, class Vector=std::monostate, class Basis>
59 void writeBasis(const Basis& basis, std::string name, int order = -1)
60 {
61 // Create a vector suitable to hold coefficients for the basis
62 auto vector = [&] {
64 return Dune::Functions::makeISTLVector<double>(basis.rootBasis().preBasis().containerDescriptor());
65 else
66 {
67 auto v = Vector();
70 return v;
71 }
72 }();
73 auto vectorBackend = Dune::Functions::istlVectorBackend(vector);
74
75 // Mark all DOFs of the subspace and deduce the appropriate order.
76 // Since there's no mechanism for deducing a bitvector so far,
77 // use a double vector to store flags.
78 auto inSubspace = vector;
79 auto inSubspaceBackend = Dune::Functions::istlVectorBackend(inSubspace);
80 auto localView = basis.localView();
81 for(const auto& element : Dune::elements(basis.gridView()))
82 {
83 localView.bind(element);
84 Dune::TypeTree::forEachLeafNode(localView.tree(), [&](auto&& node, auto&& treePath) {
85 for(auto i : Dune::range(node.size()))
86 inSubspaceBackend[localView.index(node.localIndex(i))] = 1;
87 if (order==-1)
88 order = std::max(order, int(node.finiteElement().localBasis().order()));
89 });
90 }
91
92 auto basisFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<double>(basis, vectorBackend);
93 auto i_flat=0;
94 Dune::Fufem::recursiveForEachVectorEntry(vector, [&](auto&& vector_i, const auto& i)
95 {
96 if (inSubspaceBackend[i]) {
97 vectorBackend[i] = 1;
98 auto vtkWriter = Dune::Vtk::UnstructuredGridWriter(Dune::Vtk::DiscontinuousLagrangeDataCollector(basis.gridView(), order));
99 vtkWriter.addPointData(basisFunction, Dune::VTK::FieldInfo("basisfunction", Dune::VTK::FieldInfo::Type::scalar, 1));
100 vtkWriter.write(Dune::formatString(name, i_flat));
101 vectorBackend[i] = 0;
102 }
103 i_flat++;
104 });
105 }
106
128 template<class Range=double, class Vector=std::monostate, class Basis, class Constraints>
129 void writeBasis(const Basis& basis, std::string name, const Constraints& constraints, int order = -1)
130 {
131 // Create a vector suitable to hold coefficients for the basis
132 auto vector = [&] {
134 return Dune::Functions::makeISTLVector<double>(basis.rootBasis().preBasis().containerDescriptor());
135 else
136 {
137 auto v = Vector();
138 Dune::Functions::istlVectorBackend(v).resize(basis);
140 return v;
141 }
142 }();
143 auto vectorBackend = Dune::Functions::istlVectorBackend(vector);
144
145 // Mark all DOFs of the subspace and deduce the appropriate order.
146 // Since there's no mechanism for deducing a bitvector so far,
147 // use a double vector to store flags.
148 auto inSubspace = vector;
149 auto inSubspaceBackend = Dune::Functions::istlVectorBackend(inSubspace);
150 auto localView = basis.localView();
151 for(const auto& element : Dune::elements(basis.gridView()))
152 {
153 localView.bind(element);
154 Dune::TypeTree::forEachLeafNode(localView.tree(), [&](auto&& node, auto&& treePath) {
155 for(auto i : Dune::range(node.size()))
156 inSubspaceBackend[localView.index(node.localIndex(i))] = 1;
157 if (order==-1)
158 order = std::max(order, int(node.finiteElement().localBasis().order()));
159 });
160 }
161
162 auto basisFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<double>(basis, vectorBackend);
163 auto i_flat=0;
164 Dune::Fufem::recursiveForEachVectorEntry(vector, [&](auto&& vector_i, const auto& i)
165 {
166 if (inSubspaceBackend[i]) {
167 vectorBackend = 0;
168 vectorBackend[i] = 1;
169 constraints.interpolate(vector);
170 auto vtkWriter = Dune::Vtk::UnstructuredGridWriter(Dune::Vtk::DiscontinuousLagrangeDataCollector(basis.gridView(), order));
171 vtkWriter.addPointData(basisFunction, Dune::VTK::FieldInfo("basisfunction", Dune::VTK::FieldInfo::Type::scalar, 1));
172 vtkWriter.write(Dune::formatString(name, i_flat));
173 }
174 i_flat++;
175 });
176 }
177
178
179} // end namespace Dune::Fufem
180
181#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_WRITEBASIS_HH
const char * name()
auto istlVectorBackend(Vector &v)
static std::string formatString(const std::string &s, const T &... args)
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
void writeBasis(const Basis &basis, std::string name, int order=-1)
Write basis functions as vtk-sequence.
Definition writebasis.hh:59
Definition dunefunctionsboundaryfunctionalassembler.hh:29
T forward(T... args)