SundanceFeketeQuadrature.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
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 /* declare LAPACK subroutines */
00055 extern "C"
00056 {
00057 /* matrix-vector multiplication */
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 /* constructor */
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   //int verb = 4;
00153   Tabs tabs;
00154 
00155   // Cache lookup
00156   /*if (mesh.IsSpecialWeightValid() && mesh.hasSpecialWeight(cellDim, cellLID))
00157   {
00158     weightsChanged = true;
00159     mesh.getSpecialWeight(cellDim, cellLID, quadWeights);
00160     SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedWeights Found cached weights for cell LID " << cellLID)
00161     return;
00162   }*/
00163 
00164   // Maximal cell type
00165   CellType maxCellType = mesh.cellType(mesh.spatialDim());
00166 
00167   switch (maxCellType)
00168   {
00169   // We have a triangle based mesh
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   // ToDo: What tolerance?
00228   double tol = 1.e-8;
00229   weightsChanged = true;
00230 
00231   // For pushForward() we need the cellLID in an array
00232   Array<int> cellLIDs(1);
00233   cellLIDs[0] = cellLID;
00234 
00235   // Intersection points (parameters) with the edges of triangle
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   // Create stack and put the initial triangle on stack
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   // Number of investigated triangles
00256   unsigned int nTris = 0;
00257 
00258   while (s.size() >= 3)
00259   {
00260     // Increment number of triangles investigated
00261     ++nTris;
00262 
00263     SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedTriangleWeights Current number of triangles on stack: " << sa.size());
00264 
00265     // Integration results
00266     bool refine = false;
00267     Array<double> results1(originalWeights.size());
00268     Array<double> results2(originalWeights.size());
00269 
00270     // Fetch the coordinates of current triangle from stack
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     // Intersection points (parameters) with the edges of triangle
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     //  Determine kind of intersection
00286     Point x, xref;
00287     Point vec1, vec1ref;
00288     Point vec2, vec2ref;
00289     bool xInOmega = false;
00290 
00291     // 'No intersection' is also handled here
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     // If we found a case we can deal with, calculate the integrals
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         // Check results
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     // Refine (either because of lacking accuracy or strange intersections)
00359     if (refine)
00360     {
00361       // Divide triangle into 4 smaller ones (introduce new nodes at the
00362       // center of each edge)
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     // We found an accurate solution to that part of the triangle!
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   } // Stack depleted here! We're done.
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   // Verbosity
00412   int verb = 0;
00413   Tabs tabs;
00414 
00415   // ToDo: What tolerance?
00416   double tol = 1.e-8;
00417 
00418   // Initialization
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   // For pushForward() we need the cellLID in an array
00428   Array<int> cellLIDs(1);
00429   cellLIDs[0] = cellLID;
00430   SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights: Current cell LID " << cellLID)
00431 
00432   //        IV
00433   //   2 __________ 3
00434   //    |          |
00435   //    |          |
00436   // II |          | III
00437   //    |__________|
00438   //   0            1
00439   //         I
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   // Create stack and put the initial quad
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   // Number of investigated quads
00457   unsigned int nQuads = 0;
00458 
00459   while (s.size() >= 4)
00460   {
00461     // Increment number of quads investigated
00462     ++nQuads;
00463     SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::getAdaptedQuadWeights: Current number of quads on stack: " << sa.size())
00464 
00465     // Integration results
00466     bool refine = false;
00467     bool xInOmega = false;
00468     Array<double> results1(originalWeights.size());
00469     Array<double> results2(originalWeights.size());
00470 
00471     // Fetch the coordinates of current quad from stack
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     // Intersection points (parameters) with the edges of triangle
00482     for (int jj = 0 ; jj < 4 ; jj++ ) {
00483       globalCurve.returnIntersect(nodes[edgeIndex[jj][0]], nodes[edgeIndex[jj][1]], nIntEdge[jj], IntEdgePars[jj] );
00484   /*    if ( nIntEdge[jj] == 0 ) {
00485         x = nodes[edgeIndex[jj][0]];
00486         vec1 =
00487         vec2 =
00488       }
00489   */  }
00490 
00491     //  Determine kind of intersection
00492     Point x, xref;
00493     Point vec1, vec1ref;
00494     Point vec2, vec2ref;
00495 
00496     // Baseline is not intersected
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     // If we found a case we can deal with, calculate the integrals
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         // Check results
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     // Refine (either because of lacking accuracy or strange intersections)
00561     if (refine)
00562     {
00563       // Divide quad into 4 smaller ones (introduce new nodes at the
00564       // center of each edge)
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     // We found an accurate solution to that part of the triangle!
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   } // Stack depleted here! We're done.
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     // Prepare output array
00630     integrals.resize((order() + 1) * (order() + 2) / 2);
00631     for (int i = 0; i < integrals.size(); i++)
00632       integrals[i] = 0.0;
00633 
00634     // Get 'inner' integration points (along a line)
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     // Calculate intersection points of 'integration ray' with curve
00645     // Here one needs physical coordinates because of the curve
00646     for (int edgePos = 0; edgePos < nrInnerQuadPts; edgePos++)
00647     {
00648       // Direction of current integration
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; // w/o an intersection we integrate the whole line
00660       if (nrIntersect == 1)
00661       {
00662         mu = t[0];
00663       }
00664       else if (nrIntersect >= 2)
00665       {
00666         // More than one intersection -> We have to refine!
00667         integrals.resize(0);
00668         return;
00669       }
00670 
00671       // Array for values of basis functions at inner integration points
00672       Array<double> innerIntegrals(integrals.size());
00673       for (int i = 0; i < innerIntegrals.size(); i++)
00674         innerIntegrals[i] = 0.0;
00675 
00676       // We follow one of the rays (in reference coordinates)
00677       for (int rayPos = 0; rayPos < nrInnerQuadPts; rayPos++)
00678       {
00679         Point q = xref + mu * innerQuadPts[rayPos] * rayref;
00680 
00681         // Evaluate all basis functions at quadrature point
00682         Array<double> funcVals;
00683         evaluateAllBasisFunctions(TriangleCell, q, funcVals);
00684 
00685         // Do quadrature for all basis functions
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     // We calculated on parts of the triangle -> Scale to right size
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     // Prepare output array
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     // Get 'inner' integration points (along a line)
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     // We assume: no intersection along first axis
00720     for (int xPos = 0; xPos < nrInnerQuadPts; xPos++)
00721     {
00722       // Direction of current integration
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       // Intersection along second axis?
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; // w/o an intersection we integrate the whole line
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         // More than one intersection -> We have to refine!
00744         integrals.resize(0);
00745         SUNDANCE_MSG3(verb, tabs << "FeketeQuadrature::integrateRegion: More than one intersection -> Abort!")
00746 
00747         return;
00748       }
00749 
00750       // Array for values of basis functions at inner integration points
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         // Evaluate all basis functions at quadrature point
00761         Array<double> funcVals;
00762         evaluateAllBasisFunctions(QuadCell, y_curref, funcVals);
00763 
00764         // Do quadrature for all basis functions
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     // Scale to right size
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     // Coefficients in _basisCoeffs together with PKD polynomials form
00799     // a Lagrange basis at Fekete points
00800     if (!_hasBasisCoeffs)
00801     {
00802       FeketeTriangleQuadrature::computeBasisCoeffs(order(), _basisCoeffs);
00803       _hasBasisCoeffs = true;
00804     }
00805 
00806     // KL added explicit cast of sqrt argument to double to allow
00807     // compilation on windows.
00808     // One has nFeketePts basis functions
00809     int nFeketePts = sqrt((double) _basisCoeffs.size());
00810     result.resize(nFeketePts);
00811 
00812     // Determine values of all PKD polynomials at evaluation point q
00813     Array<double> pkdVals(nFeketePts);
00814     FeketeTriangleQuadrature::evalPKDpolynomials(order(), q[0], q[1],
00815         &(pkdVals[0]));
00816 
00817     // For each Lagrange basis function, sum up weighted PKD polynomials
00818     // (The weights are found in _basisCoeffs)
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     // Coefficients in _basisCoeffs form a Lagrange basis at Fekete points
00830     if (!_hasBasisCoeffs)
00831     {
00832       FeketeQuadQuadrature::computeBasisCoeffs(order(), _basisCoeffs);
00833       _hasBasisCoeffs = true;
00834     }
00835 
00836     // KL added explicit cast of sqrt argument to double to allow
00837     // compilation on windows.
00838     // One has nFeketePts basis functions
00839     int nFeketePts = sqrt((double) _basisCoeffs.size());
00840     result.resize(nFeketePts);
00841 
00842     // Determine values of all polynomials at evaluation point q
00843     Array<double> polVals(nFeketePts);
00844     FeketeQuadQuadrature::evalPolynomials(nFeketePts, q[0], q[1],
00845         &(polVals[0]));
00846 
00847     // For each Lagrange basis function, sum up weighted polynomials
00848     // (The weights are found in _basisCoeffs)
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 }

Site Contact