void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) { Number an1, an2; Number gn1, gn2; SplitExp(an, an1, an2); // printf("an=%s\n", an.ToString().c_str()); // printf("an1=%s\n", an1.ToString().c_str()); // printf("an2=%s\n", an2.ToString().c_str()); // printf("an1.len=%i\n", an1.GetBits()); // printf("an2.len=%i\n", an2.GetBits()); gn.SplitInto(128, gn1, gn2); WNAF<128> wa1(an1, WINDOW_A); WNAF<128> wa2(an2, WINDOW_A); WNAF<128> wg1(gn1, WINDOW_G); WNAF<128> wg2(gn2, WINDOW_G); GroupElemJac a2; a2.SetMulLambda(a); WNAFPrecomp<GroupElemJac,WINDOW_A> wpa1(a); WNAFPrecomp<GroupElemJac,WINDOW_A> wpa2(a2); const ECMultConsts &c = GetECMultConsts(); int size_a1 = wa1.GetSize(); int size_a2 = wa2.GetSize(); int size_g1 = wg1.GetSize(); int size_g2 = wg2.GetSize(); int size = std::max(std::max(size_a1, size_a2), std::max(size_g1, size_g2)); out = GroupElemJac(); GroupElemJac tmpj; GroupElem tmpa; for (int i=size-1; i>=0; i--) { out.SetDouble(out); int nw; if (i < size_a1 && (nw = wa1.Get(i))) { wpa1.Get(tmpj, nw); out.SetAdd(out, tmpj); } if (i < size_a2 && (nw = wa2.Get(i))) { wpa2.Get(tmpj, nw); out.SetAdd(out, tmpj); } if (i < size_g1 && (nw = wg1.Get(i))) { c.wpg.Get(tmpa, nw); out.SetAdd(out, tmpa); } if (i < size_g2 && (nw = wg2.Get(i))) { c.wpg128.Get(tmpa, nw); out.SetAdd(out, tmpa); } } }
bool ASMs2DSpec::integrate (Integrand& integrand, GlobalIntegral& glInt, const TimeDomain& time) { if (this->empty()) return true; // silently ignore empty patches // Evaluate integration points (= nodal points) and weights Vector wg1,xg1,wg2,xg2; if (!Legendre::GLL(wg1,xg1,p1)) return false; if (!Legendre::GLL(wg2,xg2,p2)) return false; Matrix D1, D2; if (!Legendre::basisDerivatives(p1,D1)) return false; if (!Legendre::basisDerivatives(p2,D2)) return false; // === Assembly loop over all elements in the patch ========================== bool ok = true; for (size_t g = 0; g < threadGroups.size() && ok; g++) { #pragma omp parallel for schedule(static) for (size_t t = 0; t < threadGroups[g].size(); t++) { FiniteElement fe(p1*p2); Matrix dNdu(p1*p2,2), Xnod, Jac; Vec4 X; for (size_t e = 0; e < threadGroups[g][t].size(); e++) { int iel = threadGroups[g][t][e]+1; // Set up control point coordinates for current element if (!this->getElementCoordinates(Xnod,iel)) { ok = false; break; } // Initialize element quantities fe.iel = MLGE[iel-1]; LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel); if (!integrand.initElement(MNPC[iel-1],*A)) { A->destruct(); ok = false; break; } // --- Integration loop over all Gauss points in each direction -------- int count = 1; for (int j = 1; j <= p2; j++) for (int i = 1; i <= p1; i++, count++) { // Evaluate the basis functions and gradients using // tensor product of one-dimensional Lagrange polynomials evalBasis(i,j,p1,p2,D1,D2,fe.N,dNdu); // Compute Jacobian inverse of coordinate mapping and derivatives fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu); if (fe.detJxW == 0.0) continue; // skip singular points // Cartesian coordinates of current integration point X.x = Xnod(1,count); X.y = Xnod(2,count); X.t = time.t; // Evaluate the integrand and accumulate element contributions fe.detJxW *= wg1(i)*wg2(j); if (!integrand.evalInt(*A,fe,time,X)) ok = false; } // Assembly of global system integral if (ok && !glInt.assemble(A->ref(),fe.iel)) ok = false; A->destruct(); } } } return ok; }