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 "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
00086 neighborSet_.resize(mesh.numCells(dim_));
00087
00088
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
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
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;
00179
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
00226
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;
00249 }
00250 else
00251 {
00252 TEUCHOS_TEST_FOR_EXCEPTION(dim_<=0 || dim_>3, std::runtime_error,
00253 "invalid point dimension " << dim_);
00254 return false;
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
00269
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
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;
00322 }
00323 else
00324 {
00325 TEUCHOS_TEST_FOR_EXCEPTION(dim_<=0 || dim_>3, std::runtime_error,
00326 "invalid point dimension " << dim_);
00327 return false;
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
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;
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
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;
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 }