00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "SundanceFeketeBrickQuadrature.hpp"
00043 #include "SundanceFeketeQuadQuadrature.hpp"
00044 #include "SundanceFeketeQuadrature.hpp"
00045 #include "SundanceFeketeTriangleQuadrature.hpp"
00046 #include "SundanceGaussLobatto1D.hpp"
00047 #include "SundanceOut.hpp"
00048 #include "PlayaTabs.hpp"
00049 #include <stack>
00050
00051 using namespace Sundance;
00052 using namespace Teuchos;
00053
00054
00055 extern "C"
00056 {
00057
00058 void dgemv_(char *trans, int *m, int *n, double *alpha, double *a, int *lda,
00059 double *x, int *incx, double *beta, double *y, int *incy);
00060 }
00061
00062
00063 FeketeQuadrature::FeketeQuadrature(int order) :
00064 QuadratureFamilyBase(order)
00065 {
00066 _hasBasisCoeffs = false;
00067 }
00068
00069 XMLObject FeketeQuadrature::toXML() const
00070 {
00071 XMLObject rtn("FeketeQuadrature");
00072 rtn.addAttribute("order", Teuchos::toString(order()));
00073 return rtn;
00074 }
00075
00076 void FeketeQuadrature::getLineRule(Array<Point>& quadPoints,
00077 Array<double>& quadWeights) const
00078 {
00079 int p = order() + 3;
00080 p = p + (p % 2);
00081 int n = p / 2;
00082
00083 quadPoints.resize(n);
00084 quadWeights.resize(n);
00085
00086 GaussLobatto1D q1(n, 0.0, 1.0);
00087
00088 for (int i = 0; i < n; i++)
00089 {
00090 quadWeights[i] = q1.weights()[i];
00091 quadPoints[i] = Point(q1.nodes()[i]);
00092 }
00093 }
00094
00095 void FeketeQuadrature::getTriangleRule(Array<Point>& quadPoints,
00096 Array<double>& quadWeights) const
00097 {
00098 Array<double> x;
00099 Array<double> y;
00100 Array<double> w;
00101
00102 FeketeTriangleQuadrature::getPoints(order(), w, x, y);
00103 quadPoints.resize(w.length());
00104 quadWeights.resize(w.length());
00105 for (int i = 0; i < w.length(); i++)
00106 {
00107 quadWeights[i] = 0.5 * w[i];
00108 quadPoints[i] = Point(x[i], y[i]);
00109 }
00110 }
00111
00112 void FeketeQuadrature::getQuadRule(Array<Point>& quadPoints,
00113 Array<double>& quadWeights) const
00114 {
00115 Array<double> x;
00116 Array<double> y;
00117 Array<double> w;
00118
00119 FeketeQuadQuadrature::getPoints(order(), w, x, y);
00120 quadPoints.resize(w.length());
00121 quadWeights.resize(w.length());
00122 for (int i = 0; i < w.length(); i++)
00123 {
00124 quadWeights[i] = w[i];
00125 quadPoints[i] = Point(x[i], y[i]);
00126 }
00127 }
00128
00129 void FeketeQuadrature::getBrickRule(Array<Point>& quadPoints,
00130 Array<double>& quadWeights) const
00131 {
00132 Array<double> x;
00133 Array<double> y;
00134 Array<double> z;
00135 Array<double> w;
00136
00137 FeketeBrickQuadrature::getPoints(order(), w, x, y, z);
00138 quadPoints.resize(w.length());
00139 quadWeights.resize(w.length());
00140 for (int i = 0; i < w.length(); i++)
00141 {
00142 quadWeights[i] = w[i];
00143 quadPoints[i] = Point(x[i], y[i], z[i]);
00144 }
00145 }
00146
00147 void FeketeQuadrature::getAdaptedWeights(const CellType& cellType, int cellDim,
00148 int cellLID, int facetIndex, const Mesh& mesh, const ParametrizedCurve&
00149 globalCurve, Array<Point>& quadPoints, Array<double>& quadWeights,
00150 bool& weightsChanged) const
00151 {
00152
00153 Tabs tabs;
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 CellType maxCellType = mesh.cellType(mesh.spatialDim());
00166
00167 switch (maxCellType)
00168 {
00169
00170 case TriangleCell:
00171 {
00172 switch (cellType)
00173 {
00174 case TriangleCell:
00175 {
00176 getAdaptedTriangleWeights(cellLID, mesh, globalCurve, quadPoints,
00177 quadWeights, weightsChanged);
00178 break;
00179 }
00180 default:
00181 #ifndef TRILINOS_7
00182 SUNDANCE_ERROR ("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for submaximal cell " << maxCellType << " in a triangle mesh")
00183 ;
00184 #else
00185 SUNDANCE_ERROR7("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for submaximal cell " << maxCellType << " in a triangle mesh");
00186 #endif
00187 }
00188 break;
00189 }
00190 case QuadCell:
00191 {
00192 switch(cellType)
00193 {
00194 case QuadCell:
00195 {
00196 getAdaptedQuadWeights(cellLID, mesh, globalCurve, quadPoints,
00197 quadWeights, weightsChanged);
00198 break;
00199 }
00200 default:
00201 #ifndef TRILINOS_7
00202 SUNDANCE_ERROR ("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for submaximal cell " << maxCellType << " in a triangle mesh")
00203 ;
00204 #else
00205 SUNDANCE_ERROR7("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for submaximal cell " << maxCellType << " in a triangle mesh");
00206 #endif
00207 }
00208 break;
00209 }
00210 default:
00211 #ifndef TRILINOS_7
00212 SUNDANCE_ERROR("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for cell type " << cellType)
00213 ;
00214 #else
00215 SUNDANCE_ERROR7("getAdaptedWeights rule for ACI(Adaptive Cell Integration) not available for cell type " << cellType);
00216 #endif
00217 }
00218 }
00219
00220 void FeketeQuadrature::getAdaptedTriangleWeights(int cellLID, const Mesh& mesh,
00221 const ParametrizedCurve& globalCurve, Array<Point>& quadPoints, Array<
00222 double>& quadWeights, bool& weightsChanged) const
00223 {
00224 int verb = 0;
00225 Tabs tabs;
00226
00227
00228 double tol = 1.e-8;
00229 weightsChanged = true;
00230
00231
00232 Array<int> cellLIDs(1);
00233 cellLIDs[0] = cellLID;
00234
00235
00236 Array<double> ip01, ip02, ip12;
00237 int nr_ip01, nr_ip02, nr_ip12;
00238
00239 Array<double> originalWeights = quadWeights;
00240 ParametrizedCurve noCurve = new DummyParametrizedCurve();
00241 Array<double> integrals(originalWeights.size());
00242 for (int i = 0; i < integrals.size(); i++)
00243 integrals[i] = 0.0;
00244
00245
00246 std::stack<Point> s;
00247 std::stack<double> sa;
00248 s.push(Point(0.0, 0.0));
00249 s.push(Point(1.0, 0.0));
00250 s.push(Point(0.0, 1.0));
00251 sa.push(0.5);
00252 Array<Point> nodes;
00253 Array<Point> nodesref(3);
00254
00255
00256 unsigned int nTris = 0;
00257
00258 while (s.size() >= 3)
00259 {
00260
00261 ++nTris;
00262
00263 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedTriangleWeights Current number of triangles on stack: " << sa.size());
00264
00265
00266 bool refine = false;
00267 Array<double> results1(originalWeights.size());
00268 Array<double> results2(originalWeights.size());
00269
00270
00271 double area = sa.top();
00272 sa.pop();
00273 for (int i = 2; i >= 0; i--)
00274 {
00275 nodesref[i] = s.top();
00276 s.pop();
00277 }
00278 mesh.pushForward(2, cellLIDs, nodesref, nodes);
00279
00280
00281 globalCurve.returnIntersect(nodes[0], nodes[1], nr_ip01, ip01);
00282 globalCurve.returnIntersect(nodes[0], nodes[2], nr_ip02, ip02);
00283 globalCurve.returnIntersect(nodes[1], nodes[2], nr_ip12, ip12);
00284
00285
00286 Point x, xref;
00287 Point vec1, vec1ref;
00288 Point vec2, vec2ref;
00289 bool xInOmega = false;
00290
00291
00292 if ((nr_ip01 + nr_ip02 + nr_ip12 == 0) || (nr_ip01 == 0 && nr_ip02 == 0
00293 && nr_ip12 == 1) || (nr_ip01 == 1 && nr_ip02 == 1 && nr_ip12
00294 == 0))
00295 {
00296 x = nodes[0];
00297 vec1 = nodes[2] - nodes[0];
00298 vec2 = nodes[1] - nodes[0];
00299 xref = nodesref[0];
00300 vec1ref = nodesref[2] - nodesref[0];
00301 vec2ref = nodesref[1] - nodesref[0];
00302 }
00303 else if ((nr_ip01 == 0 && nr_ip02 == 1 && nr_ip12 == 0) || (nr_ip12
00304 == 1 && nr_ip01 == 1 && nr_ip02 == 0))
00305 {
00306 x = nodes[1];
00307 vec1 = nodes[0] - nodes[1];
00308 vec2 = nodes[2] - nodes[1];
00309 xref = nodesref[1];
00310 vec1ref = nodesref[0] - nodesref[1];
00311 vec2ref = nodesref[2] - nodesref[1];
00312 }
00313 else if ((nr_ip01 == 1 && nr_ip02 == 0 && nr_ip12 == 0) || (nr_ip02
00314 == 1 && nr_ip12 == 1 && nr_ip01 == 0))
00315 {
00316 x = nodes[2];
00317 vec1 = nodes[1] - nodes[2];
00318 vec2 = nodes[0] - nodes[2];
00319 xref = nodesref[2];
00320 vec1ref = nodesref[1] - nodesref[2];
00321 vec2ref = nodesref[0] - nodesref[2];
00322 }
00323 else
00324 {
00325 refine = true;
00326 }
00327
00328
00329 if (!refine)
00330 {
00331 if (globalCurve.curveEquation(x) < 0)
00332 xInOmega = true;
00333 integrateRegion(TriangleCell, 2, order() + 1, x, xref, vec1, vec2,
00334 vec1ref, vec2ref, globalCurve, results1);
00335 if (results1.size() == 0)
00336 {
00337 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedTriangleWeights Unknown error in integration. Refine.")
00338 refine = true;
00339 }
00340 else
00341 {
00342 integrateRegion(TriangleCell, 2, order() + 2, x, xref, vec1,
00343 vec2, vec1ref, vec2ref, globalCurve, results2);
00344
00345
00346 for (int i = 0; i < results1.size(); i++)
00347 {
00348 if (::fabs(results2[i] - results1[i]) > sqrt(area * tol))
00349 {
00350 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedTriangleWeights Insufficient accuracy. Refine.")
00351 refine = true;
00352 break;
00353 }
00354 }
00355 }
00356 }
00357
00358
00359 if (refine)
00360 {
00361
00362
00363 s.push(nodesref[0]);
00364 s.push((nodesref[0] + nodesref[1]) / 2);
00365 s.push((nodesref[0] + nodesref[2]) / 2);
00366 sa.push(area / 4);
00367 s.push((nodesref[0] + nodesref[1]) / 2);
00368 s.push(nodesref[1]);
00369 s.push((nodesref[1] + nodesref[2]) / 2);
00370 sa.push(area / 4);
00371 s.push((nodesref[0] + nodesref[2]) / 2);
00372 s.push((nodesref[1] + nodesref[2]) / 2);
00373 s.push(nodesref[2]);
00374 sa.push(area / 4);
00375 s.push((nodesref[0] + nodesref[2]) / 2);
00376 s.push((nodesref[0] + nodesref[1]) / 2);
00377 s.push((nodesref[1] + nodesref[2]) / 2);
00378 sa.push(area / 4);
00379 continue;
00380 }
00381
00382
00383 if (xInOmega)
00384 {
00385 for (int i = 0; i < integrals.size(); i++)
00386 integrals[i] += results2[i];
00387 }
00388 else
00389 {
00390 integrateRegion(TriangleCell, 2, order() + 1, x, xref, vec1, vec2,
00391 vec1ref, vec2ref, noCurve, results1);
00392 for (int i = 0; i < integrals.size(); i++)
00393 integrals[i] += (results1[i] - results2[i]);
00394 }
00395 }
00396
00397 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedTriangleWeights Calculations in cell " << cellLID << " completed. " << nTris << " triangle(s) used.");
00398
00399 Array<double> alphas;
00400 globalCurve.getIntegrationParams(alphas);
00401 for (int i = 0; i < quadWeights.size(); i++)
00402 quadWeights[i] = alphas[1] * integrals[i] + alphas[0]
00403 * (originalWeights[i] - integrals[i]);
00404 mesh.setSpecialWeight(2, cellLID, quadWeights);
00405 }
00406
00407 void FeketeQuadrature::getAdaptedQuadWeights(int cellLID, const Mesh& mesh,
00408 const ParametrizedCurve& globalCurve, Array<Point>& quadPoints, Array<
00409 double>& quadWeights, bool& weightsChanged) const
00410 {
00411
00412 int verb = 0;
00413 Tabs tabs;
00414
00415
00416 double tol = 1.e-8;
00417
00418
00419 weightsChanged = true;
00420 Array<double> originalWeights = quadWeights;
00421
00422 ParametrizedCurve noCurve = new DummyParametrizedCurve();
00423 Array<double> integrals(originalWeights.size());
00424 for (int i = 0; i < integrals.size(); i++)
00425 integrals[i] = 0.0;
00426
00427
00428 Array<int> cellLIDs(1);
00429 cellLIDs[0] = cellLID;
00430 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights: Current cell LID " << cellLID)
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 Array<int> nIntEdge(4);
00442 Array<Array<double> > IntEdgePars(4);
00443 int edgeIndex[4][2] = { {0,1} , {0,2} , {1,3} , {2,3} };
00444
00445
00446 std::stack<Point> s;
00447 std::stack<double> sa;
00448 s.push(Point(0.0, 0.0));
00449 s.push(Point(1.0, 0.0));
00450 s.push(Point(0.0, 1.0));
00451 s.push(Point(1.0, 1.0));
00452 sa.push(1.);
00453 Array<Point> nodes;
00454 Array<Point> nodesref(4);
00455
00456
00457 unsigned int nQuads = 0;
00458
00459 while (s.size() >= 4)
00460 {
00461
00462 ++nQuads;
00463 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights: Current number of quads on stack: " << sa.size())
00464
00465
00466 bool refine = false;
00467 bool xInOmega = false;
00468 Array<double> results1(originalWeights.size());
00469 Array<double> results2(originalWeights.size());
00470
00471
00472 double area = sa.top();
00473 sa.pop();
00474 for (int i = 3; i >= 0; i--)
00475 {
00476 nodesref[i] = s.top();
00477 s.pop();
00478 }
00479 mesh.pushForward(2, cellLIDs, nodesref, nodes);
00480
00481
00482 for (int jj = 0 ; jj < 4 ; jj++ ) {
00483 globalCurve.returnIntersect(nodes[edgeIndex[jj][0]], nodes[edgeIndex[jj][1]], nIntEdge[jj], IntEdgePars[jj] );
00484
00485
00486
00487
00488
00489 }
00490
00491
00492 Point x, xref;
00493 Point vec1, vec1ref;
00494 Point vec2, vec2ref;
00495
00496
00497 if ( nIntEdge[0] == 0 )
00498 {
00499 x = nodes[0];
00500 vec1 = nodes[1] - nodes[0];
00501 vec2 = nodes[2] - nodes[0];
00502 xref = nodesref[0];
00503 vec1ref = nodesref[1] - nodesref[0];
00504 vec2ref = nodesref[2] - nodesref[0];
00505 }
00506 else if ( nIntEdge[1] == 0 )
00507 {
00508 x = nodes[2];
00509 vec1 = nodes[0] - nodes[2];
00510 vec2 = nodes[3] - nodes[2];
00511 xref = nodesref[2];
00512 vec1ref = nodesref[0] - nodesref[2];
00513 vec2ref = nodesref[3] - nodesref[2];
00514 }
00515 else if ( nIntEdge[2] == 0 )
00516 {
00517 x = nodes[1];
00518 vec1 = nodes[3] - nodes[1];
00519 vec2 = nodes[0] - nodes[1];
00520 xref = nodesref[1];
00521 vec1ref = nodesref[3] - nodesref[1];
00522 vec2ref = nodesref[0] - nodesref[1];
00523 }
00524 else
00525 {
00526 refine = true;
00527 }
00528
00529
00530 if (!refine)
00531 {
00532 if (globalCurve.curveEquation(x) < 0)
00533 xInOmega = true;
00534 integrateRegion(QuadCell, 2, order() + 1, x, xref, vec1, vec2,
00535 vec1ref, vec2ref, globalCurve, results1);
00536 if (results1.size() == 0)
00537 {
00538 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights Unknown error in integration. Refine.")
00539 refine = true;
00540 }
00541 else
00542 {
00543 integrateRegion(QuadCell, 2, order() + 2, x, xref, vec1,
00544 vec2, vec1ref, vec2ref, globalCurve, results2);
00545
00546
00547 double reltol = ::sqrt(area * tol);
00548 for (int i = 0; i < results1.size(); i++)
00549 {
00550 if (::fabs(results2[i] - results1[i]) > reltol)
00551 {
00552 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights Insufficient accuracy. Refine.")
00553 refine = true;
00554 break;
00555 }
00556 }
00557 }
00558 }
00559
00560
00561 if (refine)
00562 {
00563
00564
00565 s.push(nodesref[0]);
00566 s.push((nodesref[0] + nodesref[1]) / 2);
00567 s.push((nodesref[0] + nodesref[2]) / 2);
00568 s.push((nodesref[0] + nodesref[3]) / 2);
00569 sa.push(area / 4);
00570 s.push((nodesref[0] + nodesref[1]) / 2);
00571 s.push(nodesref[1]);
00572 s.push((nodesref[1] + nodesref[2]) / 2);
00573 s.push((nodesref[1] + nodesref[3]) / 2);
00574 sa.push(area / 4);
00575 s.push((nodesref[0] + nodesref[2]) / 2);
00576 s.push((nodesref[1] + nodesref[2]) / 2);
00577 s.push(nodesref[2]);
00578 s.push((nodesref[2] + nodesref[3]) / 2);
00579 sa.push(area / 4);
00580 s.push((nodesref[0] + nodesref[3]) / 2);
00581 s.push((nodesref[1] + nodesref[3]) / 2);
00582 s.push((nodesref[2] + nodesref[3]) / 2);
00583 s.push(nodesref[3]);
00584 sa.push(area / 4);
00585 continue;
00586 }
00587
00588
00589 if (xInOmega)
00590 {
00591 for (int i = 0; i < integrals.size(); i++)
00592 integrals[i] += results2[i];
00593 }
00594 else
00595 {
00596 integrateRegion(QuadCell, 2, order() + 1, x, xref, vec1, vec2,
00597 vec1ref, vec2ref, noCurve, results1);
00598 for (int i = 0; i < integrals.size(); i++)
00599 integrals[i] += (results1[i] - results2[i]);
00600 }
00601 }
00602
00603 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights Calculations in cell " << cellLID << " completed. " << nQuads << " quad(s) used.");
00604
00605 Array<double> alphas;
00606 globalCurve.getIntegrationParams(alphas);
00607 for (int i = 0; i < quadWeights.size(); i++)
00608 quadWeights[i] = alphas[1] * integrals[i] + alphas[0]
00609 * (originalWeights[i] - integrals[i]);
00610 if (verb > 1 ) {
00611 writeTable(Out::os(), tabs, quadWeights, quadWeights.size());
00612 }
00613 mesh.setSpecialWeight(2, cellLID, quadWeights);
00614 }
00615
00616 void FeketeQuadrature::integrateRegion(const CellType& cellType,
00617 const int cellDim, const int innerOrder, const Point& x,
00618 const Point& xref, const Point& vec1, const Point& vec2,
00619 const Point& vec1ref, const Point& vec2ref,
00620 const ParametrizedCurve& curve, Array<double>& integrals) const
00621 {
00622 int verb = 0;
00623 Tabs tabs;
00624
00625 switch (cellType)
00626 {
00627 case TriangleCell:
00628 {
00629
00630 integrals.resize((order() + 1) * (order() + 2) / 2);
00631 for (int i = 0; i < integrals.size(); i++)
00632 integrals[i] = 0.0;
00633
00634
00635 int nrInnerQuadPts = innerOrder + 3;
00636 nrInnerQuadPts = (nrInnerQuadPts + nrInnerQuadPts % 2) / 2;
00637 GaussLobatto1D innerQuad(nrInnerQuadPts, 0.0, 1.0);
00638
00639 Array<double> innerQuadPts(nrInnerQuadPts);
00640 Array<double> innerQuadWgts(nrInnerQuadPts);
00641 innerQuadPts = innerQuad.nodes();
00642 innerQuadWgts = innerQuad.weights();
00643
00644
00645
00646 for (int edgePos = 0; edgePos < nrInnerQuadPts; edgePos++)
00647 {
00648
00649 Point ray = innerQuadPts[edgePos] * vec1 + (1.0
00650 - innerQuadPts[edgePos]) * vec2;
00651 Point rayref = innerQuadPts[edgePos] * vec1ref + (1.0
00652 - innerQuadPts[edgePos]) * vec2ref;
00653
00654 int nrIntersect = 0;
00655 Array<double> t;
00656 Point rayEnd = x + ray;
00657 curve.returnIntersect(x, rayEnd, nrIntersect, t);
00658
00659 double mu = 1.0;
00660 if (nrIntersect == 1)
00661 {
00662 mu = t[0];
00663 }
00664 else if (nrIntersect >= 2)
00665 {
00666
00667 integrals.resize(0);
00668 return;
00669 }
00670
00671
00672 Array<double> innerIntegrals(integrals.size());
00673 for (int i = 0; i < innerIntegrals.size(); i++)
00674 innerIntegrals[i] = 0.0;
00675
00676
00677 for (int rayPos = 0; rayPos < nrInnerQuadPts; rayPos++)
00678 {
00679 Point q = xref + mu * innerQuadPts[rayPos] * rayref;
00680
00681
00682 Array<double> funcVals;
00683 evaluateAllBasisFunctions(TriangleCell, q, funcVals);
00684
00685
00686 for (int i = 0; i < funcVals.size(); i++)
00687 innerIntegrals[i] += funcVals[i] * innerQuadWgts[rayPos]
00688 * innerQuadPts[rayPos];
00689 }
00690 for (int j = 0; j < integrals.size(); j++)
00691 integrals[j] += innerQuadWgts[edgePos] * mu * mu
00692 * innerIntegrals[j];
00693 }
00694
00695
00696 double det = ::fabs(vec1ref[0] * vec2ref[1] - vec2ref[0] * vec1ref[1]);
00697 for (int j = 0; j < integrals.size(); j++)
00698 integrals[j] *= det;
00699 } break;
00700
00701 case QuadCell:
00702 {
00703
00704 integrals.resize((order() + 1) * (order() + 1));
00705 for (int i = 0; i < integrals.size(); i++)
00706 integrals[i] = 0.0;
00707 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Initializing quadrature on a QuadCell")
00708
00709
00710 int nrInnerQuadPts = innerOrder + 3;
00711 nrInnerQuadPts = (nrInnerQuadPts + nrInnerQuadPts % 2) / 2;
00712 GaussLobatto1D innerQuad(nrInnerQuadPts, 0.0, 1.0);
00713
00714 Array<double> innerQuadPts(nrInnerQuadPts);
00715 Array<double> innerQuadWgts(nrInnerQuadPts);
00716 innerQuadPts = innerQuad.nodes();
00717 innerQuadWgts = innerQuad.weights();
00718
00719
00720 for (int xPos = 0; xPos < nrInnerQuadPts; xPos++)
00721 {
00722
00723 Point x_cur = x + innerQuadPts[xPos] * vec1;
00724 Point x_curref = xref + innerQuadPts[xPos] * vec1ref;
00725
00726 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Integrating at xPos " << xPos << " Ref point " << x_curref)
00727
00728
00729 int nrIntersect = 0;
00730 Array<double> t;
00731 Point x_curEnd = x_cur + vec2;
00732 curve.returnIntersect(x_cur, x_curEnd, nrIntersect, t);
00733 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Nr. of intersections along y: " << t.size())
00734
00735 double mu = 1.0;
00736 if (nrIntersect == 1)
00737 {
00738 mu = t[0];
00739 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Intersection parameter is " << mu)
00740 }
00741 else if (nrIntersect >= 2)
00742 {
00743
00744 integrals.resize(0);
00745 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: More than one intersection -> Abort!")
00746
00747 return;
00748 }
00749
00750
00751 Array<double> innerIntegrals(integrals.size());
00752 for (int jj = 0; jj < innerIntegrals.size(); jj++)
00753 innerIntegrals[jj] = 0.0;
00754
00755 for (int yPos = 0; yPos < nrInnerQuadPts; yPos++)
00756 {
00757 Point y_curref = x_curref + mu * innerQuadPts[yPos] * vec2ref;
00758 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Integrating at yPos " << yPos << " Ref point " << y_curref)
00759
00760
00761 Array<double> funcVals;
00762 evaluateAllBasisFunctions(QuadCell, y_curref, funcVals);
00763
00764
00765 for (int jj = 0; jj < funcVals.size(); jj++)
00766 innerIntegrals[jj] += funcVals[jj] * innerQuadWgts[yPos] * mu;
00767 }
00768 for (int ii = 0; ii < integrals.size(); ii++)
00769 integrals[ii] += innerQuadWgts[xPos] * innerIntegrals[ii];
00770 }
00771
00772
00773 double det = ::fabs(vec1ref[0] * vec2ref[1] - vec2ref[0] * vec1ref[1]);
00774 for (int i = 0; i < integrals.size(); i++)
00775 integrals[i] *= det;
00776 SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: Integration of region finished. Integral values " << integrals)
00777 } break;
00778
00779 default:
00780 #ifndef TRILINOS_7
00781 SUNDANCE_ERROR("FeketeQuadrature::integrateRegion() not available for cell type " << cellType)
00782 ;
00783 #else
00784 SUNDANCE_ERROR7("FeketeQuadrature::integrateRegion() not available for cell type " << cellType);
00785 #endif
00786 }
00787
00788 }
00789
00790 void FeketeQuadrature::evaluateAllBasisFunctions(const CellType cellType,
00791 const Point& q, Array<double>& result) const
00792 {
00793
00794 switch (cellType)
00795 {
00796 case TriangleCell:
00797 {
00798
00799
00800 if (!_hasBasisCoeffs)
00801 {
00802 FeketeTriangleQuadrature::computeBasisCoeffs(order(), _basisCoeffs);
00803 _hasBasisCoeffs = true;
00804 }
00805
00806
00807
00808
00809 int nFeketePts = sqrt((double) _basisCoeffs.size());
00810 result.resize(nFeketePts);
00811
00812
00813 Array<double> pkdVals(nFeketePts);
00814 FeketeTriangleQuadrature::evalPKDpolynomials(order(), q[0], q[1],
00815 &(pkdVals[0]));
00816
00817
00818
00819 char trans = 'N';
00820 double alpha = 1.;
00821 double beta = 0.;
00822 int inc = 1;
00823 ::dgemv_(&trans, &nFeketePts, &nFeketePts, &alpha, &(_basisCoeffs[0]),
00824 &nFeketePts, &(pkdVals[0]), &inc, &beta, &(result[0]), &inc);
00825 break;
00826 }
00827 case QuadCell:
00828 {
00829
00830 if (!_hasBasisCoeffs)
00831 {
00832 FeketeQuadQuadrature::computeBasisCoeffs(order(), _basisCoeffs);
00833 _hasBasisCoeffs = true;
00834 }
00835
00836
00837
00838
00839 int nFeketePts = sqrt((double) _basisCoeffs.size());
00840 result.resize(nFeketePts);
00841
00842
00843 Array<double> polVals(nFeketePts);
00844 FeketeQuadQuadrature::evalPolynomials(nFeketePts, q[0], q[1],
00845 &(polVals[0]));
00846
00847
00848
00849 char trans = 'N';
00850 double alpha = 1.;
00851 double beta = 0.;
00852 int inc = 1;
00853 ::dgemv_(&trans, &nFeketePts, &nFeketePts, &alpha, &(_basisCoeffs[0]),
00854 &nFeketePts, &(polVals[0]), &inc, &beta, &(result[0]), &inc);
00855 break;
00856 }
00857 default:
00858 #ifndef TRILINOS_7
00859 SUNDANCE_ERROR("FeketeQuadrature::evaluateAllBasisFunctions() not available for cell type " << cellType)
00860 ;
00861 #else
00862 SUNDANCE_ERROR7("FeketeQuadrature::evaluateAllBasisFunctions() not available for cell type " << cellType);
00863 #endif
00864 }
00865 }