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/>.
25 Hrvoje Jasak, Wikki Ltd. All rights reserved
27 \*----------------------------------------------------------------------------*/
29 #include "bubbleHistory.H"
30 #include "addToRunTimeSelectionTable.H"
31 #include "volFields.H"
33 #include "freeSurface.H"
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(bubbleHistory, 0);
41 addToRunTimeSelectionTable
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 Foam::bubbleHistory::bubbleHistory
59 const dictionary& dict
65 regionName_(polyMesh::defaultRegion),
69 if (dict.found("region"))
71 dict.lookup("region") >> regionName_;
74 if (Pstream::master())
76 if (!time_.processorCase())
98 time_.path()/".."/"history"
140 const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName_);
142 const volScalarField& fluidIndicator =
143 mesh.lookupObject<volScalarField>("fluidIndicator");
145 V0_ = gSum((1 - fluidIndicator.internalField())*mesh.V().field());
147 const freeSurface& fs =
148 mesh.lookupObject<freeSurface>("freeSurfaceProperties");
155 mesh.Cf().boundaryField()[fs.aPatchID()]
156 & mesh.Sf().boundaryField()[fs.aPatchID()]
159 if (mesh.nGeometricD() != 3)
161 FatalErrorIn("bubbleHistory::")
162 << "One-fluid bubble centroid calc "
163 << "is not implemented for 2d mesh"
164 << abort(FatalError);
170 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
173 bool Foam::bubbleHistory::start()
176 time_.lookupObject<fvMesh>(regionName_);
178 const volScalarField& fluidIndicator =
179 mesh.lookupObject<volScalarField>("fluidIndicator");
181 const freeSurface& fs =
182 mesh.lookupObject<freeSurface>("freeSurfaceProperties");
184 scalar V = gSum((1 - fluidIndicator.internalField())*mesh.V().field());
191 mesh.Cf().boundaryField()[fs.aPatchID()]
192 & mesh.Sf().boundaryField()[fs.aPatchID()]
195 if (mesh.nGeometricD() != 3)
197 FatalErrorIn("bubbleHistory::")
198 << "One-fluid bubble centroid calc "
199 << "is not implemented for 2d mesh"
200 << abort(FatalError);
204 const IOdictionary& mrf =
205 mesh.lookupObject<IOdictionary>("movingReferenceFrame");
207 dimensionedVector C(mrf.lookup("XF"));
208 dimensionedVector U(mrf.lookup("UF"));
209 dimensionedVector a(mrf.lookup("aF"));
211 vector F = fs.totalViscousForce() + fs.totalPressureForce();
215 if(mag(U.value()) > SMALL)
217 dragDir = -U.value()/mag(U.value());
221 dragDir = fs.g().value()/(mag(fs.g().value()) + SMALL);
224 scalar dragForce = (dragDir&F);
226 vector liftForce = transform(I - dragDir*dragDir, F);
228 scalar Deq = 2*pow(3*V/(4*M_PI), 1.0/3.0);
230 scalar Ug = -(U.value()&(fs.g().value()/(mag(fs.g().value()) + SMALL)));
233 (4.0/3.0)*(fs.rhoFluidA().value() - fs.rhoFluidB().value())
234 *mag(fs.g().value())*Deq
235 /(fs.rhoFluidA().value()*mag(U.value())*Ug + SMALL);
237 scalar ag = -(a.value()&(fs.g().value()/(mag(fs.g().value()) + SMALL)));
240 (fs.rhoFluidA().value() - fs.rhoFluidB().value())*mag(fs.g().value())
241 /(fs.rhoFluidA().value()*ag + SMALL)
242 - (fs.rhoFluidB().value()/(fs.rhoFluidA().value() + SMALL));
244 scalar RE = Ug*Deq*fs.rhoFluidA().value()/(fs.muFluidA().value() + SMALL);
246 scalar WE = fs.rhoFluidA().value()*sqr(Ug)*Deq
247 /(fs.cleanInterfaceSurfTension().value() + SMALL);
249 boundBox box(mesh.C().boundaryField()[fs.aPatchID()]);
251 if (Pstream::master())
253 historyFilePtr_->precision(12);
255 (*historyFilePtr_) << time_.value() << tab
256 << C.value().x() << tab
257 << C.value().y() << tab
258 << C.value().z() << tab
259 << U.value().x() << tab
260 << U.value().y() << tab
261 << U.value().z() << tab
262 << a.value().x() << tab
263 << a.value().y() << tab
264 << a.value().z() << tab
269 << liftForce.x() << tab
270 << liftForce.y() << tab
271 << liftForce.z() << tab
276 << mag(1.0 - V/V0_) << tab
277 << (box.max().x()-box.min().x())/2 << tab
278 << (box.max().y()-box.min().y())/2 << tab
279 << (box.max().z()-box.min().z())/2 << endl;
288 bool Foam::bubbleHistory::execute()
291 time_.lookupObject<fvMesh>(regionName_);
293 const volScalarField& fluidIndicator =
294 mesh.lookupObject<volScalarField>("fluidIndicator");
296 const freeSurface& fs =
297 mesh.lookupObject<freeSurface>("freeSurfaceProperties");
299 scalar V = gSum((1 - fluidIndicator.internalField())*mesh.V().field());
306 mesh.Cf().boundaryField()[fs.aPatchID()]
307 & mesh.Sf().boundaryField()[fs.aPatchID()]
310 if (mesh.nGeometricD() != 3)
312 FatalErrorIn("bubbleHistory")
313 << "One-fluid bubble centroid calc "
314 << "is not implemented for 2d mesh"
315 << abort(FatalError);
319 const IOdictionary& mrf =
320 mesh.lookupObject<IOdictionary>("movingReferenceFrame");
322 dimensionedVector C(mrf.lookup("XF"));
323 dimensionedVector U(mrf.lookup("UF"));
324 dimensionedVector a(mrf.lookup("aF"));
327 vector F = fs.totalViscousForce() + fs.totalPressureForce();
331 if(mag(U.value()) > SMALL)
333 dragDir = -U.value()/mag(U.value());
337 dragDir = fs.g().value()/(mag(fs.g().value()) + SMALL);
340 scalar dragForce = (dragDir&F);
342 vector liftForce = transform(I - dragDir*dragDir, F);
344 scalar Deq = pow(3*V/(4*M_PI), 1.0/3.0);
346 scalar Ug = -(U.value()&(fs.g().value()/(mag(fs.g().value()) + SMALL)));
349 (4.0/3.0)*(fs.rhoFluidA().value() - fs.rhoFluidB().value())
350 *mag(fs.g().value())*Deq
351 /(fs.rhoFluidA().value()*mag(U.value())*Ug + SMALL);
353 scalar ag = -(a.value()&(fs.g().value()/(mag(fs.g().value()) + SMALL)));
356 (fs.rhoFluidA().value() - fs.rhoFluidB().value())*mag(fs.g().value())
357 /(fs.rhoFluidA().value()*ag + SMALL)
358 - (fs.rhoFluidB().value()/(fs.rhoFluidA().value() + SMALL));
360 scalar RE = Ug*Deq*fs.rhoFluidA().value()/(fs.muFluidA().value() + SMALL);
362 scalar WE = fs.rhoFluidA().value()*sqr(Ug)*Deq
363 /(fs.cleanInterfaceSurfTension().value() + SMALL);
365 boundBox box(mesh.C().boundaryField()[fs.aPatchID()]);
367 if (Pstream::master())
369 historyFilePtr_->precision(12);
371 (*historyFilePtr_) << time_.value() << tab
372 << C.value().x() << tab
373 << C.value().y() << tab
374 << C.value().z() << tab
375 << U.value().x() << tab
376 << U.value().y() << tab
377 << U.value().z() << tab
378 << a.value().x() << tab
379 << a.value().y() << tab
380 << a.value().z() << tab
385 << liftForce.x() << tab
386 << liftForce.y() << tab
387 << liftForce.z() << tab
392 << mag(1.0 - V/V0_) << tab
393 << (box.max().x()-box.min().x())/2 << tab
394 << (box.max().y()-box.min().y())/2 << tab
395 << (box.max().z()-box.min().z())/2 << endl;
404 bool Foam::bubbleHistory::read(const dictionary& dict)
406 if (dict.found("region"))
408 dict.lookup("region") >> regionName_;
414 // ************************************************************************* //