1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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"
34 #include "AverageIOField.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 timeVaryingMappedFixedValueFvPatchField<Type>::
45 timeVaryingMappedFixedValueFvPatchField
48 const DimensionedField<Type, volMesh>& iF
51 fixedValueFvPatchField<Type>(p, iF),
55 nearestVertexWeight_(0),
58 startSampledValues_(0),
59 startAverage_(pTraits<Type>::zero),
62 endAverage_(pTraits<Type>::zero)
66 Pout<< "timeVaryingMappedFixedValue :"
67 << " construct from fvPatch and internalField" << endl;
73 timeVaryingMappedFixedValueFvPatchField<Type>::
74 timeVaryingMappedFixedValueFvPatchField
76 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf,
78 const DimensionedField<Type, volMesh>& iF,
79 const fvPatchFieldMapper& mapper
82 fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
83 setAverage_(ptf.setAverage_),
86 nearestVertexWeight_(0),
89 startSampledValues_(0),
90 startAverage_(pTraits<Type>::zero),
93 endAverage_(pTraits<Type>::zero)
97 Pout<< "timeVaryingMappedFixedValue"
98 << " : construct from mappedFixedValue and mapper" << endl;
104 timeVaryingMappedFixedValueFvPatchField<Type>::
105 timeVaryingMappedFixedValueFvPatchField
108 const DimensionedField<Type, volMesh>& iF,
109 const dictionary& dict
112 fixedValueFvPatchField<Type>(p, iF),
113 setAverage_(readBool(dict.lookup("setAverage"))),
116 nearestVertexWeight_(0),
118 startSampleTime_(-1),
119 startSampledValues_(0),
120 startAverage_(pTraits<Type>::zero),
122 endSampledValues_(0),
123 endAverage_(pTraits<Type>::zero)
127 Pout<< "timeVaryingMappedFixedValue : construct from dictionary"
131 if (dict.found("value"))
133 fvPatchField<Type>::operator==(Field<Type>("value", dict, p.size()));
143 timeVaryingMappedFixedValueFvPatchField<Type>::
144 timeVaryingMappedFixedValueFvPatchField
146 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf
149 fixedValueFvPatchField<Type>(ptf),
150 setAverage_(ptf.setAverage_),
151 referenceCS_(ptf.referenceCS_),
152 nearestVertex_(ptf.nearestVertex_),
153 nearestVertexWeight_(ptf.nearestVertexWeight_),
154 sampleTimes_(ptf.sampleTimes_),
155 startSampleTime_(ptf.startSampleTime_),
156 startSampledValues_(ptf.startSampledValues_),
157 startAverage_(ptf.startAverage_),
158 endSampleTime_(ptf.endSampleTime_),
159 endSampledValues_(ptf.endSampledValues_),
160 endAverage_(ptf.endAverage_)
164 Pout<< "timeVaryingMappedFixedValue : copy construct"
172 timeVaryingMappedFixedValueFvPatchField<Type>::
173 timeVaryingMappedFixedValueFvPatchField
175 const timeVaryingMappedFixedValueFvPatchField<Type>& ptf,
176 const DimensionedField<Type, volMesh>& iF
179 fixedValueFvPatchField<Type>(ptf, iF),
180 setAverage_(ptf.setAverage_),
181 referenceCS_(ptf.referenceCS_),
182 nearestVertex_(ptf.nearestVertex_),
183 nearestVertexWeight_(ptf.nearestVertexWeight_),
184 sampleTimes_(ptf.sampleTimes_),
185 startSampleTime_(ptf.startSampleTime_),
186 startSampledValues_(ptf.startSampledValues_),
187 startAverage_(ptf.startAverage_),
188 endSampleTime_(ptf.endSampleTime_),
189 endSampledValues_(ptf.endSampledValues_),
190 endAverage_(ptf.endAverage_)
194 Pout<< "timeVaryingMappedFixedValue :"
195 << " copy construct, resetting internal field" << endl;
200 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
203 void timeVaryingMappedFixedValueFvPatchField<Type>::autoMap
205 const fvPatchFieldMapper& m
208 fixedValueFvPatchField<Type>::autoMap(m);
209 if (startSampledValues_.size())
211 startSampledValues_.autoMap(m);
212 endSampledValues_.autoMap(m);
218 void timeVaryingMappedFixedValueFvPatchField<Type>::rmap
220 const fvPatchField<Type>& ptf,
221 const labelList& addr
224 fixedValueFvPatchField<Type>::rmap(ptf, addr);
226 const timeVaryingMappedFixedValueFvPatchField<Type>& tiptf =
227 refCast<const timeVaryingMappedFixedValueFvPatchField<Type> >(ptf);
229 startSampledValues_.rmap(tiptf.startSampledValues_, addr);
230 endSampledValues_.rmap(tiptf.endSampledValues_, addr);
235 void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
237 // Read the sample points
239 pointIOField samplePoints
244 this->db().time().constant(),
245 "boundaryData"/this->patch().name(),
248 IOobject::AUTO_WRITE,
253 const fileName samplePointsFile = samplePoints.filePath();
257 Info<< "timeVaryingMappedFixedValueFvPatchField :"
258 << " Read " << samplePoints.size() << " sample points from "
259 << samplePointsFile << endl;
262 // Determine coordinate system from samplePoints
264 if (samplePoints.size() < 3)
268 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
269 ) << "Only " << samplePoints.size() << " points read from file "
270 << samplePoints.objectPath() << nl
271 << "Need at least three non-colinear samplePoints"
272 << " to be able to interpolate."
273 << "\n on patch " << this->patch().name()
274 << " of field " << this->dimensionedInternalField().name()
275 << " in file " << this->dimensionedInternalField().objectPath()
279 const point& p0 = samplePoints[0];
281 // Find point separate from p0
285 for (label i = 1; i < samplePoints.size(); i++)
287 e1 = samplePoints[i] - p0;
289 scalar magE1 = mag(e1);
299 // Find point that makes angle with n1
304 for (label i = index1+1; i < samplePoints.size(); i++)
306 e2 = samplePoints[i] - p0;
308 scalar magE2 = mag(e2);
316 scalar magN = mag(n);
331 "timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()"
332 ) << "Cannot find points that make valid normal." << nl
333 << "Need at least three sample points which are not in a line."
334 << "\n on patch " << this->patch().name()
335 << " of field " << this->dimensionedInternalField().name()
336 << " in file " << this->dimensionedInternalField().objectPath()
342 Info<< "timeVaryingMappedFixedValueFvPatchField :"
343 << " Used points " << p0 << ' ' << samplePoints[index1]
344 << ' ' << samplePoints[index2]
345 << " to define coordinate system with normal " << n << endl;
359 tmp<vectorField> tlocalVertices
361 referenceCS().localPosition(samplePoints)
363 const vectorField& localVertices = tlocalVertices();
365 // Determine triangulation
366 List<vector2D> localVertices2D(localVertices.size());
367 forAll(localVertices, i)
369 localVertices2D[i][0] = localVertices[i][0];
370 localVertices2D[i][1] = localVertices[i][1];
373 triSurface s(triSurfaceTools::delaunay2D(localVertices2D));
375 tmp<pointField> localFaceCentres
377 referenceCS().localPosition
379 this->patch().patch().faceCentres()
385 Pout<< "readSamplePoints :"
386 <<" Dumping triangulated surface to triangulation.stl" << endl;
387 s.write(this->db().time().path()/"triangulation.stl");
389 OFstream str(this->db().time().path()/"localFaceCentres.obj");
390 Pout<< "readSamplePoints :"
391 << " Dumping face centres to " << str.name() << endl;
393 forAll(localFaceCentres(), i)
395 const point& p = localFaceCentres()[i];
396 str<< "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
400 // Determine interpolation onto face centres.
401 triSurfaceTools::calcInterpolationWeights
404 localFaceCentres, // points to interpolate to
411 // Read the times for which data is available
413 const fileName samplePointsDir = samplePointsFile.path();
415 sampleTimes_ = Time::findTimes(samplePointsDir);
419 Info<< "timeVaryingMappedFixedValueFvPatchField : In directory "
420 << samplePointsDir << " found times " << timeNames(sampleTimes_)
427 wordList timeVaryingMappedFixedValueFvPatchField<Type>::timeNames
429 const instantList& times
432 wordList names(times.size());
436 names[i] = times[i].name();
443 void timeVaryingMappedFixedValueFvPatchField<Type>::findTime
445 const fileName& instance,
446 const fileName& local,
447 const scalar timeVal,
452 lo = startSampleTime_;
455 for (label i = startSampleTime_+1; i < sampleTimes_.size(); i++)
457 if (sampleTimes_[i].value() > timeVal)
469 FatalErrorIn("findTime")
470 << "Cannot find starting sampling values for current time "
472 << "Have sampling values for times "
473 << timeNames(sampleTimes_) << nl
475 << this->db().time().constant()/"boundaryData"/this->patch().name()
476 << "\n on patch " << this->patch().name()
477 << " of field " << this->dimensionedInternalField().name()
478 << " in file " << this->dimensionedInternalField().objectPath()
482 if (lo < sampleTimes_.size()-1)
492 Pout<< "findTime : Found time " << timeVal << " after"
493 << " index:" << lo << " time:" << sampleTimes_[lo].value()
498 Pout<< "findTime : Found time " << timeVal << " inbetween"
499 << " index:" << lo << " time:" << sampleTimes_[lo].value()
500 << " and index:" << hi << " time:" << sampleTimes_[hi].value()
508 void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
511 if (startSampleTime_ == -1 && endSampleTime_ == -1)
516 // Find current time in sampleTimes
522 this->db().time().constant(),
523 "boundaryData"/this->patch().name(),
524 this->db().time().value(),
529 // Update sampled data fields.
531 if (lo != startSampleTime_)
533 startSampleTime_ = lo;
535 if (startSampleTime_ == endSampleTime_)
537 // No need to reread since are end values
540 Pout<< "checkTable : Setting startValues to (already read) "
542 /this->patch().name()
543 /sampleTimes_[startSampleTime_].name()
546 startSampledValues_ = endSampledValues_;
547 startAverage_ = endAverage_;
553 Pout<< "checkTable : Reading startValues from "
555 /this->patch().name()
556 /sampleTimes_[lo].name()
561 // Reread values and interpolate
562 AverageIOField<Type> vals
566 this->dimensionedInternalField().name(),
567 this->db().time().constant(),
569 /this->patch().name()
570 /sampleTimes_[startSampleTime_].name(),
573 IOobject::AUTO_WRITE,
578 startAverage_ = vals.average();
579 startSampledValues_ = interpolate(vals);
583 if (hi != endSampleTime_)
587 if (endSampleTime_ == -1)
589 // endTime no longer valid. Might as well clear endValues.
592 Pout<< "checkTable : Clearing endValues" << endl;
594 endSampledValues_.clear();
600 Pout<< "checkTable : Reading endValues from "
602 /this->patch().name()
603 /sampleTimes_[endSampleTime_].name()
606 // Reread values and interpolate
607 AverageIOField<Type> vals
611 this->dimensionedInternalField().name(),
612 this->db().time().constant(),
614 /this->patch().name()
615 /sampleTimes_[endSampleTime_].name(),
618 IOobject::AUTO_WRITE,
622 endAverage_ = vals.average();
623 endSampledValues_ = interpolate(vals);
630 tmp<Field<Type> > timeVaryingMappedFixedValueFvPatchField<Type>::interpolate
632 const Field<Type>& sourceFld
635 tmp<Field<Type> > tfld(new Field<Type>(nearestVertex_.size()));
636 Field<Type>& fld = tfld();
640 const FixedList<label, 3>& verts = nearestVertex_[i];
641 const FixedList<scalar, 3>& w = nearestVertexWeight_[i];
648 fld[i] = sourceFld[verts[0]];
654 w[0]*sourceFld[verts[0]]
655 + w[1]*sourceFld[verts[1]];
661 w[0]*sourceFld[verts[0]]
662 + w[1]*sourceFld[verts[1]]
663 + w[2]*sourceFld[verts[2]];
671 void timeVaryingMappedFixedValueFvPatchField<Type>::updateCoeffs()
680 // Interpolate between the sampled data
684 if (endSampleTime_ == -1)
689 Pout<< "updateCoeffs : Sampled, non-interpolated values"
690 << " from start time:"
691 << sampleTimes_[startSampleTime_].name() << nl;
694 this->operator==(startSampledValues_);
695 wantedAverage = startAverage_;
699 scalar start = sampleTimes_[startSampleTime_].value();
700 scalar end = sampleTimes_[endSampleTime_].value();
702 scalar s = (this->db().time().value()-start)/(end-start);
706 Pout<< "updateCoeffs : Sampled, interpolated values"
707 << " between start time:"
708 << sampleTimes_[startSampleTime_].name()
709 << " and end time:" << sampleTimes_[endSampleTime_].name()
710 << " with weight:" << s << endl;
713 this->operator==((1-s)*startSampledValues_ + s*endSampledValues_);
714 wantedAverage = (1-s)*startAverage_ + s*endAverage_;
717 // Enforce average. Either by scaling (if scaling factor > 0.5) or by
721 const Field<Type>& fld = *this;
724 gSum(this->patch().magSf()*fld)
725 /gSum(this->patch().magSf());
729 Pout<< "updateCoeffs :"
730 << " actual average:" << averagePsi
731 << " wanted average:" << wantedAverage
735 if (mag(averagePsi) < VSMALL)
737 // Field too small to scale. Offset instead.
738 const Type offset = wantedAverage - averagePsi;
741 Pout<< "updateCoeffs :"
742 << " offsetting with:" << offset << endl;
744 this->operator==(fld+offset);
748 const scalar scale = mag(wantedAverage)/mag(averagePsi);
752 Pout<< "updateCoeffs :"
753 << " scaling with:" << scale << endl;
755 this->operator==(scale*fld);
761 Pout<< "updateCoeffs : set fixedValue to min:" << gMin(*this)
762 << " max:" << gMax(*this) << endl;
765 fixedValueFvPatchField<Type>::updateCoeffs();
770 void timeVaryingMappedFixedValueFvPatchField<Type>::write(Ostream& os) const
772 fvPatchField<Type>::write(os);
773 os.writeKeyword("setAverage") << setAverage_ << token::END_STATEMENT << nl;
774 this->writeEntry("value", os);
778 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
780 } // End namespace Foam
782 // ************************************************************************* //