boundarytypes.hh 13.1 KB
Newer Older
1
2
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
3
/*****************************************************************************
4
 *   See the file COPYING for full copying permissions.                      *
5
 *                                                                           *
6
 *   This program is free software: you can redistribute it and/or modify    *
7
 *   it under the terms of the GNU General Public License as published by    *
8
9
 *   the Free Software Foundation, either version 2 of the License, or       *
 *   (at your option) any later version.                                     *
10
 *                                                                           *
11
12
 *   This program is distributed in the hope that it will be useful,         *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
14
15
16
17
 *   GNU General Public License for more details.                            *
 *                                                                           *
 *   You should have received a copy of the GNU General Public License       *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
18
19
20
 *****************************************************************************/
/*!
 * \file
21
 * \ingroup Common
22
23
 * \brief Class to specify the type of a boundary.
 */
24
25
#ifndef DUMUX_BOUNDARY_TYPES_HH
#define DUMUX_BOUNDARY_TYPES_HH
26
27
28
29

namespace Dumux
{

30
/*!
31
 * \ingroup Common
32
33
 * \brief Class to specify the type of a boundary.
 */
34
35
36
37
38
39
40
template <int numEq>
class BoundaryTypes
{
public:
    BoundaryTypes()
    { reset(); }

41
42
43
44
    //! we have a boundary condition for each equation
    static constexpr int size()
    { return numEq; }

45
    /*!
46
     * \brief Reset the boundary types for all equations.
47
48
     *
     * After this method no equations will be disabled and neither
49
     * Neumann nor Dirichlet conditions will be evaluated. This
50
     * corresponds to a Neumann zero boundary.
51
52
53
     */
    void reset()
    {
54
55
        for (int eqIdx=0; eqIdx < numEq; ++eqIdx)
            resetEq(eqIdx);
56
57
    }

58
59
60
61
62
    /*!
     * \brief Reset the boundary types for one equation.
     */
    void resetEq(int eqIdx)
    {
63
          boundaryInfo_[eqIdx].visited = false;
64

65
66
67
68
69
70
          boundaryInfo_[eqIdx].isDirichlet = false;
          boundaryInfo_[eqIdx].isNeumann = false;
          boundaryInfo_[eqIdx].isOutflow = false;
          boundaryInfo_[eqIdx].isCouplingDirichlet = false;
          boundaryInfo_[eqIdx].isCouplingNeumann = false;
          boundaryInfo_[eqIdx].isCouplingMortar = false;
71
72
73
74
75

          eq2pvIdx_[eqIdx] = eqIdx;
          pv2eqIdx_[eqIdx] = eqIdx;
    }

76
    /*!
77
78
79
80
     * \brief Returns true if the boundary types for a given equation
     *        has been specified.
     *
     * \param eqIdx The index of the equation
81
82
     */
    bool isSet(int eqIdx) const
83
    { return boundaryInfo_[eqIdx].visited; }
84
85
86
87

    /*!
     * \brief Make sure the boundary conditions are well-posed.
     *
88
     * If they are not, an assertion fails and the program aborts!
89
     * (if the NDEBUG macro is not defined)
90
91
92
     */
    void checkWellPosed() const
    {
93
        // if this fails, at least one condition is missing.
94
        for (int i=0; i < numEq; ++i)
95
            assert(boundaryInfo_[i].visited);
96
    }
97
98

    /*!
99
     * \brief Set all boundary conditions to Neumann.
100
101
102
     */
    void setAllNeumann()
    {
103
104
        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
            setNeumann(eqIdx);
105
106
107
    }

    /*!
108
     * \brief Set all boundary conditions to Dirichlet.
109
110
111
     */
    void setAllDirichlet()
    {
112
113
        for (int eqIdx = 0; eqIdx < numEq; ++ eqIdx)
            setDirichlet(eqIdx);
114
115
    }

116
    /*!
117
     * \brief Set all boundary conditions to Neumann.
118
119
120
     */
    void setAllOutflow()
    {
121
122
        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
            setOutflow(eqIdx);
123
124
    }

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    /*!
     * \brief Set all boundary conditions to Dirichlet-like coupling
     */
    void setAllCouplingDirichlet()
    {
        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
            setCouplingDirichlet(eqIdx);
    }

    /*!
     * \brief Set all boundary conditions to Neumann-like coupling.
     */
    void setAllCouplingNeumann()
    {
        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
            setCouplingNeumann(eqIdx);
    }
    /*!
     * \brief Set all boundary conditions to mortar coupling.
     */
    void setAllCouplingMortar()
    {
        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
            setCouplingDirichlet(eqIdx);
    }

151
    /*!
152
     * \brief Set a Neumann boundary condition for a single a single
153
     *        equation.
154
155
     *
     * \param eqIdx The index of the equation
156
157
158
     */
    void setNeumann(int eqIdx)
    {
159
        resetEq(eqIdx);
160
161
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isNeumann = true;
162
163
164
    }

