void GradGrad<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); // u dofs [ru.First() : ru.Next()-1], e dofs [re.First() : re.Next()-1] IntRange ru = cfel.GetRange(GetInd1()); IntRange re = cfel.GetRange(GetInd2()); int ndofe = re.Size(); int ndofu = ru.Size(); FlatMatrixFixWidth<D> dum(ndofu,lh); // to store grad(u-basis) FlatMatrixFixWidth<D> dem(ndofe,lh); // to store grad(e-basis) ELEMENT_TYPE eltype // get the type of element: = fel_u.ElementType(); // ET_TRIG in 2d, ET_TET in 3d. const IntegrationRule & // Note: p = fel_u.Order()-1 ir = SelectIntegrationRule(eltype, fel_u.Order()+fel_e.Order()-2); FlatMatrix<SCAL> submat(ndofe,ndofu,lh); submat = 0.0; for(int k=0; k<ir.GetNIP(); k++) { MappedIntegrationPoint<D,D> mip (ir[k],eltrans); // set grad(u-basis) and grad(e-basis) at mapped pts in dum and dem. fel_u.CalcMappedDShape( mip, dum ); fel_e.CalcMappedDShape( mip, dem ); // evaluate coefficient SCAL fac = coeff_a -> T_Evaluate<SCAL>(mip); fac *= mip.GetWeight() ; // [ndofe x D] * [D x ndofu] submat += fac * dem * Trans(dum) ; } elmat.Rows(re).Cols(ru) += submat; if (GetInd1() != GetInd2()) elmat.Rows(ru).Cols(re) += Conj(Trans(submat)); }
void FluxFluxBoundary<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); // This FE is already multiplied by normal: const HDivNormalFiniteElement<D-1> & fel_q = // q.n space dynamic_cast<const HDivNormalFiniteElement<D-1>&> (cfel[GetInd1()]); const HDivNormalFiniteElement<D-1> & fel_r = // r.n space dynamic_cast<const HDivNormalFiniteElement<D-1>&> (cfel[GetInd2()]); elmat = SCAL(0.0); IntRange rq = cfel.GetRange(GetInd1()); IntRange rr = cfel.GetRange(GetInd2()); int ndofq = rq.Size(); int ndofr = rr.Size(); FlatMatrix<SCAL> submat(ndofr, ndofq, lh); submat = SCAL(0.0); FlatVector<> qshape(fel_q.GetNDof(), lh); FlatVector<> rshape(fel_r.GetNDof(), lh); const IntegrationRule ir(fel_q.ElementType(), fel_q.Order() + fel_r.Order()); for (int i = 0 ; i < ir.GetNIP(); i++) { MappedIntegrationPoint<D-1,D> mip(ir[i], eltrans); SCAL cc = coeff_c -> T_Evaluate<SCAL>(mip); fel_r.CalcShape (ir[i], rshape); fel_q.CalcShape (ir[i], qshape); // mapped q.n-shape is simply reference q.n-shape / measure qshape *= 1.0/mip.GetMeasure(); rshape *= 1.0/mip.GetMeasure(); // [ndofr x 1] [1 x ndofq] submat += (cc*mip.GetWeight()) * rshape * Trans(qshape); } elmat.Rows(rr).Cols(rq) += submat; if (GetInd1() != GetInd2()) elmat.Rows(rq).Cols(rr) += Conj(Trans(submat)); }
void DGFiniteElement<D>:: CalcGradientMatrix (FlatMatrix<> gmat) const { IntegrationRule ir (this->ElementType(), 2*order); Vector<> shape(ndof); MatrixFixWidth<D> dshape(ndof); Vector<> norms(ndof); gmat = 0.0; norms = 0.0; for (int i = 0; i < ir.Size(); i++) { this -> CalcShape (ir[i], shape); this -> CalcDShape (ir[i], dshape); for (int j = 0; j < ndof; j++) for (int k = 0; k < ndof; k++) for (int l = 0; l < D; l++) gmat(k*D+l, j) += ir[i].Weight() * dshape(j,l) * shape(k); for (int j = 0; j < norms.Size(); j++) norms(j) += ir[i].Weight() * sqr (shape(j)); } for (int j = 0; j < ndof; j++) gmat.Rows(D*j, D*(j+1)) /= norms(j); }
void TraceTraceBoundary<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); // get surface elements const ScalarFiniteElement<D-1> & fel_u = // u space dynamic_cast<const ScalarFiniteElement<D-1>&> (cfel[GetInd1()]); const ScalarFiniteElement<D-1> & fel_e = // u space dynamic_cast<const ScalarFiniteElement<D-1>&> (cfel[GetInd2()]); elmat = SCAL(0.0); IntRange ru = cfel.GetRange(GetInd1()); IntRange re = cfel.GetRange(GetInd2()); int ndofu = ru.Size(); int ndofe = re.Size(); FlatMatrix<SCAL> submat(ndofe, ndofu, lh); submat = SCAL(0.0); FlatVector<> ushape(fel_u.GetNDof(), lh); FlatVector<> eshape(fel_e.GetNDof(), lh); const IntegrationRule ir(fel_u.ElementType(), fel_u.Order() + fel_e.Order()); for (int i = 0 ; i < ir.GetNIP(); i++) { MappedIntegrationPoint<D-1,D> mip(ir[i], eltrans); SCAL cc = coeff_c -> T_Evaluate<SCAL>(mip); fel_u.CalcShape (ir[i], ushape); fel_e.CalcShape (ir[i], eshape); // [ndofe x 1] [1 x ndofu] submat += (cc*mip.GetWeight()) * eshape * Trans(ushape); } elmat.Rows(re).Cols(ru) += submat; if (GetInd1() != GetInd2()) elmat.Rows(ru).Cols(re) += Conj(Trans(submat)); }
void EyeEye<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(); Vector<> ushape(ndofu); Vector<> eshape(ndofe); ELEMENT_TYPE eltype = fel_u.ElementType(); const IntegrationRule & ir = SelectIntegrationRule(eltype, fel_u.Order()+fel_e.Order()); FlatMatrix<SCAL> submat(ndofe,ndofu,lh); submat = SCAL(0.0); for(int k=0; k<ir.GetNIP(); k++) { MappedIntegrationPoint<D,D> mip (ir[k],eltrans); fel_u.CalcShape( ir[k], ushape ); fel_e.CalcShape( ir[k], eshape ); SCAL fac = (coeff_a -> T_Evaluate<SCAL>(mip))* mip.GetWeight() ; // [ndofe x D] * [D x ndofu] submat += fac * eshape * Trans(ushape) ; } elmat.Rows(re).Cols(ru) += submat; if (GetInd1() != GetInd2()) elmat.Rows(ru).Cols(re) += Conj(Trans(submat)); }
void CalcSchurComplement (const FlatMatrix<double> a, FlatMatrix<double> s, const BitArray & used, LocalHeap & lh) { if (s.Height() == 0) return; if (s.Height() == a.Height()) { s = a; return; } HeapReset hr(lh); int n = a.Height(); Array<int> used_dofs(n, lh); Array<int> unused_dofs(n, lh); used_dofs.SetSize(0); unused_dofs.SetSize(0); for (int i = 0; i < n; i++) if (used[i]) used_dofs.Append(i); else unused_dofs.Append(i); s = a.Rows(used_dofs).Cols(used_dofs); FlatMatrix<> b1 = a.Rows(unused_dofs).Cols(used_dofs) | lh; FlatMatrix<> b2 = a.Rows(used_dofs).Cols(unused_dofs) | lh; FlatMatrix<> c = a.Rows(unused_dofs).Cols(unused_dofs) | lh; FlatMatrix<> hb1 (b1.Height(), b1.Width(), lh); if (n > 10) { LapackInverse (c); hb1 = c * b1 | Lapack; s -= b2 * hb1 | Lapack; } else { CalcInverse (c); hb1 = c * b1; s -= b2 * hb1; } }
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 RobinVolume<D> :: T_CalcElementMatrix (const FiniteElement & base_fel, const ElementTransformation & eltrans, FlatMatrix<SCAL> elmat, LocalHeap & lh) const { ELEMENT_TYPE eltype = base_fel.ElementType(); const CompoundFiniteElement & cfel // product space = dynamic_cast<const CompoundFiniteElement&> (base_fel); // note how we do NOT refer to D-1 elements here: 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); IntRange ru = cfel.GetRange(GetInd1()); IntRange re = cfel.GetRange(GetInd2()); int ndofe = re.Size(); int ndofu = ru.Size(); FlatVector<> ushape(fel_u.GetNDof(), lh); FlatVector<> eshape(fel_e.GetNDof(), lh); FlatMatrix<SCAL> submat(ndofe,ndofu,lh); submat = SCAL(0); int nfacet = ElementTopology::GetNFacets(eltype); Facet2ElementTrafo transform(eltype); FlatVector< Vec<D> > normals = ElementTopology::GetNormals<D>(eltype); const MeshAccess & ma = *(const MeshAccess*)eltrans.GetMesh(); Array<int> fnums, sels; ma.GetElFacets (eltrans.GetElementNr(), fnums); for (int k = 0; k < nfacet; k++) { ma.GetFacetSurfaceElements (fnums[k], sels); // if interior element, then do nothing: if (sels.Size() == 0) continue; // else: Vec<D> normal_ref = normals[k]; ELEMENT_TYPE etfacet=ElementTopology::GetFacetType(eltype, k); IntegrationRule ir_facet(etfacet, fel_e.Order()+fel_u.Order()); // map the facet integration points to volume reference elt ipts IntegrationRule & ir_facet_vol = transform(k, ir_facet, lh); // ... and further to the physical element MappedIntegrationRule<D,D> mir(ir_facet_vol, eltrans, lh); for (int i = 0 ; i < ir_facet_vol.GetNIP(); i++) { SCAL val = coeff_c->T_Evaluate<SCAL> (mir[i]); // this is contrived to get the surface measure in "len" Mat<D> inv_jac = mir[i].GetJacobianInverse(); double det = mir[i].GetMeasure(); Vec<D> normal = det * Trans (inv_jac) * normal_ref; double len = L2Norm (normal); val *= len * ir_facet[i].Weight(); fel_u.CalcShape (ir_facet_vol[i], ushape); fel_e.CalcShape (ir_facet_vol[i], eshape); submat += val * eshape * Trans(ushape); } } elmat.Rows(re).Cols(ru) += submat; if (GetInd1() != GetInd2()) elmat.Rows(ru).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)); }