void FluxTrace<D>::T_CalcElementMatrix (const FiniteElement & base_fel, const ElementTransformation & eltrans, FlatMatrix<SCAL> elmat, LocalHeap & lh) const { const CompoundFiniteElement & cfel // product space = dynamic_cast<const CompoundFiniteElement&> (base_fel); const HDivFiniteElement<D> & fel_q = // q space dynamic_cast<const HDivFiniteElement<D>& > (cfel[GetInd1()]); const ScalarFiniteElement<D> & fel_e = // e space dynamic_cast<const ScalarFiniteElement<D>&> (cfel[GetInd2()]); elmat = SCAL(0.0); IntRange rq = cfel.GetRange(GetInd1()); IntRange re = cfel.GetRange(GetInd2()); int ndofq = rq.Size(); int ndofe = re.Size(); FlatMatrix<SCAL> submat(ndofe,ndofq,lh); FlatMatrixFixWidth<D> shapeq(ndofq,lh); // q-basis (vec) values FlatVector<> shapee(ndofe,lh); // e-basis basis ELEMENT_TYPE eltype // get the type of element: = fel_q.ElementType(); // ET_TRIG in 2d, ET_TET in 3d. // transform facet integration points to volume integration points Facet2ElementTrafo transform(eltype); int nfa = ElementTopology::GetNFacets(eltype); /* nfa = number of facets of an element */ submat = 0.0; for(int k = 0; k<nfa; k++) { // type of geometry of k-th facet ELEMENT_TYPE eltype_facet = ElementTopology::GetFacetType(eltype, k); const IntegrationRule & facet_ir = SelectIntegrationRule (eltype_facet, fel_q.Order()+fel_e.Order()); // reference element normal vector FlatVec<D> normal_ref = ElementTopology::GetNormals(eltype) [k]; for (int l = 0; l < facet_ir.GetNIP(); l++) { // map 1D facet points to volume integration points IntegrationPoint volume_ip = transform(k, facet_ir[l]); MappedIntegrationPoint<D,D> mip (volume_ip, eltrans); // compute normal on physcial element Mat<D> inv_jac = mip.GetJacobianInverse(); double det = mip.GetJacobiDet(); Vec<D> normal = fabs(det) * Trans(inv_jac) * normal_ref; double len = L2Norm(normal); normal /= len; double weight = facet_ir[l].Weight()*len; // mapped H(div) basis fn values and DG fn (no need to map) values fel_q.CalcMappedShape(mip,shapeq); fel_e.CalcShape(volume_ip,shapee); // evaluate coefficient SCAL dd = coeff_d -> T_Evaluate<SCAL>(mip); // [ndofe x 1] [ndofq x D] * [D x 1] submat += (dd*weight) * shapee * Trans( shapeq * normal ) ; } } elmat.Rows(re).Cols(rq) += submat; elmat.Rows(rq).Cols(re) += Conj(Trans(submat)); }
void TraceTrace<D>::T_CalcElementMatrix (const FiniteElement & base_fel, const ElementTransformation & eltrans, FlatMatrix<SCAL> elmat, LocalHeap & lh) const { const CompoundFiniteElement & cfel // product space = dynamic_cast<const CompoundFiniteElement&> (base_fel); const ScalarFiniteElement<D> & fel_u = // u space dynamic_cast<const ScalarFiniteElement<D>&> (cfel[GetInd1()]); const ScalarFiniteElement<D> & fel_e = // e space dynamic_cast<const ScalarFiniteElement<D>&> (cfel[GetInd2()]); elmat = SCAL(0.0); IntRange ru = cfel.GetRange(GetInd1()); IntRange re = cfel.GetRange(GetInd2()); int ndofe = re.Size(); int ndofu = ru.Size(); FlatVector<> shapee(ndofe,lh); FlatVector<> shapeu(ndofu,lh); FlatMatrix<SCAL> submat(ndofe,ndofu, lh); submat = SCAL(0.0); ELEMENT_TYPE eltype = fel_u.ElementType(); Facet2ElementTrafo transform(eltype); int nfa = ElementTopology :: GetNFacets(eltype); for(int k = 0; k<nfa; k++) { // type of geometry of k-th facet ELEMENT_TYPE eltype_facet = ElementTopology::GetFacetType(eltype, k); const IntegrationRule & facet_ir = SelectIntegrationRule (eltype_facet, fel_u.Order()+fel_e.Order()); // reference element normal vector FlatVec<D> normal_ref = ElementTopology::GetNormals(eltype) [k]; for (int l = 0; l < facet_ir.GetNIP(); l++) { // map 1D facet points to volume integration points IntegrationPoint volume_ip = transform(k, facet_ir[l]); MappedIntegrationPoint<D,D> mip (volume_ip, eltrans); // compute normal on physcial element Mat<D> inv_jac = mip.GetJacobianInverse(); double det = mip.GetJacobiDet(); Vec<D> normal = fabs(det) * Trans(inv_jac) * normal_ref; double len = L2Norm(normal); normal /= len; double weight = facet_ir[l].Weight()*len; fel_e.CalcShape(volume_ip,shapee); fel_u.CalcShape(volume_ip,shapeu); SCAL cc = coeff_c -> T_Evaluate<SCAL>(mip); // [ndofe x 1] [1 x ndofu] submat += (cc*weight) * shapee * Trans(shapeu); } } elmat.Rows(re).Cols(ru) += submat; if (GetInd1() != GetInd2()) elmat.Rows(ru).Cols(re) += Conj(Trans(submat)); }