#include #include "DOFVector.h" #include "Traverse.h" #include "DualTraverse.h" #include "FixVec.h" namespace AMDiS { template<> void DOFVector::coarseRestrict(RCNeighbourList& list, int n) { FUNCNAME("DOFVector::coarseRestrict()"); switch (coarsenOperation) { case NO_OPERATION: return; break; case COARSE_RESTRICT: (const_cast(feSpace->getBasisFcts()))->coarseRestr(this, &list, n); break; case COARSE_INTERPOL: TEST_EXIT_DBG(feSpace)("Should not happen!\n"); TEST_EXIT_DBG(feSpace->getBasisFcts())("Shoud not happen!\n"); (const_cast(feSpace->getBasisFcts()))->coarseInter(this, &list, n); break; default: WARNING("Invalid coarsen operation \"%d\" in vector \"%s\"\n", coarsenOperation, this->name.c_str()); } } template<> void DOFVector::refineInterpol(RCNeighbourList& list, int n) { (const_cast(feSpace->getBasisFcts()))->refineInter(this, &list, n); } template<> void DOFVector >::refineInterpol(RCNeighbourList& list, int n) { if (n < 1) return; Element *el = list.getElement(0); int n0 = feSpace->getAdmin()->getNumberOfPreDofs(VERTEX); DegreeOfFreedom dof0 = el->getDof(0, n0); DegreeOfFreedom dof1 = el->getDof(1, n0); DegreeOfFreedom dof_new = el->getChild(0)->getDof(feSpace->getMesh()->getDim(), n0); vec[dof_new] = vec[dof0]; vec[dof_new] += vec[dof1]; vec[dof_new] *= 0.5; } template<> DOFVector >* DOFVector::getGradient(DOFVector > *grad) const { FUNCNAME("DOFVector::getGradient()"); // define result vector static DOFVector > *result = NULL; if (grad) { result = grad; } else { if(result && result->getFeSpace() != feSpace) { delete result; result = new DOFVector >(feSpace, "gradient"); } } Mesh *mesh = feSpace->getMesh(); int dim = mesh->getDim(); const BasisFunction *basFcts = feSpace->getBasisFcts(); DOFAdmin *admin = feSpace->getAdmin(); // count number of nodes and dofs per node std::vector nNodeDOFs; std::vector nNodePreDofs; std::vector*> bary; int nNodes = 0; int nDofs = 0; for (int i = 0; i < dim + 1; i++) { GeoIndex geoIndex = INDEX_OF_DIM(i, dim); int nPositions = mesh->getGeo(geoIndex); int numPreDofs = admin->getNumberOfPreDofs(i); for (int j = 0; j < nPositions; j++) { int dofs = basFcts->getNumberOfDofs(geoIndex); nNodeDOFs.push_back(dofs); nDofs += dofs; nNodePreDofs.push_back(numPreDofs); } nNodes += nPositions; } TEST_EXIT_DBG(nDofs == basFcts->getNumber()) ("number of dofs != number of basis functions\n"); for (int i = 0; i < nDofs; i++) bary.push_back(basFcts->getCoords(i)); ElementVector localUh(basFcts->getNumber()); // traverse mesh std::vector visited(getUsedSize(), false); TraverseStack stack; Flag fillFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_GRD_LAMBDA | Mesh::FILL_COORDS; ElInfo *elInfo = stack.traverseFirst(mesh, -1, fillFlag); while (elInfo) { const DegreeOfFreedom **dof = elInfo->getElement()->getDof(); const DimVec > &grdLambda = elInfo->getGrdLambda(); getLocalVector(elInfo->getElement(), localUh); int localDOFNr = 0; for (int i = 0; i < nNodes; i++) { // for all nodes for (int j = 0; j < nNodeDOFs[i]; j++) { // for all dofs at this node DegreeOfFreedom dofIndex = dof[i][nNodePreDofs[i] + j]; if (!visited[dofIndex]) { basFcts->evalGrdUh(*(bary[localDOFNr]), grdLambda, localUh, &((*result)[dofIndex])); visited[dofIndex] = true; } localDOFNr++; } } elInfo = stack.traverseNext(elInfo); } return result; } template<> DOFVector >* DOFVector::getRecoveryGradient(DOFVector > *grad) const { FUNCNAME("DOFVector::getRecoveryGradient()"); #ifdef _OPENMP ERROR_EXIT("Using static variable while using OpenMP parallelization!\n"); #endif // define result vector static DOFVector > *vec = NULL; DOFVector > *result = grad; if (!result) { if (vec && vec->getFeSpace() != feSpace) { delete vec; vec = NULL; } if (!vec) vec = new DOFVector >(feSpace, "gradient"); result = vec; } result->set(WorldVector(DEFAULT_VALUE, 0.0)); DOFVector volume(feSpace, "volume"); volume.set(0.0); const BasisFunction *basFcts = feSpace->getBasisFcts(); int nPreDofs = feSpace->getAdmin()->getNumberOfPreDofs(VERTEX); DimVec bary(dim, DEFAULT_VALUE, (1.0 / (dim + 1.0))); WorldVector grd; // traverse mesh Mesh *mesh = feSpace->getMesh(); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_DET | Mesh::FILL_GRD_LAMBDA | Mesh::FILL_COORDS); ElementVector localUh(basFcts->getNumber()); while (elInfo) { double det = elInfo->getDet(); const DegreeOfFreedom **dof = elInfo->getElement()->getDof(); const DimVec > &grdLambda = elInfo->getGrdLambda(); getLocalVector(elInfo->getElement(), localUh); basFcts->evalGrdUh(bary, grdLambda, localUh, &grd); for (int i = 0; i < dim + 1; i++) { DegreeOfFreedom dofIndex = dof[i][nPreDofs]; (*result)[dofIndex] += grd * det; volume[dofIndex] += det; } elInfo = stack.traverseNext(elInfo); } DOFVector::Iterator volIt(&volume, USED_DOFS); DOFVector >::Iterator grdIt(result, USED_DOFS); for (volIt.reset(), grdIt.reset(); !volIt.end(); ++volIt, ++grdIt) if (*volIt != 0.0) *grdIt *= 1.0 / (*volIt); return result; } template<> const WorldVector *DOFVectorBase::getGrdAtQPs(const ElInfo *elInfo, const Quadrature *quad, const FastQuadrature *quadFast, WorldVector *grdAtQPs) const { FUNCNAME("DOFVector::getGrdAtQPs()"); TEST_EXIT_DBG(quad || quadFast)("neither quad nor quadFast defined\n"); if (quad && quadFast) { TEST_EXIT_DBG(quad == quadFast->getQuadrature()) ("quad != quadFast->quadrature\n"); } TEST_EXIT_DBG(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts()) ("invalid basis functions"); int dow = Global::getGeo(WORLD); int myRank = omp_get_thread_num(); int nPoints = quadFast ? quadFast->getQuadrature()->getNumPoints() : quad->getNumPoints(); static WorldVector *grd = NULL; WorldVector *result; if (grdAtQPs) { result = grdAtQPs; } else { if (grd) delete [] grd; grd = new WorldVector[nPoints]; for (int i = 0; i < nPoints; i++) grd[i].set(0.0); result = grd; } const ElementVector& localVec = localVectors[myRank]; getLocalVector(elInfo->getElement(), const_cast(localVec)); DimVec &grd1 = *grdTmp[myRank]; int parts = Global::getGeo(PARTS, dim); const DimVec > &grdLambda = elInfo->getGrdLambda(); if (quadFast) { for (int i = 0; i < nPoints; i++) { for (int j = 0; j < dim + 1; j++) grd1[j] = 0.0; for (int j = 0; j < nBasFcts; j++) for (int k = 0; k < parts; k++) grd1[k] += quadFast->getGradient(i, j, k) * localVec[j]; for (int l=0; l < dow; l++) { result[i][l] = 0.0; for (int k = 0; k < parts; k++) result[i][l] += grdLambda[k][l] * grd1[k]; } } } else { const BasisFunction *basFcts = feSpace->getBasisFcts(); DimVec* grdPhi = grdPhis[myRank]; for (int i = 0; i < nPoints; i++) { for (int j = 0; j < dim + 1; j++) grd1[j] = 0.0; for (int j = 0; j < nBasFcts; j++) { (*(basFcts->getGrdPhi(j)))(quad->getLambda(i), *grdPhi); for (int k = 0; k < parts; k++) grd1[k] += (*grdPhi)[k] * localVec[j]; } for (int l = 0; l < dow; l++) { result[i][l] = 0.0; for (int k = 0; k < parts; k++) result[i][l] += grdLambda[k][l] * grd1[k]; } } } return const_cast*>(result); } template<> const WorldVector *DOFVectorBase::getGrdAtQPs(const ElInfo *smallElInfo, const ElInfo *largeElInfo, const Quadrature *quad, const FastQuadrature *quadFast, WorldVector *grdAtQPs) const { FUNCNAME("DOFVector::getGrdAtQPs()"); TEST_EXIT_DBG(quad || quadFast)("neither quad nor quadFast defined\n"); if (quad && quadFast) { TEST_EXIT_DBG(quad == quadFast->getQuadrature())("quad != quadFast->quadrature\n"); } TEST_EXIT_DBG(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts()) ("invalid basis functions"); int dow = Global::getGeo(WORLD); int myRank = omp_get_thread_num(); int nPoints = quadFast ? quadFast->getQuadrature()->getNumPoints() : quad->getNumPoints(); static WorldVector *grd = NULL; WorldVector *result; if (grdAtQPs) { result = grdAtQPs; } else { if (grd) delete [] grd; grd = new WorldVector[nPoints]; for (int i = 0; i < nPoints; i++) grd[i].set(0.0); result = grd; } const ElementVector& localVec = localVectors[myRank]; getLocalVector(largeElInfo->getElement(), const_cast(localVec)); const BasisFunction *basFcts = feSpace->getBasisFcts(); mtl::dense2D &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree()); DimVec &grd1 = *grdTmp[myRank]; int parts = Global::getGeo(PARTS, dim); const DimVec > &grdLambda = largeElInfo->getGrdLambda(); DimVec* grdPhi = grdPhis[myRank]; DimVec tmp(dim, DEFAULT_VALUE, 0.0); for (int i = 0; i < nPoints; i++) { for (int j = 0; j < dim + 1; j++) grd1[j] = 0.0; for (int j = 0; j < nBasFcts; j++) { grdPhi->set(0.0); for (int k = 0; k < nBasFcts; k++) { (*(basFcts->getGrdPhi(k)))(quad->getLambda(i), tmp); tmp *= m[j][k]; *grdPhi += tmp; } for (int k = 0; k < parts; k++) grd1[k] += (*grdPhi)[k] * localVec[j]; } for (int l = 0; l < dow; l++) { result[i][l] = 0.0; for (int k = 0; k < parts; k++) result[i][l] += grdLambda[k][l] * grd1[k]; } } return const_cast*>(result); } template<> const WorldMatrix *DOFVectorBase::getD2AtQPs(const ElInfo *elInfo, const Quadrature *quad, const FastQuadrature *quadFast, WorldMatrix *d2AtQPs) const { FUNCNAME("DOFVector::getD2AtQPs()"); TEST_EXIT_DBG(quad || quadFast)("neither quad nor quadFast defined\n"); if (quad && quadFast) { TEST_EXIT_DBG(quad == quadFast->getQuadrature()) ("quad != quadFast->quadrature\n"); } TEST_EXIT_DBG(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts()) ("invalid basis functions"); Element *el = elInfo->getElement(); int myRank = omp_get_thread_num(); int dow = Global::getGeo(WORLD); int nPoints = quadFast ? quadFast->getQuadrature()->getNumPoints() : quad->getNumPoints(); static WorldMatrix *vec = NULL; WorldMatrix *result; if (d2AtQPs) { result = d2AtQPs; } else { if(vec) delete [] vec; vec = new WorldMatrix[nPoints]; for (int i = 0; i < nPoints; i++) { vec[i].set(0.0); } result = vec; } const ElementVector& localVec = localVectors[myRank]; getLocalVector(el, const_cast(localVec)); DimMat D2Tmp(dim, DEFAULT_VALUE, 0.0); int parts = Global::getGeo(PARTS, dim); const DimVec > &grdLambda = elInfo->getGrdLambda(); if (quadFast) { for (int iq = 0; iq < nPoints; iq++) { for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) D2Tmp[k][l] = 0.0; for (int i = 0; i < nBasFcts; i++) { for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) D2Tmp[k][l] += localVec[i] * quadFast->getSecDer(iq, i, k, l); } for (int i = 0; i < dow; i++) for (int j = 0; j < dow; j++) { result[iq][i][j] = 0.0; for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) result[iq][i][j] += grdLambda[k][i]*grdLambda[l][j]*D2Tmp[k][l]; } } } else { const BasisFunction *basFcts = feSpace->getBasisFcts(); DimMat* D2Phi = D2Phis[omp_get_thread_num()]; for (int iq = 0; iq < nPoints; iq++) { for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) D2Tmp[k][l] = 0.0; for (int i = 0; i < nBasFcts; i++) { WARNING("not tested after index correction\n"); (*(basFcts->getD2Phi(i)))(quad->getLambda(iq), *D2Phi); for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) D2Tmp[k][l] += localVec[i] * (*D2Phi)[k][l]; } for (int i = 0; i < dow; i++) for (int j = 0; j < dow; j++) { result[iq][i][j] = 0.0; for (int k = 0; k < parts; k++) for (int l = 0; l < parts; l++) result[iq][i][j] += grdLambda[k][i] * grdLambda[l][j] * D2Tmp[k][l]; } } } return const_cast*>(result); } template<> void DOFVector::interpol(DOFVector *source, double factor) { FUNCNAME("DOFVector::interpol()"); const FiniteElemSpace *sourceFeSpace = source->getFeSpace(); const BasisFunction *basisFcts = feSpace->getBasisFcts(); const BasisFunction *sourceBasisFcts = sourceFeSpace->getBasisFcts(); int nBasisFcts = basisFcts->getNumber(); int nSourceBasisFcts = sourceBasisFcts->getNumber(); this->set(0.0); DegreeOfFreedom *myLocalIndices = localIndices[omp_get_thread_num()]; ElementVector sourceLocalCoeffs(nSourceBasisFcts); if (feSpace->getMesh() == sourceFeSpace->getMesh()) { DimVec *coords = NULL; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(feSpace->getMesh(), -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); while (elInfo) { Element *el = elInfo->getElement(); basisFcts->getLocalIndices(el, feSpace->getAdmin(), myLocalIndices); source->getLocalVector(el, sourceLocalCoeffs); for (int i = 0; i < nBasisFcts; i++) { if (vec[myLocalIndices[i]] == 0.0) { coords = basisFcts->getCoords(i); vec[myLocalIndices[i]] = sourceBasisFcts->evalUh(*coords, sourceLocalCoeffs) * factor; } } elInfo = stack.traverseNext(elInfo); } } else { DimVec coords2(feSpace->getMesh()->getDim(), NO_INIT); DualTraverse dualStack; ElInfo *elInfo1, *elInfo2; ElInfo *elInfoSmall, *elInfoLarge; WorldVector worldVec; bool nextTraverse = dualStack.traverseFirst(feSpace->getMesh(), sourceFeSpace->getMesh(), -1, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS, &elInfo1, &elInfo2, &elInfoSmall, &elInfoLarge); while (nextTraverse) { basisFcts->getLocalIndices(elInfo1->getElement(), feSpace->getAdmin(), myLocalIndices); source->getLocalVector(elInfo2->getElement(), sourceLocalCoeffs); for (int i = 0; i < nBasisFcts; i++) { if (vec[myLocalIndices[i]] == 0.0) { elInfo1->coordToWorld(*(basisFcts->getCoords(i)), worldVec); elInfo2->worldToCoord(worldVec, &coords2); bool isPositive = true; for (int j = 0; j < coords2.size(); j++) { if (coords2[j] < -0.00001) { isPositive = false; break; } } if (isPositive) vec[myLocalIndices[i]] = sourceBasisFcts->evalUh(coords2, sourceLocalCoeffs); } } nextTraverse = dualStack.traverseNext(&elInfo1, &elInfo2, &elInfoSmall, &elInfoLarge); } } } template<> void DOFVector >::interpol(DOFVector > *v, double factor) { WorldVector nul(DEFAULT_VALUE,0.0); this->set(nul); DimVec *coords = NULL; const FiniteElemSpace *vFeSpace = v->getFeSpace(); if (feSpace == vFeSpace) WARNING("same FE-spaces\n"); const BasisFunction *basFcts = feSpace->getBasisFcts(); const BasisFunction *vBasFcts = vFeSpace->getBasisFcts(); int numBasFcts = basFcts->getNumber(); int vNumBasFcts = vBasFcts->getNumber(); if (feSpace->getMesh() == vFeSpace->getMesh()) { DegreeOfFreedom *myLocalIndices = localIndices[omp_get_thread_num()]; mtl::dense_vector > vLocalCoeffs(vNumBasFcts); Mesh *mesh = feSpace->getMesh(); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); while (elInfo) { Element *el = elInfo->getElement(); basFcts->getLocalIndices(el, feSpace->getAdmin(), myLocalIndices); v->getLocalVector(el, vLocalCoeffs); for (int i = 0; i < numBasFcts; i++) { if (vec[myLocalIndices[i]] == nul) { coords = basFcts->getCoords(i); vec[myLocalIndices[i]] += vBasFcts->evalUh(*coords, vLocalCoeffs, NULL) * factor; } } elInfo = stack.traverseNext(elInfo); } } else { ERROR_EXIT("not yet for dual traverse\n"); } } template<> WorldVector*> *DOFVector::getGradient(WorldVector*> *grad) const { FUNCNAME("DOFVector::getGradient()"); #ifdef _OPENMP ERROR_EXIT("Using static variable while using OpenMP parallelization!\n"); #endif Mesh *mesh = feSpace->getMesh(); int dim = mesh->getDim(); int dow = Global::getGeo(WORLD); const BasisFunction *basFcts = feSpace->getBasisFcts(); DOFAdmin *admin = feSpace->getAdmin(); // define result vector static WorldVector*> *result = NULL; if (grad) { result = grad; } else { if (!result) { result = new WorldVector*>; result->set(NULL); } for (int i = 0; i < dow; i++) { if ((*result)[i] && (*result)[i]->getFeSpace() != feSpace) { delete (*result)[i]; (*result)[i] = new DOFVector(feSpace, "gradient"); } } } // count number of nodes and dofs per node std::vector nNodeDOFs; std::vector nNodePreDofs; std::vector*> bary; int nNodes = 0; int nDofs = 0; for (int i = 0; i < dim + 1; i++) { GeoIndex geoIndex = INDEX_OF_DIM(i, dim); int numPositionNodes = mesh->getGeo(geoIndex); int numPreDofs = admin->getNumberOfPreDofs(i); for (int j = 0; j < numPositionNodes; j++) { int dofs = basFcts->getNumberOfDofs(geoIndex); nNodeDOFs.push_back(dofs); nDofs += dofs; nNodePreDofs.push_back(numPreDofs); } nNodes += numPositionNodes; } TEST_EXIT_DBG(nDofs == basFcts->getNumber()) ("number of dofs != number of basis functions\n"); for (int i = 0; i < nDofs; i++) bary.push_back(basFcts->getCoords(i)); // traverse mesh std::vector visited(getUsedSize(), false); TraverseStack stack; Flag fillFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_GRD_LAMBDA | Mesh::FILL_COORDS; ElInfo *elInfo = stack.traverseFirst(mesh, -1, fillFlag); WorldVector grd; ElementVector localUh(basFcts->getNumber()); while (elInfo) { const DegreeOfFreedom **dof = elInfo->getElement()->getDof(); getLocalVector(elInfo->getElement(), localUh); const DimVec > &grdLambda = elInfo->getGrdLambda(); int localDOFNr = 0; for (int i = 0; i < nNodes; i++) { // for all nodes for (int j = 0; j < nNodeDOFs[i]; j++) { // for all dofs at this node DegreeOfFreedom dofIndex = dof[i][nNodePreDofs[i] + j]; if (!visited[dofIndex]) { basFcts->evalGrdUh(*(bary[localDOFNr]), grdLambda, localUh, &grd); for (int k = 0; k < dow; k++) (*(*result)[k])[dofIndex] = grd[k]; visited[dofIndex] = true; } localDOFNr++; } } elInfo = stack.traverseNext(elInfo); } return result; } DOFVectorDOF::DOFVectorDOF() : DOFVector() {} void DOFVectorDOF::freeDOFContent(DegreeOfFreedom dof) {} WorldVector*> *transform(DOFVector > *vec, WorldVector*> *res) { FUNCNAME("DOFVector::transform()"); TEST_EXIT_DBG(vec)("no vector\n"); int dow = Global::getGeo(WORLD); static WorldVector*> *result = NULL; if (!res && !result) { result = new WorldVector*>; for (int i = 0; i < dow; i++) (*result)[i] = new DOFVector(vec->getFeSpace(), "transform"); } WorldVector*> *r = res ? res : result; int vecSize = vec->getSize(); for (int i = 0; i < vecSize; i++) for (int j = 0; j < dow; j++) (*((*r)[j]))[i] = (*vec)[i][j]; return r; } template<> void DOFVectorBase::getVecAtQPs(const ElInfo *smallElInfo, const ElInfo *largeElInfo, const Quadrature *quad, const FastQuadrature *quadFast, mtl::dense_vector& vecAtQPs) const { FUNCNAME("DOFVector::getVecAtQPs()"); TEST_EXIT_DBG(quad || quadFast)("neither quad nor quadFast defined\n"); if (quad && quadFast) { TEST_EXIT_DBG(quad == quadFast->getQuadrature()) ("quad != quadFast->quadrature\n"); } TEST_EXIT_DBG(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts()) ("invalid basis functions"); if (smallElInfo->getMesh() == feSpace->getMesh()) return getVecAtQPs(smallElInfo, quad, quadFast, vecAtQPs); const BasisFunction *basFcts = feSpace->getBasisFcts(); int nPoints = quadFast ? quadFast->getQuadrature()->getNumPoints() : quad->getNumPoints(); vecAtQPs.change_dim(nPoints); const ElementVector &localVec = localVectors[omp_get_thread_num()]; getLocalVector(largeElInfo->getElement(), const_cast(localVec)); mtl::dense2D &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree()); for (int i = 0; i < nPoints; i++) { vecAtQPs[i] = 0.0; for (int j = 0; j < nBasFcts; j++) { double val = 0.0; for (int k = 0; k < nBasFcts; k++) val += m[j][k] * (*(basFcts->getPhi(k)))(quad->getLambda(i)); vecAtQPs[i] += localVec[j] * val; } } } template<> void DOFVectorBase::assemble(double factor, ElInfo *elInfo, const BoundaryType *bound, Operator *op) { FUNCNAME("DOFVector::assemble()"); if (!(op || this->operators.size())) return; set_to_zero(this->elementVector); bool addVector = false; if (op) { op->getElementVector(elInfo, this->elementVector); addVector = true; } else { std::vector::iterator it; std::vector::iterator factorIt; for (it = this->operators.begin(), factorIt = this->operatorFactor.begin(); it != this->operators.end(); ++it, ++factorIt) if ((*it)->getNeedDualTraverse() == false) { (*it)->getElementVector(elInfo, this->elementVector, *factorIt ? **factorIt : 1.0); addVector = true; } } if (addVector) addElementVector(factor, this->elementVector, bound, elInfo); } template<> void DOFVectorBase::assemble2(double factor, ElInfo *mainElInfo, ElInfo *auxElInfo, ElInfo *smallElInfo, ElInfo *largeElInfo, const BoundaryType *bound, Operator *op) { FUNCNAME("DOFVector::assemble2()"); if (!(op || this->operators.size())) return; set_to_zero(this->elementVector); bool addVector = false; TEST_EXIT(!op)("Not yet implemented!\n"); std::vector::iterator it; std::vector::iterator factorIt; for (it = this->operators.begin(), factorIt = this->operatorFactor.begin(); it != this->operators.end(); ++it, ++factorIt) if ((*it)->getNeedDualTraverse()) { (*it)->getElementVector(mainElInfo, auxElInfo, smallElInfo, largeElInfo, this->elementVector, *factorIt ? **factorIt : 1.0); addVector = true; } if (addVector) addElementVector(factor, this->elementVector, bound, mainElInfo); } double integrate(const DOFVector &vec1, const DOFVector &vec2, BinaryAbstractFunction *fct) { if (vec1.getFeSpace()->getMesh() == vec2.getFeSpace()->getMesh()) return intSingleMesh(vec1, vec2, fct); else return intDualMesh(vec1, vec2, fct); } double intSingleMesh(const DOFVector &vec1, const DOFVector &vec2, BinaryAbstractFunction *fct) { FUNCNAME("intDualmesh()"); TEST_EXIT(fct)("No function defined!\n"); int deg = std::max(fct->getDegree(), 2 * vec1.getFeSpace()->getBasisFcts()->getDegree()); Quadrature* quad = Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg); FastQuadrature *fastQuad = FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); mtl::dense_vector qp1(fastQuad->getNumPoints()); mtl::dense_vector qp2(fastQuad->getNumPoints()); double value = 0.0; Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(vec1.getFeSpace()->getMesh(), -1, traverseFlag); while (elInfo) { vec1.getVecAtQPs(elInfo, quad, fastQuad, qp1); vec2.getVecAtQPs(elInfo, quad, fastQuad, qp2); double tmp = 0.0; for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) tmp += fastQuad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]); value += tmp * elInfo->getDet(); elInfo = stack.traverseNext(elInfo); } return value; } double intDualMesh(const DOFVector &vec1, const DOFVector &vec2, BinaryAbstractFunction *fct) { FUNCNAME("intDualmesh()"); TEST_EXIT(fct)("No function defined!\n"); int deg = std::max(fct->getDegree(), 2 * vec1.getFeSpace()->getBasisFcts()->getDegree()); Quadrature* quad = Quadrature::provideQuadrature(vec1.getFeSpace()->getMesh()->getDim(), deg); FastQuadrature *fastQuad = FastQuadrature::provideFastQuadrature(vec1.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); mtl::dense_vector qp1(fastQuad->getNumPoints()); mtl::dense_vector qp2(fastQuad->getNumPoints()); double value = 0.0; Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; DualTraverse dualTraverse; DualElInfo dualElInfo; bool cont = dualTraverse.traverseFirst(vec1.getFeSpace()->getMesh(), vec2.getFeSpace()->getMesh(), -1, -1, traverseFlag, traverseFlag, dualElInfo); while (cont) { vec1.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp1); vec2.getVecAtQPs(dualElInfo.smallElInfo, dualElInfo.largeElInfo, quad, NULL, qp2); double tmp = 0.0; for (int iq = 0; iq < quad->getNumPoints(); iq++) tmp += quad->getWeight(iq) * (*fct)(qp1[iq], qp2[iq]); value += tmp * dualElInfo.smallElInfo->getDet(); cont = dualTraverse.traverseNext(dualElInfo); } return value; } double integrate(const DOFVector &vec, AbstractFunction > *fct) { FUNCNAME("integrate()"); TEST_EXIT(fct)("No function defined!\n"); int deg = std::max(fct->getDegree(), 2 * vec.getFeSpace()->getBasisFcts()->getDegree()); Quadrature* quad = Quadrature::provideQuadrature(vec.getFeSpace()->getMesh()->getDim(), deg); FastQuadrature *fastQuad = FastQuadrature::provideFastQuadrature(vec.getFeSpace()->getBasisFcts(), *quad, INIT_PHI); mtl::dense_vector qp(fastQuad->getNumPoints()); WorldVector coords; double value = 0.0; Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(vec.getFeSpace()->getMesh(), -1, traverseFlag); while (elInfo) { vec.getVecAtQPs(elInfo, quad, fastQuad, qp); double tmp = 0.0; for (int iq = 0; iq < fastQuad->getNumPoints(); iq++) { elInfo->coordToWorld(fastQuad->getLambda(iq), coords); tmp += fastQuad->getWeight(iq) * (qp[iq] * (*fct)(coords)); } value += tmp * elInfo->getDet(); elInfo = stack.traverseNext(elInfo); } return value; } }