Operator.h 102 KB
Newer Older
1
2
3
4
5
6
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
7
// ==  TU Dresden                                                            ==
8
// ==                                                                        ==
9
10
11
// ==  Institut fr Wissenschaftliches Rechnen                               ==
// ==  Zellescher Weg 12-14                                                  ==
// ==  01069 Dresden                                                         ==
12
13
14
15
// ==  germany                                                               ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
16
// ==  https://gforge.zih.tu-dresden.de/projects/amdis/                      ==
17
18
19
20
21
22
23
24
25
// ==                                                                        ==
// ============================================================================

/** \file Operator.h */

#ifndef AMDIS_OPERATOR_H
#define AMDIS_OPERATOR_H

#include <vector>
26
#include "AMDiS_fwd.h"
27
28
29
30
31
#include "FixVec.h"
#include "Flag.h"
#include "MatrixVector.h"
#include "ElInfo.h"
#include "AbstractFunction.h"
32
#include "OpenMP.h"
33
#include "SubAssembler.h"
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

namespace AMDiS {

  /** 
   * \ingroup Assembler
   * 
   * \brief
   * Base class for ZeroOrderTerm, FirstOrderTerm and SecondOrderTerm. 
   * OperatorTerms are the building blocks of an Operator. Each OperatorTerm
   * has its properties which are regarded, when constructing 
   * an Assembler for the corresponding Operator.
   */
  class OperatorTerm
  {
  public:
    /** \brief
     * Constructs an OperatorTerm with initially no properties.
     * degree_ is used to determine the degree of the needed quadrature
     * for the assemblage.  
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
54
    OperatorTerm(int deg) 
55
      : properties(0), 
Thomas Witkowski's avatar
Thomas Witkowski committed
56
	degree(deg),
57
58
59
	dimOfWorld(Global::getGeo(WORLD)),
	auxFESpaces(0),
	bOne(-1)
60
    {}
61

Thomas Witkowski's avatar
Thomas Witkowski committed
62
63
    /// Destructor.
    virtual ~OperatorTerm() {}
64
65
66

    /** \brief
     * Virtual method. It's called by SubAssembler::initElement() for
Thomas Witkowski's avatar
Thomas Witkowski committed
67
68
     * each OperatorTerm belonging to this SubAssembler. E.g., vectors
     * and coordinates at quadrature points can be calculated here.
69
     */
70
    virtual void initElement(const ElInfo*, SubAssembler*, Quadrature *quad = NULL) 
71
72
73
74
    {
      FUNCNAME("OperatorTerm::initElement()");
      ERROR_EXIT("This function has not been implemented in the operator!\n");
    }
75

76
    virtual void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo,
77
78
79
80
81
			     SubAssembler*, Quadrature *quad = NULL)
    {
      FUNCNAME("OperatorTerm::initElement()");
      ERROR_EXIT("The function initElement has not been implemented for dual mesh traverse!\n");
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
82
83

    /// Returs \auxFESpaces, the list of all aux fe spaces the operator makes use off.
84
    std::vector<const FiniteElemSpace*>& getAuxFeSpaces() 
85
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
86
87
88
89
      return auxFESpaces;
    }

