DUNE-FUNCTIONS (2.7)

basistest.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_TEST_BASISTEST_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_TEST_BASISTEST_HH
5
6#include <set>
7#include <algorithm>
8
9#include <dune/common/test/testsuite.hh>
10#include <dune/common/concept.hh>
11
12#include <dune/functions/functionspacebases/concepts.hh>
13
14
15
16// check if two multi-indices are consecutive
17template<class MultiIndex>
18bool multiIndicesConsecutive(const MultiIndex& a, const MultiIndex& b)
19{
20 std::size_t i = 0;
21
22 // find largest common prefix
23 for (; (i<a.size()) and (i<b.size()) and (a[i] == b[i]); ++i)
24 {};
25
26 // if b is exhausted but a is not, then b is a strict prefix of a and does not succeed a
27 if ((i<a.size()) and (i==b.size()))
28 return false;
29
30 // if a and b are not exhausted, then the first non-common index must be an increment
31 if ((i<a.size()) and (i<b.size()))
32 {
33 if (b[i] != a[i]+1)
34 return false;
35 ++i;
36 }
37
38 // if b is not exhausted, then the following indices should be zero
39 if (i<b.size())
40 {
41 for (; i<b.size(); ++i)
42 {
43 if (b[i] != 0)
44 return false;
45 }
46 }
47 return true;
48}
49
50
51
52template<class MultiIndexSet>
53Dune::TestSuite checkBasisIndexTreeConsistency(const MultiIndexSet& multiIndexSet)
54{
55 Dune::TestSuite test("index tree consistency check");
56
57 using namespace Dune;
58
59 auto it = multiIndexSet.begin();
60 auto end = multiIndexSet.end();
61
62 // get first multi-index
63 auto lastMultiIndex = *it;
64
65 // assert that index is non-empty
66 test.require(lastMultiIndex.size()>0, "multi-index size check")
67 << "empty multi-index found";
68
69 // check if first multi-index is [0,...,0]
70 for (decltype(lastMultiIndex.size()) i = 0; i<lastMultiIndex.size(); ++i)
71 {
72 test.require(lastMultiIndex[i] == 0, "smallest index check")
73 << "smallest index contains non-zero entry " << lastMultiIndex[i] << " in position " << i;
74 }
75
76 ++it;
77 for(; it != end; ++it)
78 {
79 auto multiIndex = *it;
80
81 // assert that index is non-empty
82 test.require(multiIndex.size()>0, "multi-index size check")
83 << "empty multi-index found";
84
85 // assert that indices are consecutive
86 test.check(multiIndicesConsecutive(lastMultiIndex, multiIndex), "consecutive index check")
87 << "multi-indices " << lastMultiIndex << " and " << multiIndex << " are subsequent but not consecutive";
88
89 lastMultiIndex = multiIndex;
90 }
91
92 return test;
93}
94
95
96
97template<class Basis, class MultiIndexSet>
98Dune::TestSuite checkBasisSizeConsistency(const Basis& basis, const MultiIndexSet& multiIndexSet)
99{
100 Dune::TestSuite test("index size consistency check");
101
102 auto prefix = typename Basis::SizePrefix{};
103
104 for(const auto& index : multiIndexSet)
105 {
106 prefix.clear();
107 for (const auto& i: index)
108 {
109 // All indices i collected so far from the multi-index
110 // refer to a non-empty multi-index subtree. Hence the
111 // size must be nonzero and in fact strictly larger than
112 // the next index.
113 auto prefixSize = basis.size(prefix);
114 test.require(prefixSize > i, "basis.size(prefix) subtree check")
115 << "basis.size(" << prefix << ")=" << prefixSize << " but index " << index << " exists";
116
117 // append next index from multi-index
118 prefix.push_back(i);
119 }
120 auto prefixSize = basis.size(prefix);
121 test.require(prefixSize == 0, "basis.size(prefix) leaf check")
122 << "basis.size(" << prefix << ")=" << prefixSize << " but the prefix exists as index";
123 }
124
125 // ToDo: Add check that for basis.size(prefix)==n with i>0
126 // there exist multi-indices of the form (prefix,0,...)...(prefix,n-1,...)
127
128 return test;
129}
130
131
132
133template<class Basis>
134Dune::TestSuite checkBasisIndices(const Basis& basis)
135{
136 Dune::TestSuite test("basis index check");
137
138 using MultiIndex = typename Basis::MultiIndex;
139 auto compare = [](const auto& a, const auto& b) {
140 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
141 };
142
143 auto multiIndexSet = std::set<MultiIndex, decltype(compare)>{compare};
144
145 auto localView = basis.localView();
146 for (const auto& e : elements(basis.gridView()))
147 {
148 localView.bind(e);
149
150 test.require(localView.size() <= localView.maxSize(), "localView.size() check")
151 << "localView.size() is " << localView.size() << " but localView.maxSize() is " << localView.maxSize();
152
153 for (decltype(localView.size()) i=0; i< localView.size(); ++i)
154 {
155 auto multiIndex = localView.index(i);
156 multiIndexSet.insert(multiIndex);
157 }
158 }
159
160 test.subTest(checkBasisIndexTreeConsistency(multiIndexSet));
161 test.subTest(checkBasisSizeConsistency(basis, multiIndexSet));
162
163 return test;
164}
165
166
167
168template<class Basis>
169Dune::TestSuite checkBasis(const Basis& basis)
170{
171 Dune::TestSuite test("basis check");
172
173
174 using GridView = typename Basis::GridView;
175
176 test.check(Dune::models<Dune::Functions::Concept::GlobalBasis<GridView>, Basis>(), "global basis concept check")
177 << "type passed to checkBasis() does not model the GlobalBasis concept";
178
179 test.subTest(checkBasisIndices(basis));
180
181 return test;
182}
183
184#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_TEST_BASISTEST_HH
Definition: polynomial.hh:10
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)