void compare(CompareCmd *env, FE_Field *field_a, PointField *field_b) { if (env->verbose) { cout << "Comparing FE_Field against PointField" << endl; } assert(env->quadrature != 0); QuadratureRule *qr = env->quadrature; Residuals *residuals = env->residuals; // dimensions int nel = qr->meshPart->nel; int nq = qr->points->n_points(); int valdim = field_a->n_rank(); assert((nel*nq) == field_b->points->n_points()); assert(valdim == field_b->values->n_dim()); // field values at quadrature points Points phi_a, phi_b; double *values_a = new double[nq * valdim]; double *values_b = new double[nq * valdim]; phi_a.set_data(values_a, nq, valdim); phi_b.set_data(values_b, nq, valdim); residuals->reset_accumulator(); env->start_timer(nel, "elts"); // main loop for (int e = 0; e < nel; e++) { qr->select_cell(e); for (int q = 0; q < nq; q++) { double *globalPoint = (*(qr->points))[q]; bool ca = field_a->eval(globalPoint, &values_a[q*valdim]); //bool cb = field_b->eval(globalPoint, &values_b[q*valdim]); for (int i = 0; i < valdim; i++) { values_b[q*valdim + i] = field_b->values->data[q*valdim + i]; } } double err2 = qr->L2(phi_a, phi_b); double vol = qr->meshPart->cell->volume(); //residuals->update(e, sqrt(err2)/vol); //residuals->update(e, sqrt(err2)); residuals->update(e, sqrt(err2), vol); env->update_timer(e); } env->end_timer(); // clean up delete [] values_a; delete [] values_b; }
void compare(CompareCmd *env, FE_Field *field_a, FE_Field *field_b) { if (env->verbose) { cout << "Comparing FE_Field against FE_Field" << endl; } assert(env->quadrature != 0); QuadratureRule *qr = env->quadrature; Residuals *residuals = env->residuals; // dimensions int nel = qr->meshPart->nel; int nq = qr->points->n_points(); int valdim = field_a->n_rank(); // field values at quadrature points Points phi_a, phi_b; double *values_a = new double[nq * valdim]; double *values_b = new double[nq * valdim]; phi_a.set_data(values_a, nq, valdim); phi_b.set_data(values_b, nq, valdim); field_a->fe->initialize_basis_tab(); residuals->reset_accumulator(); // main loop env->start_timer(nel,"elts"); for (int e = 0; e < nel; e++) { qr->select_cell(e); field_a->tabulate_element(e, phi_a.data); bool cb = field_b->Field::eval(*(qr->points), phi_b); double err2 = qr->L2(phi_a, phi_b); double vol = qr->meshPart->cell->volume(); //residuals->update(e, sqrt(err2)/vol); //residuals->update(e, sqrt(err2)); residuals->update(e, sqrt(err2), vol); env->update_timer(e); } env->end_timer(); // clean up delete [] values_a; delete [] values_b; }
void CompositeIntegrator::integrate() { mResult = 0; mGrid.resetIteration(); while (mGrid.hasNextInterval()) { const Interval& interval = mGrid.nextInterval(); QuadratureRule* localIntegrator = mFactory->create(mFunction, interval.xLow, interval.xHigh); localIntegrator->integrate(); mResult += localIntegrator->getResult(); } }
int main(int argc, char* argv[]) { double a = 0; double b = 2; if (argc != 3 && argc != 5) { printHelp(argv); return 1; } if (strlen(argv[1]) > 1) { printHelp(argv); return 2; } char method = argv[1][0]; int functionIndex = atoi(argv[2]); if (functionIndex == 0) { printHelp(argv); return 3; } if (argc == 5) { a = atof(argv[3]); b = atof(argv[4]); if (b <= a) { printHelp(argv); return 4; } } fptr func = chooseFunc(functionIndex); QuadratureRule* integrator = createMethod(method, func, a, b); printf("performing integration\n"); integrator->integrate(); printf("result of integrating function %d in interval [%5.3lf, %5.3lf] = %5.3lf\n", functionIndex, a, b, integrator->getResult()); return 0; }
void PrintQuadRule(const QuadratureRule<2>& q) { cout << "QuadRule\n"; cout << "--------\n"; cout << "Order: " << q.order() << "\n"; cout << "Size: " << q.size() << "\n"; for(size_t i = 0; i < q.size(); ++i) cout << "Weight "<<i<<": "<<q.weight(i) <<"\n"; for(size_t i = 0; i < q.size(); ++i) cout << "Point "<<i<<": "<<q.point(i) <<"\n"; }
void LevelSetBDQRAdapter<FESpaceType, VectorType>:: update (UInt elementID, UInt localFaceID) { // They are ordered so that the "mapping" in // QuadratureBoundary is right. std::vector<UInt> myLID (3); if (localFaceID == 0) { myLID[0] = 0; myLID[1] = 1; myLID[2] = 2; } else if (localFaceID == 1) { myLID[0] = 0; myLID[1] = 1; myLID[2] = 3; } else if (localFaceID == 2) { myLID[0] = 3; myLID[1] = 1; myLID[2] = 2; } else { myLID[0] = 0; myLID[1] = 3; myLID[2] = 2; } // Compute the global IDs std::vector<UInt> myGID (3); for (UInt i (0); i < 3; ++i) { myGID[i] = M_lsFESpace->dof().localToGlobalMap (elementID, myLID[i]); } // Check the level set values std::vector<UInt> localPositive; std::vector<UInt> localNegative; std::vector<Real> localPositiveValue; std::vector<Real> localNegativeValue; for (UInt i (0); i < 3; ++i) { if (M_lsValue[myGID[i]] >= 0) { localPositive.push_back (i); localPositiveValue.push_back (M_lsValue[myGID[i]]); } else { localNegative.push_back (i); localNegativeValue.push_back (M_lsValue[myGID[i]]); } } // Check if the element is actually cut by the interface. if (localPositive.empty() || localNegative.empty() ) { M_isAdaptedElement = false; *M_adaptedQrBd = M_qrBd; } else { M_isAdaptedElement = true; std::vector<std::vector<Real> >refCoor (3, std::vector<Real> (2) ); refCoor[0][0] = 0.0; refCoor[0][1] = 0.0; refCoor[1][0] = 1.0; refCoor[1][1] = 0.0; refCoor[2][0] = 0.0; refCoor[2][1] = 1.0; QuadratureRule qrRef ("none", TRIANGLE, 3, 0, 0); // Disinguish the two cases if (localPositive.size() == 1) { // Do nothing } else { // Exchange positive and negative values localPositive.swap (localNegative); localPositiveValue.swap (localNegativeValue); } // Two negative case Real lambda1 = -localPositiveValue[0] / (localNegativeValue[0] - localPositiveValue[0]); std::vector < Real > I1 (2); I1[0] = refCoor[localPositive[0]][0] + lambda1 * (refCoor[localNegative[0]][0] - refCoor[localPositive[0]][0]); I1[1] = refCoor[localPositive[0]][1] + lambda1 * (refCoor[localNegative[0]][1] - refCoor[localPositive[0]][1]); Real lambda2 = -localPositiveValue[0] / (localNegativeValue[1] - localPositiveValue[0]); std::vector < Real > I2 (2); I2[0] = refCoor[localPositive[0]][0] + lambda2 * (refCoor[localNegative[1]][0] - refCoor[localPositive[0]][0]); I2[1] = refCoor[localPositive[0]][1] + lambda2 * (refCoor[localNegative[1]][1] - refCoor[localPositive[0]][1]); // First triangle { std::vector<Real> P0 (2); P0[0] = refCoor[localPositive[0]][0]; P0[1] = refCoor[localPositive[0]][1]; std::vector<Real> v1 (2); v1[0] = I1[0] - refCoor[localPositive[0]][0]; v1[1] = I1[1] - refCoor[localPositive[0]][1]; std::vector<Real> v2 (2); v2[0] = I2[0] - refCoor[localPositive[0]][0]; v2[1] = I2[1] - refCoor[localPositive[0]][1]; Real wRel (std::abs (v1[0]*v2[1] - v1[1]*v2[0]) ); for (UInt iq (0); iq < M_qrBd.qr (0).nbQuadPt(); ++iq) { Real x (P0[0] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[0] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[0]); Real y (P0[1] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[1] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[1]); qrRef.addPoint (QuadraturePoint (x, y, M_qrBd.qr (0).weight (iq) *wRel) ); } } // Second triangle { std::vector<Real> P0 (2); P0[0] = refCoor[localNegative[0]][0]; P0[1] = refCoor[localNegative[0]][1]; std::vector<Real> v1 (2); v1[0] = I1[0] - refCoor[localNegative[0]][0]; v1[1] = I1[1] - refCoor[localNegative[0]][1]; std::vector<Real> v2 (2); v2[0] = I2[0] - refCoor[localNegative[0]][0]; v2[1] = I2[1] - refCoor[localNegative[0]][1]; Real wRel (std::abs (v1[0]*v2[1] - v1[1]*v2[0]) ); for (UInt iq (0); iq < M_qrBd.qr (0).nbQuadPt(); ++iq) { Real x (P0[0] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[0] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[0]); Real y (P0[1] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[1] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[1]); qrRef.addPoint (QuadraturePoint (x, y, M_qrBd.qr (0).weight (iq) *wRel) ); } } // Third triangle { std::vector<Real> P0 (2); P0[0] = refCoor[localNegative[0]][0]; P0[1] = refCoor[localNegative[0]][1]; std::vector<Real> v1 (2); v1[0] = I2[0] - refCoor[localNegative[0]][0]; v1[1] = I2[1] - refCoor[localNegative[0]][1]; std::vector<Real> v2 (2); v2[0] = refCoor[localNegative[1]][0] - refCoor[localNegative[0]][0]; v2[1] = refCoor[localNegative[1]][1] - refCoor[localNegative[0]][1]; Real wRel (std::abs (v1[0]*v2[1] - v1[1]*v2[0]) ); for (UInt iq (0); iq < M_qrBd.qr (0).nbQuadPt(); ++iq) { Real x (P0[0] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[0] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[0]); Real y (P0[1] + M_qrBd.qr (0).quadPointCoor (iq, 0) *v1[1] + M_qrBd.qr (0).quadPointCoor (iq, 1) *v2[1]); qrRef.addPoint (QuadraturePoint (x, y, M_qrBd.qr (0).weight (iq) *wRel) ); } } // Call the make tretra M_adaptedQrBd.reset (new QuadratureBoundary (buildTetraBDQR (qrRef) ) ); } }
void WallTensionEstimatorCylindricalCoordinates<Mesh >::constructGlobalStressVector() { //Creating the local stress tensors VectorElemental elVecSigmaX (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); VectorElemental elVecSigmaY (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); VectorElemental elVecSigmaZ (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); LifeChrono chrono; //Constructing the patch area vector for reconstruction purposes solutionVect_Type patchArea (* (this->M_displacement), Unique, Add); patchArea *= 0.0; super::constructPatchAreaVector ( patchArea ); //Before assembling the reconstruction process is done solutionVect_Type patchAreaR (patchArea, Repeated); QuadratureRule fakeQuadratureRule; Real refElemArea (0); //area of reference element //compute the area of reference element for (UInt iq = 0; iq < this->M_FESpace->qr().nbQuadPt(); iq++) { refElemArea += this->M_FESpace->qr().weight (iq); } Real wQuad (refElemArea / this->M_FESpace->refFE().nbDof() ); //Setting the quadrature Points = DOFs of the element and weight = 1 std::vector<GeoVector> coords = this->M_FESpace->refFE().refCoor(); std::vector<Real> weights (this->M_FESpace->fe().nbFEDof(), wQuad); fakeQuadratureRule.setDimensionShape ( shapeDimension (this->M_FESpace->refFE().shape() ), this->M_FESpace->refFE().shape() ); fakeQuadratureRule.setPoints (coords, weights); //Set the new quadrature rule this->M_FESpace->setQuadRule (fakeQuadratureRule); this->M_displayer->leaderPrint (" \n*********************************\n "); this->M_displayer->leaderPrint (" Performing the analysis recovering the Cauchy stresses..., ", this->M_dataMaterial->solidType() ); this->M_displayer->leaderPrint (" \n*********************************\n "); UInt totalDof = this->M_FESpace->dof().numTotalDof(); VectorElemental dk_loc (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); //Vectors for the deformation tensor std::vector<matrix_Type> vectorDeformationF (this->M_FESpace->fe().nbFEDof(), * (this->M_deformationF) ); //Copying the displacement field into a vector with repeated map for parallel computations solutionVect_Type dRep (* (this->M_displacement), Repeated); chrono.start(); //Loop on each volume for ( UInt i = 0; i < this->M_FESpace->mesh()->numVolumes(); ++i ) { this->M_FESpace->fe().updateFirstDerivQuadPt ( this->M_FESpace->mesh()->volumeList ( i ) ); elVecSigmaX.zero(); elVecSigmaY.zero(); elVecSigmaZ.zero(); this->M_marker = this->M_FESpace->mesh()->volumeList ( i ).markerID(); UInt eleID = this->M_FESpace->fe().currentLocalId(); //Extracting the local displacement for ( UInt iNode = 0; iNode < ( UInt ) this->M_FESpace->fe().nbFEDof(); iNode++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( iNode ); for ( UInt iComp = 0; iComp < this->M_FESpace->fieldDim(); ++iComp ) { UInt ig = this->M_FESpace->dof().localToGlobalMap ( eleID, iloc ) + iComp * this->M_FESpace->dim() + this->M_offset; dk_loc[iloc + iComp * this->M_FESpace->fe().nbFEDof()] = dRep[ig]; } } //Compute the element tensor F AssemblyElementalStructure::computeLocalDeformationGradientWithoutIdentity ( dk_loc, vectorDeformationF, this->M_FESpace->fe() ); //Compute the local vector of the principal stresses for ( UInt nDOF = 0; nDOF < ( UInt ) this->M_FESpace->fe().nbFEDof(); nDOF++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( nDOF ); vector_Type localDisplacement (this->M_FESpace->fieldDim(), 0.0); for ( UInt coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { localDisplacement[coor] = iloc + coor * this->M_FESpace->fe().nbFEDof(); } this->M_sigma->Scale (0.0); this->M_firstPiola->Scale (0.0); this->M_cofactorF->Scale (0.0); this->M_deformationCylindricalF->Scale (0.0); moveToCylindricalCoordinates (vectorDeformationF[nDOF], iloc, *M_deformationCylindricalF); //Compute the rightCauchyC tensor AssemblyElementalStructure::computeInvariantsRightCauchyGreenTensor (this->M_invariants, *M_deformationCylindricalF, * (this->M_cofactorF) ); //Compute the first Piola-Kirchhoff tensor this->M_material->computeLocalFirstPiolaKirchhoffTensor (* (this->M_firstPiola), *M_deformationCylindricalF, * (this->M_cofactorF), this->M_invariants, this->M_marker); //Compute the Cauchy tensor AssemblyElementalStructure::computeCauchyStressTensor (* (this->M_sigma), * (this->M_firstPiola), this->M_invariants[3], *M_deformationCylindricalF); //Assembling the local vectors for local tensions Component X for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaX) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 0); } //Assembling the local vectors for local tensions Component Y for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaY) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 1); } //Assembling the local vectors for local tensions Component Z for ( int coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { (elVecSigmaZ) [iloc + coor * this->M_FESpace->fe().nbFEDof()] = (* (this->M_sigma) ) (coor, 2); } } super::reconstructElementaryVector ( elVecSigmaX, patchAreaR, *this->M_FESpace ); super::reconstructElementaryVector ( elVecSigmaY, patchAreaR, *this->M_FESpace ); super::reconstructElementaryVector ( elVecSigmaZ, patchAreaR, *this->M_FESpace ); //Assembling the three elemental vector in the three global for ( UInt ic = 0; ic < this->M_FESpace->fieldDim(); ++ic ) { assembleVector (*this->M_sigmaX, elVecSigmaX, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); assembleVector (*this->M_sigmaY, elVecSigmaY, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); assembleVector (*this->M_sigmaZ, elVecSigmaZ, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); } } this->M_sigmaX->globalAssemble(); this->M_sigmaY->globalAssemble(); this->M_sigmaZ->globalAssemble(); }
void WallTensionEstimatorCylindricalCoordinates<Mesh >::analyzeTensionsRecoveryEigenvaluesCylindrical ( void ) { LifeChrono chrono; this->M_displayer->leaderPrint (" \n*********************************\n "); this->M_displayer->leaderPrint (" Performing the analysis recovering the tensions..., ", this->M_dataMaterial->solidType() ); this->M_displayer->leaderPrint (" \n*********************************\n "); solutionVect_Type patchArea (* (this->M_displacement), Unique, Add); patchArea *= 0.0; super::constructPatchAreaVector ( patchArea ); //Before assembling the reconstruction process is done solutionVect_Type patchAreaR (patchArea, Repeated); QuadratureRule fakeQuadratureRule; Real refElemArea (0); //area of reference element //compute the area of reference element for (UInt iq = 0; iq < this->M_FESpace->qr().nbQuadPt(); iq++) { refElemArea += this->M_FESpace->qr().weight (iq); } Real wQuad (refElemArea / this->M_FESpace->refFE().nbDof() ); //Setting the quadrature Points = DOFs of the element and weight = 1 std::vector<GeoVector> coords = this->M_FESpace->refFE().refCoor(); std::vector<Real> weights (this->M_FESpace->fe().nbFEDof(), wQuad); fakeQuadratureRule.setDimensionShape ( shapeDimension (this->M_FESpace->refFE().shape() ), this->M_FESpace->refFE().shape() ); fakeQuadratureRule.setPoints (coords, weights); //Set the new quadrature rule this->M_FESpace->setQuadRule (fakeQuadratureRule); UInt totalDof = this->M_FESpace->dof().numTotalDof(); VectorElemental dk_loc (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); //Vectors for the deformation tensor std::vector<matrix_Type> vectorDeformationF (this->M_FESpace->fe().nbFEDof(), * (this->M_deformationF) ); //Copying the displacement field into a vector with repeated map for parallel computations solutionVect_Type dRep (* (this->M_displacement), Repeated); VectorElemental elVecTens (this->M_FESpace->fe().nbFEDof(), this->M_FESpace->fieldDim() ); chrono.start(); //Loop on each volume for ( UInt i = 0; i < this->M_FESpace->mesh()->numVolumes(); ++i ) { this->M_FESpace->fe().updateFirstDerivQuadPt ( this->M_FESpace->mesh()->volumeList ( i ) ); elVecTens.zero(); this->M_marker = this->M_FESpace->mesh()->volumeList ( i ).markerID(); UInt eleID = this->M_FESpace->fe().currentLocalId(); //Extracting the local displacement for ( UInt iNode = 0; iNode < ( UInt ) this->M_FESpace->fe().nbFEDof(); iNode++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( iNode ); for ( UInt iComp = 0; iComp < this->M_FESpace->fieldDim(); ++iComp ) { UInt ig = this->M_FESpace->dof().localToGlobalMap ( eleID, iloc ) + iComp * this->M_FESpace->dim() + this->M_offset; dk_loc[iloc + iComp * this->M_FESpace->fe().nbFEDof()] = dRep[ig]; } } //Compute the element tensor F AssemblyElementalStructure::computeLocalDeformationGradientWithoutIdentity ( dk_loc, vectorDeformationF, this->M_FESpace->fe() ); //Compute the local vector of the principal stresses for ( UInt nDOF = 0; nDOF < ( UInt ) this->M_FESpace->fe().nbFEDof(); nDOF++ ) { UInt iloc = this->M_FESpace->fe().patternFirst ( nDOF ); vector_Type localDisplacement (this->M_FESpace->fieldDim(), 0.0); for ( UInt coor = 0; coor < this->M_FESpace->fieldDim(); coor++ ) { localDisplacement[coor] = iloc + coor * this->M_FESpace->fe().nbFEDof(); } this->M_sigma->Scale (0.0); this->M_firstPiola->Scale (0.0); this->M_cofactorF->Scale (0.0); M_deformationCylindricalF->Scale (0.0); moveToCylindricalCoordinates (vectorDeformationF[nDOF], iloc, *M_deformationCylindricalF); //Compute the rightCauchyC tensor AssemblyElementalStructure::computeInvariantsRightCauchyGreenTensor (this->M_invariants, *M_deformationCylindricalF, * (this->M_cofactorF) ); //Compute the first Piola-Kirchhoff tensor this->M_material->computeLocalFirstPiolaKirchhoffTensor (* (this->M_firstPiola), *M_deformationCylindricalF, * (this->M_cofactorF), this->M_invariants, this->M_marker); //Compute the Cauchy tensor AssemblyElementalStructure::computeCauchyStressTensor (* (this->M_sigma), * (this->M_firstPiola), this->M_invariants[3], *M_deformationCylindricalF); //Compute the eigenvalue AssemblyElementalStructure::computeEigenvalues (* (this->M_sigma), this->M_eigenvaluesR, this->M_eigenvaluesI); //The Cauchy tensor is symmetric and therefore, the eigenvalues are real //Check on the imaginary part of eigen values given by the Lapack method Real sum (0); for ( int i = 0; i < this->M_eigenvaluesI.size(); i++ ) { sum += std::abs (this->M_eigenvaluesI[i]); } ASSERT_PRE ( sum < 1e-6 , "The eigenvalues of the Cauchy stress tensors have to be real!" ); std::sort ( this->M_eigenvaluesR.begin(), this->M_eigenvaluesR.end() ); //Assembling the local vector for ( int coor = 0; coor < this->M_eigenvaluesR.size(); coor++ ) { elVecTens[iloc + coor * this->M_FESpace->fe().nbFEDof()] = this->M_eigenvaluesR[coor]; } } super::reconstructElementaryVector ( elVecTens, patchAreaR, *this->M_FESpace ); //Assembling the local into global vector for ( UInt ic = 0; ic < this->M_FESpace->fieldDim(); ++ic ) { assembleVector (* (this->M_globalEigenvalues), elVecTens, this->M_FESpace->fe(), this->M_FESpace->dof(), ic, this->M_offset + ic * totalDof ); } } this->M_globalEigenvalues->globalAssemble(); chrono.stop(); this->M_displayer->leaderPrint ("Analysis done in: ", chrono.diff() ); }
double integrateD(const KernelD & F, const Element & e) { double result = 0.0; // Get the quadrature rules for azimuthal and polar integrations namespace mpl = boost::mpl; typedef typename mpl::at<rules_map, mpl::int_<PhiPoints> >::type PhiPolicy; typedef typename mpl::at<rules_map, mpl::int_<ThetaPoints> >::type ThetaPolicy; QuadratureRule<PhiPolicy> phiRule; QuadratureRule<ThetaPolicy> thetaRule; int upper_phi = PhiPoints / 2; // Upper limit for loop on phi points int upper_theta = ThetaPoints / 2; // Upper limit for loop on theta points // Extract relevant data from Element int nVertices = e.nVertices(); Eigen::Vector3d normal = e.normal(); Sphere sph = e.sphere(); Eigen::Matrix3Xd vertices = e.vertices(); Eigen::Matrix3Xd arcs = e.arcs(); // Calculation of the tangent and the bitangent (binormal) vectors // Tangent, Bitangent and Normal form a local reference frame: // T <-> x; B <-> y; N <-> z Eigen::Vector3d tangent, bitangent; tangent_and_bitangent(normal, tangent, bitangent); std::vector<double> theta(nVertices), phi(nVertices), phinumb(nVertices+1); std::vector<int> numb(nVertices+1); // Clean-up heap crap std::fill_n(theta.begin(), nVertices, 0.0); std::fill_n(phi.begin(), nVertices, 0.0); std::fill_n(numb.begin(), nVertices+1, 0); std::fill_n(phinumb.begin(), nVertices+1, 0.0); // Populate arrays and redefine tangent and bitangent e.spherical_polygon(tangent, bitangent, theta, phi, phinumb, numb); // Actual integration occurs here for (int i = 0; i < nVertices; ++i) { // Loop on edges double phiLower = phinumb[i]; // Lower vertex of edge double phiUpper = phinumb[i+1]; // Upper vertex of edge double phiA = (phiUpper - phiLower) / 2.0; double phiB = (phiUpper + phiLower) / 2.0; double thetaLower = theta[numb[i]]; double thetaUpper = theta[numb[i+1]]; double thetaMax = 0.0; Eigen::Vector3d oc = (arcs.col(i) - sph.center) / sph.radius; double oc_norm = oc.norm(); double oc_norm2 = std::pow(oc_norm, 2); for (int j = 0; j < upper_phi; ++j) { // Loop on Gaussian points: phi integration for (int k = 0; k <= 1; ++k) { double ph = (2*k - 1) * phiA * phiRule.abscissa(j) + phiB; double cos_phi = std::cos(ph); double sin_phi = std::sin(ph); if (oc_norm2 < 1.0e-07) { // This should check if oc_norm2 is zero double cotg_thmax = (std::sin(ph-phiLower) / std::tan(thetaUpper) + std::sin(phiUpper-ph) / std::tan( thetaLower)) / std::sin(phiUpper - phiLower); thetaMax = std::atan(1.0 / cotg_thmax); } else { Eigen::Vector3d scratch; scratch << tangent.dot(oc), bitangent.dot(oc), normal.dot(oc); double aa = std::pow(tangent.dot(oc)*cos_phi + bitangent.dot(oc)*sin_phi, 2) + std::pow(normal.dot(oc), 2); double bb = -normal.dot(oc) * oc_norm2; double cc = std::pow(oc_norm2, 2) - std::pow(tangent.dot(oc)*cos_phi + bitangent.dot(oc)*sin_phi, 2); double ds = std::pow(bb, 2) - aa*cc; if (ds < 0.0) ds = 0.0; double cs = (-bb + std::sqrt(ds)) / aa; if (cs > 1.0) cs = 1.0; if (cs < -1.0) cs = 1.0; thetaMax = std::acos(cs); } double thetaA = thetaMax / 2.0; double scratch = 0.0; if (!(thetaMax < 1.0e-08)) { for (int l = 0; l < upper_theta; ++l) { // Loop on Gaussian points: theta integration for (int m = 0; m <= 1; ++m) { double th = (2*m - 1) * thetaA * thetaRule.abscissa(l) + thetaA; double cos_theta = std::cos(th); double sin_theta = std::sin(th); Eigen::Vector3d point; point(0) = tangent(0) * sin_theta * cos_phi + bitangent(0) * sin_theta * sin_phi + normal(0) * (cos_theta - 1.0); point(1) = tangent(1) * sin_theta * cos_phi + bitangent(1) * sin_theta * sin_phi + normal(1) * (cos_theta - 1.0); point(2) = tangent(2) * sin_theta * cos_phi + bitangent(2) * sin_theta * sin_phi + normal(2) * (cos_theta - 1.0); double value = F(e.normal(), Eigen::Vector3d::Zero(), point); // Evaluate integrand at Gaussian point scratch += std::pow(sph.radius, 2) * value * sin_theta * thetaA * thetaRule.weight(l); } } result += scratch * phiA * phiRule.weight(j); } } } } return result; }
void compare(CompareCmd *env, Field *field_a, Field *field_b) { const bool debug = false; if (env->verbose) { cout << "Comparing Field against Field" << endl; } assert(env->quadrature != 0); QuadratureRule *qr = env->quadrature; Residuals *residuals = env->residuals; // dimensions int nel = qr->meshPart->nel; int nq = qr->points->n_points(); int ndim = field_a->n_dim(); int valdim = field_a->n_rank(); // field values at quadrature points Points phi_a, phi_b; double *values_a = new double[nq * valdim]; double *values_b = new double[nq * valdim]; phi_a.set_data(values_a, nq, valdim); phi_b.set_data(values_b, nq, valdim); residuals->reset_accumulator(); env->start_timer(nel, "elts"); // main loop for (int e = 0; e < nel; e++) { qr->select_cell(e); for (int q = 0; q < nq; q++) { double *globalPoint = (*(qr->points))[q]; field_a->eval(globalPoint, &values_a[q*valdim]); field_b->eval(globalPoint, &values_b[q*valdim]); if (debug) { int j; cerr << e << " " << q << " "; for (j = 0; j < ndim; j++) { cerr << globalPoint[j] << " "; } cerr << "\t"; for (j = 0; j < valdim; j++) { cerr << values_a[valdim*q + j] << " "; } cerr << "\t"; for (j = 0; j < valdim; j++) { cerr << values_b[valdim*q + j] << " "; } cerr << endl; } } double err2 = qr->L2(phi_a, phi_b); double vol = qr->meshPart->cell->volume(); //residuals->update(e, sqrt(err2)/vol); //residuals->update(e, sqrt(err2)); residuals->update(e, sqrt(err2), vol); env->update_timer(e); } env->end_timer(); // clean up delete [] values_a; delete [] values_b; }