    /// Specifies whether the matrix of the term is symmetric
90
91
    void setSymmetric(bool symm);

Thomas Witkowski's avatar
Thomas Witkowski committed
92
    /// Returns true, if the term is piecewise constant, returns false otherwise
93
94
    inline bool isPWConst() 
    { 
95
      return (degree == 0);
96
    }
97

Thomas Witkowski's avatar
Thomas Witkowski committed
98
    /// Returns true, if the term has a symmetric matrix, returns false otherwise.
99
100
    bool isSymmetric();

Thomas Witkowski's avatar
Thomas Witkowski committed
101
    /// Returns \ref degree.
102
103
    inline int getDegree() 
    { 
104
      return degree; 
105
    }
106

107
108
109
110
111
112
    /// Sets one component of the b vector to be one. See \ref bOne.
    void setB(int b)
    {
      bOne = b;
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
113
    /// Evaluation of the OperatorTerm at all quadrature points.
Thomas Witkowski's avatar
Thomas Witkowski committed
114
115
    virtual void eval(int nPoints,
		      const double *uhAtQP,
116
117
		      const WorldVector<double> *grdUhAtQP,
		      const WorldMatrix<double> *D2UhAtQP,
Thomas Witkowski's avatar
Thomas Witkowski committed
118
		      double *result,
119
120
121
		      double factor) const = 0;

    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
122
123
     * Determines the value of a dof vector at the quadrature points of a given 
     * element. It is used by all VecAtQP like operator terms.
124
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    double *getVectorAtQPs(DOFVectorBase<double>* vec,
			   const ElInfo* elInfo, 
			   SubAssembler* subAssembler,
			   Quadrature *quad);		   

    /** \brief
     * Determines the value of a dof vector at the quadrature points of a given 
     * element. This function is used, if an operator is assembled on two different
     * meshes using the dual traverse. The element, i.e. the small or the large one,
     * is choosen, which corresponds to the mesh the dof vector is defined on.
     */
    double *getVectorAtQPs(DOFVectorBase<double>* vec,
			   const ElInfo* smallElInfo, 
			   const ElInfo* largeElInfo, 
			   SubAssembler* subAssembler,
			   Quadrature *quad);	

Thomas Witkowski's avatar
Thomas Witkowski committed
142
    ///
Thomas Witkowski's avatar
Thomas Witkowski committed
143
144
145
146
147
    WorldVector<double>* getGradientsAtQPs(DOFVectorBase<double>* vec,
					   const ElInfo* elInfo,
					   SubAssembler* subAssembler,
					   Quadrature *quad);

Thomas Witkowski's avatar
Thomas Witkowski committed
148
    ///
Thomas Witkowski's avatar
Thomas Witkowski committed
149
150
151
152
153
154
155
156
    WorldVector<double>* getGradientsAtQPs(DOFVectorBase<double>* vec,
					   const ElInfo* smallElInfo, 
					   const ElInfo* largeElInfo,
					   SubAssembler* subAssembler,
					   Quadrature *quad);

  protected:
    /// Evaluation of \f$ \Lambda \cdot A \cdot \Lambda^t\f$.
157
158
159
160
161
    void lalt(const DimVec<WorldVector<double> >& Lambda,
	      const WorldMatrix<double>& matrix,
	      DimMat<double>& LALt,
	      bool symm,
	      double factor) const;
162
163
164
165
166
167
168
169

    /** \brief
     * Evaluation of \f$ \Lambda \cdot A \cdot \Lambda^t\f$ for \f$ A \f$
     * the matrix having a ONE in the position \f$ (K,L) \f$
     * and ZEROS in all other positions.
     */
    static void lalt_kl(const DimVec<WorldVector<double> >& Lambda,
			int k, int l,
Thomas Witkowski's avatar
Thomas Witkowski committed
170
171
			DimMat<double>& LALt,
			double factor);
172

173
    /// Evaluation of \f$ \Lambda \cdot A \cdot \Lambda^t\f$ for A equal to the identity.
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    inline void l1lt(const DimVec<WorldVector<double> >& Lambda, 
		     DimMat<double>& LALt,
		     double factor) const
    {
      const int dim = LALt.getNumRows();
      
      for (int i = 0; i < dim; i++) {
	double val = 0.0;
	for (int k = 0; k < dimOfWorld; k++)
	  val += Lambda[i][k] * Lambda[i][k];
	val *= factor;
	LALt[i][i] += val;
	for (int j = i + 1; j < dim; j++) {
	  val = 0.0;
	  for (int k = 0; k < dimOfWorld; k++)
	    val += Lambda[i][k] * Lambda[j][k];
	  val *= factor;
	  LALt[i][j] += val;
	  LALt[j][i] += val;
	}    
      }      
    }
196

Thomas Witkowski's avatar
Thomas Witkowski committed
197
    /// Evaluation of \f$ \Lambda \cdot b\f$.
198
199
200
201
    inline void lb(const DimVec<WorldVector<double> >& Lambda,
		   const WorldVector<double>& b,
		   DimVec<double>& Lb,
		   double factor) const
202
    {
203
      const int dim = Lambda.getSize();
204

205
      for (int i = 0; i < dim; i++) {
206
207
208
209
210
211
212
213
214
	double val = 0.0;
	
	for (int j = 0; j < dimOfWorld; j++)
	  val += Lambda[i][j] * b[j];
	
	Lb[i] += val * factor;
      }    
    }

215
216
217
218
219
    /// Evaluation of \f$ \Lambda \cdot b\f$.
    inline void lb_one(const DimVec<WorldVector<double> >& Lambda,
		       DimVec<double>& Lb,
		       double factor) const
    {
220
      const int dim = Lambda.getSize();
221
222
223
224
225

      for (int i = 0; i < dim; i++)
	Lb[i] += Lambda[i][bOne] * factor;
    }

226
227
228
229
    /** \brief
     * Evaluation of \f$ \Lambda \cdot b\f$ if b contains the value 1.0 in 
     * each component.
     */
230
231
232
    inline void l1(const DimVec<WorldVector<double> >& Lambda,
		   DimVec<double>& Lb,
		   double factor) const
233
    {
234
      const int dim = Lambda.getSize();
235

236
      for (int i = 0; i < dim; i++) {
237
238
	double val = 0.0;
      
239
	for (int j = 0; j < dimOfWorld; j++)
240
	  val += Lambda[i][j];
241

242
	Lb[i] += val * factor;
243
      }    
244
    }
245
246

  protected:
Thomas Witkowski's avatar
Thomas Witkowski committed
247
    /// Stores the properties of this OperatorTerm
248
249
    Flag properties;

Thomas Witkowski's avatar
Thomas Witkowski committed
250
    /// Polynomial degree of the term. Used to detemine the degree of the quadrature.
251
252
    int degree;

253
254
255
    /// Stores the dimension of the world.
    int dimOfWorld;

Thomas Witkowski's avatar
Thomas Witkowski committed
256
257
258
259
    /// List off all fe spaces, the operator term makes use off.
    std::vector<const FiniteElemSpace*> auxFESpaces;

    /// Pointer to the Operator this OperatorTerm belongs to.
260
261
    Operator* operat;

262
263
264
265
266
267
268
269
270
    /** \brief
     * In many cases, the vector b in the evaluation \f$ \Lambda \cdot b\f$ has zeros
     * in all components expect one that is set to one. Using the function \ref lb is
     * then unnecessary time consuming. Instead, this variable defines the component
     * of the vector b to be one. The function \ref lb_one is used if this variable is
     * not -1.
     */
    int bOne;

Thomas Witkowski's avatar
Thomas Witkowski committed
271
    /// Flag for piecewise constant terms
272
273
    static const Flag PW_CONST;

Thomas Witkowski's avatar
Thomas Witkowski committed
274
    /// Flag for symmetric terms
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    static const Flag SYMMETRIC;

    friend class SubAssembler;
    friend class ZeroOrderAssembler;
    friend class FirstOrderAssembler;
    friend class SecondOrderAssembler;
    friend class Operator;
  };

