processorPolyPatch.C 19.7 KB
Newer Older
1
2
3
4
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
5
    \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
6
7
8
9
10
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

11
12
13
14
    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
15
16
17
18
19
20
21

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
22
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
23
24
25
26
27
28
29
30
31
32

\*---------------------------------------------------------------------------*/

#include "processorPolyPatch.H"
#include "addToRunTimeSelectionTable.H"
#include "dictionary.H"
#include "SubField.H"
#include "demandDrivenData.H"
#include "matchPoints.H"
#include "OFstream.H"
mattijs's avatar
mattijs committed
33
34
35
#include "polyMesh.H"
#include "Time.H"
#include "transformList.H"
36
#include "PstreamBuffers.H"
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{
    defineTypeNameAndDebug(processorPolyPatch, 0);
    addToRunTimeSelectionTable(polyPatch, processorPolyPatch, dictionary);
}


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

Foam::processorPolyPatch::processorPolyPatch
(
    const word& name,
    const label size,
    const label start,
    const label index,
    const polyBoundaryMesh& bm,
    const int myProcNo,
mattijs's avatar
mattijs committed
57
    const int neighbProcNo
58
59
60
61
62
63
64
)
:
    coupledPolyPatch(name, size, start, index, bm),
    myProcNo_(myProcNo),
    neighbProcNo_(neighbProcNo),
    neighbFaceCentres_(),
    neighbFaceAreas_(),
65
    neighbFaceCellCentres_()
mattijs's avatar
mattijs committed
66
{}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81


Foam::processorPolyPatch::processorPolyPatch
(
    const word& name,
    const dictionary& dict,
    const label index,
    const polyBoundaryMesh& bm
)
:
    coupledPolyPatch(name, dict, index, bm),
    myProcNo_(readLabel(dict.lookup("myProcNo"))),
    neighbProcNo_(readLabel(dict.lookup("neighbProcNo"))),
    neighbFaceCentres_(),
    neighbFaceAreas_(),
82
    neighbFaceCellCentres_()
mattijs's avatar
mattijs committed
83
{}
84
85
86
87
88
89
90
91
92
93
94
95
96


Foam::processorPolyPatch::processorPolyPatch
(
    const processorPolyPatch& pp,
    const polyBoundaryMesh& bm
)
:
    coupledPolyPatch(pp, bm),
    myProcNo_(pp.myProcNo_),
    neighbProcNo_(pp.neighbProcNo_),
    neighbFaceCentres_(),
    neighbFaceAreas_(),
97
    neighbFaceCellCentres_()
98
99
100
101
102
103
104
105
106
{}


Foam::processorPolyPatch::processorPolyPatch
(
    const processorPolyPatch& pp,
    const polyBoundaryMesh& bm,
    const label index,
    const label newSize,
mattijs's avatar
mattijs committed
107
    const label newStart
108
109
110
111
112
113
114
)
:
    coupledPolyPatch(pp, bm, index, newSize, newStart),
    myProcNo_(pp.myProcNo_),
    neighbProcNo_(pp.neighbProcNo_),
    neighbFaceCentres_(),
    neighbFaceAreas_(),
115
    neighbFaceCellCentres_()
mattijs's avatar
mattijs committed
116
{}
117
118


mattijs's avatar
mattijs committed
119
120
121
122
123
Foam::processorPolyPatch::processorPolyPatch
(
    const processorPolyPatch& pp,
    const polyBoundaryMesh& bm,
    const label index,
124
    const labelUList& mapAddressing,
mattijs's avatar
mattijs committed
125
126
127
128
129
130
131
132
    const label newStart
)
:
    coupledPolyPatch(pp, bm, index, mapAddressing, newStart),
    myProcNo_(pp.myProcNo_),
    neighbProcNo_(pp.neighbProcNo_),
    neighbFaceCentres_(),
    neighbFaceAreas_(),
mattijs's avatar
mattijs committed
133
    neighbFaceCellCentres_()
mattijs's avatar
mattijs committed
134
135
136
{}


137
138
139
140
// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::processorPolyPatch::~processorPolyPatch()
{
mattijs's avatar
mattijs committed
141
142
    neighbPointsPtr_.clear();
    neighbEdgesPtr_.clear();
143
144
145
146
147
}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

148
void Foam::processorPolyPatch::initGeometry(PstreamBuffers& pBufs)
149
150
151
{
    if (Pstream::parRun())
    {
152
        UOPstream toNeighbProc(neighbProcNo(), pBufs);
153

mattijs's avatar
mattijs committed
154
155
156
157
        toNeighbProc
            << faceCentres()
            << faceAreas()
            << faceCellCentres();
158
159
160
161
    }
}


