/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2020 OpenCFD 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 "surfaceSlipDisplacementPointPatchVectorField.H" #include "addToRunTimeSelectionTable.H" #include "Time.H" #include "transformField.H" #include "fvMesh.H" #include "displacementMotionSolver.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // const Foam::Enum < Foam::surfaceSlipDisplacementPointPatchVectorField::projectMode > Foam::surfaceSlipDisplacementPointPatchVectorField::projectModeNames_ ({ { projectMode::NEAREST, "nearest" }, { projectMode::POINTNORMAL, "pointNormal" }, { projectMode::FIXEDNORMAL, "fixedNormal" }, }); // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::surfaceSlipDisplacementPointPatchVectorField::calcProjection ( vectorField& displacement ) const { const polyMesh& mesh = patch().boundaryMesh().mesh()(); const pointField& localPoints = patch().localPoints(); const labelList& meshPoints = patch().meshPoints(); //const scalar deltaT = mesh.time().deltaTValue(); // Construct large enough vector in direction of projectDir so // we're guaranteed to hit something. //- Per point projection vector: const scalar projectLen = mag(mesh.bounds().max()-mesh.bounds().min()); // For case of fixed projection vector: vector projectVec(0, 0, 0); if (projectMode_ == FIXEDNORMAL) { vector n = projectDir_/mag(projectDir_); projectVec = projectLen*n; } // Get fixed points (bit of a hack) const pointZone* zonePtr = nullptr; if (frozenPointsZone_.size() > 0) { const pointZoneMesh& pZones = mesh.pointZones(); zonePtr = &pZones[frozenPointsZone_]; Pout<< "surfaceSlipDisplacementPointPatchVectorField : Fixing all " << zonePtr->size() << " points in pointZone " << zonePtr->name() << endl; } // Get the starting locations from the motionSolver const pointField& points0 = mesh.lookupObject ( "dynamicMeshDict" ).points0(); pointField start(meshPoints.size()); forAll(start, i) { start[i] = points0[meshPoints[i]] + displacement[i]; } label nNotProjected = 0; if (projectMode_ == NEAREST) { List nearest; labelList hitSurfaces; surfaces().findNearest ( start, scalarField(start.size(), sqr(projectLen)), hitSurfaces, nearest ); forAll(nearest, i) { if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0)) { // Fixed point. Reset to point0 location. displacement[i] = points0[meshPoints[i]] - localPoints[i]; } else if (nearest[i].hit()) { displacement[i] = nearest[i].hitPoint() - points0[meshPoints[i]]; } else { nNotProjected++; if (debug) { Pout<< " point:" << meshPoints[i] << " coord:" << localPoints[i] << " did not find any surface within " << projectLen << endl; } } } } else { // Do tests on all points. Combine later on. // 1. Check if already on surface List nearest; { labelList nearestSurface; surfaces().findNearest ( start, scalarField(start.size(), sqr(SMALL)), nearestSurface, nearest ); } // 2. intersection. (combined later on with information from nearest // above) vectorField projectVecs(start.size(), projectVec); if (projectMode_ == POINTNORMAL) { projectVecs = projectLen*patch().pointNormals(); } // Knock out any wedge component scalarField offset(start.size(), Zero); if (wedgePlane_ >= 0 && wedgePlane_ < vector::nComponents) { forAll(offset, i) { offset[i] = start[i][wedgePlane_]; start[i][wedgePlane_] = 0; projectVecs[i][wedgePlane_] = 0; } } List rightHit; { labelList rightSurf; surfaces().findAnyIntersection ( start, start+projectVecs, rightSurf, rightHit ); } List leftHit; { labelList leftSurf; surfaces().findAnyIntersection ( start, start-projectVecs, leftSurf, leftHit ); } // 3. Choose either -fixed, nearest, right, left. forAll(displacement, i) { if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0)) { // Fixed point. Reset to point0 location. displacement[i] = points0[meshPoints[i]] - localPoints[i]; } else if (nearest[i].hit()) { // Found nearest. displacement[i] = nearest[i].hitPoint() - points0[meshPoints[i]]; } else { pointIndexHit interPt; if (rightHit[i].hit()) { if (leftHit[i].hit()) { if ( magSqr(rightHit[i].hitPoint()-start[i]) < magSqr(leftHit[i].hitPoint()-start[i]) ) { interPt = rightHit[i]; } else { interPt = leftHit[i]; } } else { interPt = rightHit[i]; } } else { if (leftHit[i].hit()) { interPt = leftHit[i]; } } if (interPt.hit()) { if (wedgePlane_ >= 0 && wedgePlane_ < vector::nComponents) { interPt.rawPoint()[wedgePlane_] += offset[i]; } displacement[i] = interPt.rawPoint()-points0[meshPoints[i]]; } else { nNotProjected++; if (debug) { Pout<< " point:" << meshPoints[i] << " coord:" << localPoints[i] << " did not find any intersection between" << " ray from " << start[i]-projectVecs[i] << " to " << start[i]+projectVecs[i] << endl; } } } } } reduce(nNotProjected, sumOp