  /**
   * \ingroup Assembler
   * 
   * \brief
   * Describes the second order terms: \f$ \nabla \cdot A \nabla u(\vec{x}) \f$
   */
  class SecondOrderTerm : public OperatorTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
293
    /// Constructor.
294
295
296
    SecondOrderTerm(int deg) 
      : OperatorTerm(deg) 
    {}
297

298
    /// Destructor.
299
300
    virtual ~SecondOrderTerm() 
    {}
301

302
    /// Evaluation of \f$ \Lambda A \Lambda^t \f$ at all quadrature points.
303
    virtual void getLALt(const ElInfo *elInfo, 
Thomas Witkowski's avatar
Thomas Witkowski committed
304
			 int nPoints, 
305
306
			 DimMat<double> **result) const = 0;

307
    /// Evaluation of \f$ A \nabla u(\vec{x}) \f$ at all quadrature points.
308
309
    virtual void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
			  std::vector<WorldVector<double> > &result) const = 0;
310
311
312
313
314
315
316
317
318
319
320
321

  };

  /**
   * \ingroup Assembler
   * 
   * \brief
   * Implements the laplace operator: \f$ \Delta u(\vec{x}) \f$
   */
  class Laplace_SOT : public SecondOrderTerm 
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
322
    /// Constructor.
323
324
325
326
    Laplace_SOT() 
      : SecondOrderTerm(0) 
    {
      setSymmetric(true);
327
    }
328

329
    /// Implenetation of SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
330
    inline void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const
331
332
333
    {
      const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();

334
      for (int iq = 0; iq < nPoints; iq++)
335
	l1lt(Lambda, *(LALt[iq]), 1.0);
336
    }
337

338
    /// Implementation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
339
    inline void eval(int nPoints,
340
341
		     const double *,
		     const WorldVector<double> *,
Thomas Witkowski's avatar
Thomas Witkowski committed
342
343
344
		     const WorldMatrix<double> *D2UhAtQP,
		     double *result,
		     double factor) const
345
346
347
348
    {
      int dow = Global::getGeo(WORLD);
    
      if (D2UhAtQP) {
Thomas Witkowski's avatar
Thomas Witkowski committed
349
	for (int iq = 0; iq < nPoints; iq++) {
350
	  double resultQP = 0.0;
351
	  for (int i = 0; i < dow; i++) 
352
353
354
355
	    resultQP += D2UhAtQP[iq][i][i];
	  result[iq] += factor * resultQP;
	}
      }
356
    }
357

358
    /// Implenetation of SecondOrderTerm::weakEval().
359
360
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const
361
    {
362
363
364
      int nPoints = grdUhAtQP.size();
      for (int iq = 0; iq < nPoints; iq++)
	result[iq] += grdUhAtQP[iq];
365
366
    }
  };
367
368
369
370
371
372
373
374
375
376
377

  /**
   * \ingroup Assembler
   * 
   * \brief
   * Implements the laplace operator multiplied with a scalar factor:
   * \f$ f \cdot \Delta u(\vec{x}) \f$
   */
  class FactorLaplace_SOT : public SecondOrderTerm 
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
378
    /// Constructor.
