/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "vtkPVblockMesh.H" #include "vtkPVblockMeshReader.h" // OpenFOAM includes #include "blockMesh.H" #include "blockMeshTools.H" #include "Time.H" #include "patchZones.H" #include "StringStream.H" // VTK includes #include "vtkDataArraySelection.h" #include "vtkMultiBlockDataSet.h" #include "vtkRenderer.h" #include "vtkTextActor.h" #include "vtkTextProperty.h" #include "vtkSmartPointer.h" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(vtkPVblockMesh, 0); } // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // namespace Foam { // file-scope //- Create a text actor static vtkSmartPointer createTextActor ( const std::string& s, const Foam::point& pt ) { auto txt = vtkSmartPointer::New(); txt->SetInput(s.c_str()); // Set text properties vtkTextProperty* tprop = txt->GetTextProperty(); tprop->SetFontFamilyToArial(); tprop->BoldOn(); tprop->ShadowOff(); tprop->SetLineSpacing(1.0); tprop->SetFontSize(14); tprop->SetColor(1.0, 0.0, 1.0); tprop->SetJustificationToCentered(); txt->GetPositionCoordinate()->SetCoordinateSystemToWorld(); txt->GetPositionCoordinate()->SetValue(pt.x(), pt.y(), pt.z()); return txt; } } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::vtkPVblockMesh::resetCounters() { // Reset mesh part ids and sizes rangeBlocks_.reset(); rangeEdges_.reset(); rangeCorners_.reset(); } void Foam::vtkPVblockMesh::updateInfoBlocks ( vtkDataArraySelection* select ) { if (debug) { Info<< " updateInfoBlocks" << " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl; } rangeBlocks_.reset(select->GetNumberOfArrays()); const blockMesh& blkMesh = *meshPtr_; const int nBlocks = blkMesh.size(); for (int blockI = 0; blockI < nBlocks; ++blockI) { const blockDescriptor& blockDef = blkMesh[blockI]; // Display either blockI as a number or with its name // (looked up from blockMeshDict) OStringStream ostr; blockDescriptor::write(ostr, blockI, blkMesh.meshDict()); // append the (optional) zone name if (!blockDef.zoneName().empty()) { ostr << " - " << blockDef.zoneName(); } // Add "blockId" or "blockId - zoneName" to GUI list select->AddArray(ostr.str().c_str()); ++rangeBlocks_; } if (debug) { Info<< " updateInfoBlocks" << endl; } } void Foam::vtkPVblockMesh::updateInfoEdges ( vtkDataArraySelection* select ) { if (debug) { Info<< " updateInfoEdges" << " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl; } rangeEdges_.reset(select->GetNumberOfArrays()); const blockMesh& blkMesh = *meshPtr_; const blockEdgeList& edges = blkMesh.edges(); forAll(edges, edgeI) { OStringStream ostr; blockVertex::write(ostr, edges[edgeI].start(), blkMesh.meshDict()); ostr<< ":"; blockVertex::write(ostr, edges[edgeI].end(), blkMesh.meshDict()); ostr << " - " << edges[edgeI].type(); // Add "beg:end - type" to GUI list select->AddArray(ostr.str().c_str()); ++rangeEdges_; } if (debug) { Info<< " updateInfoEdges" << endl; } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::vtkPVblockMesh::vtkPVblockMesh ( const char* const FileName, vtkPVblockMeshReader* reader ) : reader_(reader), dbPtr_(nullptr), meshPtr_(nullptr), meshRegion_(polyMesh::defaultRegion), meshDir_(polyMesh::meshSubDir), rangeBlocks_("block"), rangeEdges_("edges"), rangeCorners_("corners") { if (debug) { Info<< "vtkPVblockMesh - " << FileName << endl; } // avoid argList and get rootPath/caseName directly from the file fileName fullCasePath(fileName(FileName).path()); if (!isDir(fullCasePath)) { return; } if (fullCasePath == ".") { fullCasePath = cwd(); } // The name of the executable, unless already present in the environment setEnv("FOAM_EXECUTABLE", "paraview", false); // Set the case as an environment variable - some BCs might use this if (fullCasePath.name().find("processor", 0) == 0) { const fileName globalCase = fullCasePath.path(); setEnv("FOAM_CASE", globalCase, true); setEnv("FOAM_CASENAME", globalCase.name(), true); } else { setEnv("FOAM_CASE", fullCasePath, true); setEnv("FOAM_CASENAME", fullCasePath.name(), true); } // look for 'case{region}.OpenFOAM' // could be stringent and insist the prefix match the directory name... // Note: cannot use fileName::name() due to the embedded '{}' string caseName(fileName(FileName).lessExt()); string::size_type beg = caseName.find_last_of("/{"); string::size_type end = caseName.find('}', beg); if ( beg != string::npos && caseName[beg] == '{' && end != string::npos && end == caseName.size()-1 ) { meshRegion_ = caseName.substr(beg+1, end-beg-1); // some safety if (meshRegion_.empty()) { meshRegion_ = polyMesh::defaultRegion; } if (meshRegion_ != polyMesh::defaultRegion) { meshDir_ = meshRegion_/polyMesh::meshSubDir; } } if (debug) { Info<< "fullCasePath=" << fullCasePath << nl << "FOAM_CASE=" << getEnv("FOAM_CASE") << nl << "FOAM_CASENAME=" << getEnv("FOAM_CASENAME") << endl; } // Create time object dbPtr_.reset ( new Time ( Time::controlDictName, fileName(fullCasePath.path()), fileName(fullCasePath.name()) ) ); dbPtr_().functionObjects().off(); updateInfo(); } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::vtkPVblockMesh::~vtkPVblockMesh() { if (debug) { Info<< "~vtkPVblockMesh" << endl; } delete meshPtr_; } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::vtkPVblockMesh::updateInfo() { if (debug) { Info<< " updateInfo" << " [meshPtr=" << (meshPtr_ ? "set" : "null") << "] " << endl; } resetCounters(); vtkDataArraySelection* blockSelection = reader_->GetBlockSelection(); vtkDataArraySelection* edgeSelection = reader_->GetCurvedEdgesSelection(); const bool firstTime = (!blockSelection->GetNumberOfArrays() && !meshPtr_); // Preserve the enabled selections if possible HashSet enabledParts; HashSet enabledEdges; if (!firstTime) { enabledParts = getSelectedArraySet(blockSelection); enabledEdges = getSelectedArraySet(edgeSelection); } // Clear current mesh parts list blockSelection->RemoveAllArrays(); edgeSelection->RemoveAllArrays(); // need a blockMesh updateFoamMesh(); // Update mesh parts list updateInfoBlocks(blockSelection); // Update curved edges list updateInfoEdges(edgeSelection); // Restore the enabled selections if (!firstTime) { setSelectedArrayEntries(blockSelection, enabledParts); setSelectedArrayEntries(edgeSelection, enabledEdges); } if (debug) { Info<< " updateInfo" << endl; } } void Foam::vtkPVblockMesh::updateFoamMesh() { if (debug) { Info<< " updateFoamMesh" << endl; } // Check to see if the OpenFOAM mesh has been created if (!meshPtr_) { if (debug) { Info<< "Creating blockMesh at time=" << dbPtr_().timeName() << endl; } // Set path for the blockMeshDict const word dictName("blockMeshDict"); fileName dictPath(dbPtr_().system()/dictName); // Check if dictionary is present in the constant directory if ( exists ( dbPtr_().path()/dbPtr_().constant() /polyMesh::meshSubDir/dictName ) ) { dictPath = dbPtr_().constant()/polyMesh::meshSubDir/dictName; } // Store dictionary since is used as database inside blockMesh class // for names of vertices and blocks IOdictionary* meshDictPtr = new IOdictionary ( IOobject ( dictPath, dbPtr_(), IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE, true ) ); meshDictPtr->store(); meshPtr_ = new blockMesh(*meshDictPtr, meshRegion_); } if (debug) { Info<< " updateFoamMesh" << endl; } } void Foam::vtkPVblockMesh::Update ( vtkMultiBlockDataSet* output ) { reader_->UpdateProgress(0.1); // Update the OpenFOAM mesh updateFoamMesh(); reader_->UpdateProgress(0.5); // Convert mesh elemente int blockNo = 0; convertMeshCorners(output, blockNo); convertMeshBlocks(output, blockNo); convertMeshEdges(output, blockNo); reader_->UpdateProgress(0.8); } void Foam::vtkPVblockMesh::UpdateFinalize() { reader_->UpdateProgress(1.0); } void Foam::vtkPVblockMesh::renderPatchNames ( vtkRenderer* renderer, const bool show ) { // always remove old actors first forAll(patchTextActors_, actori) { renderer->RemoveViewProp(patchTextActors_[actori]); } patchTextActors_.clear(); // the number of text actors label nActors = 0; if (show && meshPtr_) { const blockMesh& blkMesh = *meshPtr_; const dictionary& meshDescription = blkMesh.meshDict(); const pointField& cornerPts = blkMesh.vertices(); const scalar scaleFactor = blkMesh.scaleFactor(); if (!meshDescription.found("boundary")) { return; } // 8 sides per block is plenty patchTextActors_.setSize(8*blkMesh.size()); // Collect all variables dictionary varDict(meshDescription.subOrEmptyDict("namedVertices")); varDict.merge(meshDescription.subOrEmptyDict("namedBlocks")); // Read like boundary file const PtrList patchesInfo(meshDescription.lookup("boundary")); forAll(patchesInfo, patchi) { const entry& patchInfo = patchesInfo[patchi]; if (!patchInfo.isDict()) { IOWarningInFunction(meshDescription) << "Entry " << patchInfo << " in boundary section is not a" << " valid dictionary." << endl; break; } const word& patchName = patchInfo.keyword(); // Read block faces faceList patchFaces = blockMeshTools::read ( patchInfo.dict().lookup("faces"), varDict ); forAll(patchFaces, facei) { const face& f = patchFaces[facei]; // Into a list for later removal patchTextActors_[nActors++] = createTextActor ( patchName, f.centre(cornerPts) * scaleFactor ); if (nActors == patchTextActors_.size()) { // hit max allocated space - bail out break; } } if (nActors == patchTextActors_.size()) { // hit max allocated space - bail out break; } } patchTextActors_.setSize(nActors); } // Add text to each renderer forAll(patchTextActors_, actori) { renderer->AddViewProp(patchTextActors_[actori]); } } void Foam::vtkPVblockMesh::renderPointNumbers ( vtkRenderer* renderer, const bool show ) { // always remove old actors first forAll(pointTextActors_, actori) { renderer->RemoveViewProp(pointTextActors_[actori]); } pointTextActors_.clear(); if (show && meshPtr_) { const blockMesh& blkMesh = *meshPtr_; const pointField& cornerPts = blkMesh.vertices(); const scalar scaleFactor = blkMesh.scaleFactor(); pointTextActors_.setSize(cornerPts.size()); forAll(cornerPts, pointi) { // Display either pointi as a number or with its name // (looked up from blockMeshDict) OStringStream os; blockVertex::write(os, pointi, blkMesh.meshDict()); // Into a list for later removal pointTextActors_[pointi] = createTextActor ( os.str(), cornerPts[pointi]*scaleFactor ); } } // Add text to each renderer forAll(pointTextActors_, actori) { renderer->AddViewProp(pointTextActors_[actori]); } } void Foam::vtkPVblockMesh::PrintSelf(ostream& os, vtkIndent indent) const { #if 0 os << indent << "Number of nodes: " << (meshPtr_ ? meshPtr_->nPoints() : 0) << "\n"; os << indent << "Number of cells: " << (meshPtr_ ? meshPtr_->nCells() : 0) << "\n"; os << indent << "Number of available time steps: " << (dbPtr_.valid() ? dbPtr_().times().size() : 0) << endl; #endif } // ************************************************************************* //