#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_overall_max_threads()); grdTmpVec2.resize(omp_get_overall_max_threads()); for (int i = 0; i < omp_get_overall_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]; } }