379
    FactorLaplace_SOT(double f) 
380
381
      : SecondOrderTerm(0)  
    {
382
383
384
385
      factor = new double;
      *factor = f;

      setSymmetric(true);
386
    }
387

Thomas Witkowski's avatar
Thomas Witkowski committed
388
    /// Constructor.
389
    FactorLaplace_SOT(double *fptr) 
390
391
      : SecondOrderTerm(0), 
	factor(fptr)
392
393
    {
      setSymmetric(true);
394
    }
395

396
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
397
    inline void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const
398
    {
399
      const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
Thomas Witkowski's avatar
Thomas Witkowski committed
400
      for (int iq = 0; iq < nPoints; iq++) 
401
	l1lt(Lambda, *(LALt[iq]), (*factor));
402
    }
403

404
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
405
    void eval(int nPoints,
406
	      const double *,
407
408
409
410
411
	      const WorldVector<double> *,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double f) const
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
412
      int dow = Global::getGeo(WORLD);
413

Thomas Witkowski's avatar
Thomas Witkowski committed
414
      if (D2UhAtQP) {
Thomas Witkowski's avatar
Thomas Witkowski committed
415
	for (int iq = 0; iq < nPoints; iq++) {
416
	  double resultQP = 0.0;
Thomas Witkowski's avatar
Thomas Witkowski committed
417
	  for (int i = 0; i < dow; i++) {
418
419
420
421
422
	    resultQP += D2UhAtQP[iq][i][i];
	  }
	  result[iq] += resultQP * f * (*factor);
	}
      }
423
    }
424

425
    /// Implenetation of SecondOrderTerm::weakEval().
426
427
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const
428
    {
429
430
431
      int nPoints = grdUhAtQP.size();
      for (int iq = 0; iq < nPoints; iq++)
	axpy(*factor, grdUhAtQP[iq], result[iq]);
432
    }
433
434

  private:
435
    /// Pointer to the factor.
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    double *factor;
  };

  /**
   * \ingroup Assembler
   * 
   * \brief
   * SecondOrderTerm where A is a function which maps a DOFVector evaluated at
   * a given quadrature point to a WolrdMatrix:
   * \f$ \nabla \cdot A(v(\vec{x})) \nabla u(\vec{x}) \f$
   */
  class MatrixFct_SOT : public SecondOrderTerm 
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
450
    /// Constructor.
451
452
453
    MatrixFct_SOT(DOFVectorBase<double> *dv, 
		  AbstractFunction<WorldMatrix<double>, double> *fct,
		  AbstractFunction<WorldVector<double>, WorldMatrix<double> > *div,
Thomas Witkowski's avatar
Thomas Witkowski committed
454
		  bool sym = false);
455

456
    /// Implementation of \ref OperatorTerm::initElement().
457
458
459
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

460
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
461
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
462
  
