CouplingBaseProblem2_cxx11.h 9.01 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1
/** \file CouplingBaseProblem.h */
Praetorius, Simon's avatar
Praetorius, Simon committed
2

Praetorius, Simon's avatar
Praetorius, Simon committed
3
4
#ifndef COUPLING_BASE_PROBLEM_H
#define COUPLING_BASE_PROBLEM_H
Praetorius, Simon's avatar
Praetorius, Simon committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#include "AMDiS.h"

// coupling structures
#include "CouplingIterationInterface.h"
#include "CouplingTimeInterface.h"
#include "CouplingProblemStat.h"
#include "BaseProblem.h"
#include "ProblemInstat.h"

#include <tuple>
#include "GenericLoops_cxx11.h"

namespace AMDiS {

20
21
22
namespace extensions {

  namespace detail {
23

24
25
26
27
28
29
30
31
    /// for generic loops this struct can be passed
    struct AddProblem {
      template<typename CouplingProblemStatType, typename BaseProblemType>
      static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) {
	for (size_t j = 0; j < baseProblem.getNumProblems(); j++)
	  couplingProblemStat.addProblem(baseProblem.getProblem(j));
      }
    };
32

33
34
35
36
37
38
39
    /// for generic loops this struct can be passed
    struct AddTimeInterface {
      template<typename CouplingProblemStatType, typename BaseProblemType>
      static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) {
	couplingProblemStat.addTimeInterface(&baseProblem);
      }
    };
40

41
42
43
44
45
46
47
    /// for generic loops this struct can be passed
    struct AddIterationInterface {
      template<typename CouplingProblemStatType, typename BaseProblemType>
      static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) {
	couplingProblemStat.addIterationInterface(&baseProblem);
      }
    };
48

49
50
51
52
53
    /// Functor for generic loops. Method initData() is called for each element in a sequence.
    struct InitData {
      template<typename BaseProblemType>
      static void call(BaseProblemType& baseProblem) { baseProblem.initData(); }
    };
54

55
56
57
58
59
    /// Functor for generic loops. Method initData() is called for each element in a sequence.
    struct FinalizeData {
      template<typename BaseProblemType>
      static void call(BaseProblemType& baseProblem) { baseProblem.finalizeData(); }
    };
60

61
62
63
64
65
    /// Functor for generic loops. Method fillOperators() is called for each element in a sequence.
    struct FillOperators {
      template<typename BaseProblemType>
      static void call(BaseProblemType& baseProblem) { baseProblem.fillOperators(); }
    };
66

67
68
69
70
71
    /// Functor for generic loops. Method fillBoundaryConditions() is called for each element in a sequence.
    struct FillBoundaryConditions {
      template<typename BaseProblemType>
      static void call(BaseProblemType& baseProblem) { baseProblem.fillBoundaryConditions(); }
    };
72
73


74
75
76
77
78
79
80
    struct FindProblem {
      template<typename BaseProblemType, typename ProblemType>
      static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType& prob) {
	if (baseProblem.getName() == name)
	  prob = baseProblem.getProblem();
      }
    };
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    struct FindBaseProblem {
      template<typename BaseProblemType, typename ProblemType>
      static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob) {
	typedef typename boost::mpl::if_<typename boost::is_same<BaseProblemType, ProblemType>::type,
					boost::mpl::bool_<true>,
					boost::mpl::bool_<false> >::type assign;
	call(baseProblem, name, prob,  assign());
      }
      template<typename BaseProblemType, typename ProblemType>
      static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<true>) {
	if (baseProblem.getName() == name)
	  prob = &baseProblem;
      }
      template<typename BaseProblemType, typename ProblemType>
      static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<false>) {}
    };
98

99
  } // end namespace detail
Praetorius, Simon's avatar
Praetorius, Simon committed
100
101

/**
102
  * \ingroup Problem
Praetorius, Simon's avatar
Praetorius, Simon committed
103
104
105
106
  *
  * \brief Structur to couple BaseProblems of variouse types
  */
template<typename ProblemType=ProblemStat, typename... BaseProblemTypes >
Praetorius, Simon's avatar
Praetorius, Simon committed
107
class CouplingBaseProblem : public CouplingIterationInterface,
108
109
			    public CouplingTimeInterface,
			    public AMDiS::detail::CouplingProblemStat<ProblemType>
