/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 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 .
Description
Shrinking mesh (part of adding cell layers)
\*----------------------------------------------------------------------------*/
#include "autoLayerDriver.H"
#include "fvMesh.H"
#include "Time.H"
#include "pointFields.H"
#include "motionSmoother.H"
#include "pointData.H"
#include "PointEdgeWave.H"
#include "OBJstream.H"
#include "meshTools.H"
#include "PatchTools.H"
#include "unitConversion.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Calculate inverse sum of edge weights (currently always 1.0)
void Foam::autoLayerDriver::sumWeights
(
const PackedBoolList& isMasterEdge,
const labelList& meshEdges,
const labelList& meshPoints,
const edgeList& edges,
scalarField& invSumWeight
) const
{
const pointField& pts = meshRefiner_.mesh().points();
invSumWeight = 0;
forAll(edges, edgeI)
{
if (isMasterEdge.get(meshEdges[edgeI]) == 1)
{
const edge& e = edges[edgeI];
//scalar eWeight = edgeWeights[edgeI];
//scalar eWeight = 1.0;
scalar eMag = max
(
VSMALL,
mag
(
pts[meshPoints[e[1]]]
- pts[meshPoints[e[0]]]
)
);
scalar eWeight = 1.0/eMag;
invSumWeight[e[0]] += eWeight;
invSumWeight[e[1]] += eWeight;
}
}
syncTools::syncPointList
(
meshRefiner_.mesh(),
meshPoints,
invSumWeight,
plusEqOp(),
scalar(0.0) // null value
);
forAll(invSumWeight, pointI)
{
scalar w = invSumWeight[pointI];
if (w > 0.0)
{
invSumWeight[pointI] = 1.0/w;
}
}
}
// Smooth field on moving patch
void Foam::autoLayerDriver::smoothField
(
const motionSmoother& meshMover,
const PackedBoolList& isMasterPoint,
const PackedBoolList& isMasterEdge,
const labelList& meshEdges,
const scalarField& fieldMin,
const label nSmoothDisp,
scalarField& field
) const
{
const indirectPrimitivePatch& pp = meshMover.patch();
const edgeList& edges = pp.edges();
const labelList& meshPoints = pp.meshPoints();
scalarField invSumWeight(pp.nPoints());
sumWeights
(
isMasterEdge,
meshEdges,
meshPoints,
edges,
invSumWeight
);
// Get smoothly varying patch field.
Info<< "shrinkMeshDistance : Smoothing field ..." << endl;
for (label iter = 0; iter < nSmoothDisp; iter++)
{
scalarField average(pp.nPoints());
averageNeighbours
(
meshMover.mesh(),
isMasterEdge,
meshEdges,
meshPoints,
edges,
invSumWeight,
field,
average
);
// Transfer to field
forAll(field, pointI)
{
//full smoothing neighbours + point value
average[pointI] = 0.5*(field[pointI]+average[pointI]);
// perform monotonic smoothing
if
(
average[pointI] < field[pointI]
&& average[pointI] >= fieldMin[pointI]
)
{
field[pointI] = average[pointI];
}
}
// Do residual calculation every so often.
if ((iter % 10) == 0)
{
scalar resid = meshRefinement::gAverage
(
meshMover.mesh(),
isMasterPoint,
meshPoints,
mag(field-average)()
);
Info<< " Iteration " << iter << " residual " << resid << endl;
}
}
}
//XXXXXXXXX
//void Foam::autoLayerDriver::smoothField
//(
// const motionSmoother& meshMover,
// const PackedBoolList& isMasterEdge,
// const labelList& meshEdges,
// const scalarField& fieldMin,
// const label nSmoothDisp,
// scalarField& field
//) const
//{
// const indirectPrimitivePatch& pp = meshMover.patch();
// const edgeList& edges = pp.edges();
// const labelList& meshPoints = pp.meshPoints();
//
// scalarField invSumWeight(pp.nPoints());
// sumWeights
// (
// isMasterEdge,
// meshEdges,
// meshPoints,
// edges,
// invSumWeight
// );
//
// // Get smoothly varying patch field.
// Info<< "shrinkMeshDistance : (lambda-mu) Smoothing field ..." << endl;
//
//
// const scalar lambda = 0.33;
// const scalar mu = -0.34;
//
// for (label iter = 0; iter < 90; iter++)
// {
// scalarField average(pp.nPoints());
//
// // Calculate average of field
// averageNeighbours
// (
// meshMover.mesh(),
// isMasterEdge,
// meshEdges,
// meshPoints,
// pp.edges(),
// invSumWeight,
// field,
// average
// );
//
// forAll(field, i)
// {
// if (field[i] >= fieldMin[i])
// {
// field[i] = (1-lambda)*field[i]+lambda*average[i];
// }
// }
//
//
// // Calculate average of field
// averageNeighbours
// (
// meshMover.mesh(),
// isMasterEdge,
// meshEdges,
// meshPoints,
// pp.edges(),
// invSumWeight,
// field,
// average
// );
//
// forAll(field, i)
// {
// if (field[i] >= fieldMin[i])
// {
// field[i] = (1-mu)*field[i]+mu*average[i];
// }
// }
//
//
// // Do residual calculation every so often.
// if ((iter % 10) == 0)
// {
// Info<< " Iteration " << iter << " residual "
// << gSum(mag(field-average))
// /returnReduce(average.size(), sumOp