463
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
464
465
    void eval(int nPoints,
	      const double *uhAtQP,
466
467
468
469
470
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

471
    /// Implenetation of SecondOrderTerm::weakEval().
472
473
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
474
475

  protected:
476
    /// DOFVector to be evaluated at quadrature points.
477
478
    DOFVectorBase<double>* vec;

479
    /// Pointer to the values of the DOFVector at quadrature points.
480
481
    double* vecAtQPs;

482
    /// Function for A.
483
484
    AbstractFunction<WorldMatrix<double>, double>* matrixFct;

485
    ///
486
487
    AbstractFunction<WorldVector<double>, WorldMatrix<double> >* divFct;

488
    /// True, if \ref matrixFct produces always symmetric matrices.
489
490
491
492
493
494
495
496
497
498
499
500
    bool symmetric;
  };

  /** 
   * \ingroup Assembler
   *
   * \brief
   * SecondOrderTerm where A is a given fixed WorldMatrix<double>:
   * \f$ \nabla \cdot A \nabla u(\vec{x}) \f$
   */
  class Matrix_SOT : public SecondOrderTerm {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
501
    /// Constructor
502
    Matrix_SOT(WorldMatrix<double> mat) 
Thomas Witkowski's avatar
Thomas Witkowski committed
503
      : SecondOrderTerm(0), matrix(mat)
504
505
506
    {
      symmetric = matrix.isSymmetric();
      setSymmetric(symmetric);
507
    }
508

509
    /// Implements SecondOrderTerm::getLALt().
510
511
512
513
    inline void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const
    {
      const DimVec<WorldVector<double> >& Lambda = elInfo->getGrdLambda();
      for (int iq = 0; iq < nPoints; iq++) 
514
	lalt(Lambda, matrix, *(LALt[iq]), symmetric, 1.0);
515
    }
516
  
517
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
518
519
    void eval(int nPoints,
	      const double *uhAtQP,
520
521
522
523
524
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

525
    /// Implenetation of SecondOrderTerm::weakEval().
526
527
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
528
529

  protected:
530
    /// Matrix stroring A.
531
532
    WorldMatrix<double> matrix;

533
    /// True, if \ref matrix is symmetric.
534
535
536
537
538
539
540
541
542
543
544
545
546
547
    bool symmetric;
  };

  /** 
   * \ingroup Assembler
   *
   * \brief
   * SecondOrderTerm where A is a WorldMatrix<double> having a ONE in position IJ
   * and ZERO in all other positions
   * \f$ \nabla \cdot A \nabla u(\vec{x}) \f$
   */
  class FactorIJ_SOT : public SecondOrderTerm 
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
548
    /// Constructor.
549
    FactorIJ_SOT(int x_i, int x_j, double f) 
Thomas Witkowski's avatar
Thomas Witkowski committed
550
      : SecondOrderTerm(0), xi(x_i), xj(x_j)
551
552
553
554
555
    {
      factor = new double;
      *factor = f;

      setSymmetric(xi == xj);
556
    }
557

Thomas Witkowski's avatar
Thomas Witkowski committed
558
    /// Constructor.
559
    FactorIJ_SOT(int x_i, int x_j, double *fptr) 
Thomas Witkowski's avatar
Thomas Witkowski committed
560
      : SecondOrderTerm(0), xi(x_i), xj(x_j), factor(fptr)
561
562
    {
      setSymmetric(xi == xj);
563
    }
564

565
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
566
    inline void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const
567
    {
568
      const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
569
      for (int iq = 0; iq < nPoints; iq++)
570
	lalt_kl(Lambda, xi, xj, *(LALt[iq]), (*factor));
571
    }
572

Thomas Witkowski's avatar
Thomas Witkowski committed
573
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
574
    void eval(int nPoints,
575
576
577
578
579
580
	      const double              *,
	      const WorldVector<double> *,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double fac) const
    {
581
582
      if (D2UhAtQP)
	for (int iq = 0; iq < nPoints; iq++)
583
	  result[iq] += (*factor) * D2UhAtQP[iq][xi][xj] * fac;
584
    }
585

Thomas Witkowski's avatar
Thomas Witkowski committed
586
    /// Implenetation of SecondOrderTerm::weakEval().
587
588
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const
589
    {
590
591
592
      int nPoints = grdUhAtQP.size();
      for (int iq = 0; iq < nPoints; iq++)
	result[iq][xi] += (*factor) * grdUhAtQP[iq][xj];
593
    }
594
595

  private:
Thomas Witkowski's avatar
Thomas Witkowski committed
596
    /// Directions for the derivatives.
597
598
    int xi, xj;

Thomas Witkowski's avatar
Thomas Witkowski committed
599
    /// Pointer to the factor.
600
601
602
603
604
605
606
607
608
609
610
611
612
    double *factor;
  };

  /**
   * \ingroup Assembler
   *  
   * \brief
   * Laplace operator multiplied with a function evaluated at the quadrature
   * points of a given DOFVector:
   * \f$ f(v(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class VecAtQP_SOT : public SecondOrderTerm {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
613
614
    /// Constructor.
    VecAtQP_SOT(DOFVectorBase<double> *dv, AbstractFunction<double, double> *af);
615

Thomas Witkowski's avatar
Thomas Witkowski committed
616
    /// Implementation of \ref OperatorTerm::initElement().
617
618
619
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

Thomas Witkowski's avatar
Thomas Witkowski committed
620
621
622
623
624
    /// Implementation of \ref OperatorTerm::initElement() for multilpe meshes.
    void initElement(const ElInfo* smallElInfo,
		     const ElInfo* largeElInfo,
		     SubAssembler* subAssembler,
		     Quadrature *quad = NULL);
625

Thomas Witkowski's avatar
Thomas Witkowski committed
626
627
628
629
630
631
    /// Implements SecondOrderTerm::getLALt().
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;    

    /// Implenetation of SecondOrderTerm::eval().
    void eval(int nPoints,
	      const double *uhAtQP,
632
633
634
635
636
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

Thomas Witkowski's avatar
Thomas Witkowski committed
637
    /// Implenetation of SecondOrderTerm::weakEval().
638
639
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
640
641

  protected:
Thomas Witkowski's avatar
Thomas Witkowski committed
642
    /// DOFVector to be evaluated at quadrature points.
643
644
    DOFVectorBase<double>* vec;

Thomas Witkowski's avatar
Thomas Witkowski committed
645
    /// Pointer to an array containing the DOFVector evaluated at quadrature points.
646
647
    double* vecAtQPs;

Thomas Witkowski's avatar
Thomas Witkowski committed
648
    /// Function evaluated at \ref vecAtQPs.
649
650
651
    AbstractFunction<double, double> *f;
  };

652
653
654
655
656
657
658
659
660
661
  /**
   * \ingroup Assembler
   *  
   * \brief
   * Laplace operator multiplied with a function evaluated at the quadrature
   * points of a given DOFVector:
   * \f$ f(v(\vec{x}), w(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class Vec2AtQP_SOT : public SecondOrderTerm {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
662
    /// Constructor.
663
    Vec2AtQP_SOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2, 
Thomas Witkowski's avatar
Thomas Witkowski committed
664
		 BinaryAbstractFunction<double, double, double> *af);
665

666
    /// Implementation of \ref OperatorTerm::initElement().
667
668
669
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

670
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
671
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;    
672
    
673
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
674
    void eval(int nPoints,
675
676
677
678
679
680
	      const double *uhAtQP,
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;
    
681
    /// Implenetation of SecondOrderTerm::weakEval().
682
683
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
684
685
    
  protected:
686
    /// DOFVector to be evaluated at quadrature points.
687
688
689
    DOFVectorBase<double>* vec1;
    DOFVectorBase<double>* vec2;
    
690
    /// Pointer to an array containing the DOFVector evaluated at quadrature points.
691
692
693
    double* vecAtQPs1;
    double* vecAtQPs2;
    
694
    /// Function evaluated at \ref vecAtQPs.
695
696
697
    BinaryAbstractFunction<double, double, double> *f;
  };

698
699
700
701
702
703
704
705
706
  /**
   * \ingroup Assembler
   * 
   * \brief
   * Laplace multiplied with a function evaluated at each quadrature point:
   * \f$ f(\vec{x}) \Delta u(\vec{x}) \f$
   */
  class CoordsAtQP_SOT : public SecondOrderTerm {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
707
708
709
    /// Constructor.
    CoordsAtQP_SOT(AbstractFunction<double, WorldVector<double> > *af)
      : SecondOrderTerm(af->getDegree()), g(af)
710
711
    {
      setSymmetric(true);
Thomas Witkowski's avatar
Thomas Witkowski committed
712
    }
713

Thomas Witkowski's avatar
Thomas Witkowski committed
714
    /// Implementation of \ref OperatorTerm::initElement().
715
716
717
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

Thomas Witkowski's avatar
Thomas Witkowski committed
718
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
719
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;    
720

Thomas Witkowski's avatar
Thomas Witkowski committed
721
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
722
723
    void eval(int nPoints,
	      const double *uhAtQP,
724
725
726
727
728
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

Thomas Witkowski's avatar
Thomas Witkowski committed
729
    /// Implenetation of SecondOrderTerm::weakEval().
730
731
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
732
733
734


  protected:
Thomas Witkowski's avatar
Thomas Witkowski committed
735
    /// Stores coordinates at quadrature points. Set in \ref initElement().
736
737
    WorldVector<double>* coordsAtQPs;

Thomas Witkowski's avatar
Thomas Witkowski committed
738
    /// Function evaluated at quadrature points.
739
740
741
742
743
744
745
746
747
748
749
750
751
752
    AbstractFunction<double, WorldVector<double> > *g;
  };

  /**
   * \ingroup Assembler
   *
   * \brief
   * SecondOrderTerm where A is a function which maps the gradient of a 
   * DOFVector at each quadrature point to WorldMatrix<double>:
   * \f$ \nabla \cdot A(\nabla v(\vec{x})) \nabla u(\vec{x})\f$
   */
  class MatrixGradient_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
753
    /// Constructor.
754
    MatrixGradient_SOT(DOFVectorBase<double> *dv,
Thomas Witkowski's avatar
Thomas Witkowski committed
755
756
757
		       AbstractFunction<WorldMatrix<double>, WorldVector<double> > *af,
		       AbstractFunction<WorldVector<double>, WorldMatrix<double> > *divAf,
		       bool symm = false);
758

759
    /// Implementation of \ref OperatorTerm::initElement().
760
761
762
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

763
764
765
766
767
768
    /// Implementation of \ref OperatorTerm::initElement() for multilpe meshes.
    void initElement(const ElInfo* smallElInfo, 
		     const ElInfo* largeElInfo,
		     SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

769
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
770
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
771

772
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
773
774
    void eval(int nPoints,
	      const double *uhAtQP,
775
776
777
778
779
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

780
    /// Implenetation of SecondOrderTerm::weakEval().
781
782
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
783
784
785
786

  protected:
    DOFVectorBase<double>* vec;

787
    /// Function which maps each entry in \ref gradAtQPs to a WorldMatrix<double>.
788
789
790
791
792
793
794
795
796
797
    AbstractFunction<WorldMatrix<double>, WorldVector<double> > *f;

    AbstractFunction<WorldVector<double>, WorldMatrix<double> > *divFct;

    /** \brief
     * Pointer to a WorldVector<double> array containing the gradients of the DOFVector
     * at each quadrature point.
     */
    WorldVector<double>* gradAtQPs;

798
    /// True, if \ref f provides always a symmetric WorldMatrix<double>.
799
800
801
802
803
804
805
806
807
808
809
810
811
812
    bool symmetric;
  };

  /**
   * \ingroup Assembler
   *
   * \brief
   * Laplace multiplied with a function which maps the gradient of a DOFVector
   * at each quadrature point to a double:
   * \f$ f(\nabla v(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class FctGradient_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
813
814
815
    /// Constructor.
    FctGradient_SOT(DOFVectorBase<double> *dv,  
		    AbstractFunction<double, WorldVector<double> > *af);
816

817
    /// Implementation of \ref OperatorTerm::initElement().
818
819
820
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

821
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
822
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
823

824
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
825
826
    void eval(int nPoints,
	      const double *uhAtQP,
827
828
829
830
831
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

832
    /// Implenetation of SecondOrderTerm::weakEval().
833
834
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
835
836
837
838

  protected:
    DOFVectorBase<double>* vec;

839
    /// Function wich maps \ref gradAtQPs to a double.
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
    AbstractFunction<double, WorldVector<double> > *f;

    /** \brief
     * Pointer to a WorldVector<double> array containing the gradients of the DOFVector
     * at each quadrature point.
     */
    WorldVector<double>* gradAtQPs;
  };


  /**
   * \ingroup Assembler
   *
   * \brief
   * Laplace multiplied with a function which maps the gradient of a DOFVector
   * at each quadrature point to a double:
   * \f$ f(\nabla v(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class VecAndGradientAtQP_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
861
    /// Constructor.
862
    VecAndGradientAtQP_SOT(DOFVectorBase<double> *dv,
Thomas Witkowski's avatar
Thomas Witkowski committed
863
			   BinaryAbstractFunction<double, double, WorldVector<double> > *af);
864

865
    /// Implementation of \ref OperatorTerm::initElement().
866
867
868
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

869
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
870
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
871

872
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
873
874
    void eval(int nPoints,
	      const double *uhAtQP,
875
876
877
878
879
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

880
    /// Implenetation of SecondOrderTerm::weakEval().
881
882
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
883
884
885
886

  protected:
    DOFVectorBase<double>* vec;

887
    /// Function wich maps \ref gradAtQPs to a double.
888
889
890
891
892
893
894
895
896
897
    BinaryAbstractFunction<double, double, WorldVector<double> > *f;

    /** \brief
     * Pointer to a WorldVector<double> array containing the gradients of the DOFVector
     * at each quadrature point.
     */
    double* vecAtQPs;
    WorldVector<double>* gradAtQPs;
  };

