View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002380 | OpenFOAM | Bug | public | 2016-12-08 14:33 | 2018-07-10 11:18 |
Reporter | Solidno | Assigned To | henry | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | GNU/Linux | OS | Ubuntu | OS Version | 16.04 |
Fixed in Version | dev | ||||
Summary | 0002380: MRF solver for omega=0 does not reproduce simpleFoam solver results | ||||
Description | I'm running simpleFoam solver with MRF cellZone being whole mesh, and encounter a bug explained below. The bug occures regardless if boundary conditions for U and p are freestream or Dirichlet on inlet and Neumann on outlet for U, and opposite for p ("traditional":) For freestream boundary conditions U field value boundary conditions are slowly drifted by the solver, while for traditional boundary conditions value is immediately changed by solver upon start to vector::zero. Thus, for omega=0 in MRFproperties simpleFoam produces different results compared to simpleFoam without MRF. I've checked in older versions of OpenFoam and it seems like an older bug. | ||||
Steps To Reproduce | $ ./AllrunFS reproduces bug for freestream $ ./AllrunT reproduces bug for traditional boundary conditions | ||||
Tags | No tags attached. | ||||
|
|
|
Your case setup is a bit odd. By default walls in the MRF zone are assumed to rotate with the MRF and hence if omega is 0 the wall velocity is set to 0. If you want to explicity set the velocity of patches in the MRF zone you need to specify them to be non-rotating in MRFProperties: nonRotatingPatches (outlet inlet walls); |
|
I made a mistake, I didn't want any wall patches. I am sending fixed case. But referring on sentence up "For freestream boundary conditions U field, value boundary conditions are slowly drifted by the solver, while for traditional boundary conditions value is immediately changed by solver upon start to vector::zero. Thus, for omega=0 in MRFproperties simpleFoam produces different results compared to simpleFoam without MRF." is for patches inlet and outlet. |
|
Could you provide the steps to reproduce the problem? |
|
run AllrunFS, after that go to 10/U and after } inlet { type freestream; freestreamValue uniform (0 -30 0); value nonuniform List<vector> 45 ( (-2.49822 -38.3344 -2.84088) (20.797 -28.8032 0.448504) (3.49157 -36.5005 2.97346) (-4.0257 -47.7144 -30.8864) (-1.44647 -0.563724 -7.91937) (3.26572 -27.1627 17.4214) the velocity in y-axis should be -30, but it is not. |
|
I notice that you have not put the bounary patches in nonRotatingPatches: // Fixed patches (by default they 'move' with the MRF zone) nonRotatingPatches (); It should run fine if you do and won't if you don't. |
|
There is no nonRotatingPatches patches, there is just fluid getting in at inlet, and getting out at outlet (i am talking about repaired case i send here Report_bug-MRF.tar.gz ). If You delete MRFProperties or put there: cellZone cyl; active no; the velocity in y-axis will be -30 as it should be. Another thing, if You run ./AllrunT and go to 10/U it is inlet { type fixedValue; value uniform (0 -0 0); } cylinder_surface { type fixedValue; value uniform (0 -0 0); } } but it should write (0 -3 0) as it is given in 0/U |
|
You will need to put ALL of the boundary patches in the 'nonRotatingPatches' list. |
|
MRFZone.C (14,695 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "MRFZone.H" #include "fvMesh.H" #include "volFields.H" #include "surfaceFields.H" #include "fvMatrices.H" #include "faceSet.H" #include "geometricOneField.H" #include "syncTools.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(MRFZone, 0); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::MRFZone::setMRFFaces() { const polyBoundaryMesh& patches = mesh_.boundaryMesh(); // Type per face: // 0:not in zone // 1:moving with frame // 2:other labelList faceType(mesh_.nFaces(), 0); // Determine faces in cell zone // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // (without constructing cells) const labelList& own = mesh_.faceOwner(); const labelList& nei = mesh_.faceNeighbour(); // Cells in zone boolList zoneCell(mesh_.nCells(), false); if (cellZoneID_ != -1) { const labelList& cellLabels = mesh_.cellZones()[cellZoneID_]; forAll(cellLabels, i) { zoneCell[cellLabels[i]] = true; } } label nZoneFaces = 0; for (label facei = 0; facei < mesh_.nInternalFaces(); facei++) { if (zoneCell[own[facei]] || zoneCell[nei[facei]]) { faceType[facei] = 1; nZoneFaces++; } } labelHashSet excludedPatches(excludedPatchLabels_); forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; if (pp.coupled() || excludedPatches.found(patchi)) { forAll(pp, i) { label facei = pp.start()+i; if (zoneCell[own[facei]]) { faceType[facei] = 2; nZoneFaces++; } } } else if (!isA<emptyPolyPatch>(pp)) { forAll(pp, i) { label facei = pp.start()+i; if (zoneCell[own[facei]]) { faceType[facei] = 1; nZoneFaces++; } } } } // Synchronize the faceType across processor patches syncTools::syncFaceList(mesh_, faceType, maxEqOp<label>()); // Now we have for faceType: // 0 : face not in cellZone // 1 : internal face or normal patch face // 2 : coupled patch face or excluded patch face // Sort into lists per patch. internalFaces_.setSize(mesh_.nFaces()); label nInternal = 0; for (label facei = 0; facei < mesh_.nInternalFaces(); facei++) { if (faceType[facei] == 1) { internalFaces_[nInternal++] = facei; } } internalFaces_.setSize(nInternal); labelList nIncludedFaces(patches.size(), 0); labelList nExcludedFaces(patches.size(), 0); forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; forAll(pp, patchFacei) { label facei = pp.start() + patchFacei; if (faceType[facei] == 1) { nIncludedFaces[patchi]++; } else if (faceType[facei] == 2) { nExcludedFaces[patchi]++; } } } includedFaces_.setSize(patches.size()); excludedFaces_.setSize(patches.size()); forAll(nIncludedFaces, patchi) { includedFaces_[patchi].setSize(nIncludedFaces[patchi]); excludedFaces_[patchi].setSize(nExcludedFaces[patchi]); } nIncludedFaces = 0; nExcludedFaces = 0; forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; forAll(pp, patchFacei) { label facei = pp.start() + patchFacei; if (faceType[facei] == 1) { includedFaces_[patchi][nIncludedFaces[patchi]++] = patchFacei; } else if (faceType[facei] == 2) { excludedFaces_[patchi][nExcludedFaces[patchi]++] = patchFacei; } } } if (debug) { faceSet internalFaces(mesh_, "internalFaces", internalFaces_); Pout<< "Writing " << internalFaces.size() << " internal faces in MRF zone to faceSet " << internalFaces.name() << endl; internalFaces.write(); faceSet MRFFaces(mesh_, "includedFaces", 100); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; MRFFaces.insert(patches[patchi].start()+patchFacei); } } Pout<< "Writing " << MRFFaces.size() << " patch faces in MRF zone to faceSet " << MRFFaces.name() << endl; MRFFaces.write(); faceSet excludedFaces(mesh_, "excludedFaces", 100); forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; excludedFaces.insert(patches[patchi].start()+patchFacei); } } Pout<< "Writing " << excludedFaces.size() << " faces in MRF zone with special handling to faceSet " << excludedFaces.name() << endl; excludedFaces.write(); } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::MRFZone::MRFZone ( const word& name, const fvMesh& mesh, const dictionary& dict, const word& cellZoneName ) : mesh_(mesh), name_(name), coeffs_(dict), active_(coeffs_.lookupOrDefault("active", true)), cellZoneName_(cellZoneName), cellZoneID_(), excludedPatchNames_ ( wordReList(coeffs_.lookupOrDefault("nonRotatingPatches", wordReList())) ), origin_(coeffs_.lookup("origin")), axis_(coeffs_.lookup("axis")), omega_(Function1<scalar>::New("omega", coeffs_)) { if (cellZoneName_ == word::null) { coeffs_.lookup("cellZone") >> cellZoneName_; } if (!active_) { cellZoneID_ = -1; } else { cellZoneID_ = mesh_.cellZones().findZoneID(cellZoneName_); axis_ = axis_/mag(axis_); const labelHashSet excludedPatchSet ( mesh_.boundaryMesh().patchSet(excludedPatchNames_) ); excludedPatchLabels_.setSize(excludedPatchSet.size()); label i = 0; forAllConstIter(labelHashSet, excludedPatchSet, iter) { excludedPatchLabels_[i++] = iter.key(); } bool cellZoneFound = (cellZoneID_ != -1); reduce(cellZoneFound, orOp<bool>()); if (!cellZoneFound) { FatalErrorInFunction << "cannot find MRF cellZone " << cellZoneName_ << exit(FatalError); } setMRFFaces(); } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // Foam::vector Foam::MRFZone::Omega() const { return omega_->value(mesh_.time().timeOutputValue())*axis_; } void Foam::MRFZone::addCoriolis ( const volVectorField& U, volVectorField& ddtU ) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; vectorField& ddtUc = ddtU.primitiveFieldRef(); const vectorField& Uc = U; const vector Omega = this->Omega(); forAll(cells, i) { label celli = cells[i]; ddtUc[celli] += (Omega ^ Uc[celli]); } } void Foam::MRFZone::addCoriolis(fvVectorMatrix& UEqn, const bool rhs) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; const scalarField& V = mesh_.V(); vectorField& Usource = UEqn.source(); const vectorField& U = UEqn.psi(); const vector Omega = this->Omega(); if (rhs) { forAll(cells, i) { label celli = cells[i]; Usource[celli] += V[celli]*(Omega ^ U[celli]); } } else { forAll(cells, i) { label celli = cells[i]; Usource[celli] -= V[celli]*(Omega ^ U[celli]); } } } void Foam::MRFZone::addCoriolis ( const volScalarField& rho, fvVectorMatrix& UEqn, const bool rhs ) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; const scalarField& V = mesh_.V(); vectorField& Usource = UEqn.source(); const vectorField& U = UEqn.psi(); const vector Omega = this->Omega(); if (rhs) { forAll(cells, i) { label celli = cells[i]; Usource[celli] += V[celli]*rho[celli]*(Omega ^ U[celli]); } } else { forAll(cells, i) { label celli = cells[i]; Usource[celli] -= V[celli]*rho[celli]*(Omega ^ U[celli]); } } } void Foam::MRFZone::makeRelative(volVectorField& U) const { if (cellZoneID_ == -1) { return; } const volVectorField& C = mesh_.C(); const vector Omega = this->Omega(); const labelList& cells = mesh_.cellZones()[cellZoneID_]; forAll(cells, i) { label celli = cells[i]; U[celli] -= (Omega ^ (C[celli] - origin_)); } // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; Ubf[patchi][patchFacei] = Zero; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; Ubf[patchi][patchFacei] -= (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } } void Foam::MRFZone::makeRelative(surfaceScalarField& phi) const { makeRelativeRhoFlux(geometricOneField(), phi); } void Foam::MRFZone::makeRelative(FieldField<fvsPatchField, scalar>& phi) const { makeRelativeRhoFlux(oneFieldField(), phi); } void Foam::MRFZone::makeRelative(Field<scalar>& phi, const label patchi) const { makeRelativeRhoFlux(oneField(), phi, patchi); } void Foam::MRFZone::makeRelative ( const surfaceScalarField& rho, surfaceScalarField& phi ) const { makeRelativeRhoFlux(rho, phi); } void Foam::MRFZone::makeAbsolute(volVectorField& U) const { if (cellZoneID_ == -1) { return; } const volVectorField& C = mesh_.C(); const vector Omega = this->Omega(); const labelList& cells = mesh_.cellZones()[cellZoneID_]; forAll(cells, i) { label celli = cells[i]; U[celli] += (Omega ^ (C[celli] - origin_)); } // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; Ubf[patchi][patchFacei] = (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; Ubf[patchi][patchFacei] += (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } } void Foam::MRFZone::makeAbsolute(surfaceScalarField& phi) const { makeAbsoluteRhoFlux(geometricOneField(), phi); } void Foam::MRFZone::makeAbsolute ( const surfaceScalarField& rho, surfaceScalarField& phi ) const { makeAbsoluteRhoFlux(rho, phi); } void Foam::MRFZone::correctBoundaryVelocity(volVectorField& U) const { if (!active_) { return; } const vector Omega = this->Omega(); // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { const vectorField& patchC = mesh_.Cf().boundaryField()[patchi]; vectorField pfld(Ubf[patchi]); forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; pfld[patchFacei] = (Omega ^ (patchC[patchFacei] - origin_)); } Ubf[patchi] == pfld; } } void Foam::MRFZone::writeData(Ostream& os) const { os << nl; os.write(name_) << nl; os << token::BEGIN_BLOCK << incrIndent << nl; os.writeKeyword("active") << active_ << token::END_STATEMENT << nl; os.writeKeyword("cellZone") << cellZoneName_ << token::END_STATEMENT << nl; os.writeKeyword("origin") << origin_ << token::END_STATEMENT << nl; os.writeKeyword("axis") << axis_ << token::END_STATEMENT << nl; omega_->writeData(os); if (excludedPatchNames_.size()) { os.writeKeyword("nonRotatingPatches") << excludedPatchNames_ << token::END_STATEMENT << nl; } os << decrIndent << token::END_BLOCK << nl; } bool Foam::MRFZone::read(const dictionary& dict) { coeffs_ = dict; active_ = coeffs_.lookupOrDefault("active", true); coeffs_.lookup("cellZone") >> cellZoneName_; cellZoneID_ = mesh_.cellZones().findZoneID(cellZoneName_); return true; } // ************************************************************************* // |
|
Related: some functions inside MRFZone do not check for active. I assume this is not a feature. Attached with added checking. MRFZone-2.C (14,695 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "MRFZone.H" #include "fvMesh.H" #include "volFields.H" #include "surfaceFields.H" #include "fvMatrices.H" #include "faceSet.H" #include "geometricOneField.H" #include "syncTools.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(MRFZone, 0); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::MRFZone::setMRFFaces() { const polyBoundaryMesh& patches = mesh_.boundaryMesh(); // Type per face: // 0:not in zone // 1:moving with frame // 2:other labelList faceType(mesh_.nFaces(), 0); // Determine faces in cell zone // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // (without constructing cells) const labelList& own = mesh_.faceOwner(); const labelList& nei = mesh_.faceNeighbour(); // Cells in zone boolList zoneCell(mesh_.nCells(), false); if (cellZoneID_ != -1) { const labelList& cellLabels = mesh_.cellZones()[cellZoneID_]; forAll(cellLabels, i) { zoneCell[cellLabels[i]] = true; } } label nZoneFaces = 0; for (label facei = 0; facei < mesh_.nInternalFaces(); facei++) { if (zoneCell[own[facei]] || zoneCell[nei[facei]]) { faceType[facei] = 1; nZoneFaces++; } } labelHashSet excludedPatches(excludedPatchLabels_); forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; if (pp.coupled() || excludedPatches.found(patchi)) { forAll(pp, i) { label facei = pp.start()+i; if (zoneCell[own[facei]]) { faceType[facei] = 2; nZoneFaces++; } } } else if (!isA<emptyPolyPatch>(pp)) { forAll(pp, i) { label facei = pp.start()+i; if (zoneCell[own[facei]]) { faceType[facei] = 1; nZoneFaces++; } } } } // Synchronize the faceType across processor patches syncTools::syncFaceList(mesh_, faceType, maxEqOp<label>()); // Now we have for faceType: // 0 : face not in cellZone // 1 : internal face or normal patch face // 2 : coupled patch face or excluded patch face // Sort into lists per patch. internalFaces_.setSize(mesh_.nFaces()); label nInternal = 0; for (label facei = 0; facei < mesh_.nInternalFaces(); facei++) { if (faceType[facei] == 1) { internalFaces_[nInternal++] = facei; } } internalFaces_.setSize(nInternal); labelList nIncludedFaces(patches.size(), 0); labelList nExcludedFaces(patches.size(), 0); forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; forAll(pp, patchFacei) { label facei = pp.start() + patchFacei; if (faceType[facei] == 1) { nIncludedFaces[patchi]++; } else if (faceType[facei] == 2) { nExcludedFaces[patchi]++; } } } includedFaces_.setSize(patches.size()); excludedFaces_.setSize(patches.size()); forAll(nIncludedFaces, patchi) { includedFaces_[patchi].setSize(nIncludedFaces[patchi]); excludedFaces_[patchi].setSize(nExcludedFaces[patchi]); } nIncludedFaces = 0; nExcludedFaces = 0; forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; forAll(pp, patchFacei) { label facei = pp.start() + patchFacei; if (faceType[facei] == 1) { includedFaces_[patchi][nIncludedFaces[patchi]++] = patchFacei; } else if (faceType[facei] == 2) { excludedFaces_[patchi][nExcludedFaces[patchi]++] = patchFacei; } } } if (debug) { faceSet internalFaces(mesh_, "internalFaces", internalFaces_); Pout<< "Writing " << internalFaces.size() << " internal faces in MRF zone to faceSet " << internalFaces.name() << endl; internalFaces.write(); faceSet MRFFaces(mesh_, "includedFaces", 100); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; MRFFaces.insert(patches[patchi].start()+patchFacei); } } Pout<< "Writing " << MRFFaces.size() << " patch faces in MRF zone to faceSet " << MRFFaces.name() << endl; MRFFaces.write(); faceSet excludedFaces(mesh_, "excludedFaces", 100); forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; excludedFaces.insert(patches[patchi].start()+patchFacei); } } Pout<< "Writing " << excludedFaces.size() << " faces in MRF zone with special handling to faceSet " << excludedFaces.name() << endl; excludedFaces.write(); } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::MRFZone::MRFZone ( const word& name, const fvMesh& mesh, const dictionary& dict, const word& cellZoneName ) : mesh_(mesh), name_(name), coeffs_(dict), active_(coeffs_.lookupOrDefault("active", true)), cellZoneName_(cellZoneName), cellZoneID_(), excludedPatchNames_ ( wordReList(coeffs_.lookupOrDefault("nonRotatingPatches", wordReList())) ), origin_(coeffs_.lookup("origin")), axis_(coeffs_.lookup("axis")), omega_(Function1<scalar>::New("omega", coeffs_)) { if (cellZoneName_ == word::null) { coeffs_.lookup("cellZone") >> cellZoneName_; } if (!active_) { cellZoneID_ = -1; } else { cellZoneID_ = mesh_.cellZones().findZoneID(cellZoneName_); axis_ = axis_/mag(axis_); const labelHashSet excludedPatchSet ( mesh_.boundaryMesh().patchSet(excludedPatchNames_) ); excludedPatchLabels_.setSize(excludedPatchSet.size()); label i = 0; forAllConstIter(labelHashSet, excludedPatchSet, iter) { excludedPatchLabels_[i++] = iter.key(); } bool cellZoneFound = (cellZoneID_ != -1); reduce(cellZoneFound, orOp<bool>()); if (!cellZoneFound) { FatalErrorInFunction << "cannot find MRF cellZone " << cellZoneName_ << exit(FatalError); } setMRFFaces(); } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // Foam::vector Foam::MRFZone::Omega() const { return omega_->value(mesh_.time().timeOutputValue())*axis_; } void Foam::MRFZone::addCoriolis ( const volVectorField& U, volVectorField& ddtU ) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; vectorField& ddtUc = ddtU.primitiveFieldRef(); const vectorField& Uc = U; const vector Omega = this->Omega(); forAll(cells, i) { label celli = cells[i]; ddtUc[celli] += (Omega ^ Uc[celli]); } } void Foam::MRFZone::addCoriolis(fvVectorMatrix& UEqn, const bool rhs) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; const scalarField& V = mesh_.V(); vectorField& Usource = UEqn.source(); const vectorField& U = UEqn.psi(); const vector Omega = this->Omega(); if (rhs) { forAll(cells, i) { label celli = cells[i]; Usource[celli] += V[celli]*(Omega ^ U[celli]); } } else { forAll(cells, i) { label celli = cells[i]; Usource[celli] -= V[celli]*(Omega ^ U[celli]); } } } void Foam::MRFZone::addCoriolis ( const volScalarField& rho, fvVectorMatrix& UEqn, const bool rhs ) const { if (cellZoneID_ == -1) { return; } const labelList& cells = mesh_.cellZones()[cellZoneID_]; const scalarField& V = mesh_.V(); vectorField& Usource = UEqn.source(); const vectorField& U = UEqn.psi(); const vector Omega = this->Omega(); if (rhs) { forAll(cells, i) { label celli = cells[i]; Usource[celli] += V[celli]*rho[celli]*(Omega ^ U[celli]); } } else { forAll(cells, i) { label celli = cells[i]; Usource[celli] -= V[celli]*rho[celli]*(Omega ^ U[celli]); } } } void Foam::MRFZone::makeRelative(volVectorField& U) const { if (cellZoneID_ == -1) { return; } const volVectorField& C = mesh_.C(); const vector Omega = this->Omega(); const labelList& cells = mesh_.cellZones()[cellZoneID_]; forAll(cells, i) { label celli = cells[i]; U[celli] -= (Omega ^ (C[celli] - origin_)); } // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; Ubf[patchi][patchFacei] = Zero; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; Ubf[patchi][patchFacei] -= (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } } void Foam::MRFZone::makeRelative(surfaceScalarField& phi) const { makeRelativeRhoFlux(geometricOneField(), phi); } void Foam::MRFZone::makeRelative(FieldField<fvsPatchField, scalar>& phi) const { makeRelativeRhoFlux(oneFieldField(), phi); } void Foam::MRFZone::makeRelative(Field<scalar>& phi, const label patchi) const { makeRelativeRhoFlux(oneField(), phi, patchi); } void Foam::MRFZone::makeRelative ( const surfaceScalarField& rho, surfaceScalarField& phi ) const { makeRelativeRhoFlux(rho, phi); } void Foam::MRFZone::makeAbsolute(volVectorField& U) const { if (cellZoneID_ == -1) { return; } const volVectorField& C = mesh_.C(); const vector Omega = this->Omega(); const labelList& cells = mesh_.cellZones()[cellZoneID_]; forAll(cells, i) { label celli = cells[i]; U[celli] += (Omega ^ (C[celli] - origin_)); } // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; Ubf[patchi][patchFacei] = (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; Ubf[patchi][patchFacei] += (Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_)); } } } void Foam::MRFZone::makeAbsolute(surfaceScalarField& phi) const { makeAbsoluteRhoFlux(geometricOneField(), phi); } void Foam::MRFZone::makeAbsolute ( const surfaceScalarField& rho, surfaceScalarField& phi ) const { makeAbsoluteRhoFlux(rho, phi); } void Foam::MRFZone::correctBoundaryVelocity(volVectorField& U) const { if (!active_) { return; } const vector Omega = this->Omega(); // Included patches volVectorField::Boundary& Ubf = U.boundaryFieldRef(); forAll(includedFaces_, patchi) { const vectorField& patchC = mesh_.Cf().boundaryField()[patchi]; vectorField pfld(Ubf[patchi]); forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; pfld[patchFacei] = (Omega ^ (patchC[patchFacei] - origin_)); } Ubf[patchi] == pfld; } } void Foam::MRFZone::writeData(Ostream& os) const { os << nl; os.write(name_) << nl; os << token::BEGIN_BLOCK << incrIndent << nl; os.writeKeyword("active") << active_ << token::END_STATEMENT << nl; os.writeKeyword("cellZone") << cellZoneName_ << token::END_STATEMENT << nl; os.writeKeyword("origin") << origin_ << token::END_STATEMENT << nl; os.writeKeyword("axis") << axis_ << token::END_STATEMENT << nl; omega_->writeData(os); if (excludedPatchNames_.size()) { os.writeKeyword("nonRotatingPatches") << excludedPatchNames_ << token::END_STATEMENT << nl; } os << decrIndent << token::END_BLOCK << nl; } bool Foam::MRFZone::read(const dictionary& dict) { coeffs_ = dict; active_ = coeffs_.lookupOrDefault("active", true); coeffs_.lookup("cellZone") >> cellZoneName_; cellZoneID_ = mesh_.cellZones().findZoneID(cellZoneName_); return true; } // ************************************************************************* // |
|
MRFZoneTemplates.C (5,620 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "MRFZone.H" #include "fvMesh.H" #include "volFields.H" #include "surfaceFields.H" #include "fvMatrices.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, surfaceScalarField& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; const vectorField& Cfi = Cf; const vectorField& Sfi = Sf; scalarField& phii = phi.primitiveFieldRef(); // Internal faces forAll(internalFaces_, i) { label facei = internalFaces_[i]; phii[facei] -= rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei]; } makeRelativeRhoFlux(rho.boundaryField(), phi.boundaryFieldRef()); } template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, FieldField<fvsPatchField, scalar>& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; // Included patches forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phi[patchi][patchFacei] = 0.0; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phi[patchi][patchFacei] -= rho[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } } template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, Field<scalar>& phi, const label patchi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; // Included patches forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phi[patchFacei] = 0.0; } // Excluded patches forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phi[patchFacei] -= rho[patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } template<class RhoFieldType> void Foam::MRFZone::makeAbsoluteRhoFlux ( const RhoFieldType& rho, surfaceScalarField& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; const vectorField& Cfi = Cf; const vectorField& Sfi = Sf; scalarField& phii = phi.primitiveFieldRef(); // Internal faces forAll(internalFaces_, i) { label facei = internalFaces_[i]; phii[facei] += rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei]; } surfaceScalarField::Boundary& phibf = phi.boundaryFieldRef(); // Included patches forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phibf[patchi][patchFacei] += rho.boundaryField()[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phibf[patchi][patchFacei] += rho.boundaryField()[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } } // ************************************************************************* // |
|
and templates. MRFZoneTemplates-2.C (5,620 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "MRFZone.H" #include "fvMesh.H" #include "volFields.H" #include "surfaceFields.H" #include "fvMatrices.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, surfaceScalarField& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; const vectorField& Cfi = Cf; const vectorField& Sfi = Sf; scalarField& phii = phi.primitiveFieldRef(); // Internal faces forAll(internalFaces_, i) { label facei = internalFaces_[i]; phii[facei] -= rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei]; } makeRelativeRhoFlux(rho.boundaryField(), phi.boundaryFieldRef()); } template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, FieldField<fvsPatchField, scalar>& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; // Included patches forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phi[patchi][patchFacei] = 0.0; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phi[patchi][patchFacei] -= rho[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } } template<class RhoFieldType> void Foam::MRFZone::makeRelativeRhoFlux ( const RhoFieldType& rho, Field<scalar>& phi, const label patchi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; // Included patches forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phi[patchFacei] = 0.0; } // Excluded patches forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phi[patchFacei] -= rho[patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } template<class RhoFieldType> void Foam::MRFZone::makeAbsoluteRhoFlux ( const RhoFieldType& rho, surfaceScalarField& phi ) const { if (!active_) { return; } const surfaceVectorField& Cf = mesh_.Cf(); const surfaceVectorField& Sf = mesh_.Sf(); const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_; const vectorField& Cfi = Cf; const vectorField& Sfi = Sf; scalarField& phii = phi.primitiveFieldRef(); // Internal faces forAll(internalFaces_, i) { label facei = internalFaces_[i]; phii[facei] += rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei]; } surfaceScalarField::Boundary& phibf = phi.boundaryFieldRef(); // Included patches forAll(includedFaces_, patchi) { forAll(includedFaces_[patchi], i) { label patchFacei = includedFaces_[patchi][i]; phibf[patchi][patchFacei] += rho.boundaryField()[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } // Excluded patches forAll(excludedFaces_, patchi) { forAll(excludedFaces_[patchi], i) { label patchFacei = excludedFaces_[patchi][i]; phibf[patchi][patchFacei] += rho.boundaryField()[patchi][patchFacei] * (Omega ^ (Cf.boundaryField()[patchi][patchFacei] - origin_)) & Sf.boundaryField()[patchi][patchFacei]; } } } // ************************************************************************* // |
|
None of the boundaries is wall, pardon me for the confusing initial setup. In the new setup, when none of the patches is wall, I was expecting simpleFoam solver with MRF object, when omega=0, to perform consistently with simpleFoam solver without MRF object. For instance, in the attached case it is set axis (0 1 0) for MRFzone, and patch "inlet" has normal vector in y-direction. Now if I specify Uy component to be -30 at the inlet (fixedValue) boundary I would not expect that Uy component changes during simulation, regardless if inlet patch is in nonRotatingPatches list or not. Actually, I would expect that only Ux and Uz can change as prescribed rotation makes only Ux and Uz components non-zero. In the example I gave, I set omega=0 and was expecting result for nonRotatingPatches (outlet inlet cylinder_surface); or nonRotatingPatches (); to be "same" compared to solution without the MRF object. As you mentioned, Uy component stays at -30 as expected for nonRotatingPatches (outlet inlet cylinder_surface), but for nonRotatingPatches () Uy component at the inlet behaves apparently unpredictably. But if this is expected behavior I rest my case. |
|
You will need to put ALL of the boundary patches in the 'nonRotatingPatches' list. |
|
Patch request resolved in OpenFOAM-dev by commit dc1c6d76005954f230bca829f51eb790d558eeed |
Date Modified | Username | Field | Change |
---|---|---|---|
2016-12-08 14:33 | Solidno | New Issue | |
2016-12-08 14:33 | Solidno | File Added: Report_bug-MRF.tgz | |
2016-12-08 14:33 | Solidno | Tag Attached: fixed value boundary condition for MRF solver | |
2016-12-08 15:21 | henry | Note Added: 0007431 | |
2016-12-08 17:55 | Solidno | File Added: Report_bug-MRF.tar.gz | |
2016-12-08 17:55 | Solidno | Note Added: 0007432 | |
2016-12-08 18:06 | henry | Note Added: 0007433 | |
2016-12-08 18:30 | Solidno | Note Added: 0007434 | |
2016-12-08 18:52 | henry | Note Added: 0007435 | |
2016-12-08 19:40 | Solidno | Note Added: 0007436 | |
2016-12-08 19:48 | henry | Note Added: 0007437 | |
2016-12-09 09:58 | MattijsJ | File Added: MRFZone.C | |
2016-12-09 09:59 | MattijsJ | File Added: MRFZone-2.C | |
2016-12-09 09:59 | MattijsJ | Note Added: 0007443 | |
2016-12-09 10:00 | MattijsJ | File Added: MRFZoneTemplates.C | |
2016-12-09 10:00 | MattijsJ | File Added: MRFZoneTemplates-2.C | |
2016-12-09 10:00 | MattijsJ | Note Added: 0007444 | |
2016-12-09 13:20 | Solidno | Note Added: 0007445 | |
2016-12-09 13:47 | henry | Note Added: 0007446 | |
2016-12-09 16:44 | henry | Assigned To | => henry |
2016-12-09 16:44 | henry | Status | new => resolved |
2016-12-09 16:44 | henry | Resolution | open => fixed |
2016-12-09 16:44 | henry | Fixed in Version | => dev |
2016-12-09 16:44 | henry | Note Added: 0007448 | |
2018-07-10 11:18 | administrator | Tag Detached: fixed value boundary condition for MRF solver |