1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "timeVaryingMappedFixedValueFvPatchField.H"
29 #include "triSurfaceTools.H"
30 #include "triSurface.H"
34 #include "AverageIOField.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 timeVaryingMappedFixedValueFvPatchField<Type>::
45 timeVaryingMappedFixedValueFvPatchField
48 const DimensionedField<Type, volMesh>& iF
51 fixedValueFvPatchField<Type>(p, iF),
52 fieldTableName_(iF.name()),
56 nearestVertexWeight_(0),
59 startSampledValues_(0),
60 startAverage_(pTraits<Type>::zero),
63 endAverage_(pTraits<Type>::zero)
67 Pout<< "timeVaryingMappedFixedValue :"
68 << " construct from fvPatch and internalField" << endl;
74 timeVaryingMappedFixedValueFvPatchField<Type>::
75 timeVaryingMappedFixedValueFvPatchField
77 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf,
79 const DimensionedField<Type, volMesh>& iF,
80 const fvPatchFieldMapper& mapper
83 fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
84 fieldTableName_(ptf.fieldTableName_),
85 setAverage_(ptf.setAverage_),
88 nearestVertexWeight_(0),
91 startSampledValues_(0),
92 startAverage_(pTraits<Type>::zero),
95 endAverage_(pTraits<Type>::zero)
99 Pout<< "timeVaryingMappedFixedValue"
100 << " : construct from mappedFixedValue and mapper" << endl;
106 timeVaryingMappedFixedValueFvPatchField<Type>::
107 timeVaryingMappedFixedValueFvPatchField
110 const DimensionedField<Type, volMesh>& iF,
111 const dictionary& dict
114 fixedValueFvPatchField<Type>(p, iF),
115 fieldTableName_(iF.name()),
116 setAverage_(readBool(dict.lookup("setAverage"))),
119 nearestVertexWeight_(0),
121 startSampleTime_(-1),
122 startSampledValues_(0),
123 startAverage_(pTraits<Type>::zero),
125 endSampledValues_(0),
126 endAverage_(pTraits<Type>::zero)
130 Pout<< "timeVaryingMappedFixedValue : construct from dictionary"
134 if (dict.found("fieldTableName"))
136 dict.lookup("fieldTableName") >> fieldTableName_;
139 if (dict.found("value"))
141 fvPatchField<Type>::operator==(Field<Type>("value", dict, p.size()));
151 timeVaryingMappedFixedValueFvPatchField<Type>::
152 timeVaryingMappedFixedValueFvPatchField
154 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf
157 fixedValueFvPatchField<Type>(ptf),
158 fieldTableName_(ptf.fieldTableName_),
159 setAverage_(ptf.setAverage_),
160 referenceCS_(ptf.referenceCS_),
161 nearestVertex_(ptf.nearestVertex_),
162 nearestVertexWeight_(ptf.nearestVertexWeight_),
163 sampleTimes_(ptf.sampleTimes_),
164 startSampleTime_(ptf.startSampleTime_),
165 startSampledValues_(ptf.startSampledValues_),
166 startAverage_(ptf.startAverage_),
167 endSampleTime_(ptf.endSampleTime_),
168 endSampledValues_(ptf.endSampledValues_),
169 endAverage_(ptf.endAverage_)
173 Pout<< "timeVaryingMappedFixedValue : copy construct"
181 timeVaryingMappedFixedValueFvPatchField<Type>::
182 timeVaryingMappedFixedValueFvPatchField
184 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf,
185 const DimensionedField<Type, volMesh>& iF
188 fixedValueFvPatchField<Type>(ptf, iF),
189 fieldTableName_(ptf.fieldTableName_),
190 setAverage_(ptf.setAverage_),
191 referenceCS_(ptf.referenceCS_),
192 nearestVertex_(ptf.nearestVertex_),
193 nearestVertexWeight_(ptf.nearestVertexWeight_),
194 sampleTimes_(ptf.sampleTimes_),
195 startSampleTime_(ptf.startSampleTime_),
196 startSampledValues_(ptf.startSampledValues_),
197 startAverage_(ptf.startAverage_),
198 endSampleTime_(ptf.endSampleTime_),
199 endSampledValues_(ptf.endSampledValues_),
200 endAverage_(ptf.endAverage_)
204 Pout<< "timeVaryingMappedFixedValue :"
205 << " copy construct, resetting internal field" << endl;
210 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
213 void timeVaryingMappedFixedValueFvPatchField<Type>::autoMap
215 const fvPatchFieldMapper& m
218 fixedValueFvPatchField<Type>::autoMap(m);
219 if (startSampledValues_.size() > 0)
221 startSampledValues_.autoMap(m);
222 endSampledValues_.autoMap(m);
228 void timeVaryingMappedFixedValueFvPatchField<Type>::rmap
230 const fvPatchField<Type>& ptf,
231 const labelList& addr
234 fixedValueFvPatchField<Type>::rmap(ptf, addr);
236 const timeVaryingMappedFixedValueFvPatchField<Type>& tiptf =
237 refCast<const timeVaryingMappedFixedValueFvPatchField<Type> >(ptf);
239 startSampledValues_.rmap(tiptf.startSampledValues_, addr);
240 endSampledValues_.rmap(tiptf.endSampledValues_, addr);
245 void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
247 // Read the sample points
249 pointIOField samplePoints
254 this->db().time().constant(),
255 "boundaryData"/this->patch().name(),
258 IOobject::AUTO_WRITE,
263 const fileName samplePointsFile = samplePoints.filePath();
267 Info<< "timeVaryingMappedFixedValueFvPatchField :"
268 << " Read " << samplePoints.size() << " sample points from "
269 << samplePointsFile << endl;
272 // Determine coordinate system from samplePoints
274 if (samplePoints.size() < 3)
278 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
279 ) << "Only " << samplePoints.size() << " points read from file "
280 << samplePoints.objectPath() << nl
281 << "Need at least three non-colinear samplePoints"
282 << " to be able to interpolate."
283 << "\n on patch " << this->patch().name()
284 << " of field " << this->dimensionedInternalField().name()
285 << " in file " << this->dimensionedInternalField().objectPath()
289 const point& p0 = samplePoints[0];
291 // Find point separate from p0
295 for (label i = 1; i < samplePoints.size(); i++)
297 e1 = samplePoints[i] - p0;
299 scalar magE1 = mag(e1);
309 // Find point that makes angle with n1
314 for (label i = index1+1; i < samplePoints.size(); i++)
316 e2 = samplePoints[i] - p0;
318 scalar magE2 = mag(e2);
326 scalar magN = mag(n);
341 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
342 ) << "Cannot find points that make valid normal." << nl
343 << "Need at least three sample points which are not in a line."
344 << "\n on patch " << this->patch().name()
345 << " of points " << samplePoints.name()
346 << " in file " << samplePoints.objectPath()
352 Info<< "timeVaryingMappedFixedValueFvPatchField :"
353 << " Used points " << p0 << ' ' << samplePoints[index1]
354 << ' ' << samplePoints[index2]
355 << " to define coordinate system with normal " << n << endl;
369 tmp<vectorField> tlocalVertices
371 referenceCS().localPosition(samplePoints)
373 const vectorField& localVertices = tlocalVertices();
375 // Determine triangulation
376 List<vector2D> localVertices2D(localVertices.size());
377 forAll(localVertices, i)
379 localVertices2D[i][0] = localVertices[i][0];
380 localVertices2D[i][1] = localVertices[i][1];
383 triSurface s(triSurfaceTools::delaunay2D(localVertices2D));
385 tmp<pointField> localFaceCentres
387 referenceCS().localPosition
389 this->patch().patch().faceCentres()
395 Pout<< "readSamplePoints :"
396 <<" Dumping triangulated surface to triangulation.stl" << endl;
397 s.write(this->db().time().path()/"triangulation.stl");
399 OFstream str(this->db().time().path()/"localFaceCentres.obj");
400 Pout<< "readSamplePoints :"
401 << " Dumping face centres to " << str.name() << endl;
403 forAll(localFaceCentres(), i)
405 const point& p = localFaceCentres()[i];
406 str<< "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
410 // Determine interpolation onto face centres.
411 triSurfaceTools::calcInterpolationWeights
414 localFaceCentres, // points to interpolate to
421 // Read the times for which data is available
423 const fileName samplePointsDir = samplePointsFile.path();
425 sampleTimes_ = Time::findTimes(samplePointsDir);
429 Info<< "timeVaryingMappedFixedValueFvPatchField : In directory "
430 << samplePointsDir << " found times " << timeNames(sampleTimes_)
437 wordList timeVaryingMappedFixedValueFvPatchField<Type>::timeNames
439 const instantList& times
442 wordList names(times.size());
446 names[i] = times[i].name();
453 void timeVaryingMappedFixedValueFvPatchField<Type>::findTime
455 const fileName& instance,
456 const fileName& local,
457 const scalar timeVal,
462 lo = startSampleTime_;
465 for (label i = startSampleTime_+1; i < sampleTimes_.size(); i++)
467 if (sampleTimes_[i].value() > timeVal)
479 FatalErrorIn("findTime")
480 << "Cannot find starting sampling values for current time "
482 << "Have sampling values for times "
483 << timeNames(sampleTimes_) << nl
485 << this->db().time().constant()/"boundaryData"/this->patch().name()
486 << "\n on patch " << this->patch().name()
487 << " of field " << fieldTableName_
491 if (lo < sampleTimes_.size()-1)
501 Pout<< "findTime : Found time " << timeVal << " after"
502 << " index:" << lo << " time:" << sampleTimes_[lo].value()
507 Pout<< "findTime : Found time " << timeVal << " inbetween"
508 << " index:" << lo << " time:" << sampleTimes_[lo].value()
509 << " and index:" << hi << " time:" << sampleTimes_[hi].value()
517 void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
520 if (startSampleTime_ == -1 && endSampleTime_ == -1)
525 // Find current time in sampleTimes
531 this->db().time().constant(),
532 "boundaryData"/this->patch().name(),
533 this->db().time().value(),
538 // Update sampled data fields.
540 if (lo != startSampleTime_)
542 startSampleTime_ = lo;
544 if (startSampleTime_ == endSampleTime_)
546 // No need to reread since are end values
549 Pout<< "checkTable : Setting startValues to (already read) "
551 /this->patch().name()
552 /sampleTimes_[startSampleTime_].name()
555 startSampledValues_ = endSampledValues_;
556 startAverage_ = endAverage_;
562 Pout<< "checkTable : Reading startValues from "
564 /this->patch().name()
565 /sampleTimes_[lo].name()
570 // Reread values and interpolate
571 AverageIOField<Type> vals
576 this->db().time().constant(),
578 /this->patch().name()
579 /sampleTimes_[startSampleTime_].name(),
582 IOobject::AUTO_WRITE,
587 startAverage_ = vals.average();
588 startSampledValues_ = interpolate(vals);
592 if (hi != endSampleTime_)
596 if (endSampleTime_ == -1)
598 // endTime no longer valid. Might as well clear endValues.
601 Pout<< "checkTable : Clearing endValues" << endl;
603 endSampledValues_.clear();
609 Pout<< "checkTable : Reading endValues from "
611 /this->patch().name()
612 /sampleTimes_[endSampleTime_].name()
615 // Reread values and interpolate
616 AverageIOField<Type> vals
621 this->db().time().constant(),
623 /this->patch().name()
624 /sampleTimes_[endSampleTime_].name(),
627 IOobject::AUTO_WRITE,
631 endAverage_ = vals.average();
632 endSampledValues_ = interpolate(vals);
639 tmp<Field<Type> > timeVaryingMappedFixedValueFvPatchField<Type>::interpolate
641 const Field<Type>& sourceFld
644 tmp<Field<Type> > tfld(new Field<Type>(nearestVertex_.size()));
645 Field<Type>& fld = tfld();
649 const FixedList<label, 3>& verts = nearestVertex_[i];
650 const FixedList<scalar, 3>& w = nearestVertexWeight_[i];
657 fld[i] = sourceFld[verts[0]];
663 w[0]*sourceFld[verts[0]]
664 + w[1]*sourceFld[verts[1]];
670 w[0]*sourceFld[verts[0]]
671 + w[1]*sourceFld[verts[1]]
672 + w[2]*sourceFld[verts[2]];
680 void timeVaryingMappedFixedValueFvPatchField<Type>::updateCoeffs()
689 // Interpolate between the sampled data
693 if (endSampleTime_ == -1)
698 Pout<< "updateCoeffs : Sampled, non-interpolated values"
699 << " from start time:"
700 << sampleTimes_[startSampleTime_].name() << nl;
703 this->operator==(startSampledValues_);
704 wantedAverage = startAverage_;
708 scalar start = sampleTimes_[startSampleTime_].value();
709 scalar end = sampleTimes_[endSampleTime_].value();
711 scalar s = (this->db().time().value()-start)/(end-start);
715 Pout<< "updateCoeffs : Sampled, interpolated values"
716 << " between start time:"
717 << sampleTimes_[startSampleTime_].name()
718 << " and end time:" << sampleTimes_[endSampleTime_].name()
719 << " with weight:" << s << endl;
722 this->operator==((1-s)*startSampledValues_ + s*endSampledValues_);
723 wantedAverage = (1-s)*startAverage_ + s*endAverage_;
726 // Enforce average. Either by scaling (if scaling factor > 0.5) or by
730 const Field<Type>& fld = *this;
733 gSum(this->patch().magSf()*fld)
734 /gSum(this->patch().magSf());
738 Pout<< "updateCoeffs :"
739 << " actual average:" << averagePsi
740 << " wanted average:" << wantedAverage
744 if (mag(averagePsi) < VSMALL)
746 // Field too small to scale. Offset instead.
747 const Type offset = wantedAverage - averagePsi;
750 Pout<< "updateCoeffs :"
751 << " offsetting with:" << offset << endl;
753 this->operator==(fld+offset);
757 const scalar scale = mag(wantedAverage)/mag(averagePsi);
761 Pout<< "updateCoeffs :"
762 << " scaling with:" << scale << endl;
764 this->operator==(scale*fld);
770 Pout<< "updateCoeffs : set fixedValue to min:" << gMin(*this)
771 << " max:" << gMax(*this) << endl;
774 fixedValueFvPatchField<Type>::updateCoeffs();
779 void timeVaryingMappedFixedValueFvPatchField<Type>::write(Ostream& os) const
781 fvPatchField<Type>::write(os);
782 os.writeKeyword("setAverage") << setAverage_ << token::END_STATEMENT << nl;
784 if (fieldTableName_ != this->dimensionedInternalField().name())
786 os.writeKeyword("fieldTableName") << fieldTableName_ << token::END_STATEMENT << nl;
789 this->writeEntry("value", os);
793 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
795 } // End namespace Foam
797 // ************************************************************************* //