Line | Branch | Exec | Source |
---|---|---|---|
1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||
2 | // vi: set et ts=4 sw=4 sts=4: | ||
3 | // | ||
4 | // SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup InputOutput | ||
10 | * \brief read from a file into a solution vector | ||
11 | */ | ||
12 | #ifndef DUMUX_IO_LOADSOLUTION_HH | ||
13 | #define DUMUX_IO_LOADSOLUTION_HH | ||
14 | |||
15 | #include <string> | ||
16 | #include <iostream> | ||
17 | #include <vector> | ||
18 | #include <unordered_set> | ||
19 | #include <unordered_map> | ||
20 | #include <type_traits> | ||
21 | #include <functional> | ||
22 | |||
23 | #include <dune/common/exceptions.hh> | ||
24 | #include <dune/common/indices.hh> | ||
25 | #include <dune/grid/common/partitionset.hh> | ||
26 | |||
27 | #include <dumux/common/parameters.hh> | ||
28 | #include <dumux/common/typetraits/isvalid.hh> | ||
29 | #include <dumux/common/typetraits/vector.hh> | ||
30 | #include <dumux/common/typetraits/state.hh> | ||
31 | #include <dumux/io/vtk/vtkreader.hh> | ||
32 | #include <dumux/discretization/method.hh> | ||
33 | #include <dumux/common/gridcapabilities.hh> | ||
34 | |||
35 | namespace Dumux { | ||
36 | |||
37 | /*! | ||
38 | * \ingroup InputOutput | ||
39 | * \brief a data handle to communicate the solution on ghosts and overlaps | ||
40 | * when reading from vtk file in parallel | ||
41 | */ | ||
42 | template <class Container, class EntityMapper, int codim> | ||
43 | 2 | class LoadSolutionDataHandle | |
44 | : public Dune::CommDataHandleIF< LoadSolutionDataHandle<Container, EntityMapper, codim>, | ||
45 | std::decay_t<decltype(std::declval<Container>()[0])> > | ||
46 | { | ||
47 | using FieldType = std::decay_t<decltype(std::declval<Container>()[0])>; | ||
48 | public: | ||
49 |
1/20✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
2 | LoadSolutionDataHandle(Container& container, |
50 | const EntityMapper& mapper) | ||
51 | 2 | : mapper_(mapper) | |
52 |
1/20✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
2 | , container_(container) |
53 | {} | ||
54 | |||
55 | ✗ | bool contains(int dim, int cd) const | |
56 | ✗ | { return cd == codim; } | |
57 | |||
58 | //! returns true if size per entity of given dim and codim is a constant | ||
59 | bool fixedSize(int dim, int cd) const | ||
60 | { return true; } | ||
61 | |||
62 | template<class EntityType> | ||
63 | std::size_t size (const EntityType &e) const | ||
64 | { return 1; } | ||
65 | |||
66 | template<class MessageBufferImp, class EntityType> | ||
67 | 32 | void gather(MessageBufferImp& buff, const EntityType& e) const | |
68 | { | ||
69 | 32 | const auto vIdx = mapper_.index(e); | |
70 | 32 | buff.write(container_[vIdx]); | |
71 | 32 | } | |
72 | |||
73 | template<class MessageBufferImp, class EntityType> | ||
74 | 32 | void scatter(MessageBufferImp& buff, const EntityType& e, std::size_t n) | |
75 | { | ||
76 | 32 | const auto vIdx = mapper_.index(e); | |
77 | 32 | FieldType tmp; | |
78 | 32 | buff.read(tmp); | |
79 | 32 | container_[vIdx] = tmp; | |
80 | 32 | } | |
81 | |||
82 | private: | ||
83 | EntityMapper mapper_; | ||
84 | Container& container_; | ||
85 | }; | ||
86 | |||
87 | /*! | ||
88 | * \ingroup InputOutput | ||
89 | * \brief read from a vtk file into a solution vector with primary variables without state | ||
90 | */ | ||
91 | template <class SolutionVector, class PvNameFunc, class GridGeometry> | ||
92 | 104 | auto loadSolutionFromVtkFile(SolutionVector& sol, | |
93 | const std::string fileName, | ||
94 | PvNameFunc&& targetPvNameFunc, | ||
95 | const GridGeometry& gridGeometry, | ||
96 | const VTKReader::DataType& dataType) | ||
97 | -> typename std::enable_if_t<!decltype(isValid(Detail::hasState())(sol[0]))::value, void> | ||
98 | { | ||
99 | 104 | VTKReader vtu(fileName); | |
100 | |||
101 | using PrimaryVariables = typename SolutionVector::block_type; | ||
102 | using Scalar = typename PrimaryVariables::field_type; | ||
103 | constexpr auto dim = GridGeometry::GridView::dimension; | ||
104 | const std::size_t targetSolutionSize = PrimaryVariables::dimension; | ||
105 | |||
106 | std::size_t matchingLoadedArrays = 0; | ||
107 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 54 times.
|
322 | for (std::size_t i = 0; i < targetSolutionSize; i++) |
108 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 111 times.
✓ Branch 7 taken 1 times.
|
436 | if (vtu.hasData(targetPvNameFunc(i,0), dataType)) |
109 | 216 | matchingLoadedArrays++; | |
110 | |||
111 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 24 times.
|
104 | if (matchingLoadedArrays < targetSolutionSize) |
112 | std::cout << "The loaded solution does not provide a data array for each of the primary variables. \n" | ||
113 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | << "The target solution has "<< targetSolutionSize << " entries, " |
114 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | << "whereas the loaded solution provides only " << matchingLoadedArrays << " data array(s). \n" |
115 | << "Make sure that the model concepts are compatible, " | ||
116 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | << "and be sure to provide initial conditions for the missing primary variables. \n"; |
117 | |||
118 |
3/4✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 54 times.
|
594 | for (std::size_t targetPvIdx = 0; targetPvIdx < targetSolutionSize; ++targetPvIdx) |
119 | { | ||
120 | 218 | std::vector<Scalar> vec; | |
121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
218 | const auto targetPvName = targetPvNameFunc(targetPvIdx, 0); |
122 | |||
123 |
3/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 111 times.
✓ Branch 4 taken 1 times.
|
220 | if (vtu.hasData(targetPvName, dataType)) |
124 |
2/4✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 111 times.
|
432 | vec = vtu.readData<std::vector<Scalar>>(targetPvName, dataType); |
125 | else | ||
126 | { | ||
127 | std::cout << "The loaded solution does not have a field named \"" << targetPvName << "\". " | ||
128 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | << "Make sure this field is filled using the initial method in the problem definition. \n"; |
129 | continue; | ||
130 | } | ||
131 | |||
132 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 27 times.
|
216 | if (dataType == VTKReader::DataType::cellData) |
133 | { | ||
134 | 164 | std::size_t i = 0; | |
135 |
2/12✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 3 taken 6240 times.
✗ Branch 6 not taken.
|
17876 | for (const auto& element : elements(gridGeometry.gridView(), Dune::Partitions::interior)) |
136 | { | ||
137 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
8856 | const auto eIdx = gridGeometry.elementMapper().index(element); |
138 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
8856 | sol[eIdx][targetPvIdx] = vec[i++]; |
139 | } | ||
140 | } | ||
141 | // for staggered face data (which is written out as VTK point data) we just read in the vector | ||
142 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
50 | else if (dataType == VTKReader::DataType::pointData && GridGeometry::discMethod == DiscretizationMethods::staggered) |
143 | { | ||
144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
50 | if (sol.size() != vec.size()) |
145 | ✗ | DUNE_THROW(Dune::InvalidStateException, "Solution size (" << sol.size() << ") does not match input size (" << vec.size() << ")!"); | |
146 | |||
147 |
2/2✓ Branch 0 taken 1870 times.
✓ Branch 1 taken 25 times.
|
3790 | for (std::size_t i = 0; i < sol.size(); ++i) |
148 | 3740 | sol[i][targetPvIdx] = vec[i]; | |
149 | } | ||
150 | else | ||
151 | { | ||
152 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::size_t i = 0; |
153 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | std::vector<bool> visited(gridGeometry.gridView().size(dim), false); |
154 |
2/11✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 6 not taken.
|
324 | for (const auto& element : elements(gridGeometry.gridView(), Dune::Partitions::interior)) |
155 | { | ||
156 |
2/5✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 0 taken 320 times.
|
480 | for (int vIdxLocal = 0; vIdxLocal < element.subEntities(dim); ++vIdxLocal) |
157 | { | ||
158 |
1/2✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
|
320 | const auto vIdxGlobal = gridGeometry.vertexMapper().subIndex(element, vIdxLocal, dim); |
159 |
2/2✓ Branch 0 taken 162 times.
✓ Branch 1 taken 158 times.
|
320 | if (!visited[vIdxGlobal]) |
160 | { | ||
161 | 162 | sol[vIdxGlobal][targetPvIdx] = vec[i++]; | |
162 | 162 | visited[vIdxGlobal] = true; | |
163 | } | ||
164 | } | ||
165 | } | ||
166 | 2 | } | |
167 | } | ||
168 | 104 | } | |
169 | |||
170 | /*! | ||
171 | * \ingroup InputOutput | ||
172 | * \brief read from a sequential file into a solution vector with primary variables with state | ||
173 | */ | ||
174 | template <class SolutionVector, class PvNameFunc, class GridGeometry> | ||
175 | 2 | auto loadSolutionFromVtkFile(SolutionVector& sol, | |
176 | const std::string fileName, | ||
177 | PvNameFunc&& targetPvNameFunc, | ||
178 | const GridGeometry& gridGeometry, | ||
179 | const VTKReader::DataType& dataType) | ||
180 | -> typename std::enable_if_t<decltype(isValid(Detail::hasState())(sol[0]))::value, void> | ||
181 | { | ||
182 | 2 | VTKReader vtu(fileName); | |
183 | // get states at each dof location | ||
184 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | const auto stateAtDof = vtu.readData<std::vector<int>>("phase presence", dataType); |
185 | |||
186 | // determine all states that are present | ||
187 | 2 | std::unordered_set<int> states; | |
188 |
2/2✓ Branch 0 taken 656 times.
✓ Branch 1 taken 2 times.
|
658 | for (std::size_t i = 0; i < stateAtDof.size(); ++i) |
189 |
1/2✓ Branch 1 taken 656 times.
✗ Branch 2 not taken.
|
656 | states.insert(stateAtDof[i]); |
190 | |||
191 | using PrimaryVariables = typename SolutionVector::block_type; | ||
192 | using Scalar = typename PrimaryVariables::field_type; | ||
193 | 2 | const std::size_t targetSolutionSize = PrimaryVariables::dimension; | |
194 | |||
195 | 2 | std::unordered_set<std::string> matchingNames; | |
196 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (std::size_t i = 0; i < targetSolutionSize; i++) |
197 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | for (const auto& state : states) |
198 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
|
24 | if ( vtu.hasData(targetPvNameFunc(i,state), dataType)) |
199 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
|
24 | matchingNames.insert(targetPvNameFunc(i,state)); |
200 | |||
201 | 2 | const std::size_t matchingLoadedArrays = matchingNames.size() - (states.size()-1); | |
202 | |||
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (matchingLoadedArrays < targetSolutionSize) |
204 | std::cout << "The loaded solution does not provide a data array for each of the primary variables. \n" | ||
205 | ✗ | << "The target solution has "<< targetSolutionSize << " entries, " | |
206 | ✗ | << "whereas the loaded solution provides only " << matchingLoadedArrays << " data array(s). \n" | |
207 | << "Make sure that the model concepts are compatible, " | ||
208 | ✗ | << "and be sure to provide initial conditions for the missing primary variables. \n"; | |
209 | |||
210 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (std::size_t targetPvIdx = 0; targetPvIdx < targetSolutionSize; ++targetPvIdx) |
211 | { | ||
212 | 6 | std::unordered_map<int, std::vector<Scalar>> data; | |
213 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | for (const auto& state : states) |
214 | { | ||
215 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | const auto targetPvName = targetPvNameFunc(targetPvIdx, state); |
216 | |||
217 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
|
12 | if (vtu.hasData(targetPvName, dataType)) |
218 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
24 | data[state] = vtu.readData<std::vector<Scalar>>(targetPvName, dataType); |
219 | else | ||
220 | { | ||
221 | std::cout << "Loaded Solution does not have a field named \"" << targetPvName << "\". " | ||
222 | ✗ | << "Make sure this field is filled using the initial method in the problem definition. \n"; | |
223 | continue; | ||
224 | } | ||
225 | } | ||
226 | |||
227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (dataType == VTKReader::DataType::cellData) |
228 | { | ||
229 | ✗ | std::size_t i = 0; | |
230 | ✗ | for (const auto& element : elements(gridGeometry.gridView(), Dune::Partitions::interior)) | |
231 | { | ||
232 | ✗ | const auto eIdx = gridGeometry.elementMapper().index(element); | |
233 | ✗ | const auto state = stateAtDof[i]; | |
234 | ✗ | sol[eIdx][targetPvIdx] = data[state][i++]; | |
235 | ✗ | sol[eIdx].setState(state); | |
236 | } | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | 6 | std::size_t i = 0; | |
241 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | constexpr int dim = GridGeometry::GridView::dimension; |
242 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
|
6 | std::vector<bool> visited(gridGeometry.gridView().size(dim), false); |
243 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1574 times.
✗ Branch 5 not taken.
|
3148 | for (const auto& element : elements(gridGeometry.gridView(), Dune::Partitions::interior)) |
244 | { | ||
245 |
2/2✓ Branch 0 taken 6272 times.
✓ Branch 1 taken 1568 times.
|
7840 | for (int vIdxLocal = 0; vIdxLocal < element.subEntities(dim); ++vIdxLocal) |
246 | { | ||
247 |
1/2✓ Branch 1 taken 6272 times.
✗ Branch 2 not taken.
|
6272 | const auto vIdxGlobal = gridGeometry.vertexMapper().subIndex(element, vIdxLocal, dim); |
248 |
2/2✓ Branch 0 taken 1774 times.
✓ Branch 1 taken 4498 times.
|
6272 | if (!visited[vIdxGlobal]) |
249 | { | ||
250 |
1/2✓ Branch 1 taken 1774 times.
✗ Branch 2 not taken.
|
1774 | const auto state = stateAtDof[i]; |
251 | 1774 | sol[vIdxGlobal][targetPvIdx] = data[state][i++]; | |
252 | 1774 | sol[vIdxGlobal].setState(state); | |
253 | 1774 | visited[vIdxGlobal] = true; | |
254 | } | ||
255 | } | ||
256 | } | ||
257 | 6 | } | |
258 | } | ||
259 | 4 | } | |
260 | |||
261 | /*! | ||
262 | * \ingroup InputOutput | ||
263 | * \brief helper function to determine the primary variable names of a model with privar state | ||
264 | * \note use this as input for the load solution function | ||
265 | */ | ||
266 | template<class IOFields, class PrimaryVariables, class ModelTraits = void, class FluidSystem = void, class SolidSystem = void> | ||
267 | 2 | auto createPVNameFunction(const std::string& paramGroup = "") | |
268 | -> typename std::enable_if_t<decltype(isValid(Detail::hasState())(PrimaryVariables(0)))::value, std::function<std::string(int,int)>> | ||
269 | { | ||
270 |
1/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
6 | return [paramGroup](int pvIdx, int state = 0) |
271 | { | ||
272 | static auto numStates = (1 << ModelTraits::numFluidPhases()) - 1; | ||
273 |
1/2✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
72 | const auto paramNameWithState = "LoadSolution.PriVarNamesState" + std::to_string(state); |
274 | |||
275 |
4/12✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 36 times.
|
108 | if (hasParamInGroup(paramGroup, "LoadSolution.PriVarNames") && !hasParamInGroup(paramGroup, paramNameWithState)) |
276 | ✗ | DUNE_THROW(Dune::NotImplemented, "please provide LoadSolution.PriVarNamesState1..." << numStates | |
277 | << " or remove LoadSolution.PriVarNames to use the model's default primary variable names"); | ||
278 | |||
279 |
3/4✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 24 times.
|
72 | else if (hasParamInGroup(paramGroup, paramNameWithState)) |
280 | { | ||
281 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | const auto pvName = getParamFromGroup<std::vector<std::string>>(paramGroup, paramNameWithState); |
282 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | return pvName[pvIdx]; |
283 | 12 | } | |
284 | else | ||
285 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | return IOFields::template primaryVariableName<ModelTraits, FluidSystem, SolidSystem>(pvIdx, state); |
286 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
40 | }; |
287 | } | ||
288 | |||
289 | /*! | ||
290 | * \ingroup InputOutput | ||
291 | * \brief helper function to determine the primary variable names of a model without state | ||
292 | * \note use this as input for the load solution function | ||
293 | */ | ||
294 | template<class IOFields, class PrimaryVariables, class ModelTraits = void, class FluidSystem = void, class SolidSystem = void> | ||
295 | 4 | auto createPVNameFunction(const std::string& paramGroup = "") | |
296 | -> typename std::enable_if_t<!decltype(isValid(Detail::hasState())(PrimaryVariables(0)))::value, std::function<std::string(int,int)>> | ||
297 | { | ||
298 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
8 | if (hasParamInGroup(paramGroup, "LoadSolution.PriVarNames")) |
299 | { | ||
300 | ✗ | const auto pvName = getParamFromGroup<std::vector<std::string>>(paramGroup, "LoadSolution.PriVarNames"); | |
301 | ✗ | return [n = std::move(pvName)](int pvIdx, int state = 0){ return n[pvIdx]; }; | |
302 | ✗ | } | |
303 | else | ||
304 | 16 | return [](int pvIdx, int state = 0){ return IOFields::template primaryVariableName<ModelTraits, FluidSystem, SolidSystem>(pvIdx, state); }; | |
305 | } | ||
306 | |||
307 | /*! | ||
308 | * \ingroup InputOutput | ||
309 | * \brief load a solution vector from file | ||
310 | * \note Supports the following file extensions: *.vtu *.vtp *.pvtu, *.pvtp | ||
311 | * \param sol the solution vector to read from file | ||
312 | * \param fileName the file name of the file to read from | ||
313 | * \param targetPvNameFunc a function with the signature std::string(int pvIdx) | ||
314 | * in case the primary variables have a state the signature is std::string(int pvIdx, int state) | ||
315 | * \param gridGeometry the grid geometry of the discretization method used | ||
316 | */ | ||
317 | template <class SolutionVector, class PvNameFunc, class GridGeometry> | ||
318 | 106 | void loadSolution(SolutionVector& sol, | |
319 | const std::string& fileName, | ||
320 | PvNameFunc&& targetPvNameFunc, | ||
321 | const GridGeometry& gridGeometry) | ||
322 | { | ||
323 | 106 | const auto extension = fileName.substr(fileName.find_last_of(".") + 1); | |
324 | 106 | auto dataType = GridGeometry::discMethod == DiscretizationMethods::box ? | |
325 | VTKReader::DataType::pointData : VTKReader::DataType::cellData; | ||
326 | |||
327 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 2 times.
|
106 | if (extension == "vtu" || extension == "vtp") |
328 | { | ||
329 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
|
100 | if (GridGeometry::discMethod == DiscretizationMethods::staggered && extension == "vtp") |
330 | 50 | dataType = VTKReader::DataType::pointData; | |
331 | |||
332 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
108 | loadSolutionFromVtkFile(sol, fileName, targetPvNameFunc, gridGeometry, dataType); |
333 | } | ||
334 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2 | else if (extension == "pvtu" || extension == "pvtp") |
335 | { | ||
336 | if (GridGeometry::discMethod == DiscretizationMethods::staggered) | ||
337 |
1/20✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
2 | DUNE_THROW(Dune::NotImplemented, "reading staggered solution from a parallel vtk file"); |
338 | |||
339 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | loadSolutionFromVtkFile(sol, fileName, targetPvNameFunc, gridGeometry, dataType); |
340 | } | ||
341 | else | ||
342 | ✗ | DUNE_THROW(Dune::NotImplemented, "loadSolution for file with extension " << extension); | |
343 | |||
344 | // communicate solution on ghost and overlap dofs | ||
345 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 54 times.
|
106 | if (gridGeometry.gridView().comm().size() > 1) |
346 | { | ||
347 | using GridView = typename GridGeometry::GridView; | ||
348 | ✗ | if (dataType == VTKReader::DataType::cellData) | |
349 | { | ||
350 | LoadSolutionDataHandle<SolutionVector, typename GridGeometry::ElementMapper, 0> | ||
351 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | dataHandle(sol, gridGeometry.elementMapper()); |
352 | |||
353 | if constexpr (Detail::canCommunicate<typename GridView::Traits::Grid, 0>) | ||
354 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | gridGeometry.gridView().communicate(dataHandle, |
355 | Dune::InteriorBorder_All_Interface, | ||
356 | Dune::ForwardCommunication); | ||
357 | else | ||
358 | DUNE_THROW(Dune::InvalidStateException, "Cannot call loadSolution on multiple processes for a grid that cannot communicate codim-" << 0 << "-entities."); | ||
359 | 2 | } | |
360 | else | ||
361 | { | ||
362 | LoadSolutionDataHandle<SolutionVector, typename GridGeometry::VertexMapper, GridView::dimension> | ||
363 | ✗ | dataHandle(sol, gridGeometry.vertexMapper()); | |
364 | |||
365 | if constexpr (Detail::canCommunicate<typename GridView::Traits::Grid, GridView::dimension>) | ||
366 | ✗ | gridGeometry.gridView().communicate(dataHandle, | |
367 | Dune::InteriorBorder_All_Interface, | ||
368 | Dune::ForwardCommunication); | ||
369 | else | ||
370 | DUNE_THROW(Dune::InvalidStateException, "Cannot call loadSolution on multiple processes for a grid that cannot communicate codim-" << GridView::dimension << "-entities."); | ||
371 | ✗ | } | |
372 | } | ||
373 | 106 | } | |
374 | } // end namespace Dumux | ||
375 | |||
376 | #endif | ||
377 |