    /*!
165
     * \brief Set a Dirichlet boundary condition for a single primary
166
167
     *        variable
     *
168
169
170
171
     * \param pvIdx The index of the primary variable for which the
     *              Dirichlet condition should apply.
     * \param eqIdx The index of the equation which should used to set
     *              the Dirichlet condition
172
     */
173
    void setDirichlet(int pvIdx, int eqIdx)
174
    {
175
        resetEq(eqIdx);
176
177
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isDirichlet = true;
178
179
180
181
182
183

        // update the equation <-> primary variable mapping
        eq2pvIdx_[eqIdx] = pvIdx;
        pv2eqIdx_[pvIdx] = eqIdx;
    }

184
    /*!
185
     * \brief Set a Neumann boundary condition for a single a single
186
     *        equation.
187
188
189
     *
     * \param eqIdx The index of the equation on which the outflow
     *              condition applies.
190
191
192
     */
    void setOutflow(int eqIdx)
    {
193
        resetEq(eqIdx);
194
195
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isOutflow = true;
196
197
198
199
200
201
202
203
204
    }

    /*!
     * \brief Set a boundary condition for a single equation to
     *        a Dirichlet-like coupling condition.
     */
    void setCouplingDirichlet(int eqIdx)
    {
        resetEq(eqIdx);
205
206
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isCouplingDirichlet = true;
207
208
209
210
211
212
213
214
215
    }

    /*!
     * \brief Set a boundary condition for a single equation to
     *        a Neumann-like coupling condition.
     */
    void setCouplingNeumann(int eqIdx)
    {
        resetEq(eqIdx);
216
217
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isCouplingNeumann = true;
218
219
220
221
222
223
224
225
226
    }

    /*!
     * \brief Set a boundary condition for a single equation to
     *        a mortar coupling condition.
     */
    void setCouplingMortar(int eqIdx)
    {
        resetEq(eqIdx);
227
228
        boundaryInfo_[eqIdx].visited = true;
        boundaryInfo_[eqIdx].isCouplingMortar = true;
229
230
    }

231
    /*!
232
     * \brief Set a Dirichlet boundary condition for a single primary
233
     *        variable.
234
     *
235
236
     * Depending on the discretization, setting the Dirichlet condition
     * will replace the balance equation with index equal to pvIdx.
237
     *
238
239
     * \param pvIdx The index of the primary variable inside a
     *              PrimaryVariables object.
240
     */
241
    void setDirichlet(int pvIdx)
242
    {
243
        setDirichlet(pvIdx, pvIdx);
244
245
246
247
    }

    /*!
     * \brief Returns true if an equation is used to specify a
248
     *        Dirichlet condition.
249
250
     *
     * \param eqIdx The index of the equation
251
252
     */
    bool isDirichlet(unsigned eqIdx) const
Katherina Baber's avatar
Katherina Baber committed
253
    { return boundaryInfo_[eqIdx].isDirichlet; }
254

255
    /*!
Dennis Gläser's avatar
Dennis Gläser committed
256
     * \brief Returns true if all equations are used to specify a
257
258
259
260
261
262
263
264
265
266
     *        Dirichlet condition.
     */
    bool hasOnlyDirichlet() const
    {
        return std::all_of(boundaryInfo_.begin(),
                           boundaryInfo_.end(),
                           [](const BoundaryInfo& b){ return b.isDirichlet; }
                           );
    }

267
268
    /*!
     * \brief Returns true if some equation is used to specify a
269
     *        Dirichlet condition.
270
271
272
273
274
275
276
     */
    bool hasDirichlet() const
    {
        for (int i = 0; i < numEq; ++i)
            if (boundaryInfo_[i].isDirichlet)
                return true;
        return false;
Katherina Baber's avatar
Katherina Baber committed
277
    }
278
279
280

    /*!
     * \brief Returns true if an equation is used to specify a
281
     *        Neumann condition.
282
283
     *
     * \param eqIdx The index of the equation
284
285
     */
    bool isNeumann(unsigned eqIdx) const
Katherina Baber's avatar
Katherina Baber committed
286
    { return boundaryInfo_[eqIdx].isNeumann; }
287

Dennis Gläser's avatar
Dennis Gläser committed
288
289
290
291
292
293
294
295
296
297
298
299
    /*!
     * \brief Returns true if all equations are used to specify a
     *        Neumann condition.
     */
    bool hasOnlyNeumann() const
    {
        return std::all_of(boundaryInfo_.begin(),
                           boundaryInfo_.end(),
                           [](const BoundaryInfo& b){ return b.isNeumann; }
                           );
    }

300
301
    /*!
     * \brief Returns true if some equation is used to specify a
302
     *        Neumann condition.
303
304
305
306
     */
    bool hasNeumann() const
    {
        for (int i = 0; i < numEq; ++i)
Andreas Lauser's avatar
Andreas Lauser committed
307
            if (boundaryInfo_[i].isNeumann)
308
309
                return true;
        return false;
Katherina Baber's avatar
Katherina Baber committed
310
    }
311

312
313
314
    /*!
     * \brief Returns true if an equation is used to specify an
     *        outflow condition.
315
316
     *
     * \param eqIdx The index of the equation
317
318
     */
    bool isOutflow(unsigned eqIdx) const
Katherina Baber's avatar
Katherina Baber committed
319
    { return boundaryInfo_[eqIdx].isOutflow; }
320
321
322
323
324
325
326
327
328
329
330