162
void Foam::processorPolyPatch::calcGeometry(PstreamBuffers& pBufs)
163
164
165
166
{
    if (Pstream::parRun())
    {
        {
167
168
            UIPstream fromNeighbProc(neighbProcNo(), pBufs);

169
170
171
172
173
174
175
            fromNeighbProc
                >> neighbFaceCentres_
                >> neighbFaceAreas_
                >> neighbFaceCellCentres_;
        }


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
        // My normals
        vectorField faceNormals(size());

        // Neighbour normals
        vectorField nbrFaceNormals(neighbFaceAreas_.size());

        // Calculate normals from areas and check
        forAll(faceNormals, facei)
        {
            scalar magSf = mag(faceAreas()[facei]);
            scalar nbrMagSf = mag(neighbFaceAreas_[facei]);
            scalar avSf = (magSf + nbrMagSf)/2.0;

            if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
            {
                // Undetermined normal. Use dummy normal to force separation
                // check. (note use of sqrt(VSMALL) since that is how mag
                // scales)
                faceNormals[facei] = point(1, 0, 0);
                nbrFaceNormals[facei] = faceNormals[facei];
            }
            else if (mag(magSf - nbrMagSf)/avSf > coupledPolyPatch::matchTol)
            {
                fileName nm
                (
                    boundaryMesh().mesh().time().path()
                   /name()+"_faces.obj"
                );
                Pout<< "processorPolyPatch::order : Writing my " << size()
                    << " faces to OBJ file " << nm << endl;
                writeOBJ(nm, *this, points());

                FatalErrorIn
                (
                    "processorPolyPatch::calcGeometry()"
                )   << "face " << facei << " area does not match neighbour by "
                    << 100*mag(magSf - nbrMagSf)/avSf
                    << "% -- possible face ordering problem." << endl
                    << "patch:" << name()
                    << " my area:" << magSf
                    << " neighbour area:" << nbrMagSf
                    << " matching tolerance:" << coupledPolyPatch::matchTol
                    << endl
                    << "Mesh face:" << start()+facei
                    << " vertices:"
                    << UIndirectList<point>(points(), operator[](facei))()
                    << endl
                    << "Rerun with processor debug flag set for"
                    << " more information." << exit(FatalError);
            }
            else
            {
                faceNormals[facei] = faceAreas()[facei]/magSf;
                nbrFaceNormals[facei] = neighbFaceAreas_[facei]/nbrMagSf;
            }
        }

        calcTransformTensors
234
235
236
        (
            faceCentres(),
            neighbFaceCentres_,
237
238
239
            faceNormals,
            nbrFaceNormals,
            calcFaceTol(*this, points(), faceCentres())
240
241
242
243
244
        );
    }
}


245
246
247
248
249
void Foam::processorPolyPatch::initMovePoints
(
    PstreamBuffers& pBufs,
    const pointField& p
)
250
{
251
252
    polyPatch::movePoints(pBufs, p);
    processorPolyPatch::initGeometry(pBufs);
253
254
255
}


256
257
258
259
260
void Foam::processorPolyPatch::movePoints
(
    PstreamBuffers& pBufs,
    const pointField&
)
261
{
262
    processorPolyPatch::calcGeometry(pBufs);
263
264
265
}


266
void Foam::processorPolyPatch::initUpdateMesh(PstreamBuffers& pBufs)
267
{
268
    polyPatch::initUpdateMesh(pBufs);
269

mattijs's avatar
mattijs committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
    if (Pstream::parRun())
    {
        // Express all points as patch face and index in face.
        labelList pointFace(nPoints());
        labelList pointIndex(nPoints());

        for (label patchPointI = 0; patchPointI < nPoints(); patchPointI++)
        {
            label faceI = pointFaces()[patchPointI][0];

            pointFace[patchPointI] = faceI;

            const face& f = localFaces()[faceI];

            pointIndex[patchPointI] = findIndex(f, patchPointI);
        }

        // Express all edges as patch face and index in face.
        labelList edgeFace(nEdges());
        labelList edgeIndex(nEdges());

        for (label patchEdgeI = 0; patchEdgeI < nEdges(); patchEdgeI++)
        {
            label faceI = edgeFaces()[patchEdgeI][0];

            edgeFace[patchEdgeI] = faceI;

            const labelList& fEdges = faceEdges()[faceI];

            edgeIndex[patchEdgeI] = findIndex(fEdges, patchEdgeI);
        }

        UOPstream toNeighbProc(neighbProcNo(), pBufs);

        toNeighbProc
            << pointFace
            << pointIndex
            << edgeFace
            << edgeIndex;
    }
310
311
312
}


