46 bool Foam::isoSurface::noTransform(
const tensor& tt)
const 49 (
mag(tt.xx()-1) < mergeDistance_)
50 && (
mag(tt.yy()-1) < mergeDistance_)
51 && (
mag(tt.zz()-1) < mergeDistance_)
52 && (
mag(tt.xy()) < mergeDistance_)
53 && (
mag(tt.xz()) < mergeDistance_)
54 && (
mag(tt.yx()) < mergeDistance_)
55 && (
mag(tt.yz()) < mergeDistance_)
56 && (
mag(tt.zx()) < mergeDistance_)
57 && (
mag(tt.zy()) < mergeDistance_);
61 bool Foam::isoSurface::collocatedPatch(
const polyPatch& pp)
63 const coupledPolyPatch& cpp = refCast<const coupledPolyPatch>(pp);
64 return cpp.parallel() && !cpp.separated();
70 const coupledPolyPatch& pp
74 PackedBoolList collocated(pp.size());
76 if (isA<processorPolyPatch>(pp))
78 if (collocatedPatch(pp))
86 else if (isA<cyclicPolyPatch>(pp))
88 if (collocatedPatch(pp))
99 <<
"Unhandled coupledPolyPatch type " << pp.type()
106 void Foam::isoSurface::syncUnseparatedPoints
109 const point& nullValue
114 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
123 isA<processorPolyPatch>(patches[patchi])
124 && patches[patchi].
nPoints() > 0
125 && collocatedPatch(patches[patchi])
128 const processorPolyPatch& pp =
129 refCast<const processorPolyPatch>(patches[
patchi]);
131 const labelList& meshPts = pp.meshPoints();
132 const labelList& nbrPts = pp.neighbPoints();
138 label nbrPointi = nbrPts[pointi];
139 patchInfo[nbrPointi] = pointValues[meshPts[pointi]];
157 isA<processorPolyPatch>(patches[patchi])
158 && patches[patchi].
nPoints() > 0
159 && collocatedPatch(patches[patchi])
162 const processorPolyPatch& pp =
163 refCast<const processorPolyPatch>(patches[
patchi]);
174 fromNbr >> nbrPatchInfo;
177 const labelList& meshPts = pp.meshPoints();
181 label meshPointi = meshPts[pointi];
184 pointValues[meshPointi],
195 if (isA<cyclicPolyPatch>(patches[patchi]))
197 const cyclicPolyPatch& cycPatch =
198 refCast<const cyclicPolyPatch>(patches[
patchi]);
200 if (cycPatch.owner() && collocatedPatch(cycPatch))
204 const edgeList& coupledPoints = cycPatch.coupledPoints();
205 const labelList& meshPts = cycPatch.meshPoints();
206 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
207 const labelList& nbrMeshPoints = nbrPatch.meshPoints();
214 const edge&
e = coupledPoints[i];
215 half0Values[i] = pointValues[meshPts[e[0]]];
216 half1Values[i] = pointValues[nbrMeshPoints[e[1]]];
221 const edge&
e = coupledPoints[i];
222 label p0 = meshPts[e[0]];
223 label p1 = nbrMeshPoints[e[1]];
225 minEqOp<point>()(pointValues[p0], half1Values[i]);
226 minEqOp<point>()(pointValues[p1], half0Values[i]);
233 const globalMeshData& pd = mesh_.globalData();
235 if (pd.nGlobalPoints() > 0)
238 pointField sharedPts(pd.nGlobalPoints(), nullValue);
240 forAll(pd.sharedPointLabels(), i)
242 label meshPointi = pd.sharedPointLabels()[i];
244 sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointi];
253 forAll(pd.sharedPointLabels(), i)
255 label meshPointi = pd.sharedPointLabels()[i];
256 pointValues[meshPointi] = sharedPts[pd.sharedPointAddr()[i]];
262 Foam::scalar Foam::isoSurface::isoFraction
281 bool Foam::isoSurface::isEdgeOfFaceCut
291 bool fpLower = (pVals[f[fp]] < iso_);
294 (fpLower != ownLower)
295 || (fpLower != neiLower)
296 || (fpLower != (pVals[f[f.fcIndex(fp)]] < iso_))
306 void Foam::isoSurface::getNeighbour
317 const labelList& own = mesh_.faceOwner();
318 const labelList& nei = mesh_.faceNeighbour();
320 if (mesh_.isInternalFace(facei))
322 label nbr = (own[facei] == celli ? nei[facei] : own[facei]);
323 nbrValue = cVals[nbr];
324 nbrPoint = meshC[nbr];
328 label bFacei = facei-mesh_.nInternalFaces();
329 label patchi = boundaryRegion[bFacei];
330 const polyPatch& pp = mesh_.boundaryMesh()[
patchi];
331 label patchFacei = facei-pp.start();
333 nbrValue = cVals.boundaryField()[
patchi][patchFacei];
334 nbrPoint = meshC.boundaryField()[
patchi][patchFacei];
339 void Foam::isoSurface::calcCutTypes
347 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
348 const labelList& own = mesh_.faceOwner();
349 const labelList& nei = mesh_.faceNeighbour();
351 faceCutType_.
setSize(mesh_.nFaces());
352 faceCutType_ = NOTCUT;
354 for (
label facei = 0; facei < mesh_.nInternalFaces(); facei++)
357 bool ownLower = (cVals[own[facei]] < iso_);
372 bool neiLower = (nbrValue < iso_);
374 if (ownLower != neiLower)
376 faceCutType_[facei] = CUT;
382 const face f = mesh_.faces()[facei];
384 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
386 faceCutType_[facei] = CUT;
393 const polyPatch& pp = patches[
patchi];
395 label facei = pp.start();
399 bool ownLower = (cVals[own[facei]] < iso_);
414 bool neiLower = (nbrValue < iso_);
416 if (ownLower != neiLower)
418 faceCutType_[facei] = CUT;
423 const face f = mesh_.faces()[facei];
425 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
427 faceCutType_[facei] = CUT;
438 cellCutType_.setSize(mesh_.nCells());
439 cellCutType_ = NOTCUT;
441 for (
label facei = 0; facei < mesh_.nInternalFaces(); facei++)
443 if (faceCutType_[facei] != NOTCUT)
445 if (cellCutType_[own[facei]] == NOTCUT)
447 cellCutType_[own[facei]] = CUT;
450 if (cellCutType_[nei[facei]] == NOTCUT)
452 cellCutType_[nei[facei]] = CUT;
457 for (
label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
459 if (faceCutType_[facei] != NOTCUT)
461 if (cellCutType_[own[facei]] == NOTCUT)
463 cellCutType_[own[facei]] = CUT;
471 Pout<<
"isoSurface : detected " << nCutCells_
472 <<
" candidate cut cells (out of " << mesh_.nCells()
479 Foam::point Foam::isoSurface::calcCentre(
const triSurface& s)
485 sum += s[i].centre(s.points());
491 void Foam::isoSurface::calcSnappedCc
498 DynamicList<point>& snappedPoints,
505 snappedCc.
setSize(mesh_.nCells());
509 DynamicList<point, 64> localTriPoints(64);
511 forAll(mesh_.cells(), celli)
513 if (cellCutType_[celli] == CUT)
515 scalar cVal = cVals[celli];
517 const cell& cFaces = mesh_.cells()[celli];
519 localTriPoints.clear();
528 label facei = cFaces[cFacei];
544 FixedList<scalar, 3>
s;
545 FixedList<point, 3> pt;
548 s[2] = isoFraction(cVal, nbrValue);
549 pt[2] = (1.0-s[2])*cc[celli] + s[2]*nbrPoint;
551 const face& f = mesh_.faces()[cFaces[cFacei]];
557 s[0] = isoFraction(cVal, pVals[p0]);
558 pt[0] = (1.0-s[0])*cc[celli] + s[0]*pts[p0];
561 label p1 = f[f.fcIndex(fp)];
562 s[1] = isoFraction(cVal, pVals[p1]);
563 pt[1] = (1.0-s[1])*cc[celli] + s[1]*pts[p1];
567 (s[0] >= 0.0 && s[0] <= 0.5)
568 && (s[1] >= 0.0 && s[1] <= 0.5)
569 && (s[2] >= 0.0 && s[2] <= 0.5)
572 localTriPoints.append(pt[0]);
573 localTriPoints.append(pt[1]);
574 localTriPoints.append(pt[2]);
581 if (s[i] >= 0.0 && s[i] <= 0.5)
583 otherPointSum += pt[i];
591 if (localTriPoints.size() == 0)
597 snappedCc[celli] = snappedPoints.size();
598 snappedPoints.append(otherPointSum/nOther);
605 else if (localTriPoints.size() == 3)
610 snappedCc[celli] = snappedPoints.size();
611 snappedPoints.append(
sum(points)/points.size());
636 label nZones = surf.markZones
644 snappedCc[celli] = snappedPoints.size();
645 snappedPoints.append(calcCentre(surf));
656 void Foam::isoSurface::calcSnappedPoint
658 const PackedBoolList& isBoundaryPoint,
664 DynamicList<point>& snappedPoints,
675 DynamicList<point, 64> localTriPoints(100);
677 forAll(mesh_.pointFaces(), pointi)
679 if (isBoundaryPoint.get(pointi) == 1)
684 const labelList& pFaces = mesh_.pointFaces()[pointi];
690 label facei = pFaces[i];
692 if (faceCutType_[facei] == CUT)
705 localTriPoints.clear();
714 label facei = pFaces[pFacei];
715 const face& f = mesh_.faces()[facei];
716 label own = mesh_.faceOwner()[facei];
733 FixedList<scalar, 4>
s;
734 FixedList<point, 4> pt;
737 s[0] = isoFraction(pVals[pointi], cVals[own]);
738 pt[0] = (1.0-s[0])*pts[pointi] + s[0]*cc[own];
740 s[1] = isoFraction(pVals[pointi], nbrValue);
741 pt[1] = (1.0-s[1])*pts[pointi] + s[1]*nbrPoint;
743 label nextPointi = f[f.fcIndex(fp)];
744 s[2] = isoFraction(pVals[pointi], pVals[nextPointi]);
745 pt[2] = (1.0-s[2])*pts[pointi] + s[2]*pts[nextPointi];
747 label prevPointi = f[f.rcIndex(fp)];
748 s[3] = isoFraction(pVals[pointi], pVals[prevPointi]);
749 pt[3] = (1.0-s[3])*pts[pointi] + s[3]*pts[prevPointi];
753 (s[0] >= 0.0 && s[0] <= 0.5)
754 && (s[1] >= 0.0 && s[1] <= 0.5)
755 && (s[2] >= 0.0 && s[2] <= 0.5)
758 localTriPoints.append(pt[0]);
759 localTriPoints.append(pt[1]);
760 localTriPoints.append(pt[2]);
764 (s[0] >= 0.0 && s[0] <= 0.5)
765 && (s[1] >= 0.0 && s[1] <= 0.5)
766 && (s[3] >= 0.0 && s[3] <= 0.5)
769 localTriPoints.append(pt[3]);
770 localTriPoints.append(pt[0]);
771 localTriPoints.append(pt[1]);
777 if (s[i] >= 0.0 && s[i] <= 0.5)
779 otherPointSum += pt[i];
785 if (localTriPoints.size() == 0)
791 collapsedPoint[pointi] = otherPointSum/nOther;
794 else if (localTriPoints.size() == 3)
799 collapsedPoint[pointi] =
sum(points)/points.size();
820 label nZones = surf.markZones
828 collapsedPoint[pointi] = calcCentre(surf);
835 syncUnseparatedPoints(collapsedPoint,
point::max);
838 snappedPoint.setSize(mesh_.nPoints());
841 forAll(collapsedPoint, pointi)
845 snappedPoint[pointi] = snappedPoints.size();
846 snappedPoints.append(collapsedPoint[pointi]);
854 const bool checkDuplicates,
855 const List<point>& triPoints,
860 label nTris = triPoints.size()/3;
862 if ((triPoints.size() % 3) != 0)
865 <<
"Problem: number of points " << triPoints.size()
896 <<
"Merged points contain duplicates" 897 <<
" when merging with distance " << mergeDistance_ <<
endl 898 <<
"merged:" << newPoints.size() <<
" re-merged:" 899 << newNewPoints.size()
905 List<labelledTri> tris;
907 DynamicList<labelledTri> dynTris(nTris);
909 DynamicList<label> newToOldTri(nTris);
911 for (
label oldTriI = 0; oldTriI < nTris; oldTriI++)
915 triPointReverseMap[rawPointi],
916 triPointReverseMap[rawPointi+1],
917 triPointReverseMap[rawPointi+2],
922 if ((tri[0] != tri[1]) && (tri[0] != tri[2]) && (tri[1] != tri[2]))
924 newToOldTri.append(oldTriI);
929 triMap.transfer(newToOldTri);
930 tris.transfer(dynTris);
945 DynamicList<label> newToOldTri(tris.size());
949 const labelledTri& tri = tris[triI];
950 const labelList& pFaces = pointFaces[tri[0]];
958 label nbrTriI = pFaces[i];
960 if (nbrTriI > triI && (tris[nbrTriI] == tri))
973 label newTriI = newToOldTri.size();
974 newToOldTri.append(triMap[triI]);
975 tris[newTriI] = tris[triI];
979 triMap.transfer(newToOldTri);
980 tris.setSize(triMap.size());
984 Pout<<
"isoSurface : merged from " << nTris
985 <<
" down to " << tris.size() <<
" unique triangles." <<
endl;
995 const labelledTri& f = surf[facei];
996 const labelList& fFaces = surf.faceFaces()[facei];
1000 label nbrFacei = fFaces[i];
1002 if (nbrFacei <= facei)
1008 const labelledTri& nbrF = surf[nbrFacei];
1014 <<
" triangle " << facei <<
" vertices " << f
1015 <<
" fc:" << f.centre(surf.points())
1016 <<
" has the same vertices as triangle " << nbrFacei
1017 <<
" vertices " << nbrF
1018 <<
" fc:" << nbrF.centre(surf.points())
1030 bool Foam::isoSurface::validTri(
const triSurface& surf,
const label facei)
1034 const labelledTri& f = surf[facei];
1038 (f[0] < 0) || (f[0] >= surf.points().size())
1039 || (f[1] < 0) || (f[1] >= surf.points().size())
1040 || (f[2] < 0) || (f[2] >= surf.points().size())
1044 <<
"triangle " << facei <<
" vertices " << f
1045 <<
" uses point indices outside point range 0.." 1046 << surf.points().size()-1 <<
endl;
1051 if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
1054 <<
"triangle " << facei
1055 <<
" uses non-unique vertices " << f
1062 const labelList& fFaces = surf.faceFaces()[facei];
1068 label nbrFacei = fFaces[i];
1070 if (nbrFacei <= facei)
1076 const labelledTri& nbrF = surf[nbrFacei];
1080 ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2]))
1081 && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2]))
1082 && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2]))
1086 <<
"triangle " << facei <<
" vertices " << f
1087 <<
" fc:" << f.centre(surf.points())
1088 <<
" has the same vertices as triangle " << nbrFacei
1089 <<
" vertices " << nbrF
1090 <<
" fc:" << nbrF.centre(surf.points())
1102 const triSurface& s,
1110 createWithValues<boolList>
1119 newToOldPoints.setSize(s.points().size());
1120 oldToNewPoints.setSize(s.points().size());
1121 oldToNewPoints = -1;
1125 forAll(include, oldFacei)
1127 if (include[oldFacei])
1130 const labelledTri& tri = s[oldFacei];
1134 label oldPointi = tri[fp];
1136 if (oldToNewPoints[oldPointi] == -1)
1138 oldToNewPoints[oldPointi] = pointi;
1139 newToOldPoints[pointi++] = oldPointi;
1144 newToOldPoints.setSize(pointi);
1149 forAll(newToOldPoints, i)
1151 newPoints[i] = s.points()[newToOldPoints[i]];
1154 List<labelledTri> newTriangles(newToOldFaces.size());
1159 const labelledTri& tri = s[newToOldFaces[i]];
1161 newTriangles[i][0] = oldToNewPoints[tri[0]];
1162 newTriangles[i][1] = oldToNewPoints[tri[1]];
1163 newTriangles[i][2] = oldToNewPoints[tri[2]];
1164 newTriangles[i].region() = tri.region();
1168 return triSurface(newTriangles, s.patches(), newPoints,
true);
1179 const bool regularise,
1180 const scalar mergeTol
1183 mesh_(cVals.
mesh()),
1186 regularise_(regularise),
1187 mergeDistance_(mergeTol*mesh_.bounds().mag())
1191 Pout<<
"isoSurface:" <<
nl 1192 <<
" isoField : " << cVals.
name() <<
nl 1193 <<
" cell min/max : " 1196 <<
" point min/max : " 1197 <<
min(pVals_) <<
" / " 1198 <<
max(pVals_) <<
nl 1199 <<
" isoValue : " << iso <<
nl 1200 <<
" regularise : " << regularise_ <<
nl 1201 <<
" mergeTol : " << mergeTol <<
nl 1213 cValsPtr_.reset(adaptPatchFields(cVals).ptr());
1226 mesh_.pointsInstance(),
1235 mesh_.cellCentres(),
1247 meshC.boundaryField()[
patchi]
1252 collocatedFaces(refCast<const coupledPolyPatch>(pp))
1257 if (!isCollocated[i])
1259 pfld[i] = mesh_.faceCentres()[pp.
start()+i];
1263 else if (isA<emptyPolyPatch>(pp))
1267 bType& bfld =
const_cast<bType&
>(meshC.boundaryField());
1270 bfld.
set(patchi,
nullptr);
1278 mesh_.boundary()[
patchi],
1291 labelList boundaryRegion(mesh_.nFaces()-mesh_.nInternalFaces());
1301 boundaryRegion[facei-mesh_.nInternalFaces()] =
patchi;
1309 calcCutTypes(boundaryRegion, meshC, cValsPtr_(), pVals_);
1331 snappedCc.
setSize(mesh_.nCells());
1339 Pout<<
"isoSurface : shifted " << snappedPoints.
size()
1340 <<
" cell centres to intersection." <<
endl;
1343 label nCellSnaps = snappedPoints.
size();
1358 if (patches[patchi].coupled())
1361 refCast<const coupledPolyPatch>
1370 if (!isCollocated[i])
1372 const face& f = mesh_.faces()[cpp.
start()+i];
1376 isBoundaryPoint.set(f[fp], 1);
1387 const face& f = mesh_.faces()[pp.
start()+i];
1391 isBoundaryPoint.set(f[fp], 1);
1411 snappedPoint.
setSize(mesh_.nPoints());
1417 Pout<<
"isoSurface : shifted " << snappedPoints.
size()-nCellSnaps
1418 <<
" vertices to intersection." <<
endl;
1444 Pout<<
"isoSurface : generated " << triMeshCells.
size()
1445 <<
" unmerged triangles from " << triPoints.size()
1446 <<
" unmerged points." <<
endl;
1465 Pout<<
"isoSurface : generated " << triMap.
size()
1466 <<
" merged triangles." <<
endl;
1469 meshCells_.setSize(triMap.
size());
1472 meshCells_[i] = triMeshCells[triMap[i]];
1478 Pout<<
"isoSurface : checking " << size()
1479 <<
" triangles for validity." <<
endl;
1484 validTri(*
this, triI);
1492 Pout<<
"Dumping surface to " << stlFile <<
endl;
1493 triSurface::write(stlFile);
List< labelList > labelListList
A List of labelList.
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
#define forAll(list, i)
Loop across all elements in list.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
const word & name() const
Return name.
A class for handling file names.
bool set(const label) const
Is element set.
static const Vector< scalar > max
friend Ostream & operator(Ostream &, const UList< T > &)
A face is a list of labels corresponding to mesh vertices.
List< geometricSurfacePatch > geometricSurfacePatchList
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
void size(const label)
Override size to be inconsistent with allocated storage.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
isoSurface(const volScalarField &cellIsoVals, const scalarField &pointIsoVals, const scalar iso, const bool regularise, const scalar mergeTol=1e-6)
Construct from cell values and point values. Uses boundaryField.
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
Vector< scalar > vector
A scalar version of the templated Vector.
GeometricField< vector, fvPatchField, volMesh > volVectorField
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Macros for easy insertion into run-time selection tables.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
List< bool > boolList
Bool container classes.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
vectorField pointField
pointField is a vectorField.
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
List< label > labelList
A List of labels.
errorManip< error > abort(error &err)
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross product operators.
const Mesh & mesh() const
Return mesh.
defineTypeNameAndDebug(combustionModel, 0)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
void setSize(const label)
Reset size of List.
static bool & parRun()
Is this a parallel run?
vector point
Point is a vector.
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
prefixOSstream Pout(cout, "Pout")
label start() const
Return start label of this patch in the polyMesh face list.
label mergePoints(const UList< Type > &points, const scalar mergeTol, const bool verbose, labelList &pointMap, const Type &origin=Type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
void invertManyToMany(const label len, const UList< InList > &, List< OutList > &)
Invert many-to-many.
dimensioned< scalar > mag(const dimensioned< Type > &)
fileName path() const
Return directory path name (part before last /)
const doubleScalar e
Elementary charge.
A patch is a list of labels that address the faces in the global face list.
Triangulated surface description with patch information.
Specialization of GeometricField which holds slices of given complete fields in a form that they act ...
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Tensor< scalar > tensor
Tensor of scalars.
const List< T >::subList patchSlice(const UList< T > &l) const
Slice list to patch.