surfaceFieldValue.C 24.9 KB
Newer Older
1
2
3
4
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
5
    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
6
     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
7
8
9
10
-------------------------------------------------------------------------------
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
#include "surfaceFieldValue.H"
27
28
#include "fvMesh.H"
#include "emptyPolyPatch.H"
29
#include "coupledPolyPatch.H"
30
#include "sampledSurface.H"
31
32
#include "mergePoints.H"
#include "indirectPrimitivePatch.H"
33
#include "PatchTools.H"
34
#include "meshedSurfRef.H"
35
#include "addToRunTimeSelectionTable.H"
36
37
38

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

39
namespace Foam
40
{
41
42
43
44
namespace functionObjects
{
namespace fieldValues
{
45
46
47
    defineTypeNameAndDebug(surfaceFieldValue, 0);
    addToRunTimeSelectionTable(fieldValue, surfaceFieldValue, dictionary);
    addToRunTimeSelectionTable(functionObject, surfaceFieldValue, dictionary);
48
49
}
}
50
51
}

52
53
54
template<>
const char* Foam::NamedEnum
<
55
    Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypes,
56
    4
57
58
59
60
>::names[] =
{
    "faceZone",
    "patch",
61
    "surface",
62
63
    "sampledSurface"
};
64

65
66
67
template<>
const char* Foam::NamedEnum
<
68
    Foam::functionObjects::fieldValues::surfaceFieldValue::operationType,
69
    17
70
71
72
73
>::names[] =
{
    "none",
    "sum",
74
    "weightedSum",
75
76
77
78
79
80
81
82
    "sumMag",
    "sumDirection",
    "sumDirectionBalance",
    "average",
    "weightedAverage",
    "areaAverage",
    "weightedAreaAverage",
    "areaIntegrate",
83
    "weightedAreaIntegrate",
84
85
86
87
88
89
90
    "min",
    "max",
    "CoV",
    "areaNormalAverage",
    "areaNormalIntegrate"
};

91
92
93
94
95
96
97
98
99
100
101
102
template<>
const char* Foam::NamedEnum
<
    Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationType,
    2
>::names[] =
{
    "none",
    "sqrt"
};


103
104
const Foam::NamedEnum
<
105
    Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypes,
106
    4
107
> Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypeNames_;
108
109
110

const Foam::NamedEnum
<
111
    Foam::functionObjects::fieldValues::surfaceFieldValue::operationType,
112
    17
113
> Foam::functionObjects::fieldValues::surfaceFieldValue::operationTypeNames_;
114

115
116
117
118
119
120
121
const Foam::NamedEnum
<
    Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationType,
    2
>
Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationTypeNames_;

122

Henry Weller's avatar
Henry Weller committed
123
// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
const Foam::objectRegistry&
Foam::functionObjects::fieldValues::surfaceFieldValue::obr() const
{
    if (regionType_ == stSurface)
    {
        return mesh_.lookupObject<objectRegistry>(regionName_);
    }
    else
    {
        return mesh_;
    }
}


139
void Foam::functionObjects::fieldValues::surfaceFieldValue::setFaceZoneFaces()
140
{
141
    const label zoneId = mesh_.faceZones().findZoneID(regionName_);
142
143
144

    if (zoneId < 0)
    {
145
        FatalErrorInFunction
146
            << type() << " " << name() << ": "
147
148
            << regionTypeNames_[regionType_] << "(" << regionName_ << "):" << nl
            << "    Unknown face zone name: " << regionName_
149
            << ". Valid face zones are: " << mesh_.faceZones().names()
150
151
152
            << nl << exit(FatalError);
    }

153
    const faceZone& fZone = mesh_.faceZones()[zoneId];
154

155
156
    DynamicList<label> faceIds(fZone.size());
    DynamicList<label> facePatchIds(fZone.size());
157
    DynamicList<bool>  faceFlip(fZone.size());
158
159
160

    forAll(fZone, i)
    {
161
        const label facei = fZone[i];
162
163
164

        label faceId = -1;
        label facePatchId = -1;
165
        if (mesh_.isInternalFace(facei))
166
        {
167
            faceId = facei;
168
169
170
171
            facePatchId = -1;
        }
        else
        {
172
173
            facePatchId = mesh_.boundaryMesh().whichPatch(facei);
            const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
174
            if (isA<coupledPolyPatch>(pp))
175
            {
176
                if (refCast<const coupledPolyPatch>(pp).owner())
177
                {
178
                    faceId = pp.whichFace(facei);
179
180
181
182
183
184
185
186
                }
                else
                {
                    faceId = -1;
                }
            }
            else if (!isA<emptyPolyPatch>(pp))
            {
187
                faceId = facei - pp.start();
188
189
190
191
192
193
194
195
196
197
            }
            else
            {
                faceId = -1;
                facePatchId = -1;
            }
        }

        if (faceId >= 0)
        {
198
199
            faceIds.append(faceId);
            facePatchIds.append(facePatchId);
200
            faceFlip.append(fZone.flipMap()[i] ? true : false);
201
202
203
        }
    }

204
205
    faceId_.transfer(faceIds);
    facePatchId_.transfer(facePatchIds);
206
    faceFlip_.transfer(faceFlip);
207
    nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
208
209
210

    if (debug)
    {
211
        Pout<< "Original face zone size = " << fZone.size()
212
            << ", new size = " << faceId_.size() << endl;
213
214
215
216
    }
}