313
void Foam::processorPolyPatch::updateMesh(PstreamBuffers& pBufs)
314
315
{
    // For completeness
316
    polyPatch::updateMesh(pBufs);
317

mattijs's avatar
mattijs committed
318
319
    neighbPointsPtr_.clear();
    neighbEdgesPtr_.clear();
320

mattijs's avatar
mattijs committed
321
    if (Pstream::parRun())
322
    {
mattijs's avatar
mattijs committed
323
324
325
326
        labelList nbrPointFace;
        labelList nbrPointIndex;
        labelList nbrEdgeFace;
        labelList nbrEdgeIndex;
327

mattijs's avatar
mattijs committed
328
        {
mattijs's avatar
mattijs committed
329
330
            // Note cannot predict exact size since opposite nPoints might
            // be different from one over here.
331
            UIPstream fromNeighbProc(neighbProcNo(), pBufs);
mattijs's avatar
mattijs committed
332
333
334
335
336
337

            fromNeighbProc
                >> nbrPointFace
                >> nbrPointIndex
                >> nbrEdgeFace
                >> nbrEdgeIndex;
mattijs's avatar
mattijs committed
338
        }
339

mattijs's avatar
mattijs committed
340
341
        // Convert neighbour faces and indices into face back into
        // my edges and points.
342

mattijs's avatar
mattijs committed
343
344
345
346
347
        // Convert points.
        // ~~~~~~~~~~~~~~~

        neighbPointsPtr_.reset(new labelList(nPoints(), -1));
        labelList& neighbPoints = neighbPointsPtr_();
348

mattijs's avatar
mattijs committed
349
        forAll(nbrPointFace, nbrPointI)
mattijs's avatar
mattijs committed
350
        {
mattijs's avatar
mattijs committed
351
352
353
354
            // Find face and index in face on this side.
            const face& f = localFaces()[nbrPointFace[nbrPointI]];
            label index = (f.size() - nbrPointIndex[nbrPointI]) % f.size();
            label patchPointI = f[index];
355

mattijs's avatar
mattijs committed
356
            if (neighbPoints[patchPointI] == -1)
mattijs's avatar
mattijs committed
357
            {
mattijs's avatar
mattijs committed
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
                // First reference of point
                neighbPoints[patchPointI] = nbrPointI;
            }
            else if (neighbPoints[patchPointI] >= 0)
            {
                // Point already visited. Mark as duplicate.
                neighbPoints[patchPointI] = -2;
            }
        }

        // Reset all duplicate entries to -1.
        forAll(neighbPoints, patchPointI)
        {
            if (neighbPoints[patchPointI] == -2)
            {
                neighbPoints[patchPointI] = -1;
            }
        }

        // Convert edges.
        // ~~~~~~~~~~~~~~

        neighbEdgesPtr_.reset(new labelList(nEdges(), -1));
        labelList& neighbEdges = neighbEdgesPtr_();

        forAll(nbrEdgeFace, nbrEdgeI)
        {
            // Find face and index in face on this side.
            const labelList& f = faceEdges()[nbrEdgeFace[nbrEdgeI]];
            label index = (f.size() - nbrEdgeIndex[nbrEdgeI] - 1) % f.size();
            label patchEdgeI = f[index];

            if (neighbEdges[patchEdgeI] == -1)
            {
                // First reference of edge
                neighbEdges[patchEdgeI] = nbrEdgeI;
            }
            else if (neighbEdges[patchEdgeI] >= 0)
            {
                // Edge already visited. Mark as duplicate.
                neighbEdges[patchEdgeI] = -2;
399
400
            }
        }
mattijs's avatar
mattijs committed
401
402
403
404
405
406
407
408
409
410
411
412

        // Reset all duplicate entries to -1.
        forAll(neighbEdges, patchEdgeI)
        {
            if (neighbEdges[patchEdgeI] == -2)
            {
                neighbEdges[patchEdgeI] = -1;
            }
        }

        // Remove any addressing used for shared points/edges calculation
        primitivePatch::clearOut();
413
414
415
416
    }
}


mattijs's avatar
mattijs committed
417
const Foam::labelList& Foam::processorPolyPatch::neighbPoints() const
418
{
mattijs's avatar
mattijs committed
419
420
421
422
423
424
425
426
427
    if (!neighbPointsPtr_.valid())
    {
        FatalErrorIn("processorPolyPatch::neighbPoints() const")
            << "No extended addressing calculated for patch " << name()
            << abort(FatalError);
    }
    return neighbPointsPtr_();
}

