Assembler.cc 12.3 KB
Newer Older
1
2
3
#include <vector>
#include <algorithm>
#include <boost/numeric/mtl/mtl.hpp>
4
5
6
7
8
#include "Assembler.h"
#include "Operator.h"
#include "Element.h"
#include "QPsiPhi.h"
#include "DOFVector.h"
9
#include "OpenMP.h"
10
11
12

namespace AMDiS {

Thomas Witkowski's avatar
Thomas Witkowski committed
13
14
15
  Assembler::Assembler(Operator *op,
		       const FiniteElemSpace *row,
		       const FiniteElemSpace *col) 
16
    : operat(op),
Thomas Witkowski's avatar
Thomas Witkowski committed
17
18
      rowFESpace(row),
      colFESpace(col ? col : row),
19
20
21
22
23
      nRow(rowFESpace->getBasisFcts()->getNumber()),
      nCol(colFESpace->getBasisFcts()->getNumber()),
      remember(true),
      rememberElMat(false),
      rememberElVec(false),
24
25
      elementMatrix(nRow, nCol),
      elementVector(nRow),
26
      tmpMat(nRow, nCol),
27
28
29
      lastMatEl(NULL),
      lastVecEl(NULL),
      lastTraverseId(-1)
30
  {}
Thomas Witkowski's avatar
Thomas Witkowski committed
31

32

Thomas Witkowski's avatar
Thomas Witkowski committed
33
  Assembler::~Assembler()
34
  {}
35

36

37
  void Assembler::calculateElementMatrix(const ElInfo *elInfo, 
38
					 ElementMatrix& userMat,
39
40
41
42
					 double factor)
  {
    FUNCNAME("Assembler::calculateElementMatrix()");

43
    if (remember && (factor != 1.0 || operat->uhOld))
44
      rememberElMat = true;
Thomas Witkowski's avatar
Thomas Witkowski committed
45

46
    Element *el = elInfo->getElement();
Thomas Witkowski's avatar
Thomas Witkowski committed
47

48
    if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
49
50
51
      initElement(elInfo);

    if (el != lastMatEl || !operat->isOptimized()) {
52
53
54
      if (rememberElMat)
	set_to_zero(elementMatrix);

55
56
57
      lastMatEl = el;
    } else {
      if (rememberElMat) {
58
	userMat += factor * elementMatrix;
59
60
61
	return;
      }
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
62
 
63
    ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
64
65
66
67
68
69
70
71
72
73

    if (secondOrderAssembler)
      secondOrderAssembler->calculateElementMatrix(elInfo, mat);
    if (firstOrderAssemblerGrdPsi)
      firstOrderAssemblerGrdPsi->calculateElementMatrix(elInfo, mat);
    if (firstOrderAssemblerGrdPhi)
      firstOrderAssemblerGrdPhi->calculateElementMatrix(elInfo, mat);
    if (zeroOrderAssembler)
      zeroOrderAssembler->calculateElementMatrix(elInfo, mat);

Thomas Witkowski's avatar
Thomas Witkowski committed
74
    if (rememberElMat && &userMat != &elementMatrix)
75
      userMat += factor * elementMatrix;
76
77
  }

78

79
80
  void Assembler::calculateElementMatrix(const ElInfo *rowElInfo,
					 const ElInfo *colElInfo,
81
82
					 const ElInfo *smallElInfo,
					 const ElInfo *largeElInfo,
83
					 ElementMatrix& userMat,
84
85
86
87
					 double factor)
  {
    FUNCNAME("Assembler::calculateElementMatrix()");

88
    if (remember && (factor != 1.0 || operat->uhOld))
89
90
      rememberElMat = true;
  
Thomas Witkowski's avatar
Thomas Witkowski committed
91
    Element *el = smallElInfo->getElement();   
92
    lastVecEl = lastMatEl = NULL;
Thomas Witkowski's avatar
Thomas Witkowski committed
93
   
94
    if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
Thomas Witkowski's avatar
Thomas Witkowski committed
95
      initElement(smallElInfo, largeElInfo);
96
97

    if (el != lastMatEl || !operat->isOptimized()) {
98
99
100
      if (rememberElMat)
	set_to_zero(elementMatrix);

101
102
103
      lastMatEl = el;
    } else {
      if (rememberElMat) {
104
	userMat += factor * elementMatrix;
105
106
107
	return;
      }
    }
108
 
109
    ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
110

111
    if (secondOrderAssembler) {
112
      ERROR_EXIT("Da muss i noch ma testen!\n");
113
      secondOrderAssembler->calculateElementMatrix(smallElInfo, mat);
114

115
      ElementMatrix &m =       
116
	smallElInfo->getSubElemGradCoordsMat(rowFESpace->getBasisFcts()->getDegree());
117

118
      tmpMat = m * mat;
119
      mat = tmpMat;      
120
121
122
    }

    if (firstOrderAssemblerGrdPsi) {
123
124
      //      std::cout << "PSI!" << std::endl;

125
126
      firstOrderAssemblerGrdPsi->calculateElementMatrix(smallElInfo, mat);

127
      if (largeElInfo == rowElInfo) {
128
129
	ElementMatrix &m = 
	  smallElInfo->getSubElemGradCoordsMat(rowFESpace->getBasisFcts()->getDegree());
130

131
132
	tmpMat = m * mat;
      } else {
133
134
135
136
137
	ElementMatrix &m = 
	  smallElInfo->getSubElemCoordsMat(rowFESpace->getBasisFcts()->getDegree());
	
	tmpMat = mat * trans(m);
      }
138
139
	
      mat = tmpMat;
140
141
142
    }

    if (firstOrderAssemblerGrdPhi) {
143
      firstOrderAssemblerGrdPhi->calculateElementMatrix(smallElInfo, mat);
144

145
      if (largeElInfo == colElInfo) {
146
147
148
149
150
151
152
153
154
155
156
157
	ElementMatrix &m = 
	  smallElInfo->getSubElemGradCoordsMat(rowFESpace->getBasisFcts()->getDegree());

	tmpMat = mat * trans(m);
      } else {
	ElementMatrix &m = 
	  smallElInfo->getSubElemCoordsMat(rowFESpace->getBasisFcts()->getDegree());
	
	tmpMat = m * mat;	
      }

      mat = tmpMat;
158
    }
159

160
161
    if (zeroOrderAssembler) {
      zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat);
Thomas Witkowski's avatar
Thomas Witkowski committed
162
      
163
164
      ElementMatrix &m = 
	smallElInfo->getSubElemCoordsMat(rowFESpace->getBasisFcts()->getDegree());
Thomas Witkowski's avatar
Thomas Witkowski committed
165
      
Thomas Witkowski's avatar
Thomas Witkowski committed
166
      if (smallElInfo == colElInfo)
167
168
	tmpMat = m * mat;	
      else
Thomas Witkowski's avatar
Thomas Witkowski committed
169
170
171
  	tmpMat = mat * trans(m);
      
      mat = tmpMat;
172
    }
173

174
175
    if (rememberElMat && &userMat != &elementMatrix)
      userMat += factor * elementMatrix;   
176
177
  }

178

179
  void Assembler::calculateElementVector(const ElInfo *elInfo, 
180
					 ElementVector& userVec,
181
182
183
184
					 double factor)
  {
    FUNCNAME("Assembler::calculateElementVector()");

185
    if (remember && factor != 1.0)
186
187
188
189
      rememberElVec = true;

    Element *el = elInfo->getElement();

190
    if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
191
      initElement(elInfo);
192
    
Thomas Witkowski's avatar
Thomas Witkowski committed
193
    if (el != lastVecEl || !operat->isOptimized()) {
194
195
196
      if (rememberElVec)
	set_to_zero(elementVector);
	
197
198
      lastVecEl = el;
    } else {
Thomas Witkowski's avatar
Thomas Witkowski committed
199
      if (rememberElVec) {
200
	userVec += factor * elementVector;
201
202
203
	return;
      }
    }
204
205

    ElementVector& vec = rememberElVec ? elementVector : userVec;
Thomas Witkowski's avatar
Thomas Witkowski committed
206
    if (operat->uhOld && remember) {
207
      matVecAssemble(elInfo, vec);
208
      if (rememberElVec)
209
	userVec += factor * elementVector;      
210

211
212
      return;
    } 
213
214

    if (firstOrderAssemblerGrdPsi)
215
      firstOrderAssemblerGrdPsi->calculateElementVector(elInfo, vec);
216
    if (zeroOrderAssembler)
217
      zeroOrderAssembler->calculateElementVector(elInfo, vec);
218
      
219
    if (rememberElVec)
220
      userVec += factor * elementVector;    
221
222
  }

223

Thomas Witkowski's avatar
Thomas Witkowski committed
224
225
226
227
  void Assembler::calculateElementVector(const ElInfo *mainElInfo, 
					 const ElInfo *auxElInfo,
					 const ElInfo *smallElInfo,
					 const ElInfo *largeElInfo,
228
					 ElementVector& userVec, 
Thomas Witkowski's avatar
Thomas Witkowski committed
229
230
231
232
					 double factor)
  {
    FUNCNAME("Assembler::calculateElementVector()");

233
    if (remember && factor != 1.0)
Thomas Witkowski's avatar
Thomas Witkowski committed
234
235
236
237
      rememberElVec = true;

    Element *el = mainElInfo->getElement();

238
    if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
239
240
      initElement(smallElInfo, largeElInfo);
   
Thomas Witkowski's avatar
Thomas Witkowski committed
241
    if (el != lastVecEl || !operat->isOptimized()) {
242
243
244
      if (rememberElVec)
	set_to_zero(elementVector);

Thomas Witkowski's avatar
Thomas Witkowski committed
245
246
247
      lastVecEl = el;
    } else {
      if (rememberElVec) {
248
	userVec += factor * elementVector;
Thomas Witkowski's avatar
Thomas Witkowski committed
249
250
251
	return;
      }
    }
252
    ElementVector& vec = rememberElVec ? elementVector : userVec;
Thomas Witkowski's avatar
Thomas Witkowski committed
253
254

    if (operat->uhOld && remember) {
255
      if (smallElInfo->getLevel() == largeElInfo->getLevel())
Thomas Witkowski's avatar
Thomas Witkowski committed
256
	matVecAssemble(auxElInfo, vec);
257
258
      else
	matVecAssemble(mainElInfo, auxElInfo, smallElInfo, largeElInfo, vec);      
Thomas Witkowski's avatar
Thomas Witkowski committed
259

260
      if (rememberElVec)
261
	userVec += factor * elementVector;      
262

Thomas Witkowski's avatar
Thomas Witkowski committed
263
264
265
266
267
      return;
    } 

    ERROR_EXIT("Not yet implemented!\n");

268
269
270
271
272
273
274
275
#if 0
    if (firstOrderAssemblerGrdPsi)
      firstOrderAssemblerGrdPsi->calculateElementVector(elInfo, vec);    
    if (zeroOrderAssembler)
      zeroOrderAssembler->calculateElementVector(elInfo, vec);    
    if (rememberElVec)
      axpy(factor, *elementVector, *userVec);
#endif
Thomas Witkowski's avatar
Thomas Witkowski committed
276
277
  }

278

279
  void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector& vec)
