SundanceAToCPointLocator.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 "SundanceAToCPointLocator.hpp"
00043 #include "SundanceOut.hpp"
00044 #include "PlayaTabs.hpp"
00045 #include "SundanceGeomUtils.hpp"
00046 #include "Teuchos_ScalarTraits.hpp"
00047 #include <queue>
00048 
00049 using namespace Sundance;
00050 using namespace Sundance;
00051 using namespace Sundance;
00052 using namespace Sundance;
00053 using namespace Sundance;
00054 using namespace Sundance;
00055 using namespace Sundance;
00056 using namespace Teuchos;
00057 
00058 
00059 
00060 
00061 
00062 static Time& pointLocatorCtorTimer() 
00063 {
00064   static RCP<Time> rtn 
00065     = TimeMonitor::getNewTimer("point locator ctor"); 
00066   return *rtn;
00067 }
00068 
00069 AToCPointLocator::AToCPointLocator(const Mesh& mesh, 
00070                                    const CellFilter& subdomain,
00071                                    const std::vector<int>& nx)
00072   : dim_(mesh.spatialDim()),
00073     mesh_(mesh),
00074     nFacets_(mesh.numFacets(dim_, 0, 0)),
00075     nx_(nx),
00076     low_(nx.size(), 1.0/ScalarTraits<double>::sfmin()),
00077     high_(nx.size(), -1.0/ScalarTraits<double>::sfmin()),
00078     dx_(nx.size()),
00079     table_(),
00080     subdomain_(subdomain),
00081     neighborSet_()
00082 {
00083   TimeMonitor timer(pointLocatorCtorTimer());
00084   
00085   /* allocate the neighbor set table */
00086   neighborSet_.resize(mesh.numCells(dim_));
00087 
00088   /* first pass to find bounding box */
00089   CellSet cells = subdomain.getCells(mesh);
00090   
00091   for (CellIterator i = cells.begin(); i!= cells.end(); i++)
00092     {
00093       int cellLID = *i;
00094       Array<int> facetLIDs;
00095       Array<int> facetOri;
00096       mesh.getFacetArray(dim_, cellLID, 0, facetLIDs, facetOri);
00097       for (int f=0; f<facetLIDs.size(); f++)
00098         {
00099           Point x = mesh.nodePosition(facetLIDs[f]);
00100           for (int d=0; d<dim_; d++)
00101             {
00102               if (x[d] < low_[d]) low_[d] = x[d];
00103               if (x[d] > high_[d]) high_[d] = x[d];
00104             }
00105         }
00106     }
00107 
00108   /* fudge the bounding box */
00109   for (int d=0; d<dim_; d++)
00110     {
00111       low_[d] -= 0.01 * (high_[d] - low_[d]);
00112       high_[d] += 0.01 * (high_[d] - low_[d]);
00113     }
00114 
00115   /* second pass to put cells in lookup table */
00116 
00117   int s = 1;
00118   for (int d=0; d<dim_; d++) 
00119     {
00120       dx_[d] = (high_[d] - low_[d])/nx_[d];
00121       s *= nx_[d];
00122     }
00123 
00124 
00125   table_ = rcp(new Array<int>(s, -1));
00126 
00127 
00128   Array<int> lowIndex;
00129   Array<int> highIndex;
00130   for (CellIterator i = cells.begin(); i!= cells.end(); i++)
00131     {
00132       int cellLID = *i;
00133       getGridRange(mesh, dim_, cellLID, lowIndex, highIndex);
00134       if (dim_==2)
00135         {
00136           for (int ix=lowIndex[0]; ix<=highIndex[0]; ix++)
00137             {
00138               for (int iy=lowIndex[1]; iy<=highIndex[1]; iy++)
00139                 {
00140                   int index = nx_[1]*ix + iy;
00141                   (*table_)[index] = cellLID;
00142                 }
00143             }
00144         }
00145       else
00146         {
00147           TEUCHOS_TEST_FOR_EXCEPT(true);
00148         }
00149     }
00150 }
00151 
00152 int AToCPointLocator::getGridIndex(const double* x) const 
00153 {
00154   int index = 0;
00155   for (int d=0; d<dim_; d++) 
00156     {
00157       double r = (x[d] - low_[d])/dx_[d];
00158       int ix = (int) floor(r);
00159       index = index*nx_[d] + ix;
00160     }
00161 
00162   return index;
00163 }
00164 
00165 
00166 void AToCPointLocator::getGridRange(const Mesh& mesh, int cellDim, int cellLID,
00167                                     Array<int>& lowIndex, Array<int>& highIndex) const
00168 {
00169   Array<int> facetLIDs;
00170   Array<int> facetOri;
00171   mesh.getFacetArray(cellDim, cellLID, 0, facetLIDs, facetOri);
00172 
00173   lowIndex.resize(cellDim);
00174   highIndex.resize(cellDim);
00175   for (int d=0; d<cellDim; d++) 
00176     {
00177       highIndex[d] = -1;
00178       lowIndex[d] = 1000000; /* This magic number should be much bigger than any 
00179                               * reasonable index size in any one dimension */
00180     }
00181 
00182   for (int f=0; f<facetLIDs.size(); f++)
00183     {
00184       Point x = mesh.nodePosition(facetLIDs[f]);
00185       for (int d=0; d<cellDim; d++)
00186         {
00187           double r = (x[d] - low_[d])/dx_[d];
00188           int ix = (int) floor(r);
00189           if (ix < lowIndex[d]) lowIndex[d] = ix;
00190           if (ix > highIndex[d]) highIndex[d] = ix;
00191         }
00192     }
00193 }
00194                  
00195 
00196 void AToCPointLocator::fillMaximalNeighbors(int cellLID, 
00197                                               const int* facetLID) const
00198 {
00199   if (neighborSet_[cellLID].get()==0)
00200     {
00201       neighborSet_[cellLID] = rcp(new Set<int>());
00202 
00203       for (int f=0; f<nFacets_; f++)
00204         {
00205           Array<int> cofacets;
00206           mesh_.getCofacets(0, facetLID[f], dim_, cofacets);
00207           for (int c=0; c<cofacets.size(); c++)
00208             {
00209               if (cofacets[c] != cellLID) neighborSet_[cellLID]->put(cofacets[c]);
00210             }
00211         }
00212     }
00213 }
00214 
00215 
00216 bool AToCPointLocator::cellContainsPoint(int cellLID, 
00217                                            const double* x, 
00218                                            const int* facetLID) const
00219 {
00220   if (dim_==2)
00221     {
00222       const double* A = mesh_.nodePositionView(facetLID[0]);
00223       const double* B = mesh_.nodePositionView(facetLID[1]);
00224       const double* C = mesh_.nodePositionView(facetLID[2]);
00225       /* first determine whether the three points of the triangle
00226        * are in ccw or cw order. */
00227       double sign = orient2D(A, B, C);
00228       if (sign > 0.0)
00229         {
00230           double s1 = orient2D(A, B, x);
00231           double s2 = orient2D(B, C, x);
00232           double s3 = orient2D(C, A, x);
00233           if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00234           return false;
00235         }
00236       else
00237         {
00238           double s1 = orient2D(A, C, x);
00239           double s2 = orient2D(C, B, x);
00240           double s3 = orient2D(B, A, x);
00241           if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00242           return false;
00243         }
00244     }
00245   else if (dim_==3)
00246     {
00247       TEUCHOS_TEST_FOR_EXCEPT(true);
00248       return false; // -Wall
00249     }
00250   else
00251     {
00252       TEUCHOS_TEST_FOR_EXCEPTION(dim_<=0 || dim_>3, std::runtime_error,
00253                          "invalid point dimension " << dim_);
00254       return false; // -Wall
00255     }
00256 }
00257 
00258 bool AToCPointLocator::cellContainsPoint(int cellLID, 
00259                                          const double* x, 
00260                                          const int* facetLID,
00261                                          double* localCoords) const
00262 {
00263   if (dim_==2)
00264     {
00265       const double* A = mesh_.nodePositionView(facetLID[0]);
00266       const double* B = mesh_.nodePositionView(facetLID[1]);
00267       const double* C = mesh_.nodePositionView(facetLID[2]);
00268       /* first determine whether the three points of the triangle
00269        * are in ccw or cw order. */
00270       double sign = orient2D(A, B, C);
00271       if (sign > 0.0)
00272         {
00273           double s1 = orient2D(A, B, x);
00274           double s2 = orient2D(B, C, x);
00275           double s3 = orient2D(C, A, x);
00276           if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) 
00277             {
00278               double bax = B[0] - A[0];
00279               double bay = B[1] - A[1];
00280               double cax = C[0] - A[0];
00281               double cay = C[1] - A[1];
00282               double delta = bax*cay - bay*cax;
00283               
00284               double xax = x[0] - A[0];
00285               double xay = x[1] - A[1];
00286 
00287               localCoords[0] = (cay*xax - cax*xay)/delta;
00288               localCoords[1] = (bax*xay - bay*xax)/delta;
00289               return true;
00290             }
00291           return false;
00292         }
00293       else
00294         {
00295           double s1 = orient2D(A, C, x);
00296           double s2 = orient2D(C, B, x);
00297           double s3 = orient2D(B, A, x);
00298           if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) 
00299             {
00300               /* swap B and C if cell is CW oriented */
00301               std::cout << "swapping!" << std::endl;
00302               double bax = C[0] - A[0];
00303               double bay = C[1] - A[1];
00304               double cax = B[0] - A[0];
00305               double cay = B[1] - A[1];
00306               double delta = bax*cay - bay*cax;
00307               
00308               double xax = x[0] - A[0];
00309               double xay = x[1] - A[1];
00310 
00311               localCoords[0] = (cay*xax - cax*xay)/delta;
00312               localCoords[1] = (bax*xay - bay*xax)/delta;
00313               return true;
00314             }
00315           return false;
00316         }
00317     }
00318   else if (dim_==3)
00319     {
00320       TEUCHOS_TEST_FOR_EXCEPT(true);
00321       return false; // -Wall
00322     }
00323   else
00324     {
00325       TEUCHOS_TEST_FOR_EXCEPTION(dim_<=0 || dim_>3, std::runtime_error,
00326                          "invalid point dimension " << dim_);
00327       return false; // -Wall
00328     }
00329 }
00330 
00331 int AToCPointLocator::findEnclosingCell(int initialGuessLID,
00332                                         const double* x) const
00333 {
00334   std::queue<int> Q;
00335   Set<int> repeats;
00336   int d = mesh_.spatialDim();
00337   Array<int> facets(mesh_.numFacets(d, 0, 0));
00338   Array<int> facetOr(facets.size());
00339 
00340   Q.push(initialGuessLID);
00341 
00342   while (!Q.empty())
00343     {
00344       int next = Q.front();
00345       Q.pop();
00346       if (repeats.contains(next)) continue;
00347       
00348 //      const int* facets = mesh_.elemZeroFacetView(next);
00349       mesh_.getFacetArray(d, next, 0, facets, facetOr);
00350       if (cellContainsPoint(next, x, &(facets[0]))) return next;
00351       repeats.put(next);
00352       
00353       fillMaximalNeighbors(next, &(facets[0]));
00354       
00355       for (Set<int>::const_iterator 
00356              i=neighborSet_[next]->begin(); i!=neighborSet_[next]->end(); i++)
00357         {
00358           Q.push(*i);
00359         }
00360     }
00361   return -1; // no containing cell found
00362 }
00363 
00364 
00365 
00366 
00367 int AToCPointLocator::findEnclosingCell(int initialGuessLID,
00368                                         const double* x,
00369                                         double* xLocal) const
00370 {
00371   std::queue<int> Q;
00372   Set<int> repeats;
00373   int d = mesh_.spatialDim();
00374   Array<int> facets(mesh_.numFacets(d, 0, 0));
00375   Array<int> facetOr(facets.size());
00376 
00377   Q.push(initialGuessLID);
00378 
00379   while (!Q.empty())
00380     {
00381       int next = Q.front();
00382       Q.pop();
00383       if (repeats.contains(next)) continue;
00384       
00385 //      const int* facets = mesh_.elemZeroFacetView(next);
00386       mesh_.getFacetArray(d, next, 0, facets, facetOr);
00387       if (cellContainsPoint(next, x, &(facets[0]), xLocal)) return next;
00388       repeats.put(next);
00389       
00390       fillMaximalNeighbors(next, &(facets[0]));
00391       
00392       for (Set<int>::const_iterator 
00393              i=neighborSet_[next]->begin(); i!=neighborSet_[next]->end(); i++)
00394         {
00395           Q.push(*i);
00396         }
00397     }
00398   return -1; // no containing cell found
00399 }
00400 
00401 
00402 Point AToCPointLocator::makePoint(int dim, const double* x) 
00403 {
00404   if (dim==1) return Point(x[0]);
00405   else if (dim==2) return Point(x[0], x[1]);
00406   else return Point(x[0], x[1], x[2]);
00407 }

Site Contact