Merge commit 'OpenCFD/master' into olesenm
This commit is contained in:
commit
f0f677e3d6
@ -161,6 +161,10 @@ surfaces
|
|||||||
isoField rho;
|
isoField rho;
|
||||||
isoValue 0.5;
|
isoValue 0.5;
|
||||||
interpolate true;
|
interpolate true;
|
||||||
|
|
||||||
|
//zone ABC; // Optional: zone only
|
||||||
|
//exposedPatchName fixedWalls; // Optional: zone only
|
||||||
|
|
||||||
// regularise false; // Optional: do not simplify
|
// regularise false; // Optional: do not simplify
|
||||||
}
|
}
|
||||||
constantIso
|
constantIso
|
||||||
@ -171,7 +175,7 @@ surfaces
|
|||||||
isoField rho;
|
isoField rho;
|
||||||
isoValue 0.5;
|
isoValue 0.5;
|
||||||
interpolate false;
|
interpolate false;
|
||||||
// regularise false; // Optional: do not simplify
|
regularise false; // do not simplify
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -206,7 +206,8 @@ void Foam::isoSurface::calcCutTypes
|
|||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "isoSurface : detected " << nCutCells_
|
Pout<< "isoSurface : detected " << nCutCells_
|
||||||
<< " candidate cut cells." << endl;
|
<< " candidate cut cells (out of " << mesh_.nCells()
|
||||||
|
<< ")." << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,65 +815,53 @@ Foam::triSurface Foam::isoSurface::stitchTriPoints
|
|||||||
tris.transfer(dynTris);
|
tris.transfer(dynTris);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Use face centres to determine 'flat hole' situation (see RMT paper).
|
|
||||||
// Two unconnected triangles get connected because (some of) the edges
|
|
||||||
// separating them get collapsed. Below only checks for duplicate triangles,
|
|
||||||
// not non-manifold edge connectivity.
|
|
||||||
if (checkDuplicates)
|
|
||||||
{
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "isoSurface : merged from " << nTris
|
Pout<< "isoSurface : merged from " << nTris
|
||||||
<< " down to " << tris.size() << " triangles." << endl;
|
<< " down to " << tris.size() << " triangles." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointField centres(tris.size());
|
|
||||||
forAll(tris, triI)
|
|
||||||
{
|
|
||||||
centres[triI] = tris[triI].centre(newPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointField mergedCentres;
|
|
||||||
labelList oldToMerged;
|
|
||||||
bool hasMerged = mergePoints
|
|
||||||
(
|
|
||||||
centres,
|
|
||||||
mergeDistance_,
|
|
||||||
false,
|
|
||||||
oldToMerged,
|
|
||||||
mergedCentres
|
|
||||||
);
|
|
||||||
|
|
||||||
if (debug)
|
// Determine 'flat hole' situation (see RMT paper).
|
||||||
|
// Two unconnected triangles get connected because (some of) the edges
|
||||||
|
// separating them get collapsed. Below only checks for duplicate triangles,
|
||||||
|
// not non-manifold edge connectivity.
|
||||||
|
if (checkDuplicates)
|
||||||
{
|
{
|
||||||
Pout<< "isoSurface : detected "
|
labelListList pointFaces;
|
||||||
<< centres.size()-mergedCentres.size()
|
invertManyToMany(newPoints.size(), tris, pointFaces);
|
||||||
<< " duplicate triangles." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasMerged)
|
|
||||||
{
|
|
||||||
// Filter out duplicates.
|
// Filter out duplicates.
|
||||||
label newTriI = 0;
|
|
||||||
DynamicList<label> newToOldTri(tris.size());
|
DynamicList<label> newToOldTri(tris.size());
|
||||||
labelList newToMaster(mergedCentres.size(), -1);
|
|
||||||
forAll(tris, triI)
|
forAll(tris, triI)
|
||||||
{
|
{
|
||||||
label mergedI = oldToMerged[triI];
|
const labelledTri& tri = tris[triI];
|
||||||
|
|
||||||
if (newToMaster[mergedI] == -1)
|
const labelList& pFaces = pointFaces[tri[0]];
|
||||||
|
|
||||||
|
// Find the minimum of any duplicates
|
||||||
|
label dupTriI = -1;
|
||||||
|
forAll(pFaces, i)
|
||||||
{
|
{
|
||||||
newToMaster[mergedI] = triI;
|
if (pFaces[i] < triI && tris[pFaces[i]] == tri)
|
||||||
newToOldTri.append(triMap[triI]);
|
{
|
||||||
tris[newTriI++] = tris[triI];
|
dupTriI = pFaces[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dupTriI == -1)
|
||||||
|
{
|
||||||
|
// There is no lower triangle
|
||||||
|
label newTriI = newToOldTri.size();
|
||||||
|
newToOldTri.append(triI);
|
||||||
|
tris[newTriI] = tris[triI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triMap.transfer(newToOldTri);
|
triMap.transfer(newToOldTri);
|
||||||
tris.setSize(newTriI);
|
tris.setSize(triMap.size());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return triSurface(tris, geometricSurfacePatchList(0), newPoints, true);
|
return triSurface(tris, geometricSurfacePatchList(0), newPoints, true);
|
||||||
@ -986,7 +975,7 @@ void Foam::isoSurface::calcAddressing
|
|||||||
{
|
{
|
||||||
Pout<< "isoSurface : detected "
|
Pout<< "isoSurface : detected "
|
||||||
<< mergedCentres.size()
|
<< mergedCentres.size()
|
||||||
<< " edges on " << surf.size() << " triangles." << endl;
|
<< " geometric edges on " << surf.size() << " triangles." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasMerged)
|
if (!hasMerged)
|
||||||
@ -1013,6 +1002,10 @@ void Foam::isoSurface::calcAddressing
|
|||||||
edgeFace1 = -1;
|
edgeFace1 = -1;
|
||||||
edgeFacesRest.clear();
|
edgeFacesRest.clear();
|
||||||
|
|
||||||
|
// Overflow edge faces for geometric shared edges that turned
|
||||||
|
// out to be different anyway.
|
||||||
|
EdgeMap<labelList> extraEdgeFaces(mergedCentres.size()/100);
|
||||||
|
|
||||||
forAll(oldToMerged, oldEdgeI)
|
forAll(oldToMerged, oldEdgeI)
|
||||||
{
|
{
|
||||||
label triI = oldEdgeI / 3;
|
label triI = oldEdgeI / 3;
|
||||||
@ -1020,8 +1013,48 @@ void Foam::isoSurface::calcAddressing
|
|||||||
|
|
||||||
if (edgeFace0[edgeI] == -1)
|
if (edgeFace0[edgeI] == -1)
|
||||||
{
|
{
|
||||||
|
// First triangle for edge
|
||||||
edgeFace0[edgeI] = triI;
|
edgeFace0[edgeI] = triI;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//- Check that the two triangles actually topologically
|
||||||
|
// share an edge
|
||||||
|
const labelledTri& prevTri = surf[edgeFace0[edgeI]];
|
||||||
|
const labelledTri& tri = surf[triI];
|
||||||
|
|
||||||
|
label fp = oldEdgeI % 3;
|
||||||
|
|
||||||
|
edge e(tri[fp], tri[tri.fcIndex(fp)]);
|
||||||
|
|
||||||
|
label prevTriIndex = -1;
|
||||||
|
|
||||||
|
forAll(prevTri, i)
|
||||||
|
{
|
||||||
|
if (edge(prevTri[i], prevTri[prevTri.fcIndex(i)]) == e)
|
||||||
|
{
|
||||||
|
prevTriIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevTriIndex == -1)
|
||||||
|
{
|
||||||
|
// Different edge. Store for later.
|
||||||
|
EdgeMap<labelList>::iterator iter = extraEdgeFaces.find(e);
|
||||||
|
|
||||||
|
if (iter != extraEdgeFaces.end())
|
||||||
|
{
|
||||||
|
labelList& eFaces = iter();
|
||||||
|
label sz = eFaces.size();
|
||||||
|
eFaces.setSize(sz+1);
|
||||||
|
eFaces[sz] = triI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extraEdgeFaces.insert(e, labelList(1, triI));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (edgeFace1[edgeI] == -1)
|
else if (edgeFace1[edgeI] == -1)
|
||||||
{
|
{
|
||||||
edgeFace1[edgeI] = triI;
|
edgeFace1[edgeI] = triI;
|
||||||
@ -1029,9 +1062,10 @@ void Foam::isoSurface::calcAddressing
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//WarningIn("orientSurface(triSurface&)")
|
//WarningIn("orientSurface(triSurface&)")
|
||||||
// << "Edge " << edgeI << " with centre " << mergedCentres[edgeI]
|
// << "Edge " << edgeI << " with centre "
|
||||||
// << " used by more than two triangles: " << edgeFace0[edgeI]
|
// << mergedCentres[edgeI]
|
||||||
// << ", "
|
// << " used by more than two triangles: "
|
||||||
|
// << edgeFace0[edgeI] << ", "
|
||||||
// << edgeFace1[edgeI] << " and " << triI << endl;
|
// << edgeFace1[edgeI] << " and " << triI << endl;
|
||||||
Map<labelList>::iterator iter = edgeFacesRest.find(edgeI);
|
Map<labelList>::iterator iter = edgeFacesRest.find(edgeI);
|
||||||
|
|
||||||
@ -1048,6 +1082,59 @@ void Foam::isoSurface::calcAddressing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add extraEdgeFaces
|
||||||
|
edgeI = edgeFace0.size();
|
||||||
|
|
||||||
|
edgeFace0.setSize(edgeI + extraEdgeFaces.size());
|
||||||
|
edgeFace1.setSize(edgeI + extraEdgeFaces.size(), -1);
|
||||||
|
|
||||||
|
forAllConstIter(EdgeMap<labelList>, extraEdgeFaces, iter)
|
||||||
|
{
|
||||||
|
const labelList& eFaces = iter();
|
||||||
|
|
||||||
|
// The current edge will become edgeI. Replace all occurrences in
|
||||||
|
// faceEdges
|
||||||
|
forAll(eFaces, i)
|
||||||
|
{
|
||||||
|
label triI = eFaces[i];
|
||||||
|
const labelledTri& tri = surf[triI];
|
||||||
|
|
||||||
|
FixedList<label, 3>& fEdges = faceEdges[triI];
|
||||||
|
forAll(tri, fp)
|
||||||
|
{
|
||||||
|
edge e(tri[fp], tri[tri.fcIndex(fp)]);
|
||||||
|
|
||||||
|
if (e == iter.key())
|
||||||
|
{
|
||||||
|
fEdges[fp] = edgeI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add face to edgeFaces
|
||||||
|
|
||||||
|
edgeFace0[edgeI] = eFaces[0];
|
||||||
|
|
||||||
|
if (eFaces.size() >= 2)
|
||||||
|
{
|
||||||
|
edgeFace1[edgeI] = eFaces[1];
|
||||||
|
|
||||||
|
if (eFaces.size() > 2)
|
||||||
|
{
|
||||||
|
edgeFacesRest.insert
|
||||||
|
(
|
||||||
|
edgeI,
|
||||||
|
SubList<label>(eFaces, eFaces.size()-2, 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeI++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1097,6 +1184,24 @@ void Foam::isoSurface::walkOrientation
|
|||||||
|
|
||||||
// nbr points
|
// nbr points
|
||||||
label nbrFp = findIndex(nbrTri, p0);
|
label nbrFp = findIndex(nbrTri, p0);
|
||||||
|
|
||||||
|
if (nbrFp == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn("isoSurface::walkOrientation(..)")
|
||||||
|
<< "triI:" << triI
|
||||||
|
<< " tri:" << tri
|
||||||
|
<< " p0:" << p0
|
||||||
|
<< " p1:" << p1
|
||||||
|
<< " fEdges:" << fEdges
|
||||||
|
<< " edgeI:" << edgeI
|
||||||
|
<< " edgeFace0:" << edgeFace0[edgeI]
|
||||||
|
<< " edgeFace1:" << edgeFace1[edgeI]
|
||||||
|
<< " nbrI:" << nbrI
|
||||||
|
<< " nbrTri:" << nbrTri
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
label nbrP1 = nbrTri[nbrTri.rcIndex(nbrFp)];
|
label nbrP1 = nbrTri[nbrTri.rcIndex(nbrFp)];
|
||||||
|
|
||||||
bool sameOrientation = (p1 == nbrP1);
|
bool sameOrientation = (p1 == nbrP1);
|
||||||
@ -1352,8 +1457,17 @@ Foam::isoSurface::isoSurface
|
|||||||
iso_(iso),
|
iso_(iso),
|
||||||
mergeDistance_(mergeTol*mesh_.bounds().mag())
|
mergeDistance_(mergeTol*mesh_.bounds().mag())
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "isoSurface :" << nl
|
||||||
|
<< " isoField : " << cVals.name() << nl
|
||||||
|
<< " isoValue : " << iso << nl
|
||||||
|
<< " regularise : " << regularise << nl
|
||||||
|
<< " mergeTol : " << mergeTol << nl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||||
const labelList& own = mesh_.faceOwner();
|
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
forAll(patches, patchI)
|
forAll(patches, patchI)
|
||||||
@ -1442,24 +1556,6 @@ Foam::isoSurface::isoSurface
|
|||||||
snappedCc = -1;
|
snappedCc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine neighbouring snap status
|
|
||||||
labelList neiSnappedCc(mesh_.nFaces()-mesh_.nInternalFaces(), -1);
|
|
||||||
forAll(patches, patchI)
|
|
||||||
{
|
|
||||||
const polyPatch& pp = patches[patchI];
|
|
||||||
|
|
||||||
if (pp.coupled())
|
|
||||||
{
|
|
||||||
label faceI = pp.start();
|
|
||||||
forAll(pp, i)
|
|
||||||
{
|
|
||||||
neiSnappedCc[faceI-mesh_.nInternalFaces()] =
|
|
||||||
snappedCc[own[faceI]];
|
|
||||||
faceI++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
syncTools::swapBoundaryFaceList(mesh_, neiSnappedCc, false);
|
|
||||||
|
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
|
@ -299,7 +299,16 @@ void Foam::isoSurface::generateTriPoints
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
FatalErrorIn("isoSurface::generateTriPoints(..)")
|
FatalErrorIn("isoSurface::generateTriPoints(..)")
|
||||||
<< "Incorrect size." << abort(FatalError);
|
<< "Incorrect size." << endl
|
||||||
|
<< "mesh: nCells:" << mesh_.nCells()
|
||||||
|
<< " points:" << mesh_.nPoints() << endl
|
||||||
|
<< "cVals:" << cVals.size() << endl
|
||||||
|
<< "cCoords:" << cCoords.size() << endl
|
||||||
|
<< "snappedCc:" << snappedCc.size() << endl
|
||||||
|
<< "pVals:" << pVals.size() << endl
|
||||||
|
<< "pCoords:" << pCoords.size() << endl
|
||||||
|
<< "snappedPoint:" << snappedPoint.size() << endl
|
||||||
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine neighbouring snap status
|
// Determine neighbouring snap status
|
||||||
|
@ -29,7 +29,6 @@ License
|
|||||||
#include "volFields.H"
|
#include "volFields.H"
|
||||||
#include "volPointInterpolation.H"
|
#include "volPointInterpolation.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
#include "fvMesh.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -45,8 +44,6 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
{
|
{
|
||||||
const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
|
const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
|
||||||
|
|
||||||
word pointFldName = "volPointInterpolate(" + isoField_ + ')';
|
|
||||||
|
|
||||||
// Get volField
|
// Get volField
|
||||||
// ~~~~~~~~~~~~
|
// ~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -54,7 +51,7 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Info<< "sampledIsoSurface::getIsoField() : lookup "
|
Info<< "sampledIsoSurface::getIsoField() : lookup volField "
|
||||||
<< isoField_ << endl;
|
<< isoField_ << endl;
|
||||||
}
|
}
|
||||||
storedVolFieldPtr_.clear();
|
storedVolFieldPtr_.clear();
|
||||||
@ -79,7 +76,7 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Info<< "sampledIsoSurface::getIsoField() : reading "
|
Info<< "sampledIsoSurface::getIsoField() : reading volField "
|
||||||
<< isoField_ << " from time " << fvm.time().timeName()
|
<< isoField_ << " from time " << fvm.time().timeName()
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
@ -101,20 +98,6 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
volFieldPtr_ = storedVolFieldPtr_.operator->();
|
volFieldPtr_ = storedVolFieldPtr_.operator->();
|
||||||
|
|
||||||
// Interpolate to get pointField
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "sampledIsoSurface::getIsoField() : interpolating "
|
|
||||||
<< pointFldName << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
storedPointFieldPtr_.reset
|
|
||||||
(
|
|
||||||
volPointInterpolation::New(fvm).interpolate(*volFieldPtr_).ptr()
|
|
||||||
);
|
|
||||||
pointFieldPtr_ = storedPointFieldPtr_.operator->();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +106,15 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
// Get pointField
|
// Get pointField
|
||||||
// ~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
if (!subMeshPtr_.valid())
|
||||||
|
{
|
||||||
|
word pointFldName = "volPointInterpolate(" + isoField_ + ')';
|
||||||
|
|
||||||
if (fvm.foundObject<pointScalarField>(pointFldName))
|
if (fvm.foundObject<pointScalarField>(pointFldName))
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Info<< "sampledIsoSurface::getIsoField() : lookup "
|
Info<< "sampledIsoSurface::getIsoField() : lookup pointField "
|
||||||
<< pointFldName << endl;
|
<< pointFldName << endl;
|
||||||
}
|
}
|
||||||
pointFieldPtr_ = &fvm.lookupObject<pointScalarField>(pointFldName);
|
pointFieldPtr_ = &fvm.lookupObject<pointScalarField>(pointFldName);
|
||||||
@ -138,9 +125,9 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Info<< "sampledIsoSurface::getIsoField() : checking interpolate "
|
Info<< "sampledIsoSurface::getIsoField() : checking pointField "
|
||||||
<< isoField_ << " for same time " << fvm.time().timeName()
|
<< pointFldName << " for same time "
|
||||||
<< endl;
|
<< fvm.time().timeName() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if
|
if
|
||||||
@ -151,14 +138,17 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Info<< "sampledIsoSurface::getIsoField() : interpolating "
|
Info<< "sampledIsoSurface::getIsoField() :"
|
||||||
<< pointFldName << endl;
|
<< " interpolating volField " << volFieldPtr_->name()
|
||||||
|
<< " to get pointField " << pointFldName << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
storedPointFieldPtr_.reset
|
storedPointFieldPtr_.reset
|
||||||
(
|
(
|
||||||
volPointInterpolation::New(fvm).interpolate(*volFieldPtr_).ptr()
|
volPointInterpolation::New(fvm)
|
||||||
|
.interpolate(*volFieldPtr_).ptr()
|
||||||
);
|
);
|
||||||
|
storedPointFieldPtr_->checkOut();
|
||||||
pointFieldPtr_ = storedPointFieldPtr_.operator->();
|
pointFieldPtr_ = storedPointFieldPtr_.operator->();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,6 +163,147 @@ void Foam::sampledIsoSurface::getIsoFields() const
|
|||||||
<< " min:" << gMin(pointFieldPtr_->internalField())
|
<< " min:" << gMin(pointFieldPtr_->internalField())
|
||||||
<< " max:" << gMax(pointFieldPtr_->internalField()) << endl;
|
<< " max:" << gMax(pointFieldPtr_->internalField()) << endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get subMesh variants
|
||||||
|
const fvMesh& subFvm = subMeshPtr_().subMesh();
|
||||||
|
|
||||||
|
// Either lookup on the submesh or subset the whole-mesh volField
|
||||||
|
|
||||||
|
if (subFvm.foundObject<volScalarField>(isoField_))
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() :"
|
||||||
|
<< " submesh lookup volField "
|
||||||
|
<< isoField_ << endl;
|
||||||
|
}
|
||||||
|
storedVolSubFieldPtr_.clear();
|
||||||
|
volSubFieldPtr_ = &subFvm.lookupObject<volScalarField>(isoField_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() : subsetting volField "
|
||||||
|
<< isoField_ << endl;
|
||||||
|
}
|
||||||
|
storedVolSubFieldPtr_.reset
|
||||||
|
(
|
||||||
|
subMeshPtr_().interpolate
|
||||||
|
(
|
||||||
|
*volFieldPtr_
|
||||||
|
).ptr()
|
||||||
|
);
|
||||||
|
storedVolSubFieldPtr_->checkOut();
|
||||||
|
volSubFieldPtr_ = storedVolSubFieldPtr_.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Pointfield on submesh
|
||||||
|
|
||||||
|
word pointFldName =
|
||||||
|
"volPointInterpolate("
|
||||||
|
+ volSubFieldPtr_->name()
|
||||||
|
+ ')';
|
||||||
|
|
||||||
|
if (subFvm.foundObject<pointScalarField>(pointFldName))
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() :"
|
||||||
|
<< " submesh lookup pointField " << pointFldName << endl;
|
||||||
|
}
|
||||||
|
storedPointSubFieldPtr_.clear();
|
||||||
|
pointSubFieldPtr_ = &subFvm.lookupObject<pointScalarField>
|
||||||
|
(
|
||||||
|
pointFldName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() :"
|
||||||
|
<< " interpolating submesh volField "
|
||||||
|
<< volSubFieldPtr_->name()
|
||||||
|
<< " to get submesh pointField " << pointFldName << endl;
|
||||||
|
}
|
||||||
|
storedPointSubFieldPtr_.reset
|
||||||
|
(
|
||||||
|
volPointInterpolation::New
|
||||||
|
(
|
||||||
|
subFvm
|
||||||
|
).interpolate(*volSubFieldPtr_).ptr()
|
||||||
|
);
|
||||||
|
storedPointSubFieldPtr_->checkOut();
|
||||||
|
pointSubFieldPtr_ = storedPointSubFieldPtr_.operator->();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() : volSubField "
|
||||||
|
<< volSubFieldPtr_->name()
|
||||||
|
<< " min:" << min(*volSubFieldPtr_).value()
|
||||||
|
<< " max:" << max(*volSubFieldPtr_).value() << endl;
|
||||||
|
Info<< "sampledIsoSurface::getIsoField() : pointSubField "
|
||||||
|
<< pointSubFieldPtr_->name()
|
||||||
|
<< " min:" << gMin(pointSubFieldPtr_->internalField())
|
||||||
|
<< " max:" << gMax(pointSubFieldPtr_->internalField()) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::volScalarField> Foam::sampledIsoSurface::average
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const pointScalarField& pfld
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
tmp<volScalarField> tcellAvg
|
||||||
|
(
|
||||||
|
new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"cellAvg",
|
||||||
|
mesh.time().timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimless, scalar(0.0))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
volScalarField& cellAvg = tcellAvg();
|
||||||
|
|
||||||
|
labelField nPointCells(mesh.nCells(), 0);
|
||||||
|
{
|
||||||
|
for (label pointI = 0; pointI < mesh.nPoints(); pointI++)
|
||||||
|
{
|
||||||
|
const labelList& pCells = mesh.pointCells(pointI);
|
||||||
|
|
||||||
|
forAll(pCells, i)
|
||||||
|
{
|
||||||
|
label cellI = pCells[i];
|
||||||
|
|
||||||
|
cellAvg[cellI] += pfld[pointI];
|
||||||
|
nPointCells[cellI]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forAll(cellAvg, cellI)
|
||||||
|
{
|
||||||
|
cellAvg[cellI] /= nPointCells[cellI];
|
||||||
|
}
|
||||||
|
// Give value to calculatedFvPatchFields
|
||||||
|
cellAvg.correctBoundaryConditions();
|
||||||
|
|
||||||
|
return tcellAvg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -186,6 +317,33 @@ bool Foam::sampledIsoSurface::updateGeometry() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get any subMesh
|
||||||
|
if (zoneID_.index() != -1 && !subMeshPtr_.valid())
|
||||||
|
{
|
||||||
|
const polyBoundaryMesh& patches = mesh().boundaryMesh();
|
||||||
|
|
||||||
|
// Patch to put exposed internal faces into
|
||||||
|
label exposedPatchI = patches.findPatchID(exposedPatchName_);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "Allocating subset of size "
|
||||||
|
<< mesh().cellZones()[zoneID_.index()].size()
|
||||||
|
<< " with exposed faces into patch "
|
||||||
|
<< patches[exposedPatchI].name() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
subMeshPtr_.reset
|
||||||
|
(
|
||||||
|
new fvMeshSubset(static_cast<const fvMesh&>(mesh()))
|
||||||
|
);
|
||||||
|
subMeshPtr_().setLargeCellSubset
|
||||||
|
(
|
||||||
|
labelHashSet(mesh().cellZones()[zoneID_.index()]),
|
||||||
|
exposedPatchI
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
prevTimeIndex_ = fvm.time().timeIndex();
|
prevTimeIndex_ = fvm.time().timeIndex();
|
||||||
getIsoFields();
|
getIsoFields();
|
||||||
@ -196,57 +354,53 @@ bool Foam::sampledIsoSurface::updateGeometry() const
|
|||||||
|
|
||||||
if (average_)
|
if (average_)
|
||||||
{
|
{
|
||||||
//- From point field and interpolated cell.
|
if (subMeshPtr_.valid())
|
||||||
volScalarField cellAvg
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"cellAvg",
|
|
||||||
fvm.time().timeName(),
|
|
||||||
fvm.time(),
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
fvm,
|
|
||||||
dimensionedScalar("zero", dimless, scalar(0.0))
|
|
||||||
);
|
|
||||||
labelField nPointCells(fvm.nCells(), 0);
|
|
||||||
{
|
{
|
||||||
for (label pointI = 0; pointI < fvm.nPoints(); pointI++)
|
|
||||||
{
|
|
||||||
const labelList& pCells = fvm.pointCells(pointI);
|
|
||||||
|
|
||||||
forAll(pCells, i)
|
|
||||||
{
|
|
||||||
label cellI = pCells[i];
|
|
||||||
|
|
||||||
cellAvg[cellI] += (*pointFieldPtr_)[pointI];
|
|
||||||
nPointCells[cellI]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
forAll(cellAvg, cellI)
|
|
||||||
{
|
|
||||||
cellAvg[cellI] /= nPointCells[cellI];
|
|
||||||
}
|
|
||||||
// Give value to calculatedFvPatchFields
|
|
||||||
cellAvg.correctBoundaryConditions();
|
|
||||||
|
|
||||||
surfPtr_.reset
|
surfPtr_.reset
|
||||||
(
|
(
|
||||||
new isoSurface
|
new isoSurface
|
||||||
(
|
(
|
||||||
cellAvg,
|
average(subMeshPtr_().subMesh(), *pointSubFieldPtr_),
|
||||||
*pointFieldPtr_,
|
*pointSubFieldPtr_,
|
||||||
isoVal_,
|
isoVal_,
|
||||||
regularise_
|
regularise_,
|
||||||
|
mergeTol_
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
surfPtr_.reset
|
||||||
|
(
|
||||||
|
new isoSurface
|
||||||
|
(
|
||||||
|
average(fvm, *pointFieldPtr_),
|
||||||
|
*pointFieldPtr_,
|
||||||
|
isoVal_,
|
||||||
|
regularise_,
|
||||||
|
mergeTol_
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (subMeshPtr_.valid())
|
||||||
|
{
|
||||||
|
surfPtr_.reset
|
||||||
|
(
|
||||||
|
new isoSurface
|
||||||
|
(
|
||||||
|
*volSubFieldPtr_,
|
||||||
|
*pointSubFieldPtr_,
|
||||||
|
isoVal_,
|
||||||
|
regularise_,
|
||||||
|
mergeTol_
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//- Direct from cell field and point field.
|
|
||||||
surfPtr_.reset
|
surfPtr_.reset
|
||||||
(
|
(
|
||||||
new isoSurface
|
new isoSurface
|
||||||
@ -254,10 +408,12 @@ bool Foam::sampledIsoSurface::updateGeometry() const
|
|||||||
*volFieldPtr_,
|
*volFieldPtr_,
|
||||||
*pointFieldPtr_,
|
*pointFieldPtr_,
|
||||||
isoVal_,
|
isoVal_,
|
||||||
regularise_
|
regularise_,
|
||||||
|
mergeTol_
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -267,8 +423,13 @@ bool Foam::sampledIsoSurface::updateGeometry() const
|
|||||||
<< " regularise : " << regularise_ << nl
|
<< " regularise : " << regularise_ << nl
|
||||||
<< " average : " << average_ << nl
|
<< " average : " << average_ << nl
|
||||||
<< " isoField : " << isoField_ << nl
|
<< " isoField : " << isoField_ << nl
|
||||||
<< " isoValue : " << isoVal_ << nl
|
<< " isoValue : " << isoVal_ << nl;
|
||||||
<< " points : " << points().size() << nl
|
if (subMeshPtr_.valid())
|
||||||
|
{
|
||||||
|
Pout<< " zone size : " << subMeshPtr_().subMesh().nCells()
|
||||||
|
<< nl;
|
||||||
|
}
|
||||||
|
Pout<< " points : " << points().size() << nl
|
||||||
<< " tris : " << surface().size() << nl
|
<< " tris : " << surface().size() << nl
|
||||||
<< " cut cells : " << surface().meshCells().size()
|
<< " cut cells : " << surface().meshCells().size()
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -290,9 +451,11 @@ Foam::sampledIsoSurface::sampledIsoSurface
|
|||||||
sampledSurface(name, mesh, dict),
|
sampledSurface(name, mesh, dict),
|
||||||
isoField_(dict.lookup("isoField")),
|
isoField_(dict.lookup("isoField")),
|
||||||
isoVal_(readScalar(dict.lookup("isoValue"))),
|
isoVal_(readScalar(dict.lookup("isoValue"))),
|
||||||
|
mergeTol_(dict.lookupOrDefault("mergeTol", 1E-6)),
|
||||||
regularise_(dict.lookupOrDefault("regularise", true)),
|
regularise_(dict.lookupOrDefault("regularise", true)),
|
||||||
average_(dict.lookupOrDefault("average", false)),
|
average_(dict.lookupOrDefault("average", false)),
|
||||||
zoneName_(word::null),
|
zoneID_(dict.lookupOrDefault("zone", word::null), mesh.cellZones()),
|
||||||
|
exposedPatchName_(word::null),
|
||||||
surfPtr_(NULL),
|
surfPtr_(NULL),
|
||||||
facesPtr_(NULL),
|
facesPtr_(NULL),
|
||||||
prevTimeIndex_(-1),
|
prevTimeIndex_(-1),
|
||||||
@ -311,16 +474,29 @@ Foam::sampledIsoSurface::sampledIsoSurface
|
|||||||
<< " span across cells." << exit(FatalError);
|
<< " span across cells." << exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dict.readIfPresent("zone", zoneName_);
|
if (zoneID_.index() != -1)
|
||||||
//
|
{
|
||||||
// if (debug && zoneName_.size())
|
dict.lookup("exposedPatchName") >> exposedPatchName_;
|
||||||
// {
|
|
||||||
// if (mesh.cellZones().findZoneID(zoneName_) < 0)
|
if (mesh.boundaryMesh().findPatchID(exposedPatchName_) == -1)
|
||||||
// {
|
{
|
||||||
// Info<< "cellZone \"" << zoneName_
|
FatalErrorIn
|
||||||
// << "\" not found - using entire mesh" << endl;
|
(
|
||||||
// }
|
"sampledIsoSurface::sampledIsoSurface"
|
||||||
// }
|
"(const word&, const polyMesh&, const dictionary&)"
|
||||||
|
) << "Cannot find patch " << exposedPatchName_
|
||||||
|
<< " in which to put exposed faces." << endl
|
||||||
|
<< "Valid patches are " << mesh.boundaryMesh().names()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug && zoneID_.index() != -1)
|
||||||
|
{
|
||||||
|
Info<< "Restricting to cellZone " << zoneID_.name()
|
||||||
|
<< " with exposed internal faces into patch "
|
||||||
|
<< exposedPatchName_ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -344,6 +520,7 @@ bool Foam::sampledIsoSurface::expire()
|
|||||||
{
|
{
|
||||||
surfPtr_.clear();
|
surfPtr_.clear();
|
||||||
facesPtr_.clear();
|
facesPtr_.clear();
|
||||||
|
subMeshPtr_.clear();
|
||||||
|
|
||||||
// already marked as expired
|
// already marked as expired
|
||||||
if (prevTimeIndex_ == -1)
|
if (prevTimeIndex_ == -1)
|
||||||
@ -465,8 +642,8 @@ Foam::sampledIsoSurface::interpolate
|
|||||||
void Foam::sampledIsoSurface::print(Ostream& os) const
|
void Foam::sampledIsoSurface::print(Ostream& os) const
|
||||||
{
|
{
|
||||||
os << "sampledIsoSurface: " << name() << " :"
|
os << "sampledIsoSurface: " << name() << " :"
|
||||||
<< " field:" << isoField_
|
<< " field :" << isoField_
|
||||||
<< " value:" << isoVal_;
|
<< " value :" << isoVal_;
|
||||||
//<< " faces:" << faces().size() // note: possibly no geom yet
|
//<< " faces:" << faces().size() // note: possibly no geom yet
|
||||||
//<< " points:" << points().size();
|
//<< " points:" << points().size();
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,10 @@ SourceFiles
|
|||||||
#ifndef sampledIsoSurface_H
|
#ifndef sampledIsoSurface_H
|
||||||
#define sampledIsoSurface_H
|
#define sampledIsoSurface_H
|
||||||
|
|
||||||
#include "sampledSurface.H"
|
|
||||||
#include "isoSurface.H"
|
#include "isoSurface.H"
|
||||||
|
#include "sampledSurface.H"
|
||||||
|
#include "ZoneIDs.H"
|
||||||
|
#include "fvMeshSubset.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -62,14 +64,20 @@ class sampledIsoSurface
|
|||||||
//- iso value
|
//- iso value
|
||||||
const scalar isoVal_;
|
const scalar isoVal_;
|
||||||
|
|
||||||
|
//- Merge tolerance
|
||||||
|
const scalar mergeTol_;
|
||||||
|
|
||||||
//- Whether to coarse
|
//- Whether to coarse
|
||||||
const Switch regularise_;
|
const Switch regularise_;
|
||||||
|
|
||||||
//- Whether to recalculate cell values as average of point values
|
//- Whether to recalculate cell values as average of point values
|
||||||
const Switch average_;
|
const Switch average_;
|
||||||
|
|
||||||
//- zone name (if restricted to zones)
|
//- zone name/index (if restricted to zones)
|
||||||
word zoneName_;
|
mutable cellZoneID zoneID_;
|
||||||
|
|
||||||
|
//- for zones: patch to put exposed faces into
|
||||||
|
mutable word exposedPatchName_;
|
||||||
|
|
||||||
mutable autoPtr<isoSurface> surfPtr_;
|
mutable autoPtr<isoSurface> surfPtr_;
|
||||||
|
|
||||||
@ -90,6 +98,19 @@ class sampledIsoSurface
|
|||||||
mutable autoPtr<pointScalarField> storedPointFieldPtr_;
|
mutable autoPtr<pointScalarField> storedPointFieldPtr_;
|
||||||
mutable const pointScalarField* pointFieldPtr_;
|
mutable const pointScalarField* pointFieldPtr_;
|
||||||
|
|
||||||
|
// And on subsetted mesh
|
||||||
|
|
||||||
|
//- Cached submesh
|
||||||
|
mutable autoPtr<fvMeshSubset> subMeshPtr_;
|
||||||
|
|
||||||
|
//- Cached volfield
|
||||||
|
mutable autoPtr<volScalarField> storedVolSubFieldPtr_;
|
||||||
|
mutable const volScalarField* volSubFieldPtr_;
|
||||||
|
|
||||||
|
//- Cached pointfield
|
||||||
|
mutable autoPtr<pointScalarField> storedPointSubFieldPtr_;
|
||||||
|
mutable const pointScalarField* pointSubFieldPtr_;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
@ -97,6 +118,12 @@ class sampledIsoSurface
|
|||||||
//- Get fields needed to recreate iso surface.
|
//- Get fields needed to recreate iso surface.
|
||||||
void getIsoFields() const;
|
void getIsoFields() const;
|
||||||
|
|
||||||
|
tmp<volScalarField> average
|
||||||
|
(
|
||||||
|
const fvMesh&,
|
||||||
|
const pointScalarField&
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Create iso surface (if time has changed)
|
//- Create iso surface (if time has changed)
|
||||||
// Do nothing (and return false) if no update was needed
|
// Do nothing (and return false) if no update was needed
|
||||||
bool updateGeometry() const;
|
bool updateGeometry() const;
|
||||||
|
@ -52,34 +52,47 @@ Foam::sampledIsoSurface::interpolateField
|
|||||||
const interpolation<Type>& interpolator
|
const interpolation<Type>& interpolator
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const fvMesh& fvm = static_cast<const fvMesh&>(mesh());
|
|
||||||
|
|
||||||
// Get fields to sample. Assume volPointInterpolation!
|
// Get fields to sample. Assume volPointInterpolation!
|
||||||
const GeometricField<Type, fvPatchField, volMesh>& volFld =
|
const GeometricField<Type, fvPatchField, volMesh>& volFld =
|
||||||
interpolator.psi();
|
interpolator.psi();
|
||||||
|
|
||||||
tmp<GeometricField<Type, pointPatchField, pointMesh> > tpointFld
|
|
||||||
(
|
|
||||||
volPointInterpolation::New(fvm).interpolate(volFld)
|
|
||||||
);
|
|
||||||
|
|
||||||
const GeometricField<Type, pointPatchField, pointMesh>& pointFld =
|
|
||||||
tpointFld();
|
|
||||||
|
|
||||||
// Get pointers to sampling field (both original and interpolated one)
|
|
||||||
getIsoFields();
|
|
||||||
|
|
||||||
// Recreate geometry if time has changed
|
// Recreate geometry if time has changed
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
|
||||||
|
if (subMeshPtr_.valid())
|
||||||
|
{
|
||||||
|
tmp<GeometricField<Type, fvPatchField, volMesh> > tvolSubFld =
|
||||||
|
subMeshPtr_().interpolate(volFld);
|
||||||
|
|
||||||
|
const GeometricField<Type, fvPatchField, volMesh>& volSubFld =
|
||||||
|
tvolSubFld();
|
||||||
|
|
||||||
|
tmp<GeometricField<Type, pointPatchField, pointMesh> > tpointSubFld =
|
||||||
|
volPointInterpolation::New(volSubFld.mesh()).interpolate(volSubFld);
|
||||||
|
|
||||||
|
// Sample.
|
||||||
|
return surface().interpolate
|
||||||
|
(
|
||||||
|
*volSubFieldPtr_,
|
||||||
|
*pointSubFieldPtr_,
|
||||||
|
volSubFld,
|
||||||
|
tpointSubFld()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp<GeometricField<Type, pointPatchField, pointMesh> > tpointFld =
|
||||||
|
volPointInterpolation::New(volFld.mesh()).interpolate(volFld);
|
||||||
|
|
||||||
// Sample.
|
// Sample.
|
||||||
return surface().interpolate
|
return surface().interpolate
|
||||||
(
|
(
|
||||||
*volFieldPtr_,
|
*volFieldPtr_,
|
||||||
*pointFieldPtr_,
|
*pointFieldPtr_,
|
||||||
volFld,
|
volFld,
|
||||||
pointFld
|
tpointFld()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user