-
Thomas Witkowski authoredThomas Witkowski authored
Assembler.cc 10.52 KiB
#include "Assembler.h"
#include "Operator.h"
#include "Element.h"
#include "QPsiPhi.h"
#include "ElementMatrix.h"
#include "ElementVector.h"
#include "DOFVector.h"
#include "OpenMP.h"
#include <vector>
#include <algorithm>
namespace AMDiS {
Assembler::Assembler(Operator *op,
const FiniteElemSpace *rowFESpace_,
const FiniteElemSpace *colFESpace_)
: operat(op),
rowFESpace(rowFESpace_),
colFESpace(colFESpace_ ? colFESpace_ : rowFESpace_),
nRow(rowFESpace->getBasisFcts()->getNumber()),
nCol(colFESpace->getBasisFcts()->getNumber()),
remember(true),
rememberElMat(false),
rememberElVec(false),
elementMatrix(NULL),
elementVector(NULL),
lastMatEl(NULL),
lastVecEl(NULL),
lastTraverseId(-1)
{}
void Assembler::calculateElementMatrix(const ElInfo *elInfo,
ElementMatrix *userMat,
double factor)
{
FUNCNAME("Assembler::calculateElementMatrix()");
if (remember && ((factor != 1.0) || (operat->uhOld))) {
rememberElMat = true;
}
if (rememberElMat && !elementMatrix)
elementMatrix = NEW ElementMatrix(nRow, nCol);
Element *el = elInfo->getElement();
checkForNewTraverse();
checkQuadratures();
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) {
initElement(elInfo);
}
if (el != lastMatEl || !operat->isOptimized()) {
if (rememberElMat) {
elementMatrix->set(0.0);
}
lastMatEl = el;
} else {
if (rememberElMat) {
axpy(factor, *elementMatrix, *userMat);
return;
}
}
ElementMatrix *mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler)
secondOrderAssembler->calculateElementMatrix(elInfo, mat);
if (firstOrderAssemblerGrdPsi)
firstOrderAssemblerGrdPsi->calculateElementMatrix(elInfo, mat);
if (firstOrderAssemblerGrdPhi)
firstOrderAssemblerGrdPhi->calculateElementMatrix(elInfo, mat);
if (zeroOrderAssembler)
zeroOrderAssembler->calculateElementMatrix(elInfo, mat);
if (rememberElMat && userMat) {
axpy(factor, *elementMatrix, *userMat);
}
}
void Assembler::calculateElementMatrix(const ElInfo *rowElInfo,
const ElInfo *colElInfo,
const ElInfo *smallElInfo,
const ElInfo *largeElInfo,
ElementMatrix *userMat,
double factor)
{
FUNCNAME("Assembler::calculateElementMatrix()");
if (remember && ((factor != 1.0) || (operat->uhOld))) {
rememberElMat = true;
}
if (rememberElMat && !elementMatrix)
elementMatrix = NEW ElementMatrix(nRow, nCol);
Element *el = rowElInfo->getElement();
// checkForNewTraverse();
lastVecEl = lastMatEl = NULL;
checkQuadratures();
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) {
initElement(rowElInfo);
}
if (el != lastMatEl || !operat->isOptimized()) {
if (rememberElMat) {
elementMatrix->set(0.0);
}
lastMatEl = el;
} else {
if (rememberElMat) {
axpy(factor, *elementMatrix, *userMat);
return;
}
}
ElementMatrix *mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler) {
secondOrderAssembler->calculateElementMatrix(rowElInfo, colElInfo,
smallElInfo, largeElInfo, mat);
}
if (firstOrderAssemblerGrdPsi) {
firstOrderAssemblerGrdPsi->calculateElementMatrix(rowElInfo, colElInfo,
smallElInfo, largeElInfo, mat);
}
if (firstOrderAssemblerGrdPhi) {
firstOrderAssemblerGrdPhi->calculateElementMatrix(rowElInfo, colElInfo,
smallElInfo, largeElInfo, mat);
}
if (zeroOrderAssembler) {
zeroOrderAssembler->calculateElementMatrix(rowElInfo, colElInfo,
smallElInfo, largeElInfo, mat);
}
if (rememberElMat && userMat) {
axpy(factor, *elementMatrix, *userMat);
}
}
void Assembler::calculateElementVector(const ElInfo *elInfo,
ElementVector *userVec,
double factor)
{
FUNCNAME("Assembler::calculateElementVector()");
if (remember && factor != 1.0) {
rememberElVec = true;
}
if (rememberElVec && !elementVector) {
elementVector = NEW ElementVector(nRow);
}
Element *el = elInfo->getElement();
checkForNewTraverse();
checkQuadratures();
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) {
initElement(elInfo);
}
if (el != lastVecEl || !operat->isOptimized()) {
if (rememberElVec) {
elementVector->set(0.0);
}
lastVecEl = el;
} else {
if (rememberElVec) {
axpy(factor, *elementVector, *userVec);
return;
}
}
ElementVector *vec = rememberElVec ? elementVector : userVec;
if (operat->uhOld && remember) {
matVecAssemble(elInfo, vec);
if (rememberElVec) {
axpy(factor, *elementVector, *userVec);
}
return;
}
if (firstOrderAssemblerGrdPsi) {
firstOrderAssemblerGrdPsi->calculateElementVector(elInfo, vec);
}
if (zeroOrderAssembler) {
zeroOrderAssembler->calculateElementVector(elInfo, vec);
}
if (rememberElVec) {
axpy(factor, *elementVector, *userVec);
}
}
void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector *vec)
{
FUNCNAME("Assembler::matVecAssemble()");
Element *el = elInfo->getElement();
const BasisFunction *basFcts = rowFESpace->getBasisFcts();
int nBasFcts = basFcts->getNumber();
double *uhOldLoc = new double[nBasFcts];
operat->uhOld->getLocalVector(el, uhOldLoc);
if (el != lastMatEl) {
calculateElementMatrix(elInfo, NULL);
}
for (int i = 0; i < nBasFcts; i++) {
double val = 0.0;
for (int j = 0; j < nBasFcts; j++) {
val += (*elementMatrix)[i][j] * uhOldLoc[j];
}
(*vec)[i] += val;
}
delete [] uhOldLoc;
}
void Assembler::initElement(const ElInfo *elInfo, Quadrature *quad)
{
checkQuadratures();
if (secondOrderAssembler)
secondOrderAssembler->initElement(elInfo, quad);
if (firstOrderAssemblerGrdPsi)
firstOrderAssemblerGrdPsi->initElement(elInfo, quad);
if (firstOrderAssemblerGrdPhi)
firstOrderAssemblerGrdPhi->initElement(elInfo, quad);
if (zeroOrderAssembler)
zeroOrderAssembler->initElement(elInfo, quad);
}
OptimizedAssembler::OptimizedAssembler(Operator *op,
Quadrature *quad2,
Quadrature *quad1GrdPsi,
Quadrature *quad1GrdPhi,
Quadrature *quad0,
const FiniteElemSpace *rowFESpace_,
const FiniteElemSpace *colFESpace_)
: Assembler(op, rowFESpace_, colFESpace_)
{
bool opt = (rowFESpace_ == colFESpace_);
// 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);
}
StandardAssembler::StandardAssembler(Operator *op,
Quadrature *quad2,
Quadrature *quad1GrdPsi,
Quadrature *quad1GrdPhi,
Quadrature *quad0,
const FiniteElemSpace *rowFESpace_,
const FiniteElemSpace *colFESpace_)
: Assembler(op, rowFESpace_, colFESpace_)
{
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);
}
ElementMatrix *Assembler::initElementMatrix(ElementMatrix *elMat,
const ElInfo *rowElInfo,
const ElInfo *colElInfo)
{
if (!elMat) {
elMat = NEW ElementMatrix(nRow, nCol);
}
elMat->set(0.0);
rowFESpace->getBasisFcts()->getLocalIndicesVec(rowElInfo->getElement(),
rowFESpace->getAdmin(),
&(elMat->rowIndices));
if (rowFESpace == colFESpace) {
elMat->colIndices = elMat->rowIndices;
} else {
if (colElInfo) {
colFESpace->getBasisFcts()->getLocalIndicesVec(colElInfo->getElement(),
colFESpace->getAdmin(),
&(elMat->colIndices));
} else {
// If there is no colElInfo pointer, use rowElInfo the get the indices.
colFESpace->getBasisFcts()->getLocalIndicesVec(rowElInfo->getElement(),
colFESpace->getAdmin(),
&(elMat->colIndices));
}
}
return elMat;
}
ElementVector *Assembler::initElementVector(ElementVector *elVec,
const ElInfo *elInfo)
{
if (!elVec) {
elVec = NEW ElementVector(nRow);
}
elVec->set(0.0);
DOFAdmin *rowAdmin = rowFESpace->getAdmin();
Element *element = elInfo->getElement();
rowFESpace->getBasisFcts()->getLocalIndicesVec(element, rowAdmin, &(elVec->dofIndices));
return elVec;
}
void Assembler::checkQuadratures()
{
if (secondOrderAssembler) {
// create quadrature
if (!secondOrderAssembler->getQuadrature()) {
int dim = rowFESpace->getMesh()->getDim();
int degree = operat->getQuadratureDegree(2);
Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
secondOrderAssembler->setQuadrature(quadrature);
}
}
if (firstOrderAssemblerGrdPsi) {
// create quadrature
if (!firstOrderAssemblerGrdPsi->getQuadrature()) {
int dim = rowFESpace->getMesh()->getDim();
int degree = operat->getQuadratureDegree(1, GRD_PSI);
Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
firstOrderAssemblerGrdPsi->setQuadrature(quadrature);
}
}
if (firstOrderAssemblerGrdPhi) {
// create quadrature
if (!firstOrderAssemblerGrdPhi->getQuadrature()) {
int dim = rowFESpace->getMesh()->getDim();
int degree = operat->getQuadratureDegree(1, GRD_PHI);
Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
firstOrderAssemblerGrdPhi->setQuadrature(quadrature);
}
}
if (zeroOrderAssembler) {
// create quadrature
if (!zeroOrderAssembler->getQuadrature()) {
int dim = rowFESpace->getMesh()->getDim();
int degree = operat->getQuadratureDegree(0);
Quadrature *quadrature = Quadrature::provideQuadrature(dim, degree);
zeroOrderAssembler->setQuadrature(quadrature);
}
}
}
}