280
281
282
  {
    FUNCNAME("Assembler::matVecAssemble()");

283
    Element *el = elInfo->getElement(); 
284
    double *uhOldLoc = new double[nRow];
285

286
    operat->uhOld->getLocalVector(el, uhOldLoc);
287
    
288
    if (el != lastMatEl) {
289
      set_to_zero(elementMatrix);
290
      calculateElementMatrix(elInfo, elementMatrix);
291
292
    }

293
    for (int i = 0; i < nRow; i++) {
294
      double val = 0.0;
295
      for (int j = 0; j < nRow; j++)
296
	val += elementMatrix[i][j] * uhOldLoc[j];
297
      
298
      vec[i] += val;
299
    }   
300

Thomas Witkowski's avatar
Thomas Witkowski committed
301
302
303
    delete [] uhOldLoc;
  }

304

Thomas Witkowski's avatar
Thomas Witkowski committed
305
306
  void Assembler::matVecAssemble(const ElInfo *mainElInfo, const ElInfo *auxElInfo,
				 const ElInfo *smallElInfo, const ElInfo *largeElInfo,
307
				 ElementVector& vec)
Thomas Witkowski's avatar
Thomas Witkowski committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  {
    FUNCNAME("Assembler::matVecAssemble()");

    TEST_EXIT(rowFESpace->getBasisFcts() == colFESpace->getBasisFcts())
      ("Works only for equal basis functions for different components!\n");

    TEST_EXIT(operat->uhOld->getFESpace()->getMesh() == auxElInfo->getMesh())
      ("Da stimmt was nicht!\n");

    Element *mainEl = mainElInfo->getElement(); 
    Element *auxEl = auxElInfo->getElement();

    const BasisFunction *basFcts = rowFESpace->getBasisFcts();
    int nBasFcts = basFcts->getNumber();
322
    std::vector<double> uhOldLoc(nBasFcts);
Thomas Witkowski's avatar
Thomas Witkowski committed
323

324
    operat->uhOld->getLocalVector(auxEl, &(uhOldLoc[0]));
Thomas Witkowski's avatar
Thomas Witkowski committed
325
326

    if (mainEl != lastMatEl) {
327
      set_to_zero(elementMatrix);
328
      calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo, 
329
 			     elementMatrix);    
Thomas Witkowski's avatar
Thomas Witkowski committed
330
    }