217
void Foam::functionObjects::fieldValues::surfaceFieldValue::setPatchFaces()
218
{
219
    const label patchid = mesh_.boundaryMesh().findPatchID(regionName_);
220

221
    if (patchid < 0)
222
    {
223
        FatalErrorInFunction
224
            << type() << " " << name() << ": "
225
226
            << regionTypeNames_[regionType_] << "(" << regionName_ << "):" << nl
            << "    Unknown patch name: " << regionName_
227
            << ". Valid patch names are: "
228
            << mesh_.boundaryMesh().names() << nl
229
230
231
            << exit(FatalError);
    }

232
    const polyPatch& pp = mesh_.boundaryMesh()[patchid];
233
234

    label nFaces = pp.size();
235
    if (isA<emptyPolyPatch>(pp))
236
237
238
239
240
241
    {
        nFaces = 0;
    }

    faceId_.setSize(nFaces);
    facePatchId_.setSize(nFaces);
242
    faceFlip_.setSize(nFaces);
243
    nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
244

245
    forAll(faceId_, facei)
246
    {
247
248
        faceId_[facei] = facei;
        facePatchId_[facei] = patchid;
249
        faceFlip_[facei] = false;
250
251
252
253
    }
}


254
void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
255
256
257
258
259
260
261
262
263
264
265
266
267
(
    faceList& faces,
    pointField& points
) const
{
    List<faceList> allFaces(Pstream::nProcs());
    List<pointField> allPoints(Pstream::nProcs());

    labelList globalFacesIs(faceId_);
    forAll(globalFacesIs, i)
    {
        if (facePatchId_[i] != -1)
        {
268
            label patchi = facePatchId_[i];
269
            globalFacesIs[i] += mesh_.boundaryMesh()[patchi].start();
270
271
272
273
274
275
        }
    }

    // Add local faces and points to the all* lists
    indirectPrimitivePatch pp
    (
276
277
        IndirectList<face>(mesh_.faces(), globalFacesIs),
        mesh_.points()
278
279
280
281
282
283
284
285
286
287
    );
    allFaces[Pstream::myProcNo()] = pp.localFaces();
    allPoints[Pstream::myProcNo()] = pp.localPoints();

    Pstream::gatherList(allFaces);
    Pstream::gatherList(allPoints);

    // Renumber and flatten
    label nFaces = 0;
    label nPoints = 0;
288
    forAll(allFaces, proci)
289
    {
290
291
        nFaces += allFaces[proci].size();
        nPoints += allPoints[proci].size();
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    }

    faces.setSize(nFaces);
    points.setSize(nPoints);

    nFaces = 0;
    nPoints = 0;

    // My own data first
    {
        const faceList& fcs = allFaces[Pstream::myProcNo()];
        forAll(fcs, i)
        {
            const face& f = fcs[i];
            face& newF = faces[nFaces++];
            newF.setSize(f.size());
            forAll(f, fp)
            {
                newF[fp] = f[fp] + nPoints;
            }
        }

        const pointField& pts = allPoints[Pstream::myProcNo()];
        forAll(pts, i)
        {
            points[nPoints++] = pts[i];
        }
    }

    // Other proc data follows
322
    forAll(allFaces, proci)
323
    {
324
        if (proci != Pstream::myProcNo())
325
        {
326
            const faceList& fcs = allFaces[proci];
327
328
329
330
331
332
333
334
335
336
337
            forAll(fcs, i)
            {
                const face& f = fcs[i];
                face& newF = faces[nFaces++];
                newF.setSize(f.size());
                forAll(f, fp)
                {
                    newF[fp] = f[fp] + nPoints;
                }
            }

338
            const pointField& pts = allPoints[proci];
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
            forAll(pts, i)
            {
                points[nPoints++] = pts[i];
            }
        }
    }

    // Merge
    labelList oldToNew;
    pointField newPoints;
    bool hasMerged = mergePoints
    (
        points,
        SMALL,
        false,
        oldToNew,
        newPoints
    );

    if (hasMerged)
    {
        if (debug)
        {
            Pout<< "Merged from " << points.size()
                << " down to " << newPoints.size() << " points" << endl;
        }

        points.transfer(newPoints);
        forAll(faces, i)
        {
            inplaceRenumber(oldToNew, faces[i]);
        }
    }
}