Praetorius, Simon's avatar
Praetorius, Simon committed
110
111
{
public:
112
  typedef AMDiS::detail::CouplingProblemStat<ProblemType> CProblemStat;
Praetorius, Simon's avatar
Praetorius, Simon committed
113
114
115
  typedef std::tuple<BaseProblemTypes&...> BaseProblemsTupleType;

  template<typename... BaseProblemTypes_>
Praetorius, Simon's avatar
Praetorius, Simon committed
116
  CouplingBaseProblem(std::string name_, BaseProblemTypes_&&... baseProblems_)
117
118
119
  : ProblemIterationInterface(),	// virtual base class constructor
    ProblemTimeInterface(),		// virtual base class constructor
    CProblemStat(name_),
Praetorius, Simon's avatar
Praetorius, Simon committed
120
121
122
    baseProblems(baseProblems_...),
    name(name_)
  {
123
    dow = Global::getGeo(WORLD);
Praetorius, Simon's avatar
Praetorius, Simon committed
124
125
  }

126
  ~CouplingBaseProblem() { }
127
128
129
130
131
132
133
134
135
136

  /**
   * Add the problems to the iterationInterface, timeInterface and couplingProblemStat.
   * As a consequence all problem can be initialized one after another and in the
   * adaption loop they are solved in rotation.
   *
   * In the adaption loop the problems are solved the same order as they are added to the
   * iterationInterface in this method. This order can be changed manually in the oneIteration
   * method.
   **/
137
  virtual void initialize(Flag initFlag,
138
139
		  ProblemStatSeq *adoptProblem = NULL,
		  Flag adoptFlag = INIT_NOTHING) override
Praetorius, Simon's avatar
Praetorius, Simon committed
140
141
142
143
144
145
146
  {
    tools::FOR_EACH< detail::AddProblem >::loop2(*this, baseProblems);
    tools::FOR_EACH< detail::AddIterationInterface >::loop2(*this, baseProblems);
    tools::FOR_EACH< detail::AddTimeInterface >::loop2(*this, baseProblems);

    // initialize all ProblemStat
    CProblemStat::initialize(initFlag, adoptProblem, adoptFlag);
147

Praetorius, Simon's avatar
Praetorius, Simon committed
148
149
150
    // set mesh dimension
    dim = CProblemStat::getMesh(0)->getDim();
  }
151
152

  virtual void initData() {}
Praetorius, Simon's avatar
Praetorius, Simon committed
153
  virtual void finalizeData() {}
154

155
156
157
158
159
  /**
   * At first the initData method is called for all baseProblems, then
   * the problems are filled with operators and coupling operators as well as
   * boundary conditions are added.
   **/
Praetorius, Simon's avatar
Praetorius, Simon committed
160
161
162
163
  virtual void initTimeInterface()
  {
    tools::FOR_EACH< detail::InitData >::loop(baseProblems);
    initData();
164

Praetorius, Simon's avatar
Praetorius, Simon committed
165
166
    tools::FOR_EACH< detail::FillOperators >::loop(baseProblems);
    fillCouplingOperators();
167

Praetorius, Simon's avatar
Praetorius, Simon committed
168
169
    tools::FOR_EACH< detail::FillBoundaryConditions >::loop(baseProblems);
    fillCouplingBoundaryConditions();
170

Praetorius, Simon's avatar
Praetorius, Simon committed
171
172
    tools::FOR_EACH< detail::FinalizeData >::loop(baseProblems);
    finalizeData();
Praetorius, Simon's avatar
Praetorius, Simon committed
173
  }
174
175


Praetorius, Simon's avatar
Praetorius, Simon committed
176
177
  virtual void fillCouplingOperators() {}
  virtual void fillCouplingBoundaryConditions() {}
178
179


Praetorius, Simon's avatar
Praetorius, Simon committed
180
181
182
  /// get the j-th solution-vector of the i-th problem
  template<int i>
  DOFVector<double> *getSolution(int j)
Praetorius, Simon's avatar
Praetorius, Simon committed
183
  { FUNCNAME("CouplingBaseProblem::getSolution<i>(j)");
Praetorius, Simon's avatar
Praetorius, Simon committed
184
    BOOST_STATIC_ASSERT_MSG(0 <= i && i < _LENGTH_<BaseProblemsTupleType>::value , "********** ERROR: BaseProblem-index out of range **********");
185

Praetorius, Simon's avatar
Praetorius, Simon committed
186
187
188
    TEST_EXIT(0 <= j && j <= _GET_<i>(baseProblems).getNumComponents())("Indices out of range!\n");
    return _GET_<i>(baseProblems).getSolution()->getDOFVector(j);
  }
189
190


Praetorius, Simon's avatar
Praetorius, Simon committed
191
192
  /// pointer to the j-th feSpace of the i-th problem
  template<int i>
193
  inline const FiniteElemSpace* getFeSpace(int j=0)
Praetorius, Simon's avatar
Praetorius, Simon committed
194
  { FUNCNAME("CouplingBaseProblem::getFeSpace<i>(j)");
Praetorius, Simon's avatar
Praetorius, Simon committed
195
    BOOST_STATIC_ASSERT_MSG(0 <= i && i < _LENGTH_<BaseProblemsTupleType>::value , "********** ERROR: BaseProblem index out of range **********");
196

Praetorius, Simon's avatar
Praetorius, Simon committed
197
    TEST_EXIT(0 <= j && j <= _GET_<i>(baseProblems).getNumComponents())("Indices out of range!\n");
198
    return _GET_<i>(baseProblems).getFeSpace(j);
Praetorius, Simon's avatar
Praetorius, Simon committed
199
  }
200

Praetorius, Simon's avatar
Praetorius, Simon committed
201
  std::string getName() const { return name; }
202

Praetorius, Simon's avatar
Praetorius, Simon committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

  ProblemType *getProblem(std::string name_)
  {
    ProblemType *prob = NULL;
    tools::FOR_EACH< detail::FindProblem >::loop1(baseProblems, name_, prob);
    if (prob)
      return prob;
    else
      throw(std::runtime_error("problem with given name '" + name_ + "' does not exist"));
  }

  template<typename BaseProblemType>
  BaseProblemType *getBaseProblem(std::string name_)
  {
    BaseProblemType *prob = NULL;
    tools::FOR_EACH< detail::FindBaseProblem >::loop1(baseProblems, name_, prob);
    if (prob)
      return prob;
    else
      throw(std::runtime_error("problem with given name '" + name_ + "' does not exist"));
  }
224

225
  // final overriders for some functions...
226

227
228
  virtual void serialize(std::ostream &out) {};
  virtual void deserialize(std::istream &in) {};
229

230
  // using CouplingIterationInterface::beginIteration
231
232
233
  virtual void beginIteration(AdaptInfo *adaptInfo) override
  {
    CouplingIterationInterface::beginIteration(adaptInfo);
234
  }
235

236
  // using CouplingIterationInterface::oneIteration
237
238
239
  virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo) override
  {
    return CouplingIterationInterface::oneIteration(adaptInfo,toDo);
240
  }
241

242
  // using CouplingIterationInterface::endIteration
243
244
245
  virtual void endIteration(AdaptInfo *adaptInfo) override
  {
    CouplingIterationInterface::endIteration(adaptInfo);
246
  }
247

248
  // using CProblemStat::getNumProblems
Praetorius, Simon's avatar
Praetorius, Simon committed
249
  virtual int getNumProblems() const override
250
251
  {
    return CProblemStat::getNumProblems();
252
  }
253

254
  // using CProblemStat::getProblem
255
256
257
  virtual ProblemType *getProblem(int number = 0) override
  {
    return CProblemStat::getProblem(number);
258
  }
259

Praetorius, Simon's avatar
Praetorius, Simon committed
260
261
262
263
264
protected:
  BaseProblemsTupleType baseProblems;

  unsigned dim;	// dimension of the meshes
  unsigned dow;	// dimension of the world
265

Praetorius, Simon's avatar
Praetorius, Simon committed
266
267
268
  std::string name;
};

269
270
} // end namespace extensions

Praetorius, Simon's avatar
Praetorius, Simon committed
271
272
} // end namespace AMDiS

Praetorius, Simon's avatar
Praetorius, Simon committed
273
#endif // COUPLING_BASE_PROBLEM_H