331

Thomas Witkowski's avatar
Thomas Witkowski committed
332
333
    for (int i = 0; i < nBasFcts; i++) {
      double val = 0.0;
334
      for (int j = 0; j < nBasFcts; j++)
335
 	val += elementMatrix[i][j] * uhOldLoc[j];
336
      vec[i] += val;
337
    }   
338
339
  }

340

Thomas Witkowski's avatar
Thomas Witkowski committed
341
342
343
  void Assembler::initElement(const ElInfo *smallElInfo, 
			      const ElInfo *largeElInfo,
			      Quadrature *quad)
344
  {
Thomas Witkowski's avatar
Thomas Witkowski committed
345
    if (secondOrderAssembler) 
Thomas Witkowski's avatar
Thomas Witkowski committed
346
      secondOrderAssembler->initElement(smallElInfo, largeElInfo, quad);
Thomas Witkowski's avatar
Thomas Witkowski committed
347
    if (firstOrderAssemblerGrdPsi)
Thomas Witkowski's avatar
Thomas Witkowski committed
348
      firstOrderAssemblerGrdPsi->initElement(smallElInfo, largeElInfo, quad);
Thomas Witkowski's avatar
Thomas Witkowski committed
349
    if (firstOrderAssemblerGrdPhi)
Thomas Witkowski's avatar
Thomas Witkowski committed
350
      firstOrderAssemblerGrdPhi->initElement(smallElInfo, largeElInfo, quad);
Thomas Witkowski's avatar
Thomas Witkowski committed
351
    if (zeroOrderAssembler)
Thomas Witkowski's avatar
Thomas Witkowski committed
352
      zeroOrderAssembler->initElement(smallElInfo, largeElInfo, quad);
353
354
  }

