OpenFOAM有方法能够使一部分网格不参与计算吗?
-
@Samuel-Tu 在 OpenFOAM有方法能够使一部分网格不参与计算吗? 中说:
想在计算过程中使得一部分网格不参与计算,有没有啥近似的方法呢?我想的是对那部分网格赋予一个很大的粘度,使他们近似于固体,不知道可不可行。
这是要模拟什么工况?凝固?
-
#include "fvCFD.H" #include "pisoControl.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) { argList::addNote ( "Transient solver for incompressible, laminar flow" " of Newtonian fluids." ); #include "postProcess.H" #include "addCheckCaseOptions.H" #include "setRootCaseLists.H" #include "createTime.H" #include "createMesh.H" pisoControl piso(mesh); #include "createFields.H" #include "initContinuityErrs.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Info<< "\nStarting time loop\n" << endl; DynamicList<label> lowerFaceCells(mesh.C().size()); DynamicList<label> upperFaceCells(mesh.C().size()); //mesh LDU address const labelUList& lowAddr = mesh.lduAddr().lowerAddr(); const labelUList& upAddr = mesh.lduAddr().upperAddr(); if(mesh.cellZones().size()) { const cellZone& cellBlock = mesh.cellZones()[0]; Info << "cell block size: " << cellBlock.size() << endl; Info << cellBlock << endl; //low efficient forAll(lowAddr, faceI) { for(auto cellI : cellBlock) { if(lowAddr[faceI] == cellI) { lowerFaceCells.append(faceI); } if(upAddr[faceI] == cellI) { upperFaceCells.append(faceI); } } } } lowerFaceCells.shrink(); upperFaceCells.shrink(); Info << "low Cells size: " << lowerFaceCells.size() << ", low Cells size: " << upperFaceCells.size() << endl; while (runTime.loop()) { Info<< "Time = " << runTime.timeName() << nl << endl; #include "CourantNo.H" // Momentum predictor fvVectorMatrix UEqn ( fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U) ); //modify matrix if(mesh.cellZones().size()) { const cellZone& cellBlock = mesh.cellZones()[0]; //should select cellZone accor name scalarField& lower = UEqn.lower(); scalarField& upper = UEqn.upper(); scalarField& diag = UEqn.diag(); for(auto cellI : cellBlock) { diag[cellI] = 1.; UEqn.source()[cellI] = vector::zero; //vector(0.,0.,0.); you can set your deserved value here, or read from dict, ref. fvoptions } for(auto faceI : lowerFaceCells) { lower[faceI] = 0.; } for(auto faceI : upperFaceCells) { upper[faceI] = 0.; } } else { Info << "There is no cell selected" << endl; } if (piso.momentumPredictor()) { solve(UEqn == -fvc::grad(p)); } // --- PISO loop while (piso.correct()) { volScalarField rAU(1.0/UEqn.A()); volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p)); surfaceScalarField phiHbyA ( "phiHbyA", fvc::flux(HbyA) + fvc::interpolate(rAU)*fvc::ddtCorr(U, phi) ); adjustPhi(phiHbyA, U, p); // Update the pressure BCs to ensure flux consistency constrainPressure(p, U, phiHbyA, rAU); // Non-orthogonal pressure corrector loop while (piso.correctNonOrthogonal()) { // Pressure corrector fvScalarMatrix pEqn ( fvm::laplacian(rAU, p) == fvc::div(phiHbyA) ); pEqn.setReference(pRefCell, pRefValue); //modify p matrix if(mesh.cellZones().size()) { const cellZone& cellBlock = mesh.cellZones()[0]; //p matrix symmetry scalarField& offDiag = pEqn.hasUpper() ? pEqn.upper() : pEqn.lower(); scalarField& diag = pEqn.diag(); for(auto cellI : cellBlock) { diag[cellI] = 1.; pEqn.source()[cellI] = 0.; } //for(auto faceI : upperFaceCells) //should find faces again? //{ // offDiag[faceI] = 0.; //} const labelUList& offAddr = pEqn.hasUpper() ? pEqn.lduAddr().upperAddr() : pEqn.lduAddr().lowerAddr(); forAll(offAddr, faceI) { for(auto cellI : cellBlock) { if(offAddr[faceI] == cellI) { offDiag[faceI] = 0.; } } } } pEqn.solve(mesh.solver(p.select(piso.finalInnerIter()))); if (piso.finalNonOrthogonalIter()) { phi = phiHbyA - pEqn.flux(); } } #include "continuityErrs.H" U = HbyA - rAU*fvc::grad(p); U.correctBoundaryConditions(); } runTime.write(); runTime.printExecutionTime(Info); } Info<< "End\n" << endl; return 0; }
toposetDict // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // actions ( // porousBlockage { name porousBlockageCellSet; type cellSet; action new; source boxToCell; box (0.04 0.04 -1) (0.06 0.06 1); } { name porousBlockage; type cellZoneSet; action new; source setToCellZone; set porousBlockageCellSet; } );
-
(Sorry, I don't have chinese input right now)
I once had the exactly same issue!
Check my thesis Chapter 6.3 :
https://scholar.uwindsor.ca/cgi/viewcontent.cgi?article=8585&context=etd
I wrote a paper in this: https://ascelibrary.org/doi/pdf/10.1061/9780784415153.ch06
Figure 2 is the original plate. (Sorry due to copy-right reason, I cannot put it here.)
In my thesis, I had to open the plate with some holes in ICEM. So, I maual dig out the block out of the computation domain.
It's really a painful process.
But it works!
This is the original plate:
This is after the "dig":
-
fvVectorMatrix UEqn ( fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U) ); // 固定值 labelList cells = mesh.cellZones()["null"]; vectorField value(cells.size(), Zero); UEqn.setValues(cells, value); if (piso.momentumPredictor()) { solve(UEqn == -fvc::grad(p)); }
可以通过设定一个
null
区域,然后对区域的网格点强行赋值,但就像我之前说的,总觉得边界处需要处理。也就像 @cccrrryyy 说的,变成了浸没边界法。这个代码只是大体上是个思路,需要更深的研究。可以看看fvOptions里面一些源项的处理,都是操纵矩阵的,比如fixedTempresure,meanVelocityForce等,