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