355

356
  void Assembler::checkQuadratures()
Thomas Witkowski's avatar
Thomas Witkowski committed
357
358
  { 
    if (secondOrderAssembler) {
359
      // create quadrature
Thomas Witkowski's avatar
Thomas Witkowski committed
360
361
      if (!secondOrderAssembler->getQuadrature()) {
	int dim = rowFESpace->getMesh()->getDim();
362
363
364
365
366
	int degree = operat->getQuadratureDegree(2);
	Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
	secondOrderAssembler->setQuadrature(quadrature);
      }
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
367
    if (firstOrderAssemblerGrdPsi) {
368
      // create quadrature
Thomas Witkowski's avatar
Thomas Witkowski committed
369
370
      if (!firstOrderAssemblerGrdPsi->getQuadrature()) {
	int dim = rowFESpace->getMesh()->getDim();
371
372
373
374
375
	int degree = operat->getQuadratureDegree(1, GRD_PSI);
	Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
	firstOrderAssemblerGrdPsi->setQuadrature(quadrature);
      }
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
376
    if (firstOrderAssemblerGrdPhi) {
377
      // create quadrature
Thomas Witkowski's avatar
Thomas Witkowski committed
378
379
      if (!firstOrderAssemblerGrdPhi->getQuadrature()) {
	int dim = rowFESpace->getMesh()->getDim();
380
381
382
383
384
	int degree = operat->getQuadratureDegree(1, GRD_PHI);
	Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
	firstOrderAssemblerGrdPhi->setQuadrature(quadrature);
      }
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
385
    if (zeroOrderAssembler) {
386
      // create quadrature
Thomas Witkowski's avatar
Thomas Witkowski committed
387
388
      if (!zeroOrderAssembler->getQuadrature()) {
	int dim = rowFESpace->getMesh()->getDim();
389
390
391
392
393
394
395
	int degree = operat->getQuadratureDegree(0);
	Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
	zeroOrderAssembler->setQuadrature(quadrature);
      }
    }
  }

396

Thomas Witkowski's avatar
Thomas Witkowski committed
397
398
399
400
401
  void Assembler::finishAssembling()
  {
    lastVecEl = NULL;
    lastMatEl = NULL;
  }
Thomas Witkowski's avatar
Thomas Witkowski committed
402

403

Thomas Witkowski's avatar
Thomas Witkowski committed
404
405
406
407
408
  OptimizedAssembler::OptimizedAssembler(Operator  *op,
					 Quadrature *quad2,
					 Quadrature *quad1GrdPsi,
					 Quadrature *quad1GrdPhi,
					 Quadrature *quad0,
409
410
411
					 const FiniteElemSpace *rowFeSpace,
					 const FiniteElemSpace *colFeSpace) 
    : Assembler(op, rowFeSpace, colFeSpace)
Thomas Witkowski's avatar
Thomas Witkowski committed
412
  {
413
    bool opt = (rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts());
Thomas Witkowski's avatar
Thomas Witkowski committed
414
415
416
417
418
419
420
421
422
423
424
425
426
427

    // create sub assemblers
    secondOrderAssembler = 
      SecondOrderAssembler::getSubAssembler(op, this, quad2, opt);
    firstOrderAssemblerGrdPsi = 
      FirstOrderAssembler::getSubAssembler(op, this, quad1GrdPsi, GRD_PSI, opt);
    firstOrderAssemblerGrdPhi = 
      FirstOrderAssembler::getSubAssembler(op, this, quad1GrdPhi, GRD_PHI, opt);
    zeroOrderAssembler = 
      ZeroOrderAssembler::getSubAssembler(op, this, quad0, opt);

    checkQuadratures();
  }

428

Thomas Witkowski's avatar
Thomas Witkowski committed
429
430
431
432
433
  StandardAssembler::StandardAssembler(Operator *op,
				       Quadrature *quad2,
				       Quadrature *quad1GrdPsi,
				       Quadrature *quad1GrdPhi,
				       Quadrature *quad0,
434
435
436
				       const FiniteElemSpace *rowFeSpace,
				       const FiniteElemSpace *colFeSpace) 
    : Assembler(op, rowFeSpace, colFeSpace)
Thomas Witkowski's avatar
Thomas Witkowski committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  {
    remember = false;

    // create sub assemblers
    secondOrderAssembler = 
      SecondOrderAssembler::getSubAssembler(op, this, quad2, false);
    firstOrderAssemblerGrdPsi = 
      FirstOrderAssembler::getSubAssembler(op, this, quad1GrdPsi, GRD_PSI, false);
    firstOrderAssemblerGrdPhi = 
      FirstOrderAssembler::getSubAssembler(op, this, quad1GrdPhi, GRD_PHI, false);
    zeroOrderAssembler = 
      ZeroOrderAssembler::getSubAssembler(op, this, quad0, false);

    checkQuadratures();
  }

453
}