ProblemStat.inc.hpp 8.57 KB
Newer Older
1
2
#pragma once

3
4
5
6
#include <map>
#include <string>
#include <utility>

7
#include <dune/common/timer.hh>
8
9
#include <dune/typetree/childextraction.hh>

10
11
12
13
14
#include <amdis/AdaptInfo.hpp>
#include <amdis/FileWriter.hpp>
#include <amdis/LocalAssembler.hpp>
#include <amdis/GridFunctionOperator.hpp>
#include <amdis/common/Loops.hpp>
15

16
17
namespace AMDiS {

18
19
template <class Traits>
void ProblemStat<Traits>::initialize(
20
21
22
    Flag initFlag,
    Self* adoptProblem,
    Flag adoptFlag)
23
{
24
  // create grids
25
  if (grid_) {
26
    warning("grid already created");
27
28
29
30
31
  }
  else {
    if (initFlag.isSet(CREATE_MESH) ||
        (!adoptFlag.isSet(INIT_MESH) &&
        (initFlag.isSet(INIT_SYSTEM) || initFlag.isSet(INIT_FE_SPACE)))) {
32
      createGrid();
33
    }
34

35
36
37
38
    if (adoptProblem &&
        (adoptFlag.isSet(INIT_MESH) ||
        adoptFlag.isSet(INIT_SYSTEM) ||
        adoptFlag.isSet(INIT_FE_SPACE))) {
39
      grid_ = adoptProblem->grid_;
40
    }
41
  }
42

43
  if (!grid_)
44
    warning("no grid created");
45

46
  int globalRefinements = 0;
47
  Parameters::get(gridName_ + "->global refinements", globalRefinements);
48
  if (globalRefinements > 0) {
49
    grid_->globalRefine(globalRefinements);
50
  }
51
52


53
  // create fespace
54
  if (globalBasis_) {
55
    warning("globalBasis already created");
56
57
58
59
  }
  else {
    if (initFlag.isSet(INIT_FE_SPACE) ||
        (initFlag.isSet(INIT_SYSTEM) && !adoptFlag.isSet(INIT_FE_SPACE))) {
60
      createGlobalBasis();
61
    }
62

63
64
    if (adoptProblem &&
        (adoptFlag.isSet(INIT_FE_SPACE) || adoptFlag.isSet(INIT_SYSTEM))) {
65
66
      globalBasis_ = adoptProblem->globalBasis_;
      initGlobalBasis(*globalBasis_);
67
    }
68
  }
69

70
  if (!globalBasis_)
71
    warning("no globalBasis created\n");
72
73


74
75
76
  // create system
  if (initFlag.isSet(INIT_SYSTEM))
    createMatricesAndVectors();
77

78
  if (adoptProblem && adoptFlag.isSet(INIT_SYSTEM)) {
79
    solution_ = adoptProblem->solution_;
80
    estimates_ = adoptProblem->estimates_;
81
82
    rhs_ = adoptProblem->rhs_;
    systemMatrix_ = adoptProblem->systemMatrix_;
83
  }
84

85

86
  // create solver
87
  if (linearSolver_) {
88
89
90
91
92
    warning("solver already created\n");
  }
  else {
    if (initFlag.isSet(INIT_SOLVER))
      createSolver();
93

94
    if (adoptProblem && adoptFlag.isSet(INIT_SOLVER)) {
95
96
      test_exit(!linearSolver_, "solver already created\n");
      linearSolver_ = adoptProblem->linearSolver_;
97
    }
98
99
  }

100
  if (!linearSolver_) {
101
    warning("no solver created\n");
102
103
  }

104
105
106
107
108
  // create marker
    if (initFlag.isSet(INIT_MARKER))
      createMarker();

    if (adoptProblem && adoptFlag.isSet(INIT_MARKER))
109
      marker_ = adoptProblem->marker_;
110

111

112
113
114
  // create file writer
  if (initFlag.isSet(INIT_FILEWRITER))
    createFileWriter();
115

116
  solution_->compress();
117
}
118

119

120
121
122
template <class Traits>
void ProblemStat<Traits>::createMarker()
{
123
124
  auto localView = globalBasis_->localView();
  AMDiS::forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath)
125
  {
126
    std::string componentName = name_ + "->marker[" + to_string(treePath) + "]";
127
128
129
130

    if (!Parameters::get<std::string>(componentName + "->strategy"))
      return;

131
132
    std::string tp = to_string(treePath);
    auto newMarker = Marker<Traits>::createMarker(componentName, tp, estimates_[tp], grid_);
133
    if (newMarker)
134
135
      marker_.push_back(std::move(newMarker));

136
137
    // If there is more than one marker, and all components are defined
    // on the same grid, the maximum marking has to be enabled.
138
139
140
    // TODO: needs to be checked!
    if (marker_.size() > 1)
      marker_.back()->setMaximumMarking(true);
141
142
143
144
  });
}


145
146
template <class Traits>
void ProblemStat<Traits>::createFileWriter()
147
{
148
149
  auto localView = globalBasis_->localView();
  forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath)
150
  {
151
    std::string componentName = name_ + "->output[" + to_string(treePath) + "]";
152
153
154
155

    if (!Parameters::get<std::string>(componentName + "->filename"))
      return;

156
    auto writer = makeFileWriterPtr(componentName, this->getSolution(treePath));
157
    filewriter_.push_back(std::move(writer));
158
159
160
161
  });
}


162
// Adds a Dirichlet boundary condition
163
template <class Traits>
164
  template <class Predicate, class RowTreePath, class ColTreePath, class Values>