898
899
900
901
902
903
904
905
906
907
908
  /**
   * \ingroup Assembler
   *
   * \brief
   * Laplace multiplied with a function which maps the gradient of a DOFVector
   * at each quadrature point to a double:
   * \f$ \nabla \cdot A(v(\vec{x}), \nabla v(\vec{x})) \nabla u(\vec{x}) \f$
   */
  class VecMatrixGradientAtQP_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
909
    /// Constructor.
910
    VecMatrixGradientAtQP_SOT(DOFVectorBase<double> *dv,
Thomas Witkowski's avatar
Thomas Witkowski committed
911
912
913
			      BinaryAbstractFunction<WorldMatrix<double>, double, WorldVector<double> > *af,
			      AbstractFunction<WorldVector<double>, WorldMatrix<double> > *divAf,
			      bool symm = false);
914

915
    /// Implementation of \ref OperatorTerm::initElement().
916
917
918
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

919
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
920
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
921

922
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
923
924
    void eval(int nPoints,
	      const double *uhAtQP,
925
926
927
928
929
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

930
    /// Implenetation of SecondOrderTerm::weakEval().
931
932
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
Thomas Witkowski's avatar
Thomas Witkowski committed
933
    
934
935
  protected:
    DOFVectorBase<double>* vec;
Thomas Witkowski's avatar
Thomas Witkowski committed
936
    
937
    /// Function wich maps \ref gradAtQPs to a double.
938
939
    BinaryAbstractFunction<WorldMatrix<double>, 
			   double, WorldVector<double> > *f;
Thomas Witkowski's avatar
Thomas Witkowski committed
940
941
942
943
944
945
946
947
948
949
950
951
    
    AbstractFunction<WorldVector<double>, WorldMatrix<double> > *divFct;
    
    /** \brief
     * Pointer to a WorldVector<double> array containing the gradients of the DOFVector
     * at each quadrature point.
     */
    double* vecAtQPs;
    WorldVector<double>* gradAtQPs;
    
    bool symmetric;
  };