375
376
void Foam::functionObjects::fieldValues::surfaceFieldValue::
combineSurfaceGeometry
377
378
379
380
381
(
    faceList& faces,
    pointField& points
) const
{
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
    if (regionType_ == stSurface)
    {
        const surfMesh& s = dynamicCast<const surfMesh>(obr());

        if (Pstream::parRun())
        {
            // Dimension as fraction of surface
            const scalar mergeDim = 1e-10*boundBox(s.points(), true).mag();

            labelList pointsMap;

            PatchTools::gatherAndMerge
            (
                mergeDim,
                primitivePatch
                (
                    SubList<face>(s.faces(), s.faces().size()),
                    s.points()
                ),
                points,
                faces,
                pointsMap
            );
        }
        else
        {
            faces = s.faces();
            points = s.points();
        }
    }
    else if (surfacePtr_.valid())
413
414
415
416
417
    {
        const sampledSurface& s = surfacePtr_();

        if (Pstream::parRun())
        {
418
            // Dimension as fraction of mesh bounding box
419
            const scalar mergeDim = 1e-10*mesh_.bounds().mag();
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

            labelList pointsMap;

            PatchTools::gatherAndMerge
            (
                mergeDim,
                primitivePatch
                (
                    SubList<face>(s.faces(), s.faces().size()),
                    s.points()
                ),
                points,
                faces,
                pointsMap
            );
        }
        else
        {
            faces = s.faces();
            points = s.points();
        }
    }
}


445
Foam::scalar
446
Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
447
448
449
{
    scalar totalArea;

450
451
452
453
454
455
456
    if (regionType_ == stSurface)
    {
        const surfMesh& s = dynamicCast<const surfMesh>(obr());

        totalArea = gSum(s.magSf());
    }
    else if (surfacePtr_.valid())
457
458
459
460
461
    {
        totalArea = gSum(surfacePtr_().magSf());
    }
    else
    {
462
        totalArea = gSum(filterField(mesh_.magSf(), false));
463
464
465
466
467
468
    }

    return totalArea;
}


469
470
// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
bool Foam::functionObjects::fieldValues::surfaceFieldValue::needsSf() const
{
    // Many operations use the Sf field
    switch (operation_)
    {
        case opNone:
        case opSum:
        case opSumMag:
        case opAverage:
        case opMin:
        case opMax:
            return false;

        default:
            return true;
    }
}


bool Foam::functionObjects::fieldValues::surfaceFieldValue::needsWeight() const
{
    // Only a few operations use weight field
    switch (operation_)
    {
        case opWeightedSum:
        case opWeightedAverage:
        case opWeightedAreaAverage:
        case opWeightedAreaIntegrate:
            return true;

        default:
            return false;
    }
}


