/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2015 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 "snappySnapDriver.H" #include "polyTopoChange.H" #include "syncTools.H" #include "fvMesh.H" #include "OBJstream.H" #include "motionSmoother.H" #include "refinementSurfaces.H" #include "refinementFeatures.H" #include "unitConversion.H" #include "plane.H" #include "featureEdgeMesh.H" #include "treeDataPoint.H" #include "indexedOctree.H" #include "snapParameters.H" #include "PatchTools.H" #include "pyramidPointFaceRef.H" #include "localPointRegion.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { template class listPlusEqOp { public: void operator()(List& x, const List& y) const { label sz = x.size(); x.setSize(sz+y.size()); forAll(y, i) { x[sz++] = y[i]; } } }; } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // bool Foam::snappySnapDriver::isFeaturePoint ( const scalar featureCos, const indirectPrimitivePatch& pp, const PackedBoolList& isFeatureEdge, const label pointi ) const { const pointField& points = pp.localPoints(); const edgeList& edges = pp.edges(); const labelList& pEdges = pp.pointEdges()[pointi]; label nFeatEdges = 0; forAll(pEdges, i) { if (isFeatureEdge[pEdges[i]]) { nFeatEdges++; for (label j = i+1; j < pEdges.size(); j++) { if (isFeatureEdge[pEdges[j]]) { const edge& ei = edges[pEdges[i]]; const edge& ej = edges[pEdges[j]]; const point& p = points[pointi]; const point& pi = points[ei.otherVertex(pointi)]; const point& pj = points[ej.otherVertex(pointi)]; vector vi = p-pi; scalar viMag = mag(vi); vector vj = pj-p; scalar vjMag = mag(vj); if ( viMag > SMALL && vjMag > SMALL && ((vi/viMag & vj/vjMag) < featureCos) ) { return true; } } } } } if (nFeatEdges == 1) { // End of feature-edge string return true; } return false; } void Foam::snappySnapDriver::smoothAndConstrain ( const PackedBoolList& isPatchMasterEdge, const indirectPrimitivePatch& pp, const labelList& meshEdges, const List& constraints, vectorField& disp ) const { const fvMesh& mesh = meshRefiner_.mesh(); for (label avgIter = 0; avgIter < 20; avgIter++) { // Calculate average displacement of neighbours // - unconstrained (i.e. surface) points use average of all // neighbouring points // - from testing it has been observed that it is not beneficial // to have edge constrained points use average of all edge or point // constrained neighbours since they're already attracted to // the nearest point on the feature. // Having them attract to point-constrained neighbours does not // make sense either since there is usually just one of them so // it severely distorts it. // - same for feature points. They are already attracted to the // nearest feature point. vectorField dispSum(pp.nPoints(), Zero); labelList dispCount(pp.nPoints(), 0); const labelListList& pointEdges = pp.pointEdges(); const edgeList& edges = pp.edges(); forAll(pointEdges, pointi) { const labelList& pEdges = pointEdges[pointi]; label nConstraints = constraints[pointi].first(); if (nConstraints <= 1) { forAll(pEdges, i) { label edgei = pEdges[i]; if (isPatchMasterEdge[edgei]) { label nbrPointi = edges[edgei].otherVertex(pointi); if (constraints[nbrPointi].first() >= nConstraints) { dispSum[pointi] += disp[nbrPointi]; dispCount[pointi]++; } } } } } syncTools::syncPointList ( mesh, pp.meshPoints(), dispSum, plusEqOp(), vector::zero, mapDistribute::transform() ); syncTools::syncPointList ( mesh, pp.meshPoints(), dispCount, plusEqOp