952
953
954
955
956
957
958
959
960
961
962
963

  /**
   * \ingroup Assembler
   *
   * \brief
   * Laplace multiplied with a function which maps the gradient of a DOFVector
   * at each quadrature point to a double:
   * \f$ f(\nabla v(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class VecGradCoordsAtQP_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
964
    /// Constructor.
965
966
    VecGradCoordsAtQP_SOT(DOFVectorBase<double> *dv,
			  TertiaryAbstractFunction<double, double,
Thomas Witkowski's avatar
Thomas Witkowski committed
967
			  WorldVector<double>, WorldVector<double> > *af);
968

969
    /// Implementation of \ref OperatorTerm::initElement().
970
971
972
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

973
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
974
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
975

976
    /// Implenetation of SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
977
978
    void eval(int nPoints,
	      const double *uhAtQP,
979
980
981
982
983
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

984
    /// Implenetation of SecondOrderTerm::weakEval().
985
986
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
987
988
989
990

  protected:
    DOFVectorBase<double>* vec;

991
    /// Function wich maps \ref gradAtQPs to a double.
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
    TertiaryAbstractFunction<double, double, WorldVector<double>,
			     WorldVector<double> > *f;

    /** \brief
     * Pointer to a WorldVector<double> array containing the gradients of the DOFVector
     * at each quadrature point.
     */
    double* vecAtQPs;
    WorldVector<double>* gradAtQPs;
    WorldVector<double>* coordsAtQPs;
  
  };


  /**
   * \ingroup Assembler
   *  
   * \brief
   * Laplace operator multiplied with a function evaluated at the quadrature
   * points of a given DOFVector:
   * \f$ -f(v(\vec{x})) \Delta u(\vec{x}) \f$
   */
  class VecAndCoordsAtQP_SOT : public SecondOrderTerm {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
1016
    /// Constructor.
1017
    VecAndCoordsAtQP_SOT(DOFVectorBase<double> *dv, 
Thomas Witkowski's avatar
Thomas Witkowski committed
1018
			 BinaryAbstractFunction<double, double, WorldVector<double> > *af);
1019

1020
    /// Implementation of \ref OperatorTerm::initElement().
1021
1022
1023
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

1024
    /// Implements SecondOrderTerm::eval().
Thomas Witkowski's avatar
Thomas Witkowski committed
1025
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;    
1026

Thomas Witkowski's avatar
Thomas Witkowski committed
1027
1028
    void eval(int nPoints,
	      const double *uhAtQP,
1029
1030
1031
1032
1033
	      const WorldVector<double> *grdUhAtQP,
	      const WorldMatrix<double> *D2UhAtQP,
	      double *result,
	      double factor) const;

1034
1035
    void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP,
		  std::vector<WorldVector<double> > &result) const;