507
void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
508
509
510
(
    const dictionary& dict
)
511
{
512
    dict.lookup("name") >> regionName_;
513

514
    switch (regionType_)
515
516
517
518
    {
        case stFaceZone:
        {
            setFaceZoneFaces();
519
            surfacePtr_.clear();
520
521
522
523
524
            break;
        }
        case stPatch:
        {
            setPatchFaces();
525
526
527
528
529
530
531
532
533
534
535
536
            surfacePtr_.clear();
            break;
        }
        case stSurface:
        {
            const surfMesh& s = dynamicCast<const surfMesh>(obr());
            nFaces_ = returnReduce(s.size(), sumOp<label>());

            faceId_.clear();
            facePatchId_.clear();
            faceFlip_.clear();
            surfacePtr_.clear();
537
538
            break;
        }
539
540
        case stSampledSurface:
        {
541
542
543
544
545
546
547
548
549
550
551
552
553
554
            faceId_.clear();
            facePatchId_.clear();
            faceFlip_.clear();

            surfacePtr_ = sampledSurface::New
            (
                name(),
                mesh_,
                dict.subDict("sampledSurfaceDict")
            );
            surfacePtr_().update();
            nFaces_ =
                returnReduce(surfacePtr_().faces().size(), sumOp<label>());

555
556
            break;
        }
557
558
        default:
        {
559
            FatalErrorInFunction
560
                << type() << " " << name() << ": "
561
                << regionTypeNames_[regionType_] << "(" << regionName_ << "):"
562
563
                << nl << "    Unknown region type. Valid region types are:"
                << regionTypeNames_.sortedToc() << nl << exit(FatalError);
564
565
566
        }
    }

567
568
    if (nFaces_ == 0)
    {
569
        FatalErrorInFunction
570
            << type() << " " << name() << ": "
571
            << regionTypeNames_[regionType_] << "(" << regionName_ << "):" << nl
572
            << "    Region has no faces" << exit(FatalError);
573
574
    }

575
576
577
578
579
    if (surfacePtr_.valid())
    {
        surfacePtr_().update();
    }

580
581
    totalArea_ = totalArea();

582
    Info<< type() << " " << name() << ":" << nl
583
        << "    operation     = ";
Andrew Heather's avatar
Andrew Heather committed
584

585
    if (postOperation_ != postOpNone)
Andrew Heather's avatar
Andrew Heather committed
586
    {
587
588
589
590
591
592
        Info<< postOperationTypeNames_[postOperation_] << '('
            << operationTypeNames_[operation_] << ')'  << nl;
    }
    else
    {
        Info<< operationTypeNames_[operation_] << nl;
593
    }
594
595
596
    Info<< "    total faces   = " << nFaces_ << nl
        << "    total area    = " << totalArea_ << nl;

597

598
599
600
    weightFieldName_ = "none";
    orientWeightField_ = false;
    if (needsWeight())
601
    {
602
        if (dict.readIfPresent("weightField", weightFieldName_))
603
        {
604
605
606
607
608
609
610
611
            if (regionType_ == stSampledSurface)
            {
                FatalIOErrorInFunction(dict)
                    << "Cannot use weightField for sampledSurface"
                    << exit(FatalIOError);
            }

            Info<< "    weight field  = " << weightFieldName_ << nl;
612
        }
613
614

        if (dict.found("orientedWeightField"))
615
        {
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
            if (regionType_ == stSurface || regionType_ == stSampledSurface)
            {
                FatalIOErrorInFunction(dict)
                    << "Cannot use orientedWeightField "
                    << "for surface/sampledSurface"
                    << exit(FatalIOError);
            }

            if (weightFieldName_ == "none")
            {
                dict.lookup("orientedWeightField") >> weightFieldName_;
                orientWeightField_ = true;

                Info<< "    weight field  = " << weightFieldName_ << nl;
            }
            else
            {
                FatalIOErrorInFunction(dict)
                    << "Cannot specify both weightField and orientedWeightField"
                    << exit(FatalIOError);
            }
637
638
639
640
        }
    }

    List<word> orientedFields;
641
    orientedFieldsStart_ = labelMax;
642
643
644
645
    if (dict.readIfPresent("orientedFields", orientedFields))
    {
        orientedFieldsStart_ = fields_.size();
        fields_.append(orientedFields);
Andrew Heather's avatar
Andrew Heather committed
646
647
    }

648
    surfaceWriterPtr_.clear();
649
    if (writeFields_)
650
    {
651
652
        const word surfaceFormat(dict.lookup("surfaceFormat"));

653
654
655
        if (surfaceFormat != "none")
        {
            surfaceWriterPtr_.reset
656
            (
657
658
659
660
661
662
663
664
665
666
                surfaceWriter::New
                (
                    surfaceFormat,
                    dict.subOrEmptyDict("formatOptions").
                        subOrEmptyDict(surfaceFormat)
                ).ptr()
            );

            Info<< "    surfaceFormat = " << surfaceFormat << nl;
        }
667
    }
668
669

    Info<< nl << endl;
670
671
672
}


