1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "mixerFvMesh.H"
28 #include "regionSplit.H"
29 #include "slidingInterface.H"
30 #include "mapPolyMesh.H"
32 #include "addToRunTimeSelectionTable.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 defineTypeNameAndDebug(mixerFvMesh, 0);
39 addToRunTimeSelectionTable(topoChangerFvMesh, mixerFvMesh, IOobject);
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 void Foam::mixerFvMesh::addZonesAndModifiers()
47 // Add zones and modifiers for motion action
48 if (cellZones().size() > 0)
50 Info<< "void mixerFvMesh::addZonesAndModifiers() : "
51 << "Zones and modifiers already present. Skipping."
54 // Check definition of the modifier
57 pointZones().size() > 0
58 || faceZones().size() > 0
61 if (topoChanger_.size() == 0)
65 "void mixerFvMesh::addZonesAndModifiers()"
66 ) << "Mesh modifiers not read properly. "
67 << "pointZones = " << pointZones().size()
68 << " faceZones = " << faceZones().size()
76 // Find patches and check sizes
79 const word movingSliderName(dict_.subDict("slider").lookup("moving"));
80 label movingSliderIndex = boundaryMesh().findPatchID(movingSliderName);
82 if (movingSliderIndex < 0)
84 FatalErrorIn("void mixerFvMesh::addZonesAndModifiers() const")
85 << "Moving slider patch not found in boundary"
89 const word staticSliderName(dict_.subDict("slider").lookup("static"));
90 label staticSliderIndex = boundaryMesh().findPatchID(staticSliderName);
92 if (staticSliderIndex < 0)
94 FatalErrorIn("void mixerFvMesh::addZonesAndModifiers() const")
95 << "Static slider patch not found in boundary"
100 const polyPatch& movingSlider = boundaryMesh()[movingSliderIndex];
101 const polyPatch& staticSlider = boundaryMesh()[staticSliderIndex];
106 bool addSlider = false;
108 if (movingSlider.size() > 0 && staticSlider.size() > 0)
115 Info<< "Time = " << time().timeName() << endl
116 << "Adding zones and modifiers to the mesh" << endl;
120 // Add an empty zone for cut points
122 pz[0] = new pointZone
131 // Do face zones for slider
134 labelList isf(movingSlider.size());
138 isf[i] = movingSlider.start() + i;
143 movingSliderName + "Zone",
145 boolList(movingSlider.size(), false),
151 labelList osf(staticSlider.size());
155 osf[i] = staticSlider.start() + i;
160 staticSliderName + "Zone",
162 boolList(staticSlider.size(), false),
167 // Add empty zone for cut faces
178 // Add cell zone even if slider does not exist
180 List<cellZone*> cz(1);
182 // Mark every cell with its topological region
183 regionSplit rs(*this);
185 // Get the region of the cell containing the origin.
186 label originRegion = rs[findNearestCell(rotatingRegionMarker_)];
188 labelList movingCells(nCells());
189 label nMovingCells = 0;
193 if (rs[cellI] == originRegion)
195 movingCells[nMovingCells] = cellI;
200 movingCells.setSize(nMovingCells);
201 Info << "Number of cells in the moving region: " << nMovingCells << endl;
211 Info << "Adding point, face and cell zones" << endl;
212 addZones(pz, fz, cz);
216 // Add a topology modifier
217 Info << "Adding topology modifiers" << endl;
218 topoChanger_.setSize(1);
228 staticSliderName + "Zone",
229 movingSliderName + "Zone",
234 slidingInterface::INTEGRAL, // Edge matching algorithm
235 attachDetach_, // Attach-detach action
236 intersection::VISIBLE // Projection algorithm
241 // Write mesh and modifiers
242 topoChanger_.writeOpt() = IOobject::AUTO_WRITE;
243 topoChanger_.write();
248 bool Foam::mixerFvMesh::attached() const
252 if (topoChanger_.size() > 0)
254 result = refCast<const slidingInterface>(topoChanger_[0]).attached();
257 reduce(result, orOp<bool>());
263 void Foam::mixerFvMesh::calcMovingMask() const
267 Info<< "void mixerFvMesh::calcMovingMask() const : "
268 << "Calculating point and cell masks"
272 if (movingPointsMaskPtr_)
274 FatalErrorIn("void mixerFvMesh::calcMovingMask() const")
275 << "point mask already calculated"
276 << abort(FatalError);
279 // Set the point mask
280 movingPointsMaskPtr_ = new scalarField(allPoints().size(), 0);
281 scalarField& movingPointsMask = *movingPointsMaskPtr_;
283 const cellList& c = cells();
284 const faceList& f = allFaces();
286 const labelList& cellAddr =
287 cellZones()[cellZones().findZoneID("movingCells")];
289 forAll (cellAddr, cellI)
291 const cell& curCell = c[cellAddr[cellI]];
293 forAll (curCell, faceI)
295 // Mark all the points as moving
296 const face& curFace = f[curCell[faceI]];
298 forAll (curFace, pointI)
300 movingPointsMask[curFace[pointI]] = 1;
305 if (topoChanger_.size() > 0)
307 // Topo changer present. Use zones for motion
308 const word movingSliderZoneName
310 word(dict_.subDict("slider").lookup("moving")) + "Zone"
313 const labelList& movingSliderAddr =
314 faceZones()[faceZones().findZoneID(movingSliderZoneName)];
316 forAll (movingSliderAddr, faceI)
318 const face& curFace = f[movingSliderAddr[faceI]];
320 forAll (curFace, pointI)
322 movingPointsMask[curFace[pointI]] = 1;
326 const word staticSliderZoneName
328 word(dict_.subDict("slider").lookup("static")) + "Zone"
331 const labelList& staticSliderAddr =
332 faceZones()[faceZones().findZoneID(staticSliderZoneName)];
334 forAll (staticSliderAddr, faceI)
336 const face& curFace = f[staticSliderAddr[faceI]];
338 forAll (curFace, pointI)
340 movingPointsMask[curFace[pointI]] = 0;
347 // Return moving points mask. Moving points marked with 1
348 const Foam::scalarField& Foam::mixerFvMesh::movingPointsMask() const
350 if (!movingPointsMaskPtr_)
355 return *movingPointsMaskPtr_;
359 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
361 // Construct from components
362 Foam::mixerFvMesh::mixerFvMesh
367 topoChangerFvMesh(io),
380 ).subDict(typeName + "Coeffs")
385 dict_.subDict("coordinateSystem")
387 rpm_(readScalar(dict_.lookup("rpm"))),
388 rotatingRegionMarker_
390 dict_.lookupOrDefault<point>("rotatingRegionMarker", cs_.origin())
392 attachDetach_(dict_.lookupOrDefault<bool>("attachDetach", false)),
393 movingPointsMaskPtr_(NULL)
395 // Make sure the coordinate system does not operate in degrees
396 // Bug fix, HJ, 3/Oct/2011
397 if (!cs_.inDegrees())
399 WarningIn("mixerFvMesh::mixerFvMesh(const IOobject& io)")
400 << "Mixer coordinate system is set to operate in radians. "
401 << "Changing to rad for correct calculation of angular velocity."
403 << "To remove this message please add entry" << nl << nl
404 << "inDegrees true;" << nl << nl
405 << "to the specification of the coordinate system"
408 cs_.inDegrees() = true;
411 Info<< "Rotating region marker point: " << rotatingRegionMarker_
412 << " Attach-detach action = " << attachDetach_ << endl;
414 addZonesAndModifiers();
416 Info<< "Mixer mesh" << nl
417 << " origin : " << cs().origin() << nl
418 << " axis : " << cs().axis() << nl
419 << " rpm : " << rpm_ << nl
420 << " marker : " << rotatingRegionMarker_ << nl
421 << " attach-detach: " << attachDetach_
426 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
428 Foam::mixerFvMesh::~mixerFvMesh()
430 deleteDemandDrivenData(movingPointsMaskPtr_);
434 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
436 bool Foam::mixerFvMesh::update()
438 if (attached() && attachDetach_)
441 Info << "Detaching rotors" << endl;
442 autoPtr<mapPolyMesh> topoChangeMap = topoChanger_.changeMesh();
444 deleteDemandDrivenData(movingPointsMaskPtr_);
448 pointField oldPointsNew = allPoints();
450 // Move points. Rotational speed needs to be converted from rpm
455 cs_.localPosition(allPoints())
456 + vector(0, rpm_*360.0*time().deltaT().value()/60.0, 0)
461 autoPtr<mapPolyMesh> topoChangeMap = topoChanger_.changeMesh();
463 bool localMorphing = topoChangeMap->morphing();
464 bool globalMorphing = localMorphing;
466 reduce(globalMorphing, orOp<bool>());
470 Info<< "Attaching rotors" << endl;
472 deleteDemandDrivenData(movingPointsMaskPtr_);
474 // Move the sliding interface points to correct position
477 pointField mappedOldPointsNew(allPoints().size());
478 mappedOldPointsNew.map(oldPointsNew, topoChangeMap->pointMap());
480 // Note: using setOldPoints instead of movePoints.
482 setOldPoints(mappedOldPointsNew);
487 // Move the sliding interface points to correct position
488 movePoints(topoChangeMap->preMotionPoints());
492 pointField newPoints = allPoints();
494 // Note: using setOldPoints instead of movePoints.
496 setOldPoints(oldPointsNew);
501 // Move the sliding interface points to correct position
502 movePoints(newPoints);
506 return topoChangeMap->morphing();
510 // ************************************************************************* //