1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 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"
31 #include "cartesianCS.H"
35 #include "AverageIOField.H"
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
45 timeVaryingMappedFixedValueFvPatchField<Type>::
46 timeVaryingMappedFixedValueFvPatchField
49 const DimensionedField<Type, volMesh>& iF
52 fixedValueFvPatchField<Type>(p, iF),
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 setAverage_(ptf.setAverage_),
87 nearestVertexWeight_(0),
90 startSampledValues_(0),
91 startAverage_(pTraits<Type>::zero),
94 endAverage_(pTraits<Type>::zero)
98 Pout<< "timeVarying<appedFixedValue"
99 << " : construct from mappedFixedValue and mapper" << endl;
105 timeVaryingMappedFixedValueFvPatchField<Type>::
106 timeVaryingMappedFixedValueFvPatchField
109 const DimensionedField<Type, volMesh>& iF,
110 const dictionary& dict
113 fixedValueFvPatchField<Type>(p, iF),
114 setAverage_(readBool(dict.lookup("setAverage"))),
117 nearestVertexWeight_(0),
119 startSampleTime_(-1),
120 startSampledValues_(0),
121 startAverage_(pTraits<Type>::zero),
123 endSampledValues_(0),
124 endAverage_(pTraits<Type>::zero)
128 Pout<< "timeVaryingMappedFixedValue : construct from dictionary"
132 if (dict.found("value"))
134 fvPatchField<Type>::operator==(Field<Type>("value", dict, p.size()));
144 timeVaryingMappedFixedValueFvPatchField<Type>::
145 timeVaryingMappedFixedValueFvPatchField
147 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf
150 fixedValueFvPatchField<Type>(ptf),
151 setAverage_(ptf.setAverage_),
152 referenceCS_(ptf.referenceCS_),
153 nearestVertex_(ptf.nearestVertex_),
154 nearestVertexWeight_(ptf.nearestVertexWeight_),
155 sampleTimes_(ptf.sampleTimes_),
156 startSampleTime_(ptf.startSampleTime_),
157 startSampledValues_(ptf.startSampledValues_),
158 startAverage_(ptf.startAverage_),
159 endSampleTime_(ptf.endSampleTime_),
160 endSampledValues_(ptf.endSampledValues_),
161 endAverage_(ptf.endAverage_)
165 Pout<< "timeVaryingMappedFixedValue : copy construct"
173 timeVaryingMappedFixedValueFvPatchField<Type>::
174 timeVaryingMappedFixedValueFvPatchField
176 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf,
177 const DimensionedField<Type, volMesh>& iF
180 fixedValueFvPatchField<Type>(ptf, iF),
181 setAverage_(ptf.setAverage_),
182 referenceCS_(ptf.referenceCS_),
183 nearestVertex_(ptf.nearestVertex_),
184 nearestVertexWeight_(ptf.nearestVertexWeight_),
185 sampleTimes_(ptf.sampleTimes_),
186 startSampleTime_(ptf.startSampleTime_),
187 startSampledValues_(ptf.startSampledValues_),
188 startAverage_(ptf.startAverage_),
189 endSampleTime_(ptf.endSampleTime_),
190 endSampledValues_(ptf.endSampledValues_),
191 endAverage_(ptf.endAverage_)
195 Pout<< "timeVaryingMappedFixedValue :"
196 << " copy construct, resetting internal field" << endl;
201 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
204 void timeVaryingMappedFixedValueFvPatchField<Type>::autoMap
206 const fvPatchFieldMapper& m
209 fixedValueFvPatchField<Type>::autoMap(m);
210 startSampledValues_.autoMap(m);
211 endSampledValues_.autoMap(m);
216 void timeVaryingMappedFixedValueFvPatchField<Type>::rmap
218 const fvPatchField<Type>& ptf,
219 const labelList& addr
222 fixedValueFvPatchField<Type>::rmap(ptf, addr);
224 const timeVaryingMappedFixedValueFvPatchField<Type>& tiptf =
225 refCast<const timeVaryingMappedFixedValueFvPatchField<Type> >(ptf);
227 startSampledValues_.rmap(tiptf.startSampledValues_, addr);
228 endSampledValues_.rmap(tiptf.endSampledValues_, addr);
233 void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
235 // Read the sample points
237 pointIOField samplePoints
242 this->db().time().constant(),
243 "boundaryData"/this->patch().name(),
246 IOobject::AUTO_WRITE,
251 const fileName samplePointsFile = samplePoints.filePath();
255 Info<< "timeVaryingMappedFixedValueFvPatchField :"
256 << " Read " << samplePoints.size() << " sample points from "
257 << samplePointsFile << endl;
260 // Determine coordinate system from samplePoints
262 if (samplePoints.size() < 3)
266 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
267 ) << "Only " << samplePoints.size() << " points read from file "
268 << samplePoints.objectPath() << nl
269 << "Need at least three non-colinear samplePoints"
270 << " to be able to interpolate."
271 << "\n on patch " << this->patch().name()
272 << " of field " << this->dimensionedInternalField().name()
273 << " in file " << this->dimensionedInternalField().objectPath()
277 const point& p0 = samplePoints[0];
279 // Find point separate from p0
283 for (label i = 1; i < samplePoints.size(); i++)
285 e1 = samplePoints[i] - p0;
287 scalar magE1 = mag(e1);
297 // Find point that makes angle with n1
302 for (label i = index1+1; i < samplePoints.size(); i++)
304 e2 = samplePoints[i] - p0;
306 scalar magE2 = mag(e2);
314 scalar magN = mag(n);
329 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
330 ) << "Cannot find points that make valid normal." << nl
331 << "Need at least three sample points which are not in a line."
332 << "\n on patch " << this->patch().name()
333 << " of field " << this->dimensionedInternalField().name()
334 << " in file " << this->dimensionedInternalField().objectPath()
340 Info<< "timeVaryingMappedFixedValueFvPatchField :"
341 << " Used points " << p0 << ' ' << samplePoints[index1]
342 << ' ' << samplePoints[index2]
343 << " to define coordinate system with normal " << n << endl;
357 tmp<vectorField> tlocalVertices
359 referenceCS().localPosition(samplePoints)
361 const vectorField& localVertices = tlocalVertices();
363 // Determine triangulation
364 List<vector2D> localVertices2D(localVertices.size());
365 forAll(localVertices, i)
367 localVertices2D[i][0] = localVertices[i][0];
368 localVertices2D[i][1] = localVertices[i][1];
371 triSurface s(triSurfaceTools::delaunay2D(localVertices2D));
373 tmp<pointField> localFaceCentres
375 referenceCS().localPosition
377 this->patch().patch().faceCentres()
383 Pout<< "readSamplePoints :"
384 <<" Dumping triangulated surface to triangulation.stl" << endl;
385 s.write(this->db().time().path()/"triangulation.stl");
387 OFstream str(this->db().time().path()/"localFaceCentres.obj");
388 Pout<< "readSamplePoints :"
389 << " Dumping face centres to " << str.name() << endl;
391 forAll(localFaceCentres(), i)
393 const point& p = localFaceCentres()[i];
394 str<< "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
398 // Determine interpolation onto face centres.
399 triSurfaceTools::calcInterpolationWeights
402 localFaceCentres, // points to interpolate to
409 // Read the times for which data is available
411 const fileName samplePointsDir = samplePointsFile.path();
413 sampleTimes_ = Time::findTimes(samplePointsDir);
417 Info<< "timeVaryingMappedFixedValueFvPatchField : In directory "
418 << samplePointsDir << " found times " << timeNames(sampleTimes_)
425 wordList timeVaryingMappedFixedValueFvPatchField<Type>::timeNames
427 const instantList& times
430 wordList names(times.size());
434 names[i] = times[i].name();
441 void timeVaryingMappedFixedValueFvPatchField<Type>::findTime
443 const fileName& instance,
444 const fileName& local,
445 const scalar timeVal,
450 lo = startSampleTime_;
453 for (label i = startSampleTime_+1; i < sampleTimes_.size(); i++)
455 if (sampleTimes_[i].value() > timeVal)
467 FatalErrorIn("findTime")
468 << "Cannot find starting sampling values for current time "
470 << "Have sampling values for times "
471 << timeNames(sampleTimes_) << nl
473 << this->db().time().constant()/"boundaryData"/this->patch().name()
474 << "\n on patch " << this->patch().name()
475 << " of field " << this->dimensionedInternalField().name()
476 << " in file " << this->dimensionedInternalField().objectPath()
480 if (lo < sampleTimes_.size()-1)
490 Pout<< "findTime : Found time " << timeVal << " after"
491 << " index:" << lo << " time:" << sampleTimes_[lo].value()
496 Pout<< "findTime : Found time " << timeVal << " inbetween"
497 << " index:" << lo << " time:" << sampleTimes_[lo].value()
498 << " and index:" << hi << " time:" << sampleTimes_[hi].value()
506 void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
509 if (startSampleTime_ == -1 && endSampleTime_ == -1)
514 // Find current time in sampleTimes
520 this->db().time().constant(),
521 "boundaryData"/this->patch().name(),
522 this->db().time().value(),
527 // Update sampled data fields.
529 if (lo != startSampleTime_)
531 startSampleTime_ = lo;
533 if (startSampleTime_ == endSampleTime_)
535 // No need to reread since are end values
538 Pout<< "checkTable : Setting startValues to (already read) "
540 /this->patch().name()
541 /sampleTimes_[startSampleTime_].name()
544 startSampledValues_ = endSampledValues_;
545 startAverage_ = endAverage_;
551 Pout<< "checkTable : Reading startValues from "
553 /this->patch().name()
554 /sampleTimes_[lo].name()
559 // Reread values and interpolate
560 AverageIOField<Type> vals
564 this->dimensionedInternalField().name(),
565 this->db().time().constant(),
567 /this->patch().name()
568 /sampleTimes_[startSampleTime_].name(),
571 IOobject::AUTO_WRITE,
576 startAverage_ = vals.average();
577 startSampledValues_ = interpolate(vals);
581 if (hi != endSampleTime_)
585 if (endSampleTime_ == -1)
587 // endTime no longer valid. Might as well clear endValues.
590 Pout<< "checkTable : Clearing endValues" << endl;
592 endSampledValues_.clear();
598 Pout<< "checkTable : Reading endValues from "
600 /this->patch().name()
601 /sampleTimes_[endSampleTime_].name()
604 // Reread values and interpolate
605 AverageIOField<Type> vals
609 this->dimensionedInternalField().name(),
610 this->db().time().constant(),
612 /this->patch().name()
613 /sampleTimes_[endSampleTime_].name(),
616 IOobject::AUTO_WRITE,
620 endAverage_ = vals.average();
621 endSampledValues_ = interpolate(vals);
628 tmp<Field<Type> > timeVaryingMappedFixedValueFvPatchField<Type>::interpolate
630 const Field<Type>& sourceFld
633 tmp<Field<Type> > tfld(new Field<Type>(nearestVertex_.size()));
634 Field<Type>& fld = tfld();
638 const FixedList<label, 3>& verts = nearestVertex_[i];
639 const FixedList<scalar, 3>& w = nearestVertexWeight_[i];
646 fld[i] = sourceFld[verts[0]];
652 w[0]*sourceFld[verts[0]]
653 + w[1]*sourceFld[verts[1]];
659 w[0]*sourceFld[verts[0]]
660 + w[1]*sourceFld[verts[1]]
661 + w[2]*sourceFld[verts[2]];
669 void timeVaryingMappedFixedValueFvPatchField<Type>::updateCoeffs()
678 // Interpolate between the sampled data
682 if (endSampleTime_ == -1)
687 Pout<< "updateCoeffs : Sampled, non-interpolated values"
688 << " from start time:"
689 << sampleTimes_[startSampleTime_].name() << nl;
692 this->operator==(startSampledValues_);
693 wantedAverage = startAverage_;
697 scalar start = sampleTimes_[startSampleTime_].value();
698 scalar end = sampleTimes_[endSampleTime_].value();
700 scalar s = (this->db().time().value()-start)/(end-start);
704 Pout<< "updateCoeffs : Sampled, interpolated values"
705 << " between start time:"
706 << sampleTimes_[startSampleTime_].name()
707 << " and end time:" << sampleTimes_[endSampleTime_].name()
708 << " with weight:" << s << endl;
711 this->operator==((1-s)*startSampledValues_ + s*endSampledValues_);
712 wantedAverage = (1-s)*startAverage_ + s*endAverage_;
715 // Enforce average. Either by scaling (if scaling factor > 0.5) or by
719 const Field<Type>& fld = *this;
722 gSum(this->patch().magSf()*fld)
723 /gSum(this->patch().magSf());
727 Pout<< "updateCoeffs :"
728 << " actual average:" << averagePsi
729 << " wanted average:" << wantedAverage
733 if (mag(averagePsi) < VSMALL)
735 // Field too small to scale. Offset instead.
736 const Type offset = wantedAverage - averagePsi;
739 Pout<< "updateCoeffs :"
740 << " offsetting with:" << offset << endl;
742 this->operator==(fld+offset);
746 const scalar scale = mag(wantedAverage)/mag(averagePsi);
750 Pout<< "updateCoeffs :"
751 << " scaling with:" << scale << endl;
753 this->operator==(scale*fld);
759 Pout<< "updateCoeffs : set fixedValue to min:" << gMin(*this)
760 << " max:" << gMax(*this) << endl;
763 fixedValueFvPatchField<Type>::updateCoeffs();
768 void timeVaryingMappedFixedValueFvPatchField<Type>::write(Ostream& os) const
770 fvPatchField<Type>::write(os);
771 os.writeKeyword("setAverage") << setAverage_ << token::END_STATEMENT << nl;
772 this->writeEntry("value", os);
776 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
778 } // End namespace Foam
780 // ************************************************************************* //