673
674
675
676
void Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
(
    Ostream& os
) const
677
{
678
    if (operation_ != opNone)
679
    {
680
681
        writeCommented(os, "Region type : ");
        os << regionTypeNames_[regionType_] << " " << regionName_ << endl;
682

683
684
685
686
        writeHeaderValue(os, "Faces", nFaces_);
        writeHeaderValue(os, "Area", totalArea_);
        writeHeaderValue(os, "Scale factor", scaleFactor_);

687
688
689
690
691
        if (weightFieldName_ != "none")
        {
            writeHeaderValue(os, "Weight field", weightFieldName_);
        }

692
        writeCommented(os, "Time");
693
694
        if (writeArea_)
        {
695
            os  << tab << "Area";
696
        }
697

698
        forAll(fields_, i)
699
        {
700
701
            os  << tab << operationTypeNames_[operation_]
                << "(" << fields_[i] << ")";
702
        }
703

704
        os  << endl;
705
    }
706
707
708
}


709
template<>
710
711
Foam::scalar
Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
712
713
714
715
716
717
718
719
720
721
(
    const Field<scalar>& values,
    const vectorField& Sf,
    const scalarField& weightField
) const
{
    switch (operation_)
    {
        case opSumDirection:
        {
722
            vector n(dict_.lookup("direction"));
723
            return gSum(pos(values*(Sf & n))*mag(values));
724
725
726
727
728
        }
        case opSumDirectionBalance:
        {
            vector n(dict_.lookup("direction"));
            const scalarField nv(values*(Sf & n));
729

730
            return gSum(pos(nv)*mag(values) - neg(nv)*mag(values));
731
732
733
734
735
736
737
738
739
740
        }
        default:
        {
            // Fall through to other operations
            return processSameTypeValues(values, Sf, weightField);
        }
    }
}


741
template<>
742
743
Foam::vector
Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
744
745
746
747
748
749
750
751
(
    const Field<vector>& values,
    const vectorField& Sf,
    const scalarField& weightField
) const
{
    switch (operation_)
    {
752
753
        case opSumDirection:
        {
754
755
756
            vector n(dict_.lookup("direction"));
            n /= mag(n) + ROOTVSMALL;

757
            const scalarField nv(n & values);
758
            return gSum(pos(nv)*n*(nv));
759
760
761
762
763
764
        }
        case opSumDirectionBalance:
        {
            vector n(dict_.lookup("direction"));
            n /= mag(n) + ROOTVSMALL;

765
            const scalarField nv(n & values);
766
            return gSum(pos(nv)*n*(nv));
767
        }
768
769
        case opAreaNormalAverage:
        {
770
771
            const scalar val = gSum(values & Sf)/gSum(mag(Sf));
            return vector(val, 0, 0);
772
773
774
        }
        case opAreaNormalIntegrate:
        {
775
776
            const scalar val = gSum(values & Sf);
            return vector(val, 0, 0);
777
778
779
780
781
782
783
784
785
786
        }
        default:
        {
            // Fall through to other operations
            return processSameTypeValues(values, Sf, weightField);
        }
    }
}


787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
template<>
Foam::tmp<Foam::scalarField>
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
(
    const Field<scalar>& weightField
)
{
    // pass through
    return weightField;
}


template<>
Foam::tmp<Foam::scalarField>
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
(
    const Field<scalar>& weightField,
    const vectorField& Sf
)
{
    // scalar * Area
    if (returnReduce(weightField.empty(), andOp<bool>()))
    {
        return mag(Sf);
    }
    else
    {
        return weightField * mag(Sf);
    }
}


template<>
Foam::tmp<Foam::scalarField>
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
(
    const Field<vector>& weightField,
    const vectorField& Sf
)
{
    // vector (dot) Area
    if (returnReduce(weightField.empty(), andOp<bool>()))
    {
        return mag(Sf);
    }
    else
    {
        return weightField & Sf;
    }
}


839
840
// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

841
Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
842
843
844
845
846
847
848
(
    const word& name,
    const Time& runTime,
    const dictionary& dict
)
:
    fieldValue(name, runTime, dict, typeName),
849
    regionType_(regionTypeNames_.read(dict.lookup("regionType"))),
850
    operation_(operationTypeNames_.read(dict.lookup("operation"))),
851
852
853
854
855
    postOperation_
    (
        postOperationTypeNames_
        [dict.lookupOrDefault<word>("postOperation", "none")]
    ),
856
857
858
859
860
861
862
    weightFieldName_("none"),
    orientWeightField_(false),
    orientedFieldsStart_(labelMax),
    writeArea_(dict.lookupOrDefault("writeArea", false)),
    nFaces_(0),
    faceId_(),
    facePatchId_(),
863
    faceFlip_()
