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 #include "directMappedPatchBase.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <OpenFOAM/ListListOps.H>
00029 #include <meshTools/meshSearch.H>
00030 #include <meshTools/meshTools.H>
00031 #include <OpenFOAM/OFstream.H>
00032 #include <OpenFOAM/Random.H>
00033 #include <meshTools/treeDataFace.H>
00034 #include <meshTools/indexedOctree.H>
00035 #include <OpenFOAM/mapDistribute.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()]+offsets_;
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 gAverage(mag(offsets_)) <= ROOTVSMALL
00369 && mode_ == NEARESTPATCHFACE
00370 && sampleRegion_ == patch_.boundaryMesh().mesh().name()
00371 && samplePatch_ == patch_.name()
00372 )
00373 {
00374 WarningIn("directMappedPatchBase::calcMapping() const")
00375 << "Invalid offset " << offsets_ << endl
00376 << "Offset is the vector added to the patch face centres to"
00377 << " find the patch face supplying the data." << endl
00378 << "Setting it to " << offsets_
00379 << " on the same patch, on the same region"
00380 << " will find the faces themselves which does not make sense"
00381 << " for anything but testing." << endl
00382 << "patch_:" << patch_.name() << endl
00383 << "sampleRegion_:" << sampleRegion_ << endl
00384 << "mode_:" << sampleModeNames_[mode_] << endl
00385 << "samplePatch_:" << samplePatch_ << endl
00386 << "offsets_:" << offsets_ << endl;
00387 }
00388
00389
00390
00391 pointField samples;
00392 labelList patchFaceProcs;
00393 labelList patchFaces;
00394 pointField patchFc;
00395 collectSamples(samples, patchFaceProcs, patchFaces, patchFc);
00396
00397
00398 labelList sampleProcs;
00399 labelList sampleIndices;
00400 pointField sampleLocations;
00401 findSamples(samples, sampleProcs, sampleIndices, sampleLocations);
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 if (debug && Pstream::master())
00427 {
00428 OFstream str
00429 (
00430 patch_.boundaryMesh().mesh().time().path()
00431 / patch_.name()
00432 + "_directMapped.obj"
00433 );
00434 Pout<< "Dumping mapping as lines from patch faceCentres to"
00435 << " sampled cell/faceCentres to file " << str.name() << endl;
00436
00437 label vertI = 0;
00438
00439 forAll(patchFc, i)
00440 {
00441 meshTools::writeOBJ(str, patchFc[i]);
00442 vertI++;
00443 meshTools::writeOBJ(str, sampleLocations[i]);
00444 vertI++;
00445 str << "l " << vertI-1 << ' ' << vertI << nl;
00446 }
00447 }
00448
00449
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 mapPtr_.reset(new mapDistribute(sampleProcs, patchFaceProcs));
00486
00487
00488
00489
00490 labelListList& subMap = mapPtr_().subMap();
00491 labelListList& constructMap = mapPtr_().constructMap();
00492
00493 forAll(subMap, procI)
00494 {
00495 subMap[procI] = UIndirectList<label>
00496 (
00497 sampleIndices,
00498 subMap[procI]
00499 );
00500 constructMap[procI] = UIndirectList<label>
00501 (
00502 patchFaces,
00503 constructMap[procI]
00504 );
00505
00506 if (debug)
00507 {
00508 Pout<< "To proc:" << procI << " sending values of cells/faces:"
00509 << subMap[procI] << endl;
00510 Pout<< "From proc:" << procI << " receiving values of patch faces:"
00511 << constructMap[procI] << endl;
00512 }
00513 }
00514
00515
00516 mapPtr_().constructSize() = patch_.size();
00517
00518 if (debug)
00519 {
00520
00521 PackedBoolList used(patch_.size());
00522 forAll(constructMap, procI)
00523 {
00524 const labelList& map = constructMap[procI];
00525
00526 forAll(map, i)
00527 {
00528 label faceI = map[i];
00529
00530 if (used[faceI] == 0)
00531 {
00532 used[faceI] = 1;
00533 }
00534 else
00535 {
00536 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00537 << "On patch " << patch_.name()
00538 << " patchface " << faceI
00539 << " is assigned to more than once."
00540 << abort(FatalError);
00541 }
00542 }
00543 }
00544 forAll(used, faceI)
00545 {
00546 if (used[faceI] == 0)
00547 {
00548 FatalErrorIn("directMappedPatchBase::calcMapping() const")
00549 << "On patch " << patch_.name()
00550 << " patchface " << faceI
00551 << " is never assigned to."
00552 << abort(FatalError);
00553 }
00554 }
00555 }
00556 }
00557
00558
00559
00560
00561 Foam::directMappedPatchBase::directMappedPatchBase
00562 (
00563 const polyPatch& pp
00564 )
00565 :
00566 patch_(pp),
00567 sampleRegion_(patch_.boundaryMesh().mesh().name()),
00568 mode_(NEARESTPATCHFACE),
00569 samplePatch_("none"),
00570 uniformOffset_(true),
00571 offset_(vector::zero),
00572 offsets_(pp.size(), offset_),
00573 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00574 mapPtr_(NULL)
00575 {}
00576
00577
00578 Foam::directMappedPatchBase::directMappedPatchBase
00579 (
00580 const polyPatch& pp,
00581 const word& sampleRegion,
00582 const sampleMode mode,
00583 const word& samplePatch,
00584 const vectorField& offsets
00585 )
00586 :
00587 patch_(pp),
00588 sampleRegion_(sampleRegion),
00589 mode_(mode),
00590 samplePatch_(samplePatch),
00591 uniformOffset_(false),
00592 offsets_(offsets),
00593 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00594 mapPtr_(NULL)
00595 {}
00596
00597
00598 Foam::directMappedPatchBase::directMappedPatchBase
00599 (
00600 const polyPatch& pp,
00601 const word& sampleRegion,
00602 const sampleMode mode,
00603 const word& samplePatch,
00604 const vector& offset
00605 )
00606 :
00607 patch_(pp),
00608 sampleRegion_(sampleRegion),
00609 mode_(mode),
00610 samplePatch_(samplePatch),
00611 uniformOffset_(true),
00612 offset_(offset),
00613 offsets_(pp.size(), offset_),
00614 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00615 mapPtr_(NULL)
00616 {}
00617
00618
00619 Foam::directMappedPatchBase::directMappedPatchBase
00620 (
00621 const polyPatch& pp,
00622 const dictionary& dict
00623 )
00624 :
00625 patch_(pp),
00626 sampleRegion_
00627 (
00628 dict.lookupOrDefault
00629 (
00630 "sampleRegion",
00631 patch_.boundaryMesh().mesh().name()
00632 )
00633 ),
00634 mode_(sampleModeNames_.read(dict.lookup("sampleMode"))),
00635 samplePatch_(dict.lookup("samplePatch")),
00636 uniformOffset_(dict.found("offset")),
00637 offset_
00638 (
00639 uniformOffset_
00640 ? point(dict.lookup("offset"))
00641 : vector::zero
00642 ),
00643 offsets_
00644 (
00645 uniformOffset_
00646 ? pointField(pp.size(), offset_)
00647 : dict.lookup("offsets")
00648 ),
00649 sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
00650 mapPtr_(NULL)
00651 {}
00652
00653
00654 Foam::directMappedPatchBase::directMappedPatchBase
00655 (
00656 const polyPatch& pp,
00657 const directMappedPatchBase& dmp
00658 )
00659 :
00660 patch_(pp),
00661 sampleRegion_(dmp.sampleRegion_),
00662 mode_(dmp.mode_),
00663 samplePatch_(dmp.samplePatch_),
00664 uniformOffset_(dmp.uniformOffset_),
00665 offset_(dmp.offset_),
00666 offsets_(dmp.offsets_),
00667 sameRegion_(dmp.sameRegion_),
00668 mapPtr_(NULL)
00669 {}
00670
00671
00672
00673
00674 Foam::directMappedPatchBase::~directMappedPatchBase()
00675 {
00676 clearOut();
00677 }
00678
00679
00680 void Foam::directMappedPatchBase::clearOut()
00681 {
00682 mapPtr_.clear();
00683 }
00684
00685
00686
00687
00688 const Foam::polyMesh& Foam::directMappedPatchBase::sampleMesh() const
00689 {
00690 return patch_.boundaryMesh().mesh().time().lookupObject<polyMesh>
00691 (
00692 sampleRegion_
00693 );
00694 }
00695
00696
00697 const Foam::polyPatch& Foam::directMappedPatchBase::samplePolyPatch() const
00698 {
00699 const polyMesh& nbrMesh = sampleMesh();
00700
00701 label patchI = nbrMesh.boundaryMesh().findPatchID(samplePatch_);
00702
00703 if (patchI == -1)
00704 {
00705 FatalErrorIn("directMappedPatchBase::samplePolyPatch() ")
00706 << "Cannot find patch " << samplePatch_
00707 << " in region " << sampleRegion_ << endl
00708 << "Valid patches are " << nbrMesh.boundaryMesh().names()
00709 << exit(FatalError);
00710 }
00711
00712 return nbrMesh.boundaryMesh()[patchI];
00713 }
00714
00715
00716 void Foam::directMappedPatchBase::write(Ostream& os) const
00717 {
00718 os.writeKeyword("sampleMode") << sampleModeNames_[mode_]
00719 << token::END_STATEMENT << nl;
00720 os.writeKeyword("sampleRegion") << sampleRegion_
00721 << token::END_STATEMENT << nl;
00722 os.writeKeyword("samplePatch") << samplePatch_
00723 << token::END_STATEMENT << nl;
00724 if (uniformOffset_)
00725 {
00726 os.writeKeyword("offset") << offset_ << token::END_STATEMENT << nl;
00727 }
00728 else
00729 {
00730 os.writeKeyword("offsets") << offsets_ << token::END_STATEMENT << nl;
00731 }
00732 }
00733
00734
00735