428

mattijs's avatar
mattijs committed
429
430
431
const Foam::labelList& Foam::processorPolyPatch::neighbEdges() const
{
    if (!neighbEdgesPtr_.valid())
432
    {
mattijs's avatar
mattijs committed
433
434
435
        FatalErrorIn("processorPolyPatch::neighbEdges() const")
            << "No extended addressing calculated for patch " << name()
            << abort(FatalError);
436
    }
mattijs's avatar
mattijs committed
437
    return neighbEdgesPtr_();
mattijs's avatar
mattijs committed
438
}
439
440


441
442
443
444
445
void Foam::processorPolyPatch::initOrder
(
    PstreamBuffers& pBufs,
    const primitivePatch& pp
) const
mattijs's avatar
mattijs committed
446
{
mattijs's avatar
mattijs committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    if (!Pstream::parRun())
    {
        return;
    }

    if (debug)
    {
        fileName nm
        (
            boundaryMesh().mesh().time().path()
           /name()+"_faces.obj"
        );
        Pout<< "processorPolyPatch::order : Writing my " << pp.size()
            << " faces to OBJ file " << nm << endl;
        writeOBJ(nm, pp, pp.points());

        // Calculate my face centres
mattijs's avatar
mattijs committed
464
        const pointField& fc = pp.faceCentres();
mattijs's avatar
mattijs committed
465
466
467
468
469
470
471

        OFstream localStr
        (
            boundaryMesh().mesh().time().path()
           /name() + "_localFaceCentres.obj"
        );
        Pout<< "processorPolyPatch::order : "
mattijs's avatar
mattijs committed
472
            << "Dumping " << fc.size()
mattijs's avatar
mattijs committed
473
474
            << " local faceCentres to " << localStr.name() << endl;

mattijs's avatar
mattijs committed
475
        forAll(fc, faceI)
mattijs's avatar
mattijs committed
476
        {
mattijs's avatar
mattijs committed
477
            writeOBJ(localStr, fc[faceI]);
mattijs's avatar
mattijs committed
478
479
480
481
482
483
484
485
        }
    }

    if (owner())
    {
        pointField anchors(getAnchorPoints(pp, pp.points()));

        // Now send all info over to the neighbour
486
        UOPstream toNeighbour(neighbProcNo(), pBufs);
mattijs's avatar
mattijs committed
487
        toNeighbour << pp.faceCentres() << anchors;
mattijs's avatar
mattijs committed
488
    }
489
490
491
492
493
494
495
496
497
}


