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 #include "directMappedPatchBase.H"
00028 #include "addToRunTimeSelectionTable.H"
00029 #include "ListListOps.H"
00030 #include "meshSearch.H"
00031 #include "meshTools.H"
00032 #include "OFstream.H"
00033 #include "Random.H"
00034 #include "treeDataFace.H"
00035 #include "indexedOctree.H"
00036
00037
00038
00039 namespace Foam
00040 {
00041 defineTypeNameAndDebug(directMappedPatchBase, 0);
00042
00043 template<>
00044 const char* NamedEnum<directMappedPatchBase::sampleMode, 3>::names[] =
00045 {
00046 "nearestCell",
00047 "nearestPatchFace",
00048 "nearestFace"
00049 };
00050
00051 const NamedEnum<directMappedPatchBase::sampleMode, 3>
00052 directMappedPatchBase::sampleModeNames_;
00053 }
00054
00055
00056
00057
00058 void Foam::directMappedPatchBase::collectSamples
00059 (
00060 pointField& samples,
00061 labelList& patchFaceProcs,
00062 labelList& patchFaces,
00063 pointField& patchFc
00064 ) const
00065 {
00066
00067
00068 List<pointField> globalFc(Pstream::nProcs());
00069 List<pointField> globalSamples(Pstream::nProcs());
00070 labelListList globalFaces(Pstream::nProcs());
00071
00072 globalFc[Pstream::myProcNo()] = patch_.faceCentres();
00073 globalSamples[Pstream::myProcNo()] = globalFc[Pstream::myProcNo()]+offset_;
00074 globalFaces[Pstream::myProcNo()] = identity(patch_.size());
00075
00076
00077 Pstream::gatherList(globalSamples);
00078 Pstream::scatterList(globalSamples);
00079 Pstream::gatherList(globalFaces);
00080 Pstream::scatterList(globalFaces);
00081 Pstream::gatherList(globalFc);
00082 Pstream::scatterList(globalFc);
00083
00084
00085 samples = ListListOps::combine<pointField>
00086 (
00087 globalSamples,
00088 accessOp<pointField>()
00089 );
00090 patchFaces = ListListOps::combine<labelList>
00091 (
00092 globalFaces,
00093 accessOp<labelList>()
00094 );
00095 patchFc = ListListOps::combine<pointField>
00096 (
00097 globalFc,
00098 accessOp<pointField>()
00099 );
00100
00101 patchFaceProcs.setSize(patchFaces.size());
00102 labelList nPerProc
00103 (
00104 ListListOps::subSizes
00105 (
00106 globalFaces,
00107 accessOp<labelList>()
00108 )
00109 );
00110 label sampleI = 0;
00111 forAll(nPerProc, procI)
00112 {
00113 for (label i = 0; i < nPerProc[procI]; i++)
00114 {
00115 patchFaceProcs[sampleI++] = procI;
00116 }
00117 }
00118 }
00119
00120
00121
00122
00123 void Foam::directMappedPatchBase::findSamples
00124 (
00125 const pointField& samples,
00126 labelList& sampleProcs,
00127 labelList& sampleIndices,
00128 pointField& sampleLocations
00129 ) const
00130 {
00131
00132 const polyMesh& mesh = sampleMesh();
00133
00134
00135 List<nearInfo> nearest(samples.size());
00136
00137 switch (mode_)
00138 {
00139 case NEARESTCELL:
00140 {
00141 if (samplePatch_.size() && samplePatch_ != "none")
00142 {
00143 FatalErrorIn
00144 (
00145 "directMappedPatchBase::findSamples(const pointField&,"
00146 " labelList&, labelList&, pointField&) const"
00147 ) << "No need to supply a patch name when in "
00148 << sampleModeNames_[mode_] << " mode." << exit(FatalError);
00149 }
00150
00151
00152 meshSearch meshSearchEngine(mesh, false);
00153
00154 forAll(samples, sampleI)
00155 {
00156 const point& sample = samples[sampleI];
00157
00158 label cellI = meshSearchEngine.findCell(sample);
00159
00160 if (cellI == -1)
00161 {
00162 nearest[sampleI].second().first() = Foam::sqr(GREAT);
00163 nearest[sampleI].second().second() = Pstream::myProcNo();
00164 }
00165 else
00166 {
00167 const point& cc = mesh.cellCentres()[cellI];
00168
00169 nearest[sampleI].first() = pointIndexHit
00170 (
00171 true,
00172 cc,
00173 cellI
00174 );
00175 nearest[sampleI].second().first() = magSqr(cc-sample);
00176 nearest[sampleI].second().second() = Pstream::myProcNo();
00177 }
00178 }
00179 break;
00180 }
00181
00182 case NEARESTPATCHFACE:
00183 {
00184 Random rndGen(123456);
00185
00186 const polyPatch& pp = samplePolyPatch();
00187
00188 if (pp.empty())
00189 {
00190 forAll(samples, sampleI)
00191 {
00192 nearest[sampleI].second().first() = Foam::sqr(GREAT);
00193 nearest[sampleI].second().second() = Pstream::myProcNo();
00194 }
00195 }
00196 else
00197 {
00198
00199 const labelList patchFaces(identity(pp.size()) + pp.start());
00200
00201 treeBoundBox patchBb
00202 (
00203 treeBoundBox(pp.points(), pp.meshPoints()).extend
00204 (
00205 rndGen,
00206 1E-4
00207 )
00208 );
00209 patchBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00210 patchBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00211
00212 indexedOctree<treeDataFace> boundaryTree
00213 (
00214 treeDataFace
00215 (
00216 false,
00217 mesh,
00218 patchFaces
00219 ),
00220 patchBb,
00221 8,
00222 10,
00223 3.0
00224 );
00225
00226 forAll(samples, sampleI)
00227 {
00228 const point& sample = samples[sampleI];
00229
00230 pointIndexHit& nearInfo = nearest[sampleI].first();
00231 nearInfo = boundaryTree.findNearest
00232 (
00233 sample,
00234 magSqr(patchBb.span())
00235 );
00236
00237 if (!nearInfo.hit())
00238 {
00239 nearest[sampleI].second().first() = Foam::sqr(GREAT);
00240 nearest[sampleI].second().second() =
00241 Pstream::myProcNo();
00242 }
00243 else
00244 {
00245 point fc(pp[nearInfo.index()].centre(pp.points()));
00246 nearInfo.setPoint(fc);
00247 nearest[sampleI].second().first() = magSqr(fc-sample);
00248 nearest[sampleI].second().second() =
00249 Pstream::myProcNo();
00250 }
00251 }
00252 }
00253 break;
00254 }
00255
00256 case NEARESTFACE:
00257 {
00258 if (samplePatch_.size() && samplePatch_ != "none")
00259 {
00260 FatalErrorIn
00261 (
00262 "directMappedPatchBase::findSamples(const pointField&,"
00263 " labelList&, labelList&, pointField&) const"
00264 ) << "No need to supply a patch name when in "
00265 << sampleModeNames_[mode_] << " mode." << exit(FatalError);
00266 }
00267
00268
00269 meshSearch meshSearchEngine(mesh, false);
00270
00271 forAll(samples, sampleI)
00272 {
00273 const point& sample = samples[sampleI];
00274
00275 label faceI = meshSearchEngine.findNearestFace(sample);
00276
00277 if (faceI == -1)
00278 {
00279 nearest[sampleI].second().first() = Foam::sqr(GREAT);
00280 nearest[sampleI].second().second() = Pstream::myProcNo();
00281 }
00282 else
00283 {
00284 const point& fc = mesh.faceCentres()[faceI];
00285
00286 nearest[sampleI].first() = pointIndexHit
00287 (
00288 true,
00289 fc,
00290 faceI
00291 );
00292 nearest[sampleI].second().first() = magSqr(fc-sample);
00293 nearest[sampleI].second().second() = Pstream::myProcNo();
00294 }
00295 }
00296 break;
00297 }
00298
00299 default:
00300 {
00301 FatalErrorIn("directMappedPatchBase::findSamples(..)")
00302 << "problem." << abort(FatalError);
00303 }
00304 }
00305
00306
00307
00308 Pstream::listCombineGather(nearest, nearestEqOp());
00309 Pstream::listCombineScatter(nearest);
00310
00311 if (debug)
00312 {
00313 Info<< "directMappedPatchBase::findSamples on mesh " << sampleRegion_
00314 << " : " << endl;
00315 forAll(nearest, sampleI)
00316 {
00317 label procI = nearest[sampleI].second().second();
00318 label localI = nearest[sampleI].first().index();
00319
00320 Info<< " " << sampleI << " coord:"<< samples[sampleI]
00321 << " found on processor:" << procI
00322 << " in local cell/face:" << localI
00323 << " with cc:" << nearest[sampleI].first().rawPoint() << endl;
00324 }
00325 }
00326
00327
00328 forAll(nearest, sampleI)
00329 {
00330 if (!nearest[sampleI].first().hit())
00331 {
00332 FatalErrorIn
00333 (
00334 "directMappedPatchBase::findSamples"
00335 "(const pointField&, labelList&"
00336 ", labelList&, pointField&)"
00337 ) << "Did not find sample " << samples[sampleI]
00338 << " on any processor of region" << sampleRegion_
00339 << exit(FatalError);
00340 }
00341 }
00342
00343
00344
00345 sampleProcs.setSize(samples.size());
00346 sampleIndices.setSize(samples.size());
00347 sampleLocations.setSize(samples.size());
00348
00349 forAll(nearest, sampleI)
00350 {
00351 sampleProcs[sampleI] = nearest[sampleI].second().second();
00352 sampleIndices[sampleI] = nearest[sampleI].first().index();
00353 sampleLocations[sampleI] = nearest[sampleI].first().hitPoint();
00354 }
00355 }
00356
00357
00358 void Foam::directMappedPatchBase::calcMapping() const
00359 {
00360 if (mapPtr_.valid())
00361 {
00362 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00363 << "Mapping already calculated" << exit(FatalError);
00364 }
00365
00366 if
00367 (
00368 offset_ == vector::zero
00369 && sampleRegion_ == patch_.boundaryMesh().mesh().name()
00370 )
00371 {
00372 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00373 << "Invalid offset " << offset_ << endl
00374 << "Offset is the vector added to the patch face centres to"
00375 << " find the cell supplying the data."
00376 << exit(FatalError);
00377 }
00378
00379
00380
00381 pointField samples;
00382 labelList patchFaceProcs;
00383 labelList patchFaces;
00384 pointField patchFc;
00385 collectSamples(samples, patchFaceProcs, patchFaces, patchFc);
00386
00387
00388 labelList sampleProcs;
00389 labelList sampleIndices;
00390 pointField sampleLocations;
00391 findSamples(samples, sampleProcs, sampleIndices, sampleLocations);
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 if (debug && Pstream::master())
00417 {
00418 OFstream str
00419 (
00420 patch_.boundaryMesh().mesh().time().path()
00421 / patch_.name()
00422 + "_directMapped.obj"
00423 );
00424 Pout<< "Dumping mapping as lines from patch faceCentres to"
00425 << " sampled cellCentres to file " << str.name() << endl;
00426
00427 label vertI = 0;
00428
00429 forAll(patchFc, i)
00430 {
00431 meshTools::writeOBJ(str, patchFc[i]);
00432 vertI++;
00433 meshTools::writeOBJ(str, sampleLocations[i]);
00434 vertI++;
00435 str << "l " << vertI-1 << ' ' << vertI << nl;
00436 }
00437 }
00438
00439
00440
00441
00442 if (Pstream::master())
00443 {
00444 const scalarField magOffset(mag(sampleLocations - patchFc));
00445 const scalar avgOffset(average(magOffset));
00446
00447 forAll(magOffset, sampleI)
00448 {
00449 if (mag(magOffset[sampleI]-avgOffset) > max(SMALL, 0.001*avgOffset))
00450 {
00451 WarningIn("directMappedPatchBase::calcMapping() const")
00452 << "The actual cell/face centres picked up using offset "
00453 << offset_ << " are not" << endl
00454 << " on a single plane."
00455 << " This might give numerical problems." << endl
00456 << " At patchface " << patchFc[sampleI]
00457 << " the sampled cell/face " << sampleLocations[sampleI]
00458 << endl
00459 << " is not on a plane " << avgOffset
00460 << " offset from the patch." << endl
00461 << " You might want to shift your plane offset."
00462 << " Set the debug flag to get a dump of sampled cells."
00463 << endl;
00464 break;
00465 }
00466 }
00467 }
00468
00469
00470
00471 mapPtr_.reset(new mapDistribute(sampleProcs, patchFaceProcs));
00472
00473
00474
00475
00476 labelListList& subMap = mapPtr_().subMap();
00477 labelListList& constructMap = mapPtr_().constructMap();
00478
00479 forAll(subMap, procI)
00480 {
00481 subMap[procI] = UIndirectList<label>
00482 (
00483 sampleIndices,
00484 subMap[procI]
00485 );
00486 constructMap[procI] = UIndirectList<label>
00487 (
00488 patchFaces,
00489 constructMap[procI]
00490 );
00491
00492 if (debug)
00493 {
00494 Pout<< "To proc:" << procI << " sending values of cells/faces:"
00495 << subMap[procI] << endl;
00496 Pout<< "From proc:" << procI << " receiving values of patch faces:"
00497 << constructMap[procI] << endl;
00498 }
00499 }
00500
00501
00502 mapPtr_().constructSize() = patch_.size();
00503
00504 if (debug)
00505 {
00506
00507 PackedBoolList used(patch_.size());
00508 forAll(constructMap, procI)
00509 {
00510 const labelList& map = constructMap[procI];
00511
00512 forAll(map, i)
00513 {
00514 label faceI = map[i];
00515
00516 if (used[faceI] == 0)
00517 {
00518 used[faceI] = 1;
00519 }
00520 else
00521 {
00522 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00523 << "On patch " << patch_.name()
00524 << " patchface " << faceI
00525 << " is assigned to more than once."
00526 << abort(FatalError);
00527 }
00528 }
00529 }
00530 forAll(used, faceI)
00531 {
00532 if (used[faceI] == 0)
00533 {
00534 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00535 << "On patch " << patch_.name()
00536 << " patchface " << faceI
00537 << " is never assigned to."
00538 << abort(FatalError);
00539 }
00540 }
00541 }
00542 }
00543
00544
00545
00546
00547 Foam::directMappedPatchBase::directMappedPatchBase
00548 (
00549 const polyPatch& pp
00550 )
00551 :
00552 patch_(pp),
00553 sampleRegion_(patch_.boundaryMesh().mesh().name()),
00554 mode_(NEARESTPATCHFACE),
00555 samplePatch_("none"),
00556 offset_(vector::zero),
00557 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00558 mapPtr_(NULL)
00559 {}
00560
00561
00562 Foam::directMappedPatchBase::directMappedPatchBase
00563 (
00564 const polyPatch& pp,
00565 const dictionary& dict
00566 )
00567 :
00568 patch_(pp),
00569 sampleRegion_
00570 (
00571 dict.lookupOrDefault
00572 (
00573 "sampleRegion",
00574 patch_.boundaryMesh().mesh().name()
00575 )
00576 ),
00577 mode_(sampleModeNames_.read(dict.lookup("sampleMode"))),
00578 samplePatch_(dict.lookup("samplePatch")),
00579 offset_(dict.lookup("offset")),
00580 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00581 mapPtr_(NULL)
00582 {}
00583
00584
00585 Foam::directMappedPatchBase::directMappedPatchBase
00586 (
00587 const polyPatch& pp,
00588 const directMappedPatchBase& dmp
00589 )
00590 :
00591 patch_(pp),
00592 sampleRegion_(dmp.sampleRegion_),
00593 mode_(dmp.mode_),
00594 samplePatch_(dmp.samplePatch_),
00595 offset_(dmp.offset_),
00596 sameRegion_(dmp.sameRegion_),
00597 mapPtr_(NULL)
00598 {}
00599
00600
00601
00602
00603 Foam::directMappedPatchBase::~directMappedPatchBase()
00604 {
00605 clearOut();
00606 }
00607
00608
00609 void Foam::directMappedPatchBase::clearOut()
00610 {
00611 mapPtr_.clear();
00612 }
00613
00614
00615
00616
00617 const Foam::polyMesh& Foam::directMappedPatchBase::sampleMesh() const
00618 {
00619 return patch_.boundaryMesh().mesh().time().lookupObject<polyMesh>
00620 (
00621 sampleRegion_
00622 );
00623 }
00624
00625
00626 const Foam::polyPatch& Foam::directMappedPatchBase::samplePolyPatch() const
00627 {
00628 const polyMesh& nbrMesh = sampleMesh();
00629
00630 label patchI = nbrMesh.boundaryMesh().findPatchID(samplePatch_);
00631
00632 if (patchI == -1)
00633 {
00634 FatalErrorIn("directMappedPatchBase::samplePolyPatch() ")
00635 << "Cannot find patch " << samplePatch_
00636 << " in region " << sampleRegion_ << endl
00637 << "Valid patches are " << nbrMesh.boundaryMesh().names()
00638 << exit(FatalError);
00639 }
00640
00641 return nbrMesh.boundaryMesh()[patchI];
00642 }
00643
00644
00645 void Foam::directMappedPatchBase::write(Ostream& os) const
00646 {
00647 os.writeKeyword("sampleMode") << sampleModeNames_[mode_]
00648 << token::END_STATEMENT << nl;
00649 os.writeKeyword("sampleRegion") << sampleRegion_
00650 << token::END_STATEMENT << nl;
00651 os.writeKeyword("samplePatch") << samplePatch_
00652 << token::END_STATEMENT << nl;
00653 os.writeKeyword("offset") << offset_ << token::END_STATEMENT << nl;
00654 }
00655
00656
00657