1036
1037

  protected:
1038
    /// DOFVector to be evaluated at quadrature points.
1039
1040
    DOFVectorBase<double>* vec;

1041
    /// Pointer to an array containing the DOFVector evaluated at quadrature points.
1042
1043
1044
1045
    double* vecAtQPs;
  
    WorldVector<double>* coordsAtQPs;

1046
    /// Function evaluated at \ref vecAtQPs.
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
    BinaryAbstractFunction<double, double,  WorldVector<double> > *f;
  };

  /**
   * \ingroup Assembler
   *
   * \brief
   * SecondOrderTerm where A is a function which maps the gradient of a 
   * DOFVector at each quadrature point to WorldMatrix<double>:
   * \f$ \nabla \cdot A(\nabla v(\vec{x})) \nabla u(\vec{x})\f$
   */
  class MatrixGradientAndCoords_SOT : public SecondOrderTerm
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
1061
    /// Constructor.
1062
1063
1064
    MatrixGradientAndCoords_SOT(DOFVectorBase<double> *dv,
				BinaryAbstractFunction<WorldMatrix<double>,
				WorldVector<double> , 
Thomas Witkowski's avatar
Thomas Witkowski committed
1065
				WorldVector<double> > *af,
1066
				AbstractFunction<WorldVector<double>,
Thomas Witkowski's avatar
Thomas Witkowski committed
1067
1068
				WorldMatrix<double> > *divAf,
				bool symm = false);
1069

1070
    /// Implementation of \ref OperatorTerm::initElement().
1071
1072
1073
    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
		     Quadrature *quad = NULL);

1074
    /// Implements SecondOrderTerm::getLALt().
Thomas Witkowski's avatar
Thomas Witkowski committed
1075
    void getLALt(const ElInfo *elInfo, int nPoints, DimMat<double> **LALt) const;
1076