    /*!
     * \brief Returns true if some equation is used to specify an
     *        outflow condition.
     */
    bool hasOutflow() const
    {
        for (int i = 0; i < numEq; ++i)
            if (boundaryInfo_[i].isOutflow)
                return true;
        return false;
Katherina Baber's avatar
Katherina Baber committed
331
    }
332

333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
    /*!
     * \brief Returns true if an equation is used to specify an
     *        Dirichlet coupling condition.
     *
     * \param eqIdx The index of the equation
     */
    bool isCouplingDirichlet(unsigned eqIdx) const
    { return boundaryInfo_[eqIdx].isCouplingDirichlet; }

    /*!
     * \brief Returns true if some equation is used to specify an
     *        Dirichlet coupling condition.
     */
    bool hasCouplingDirichlet() const
    {
        for (int i = 0; i < numEq; ++i)
            if (boundaryInfo_[i].isCouplingDirichlet)
                return true;
        return false;
    }

    /*!
     * \brief Returns true if an equation is used to specify an
     *        Neumann coupling condition.
     *
     * \param eqIdx The index of the equation
     */
    bool isCouplingNeumann(unsigned eqIdx) const
    { return boundaryInfo_[eqIdx].isCouplingNeumann; }

    /*!
     * \brief Returns true if some equation is used to specify an
     *        Neumann coupling condition.
     */
    bool hasCouplingNeumann() const
    {
        for (int i = 0; i < numEq; ++i)
            if (boundaryInfo_[i].isCouplingNeumann)
                return true;
        return false;
    }

375
376
    /*!
     * \brief Returns true if an equation is used to specify a
377
     *        Mortar coupling condition.
378
379
     *
     * \param eqIdx The index of the equation
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
     */
    bool isCouplingMortar(unsigned eqIdx) const
    {
        return boundaryInfo_[eqIdx].isCouplingMortar;
    }

    /*!
     * \brief Returns true if some equation is used to specify an
     *        Mortar coupling condition.
     */
    bool hasCouplingMortar() const
    {
        for (int i = 0; i < numEq; ++i)
            if (boundaryInfo_[i].isCouplingMortar)
                return true;
        return false;
    }

    /*!
     * \brief Returns true if an equation is used to specify a
     *        coupling condition.
401
     *
402
     * \param eqIdx The index of the equation
403
404
405
     */
    bool isCoupling(unsigned eqIdx) const
    {
406
407
408
        return boundaryInfo_[eqIdx].isCouplingDirichlet
               || boundaryInfo_[eqIdx].isCouplingNeumann
               || boundaryInfo_[eqIdx].isCouplingMortar;
409
410
411
412
413
414
415
416
    }

    /*!
     * \brief Returns true if some equation is used to specify a
     *        coupling condition.
     */
    bool hasCoupling() const
    {
417
418
419
        for (int i = 0; i < numEq; ++i)
            if (isCoupling(i))
                return true;
420
421
422
        return false;
    }

423
424
    /*!
     * \brief Returns the index of the equation which should be used
425
     *        for the Dirichlet condition of the pvIdx's primary
426
     *        variable.
427
428
429
     *
     * \param pvIdx The index of the primary variable which is be set
     *              by the Dirichlet condition.
430
431
     */
    unsigned dirichletToEqIndex(unsigned pvIdx) const
Katherina Baber's avatar
Katherina Baber committed
432
    { return pv2eqIdx_[pvIdx]; }
433
434
435

    /*!
     * \brief Returns the index of the primary variable which should
436
     *        be used for the Dirichlet condition given an equation
437
     *        index.
438
439
440
     *
     * \param eqIdx The index of the equation which is used to set
     *              the Dirichlet condition.
441
442
     */
    unsigned eqToDirichletIndex(unsigned eqIdx) const
Katherina Baber's avatar
Katherina Baber committed
443
    { return eq2pvIdx_[eqIdx]; }
444

445
protected:
446
    //! use bitfields to minimize the size
447
    struct BoundaryInfo {
448
449
450
451
452
453
454
        bool visited : 1;
        bool isDirichlet : 1;
        bool isNeumann : 1;
        bool isOutflow : 1;
        bool isCouplingDirichlet : 1;
        bool isCouplingNeumann : 1;
        bool isCouplingMortar : 1;
455
456
457
458
    };

    std::array<BoundaryInfo, numEq> boundaryInfo_;
    std::array<unsigned int, numEq> eq2pvIdx_, pv2eqIdx_;
459
460
};

461
} // end namespace Dumux
462
463

#endif