-
Thomas Witkowski authored
* ::std:: -> std::
Thomas Witkowski authored* ::std:: -> std::
BasisFunction.cc 4.26 KiB
#include <algorithm>
#include "FixVec.h"
#include "DOFVector.h"
#include "BasisFunction.h"
#include "Lagrange.h"
#include "OpenMP.h"
namespace AMDiS {
/****************************************************************************/
/* Lagrangian basisfunctions of order 0-4; these */
/* functions are evaluated in barycentric coordinates; the derivatives */
/* are those corresponding to these barycentric coordinates. */
/****************************************************************************/
BasisFunction::BasisFunction(const std::string& name_, int dim_, int degree_)
: name(name_),
degree(degree_),
dim(dim_)
{
FUNCNAME("BasisFunction::BasisFunction()");
nDOF = NEW DimVec<int>(dim, DEFAULT_VALUE, -1);
dow = Global::getGeo(WORLD);
grdTmpVec1.resize(omp_get_max_threads());
grdTmpVec2.resize(omp_get_max_threads());
for (int i = 0; i < omp_get_max_threads(); i++) {
grdTmpVec1[i] = NEW DimVec<double>(dim, DEFAULT_VALUE, 0.0);
grdTmpVec2[i] = NEW DimVec<double>(dim, DEFAULT_VALUE, 0.0);
}
};
BasisFunction::~BasisFunction()
{
DELETE nDOF;
for (int i = 0; i < static_cast<int>(grdTmpVec1.size()); i++) {
DELETE grdTmpVec1[i];
DELETE grdTmpVec2[i];
}
}
/****************************************************************************/
/* some routines for evaluation of a finite element function, its gradient */
/* and second derivatives; all those with _fast use the preevaluated */
/* basis functions at that point. */
/****************************************************************************/
double BasisFunction::evalUh(const DimVec<double>& lambda,
const double *uh_loc) const
{
double val = 0.0;
for (int i = 0; i < nBasFcts; i++)
val += uh_loc[i] * (*(*phi)[i])(lambda);
return(val);
}
const WorldVector<double>& BasisFunction::evalUh(const DimVec<double>& lambda,
const WorldVector<double> *uh_loc,
WorldVector<double>* values) const
{
static WorldVector<double> Values(DEFAULT_VALUE, 0.0);
WorldVector<double> *val = (NULL != values) ? values : &Values;
for (int n = 0; n < dow; n++)
(*val)[n] = 0;
for (int i = 0; i < nBasFcts; i++) {
double phil = (*(*phi)[i])(lambda);
for (int n = 0; n < dow; n++)
(*val)[n] += uh_loc[i][n] * phil;
}
return((*val));
}
const WorldVector<double>& BasisFunction::evalGrdUh(const DimVec<double>& lambda,
const DimVec<WorldVector<double> >& grd_lambda,
const double *uh_loc,
WorldVector<double>* val) const
{
TEST_EXIT_DBG(val)("return value is NULL\n");
int myRank = omp_get_thread_num();
DimVec<double> *grdTmp1 = grdTmpVec1[myRank];
DimVec<double> *grdTmp2 = grdTmpVec2[myRank];
for (int j = 0; j < dim + 1; j++)
(*grdTmp2)[j] = 0.0;
for (int i = 0; i < nBasFcts; i++) {
(*(*grdPhi)[i])(lambda, *grdTmp1);
for (int j = 0; j < dim + 1; j++)
(*grdTmp2)[j] += uh_loc[i] * (*grdTmp1)[j];
}
for (int i = 0; i < dow; i++) {
(*val)[i] = 0.0;
for (int j = 0; j < dim + 1; j++)
(*val)[i] += grd_lambda[j][i] * (*grdTmp2)[j];
}
return ((*val));
}
const WorldMatrix<double>& BasisFunction::evalD2Uh(const DimVec<double>& lambda,
const DimVec<WorldVector<double> >& grd_lambda,
const double *uh_loc, WorldMatrix<double>* D2_uh) const
{
static WorldMatrix<double> D2(DEFAULT_VALUE, 0.0);
DimMat<double> D2_b(dim, DEFAULT_VALUE, 0.0);
DimMat<double> D2_tmp(dim, DEFAULT_VALUE, 0.0);
WorldMatrix<double> *val = D2_uh ? D2_uh : &D2;
for (int i = 0; i < nBasFcts; i++) {
(*(*d2Phi)[i])(lambda, D2_b);
for (int k = 0; k < dim + 1; k++)
for (int l = 0; l < dim + 1; l++)
D2_tmp[k][l] += uh_loc[i] * D2_b[k][l];
}
for (int i = 0; i < dow; i++)
for (int j = 0; j < dow; j++) {
(*val)[i][j] = 0.0;
for (int k = 0; k < dim + 1; k++)
for (int l = 0; l < dim + 1; l++)
(*val)[i][j] += grd_lambda[k][i] * grd_lambda[l][j] * D2_tmp[k][l];
}
return ((*val));
}
int BasisFunction::getNumberOfDOFs(int i) const
{
return (*nDOF)[i];
}
}