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 "processorPolyPatch.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <OpenFOAM/dictionary.H>
00029 #include <OpenFOAM/SubField.H>
00030 #include <OpenFOAM/demandDrivenData.H>
00031 #include <OpenFOAM/matchPoints.H>
00032 #include <OpenFOAM/OFstream.H>
00033 #include <OpenFOAM/polyMesh.H>
00034 #include <OpenFOAM/Time.H>
00035 #include <OpenFOAM/transformList.H>
00036
00037
00038
00039 namespace Foam
00040 {
00041 defineTypeNameAndDebug(processorPolyPatch, 0);
00042 addToRunTimeSelectionTable(polyPatch, processorPolyPatch, dictionary);
00043 }
00044
00045
00046
00047
00048 Foam::processorPolyPatch::processorPolyPatch
00049 (
00050 const word& name,
00051 const label size,
00052 const label start,
00053 const label index,
00054 const polyBoundaryMesh& bm,
00055 const int myProcNo,
00056 const int neighbProcNo
00057 )
00058 :
00059 coupledPolyPatch(name, size, start, index, bm),
00060 myProcNo_(myProcNo),
00061 neighbProcNo_(neighbProcNo),
00062 neighbFaceCentres_(),
00063 neighbFaceAreas_(),
00064 neighbFaceCellCentres_(),
00065 neighbPointsPtr_(NULL),
00066 neighbEdgesPtr_(NULL)
00067 {}
00068
00069
00070 Foam::processorPolyPatch::processorPolyPatch
00071 (
00072 const word& name,
00073 const dictionary& dict,
00074 const label index,
00075 const polyBoundaryMesh& bm
00076 )
00077 :
00078 coupledPolyPatch(name, dict, index, bm),
00079 myProcNo_(readLabel(dict.lookup("myProcNo"))),
00080 neighbProcNo_(readLabel(dict.lookup("neighbProcNo"))),
00081 neighbFaceCentres_(),
00082 neighbFaceAreas_(),
00083 neighbFaceCellCentres_(),
00084 neighbPointsPtr_(NULL),
00085 neighbEdgesPtr_(NULL)
00086 {}
00087
00088
00089 Foam::processorPolyPatch::processorPolyPatch
00090 (
00091 const processorPolyPatch& pp,
00092 const polyBoundaryMesh& bm
00093 )
00094 :
00095 coupledPolyPatch(pp, bm),
00096 myProcNo_(pp.myProcNo_),
00097 neighbProcNo_(pp.neighbProcNo_),
00098 neighbFaceCentres_(),
00099 neighbFaceAreas_(),
00100 neighbFaceCellCentres_(),
00101 neighbPointsPtr_(NULL),
00102 neighbEdgesPtr_(NULL)
00103 {}
00104
00105
00106 Foam::processorPolyPatch::processorPolyPatch
00107 (
00108 const processorPolyPatch& pp,
00109 const polyBoundaryMesh& bm,
00110 const label index,
00111 const label newSize,
00112 const label newStart
00113 )
00114 :
00115 coupledPolyPatch(pp, bm, index, newSize, newStart),
00116 myProcNo_(pp.myProcNo_),
00117 neighbProcNo_(pp.neighbProcNo_),
00118 neighbFaceCentres_(),
00119 neighbFaceAreas_(),
00120 neighbFaceCellCentres_(),
00121 neighbPointsPtr_(NULL),
00122 neighbEdgesPtr_(NULL)
00123 {}
00124
00125
00126
00127
00128 Foam::processorPolyPatch::~processorPolyPatch()
00129 {
00130 deleteDemandDrivenData(neighbPointsPtr_);
00131 deleteDemandDrivenData(neighbEdgesPtr_);
00132 }
00133
00134
00135
00136
00137 void Foam::processorPolyPatch::initGeometry()
00138 {
00139 if (Pstream::parRun())
00140 {
00141 OPstream toNeighbProc
00142 (
00143 Pstream::blocking,
00144 neighbProcNo(),
00145 3*(sizeof(label) + size()*sizeof(vector) + sizeof(scalar))
00146 );
00147
00148 toNeighbProc
00149 << faceCentres()
00150 << faceAreas()
00151 << faceCellCentres();
00152 }
00153 }
00154
00155
00156 void Foam::processorPolyPatch::calcGeometry()
00157 {
00158 if (Pstream::parRun())
00159 {
00160 {
00161 IPstream fromNeighbProc
00162 (
00163 Pstream::blocking,
00164 neighbProcNo(),
00165 3*(sizeof(label) + size()*sizeof(vector) + sizeof(scalar))
00166 );
00167 fromNeighbProc
00168 >> neighbFaceCentres_
00169 >> neighbFaceAreas_
00170 >> neighbFaceCellCentres_;
00171 }
00172
00173
00174 vectorField faceNormals(size());
00175
00176
00177 vectorField nbrFaceNormals(neighbFaceAreas_.size());
00178
00179
00180 forAll(faceNormals, facei)
00181 {
00182 scalar magSf = mag(faceAreas()[facei]);
00183 scalar nbrMagSf = mag(neighbFaceAreas_[facei]);
00184 scalar avSf = (magSf + nbrMagSf)/2.0;
00185
00186 if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
00187 {
00188
00189
00190
00191 faceNormals[facei] = point(1, 0, 0);
00192 nbrFaceNormals[facei] = faceNormals[facei];
00193 }
00194 else if (mag(magSf - nbrMagSf)/avSf > coupledPolyPatch::matchTol)
00195 {
00196 FatalErrorIn
00197 (
00198 "processorPolyPatch::calcGeometry()"
00199 ) << "face " << facei << " area does not match neighbour by "
00200 << 100*mag(magSf - nbrMagSf)/avSf
00201 << "% -- possible face ordering problem." << endl
00202 << "patch:" << name()
00203 << " my area:" << magSf
00204 << " neighbour area:" << nbrMagSf
00205 << " matching tolerance:" << coupledPolyPatch::matchTol
00206 << endl
00207 << "Mesh face:" << start()+facei
00208 << " vertices:"
00209 << UIndirectList<point>(points(), operator[](facei))()
00210 << endl
00211 << "Rerun with processor debug flag set for"
00212 << " more information." << exit(FatalError);
00213 }
00214 else
00215 {
00216 faceNormals[facei] = faceAreas()[facei]/magSf;
00217 nbrFaceNormals[facei] = neighbFaceAreas_[facei]/nbrMagSf;
00218 }
00219 }
00220
00221 calcTransformTensors
00222 (
00223 faceCentres(),
00224 neighbFaceCentres_,
00225 faceNormals,
00226 nbrFaceNormals,
00227 calcFaceTol(*this, points(), faceCentres())
00228 );
00229 }
00230 }
00231
00232
00233 void Foam::processorPolyPatch::initMovePoints(const pointField& p)
00234 {
00235 polyPatch::movePoints(p);
00236 processorPolyPatch::initGeometry();
00237 }
00238
00239
00240 void Foam::processorPolyPatch::movePoints(const pointField&)
00241 {
00242 processorPolyPatch::calcGeometry();
00243 }
00244
00245
00246 void Foam::processorPolyPatch::initUpdateMesh()
00247 {
00248 polyPatch::initUpdateMesh();
00249
00250 deleteDemandDrivenData(neighbPointsPtr_);
00251 deleteDemandDrivenData(neighbEdgesPtr_);
00252
00253 if (Pstream::parRun())
00254 {
00255
00256 labelList pointFace(nPoints());
00257 labelList pointIndex(nPoints());
00258
00259 for (label patchPointI = 0; patchPointI < nPoints(); patchPointI++)
00260 {
00261 label faceI = pointFaces()[patchPointI][0];
00262
00263 pointFace[patchPointI] = faceI;
00264
00265 const face& f = localFaces()[faceI];
00266
00267 pointIndex[patchPointI] = findIndex(f, patchPointI);
00268 }
00269
00270
00271 labelList edgeFace(nEdges());
00272 labelList edgeIndex(nEdges());
00273
00274 for (label patchEdgeI = 0; patchEdgeI < nEdges(); patchEdgeI++)
00275 {
00276 label faceI = edgeFaces()[patchEdgeI][0];
00277
00278 edgeFace[patchEdgeI] = faceI;
00279
00280 const labelList& fEdges = faceEdges()[faceI];
00281
00282 edgeIndex[patchEdgeI] = findIndex(fEdges, patchEdgeI);
00283 }
00284
00285 OPstream toNeighbProc
00286 (
00287 Pstream::blocking,
00288 neighbProcNo(),
00289 8*sizeof(label)
00290 + 2*nPoints()*sizeof(label)
00291 + 2*nEdges()*sizeof(label)
00292 );
00293
00294 toNeighbProc
00295 << pointFace
00296 << pointIndex
00297 << edgeFace
00298 << edgeIndex;
00299 }
00300 }
00301
00302
00303 void Foam::processorPolyPatch::updateMesh()
00304 {
00305
00306 polyPatch::updateMesh();
00307
00308 if (Pstream::parRun())
00309 {
00310 labelList nbrPointFace;
00311 labelList nbrPointIndex;
00312 labelList nbrEdgeFace;
00313 labelList nbrEdgeIndex;
00314
00315 {
00316
00317
00318 IPstream fromNeighbProc(Pstream::blocking, neighbProcNo());
00319
00320 fromNeighbProc
00321 >> nbrPointFace
00322 >> nbrPointIndex
00323 >> nbrEdgeFace
00324 >> nbrEdgeIndex;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 neighbPointsPtr_ = new labelList(nPoints(), -1);
00334 labelList& neighbPoints = *neighbPointsPtr_;
00335
00336 forAll(nbrPointFace, nbrPointI)
00337 {
00338
00339 const face& f = localFaces()[nbrPointFace[nbrPointI]];
00340 label index = (f.size() - nbrPointIndex[nbrPointI]) % f.size();
00341 label patchPointI = f[index];
00342
00343 if (neighbPoints[patchPointI] == -1)
00344 {
00345
00346 neighbPoints[patchPointI] = nbrPointI;
00347 }
00348 else if (neighbPoints[patchPointI] >= 0)
00349 {
00350
00351 neighbPoints[patchPointI] = -2;
00352 }
00353 }
00354
00355
00356 forAll(neighbPoints, patchPointI)
00357 {
00358 if (neighbPoints[patchPointI] == -2)
00359 {
00360 neighbPoints[patchPointI] = -1;
00361 }
00362 }
00363
00364
00365
00366
00367 neighbEdgesPtr_ = new labelList(nEdges(), -1);
00368 labelList& neighbEdges = *neighbEdgesPtr_;
00369
00370 forAll(nbrEdgeFace, nbrEdgeI)
00371 {
00372
00373 const labelList& f = faceEdges()[nbrEdgeFace[nbrEdgeI]];
00374 label index = (f.size() - nbrEdgeIndex[nbrEdgeI] - 1) % f.size();
00375 label patchEdgeI = f[index];
00376
00377 if (neighbEdges[patchEdgeI] == -1)
00378 {
00379
00380 neighbEdges[patchEdgeI] = nbrEdgeI;
00381 }
00382 else if (neighbEdges[patchEdgeI] >= 0)
00383 {
00384
00385 neighbEdges[patchEdgeI] = -2;
00386 }
00387 }
00388
00389
00390 forAll(neighbEdges, patchEdgeI)
00391 {
00392 if (neighbEdges[patchEdgeI] == -2)
00393 {
00394 neighbEdges[patchEdgeI] = -1;
00395 }
00396 }
00397
00398
00399 primitivePatch::clearOut();
00400 }
00401 }
00402
00403
00404 const Foam::labelList& Foam::processorPolyPatch::neighbPoints() const
00405 {
00406 if (!neighbPointsPtr_)
00407 {
00408 FatalErrorIn("processorPolyPatch::neighbPoints() const")
00409 << "No extended addressing calculated for patch " << name()
00410 << abort(FatalError);
00411 }
00412 return *neighbPointsPtr_;
00413 }
00414
00415
00416 const Foam::labelList& Foam::processorPolyPatch::neighbEdges() const
00417 {
00418 if (!neighbEdgesPtr_)
00419 {
00420 FatalErrorIn("processorPolyPatch::neighbEdges() const")
00421 << "No extended addressing calculated for patch " << name()
00422 << abort(FatalError);
00423 }
00424 return *neighbEdgesPtr_;
00425 }
00426
00427
00428 void Foam::processorPolyPatch::initOrder(const primitivePatch& pp) const
00429 {
00430 if (!Pstream::parRun())
00431 {
00432 return;
00433 }
00434
00435 if (debug)
00436 {
00437 fileName nm
00438 (
00439 boundaryMesh().mesh().time().path()
00440 /name()+"_faces.obj"
00441 );
00442 Pout<< "processorPolyPatch::order : Writing my " << pp.size()
00443 << " faces to OBJ file " << nm << endl;
00444 writeOBJ(nm, pp, pp.points());
00445
00446
00447 pointField ctrs(calcFaceCentres(pp, pp.points()));
00448
00449 OFstream localStr
00450 (
00451 boundaryMesh().mesh().time().path()
00452 /name() + "_localFaceCentres.obj"
00453 );
00454 Pout<< "processorPolyPatch::order : "
00455 << "Dumping " << ctrs.size()
00456 << " local faceCentres to " << localStr.name() << endl;
00457
00458 forAll(ctrs, faceI)
00459 {
00460 writeOBJ(localStr, ctrs[faceI]);
00461 }
00462 }
00463
00464 const bool isMaster = Pstream::myProcNo() < neighbProcNo();
00465
00466 if (isMaster)
00467 {
00468 pointField ctrs(calcFaceCentres(pp, pp.points()));
00469
00470 pointField anchors(getAnchorPoints(pp, pp.points()));
00471
00472
00473 OPstream toNeighbour(Pstream::blocking, neighbProcNo());
00474 toNeighbour << ctrs << anchors;
00475 }
00476 }
00477
00478
00479
00480
00481
00482
00483 bool Foam::processorPolyPatch::order
00484 (
00485 const primitivePatch& pp,
00486 labelList& faceMap,
00487 labelList& rotation
00488 ) const
00489 {
00490 if (!Pstream::parRun())
00491 {
00492 return false;
00493 }
00494
00495 faceMap.setSize(pp.size());
00496 faceMap = -1;
00497
00498 rotation.setSize(pp.size());
00499 rotation = 0;
00500
00501 const bool isMaster = Pstream::myProcNo() < neighbProcNo();
00502
00503 if (isMaster)
00504 {
00505
00506
00507 forAll(faceMap, patchFaceI)
00508 {
00509 faceMap[patchFaceI] = patchFaceI;
00510 }
00511
00512 return false;
00513 }
00514 else
00515 {
00516 vectorField masterCtrs;
00517 vectorField masterAnchors;
00518
00519
00520 {
00521 IPstream fromNeighbour(Pstream::blocking, neighbProcNo());
00522 fromNeighbour >> masterCtrs >> masterAnchors;
00523 }
00524
00525
00526 pointField ctrs(calcFaceCentres(pp, pp.points()));
00527
00528
00529 scalarField tols(calcFaceTol(pp, pp.points(), ctrs));
00530
00531 if (debug || masterCtrs.size() != pp.size())
00532 {
00533 {
00534 OFstream nbrStr
00535 (
00536 boundaryMesh().mesh().time().path()
00537 /name() + "_nbrFaceCentres.obj"
00538 );
00539 Pout<< "processorPolyPatch::order : "
00540 << "Dumping neighbour faceCentres to " << nbrStr.name()
00541 << endl;
00542 forAll(masterCtrs, faceI)
00543 {
00544 writeOBJ(nbrStr, masterCtrs[faceI]);
00545 }
00546 }
00547
00548 if (masterCtrs.size() != pp.size())
00549 {
00550 FatalErrorIn
00551 (
00552 "processorPolyPatch::order(const primitivePatch&"
00553 ", labelList&, labelList&) const"
00554 ) << "in patch:" << name() << " : "
00555 << "Local size of patch is " << pp.size() << " (faces)."
00556 << endl
00557 << "Received from neighbour " << masterCtrs.size()
00558 << " faceCentres!"
00559 << abort(FatalError);
00560 }
00561 }
00562
00563
00564
00565
00566
00567 bool matchedAll = false;
00568
00569 if
00570 (
00571 separated()
00572 && (separation().size() == 1 || separation().size() == pp.size())
00573 )
00574 {
00575 vectorField transformedCtrs;
00576
00577 const vectorField& v = separation();
00578
00579 if (v.size() == 1)
00580 {
00581 transformedCtrs = masterCtrs-v[0];
00582 }
00583 else
00584 {
00585 transformedCtrs = masterCtrs-v;
00586 }
00587 matchedAll = matchPoints
00588 (
00589 ctrs,
00590 transformedCtrs,
00591 tols,
00592 true,
00593 faceMap
00594 );
00595
00596 if (matchedAll)
00597 {
00598
00599 masterCtrs = transformedCtrs;
00600
00601
00602 if (v.size() == 1)
00603 {
00604 masterAnchors -= v[0];
00605 }
00606 else
00607 {
00608 masterAnchors -= v;
00609 }
00610 }
00611 }
00612 else if
00613 (
00614 !parallel()
00615 && (forwardT().size() == 1 || forwardT().size() == pp.size())
00616 )
00617 {
00618 vectorField transformedCtrs = masterCtrs;
00619 transformList(forwardT(), transformedCtrs);
00620 matchedAll = matchPoints
00621 (
00622 ctrs,
00623 transformedCtrs,
00624 tols,
00625 true,
00626 faceMap
00627 );
00628
00629 if (matchedAll)
00630 {
00631
00632 masterCtrs = transformedCtrs;
00633
00634
00635 transformList(forwardT(), masterAnchors);
00636 }
00637 }
00638
00639
00640
00641 if (!matchedAll)
00642 {
00643 matchedAll = matchPoints(ctrs, masterCtrs, tols, true, faceMap);
00644 }
00645
00646 if (!matchedAll || debug)
00647 {
00648
00649 fileName str
00650 (
00651 boundaryMesh().mesh().time().path()
00652 /name()/name()+"_faces.obj"
00653 );
00654 Pout<< "processorPolyPatch::order :"
00655 << " Writing faces to OBJ file " << str.name() << endl;
00656 writeOBJ(str, pp, pp.points());
00657
00658 OFstream ccStr
00659 (
00660 boundaryMesh().mesh().time().path()
00661 /name() + "_faceCentresConnections.obj"
00662 );
00663
00664 Pout<< "processorPolyPatch::order :"
00665 << " Dumping newly found match as lines between"
00666 << " corresponding face centres to OBJ file " << ccStr.name()
00667 << endl;
00668
00669 label vertI = 0;
00670
00671 forAll(ctrs, faceI)
00672 {
00673 label masterFaceI = faceMap[faceI];
00674
00675 if (masterFaceI != -1)
00676 {
00677 const point& c0 = masterCtrs[masterFaceI];
00678 const point& c1 = ctrs[faceI];
00679 writeOBJ(ccStr, c0, c1, vertI);
00680 }
00681 }
00682 }
00683
00684 if (!matchedAll)
00685 {
00686 SeriousErrorIn
00687 (
00688 "processorPolyPatch::order(const primitivePatch&"
00689 ", labelList&, labelList&) const"
00690 ) << "in patch:" << name() << " : "
00691 << "Cannot match vectors to faces on both sides of patch"
00692 << endl
00693 << " masterCtrs[0]:" << masterCtrs[0] << endl
00694 << " ctrs[0]:" << ctrs[0] << endl
00695 << " Please check your topology changes or maybe you have"
00696 << " multiple separated (from cyclics) processor patches"
00697 << endl
00698 << " Continuing with incorrect face ordering from now on!"
00699 << endl;
00700
00701 return false;
00702 }
00703
00704
00705 forAll(faceMap, oldFaceI)
00706 {
00707
00708
00709
00710
00711 label newFaceI = faceMap[oldFaceI];
00712
00713 const point& wantedAnchor = masterAnchors[newFaceI];
00714
00715 rotation[newFaceI] = getRotation
00716 (
00717 pp.points(),
00718 pp[oldFaceI],
00719 wantedAnchor,
00720 tols[oldFaceI]
00721 );
00722
00723 if (rotation[newFaceI] == -1)
00724 {
00725 SeriousErrorIn
00726 (
00727 "processorPolyPatch::order(const primitivePatch&"
00728 ", labelList&, labelList&) const"
00729 ) << "in patch " << name()
00730 << " : "
00731 << "Cannot find point on face " << pp[oldFaceI]
00732 << " with vertices "
00733 << UIndirectList<point>(pp.points(), pp[oldFaceI])()
00734 << " that matches point " << wantedAnchor
00735 << " when matching the halves of processor patch " << name()
00736 << "Continuing with incorrect face ordering from now on!"
00737 << endl;
00738
00739 return false;
00740 }
00741 }
00742
00743 forAll(faceMap, faceI)
00744 {
00745 if (faceMap[faceI] != faceI || rotation[faceI] != 0)
00746 {
00747 return true;
00748 }
00749 }
00750
00751 return false;
00752 }
00753 }
00754
00755
00756 void Foam::processorPolyPatch::write(Ostream& os) const
00757 {
00758 polyPatch::write(os);
00759 os.writeKeyword("myProcNo") << myProcNo_
00760 << token::END_STATEMENT << nl;
00761 os.writeKeyword("neighbProcNo") << neighbProcNo_
00762 << token::END_STATEMENT << nl;
00763 }
00764
00765
00766