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]];
153 isA<processorPolyPatch>(patches[patchi])
154 && patches[patchi].
nPoints() > 0
155 && collocatedPatch(patches[patchi])
158 const processorPolyPatch& pp =
159 refCast<const processorPolyPatch>(patches[
patchi]);
166 fromNbr >> nbrPatchInfo;
169 const labelList& meshPts = pp.meshPoints();
173 label meshPointi = meshPts[pointi];
176 pointValues[meshPointi],
187 if (isA<cyclicPolyPatch>(patches[patchi]))
189 const cyclicPolyPatch& cycPatch =
190 refCast<const cyclicPolyPatch>(patches[
patchi]);
192 if (cycPatch.owner() && collocatedPatch(cycPatch))
196 const edgeList& coupledPoints = cycPatch.coupledPoints();
197 const labelList& meshPts = cycPatch.meshPoints();
198 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
199 const labelList& nbrMeshPoints = nbrPatch.meshPoints();
206 const edge&
e = coupledPoints[i];
207 half0Values[i] = pointValues[meshPts[e[0]]];
208 half1Values[i] = pointValues[nbrMeshPoints[e[1]]];
213 const edge&
e = coupledPoints[i];
214 label p0 = meshPts[e[0]];
215 label p1 = nbrMeshPoints[e[1]];
217 minEqOp<point>()(pointValues[p0], half1Values[i]);
218 minEqOp<point>()(pointValues[p1], half0Values[i]);
225 const globalMeshData& pd = mesh_.globalData();
227 if (pd.nGlobalPoints() > 0)
230 pointField sharedPts(pd.nGlobalPoints(), nullValue);
232 forAll(pd.sharedPointLabels(), i)
234 label meshPointi = pd.sharedPointLabels()[i];
236 sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointi];
245 forAll(pd.sharedPointLabels(), i)
247 label meshPointi = pd.sharedPointLabels()[i];
248 pointValues[meshPointi] = sharedPts[pd.sharedPointAddr()[i]];
254 Foam::scalar Foam::isoSurface::isoFraction
273 bool Foam::isoSurface::isEdgeOfFaceCut
283 bool fpLower = (pVals[f[fp]] < iso_);
286 (fpLower != ownLower)
287 || (fpLower != neiLower)
288 || (fpLower != (pVals[f[f.fcIndex(fp)]] < iso_))
298 void Foam::isoSurface::getNeighbour
309 const labelList& own = mesh_.faceOwner();
310 const labelList& nei = mesh_.faceNeighbour();
312 if (mesh_.isInternalFace(facei))
314 label nbr = (own[facei] == celli ? nei[facei] : own[facei]);
315 nbrValue = cVals[nbr];
316 nbrPoint = meshC[nbr];
320 label bFacei = facei-mesh_.nInternalFaces();
321 label patchi = boundaryRegion[bFacei];
322 const polyPatch& pp = mesh_.boundaryMesh()[
patchi];
323 label patchFacei = facei-pp.start();
325 nbrValue = cVals.boundaryField()[
patchi][patchFacei];
326 nbrPoint = meshC.boundaryField()[
patchi][patchFacei];
331 void Foam::isoSurface::calcCutTypes
339 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
340 const labelList& own = mesh_.faceOwner();
341 const labelList& nei = mesh_.faceNeighbour();
343 faceCutType_.
setSize(mesh_.nFaces());
344 faceCutType_ = NOTCUT;
346 for (
label facei = 0; facei < mesh_.nInternalFaces(); facei++)
349 bool ownLower = (cVals[own[facei]] < iso_);
364 bool neiLower = (nbrValue < iso_);
366 if (ownLower != neiLower)
368 faceCutType_[facei] = CUT;
374 const face f = mesh_.faces()[facei];
376 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
378 faceCutType_[facei] = CUT;
385 const polyPatch& pp = patches[
patchi];
387 label facei = pp.start();
391 bool ownLower = (cVals[own[facei]] < iso_);
406 bool neiLower = (nbrValue < iso_);
408 if (ownLower != neiLower)
410 faceCutType_[facei] = CUT;
415 const face f = mesh_.faces()[facei];
417 if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
419 faceCutType_[facei] = CUT;
430 cellCutType_.setSize(mesh_.nCells());
431 cellCutType_ = NOTCUT;
433 for (
label facei = 0; facei < mesh_.nInternalFaces(); facei++)
435 if (faceCutType_[facei] != NOTCUT)
437 if (cellCutType_[own[facei]] == NOTCUT)
439 cellCutType_[own[facei]] = CUT;
442 if (cellCutType_[nei[facei]] == NOTCUT)
444 cellCutType_[nei[facei]] = CUT;
449 for (
label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
451 if (faceCutType_[facei] != NOTCUT)
453 if (cellCutType_[own[facei]] == NOTCUT)
455 cellCutType_[own[facei]] = CUT;
463 Pout<<
"isoSurface : detected " << nCutCells_
464 <<
" candidate cut cells (out of " << mesh_.nCells()
471 Foam::point Foam::isoSurface::calcCentre(
const triSurface& s)
477 sum += s[i].centre(s.points());
483 void Foam::isoSurface::calcSnappedCc
490 DynamicList<point>& snappedPoints,
497 snappedCc.
setSize(mesh_.nCells());
501 DynamicList<point, 64> localTriPoints(64);
503 forAll(mesh_.cells(), celli)
505 if (cellCutType_[celli] == CUT)
507 scalar cVal = cVals[celli];
509 const cell& cFaces = mesh_.cells()[celli];
511 localTriPoints.clear();
520 label facei = cFaces[cFacei];
536 FixedList<scalar, 3>
s;
537 FixedList<point, 3> pt;
540 s[2] = isoFraction(cVal, nbrValue);
541 pt[2] = (1.0-s[2])*cc[celli] + s[2]*nbrPoint;
543 const face& f = mesh_.faces()[cFaces[cFacei]];
549 s[0] = isoFraction(cVal, pVals[p0]);
550 pt[0] = (1.0-s[0])*cc[celli] + s[0]*pts[p0];
553 label p1 = f[f.fcIndex(fp)];
554 s[1] = isoFraction(cVal, pVals[p1]);
555 pt[1] = (1.0-s[1])*cc[celli] + s[1]*pts[p1];
559 (s[0] >= 0.0 && s[0] <= 0.5)
560 && (s[1] >= 0.0 && s[1] <= 0.5)
561 && (s[2] >= 0.0 && s[2] <= 0.5)
564 localTriPoints.append(pt[0]);
565 localTriPoints.append(pt[1]);
566 localTriPoints.append(pt[2]);
573 if (s[i] >= 0.0 && s[i] <= 0.5)
575 otherPointSum += pt[i];
583 if (localTriPoints.size() == 0)
589 snappedCc[celli] = snappedPoints.size();
590 snappedPoints.append(otherPointSum/nOther);
597 else if (localTriPoints.size() == 3)
602 snappedCc[celli] = snappedPoints.size();
603 snappedPoints.append(
sum(points)/points.size());
628 label nZones = surf.markZones
636 snappedCc[celli] = snappedPoints.size();
637 snappedPoints.append(calcCentre(surf));
648 void Foam::isoSurface::calcSnappedPoint
650 const PackedBoolList& isBoundaryPoint,
656 DynamicList<point>& snappedPoints,
667 DynamicList<point, 64> localTriPoints(100);
669 forAll(mesh_.pointFaces(), pointi)
671 if (isBoundaryPoint.get(pointi) == 1)
676 const labelList& pFaces = mesh_.pointFaces()[pointi];
682 label facei = pFaces[i];
684 if (faceCutType_[facei] == CUT)
697 localTriPoints.clear();
706 label facei = pFaces[pFacei];
707 const face& f = mesh_.faces()[facei];
708 label own = mesh_.faceOwner()[facei];
725 FixedList<scalar, 4>
s;
726 FixedList<point, 4> pt;
729 s[0] = isoFraction(pVals[pointi], cVals[own]);
730 pt[0] = (1.0-s[0])*pts[pointi] + s[0]*cc[own];
732 s[1] = isoFraction(pVals[pointi], nbrValue);
733 pt[1] = (1.0-s[1])*pts[pointi] + s[1]*nbrPoint;
735 label nextPointi = f[f.fcIndex(fp)];
736 s[2] = isoFraction(pVals[pointi], pVals[nextPointi]);
737 pt[2] = (1.0-s[2])*pts[pointi] + s[2]*pts[nextPointi];
739 label prevPointi = f[f.rcIndex(fp)];
740 s[3] = isoFraction(pVals[pointi], pVals[prevPointi]);
741 pt[3] = (1.0-s[3])*pts[pointi] + s[3]*pts[prevPointi];
745 (s[0] >= 0.0 && s[0] <= 0.5)
746 && (s[1] >= 0.0 && s[1] <= 0.5)
747 && (s[2] >= 0.0 && s[2] <= 0.5)
750 localTriPoints.append(pt[0]);
751 localTriPoints.append(pt[1]);
752 localTriPoints.append(pt[2]);
756 (s[0] >= 0.0 && s[0] <= 0.5)
757 && (s[1] >= 0.0 && s[1] <= 0.5)
758 && (s[3] >= 0.0 && s[3] <= 0.5)
761 localTriPoints.append(pt[3]);
762 localTriPoints.append(pt[0]);
763 localTriPoints.append(pt[1]);
769 if (s[i] >= 0.0 && s[i] <= 0.5)
771 otherPointSum += pt[i];
777 if (localTriPoints.size() == 0)
783 collapsedPoint[pointi] = otherPointSum/nOther;
786 else if (localTriPoints.size() == 3)
791 collapsedPoint[pointi] =
sum(points)/points.size();
812 label nZones = surf.markZones
820 collapsedPoint[pointi] = calcCentre(surf);
827 syncUnseparatedPoints(collapsedPoint,
point::max);
830 snappedPoint.setSize(mesh_.nPoints());
833 forAll(collapsedPoint, pointi)
837 snappedPoint[pointi] = snappedPoints.size();
838 snappedPoints.append(collapsedPoint[pointi]);
846 const bool checkDuplicates,
847 const List<point>& triPoints,
852 label nTris = triPoints.size()/3;
854 if ((triPoints.size() % 3) != 0)
857 <<
"Problem: number of points " << triPoints.size()
888 <<
"Merged points contain duplicates" 889 <<
" when merging with distance " << mergeDistance_ <<
endl 890 <<
"merged:" << newPoints.size() <<
" re-merged:" 891 << newNewPoints.size()
897 List<labelledTri> tris;
899 DynamicList<labelledTri> dynTris(nTris);
901 DynamicList<label> newToOldTri(nTris);
903 for (
label oldTriI = 0; oldTriI < nTris; oldTriI++)
907 triPointReverseMap[rawPointi],
908 triPointReverseMap[rawPointi+1],
909 triPointReverseMap[rawPointi+2],
914 if ((tri[0] != tri[1]) && (tri[0] != tri[2]) && (tri[1] != tri[2]))
916 newToOldTri.append(oldTriI);
921 triMap.transfer(newToOldTri);
922 tris.transfer(dynTris);
937 DynamicList<label> newToOldTri(tris.size());
941 const labelledTri& tri = tris[triI];
942 const labelList& pFaces = pointFaces[tri[0]];
950 label nbrTriI = pFaces[i];
952 if (nbrTriI > triI && (tris[nbrTriI] == tri))
965 label newTriI = newToOldTri.size();
966 newToOldTri.append(triMap[triI]);
967 tris[newTriI] = tris[triI];
971 triMap.transfer(newToOldTri);
972 tris.setSize(triMap.size());
976 Pout<<
"isoSurface : merged from " << nTris
977 <<
" down to " << tris.size() <<
" unique triangles." <<
endl;
987 const labelledTri& f = surf[facei];
988 const labelList& fFaces = surf.faceFaces()[facei];
992 label nbrFacei = fFaces[i];
994 if (nbrFacei <= facei)
1000 const labelledTri& nbrF = surf[nbrFacei];
1006 <<
" triangle " << facei <<
" vertices " << f
1007 <<
" fc:" << f.centre(surf.points())
1008 <<
" has the same vertices as triangle " << nbrFacei
1009 <<
" vertices " << nbrF
1010 <<
" fc:" << nbrF.centre(surf.points())
1022 bool Foam::isoSurface::validTri(
const triSurface& surf,
const label facei)
1026 const labelledTri& f = surf[facei];
1030 (f[0] < 0) || (f[0] >= surf.points().size())
1031 || (f[1] < 0) || (f[1] >= surf.points().size())
1032 || (f[2] < 0) || (f[2] >= surf.points().size())
1036 <<
"triangle " << facei <<
" vertices " << f
1037 <<
" uses point indices outside point range 0.." 1038 << surf.points().size()-1 <<
endl;
1043 if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
1046 <<
"triangle " << facei
1047 <<
" uses non-unique vertices " << f
1054 const labelList& fFaces = surf.faceFaces()[facei];
1060 label nbrFacei = fFaces[i];
1062 if (nbrFacei <= facei)
1068 const labelledTri& nbrF = surf[nbrFacei];
1072 ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2]))
1073 && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2]))
1074 && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2]))
1078 <<
"triangle " << facei <<
" vertices " << f
1079 <<
" fc:" << f.centre(surf.points())
1080 <<
" has the same vertices as triangle " << nbrFacei
1081 <<
" vertices " << nbrF
1082 <<
" fc:" << nbrF.centre(surf.points())
1094 const triSurface& s,
1102 createWithValues<boolList>
1111 newToOldPoints.setSize(s.points().size());
1112 oldToNewPoints.setSize(s.points().size());
1113 oldToNewPoints = -1;
1117 forAll(include, oldFacei)
1119 if (include[oldFacei])
1122 const labelledTri& tri = s[oldFacei];
1126 label oldPointi = tri[fp];
1128 if (oldToNewPoints[oldPointi] == -1)
1130 oldToNewPoints[oldPointi] = pointi;
1131 newToOldPoints[pointi++] = oldPointi;
1136 newToOldPoints.setSize(pointi);
1141 forAll(newToOldPoints, i)
1143 newPoints[i] = s.points()[newToOldPoints[i]];
1146 List<labelledTri> newTriangles(newToOldFaces.size());
1151 const labelledTri& tri = s[newToOldFaces[i]];
1153 newTriangles[i][0] = oldToNewPoints[tri[0]];
1154 newTriangles[i][1] = oldToNewPoints[tri[1]];
1155 newTriangles[i][2] = oldToNewPoints[tri[2]];
1156 newTriangles[i].region() = tri.region();
1160 return triSurface(newTriangles, s.patches(), newPoints,
true);
1171 const bool regularise,
1172 const scalar mergeTol
1175 mesh_(cVals.
mesh()),
1178 regularise_(regularise),
1179 mergeDistance_(mergeTol*mesh_.bounds().mag())
1183 Pout<<
"isoSurface:" <<
nl 1184 <<
" isoField : " << cVals.
name() <<
nl 1185 <<
" cell min/max : " 1188 <<
" point min/max : " 1189 <<
min(pVals_) <<
" / " 1190 <<
max(pVals_) <<
nl 1191 <<
" isoValue : " << iso <<
nl 1192 <<
" regularise : " << regularise_ <<
nl 1193 <<
" mergeTol : " << mergeTol <<
nl 1205 cValsPtr_.reset(adaptPatchFields(cVals).ptr());
1218 mesh_.pointsInstance(),
1227 mesh_.cellCentres(),
1239 meshC.boundaryField()[
patchi]
1244 collocatedFaces(refCast<const coupledPolyPatch>(pp))
1249 if (!isCollocated[i])
1251 pfld[i] = mesh_.faceCentres()[pp.
start()+i];
1255 else if (isA<emptyPolyPatch>(pp))
1259 bType& bfld =
const_cast<bType&
>(meshC.boundaryField());
1262 bfld.
set(patchi, NULL);
1270 mesh_.boundary()[
patchi],
1283 labelList boundaryRegion(mesh_.nFaces()-mesh_.nInternalFaces());
1293 boundaryRegion[facei-mesh_.nInternalFaces()] =
patchi;
1301 calcCutTypes(boundaryRegion, meshC, cValsPtr_(), pVals_);
1323 snappedCc.
setSize(mesh_.nCells());
1331 Pout<<
"isoSurface : shifted " << snappedPoints.
size()
1332 <<
" cell centres to intersection." <<
endl;
1335 label nCellSnaps = snappedPoints.
size();
1350 if (patches[patchi].coupled())
1353 refCast<const coupledPolyPatch>
1362 if (!isCollocated[i])
1364 const face& f = mesh_.faces()[cpp.
start()+i];
1368 isBoundaryPoint.set(f[fp], 1);
1379 const face& f = mesh_.faces()[pp.
start()+i];
1383 isBoundaryPoint.set(f[fp], 1);
1403 snappedPoint.
setSize(mesh_.nPoints());
1409 Pout<<
"isoSurface : shifted " << snappedPoints.
size()-nCellSnaps
1410 <<
" vertices to intersection." <<
endl;
1436 Pout<<
"isoSurface : generated " << triMeshCells.
size()
1437 <<
" unmerged triangles from " << triPoints.size()
1438 <<
" unmerged points." <<
endl;
1457 Pout<<
"isoSurface : generated " << triMap.
size()
1458 <<
" merged triangles." <<
endl;
1461 meshCells_.setSize(triMap.
size());
1464 meshCells_[i] = triMeshCells[triMap[i]];
1470 Pout<<
"isoSurface : checking " << size()
1471 <<
" triangles for validity." <<
endl;
1476 validTri(*
this, triI);
1484 Pout<<
"Dumping surface to " << stlFile <<
endl;
1485 triSurface::write(stlFile);
static const Vector< scalar > max
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.
A class for handling file names.
friend Ostream & operator(Ostream &, const UList< T > &)
A face is a list of labels corresponding to mesh vertices.
const double e
Elementary charge.
List< geometricSurfacePatch > geometricSurfacePatchList
const List< T >::subList patchSlice(const UList< T > &l) const
Slice list to patch.
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...
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
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.
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.
label start() const
Return start label of this patch in the polyMesh face list.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
bool set(const label) const
Is element set.
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.
prefixOSstream Pout(cout,"Pout")
defineTypeNameAndDebug(combustionModel, 0)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence 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)
const Mesh & mesh() const
Return mesh.
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 > &)
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...
fileName path() const
Return directory path name (part before last /)
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Tensor< scalar > tensor
Tensor of scalars.
const word & name() const
Return name.