00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "sampledSurfaces.H"
00027 #include <finiteVolume/volFields.H>
00028 #include <OpenFOAM/dictionary.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <OpenFOAM/IOmanip.H>
00031 #include <OpenFOAM/ListListOps.H>
00032 #include <OpenFOAM/mergePoints.H>
00033 #include <finiteVolume/volPointInterpolation.H>
00034
00035
00036
00037 namespace Foam
00038 {
00039
00040 template <>
00041 class offsetOp<face>
00042 {
00043
00044 public:
00045
00046 face operator()
00047 (
00048 const face& x,
00049 const label offset
00050 ) const
00051 {
00052 face result(x.size());
00053
00054 forAll(x, xI)
00055 {
00056 result[xI] = x[xI] + offset;
00057 }
00058 return result;
00059 }
00060 };
00061
00062
00063 defineTypeNameAndDebug(sampledSurfaces, 0);
00064 }
00065
00066
00067 bool Foam::sampledSurfaces::verbose_(false);
00068 Foam::scalar Foam::sampledSurfaces::mergeTol_(1e-10);
00069
00070
00071
00072 Foam::label Foam::sampledSurfaces::classifyFieldTypes()
00073 {
00074 label nFields = 0;
00075
00076 scalarFields_.clear();
00077 vectorFields_.clear();
00078 sphericalTensorFields_.clear();
00079 symmTensorFields_.clear();
00080 tensorFields_.clear();
00081
00082 forAll(fieldNames_, fieldI)
00083 {
00084 const word& fieldName = fieldNames_[fieldI];
00085 word fieldType = "";
00086
00087
00088 if (loadFromFiles_)
00089 {
00090 IOobject io
00091 (
00092 fieldName,
00093 mesh_.time().timeName(),
00094 mesh_,
00095 IOobject::MUST_READ,
00096 IOobject::NO_WRITE,
00097 false
00098 );
00099
00100 if (io.headerOk())
00101 {
00102 fieldType = io.headerClassName();
00103 }
00104 else
00105 {
00106 continue;
00107 }
00108 }
00109 else
00110 {
00111
00112 objectRegistry::const_iterator iter = mesh_.find(fieldName);
00113
00114 if (iter != mesh_.objectRegistry::end())
00115 {
00116 fieldType = iter()->type();
00117 }
00118 else
00119 {
00120 continue;
00121 }
00122 }
00123
00124
00125 if (fieldType == volScalarField::typeName)
00126 {
00127 scalarFields_.append(fieldName);
00128 nFields++;
00129 }
00130 else if (fieldType == volVectorField::typeName)
00131 {
00132 vectorFields_.append(fieldName);
00133 nFields++;
00134 }
00135 else if (fieldType == volSphericalTensorField::typeName)
00136 {
00137 sphericalTensorFields_.append(fieldName);
00138 nFields++;
00139 }
00140 else if (fieldType == volSymmTensorField::typeName)
00141 {
00142 symmTensorFields_.append(fieldName);
00143 nFields++;
00144 }
00145 else if (fieldType == volTensorField::typeName)
00146 {
00147 tensorFields_.append(fieldName);
00148 nFields++;
00149 }
00150
00151 }
00152
00153 return nFields;
00154 }
00155
00156
00157 void Foam::sampledSurfaces::writeGeometry() const
00158 {
00159
00160
00161
00162 const fileName outputDir = outputPath_/mesh_.time().timeName();
00163
00164 forAll(*this, surfI)
00165 {
00166 const sampledSurface& s = operator[](surfI);
00167
00168 if (Pstream::parRun())
00169 {
00170 if (Pstream::master() && mergeList_[surfI].faces.size())
00171 {
00172 genericFormatter_->write
00173 (
00174 outputDir,
00175 s.name(),
00176 mergeList_[surfI].points,
00177 mergeList_[surfI].faces
00178 );
00179 }
00180 }
00181 else if (s.faces().size())
00182 {
00183 genericFormatter_->write
00184 (
00185 outputDir,
00186 s.name(),
00187 s.points(),
00188 s.faces()
00189 );
00190 }
00191 }
00192 }
00193
00194
00195
00196
00197 Foam::sampledSurfaces::sampledSurfaces
00198 (
00199 const word& name,
00200 const objectRegistry& obr,
00201 const dictionary& dict,
00202 const bool loadFromFiles
00203 )
00204 :
00205 PtrList<sampledSurface>(),
00206 name_(name),
00207 mesh_(refCast<const fvMesh>(obr)),
00208 loadFromFiles_(loadFromFiles),
00209 outputPath_(fileName::null),
00210 fieldNames_(),
00211 interpolationScheme_(word::null),
00212 writeFormat_(word::null),
00213 mergeList_(),
00214 genericFormatter_(NULL),
00215 scalarFields_(),
00216 vectorFields_(),
00217 sphericalTensorFields_(),
00218 symmTensorFields_(),
00219 tensorFields_()
00220 {
00221 if (Pstream::parRun())
00222 {
00223 outputPath_ = mesh_.time().path()/".."/name_;
00224 }
00225 else
00226 {
00227 outputPath_ = mesh_.time().path()/name_;
00228 }
00229
00230 read(dict);
00231 }
00232
00233
00234
00235
00236 Foam::sampledSurfaces::~sampledSurfaces()
00237 {}
00238
00239
00240
00241
00242 void Foam::sampledSurfaces::verbose(const bool verbosity)
00243 {
00244 verbose_ = verbosity;
00245 }
00246
00247
00248 void Foam::sampledSurfaces::execute()
00249 {
00250
00251 }
00252
00253
00254 void Foam::sampledSurfaces::end()
00255 {
00256
00257 }
00258
00259
00260 void Foam::sampledSurfaces::write()
00261 {
00262 if (size())
00263 {
00264
00265 update();
00266
00267 const label nFields = classifyFieldTypes();
00268
00269 if (Pstream::master())
00270 {
00271 if (debug)
00272 {
00273 Pout<< "timeName = " << mesh_.time().timeName() << nl
00274 << "scalarFields " << scalarFields_ << nl
00275 << "vectorFields " << vectorFields_ << nl
00276 << "sphTensorFields " << sphericalTensorFields_ << nl
00277 << "symTensorFields " << symmTensorFields_ <<nl
00278 << "tensorFields " << tensorFields_ <<nl;
00279
00280 Pout<< "Creating directory "
00281 << outputPath_/mesh_.time().timeName() << nl << endl;
00282
00283 }
00284
00285 mkDir(outputPath_/mesh_.time().timeName());
00286 }
00287
00288
00289
00290 if (nFields == 0 || genericFormatter_->separateFiles())
00291 {
00292 writeGeometry();
00293 }
00294
00295 sampleAndWrite(scalarFields_);
00296 sampleAndWrite(vectorFields_);
00297 sampleAndWrite(sphericalTensorFields_);
00298 sampleAndWrite(symmTensorFields_);
00299 sampleAndWrite(tensorFields_);
00300 }
00301 }
00302
00303
00304 void Foam::sampledSurfaces::read(const dictionary& dict)
00305 {
00306 fieldNames_ = wordList(dict.lookup("fields"));
00307
00308 const label nFields = fieldNames_.size();
00309
00310 scalarFields_.reset(nFields);
00311 vectorFields_.reset(nFields);
00312 sphericalTensorFields_.reset(nFields);
00313 symmTensorFields_.reset(nFields);
00314 tensorFields_.reset(nFields);
00315
00316 interpolationScheme_ = dict.lookupOrDefault<word>
00317 (
00318 "interpolationScheme",
00319 "cell"
00320 );
00321 writeFormat_ = dict.lookupOrDefault<word>
00322 (
00323 "surfaceFormat",
00324 "null"
00325 );
00326
00327
00328
00329 genericFormatter_ = surfaceWriter<bool>::New(writeFormat_);
00330
00331
00332 PtrList<sampledSurface> newList
00333 (
00334 dict.lookup("surfaces"),
00335 sampledSurface::iNew(mesh_)
00336 );
00337
00338 transfer(newList);
00339
00340 if (Pstream::parRun())
00341 {
00342 mergeList_.setSize(size());
00343 }
00344
00345
00346 expire();
00347
00348 if (Pstream::master() && debug)
00349 {
00350 Pout<< "sample fields:" << fieldNames_ << nl
00351 << "sample surfaces:" << nl << "(" << nl;
00352
00353 forAll(*this, surfI)
00354 {
00355 Pout<< " " << operator[](surfI) << endl;
00356 }
00357 Pout<< ")" << endl;
00358 }
00359 }
00360
00361
00362 void Foam::sampledSurfaces::updateMesh(const mapPolyMesh&)
00363 {
00364 expire();
00365
00366
00367 }
00368
00369
00370 void Foam::sampledSurfaces::movePoints(const pointField&)
00371 {
00372 expire();
00373 }
00374
00375
00376 void Foam::sampledSurfaces::readUpdate(const polyMesh::readUpdateState state)
00377 {
00378 if (state != polyMesh::UNCHANGED)
00379 {
00380 expire();
00381 }
00382 }
00383
00384
00385 bool Foam::sampledSurfaces::needsUpdate() const
00386 {
00387 forAll(*this, surfI)
00388 {
00389 if (operator[](surfI).needsUpdate())
00390 {
00391 return true;
00392 }
00393 }
00394
00395 return false;
00396 }
00397
00398
00399 bool Foam::sampledSurfaces::expire()
00400 {
00401 bool justExpired = false;
00402
00403 forAll(*this, surfI)
00404 {
00405 if (operator[](surfI).expire())
00406 {
00407 justExpired = true;
00408 }
00409
00410
00411 if (Pstream::parRun())
00412 {
00413 mergeList_[surfI].clear();
00414 }
00415 }
00416
00417
00418 return justExpired;
00419 }
00420
00421
00422 bool Foam::sampledSurfaces::update()
00423 {
00424 bool updated = false;
00425
00426 if (!needsUpdate())
00427 {
00428 return updated;
00429 }
00430
00431
00432 if (!Pstream::parRun())
00433 {
00434 forAll(*this, surfI)
00435 {
00436 if (operator[](surfI).update())
00437 {
00438 updated = true;
00439 }
00440 }
00441
00442 return updated;
00443 }
00444
00445
00446 scalar mergeDim = mergeTol_ * mesh_.globalData().bb().mag();
00447
00448 if (Pstream::master() && debug)
00449 {
00450 Pout<< nl << "Merging all points within "
00451 << mergeDim << " meter" << endl;
00452 }
00453
00454 forAll(*this, surfI)
00455 {
00456 sampledSurface& s = operator[](surfI);
00457
00458 if (s.update())
00459 {
00460 updated = true;
00461 }
00462 else
00463 {
00464 continue;
00465 }
00466
00467
00468
00469 List<pointField> gatheredPoints(Pstream::nProcs());
00470 gatheredPoints[Pstream::myProcNo()] = s.points();
00471 Pstream::gatherList(gatheredPoints);
00472
00473 if (Pstream::master())
00474 {
00475 mergeList_[surfI].points = ListListOps::combine<pointField>
00476 (
00477 gatheredPoints,
00478 accessOp<pointField>()
00479 );
00480 }
00481
00482
00483
00484 List<faceList> gatheredFaces(Pstream::nProcs());
00485 gatheredFaces[Pstream::myProcNo()] = s.faces();
00486 Pstream::gatherList(gatheredFaces);
00487
00488 if (Pstream::master())
00489 {
00490 mergeList_[surfI].faces = static_cast<const faceList&>
00491 (
00492 ListListOps::combineOffset<faceList>
00493 (
00494 gatheredFaces,
00495 ListListOps::subSizes
00496 (
00497 gatheredPoints,
00498 accessOp<pointField>()
00499 ),
00500 accessOp<faceList>(),
00501 offsetOp<face>()
00502 )
00503 );
00504 }
00505
00506 pointField newPoints;
00507 labelList oldToNew;
00508
00509 bool hasMerged = mergePoints
00510 (
00511 mergeList_[surfI].points,
00512 mergeDim,
00513 false,
00514 oldToNew,
00515 newPoints
00516 );
00517
00518 if (hasMerged)
00519 {
00520
00521 mergeList_[surfI].pointsMap.transfer(oldToNew);
00522
00523
00524 mergeList_[surfI].points.transfer(newPoints);
00525
00526
00527 faceList& faces = mergeList_[surfI].faces;
00528
00529 forAll(faces, faceI)
00530 {
00531 inplaceRenumber(mergeList_[surfI].pointsMap, faces[faceI]);
00532 }
00533
00534 if (Pstream::master() && debug)
00535 {
00536 Pout<< "For surface " << surfI << " merged from "
00537 << mergeList_[surfI].pointsMap.size() << " points down to "
00538 << mergeList_[surfI].points.size() << " points" << endl;
00539 }
00540 }
00541 }
00542
00543 return updated;
00544 }
00545
00546
00547