/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | \\/ M anipulation | ------------------------------------------------------------------------------- | Copyright (C) 2016-2017 Wikki 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 "faMesh.H" #include "faMeshLduAddressing.H" #include "areaFields.H" #include "edgeFields.H" #include "primitiveFacePatch.H" #include "fac.H" #include "processorFaPatch.H" #include "wedgeFaPatch.H" #include "PstreamCombineReduceOps.H" #include "coordinateSystem.H" #include "scalarMatrices.H" #include "processorFaPatchFields.H" #include "emptyFaPatchFields.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::faMesh::calcLduAddressing() const { DebugInFunction << "Calculating addressing" << endl; if (lduPtr_) { FatalErrorInFunction << "lduPtr_ already allocated" << abort(FatalError); } lduPtr_ = new faMeshLduAddressing(*this); } void Foam::faMesh::calcPatchStarts() const { DebugInFunction << "Calculating patch starts" << endl; if (patchStartsPtr_) { FatalErrorInFunction << "patchStartsPtr_ already allocated" << abort(FatalError); } patchStartsPtr_ = new labelList(boundary().size(), -1); labelList& patchStarts = *patchStartsPtr_; patchStarts[0] = nInternalEdges(); for (label i = 1; i < boundary().size(); ++i) { patchStarts[i] = patchStarts[i - 1] + boundary()[i - 1].faPatch::size(); } } void Foam::faMesh::calcLe() const { DebugInFunction << "Calculating local edges" << endl; if (LePtr_) { FatalErrorInFunction << "LePtr_ already allocated" << abort(FatalError); } LePtr_ = new edgeVectorField ( IOobject ( "Le", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimLength ); edgeVectorField& Le = *LePtr_; const pointField& pPoints = points(); const edgeList& pEdges = edges(); const edgeVectorField& eCentres = edgeCentres(); const areaVectorField& fCentres = areaCentres(); const edgeVectorField& edgeNormals = edgeAreaNormals(); vectorField& leInternal = Le.ref(); const vectorField& edgeNormalsInternal = edgeNormals.internalField(); const vectorField& fCentresInternal = fCentres.internalField(); const vectorField& eCentresInternal = eCentres.internalField(); const scalarField& magLeInternal = magLe().internalField(); forAll(leInternal, edgeI) { leInternal[edgeI] = pEdges[edgeI].vec(pPoints) ^ edgeNormalsInternal[edgeI]; leInternal[edgeI] *= - sign ( leInternal[edgeI] & ( fCentresInternal[owner()[edgeI]] - eCentresInternal[edgeI] ) ); leInternal[edgeI] *= magLeInternal[edgeI]/mag(leInternal[edgeI]); } forAll(boundary(), patchI) { const labelUList& bndEdgeFaces = boundary()[patchI].edgeFaces(); const edgeList::subList bndEdges = boundary()[patchI].patchSlice(pEdges); const vectorField& bndEdgeNormals = edgeNormals.boundaryField()[patchI]; vectorField& patchLe = Le.boundaryFieldRef()[patchI]; const vectorField& patchECentres = eCentres.boundaryField()[patchI]; forAll(patchLe, edgeI) { patchLe[edgeI] = bndEdges[edgeI].vec(pPoints) ^ bndEdgeNormals[edgeI]; patchLe[edgeI] *= - sign ( patchLe[edgeI]& ( fCentresInternal[bndEdgeFaces[edgeI]] - patchECentres[edgeI] ) ); patchLe[edgeI] *= magLe().boundaryField()[patchI][edgeI] /mag(patchLe[edgeI]); } } } void Foam::faMesh::calcMagLe() const { DebugInFunction << "Calculating local edge magnitudes" << endl; if (magLePtr_) { FatalErrorInFunction << "magLePtr_ already allocated" << abort(FatalError); } magLePtr_ = new edgeScalarField ( IOobject ( "magLe", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimLength ); edgeScalarField& magLe = *magLePtr_; const pointField& localPoints = points(); const edgeList::subList internalEdges = edgeList::subList(edges(), nInternalEdges()); forAll(internalEdges, edgeI) { magLe.ref()[edgeI] = internalEdges[edgeI].mag(localPoints); } forAll(boundary(), patchI) { const edgeList::subList patchEdges = boundary()[patchI].patchSlice(edges()); forAll(patchEdges, edgeI) { magLe.boundaryFieldRef()[patchI][edgeI] = patchEdges[edgeI].mag(localPoints); } } } void Foam::faMesh::calcAreaCentres() const { DebugInFunction << "Calculating face centres" << endl; if (centresPtr_) { FatalErrorInFunction << "centresPtr_ already allocated" << abort(FatalError); } centresPtr_ = new areaVectorField ( IOobject ( "centres", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimLength ); areaVectorField& centres = *centresPtr_; const pointField& localPoints = points(); const faceList& localFaces = faces(); forAll(localFaces, faceI) { centres.ref()[faceI] = localFaces[faceI].centre(localPoints); } forAll(boundary(), patchI) { const edgeList::subList patchEdges = boundary()[patchI].patchSlice(edges()); forAll(patchEdges, edgeI) { centres.boundaryFieldRef()[patchI][edgeI] = patchEdges[edgeI].centre(localPoints); } } forAll(centres.boundaryField(), patchI) { //HJ: this is wrong! 5/Aug/2011 if ( isA ( centres.boundaryField()[patchI] ) ) { centres.boundaryFieldRef()[patchI].initEvaluate(); centres.boundaryFieldRef()[patchI].evaluate(); } } } void Foam::faMesh::calcEdgeCentres() const { DebugInFunction << "Calculating edge centres" << endl; if (edgeCentresPtr_) { FatalErrorInFunction << "edgeCentresPtr_ already allocated" << abort(FatalError); } edgeCentresPtr_ = new edgeVectorField ( IOobject ( "edgeCentres", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimLength ); edgeVectorField& edgeCentres = *edgeCentresPtr_; const pointField& localPoints = points(); const edgeList::subList internalEdges = edgeList::subList(edges(), nInternalEdges()); forAll(internalEdges, edgeI) { edgeCentres.ref()[edgeI] = internalEdges[edgeI].centre(localPoints); } forAll(boundary(), patchI) { const edgeList::subList patchEdges = boundary()[patchI].patchSlice(edges()); forAll(patchEdges, edgeI) { edgeCentres.boundaryFieldRef()[patchI][edgeI] = patchEdges[edgeI].centre(localPoints); } } } void Foam::faMesh::calcS() const { DebugInFunction << "Calculating areas" << endl; if (SPtr_) { FatalErrorInFunction << "SPtr_ already allocated" << abort(FatalError); } SPtr_ = new DimensionedField ( IOobject ( "S", time().timeName(), mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), *this, dimArea ); DimensionedField& S = *SPtr_; const pointField& localPoints = points(); const faceList& localFaces = faces(); forAll(S, faceI) { S[faceI] = localFaces[faceI].mag(localPoints); } } void Foam::faMesh::calcFaceAreaNormals() const { DebugInFunction << "Calculating face area normals" << endl; if (faceAreaNormalsPtr_) { FatalErrorInFunction << "faceAreaNormalsPtr_ already allocated" << abort(FatalError); } faceAreaNormalsPtr_ = new areaVectorField ( IOobject ( "faceAreaNormals", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimless ); areaVectorField& faceAreaNormals = *faceAreaNormalsPtr_; const pointField& localPoints = points(); const faceList& localFaces = faces(); vectorField& nInternal = faceAreaNormals.ref(); forAll(localFaces, faceI) { nInternal[faceI] = localFaces[faceI].normal(localPoints)/ localFaces[faceI].mag(localPoints); } forAll(boundary(), patchI) { faceAreaNormals.boundaryFieldRef()[patchI] = edgeAreaNormals().boundaryField()[patchI]; } forAll(faceAreaNormals.boundaryField(), patchI) { if ( isA ( faceAreaNormals.boundaryField()[patchI] ) ) { faceAreaNormals.boundaryFieldRef()[patchI].initEvaluate(); faceAreaNormals.boundaryFieldRef()[patchI].evaluate(); } } } void Foam::faMesh::calcEdgeAreaNormals() const { DebugInFunction << "Calculating edge area normals" << endl; if (edgeAreaNormalsPtr_) { FatalErrorInFunction << "edgeAreaNormalsPtr_ already allocated" << abort(FatalError); } edgeAreaNormalsPtr_ = new edgeVectorField ( IOobject ( "edgeAreaNormals", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimless ); edgeVectorField& edgeAreaNormals = *edgeAreaNormalsPtr_; // Point area normals const vectorField& pointNormals = pointAreaNormals(); // // Primitive patch edge normals // const labelListList& patchPointEdges = patch().pointEdges(); // vectorField patchEdgeNormals(nEdges(), vector::zero); // forAll(pointNormals, pointI) // { // const labelList& curPointEdges = patchPointEdges[pointI]; // forAll(curPointEdges, edgeI) // { // label curEdge = curPointEdges[edgeI]; // patchEdgeNormals[curEdge] += 0.5*pointNormals[pointI]; // } // } // patchEdgeNormals /= mag(patchEdgeNormals); // // Edge area normals // label nIntEdges = patch().nInternalEdges(); // for (label edgeI = 0; edgeI < nIntEdges; ++edgeI) // { // edgeAreaNormals.ref()[edgeI] = // patchEdgeNormals[edgeI]; // } // forAll(boundary(), patchI) // { // const labelList& edgeLabels = boundary()[patchI]; // forAll(edgeAreaNormals.boundaryFieldRef()[patchI], edgeI) // { // edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] = // patchEdgeNormals[edgeLabels[edgeI]]; // } // } forAll(edgeAreaNormals.internalField(), edgeI) { vector e = edges()[edgeI].vec(points()); e /= mag(e); // scalar wStart = // 1.0 - sqr(mag(e^pointNormals[edges()[edgeI].end()])); // scalar wEnd = // 1.0 - sqr(mag(e^pointNormals[edges()[edgeI].start()])); // wStart = 1.0; // wEnd = 1.0; // edgeAreaNormals.ref()[edgeI] = // wStart*pointNormals[edges()[edgeI].start()] // + wEnd*pointNormals[edges()[edgeI].end()]; // vector eC = // 0.5 // *( // points()[edges()[edgeI].start()] // + points()[edges()[edgeI].end()] // ); // vector eCp = 0.5* // ( // points()[edges()[edgeI].start()] // + pointNormals[edges()[edgeI].start()] // points()[edges()[edgeI].end()] + // ); edgeAreaNormals.ref()[edgeI] = pointNormals[edges()[edgeI].start()] + pointNormals[edges()[edgeI].end()]; edgeAreaNormals.ref()[edgeI] -= e*(e&edgeAreaNormals.internalField()[edgeI]); } edgeAreaNormals.ref() /= mag(edgeAreaNormals.internalField()); forAll(boundary(), patchI) { const edgeList::subList patchEdges = boundary()[patchI].patchSlice(edges()); forAll(patchEdges, edgeI) { edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] = pointNormals[patchEdges[edgeI].start()] + pointNormals[patchEdges[edgeI].end()]; vector e = patchEdges[edgeI].vec(points()); e /= mag(e); edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] -= e*(e&edgeAreaNormals.boundaryField()[patchI][edgeI]); } edgeAreaNormals.boundaryFieldRef()[patchI] /= mag(edgeAreaNormals.boundaryField()[patchI]); } } void Foam::faMesh::calcFaceCurvatures() const { DebugInFunction << "Calculating face curvatures" << endl; if (faceCurvaturesPtr_) { FatalErrorInFunction << "faceCurvaturesPtr_ already allocated" << abort(FatalError); } faceCurvaturesPtr_ = new areaScalarField ( IOobject ( "faceCurvatures", mesh().pointsInstance(), meshSubDir, mesh() ), *this, dimless/dimLength ); areaScalarField& faceCurvatures = *faceCurvaturesPtr_; // faceCurvatures = // fac::edgeIntegrate(Le()*edgeLengthCorrection()) // &faceAreaNormals(); areaVectorField kN(fac::edgeIntegrate(Le()*edgeLengthCorrection())); faceCurvatures = sign(kN&faceAreaNormals())*mag(kN); } void Foam::faMesh::calcEdgeTransformTensors() const { DebugInFunction << "Calculating edge transformation tensors" << endl; if (edgeTransformTensorsPtr_) { FatalErrorInFunction << "edgeTransformTensorsPtr_ already allocated" << abort(FatalError); } edgeTransformTensorsPtr_ = new FieldField(nEdges()); FieldField& edgeTransformTensors = *edgeTransformTensorsPtr_; const areaVectorField& Nf = faceAreaNormals(); const areaVectorField& Cf = areaCentres(); const edgeVectorField& Ne = edgeAreaNormals(); const edgeVectorField& Ce = edgeCentres(); // Internal edges transformation tensors for (label edgeI=0; edgeI(3, I)); vector E = Ce.internalField()[edgeI]; if (skew()) { E -= skewCorrectionVectors().internalField()[edgeI]; } // Edge transformation tensor vector il = E - Cf.internalField()[owner()[edgeI]]; il -= Ne.internalField()[edgeI] *(Ne.internalField()[edgeI]&il); il /= mag(il); vector kl = Ne.internalField()[edgeI]; vector jl = kl^il; edgeTransformTensors[edgeI][0] = tensor ( il.x(), il.y(), il.z(), jl.x(), jl.y(), jl.z(), kl.x(), kl.y(), kl.z() ); // Owner transformation tensor il = E - Cf.internalField()[owner()[edgeI]]; il -= Nf.internalField()[owner()[edgeI]] *(Nf.internalField()[owner()[edgeI]]&il); il /= mag(il); kl = Nf.internalField()[owner()[edgeI]]; jl = kl^il; edgeTransformTensors[edgeI][1] = tensor ( il.x(), il.y(), il.z(), jl.x(), jl.y(), jl.z(), kl.x(), kl.y(), kl.z() ); // Neighbour transformation tensor il = Cf.internalField()[neighbour()[edgeI]] - E; il -= Nf.internalField()[neighbour()[edgeI]] *(Nf.internalField()[neighbour()[edgeI]]&il); il /= mag(il); kl = Nf.internalField()[neighbour()[edgeI]]; jl = kl^il; edgeTransformTensors[edgeI][2] = tensor ( il.x(), il.y(), il.z(), jl.x(), jl.y(), jl.z(), kl.x(), kl.y(), kl.z() ); } // Boundary edges transformation tensors forAll(boundary(), patchI) { if (boundary()[patchI].coupled()) { const labelUList& edgeFaces = boundary()[patchI].edgeFaces(); vectorField ngbCf(Cf.boundaryField()[patchI].patchNeighbourField()); vectorField ngbNf(Nf.boundaryField()[patchI].patchNeighbourField()); forAll(edgeFaces, edgeI) { edgeTransformTensors.set ( boundary()[patchI].start() + edgeI, new Field(3, I) ); vector E = Ce.boundaryField()[patchI][edgeI]; if (skew()) { E -= skewCorrectionVectors() .boundaryField()[patchI][edgeI]; } // Edge transformation tensor vector il = E - Cf.internalField()[edgeFaces[edgeI]]; il -= Ne.boundaryField()[patchI][edgeI] *(Ne.boundaryField()[patchI][edgeI]&il); il /= mag(il); vector kl = Ne.boundaryField()[patchI][edgeI]; vector jl = kl^il; edgeTransformTensors[boundary()[patchI].start() + edgeI][0] = tensor(il, jl, kl); // Owner transformation tensor il = E - Cf.internalField()[edgeFaces[edgeI]]; il -= Nf.internalField()[edgeFaces[edgeI]] *(Nf.internalField()[edgeFaces[edgeI]]&il); il /= mag(il); kl = Nf.internalField()[edgeFaces[edgeI]]; jl = kl^il; edgeTransformTensors[boundary()[patchI].start() + edgeI][1] = tensor(il, jl, kl); // Neighbour transformation tensor il = ngbCf[edgeI] - E; il -= ngbNf[edgeI]*(ngbNf[edgeI]&il); il /= mag(il); kl = ngbNf[edgeI]; jl = kl^il; edgeTransformTensors[boundary()[patchI].start() + edgeI][2] = tensor(il, jl, kl); } } else { const labelUList& edgeFaces = boundary()[patchI].edgeFaces(); forAll(edgeFaces, edgeI) { edgeTransformTensors.set ( boundary()[patchI].start() + edgeI, new Field(3, I) ); vector E = Ce.boundaryField()[patchI][edgeI]; if (skew()) { E -= skewCorrectionVectors() .boundaryField()[patchI][edgeI]; } // Edge transformation tensor vector il = E - Cf.internalField()[edgeFaces[edgeI]]; il -= Ne.boundaryField()[patchI][edgeI] *(Ne.boundaryField()[patchI][edgeI]&il); il /= mag(il); vector kl = Ne.boundaryField()[patchI][edgeI]; vector jl = kl^il; edgeTransformTensors[boundary()[patchI].start() + edgeI][0] = tensor(il, jl, kl); // Owner transformation tensor il = E - Cf.internalField()[edgeFaces[edgeI]]; il -= Nf.internalField()[edgeFaces[edgeI]] *(Nf.internalField()[edgeFaces[edgeI]]&il); il /= mag(il); kl = Nf.internalField()[edgeFaces[edgeI]]; jl = kl^il; edgeTransformTensors[boundary()[patchI].start() + edgeI][1] = tensor(il, jl, kl); } } } } Foam::labelList Foam::faMesh::internalPoints() const { DebugInFunction << "Calculating internal points" << endl; const edgeList& edges = patch().edges(); label nIntEdges = patch().nInternalEdges(); List internal(nPoints(), true); for (label curEdge = nIntEdges; curEdge < edges.size(); ++curEdge) { internal[edges[curEdge].start()] = false; internal[edges[curEdge].end()] = false; } SLList