165
void ProblemStat<Traits>::
166
addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values)
167
168
{
  static_assert( Concepts::Functor<Predicate, bool(WorldVector)>,
169
    "Function passed to addDirichletBC for `predicate` does not model the Functor<bool(WorldVector)> concept");
170

171
172
173
  auto localView = globalBasis_->localView();
  auto i = child(localView.tree(), makeTreePath(row));
  auto j = child(localView.tree(), makeTreePath(col));
174

175
  auto valueGridFct = makeGridFunction(values, globalBasis_->gridView());
176

177
  using Range = RangeType_t<decltype(i)>;
178
  using BcType = DirichletBC<WorldVector,Range>;
179
  auto bc = std::make_shared<BcType>(predicate, valueGridFct);
180
  constraints_[i][j].push_back(bc);
181
  // TODO: make DirichletBC an abstract class and add specialization with gridfunction type
182
}
183

184

185
186
template <class Traits>
void ProblemStat<Traits>::
187
188
solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData)
{
189
  Dune::Timer t;
190

191
  SolverInfo solverInfo(name_ + "->solver");
192
193
194
  solverInfo.setCreateMatrixData(createMatrixData);
  solverInfo.setStoreMatrixData(storeMatrixData);

195
  solution_->compress();
196

197
  linearSolver_->solve(systemMatrix_->matrix(), solution_->vector(), rhs_->vector(),
198
199
200
                      solverInfo);

  if (solverInfo.getInfo() > 0) {
201
    msg("solution of discrete system needed {} seconds", t.elapsed());
202
203
204

    if (solverInfo.getAbsResidual() >= 0.0) {
      if (solverInfo.getRelResidual() >= 0.0)
205
206
        msg("Residual norm: ||b-Ax|| = {}, ||b-Ax||/||b|| = {}",
          solverInfo.getAbsResidual(), solverInfo.getRelResidual());
207
      else
208
        msg("Residual norm: ||b-Ax|| = {}", solverInfo.getAbsResidual());
209
210
    }
  }
211

212
213
214
215
216
217
218
219
  if (solverInfo.doBreak()) {
    std::stringstream tol_str;
    if (solverInfo.getAbsTolerance() > 0
        && solverInfo.getAbsResidual() > solverInfo.getAbsTolerance())
      tol_str << "absTol = " << solverInfo.getAbsTolerance() << " ";
    if (solverInfo.getRelTolerance() > 0
        && solverInfo.getRelResidual() > solverInfo.getRelTolerance())
      tol_str << "relTol = " << solverInfo.getRelTolerance() << " ";
220
    error_exit("Tolerance {} could not be reached!", tol_str.str());
221
222
  }
}
223

224

225
226
227
228
229
230
template <class Traits>
Flag ProblemStat<Traits>::markElements(AdaptInfo& adaptInfo)
{
  Dune::Timer t;

  Flag markFlag = 0;
231
  for (auto& currentMarker : marker_)
232
    markFlag |= currentMarker->markGrid(adaptInfo);
233

234
  msg("markElements needed {} seconds", t.elapsed());
235
236
237
238
239

  return markFlag;
}


240
241
242
243
244
245
246
247
248
249
250
template <class Traits>
Flag ProblemStat<Traits>::
adaptGrid(AdaptInfo& adaptInfo)
{
  Dune::Timer t;

  grid_->preAdapt();
  grid_->adapt();
  globalBasis_->update(gridView());
  grid_->postAdapt();

251
  msg("adaptGrid needed {} seconds", t.elapsed());
252
253
254
255
  return 0;
}


256
257
template <class Traits>
void ProblemStat<Traits>::
258
buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool asmVector)
259
{
260
  Dune::Timer t;
261

262
263
264
265
266
  // 1. init matrix and rhs vector and initialize dirichlet boundary conditions
  systemMatrix_->init(asmMatrix);
  rhs_->init(asmVector);
  solution_->resize(*globalBasis_);

267
268
269
  auto localView = globalBasis_->localView();
  forEachNode_(localView.tree(), [&,this](auto const& rowNode, auto) {
    forEachNode_(localView.tree(), [&,this](auto const& colNode, auto) {
270
      for (auto bc : constraints_[rowNode][colNode])
271
        bc->init(*systemMatrix_, *solution_, *rhs_, rowNode, colNode);
272
273
274
275
276
277
    });
  });
  msg("{} total DOFs", globalBasis_->dimension());

  // 2. traverse grid and assemble operators on the elements
  for (auto const& element : elements(gridView())) {
278
    localView.bind(element);
279
280

    if (asmMatrix)
281
      systemMatrix_->assemble(localView, localView);
282
    if (asmVector)
283
      rhs_->assemble(localView);
284

285
    localView.unbind();
286
287
288
289
290
  }

  // 3. finish matrix insertion and apply dirichlet boundary conditions
  systemMatrix_->finish(asmMatrix);
  rhs_->finish(asmVector);
291
  (*solution_) = 0;
292

293
294
  forEachNode_(localView.tree(), [&,this](auto const& rowNode, auto) {
    forEachNode_(localView.tree(), [&,this](auto const& colNode, auto) {
295
296
      // finish boundary condition
      for (auto bc : constraints_[rowNode][colNode])
297
        bc->finish(*systemMatrix_, *solution_, *rhs_, rowNode, colNode);
298
299
    });
  });
300

301
  msg("fill-in of assembled matrix: {}", systemMatrix_->nnz());
302
  msg("buildAfterAdapt needed {} seconds", t.elapsed());
303
}
304

305

306
307
template <class Traits>
void ProblemStat<Traits>::
308
writeFiles(AdaptInfo& adaptInfo, bool force)
309
{
310
  Dune::Timer t;
311
  for (auto writer : filewriter_)
312
    writer->writeFiles(adaptInfo, force);
313
  msg("writeFiles needed {} seconds", t.elapsed());
314
}
315

316

317
} // end namespace AMDiS