1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "sampledIsoSurface.H"
27 #include "dictionary.H"
28 #include "volFields.H"
29 #include "volPointInterpolation.H"
30 #include "addToRunTimeSelectionTable.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 defineTypeNameAndDebug(sampledIsoSurface, 0);
37 addNamedToRunTimeSelectionTable
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 void Foam::sampledIsoSurface::getIsoFields() const
50 const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
55 if (fvm.foundObject<volScalarField>(isoField_))
59 Info<< "sampledIsoSurface::getIsoField() : lookup volField "
62 storedVolFieldPtr_.clear();
63 volFieldPtr_ = &fvm.lookupObject<volScalarField>(isoField_);
67 // Bit of a hack. Read field and store.
71 Info<< "sampledIsoSurface::getIsoField() : checking "
72 << isoField_ << " for same time " << fvm.time().timeName()
78 storedVolFieldPtr_.empty()
79 || (fvm.time().timeName() != storedVolFieldPtr_().instance())
84 Info<< "sampledIsoSurface::getIsoField() : reading volField "
85 << isoField_ << " from time " << fvm.time().timeName()
89 storedVolFieldPtr_.reset
96 fvm.time().timeName(),
105 volFieldPtr_ = storedVolFieldPtr_.operator->();
114 if (!subMeshPtr_.valid())
116 word pointFldName = "volPointInterpolate(" + isoField_ + ')';
118 if (fvm.foundObject<pointScalarField>(pointFldName))
122 Info<< "sampledIsoSurface::getIsoField() : lookup pointField "
123 << pointFldName << endl;
125 pointFieldPtr_ = &fvm.lookupObject<pointScalarField>(pointFldName);
129 // Not in registry. Interpolate.
133 Info<< "sampledIsoSurface::getIsoField() : checking pointField "
134 << pointFldName << " for same time "
135 << fvm.time().timeName() << endl;
140 storedPointFieldPtr_.empty()
141 || (fvm.time().timeName() != storedPointFieldPtr_().instance())
146 Info<< "sampledIsoSurface::getIsoField() :"
147 << " interpolating volField " << volFieldPtr_->name()
148 << " to get pointField " << pointFldName << endl;
151 storedPointFieldPtr_.reset
153 volPointInterpolation::New(fvm)
154 .interpolate(*volFieldPtr_).ptr()
156 storedPointFieldPtr_->checkOut();
157 pointFieldPtr_ = storedPointFieldPtr_.operator->();
162 // If averaging redo the volField. Can only be done now since needs the
166 storedVolFieldPtr_.reset(average(fvm, *pointFieldPtr_).ptr());
167 volFieldPtr_ = storedVolFieldPtr_.operator->();
173 Info<< "sampledIsoSurface::getIsoField() : volField "
174 << volFieldPtr_->name() << " min:" << min(*volFieldPtr_).value()
175 << " max:" << max(*volFieldPtr_).value() << endl;
176 Info<< "sampledIsoSurface::getIsoField() : pointField "
177 << pointFieldPtr_->name()
178 << " min:" << gMin(pointFieldPtr_->internalField())
179 << " max:" << gMax(pointFieldPtr_->internalField()) << endl;
184 // Get subMesh variants
185 const fvMesh& subFvm = subMeshPtr_().subMesh();
187 // Either lookup on the submesh or subset the whole-mesh volField
189 if (subFvm.foundObject<volScalarField>(isoField_))
193 Info<< "sampledIsoSurface::getIsoField() :"
194 << " submesh lookup volField "
195 << isoField_ << endl;
197 storedVolSubFieldPtr_.clear();
198 volSubFieldPtr_ = &subFvm.lookupObject<volScalarField>(isoField_);
204 Info<< "sampledIsoSurface::getIsoField() : subsetting volField "
205 << isoField_ << endl;
207 storedVolSubFieldPtr_.reset
209 subMeshPtr_().interpolate
214 storedVolSubFieldPtr_->checkOut();
215 volSubFieldPtr_ = storedVolSubFieldPtr_.operator->();
219 // Pointfield on submesh
222 "volPointInterpolate("
223 + volSubFieldPtr_->name()
226 if (subFvm.foundObject<pointScalarField>(pointFldName))
230 Info<< "sampledIsoSurface::getIsoField() :"
231 << " submesh lookup pointField " << pointFldName << endl;
233 storedPointSubFieldPtr_.clear();
234 pointSubFieldPtr_ = &subFvm.lookupObject<pointScalarField>
243 Info<< "sampledIsoSurface::getIsoField() :"
244 << " interpolating submesh volField "
245 << volSubFieldPtr_->name()
246 << " to get submesh pointField " << pointFldName << endl;
248 storedPointSubFieldPtr_.reset
250 volPointInterpolation::New
253 ).interpolate(*volSubFieldPtr_).ptr()
255 storedPointSubFieldPtr_->checkOut();
256 pointSubFieldPtr_ = storedPointSubFieldPtr_.operator->();
261 // If averaging redo the volField. Can only be done now since needs the
265 storedVolSubFieldPtr_.reset
267 average(subFvm, *pointSubFieldPtr_).ptr()
269 volSubFieldPtr_ = storedVolSubFieldPtr_.operator->();
275 Info<< "sampledIsoSurface::getIsoField() : volSubField "
276 << volSubFieldPtr_->name()
277 << " min:" << min(*volSubFieldPtr_).value()
278 << " max:" << max(*volSubFieldPtr_).value() << endl;
279 Info<< "sampledIsoSurface::getIsoField() : pointSubField "
280 << pointSubFieldPtr_->name()
281 << " min:" << gMin(pointSubFieldPtr_->internalField())
282 << " max:" << gMax(pointSubFieldPtr_->internalField()) << endl;
288 Foam::tmp<Foam::volScalarField> Foam::sampledIsoSurface::average
291 const pointScalarField& pfld
294 tmp<volScalarField> tcellAvg
301 mesh.time().timeName(),
308 dimensionedScalar("zero", dimless, scalar(0.0))
311 volScalarField& cellAvg = tcellAvg();
313 labelField nPointCells(mesh.nCells(), 0);
315 for (label pointI = 0; pointI < mesh.nPoints(); pointI++)
317 const labelList& pCells = mesh.pointCells(pointI);
321 label cellI = pCells[i];
323 cellAvg[cellI] += pfld[pointI];
324 nPointCells[cellI]++;
328 forAll(cellAvg, cellI)
330 cellAvg[cellI] /= nPointCells[cellI];
332 // Give value to calculatedFvPatchFields
333 cellAvg.correctBoundaryConditions();
339 Foam::tmp<Foam::pointScalarField> Foam::sampledIsoSurface::average
341 const pointMesh& pMesh,
342 const volScalarField& fld
345 tmp<pointScalarField> tpointAvg
352 fld.time().timeName(),
359 dimensionedScalar("zero", dimless, scalar(0.0))
362 pointScalarField& pointAvg = tpointAvg();
364 for (label pointI = 0; pointI < fld.mesh().nPoints(); pointI++)
366 const labelList& pCells = fld.mesh().pointCells(pointI);
370 pointAvg[pointI] += fld[pCells[i]];
372 pointAvg[pointI] /= pCells.size();
374 // Give value to calculatedFvPatchFields
375 pointAvg.correctBoundaryConditions();
381 bool Foam::sampledIsoSurface::updateGeometry() const
383 const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
386 if (fvm.time().timeIndex() == prevTimeIndex_)
392 if (zoneID_.index() != -1 && !subMeshPtr_.valid())
394 const polyBoundaryMesh& patches = mesh().boundaryMesh();
396 // Patch to put exposed internal faces into
397 label exposedPatchI = patches.findPatchID(exposedPatchName_);
401 Info<< "Allocating subset of size "
402 << mesh().cellZones()[zoneID_.index()].size()
403 << " with exposed faces into patch "
404 << patches[exposedPatchI].name() << endl;
409 new fvMeshSubset(fvm)
411 subMeshPtr_().setLargeCellSubset
413 labelHashSet(mesh().cellZones()[zoneID_.index()]),
419 prevTimeIndex_ = fvm.time().timeIndex();
422 // Clear any stored topo
426 // Clear derived data
429 if (subMeshPtr_.valid())
461 Pout<< "sampledIsoSurface::updateGeometry() : constructed iso:"
463 << " regularise : " << regularise_ << nl
464 << " average : " << average_ << nl
465 << " isoField : " << isoField_ << nl
466 << " isoValue : " << isoVal_ << nl;
467 if (subMeshPtr_.valid())
469 Pout<< " zone size : " << subMeshPtr_().subMesh().nCells()
472 Pout<< " points : " << points().size() << nl
473 << " tris : " << surface().size() << nl
474 << " cut cells : " << surface().meshCells().size()
482 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
484 Foam::sampledIsoSurface::sampledIsoSurface
487 const polyMesh& mesh,
488 const dictionary& dict
491 sampledSurface(name, mesh, dict),
492 isoField_(dict.lookup("isoField")),
493 isoVal_(readScalar(dict.lookup("isoValue"))),
494 mergeTol_(dict.lookupOrDefault("mergeTol", 1E-6)),
495 regularise_(dict.lookupOrDefault("regularise", true)),
496 average_(dict.lookupOrDefault("average", false)),
497 zoneID_(dict.lookupOrDefault("zone", word::null), mesh.cellZones()),
498 exposedPatchName_(word::null),
502 storedVolFieldPtr_(NULL),
504 storedPointFieldPtr_(NULL),
507 if (!sampledSurface::interpolate())
511 "sampledIsoSurface::sampledIsoSurface"
512 "(const word&, const polyMesh&, const dictionary&)",
514 ) << "Non-interpolated iso surface not supported since triangles"
515 << " span across cells." << exit(FatalIOError);
518 if (zoneID_.index() != -1)
520 dict.lookup("exposedPatchName") >> exposedPatchName_;
522 if (mesh.boundaryMesh().findPatchID(exposedPatchName_) == -1)
526 "sampledIsoSurface::sampledIsoSurface"
527 "(const word&, const polyMesh&, const dictionary&)",
529 ) << "Cannot find patch " << exposedPatchName_
530 << " in which to put exposed faces." << endl
531 << "Valid patches are " << mesh.boundaryMesh().names()
532 << exit(FatalIOError);
535 if (debug && zoneID_.index() != -1)
537 Info<< "Restricting to cellZone " << zoneID_.name()
538 << " with exposed internal faces into patch "
539 << exposedPatchName_ << endl;
545 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
547 Foam::sampledIsoSurface::~sampledIsoSurface()
551 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
553 bool Foam::sampledIsoSurface::needsUpdate() const
555 const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
557 return fvm.time().timeIndex() != prevTimeIndex_;
561 bool Foam::sampledIsoSurface::expire()
567 // Clear derived data
570 // already marked as expired
571 if (prevTimeIndex_ == -1)
582 bool Foam::sampledIsoSurface::update()
584 return updateGeometry();
588 Foam::tmp<Foam::scalarField> Foam::sampledIsoSurface::sample
590 const volScalarField& vField
593 return sampleField(vField);
597 Foam::tmp<Foam::vectorField> Foam::sampledIsoSurface::sample
599 const volVectorField& vField
602 return sampleField(vField);
606 Foam::tmp<Foam::sphericalTensorField> Foam::sampledIsoSurface::sample
608 const volSphericalTensorField& vField
611 return sampleField(vField);
615 Foam::tmp<Foam::symmTensorField> Foam::sampledIsoSurface::sample
617 const volSymmTensorField& vField
620 return sampleField(vField);
624 Foam::tmp<Foam::tensorField> Foam::sampledIsoSurface::sample
626 const volTensorField& vField
629 return sampleField(vField);
633 Foam::tmp<Foam::scalarField> Foam::sampledIsoSurface::interpolate
635 const interpolation<scalar>& interpolator
638 return interpolateField(interpolator);
642 Foam::tmp<Foam::vectorField> Foam::sampledIsoSurface::interpolate
644 const interpolation<vector>& interpolator
647 return interpolateField(interpolator);
650 Foam::tmp<Foam::sphericalTensorField> Foam::sampledIsoSurface::interpolate
652 const interpolation<sphericalTensor>& interpolator
655 return interpolateField(interpolator);
659 Foam::tmp<Foam::symmTensorField> Foam::sampledIsoSurface::interpolate
661 const interpolation<symmTensor>& interpolator
664 return interpolateField(interpolator);
668 Foam::tmp<Foam::tensorField> Foam::sampledIsoSurface::interpolate
670 const interpolation<tensor>& interpolator
673 return interpolateField(interpolator);
677 void Foam::sampledIsoSurface::print(Ostream& os) const
679 os << "sampledIsoSurface: " << name() << " :"
680 << " field :" << isoField_
681 << " value :" << isoVal_;
682 //<< " faces:" << faces().size() // note: possibly no geom yet
683 //<< " points:" << points().size();
687 // ************************************************************************* //