864
865
{
    read(dict);
866
    writeFileHeader(file());
867
868
}

869

870
Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
871
872
873
(
    const word& name,
    const objectRegistry& obr,
874
    const dictionary& dict
875
876
)
:
877
    fieldValue(name, obr, dict, typeName),
878
    regionType_(regionTypeNames_.read(dict.lookup("regionType"))),
879
    operation_(operationTypeNames_.read(dict.lookup("operation"))),
880
881
882
883
884
    postOperation_
    (
        postOperationTypeNames_
        [dict.lookupOrDefault<word>("postOperation", "none")]
    ),
885
    weightFieldName_("none"),
886
887
    orientWeightField_(false),
    orientedFieldsStart_(labelMax),
888
    writeArea_(dict.lookupOrDefault("writeArea", false)),
889
    nFaces_(0),
890
891
    faceId_(),
    facePatchId_(),
892
    faceFlip_()
893
{
894
    read(dict);
895
    writeFileHeader(file());
896
897
898
899
900
}


// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

901
Foam::functionObjects::fieldValues::surfaceFieldValue::~surfaceFieldValue()
902
903
904
905
906
{}


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

907
bool Foam::functionObjects::fieldValues::surfaceFieldValue::read
908
909
910
(
    const dictionary& dict
)
911
{
Andrew Heather's avatar
Andrew Heather committed
912
    fieldValue::read(dict);
913
    initialise(dict);
914

915
    return true;
916
917
918
}


919
bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
920
{
921
    if (surfacePtr_.valid())
922
    {
923
924
        surfacePtr_().update();
    }
925

926
    if (operation_ != opNone)
927
    {
928
929
930
931
932
933
        fieldValue::write();

        if (Pstream::master())
        {
            writeTime(file());
        }
934
    }
935

936
937
938
    if (writeArea_)
    {
        totalArea_ = totalArea();
939
940
        Log << "    total area = " << totalArea_ << endl;

941
        if (operation_ != opNone && Pstream::master())
942
        {
943
            file() << tab << totalArea_;
944
        }
945
    }
946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
    // Many operations use the Sf field
    vectorField Sf;
    if (needsSf())
    {
        if (regionType_ == stSurface)
        {
            const surfMesh& s = dynamicCast<const surfMesh>(obr());
            Sf = s.Sf();
        }
        else if (surfacePtr_.valid())
        {
            Sf = surfacePtr_().Sf();
        }
        else
        {
            Sf = filterField(mesh_.Sf(), true); // Oriented Sf
        }
    }

    // Faces and points for surface format (if specified)
    faceList faces;
    pointField points;

    if (surfaceWriterPtr_.valid())
    {
        if (regionType_ == stSurface || surfacePtr_.valid())
        {
            combineSurfaceGeometry(faces, points);
        }
        else
        {
            combineMeshGeometry(faces, points);
        }
    }

    meshedSurfRef surfToWrite(points, faces);

    // Only a few weight types (scalar, vector)
985
986
    if (weightFieldName_ != "none")
    {
987
988
        if (validField<scalar>(weightFieldName_))
        {
989
            scalarField weightField
990
            (
991
992
993
994
995
996
                getFieldValues<scalar>
                (
                    weightFieldName_,
                    true,
                    orientWeightField_
                )
997
            );
998

999
1000
1001
1002
1003
            // Process the fields
            writeAll(Sf, weightField, surfToWrite);
        }
        else if (validField<vector>(weightFieldName_))
        {
1004
            vectorField weightField
1005
            (
1006
1007
1008
1009
1010
1011
                getFieldValues<vector>
                (
                    weightFieldName_,
                    true,
                    orientWeightField_
                )
1012
            );
1013

1014
1015
1016
1017
            // Process the fields
            writeAll(Sf, weightField, surfToWrite);
        }
        else
1018
        {
1019
1020
1021
1022
            FatalErrorInFunction
                << "weightField " << weightFieldName_
                << " not found or an unsupported type"
                << abort(FatalError);
1023
        }
1024
    }
1025
1026
1027
1028
1029
1030
1031
1032
    else
    {
        // Default is a zero-size scalar weight field (ie, weight = 1)
        scalarField weightField;

        // Process the fields
        writeAll(Sf, weightField, surfToWrite);
    }
1033

1034
    if (operation_ != opNone && Pstream::master())
1035
    {
1036
        file() << endl;
1037
    }
1038

1039
    Log << endl;
1040
1041

    return true;
1042
1043
1044
1045
}


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