// Return new ordering. Ordering is -faceMap: for every face index
// the new face -rotation:for every new face the clockwise shift
// of the original face. Return false if nothing changes (faceMap
// is identity, rotation is 0)
bool Foam::processorPolyPatch::order
(
498
    PstreamBuffers& pBufs,
499
500
501
502
503
    const primitivePatch& pp,
    labelList& faceMap,
    labelList& rotation
) const
{
mattijs's avatar
mattijs committed
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    // Note: we only get the faces that originate from internal faces.

    if (!Pstream::parRun())
    {
        return false;
    }

    faceMap.setSize(pp.size());
    faceMap = -1;

    rotation.setSize(pp.size());
    rotation = 0;

    if (owner())
    {
        // Do nothing (i.e. identical mapping, zero rotation).
        // See comment at top.
        forAll(faceMap, patchFaceI)
        {
            faceMap[patchFaceI] = patchFaceI;
        }

        return false;
    }
    else
    {
        vectorField masterCtrs;
        vectorField masterAnchors;

        // Receive data from neighbour
        {
535
            UIPstream fromNeighbour(neighbProcNo(), pBufs);
mattijs's avatar
mattijs committed
536
537
538
539
            fromNeighbour >> masterCtrs >> masterAnchors;
        }

        // Calculate typical distance from face centre
mattijs's avatar
mattijs committed
540
        scalarField tols(calcFaceTol(pp, pp.points(), pp.faceCentres()));
mattijs's avatar
mattijs committed
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

        if (debug || masterCtrs.size() != pp.size())
        {
            {
                OFstream nbrStr
                (
                    boundaryMesh().mesh().time().path()
                   /name() + "_nbrFaceCentres.obj"
                );
                Pout<< "processorPolyPatch::order : "
                    << "Dumping neighbour faceCentres to " << nbrStr.name()
                    << endl;
                forAll(masterCtrs, faceI)
                {
                    writeOBJ(nbrStr, masterCtrs[faceI]);
                }
            }

            if (masterCtrs.size() != pp.size())
            {
                FatalErrorIn
                (
                    "processorPolyPatch::order(const primitivePatch&"
                    ", labelList&, labelList&) const"
                )   << "in patch:" << name() << " : "
                    << "Local size of patch is " << pp.size() << " (faces)."
                    << endl
                    << "Received from neighbour " << masterCtrs.size()
                    << " faceCentres!"
                    << abort(FatalError);
            }
        }

        // Geometric match of face centre vectors
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        // 1. Try existing ordering and transformation
mattijs's avatar
mattijs committed
578
579
580
581
582
583
584
585
        bool matchedAll = matchPoints
        (
            pp.faceCentres(),
            masterCtrs,
            tols,
            true,
            faceMap
        );
mattijs's avatar
mattijs committed
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

        if (!matchedAll || debug)
        {
            // Dump faces
            fileName str
            (
                boundaryMesh().mesh().time().path()
               /name()/name()+"_faces.obj"
            );
            Pout<< "processorPolyPatch::order :"
                << " Writing faces to OBJ file " << str.name() << endl;
            writeOBJ(str, pp, pp.points());

            OFstream ccStr
            (
                boundaryMesh().mesh().time().path()
               /name() + "_faceCentresConnections.obj"
            );

            Pout<< "processorPolyPatch::order :"
                << " Dumping newly found match as lines between"
                << " corresponding face centres to OBJ file " << ccStr.name()
                << endl;

            label vertI = 0;

mattijs's avatar
mattijs committed
612
            forAll(pp.faceCentres(), faceI)
mattijs's avatar
mattijs committed
613
614
615
616
617
618
            {
                label masterFaceI = faceMap[faceI];

                if (masterFaceI != -1)
                {
                    const point& c0 = masterCtrs[masterFaceI];
mattijs's avatar
mattijs committed
619
                    const point& c1 = pp.faceCentres()[faceI];
mattijs's avatar
mattijs committed
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
                    writeOBJ(ccStr, c0, c1, vertI);
                }
            }
        }

        if (!matchedAll)
        {
            SeriousErrorIn
            (
                "processorPolyPatch::order(const primitivePatch&"
                ", labelList&, labelList&) const"
            )   << "in patch:" << name() << " : "
                << "Cannot match vectors to faces on both sides of patch"
                << endl
                << "    masterCtrs[0]:" << masterCtrs[0] << endl
mattijs's avatar
mattijs committed
635
                << "    ctrs[0]:" << pp.faceCentres()[0] << endl
mattijs's avatar
mattijs committed
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
                << "    Please check your topology changes or maybe you have"
                << " multiple separated (from cyclics) processor patches"
                << endl
                << "    Continuing with incorrect face ordering from now on!"
                << endl;

            return false;
        }

        // Set rotation.
        forAll(faceMap, oldFaceI)
        {
            // The face f will be at newFaceI (after morphing) and we want its
            // anchorPoint (= f[0]) to align with the anchorpoint for the
            // corresponding face on the other side.

            label newFaceI = faceMap[oldFaceI];

            const point& wantedAnchor = masterAnchors[newFaceI];

            rotation[newFaceI] = getRotation
            (
                pp.points(),
                pp[oldFaceI],
                wantedAnchor,
                tols[oldFaceI]
            );

            if (rotation[newFaceI] == -1)
            {
                SeriousErrorIn
                (
                    "processorPolyPatch::order(const primitivePatch&"
                    ", labelList&, labelList&) const"
                )   << "in patch " << name()
                    << " : "
                    << "Cannot find point on face " << pp[oldFaceI]
                    << " with vertices "
mattijs's avatar
mattijs committed
674
                    << UIndirectList<point>(pp.points(), pp[oldFaceI])()
mattijs's avatar
mattijs committed
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
                    << " that matches point " << wantedAnchor
                    << " when matching the halves of processor patch " << name()
                    << "Continuing with incorrect face ordering from now on!"
                    << endl;

                return false;
            }
        }

        forAll(faceMap, faceI)
        {
            if (faceMap[faceI] != faceI || rotation[faceI] != 0)
            {
                return true;
            }
        }

        return false;
    }
694
695
696
697
698
699
700
701
702
703
704
705
706
707
}


void Foam::processorPolyPatch::write(Ostream& os) const
{
    polyPatch::write(os);
    os.writeKeyword("myProcNo") << myProcNo_
        << token::END_STATEMENT << nl;
    os.writeKeyword("neighbProcNo") << neighbProcNo_
        << token::END_STATEMENT << nl;
}


// ************************************************************************* //