← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 4138: Added force and torque export to VTKRecorder (question #252413)

 

------------------------------------------------------------
revno: 4138
committer: Jan Stransky <jan.stransky@xxxxxxxxxxx>
timestamp: Fri 2014-08-08 11:26:21 +0200
message:
  Added force and torque export to VTKRecorder (question #252413)
modified:
  pkg/dem/VTKRecorder.cpp
  pkg/dem/VTKRecorder.hpp


--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== modified file 'pkg/dem/VTKRecorder.cpp'
--- pkg/dem/VTKRecorder.cpp	2014-07-17 08:39:25 +0000
+++ pkg/dem/VTKRecorder.cpp	2014-08-08 09:26:21 +0000
@@ -59,6 +59,7 @@
 			recActive[REC_CLUMPID]=true;
 			recActive[REC_MATERIALID]=true;
 			recActive[REC_STRESS]=true;
+			recActive[REC_FORCE]=true;
 			if (scene->isPeriodic) { recActive[REC_PERICELL]=true; }
 		}
 		else if(rec=="spheres") recActive[REC_SPHERES]=true;
@@ -75,6 +76,7 @@
 		else if((rec=="clumpids") || (rec=="clumpId")) recActive[REC_CLUMPID]=true;
 		else if(rec=="materialId") recActive[REC_MATERIALID]=true;
 		else if(rec=="stress") recActive[REC_STRESS]=true;
+		else if(rec=="force") recActive[REC_FORCE]=true;
 		else if(rec=="jcfpm") recActive[REC_JCFPM]=true;
 		else if(rec=="cracks") recActive[REC_CRACKS]=true;
 		else if(rec=="pericell" && scene->isPeriodic) recActive[REC_PERICELL]=true;
@@ -211,6 +213,22 @@
 	spheresMaterialId->SetNumberOfComponents(1);
 	spheresMaterialId->SetName("materialId");
 
+	vtkSmartPointer<vtkDoubleArray> spheresForceVec = vtkSmartPointer<vtkDoubleArray>::New();
+	spheresForceVec->SetNumberOfComponents(3);
+	spheresForceVec->SetName("forceVec");
+
+	vtkSmartPointer<vtkDoubleArray> spheresForceLen = vtkSmartPointer<vtkDoubleArray>::New();
+	spheresForceLen->SetNumberOfComponents(1);
+	spheresForceLen->SetName("forceLen");
+
+	vtkSmartPointer<vtkDoubleArray> spheresTorqueVec = vtkSmartPointer<vtkDoubleArray>::New();
+	spheresTorqueVec->SetNumberOfComponents(3);
+	spheresTorqueVec->SetName("torqueVec");
+
+	vtkSmartPointer<vtkDoubleArray> spheresTorqueLen = vtkSmartPointer<vtkDoubleArray>::New();
+	spheresTorqueLen->SetNumberOfComponents(1);
+	spheresTorqueLen->SetName("torqueLen");
+
 	// facets
 	vtkSmartPointer<vtkPoints> facetsPos = vtkSmartPointer<vtkPoints>::New();
 	vtkSmartPointer<vtkCellArray> facetsCells = vtkSmartPointer<vtkCellArray>::New();
@@ -218,13 +236,13 @@
 	facetsColors->SetNumberOfComponents(3);
 	facetsColors->SetName("color");
 	
-	vtkSmartPointer<vtkDoubleArray> facetsForceVec = vtkSmartPointer<vtkDoubleArray>::New();
-	facetsForceVec->SetNumberOfComponents(3);
-	facetsForceVec->SetName("stressVec");
+	vtkSmartPointer<vtkDoubleArray> facetsStressVec = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsStressVec->SetNumberOfComponents(3);
+	facetsStressVec->SetName("stressVec");
 	
-	vtkSmartPointer<vtkDoubleArray> facetsForceLen = vtkSmartPointer<vtkDoubleArray>::New();
-	facetsForceLen->SetNumberOfComponents(1);
-	facetsForceLen->SetName("stressLen");
+	vtkSmartPointer<vtkDoubleArray> facetsStressLen = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsStressLen->SetNumberOfComponents(1);
+	facetsStressLen->SetName("stressLen");
 	
 	vtkSmartPointer<vtkDoubleArray> facetsMaterialId = vtkSmartPointer<vtkDoubleArray>::New();
 	facetsMaterialId->SetNumberOfComponents(1);
@@ -234,6 +252,22 @@
 	facetsMask->SetNumberOfComponents(1);
 	facetsMask->SetName("mask");
 
+	vtkSmartPointer<vtkDoubleArray> facetsForceVec = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsForceVec->SetNumberOfComponents(3);
+	facetsForceVec->SetName("forceVec");
+
+	vtkSmartPointer<vtkDoubleArray> facetsForceLen = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsForceLen->SetNumberOfComponents(1);
+	facetsForceLen->SetName("forceLen");
+
+	vtkSmartPointer<vtkDoubleArray> facetsTorqueVec = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsTorqueVec->SetNumberOfComponents(3);
+	facetsTorqueVec->SetName("torqueVec");
+
+	vtkSmartPointer<vtkDoubleArray> facetsTorqueLen = vtkSmartPointer<vtkDoubleArray>::New();
+	facetsTorqueLen->SetNumberOfComponents(1);
+	facetsTorqueLen->SetName("torqueLen");
+
 	// boxes
 	vtkSmartPointer<vtkPoints> boxesPos = vtkSmartPointer<vtkPoints>::New();
 	vtkSmartPointer<vtkCellArray> boxesCells = vtkSmartPointer<vtkCellArray>::New();
@@ -241,13 +275,13 @@
 	boxesColors->SetNumberOfComponents(3);
 	boxesColors->SetName("color");
 	
-	vtkSmartPointer<vtkDoubleArray> boxesForceVec = vtkSmartPointer<vtkDoubleArray>::New();
-	boxesForceVec->SetNumberOfComponents(3);
-	boxesForceVec->SetName("stressVec");
+	vtkSmartPointer<vtkDoubleArray> boxesStressVec = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesStressVec->SetNumberOfComponents(3);
+	boxesStressVec->SetName("stressVec");
 	
-	vtkSmartPointer<vtkDoubleArray> boxesForceLen = vtkSmartPointer<vtkDoubleArray>::New();
-	boxesForceLen->SetNumberOfComponents(1);
-	boxesForceLen->SetName("stressLen");
+	vtkSmartPointer<vtkDoubleArray> boxesStressLen = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesStressLen->SetNumberOfComponents(1);
+	boxesStressLen->SetName("stressLen");
 	
 	vtkSmartPointer<vtkDoubleArray> boxesMaterialId = vtkSmartPointer<vtkDoubleArray>::New();
 	boxesMaterialId->SetNumberOfComponents(1);
@@ -257,6 +291,22 @@
 	boxesMask->SetNumberOfComponents(1);
 	boxesMask->SetName("mask");
 
+	vtkSmartPointer<vtkDoubleArray> boxesForceVec = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesForceVec->SetNumberOfComponents(3);
+	boxesForceVec->SetName("forceVec");
+
+	vtkSmartPointer<vtkDoubleArray> boxesForceLen = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesForceLen->SetNumberOfComponents(1);
+	boxesForceLen->SetName("forceLen");
+
+	vtkSmartPointer<vtkDoubleArray> boxesTorqueVec = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesTorqueVec->SetNumberOfComponents(3);
+	boxesTorqueVec->SetName("torqueVec");
+
+	vtkSmartPointer<vtkDoubleArray> boxesTorqueLen = vtkSmartPointer<vtkDoubleArray>::New();
+	boxesTorqueLen->SetNumberOfComponents(1);
+	boxesTorqueLen->SetName("torqueLen");
+
 	// interactions
 	vtkSmartPointer<vtkPoints> intrBodyPos = vtkSmartPointer<vtkPoints>::New();
 	vtkSmartPointer<vtkCellArray> intrCells = vtkSmartPointer<vtkCellArray>::New();
@@ -521,6 +571,19 @@
 					spheresShearStressVec->InsertNextTupleValue(s);
 					spheresNormalStressNorm->InsertNextValue(stress.norm());
 				}
+				if(recActive[REC_FORCE]){
+					scene->forces.sync();
+					const Vector3r& f = scene->forces.getForce(b->getId());
+					const Vector3r& t = scene->forces.getTorque(b->getId());
+					Real ff[3] = { (Real)  f[0], (Real) f[1], (Real) f[2] };
+					Real tt[3] = { (Real)  t[0], (Real) t[1], (Real) t[2] };
+					Real fn = f.norm();
+					Real tn = t.norm();
+					spheresForceVec->InsertNextTupleValue(ff);
+					spheresForceLen->InsertNextValue(fn);
+					spheresTorqueVec->InsertNextTupleValue(tt);
+					spheresTorqueLen->InsertNextValue(tn);
+				}
 				
 				if (recActive[REC_CPM]){
 					cpmDamage->InsertNextValue(YADE_PTR_CAST<CpmState>(b->state)->normDmg);
@@ -574,8 +637,21 @@
 				if(recActive[REC_STRESS]){
 					const Vector3r& stress = bodyStates[b->getId()].normStress+bodyStates[b->getId()].shearStress;
 					Real s[3] = { (Real) stress[0], (Real) stress[1], (Real) stress[2] };
-					facetsForceVec->InsertNextTupleValue(s);
-					facetsForceLen->InsertNextValue(stress.norm());
+					facetsStressVec->InsertNextTupleValue(s);
+					facetsStressLen->InsertNextValue(stress.norm());
+				}
+				if(recActive[REC_FORCE]){
+					scene->forces.sync();
+					const Vector3r& f = scene->forces.getForce(b->getId());
+					const Vector3r& t = scene->forces.getTorque(b->getId());
+					Real ff[3] = { (Real)  f[0], (Real) f[1], (Real) f[2] };
+					Real tt[3] = { (Real)  t[0], (Real) t[1], (Real) t[2] };
+					Real fn = f.norm();
+					Real tn = t.norm();
+					facetsForceVec->InsertNextTupleValue(ff);
+					facetsForceLen->InsertNextValue(fn);
+					facetsTorqueVec->InsertNextTupleValue(tt);
+					facetsTorqueLen->InsertNextValue(tn);
 				}
 				if (recActive[REC_MATERIALID]) facetsMaterialId->InsertNextValue(b->material->id);
 				if (recActive[REC_MASK]) facetsMask->InsertNextValue(GET_MASK(b));
@@ -585,6 +661,21 @@
 		if (recActive[REC_BOXES]){
 			const Box* box = dynamic_cast<Box*>(b->shape.get()); 
 			if (box){
+
+				if(recActive[REC_FORCE]){
+					scene->forces.sync();
+					const Vector3r& f = scene->forces.getForce(b->getId());
+					const Vector3r& t = scene->forces.getTorque(b->getId());
+					Real ff[3] = { (Real)  f[0], (Real) f[1], (Real) f[2] };
+					Real tt[3] = { (Real)  t[0], (Real) t[1], (Real) t[2] };
+					Real fn = f.norm();
+					Real tn = t.norm();
+					boxesForceVec->InsertNextTupleValue(ff);
+					boxesForceLen->InsertNextValue(fn);
+					boxesTorqueVec->InsertNextTupleValue(tt);
+					boxesTorqueLen->InsertNextValue(tn);
+				}
+
 				Vector3r pos(scene->isPeriodic ? scene->cell->wrapShearedPt(b->state->pos) : b->state->pos);
 				Vector3r ext(box->extents);
 				vtkSmartPointer<vtkQuad> boxes = vtkSmartPointer<vtkQuad>::New();
@@ -626,8 +717,8 @@
 					if(recActive[REC_STRESS]){
 						const Vector3r& stress = bodyStates[b->getId()].normStress+bodyStates[b->getId()].shearStress;
 						Real s[3] = { (Real) stress[0], (Real) stress[1], (Real) stress[2] };
-						boxesForceVec->InsertNextTupleValue(s);
-						boxesForceLen->InsertNextValue(stress.norm());
+						boxesStressVec->InsertNextTupleValue(s);
+						boxesStressLen->InsertNextValue(stress.norm());
 					}
 					if (recActive[REC_MATERIALID]) boxesMaterialId->InsertNextValue(b->material->id);
 					if (recActive[REC_MASK]) boxesMask->InsertNextValue(GET_MASK(b));
@@ -701,6 +792,12 @@
 			spheresUg->GetPointData()->AddArray(spheresShearStressVec);
 			spheresUg->GetPointData()->AddArray(spheresNormalStressNorm);
 		}
+		if (recActive[REC_FORCE]){
+			spheresUg->GetPointData()->AddArray(spheresForceVec);
+			spheresUg->GetPointData()->AddArray(spheresForceLen);
+			spheresUg->GetPointData()->AddArray(spheresTorqueVec);
+			spheresUg->GetPointData()->AddArray(spheresTorqueLen);
+		}
 		if (recActive[REC_CPM]){
 			spheresUg->GetPointData()->AddArray(cpmDamage);
 			spheresUg->GetPointData()->AddArray(cpmStress);
@@ -743,8 +840,14 @@
 		facetsUg->SetCells(VTK_TRIANGLE, facetsCells);
 		if (recActive[REC_COLORS]) facetsUg->GetCellData()->AddArray(facetsColors);
 		if (recActive[REC_STRESS]){
+			facetsUg->GetCellData()->AddArray(facetsStressVec);
+			facetsUg->GetCellData()->AddArray(facetsStressLen);
+		}
+		if (recActive[REC_FORCE]){
 			facetsUg->GetCellData()->AddArray(facetsForceVec);
 			facetsUg->GetCellData()->AddArray(facetsForceLen);
+			facetsUg->GetCellData()->AddArray(facetsTorqueVec);
+			facetsUg->GetCellData()->AddArray(facetsTorqueLen);
 		}
 		if (recActive[REC_MATERIALID]) facetsUg->GetCellData()->AddArray(facetsMaterialId);
 		if (recActive[REC_MASK]) facetsUg->GetCellData()->AddArray(facetsMask);
@@ -771,8 +874,14 @@
 		boxesUg->SetCells(VTK_QUAD, boxesCells);
 		if (recActive[REC_COLORS]) boxesUg->GetCellData()->AddArray(boxesColors);
 		if (recActive[REC_STRESS]){
+			boxesUg->GetCellData()->AddArray(boxesStressVec);
+			boxesUg->GetCellData()->AddArray(boxesStressLen);
+		}
+		if (recActive[REC_FACETS]){
 			boxesUg->GetCellData()->AddArray(boxesForceVec);
 			boxesUg->GetCellData()->AddArray(boxesForceLen);
+			boxesUg->GetCellData()->AddArray(boxesTorqueVec);
+			boxesUg->GetCellData()->AddArray(boxesTorqueLen);
 		}
 		if (recActive[REC_MATERIALID]) boxesUg->GetCellData()->AddArray(boxesMaterialId);
 		if (recActive[REC_MASK]) boxesUg->GetCellData()->AddArray(boxesMask);

=== modified file 'pkg/dem/VTKRecorder.hpp'
--- pkg/dem/VTKRecorder.hpp	2014-07-17 08:39:25 +0000
+++ pkg/dem/VTKRecorder.hpp	2014-08-08 09:26:21 +0000
@@ -11,7 +11,7 @@
 
 class VTKRecorder: public PeriodicEngine {
 	public:
-  enum {REC_SPHERES=0,REC_FACETS,REC_BOXES,REC_COLORS,REC_MASS,REC_CPM,REC_INTR,REC_VELOCITY,REC_ID,REC_CLUMPID,REC_SENTINEL,REC_MATERIALID,REC_STRESS,REC_MASK,REC_RPM,REC_JCFPM,REC_CRACKS,REC_WPM,REC_PERICELL,REC_LIQ,REC_BSTRESS};
+  enum {REC_SPHERES=0,REC_FACETS,REC_BOXES,REC_COLORS,REC_MASS,REC_CPM,REC_INTR,REC_VELOCITY,REC_ID,REC_CLUMPID,REC_SENTINEL,REC_MATERIALID,REC_STRESS,REC_MASK,REC_RPM,REC_JCFPM,REC_CRACKS,REC_WPM,REC_PERICELL,REC_LIQ,REC_BSTRESS,REC_FORCE};
 		virtual void action();
 		void addWallVTK (vtkSmartPointer<vtkQuad>& boxes, vtkSmartPointer<vtkPoints>& boxesPos, Vector3r& W1, Vector3r& W2, Vector3r& W3, Vector3r& W4);
 	YADE_CLASS_BASE_DOC_ATTRS_CTOR(VTKRecorder,PeriodicEngine,"Engine recording snapshots of simulation into series of \\*.vtu files, readable by VTK-based postprocessing programs such as Paraview. Both bodies (spheres and facets) and interactions can be recorded, with various vector/scalar quantities that are defined on them.\n\n:yref:`PeriodicEngine.initRun` is initialized to ``True`` automatically.",
@@ -23,7 +23,7 @@
 			((bool,multiblock,false,,"Use multi-block (``.vtm``) files to store data, rather than separate ``.vtu`` files."))
 		#endif
 		((string,fileName,"",,"Base file name; it will be appended with {spheres,intrs,facets}-243100.vtu (unless *multiblock* is ``True``) depending on active recorders and step number (243100 in this case). It can contain slashes, but the directory must exist already."))
-		((vector<string>,recorders,vector<string>(1,string("all")),,"List of active recorders (as strings). ``all`` (the default value) enables all base and generic recorders.\n\n.. admonition:: Base recorders\n\n\tBase recorders save the geometry (unstructured grids) on which other data is defined. They are implicitly activated by many of the other recorders. Each of them creates a new file (or a block, if :yref:`multiblock <VTKRecorder.multiblock>` is set).\n\n\t``spheres``\n\t\tSaves positions and radii (``radii``) of :yref:`spherical<Sphere>` particles.\n\t``facets``\n\t\tSave :yref:`facets<Facet>` positions (vertices).\n\t``boxes``\n\t\tSave :yref:`boxes<Box>` positions (edges).\n\t``intr``\n\t\tStore interactions as lines between nodes at respective particles positions. Additionally stores magnitude of normal (``forceN``) and shear (``absForceT``) forces on interactions (the :yref:`geom<Interaction.geom> must be of type :yref:`NormShearPhys`). \n\n.. admonition:: Generic recorders\n\n\tGeneric recorders do not depend on specific model being used and save commonly useful data.\n\n\t``id``\n\t\tSaves id's (field ``id``) of spheres; active only if ``spheres`` is active.\n\t``mass``\n\t\tSaves masses (field ``mass``) of spheres; active only if ``spheres`` is active.\n\t``clumpId``\n\t\tSaves id's of clumps to which each sphere belongs (field ``clumpId``); active only if ``spheres`` is active.\n\t``colors``\n\t\tSaves colors of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``color``); only active if ``spheres`` or ``facets`` are activated.\n\t``mask``\n\t\tSaves groupMasks of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``mask``); only active if ``spheres`` or ``facets`` are activated.\n\t``materialId``\n\t\tSaves materialID of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`; only active if ``spheres`` or ``facets`` are activated.\n\t``velocity``\n\t\tSaves linear and angular velocities of spherical particles as Vector3 and length(fields ``linVelVec``, ``linVelLen`` and ``angVelVec``, ``angVelLen`` respectively``); only effective with ``spheres``.\n\t``stress``\n\t\tSaves stresses of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`  as Vector3 and length; only active if ``spheres`` or ``facets`` are activated.\n\t``pericell``\n\t\tSaves the shape of the cell (simulation has to be periodic).\n\t``bstresses``\n\t\tSaves per-particle principal stresses (sigI >= sigII >= sigIII) and associated principal directions (dirI/II/III). Per-particle stress tensors are given by :yref:`bodyStressTensors<yade.utils.bodyStressTensors>` (positive values for tensile states).\n\n.. admonition:: Specific recorders\n\n\tThe following should only be activated in appropriate cases, otherwise crashes can occur due to violation of type presuppositions.\n\n\t``cpm``\n\t\tSaves data pertaining to the :yref:`concrete model<Law2_ScGeom_CpmPhys_Cpm>`: ``cpmDamage`` (normalized residual strength averaged on particle), ``cpmStress`` (stress on particle); ``intr`` is activated automatically by ``cpm``\n\t``wpm``\n\t\tSaves data pertaining to the :yref:`wire particle model<Law2_ScGeom_WirePhys_WirePM>`: ``wpmForceNFactor`` shows the loading factor for the wire, e.g. normal force divided by threshold normal force.\n\t``jcfpm``\n\t\tSaves data pertaining to the :yref:`rock (smooth)-jointed model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``damage`` is defined by :yref:`JCFpmState.tensBreak` + :yref:`JCFpmState.shearBreak`; ``intr`` is activated automatically by ``jcfpm``, and :yref:`on joint<JCFpmPhys.isOnJoint>` or :yref:`cohesive<JCFpmPhys.isCohesive>` interactions can be vizualized.\n\t``cracks``\n\t\tSaves other data pertaining to the :yref:`rock model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``cracks`` shows locations where cohesive bonds failed during the simulation, with their types (0/1  for tensile/shear breakages), their sizes (0.5*(R1+R2)), and their normal directions. The :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.recordCracks>` has to be activated, and Key attributes have to be consistent.\n\n"))
+		((vector<string>,recorders,vector<string>(1,string("all")),,"List of active recorders (as strings). ``all`` (the default value) enables all base and generic recorders.\n\n.. admonition:: Base recorders\n\n\tBase recorders save the geometry (unstructured grids) on which other data is defined. They are implicitly activated by many of the other recorders. Each of them creates a new file (or a block, if :yref:`multiblock <VTKRecorder.multiblock>` is set).\n\n\t``spheres``\n\t\tSaves positions and radii (``radii``) of :yref:`spherical<Sphere>` particles.\n\t``facets``\n\t\tSave :yref:`facets<Facet>` positions (vertices).\n\t``boxes``\n\t\tSave :yref:`boxes<Box>` positions (edges).\n\t``intr``\n\t\tStore interactions as lines between nodes at respective particles positions. Additionally stores magnitude of normal (``forceN``) and shear (``absForceT``) forces on interactions (the :yref:`geom<Interaction.geom> must be of type :yref:`NormShearPhys`). \n\n.. admonition:: Generic recorders\n\n\tGeneric recorders do not depend on specific model being used and save commonly useful data.\n\n\t``id``\n\t\tSaves id's (field ``id``) of spheres; active only if ``spheres`` is active.\n\t``mass``\n\t\tSaves masses (field ``mass``) of spheres; active only if ``spheres`` is active.\n\t``clumpId``\n\t\tSaves id's of clumps to which each sphere belongs (field ``clumpId``); active only if ``spheres`` is active.\n\t``colors``\n\t\tSaves colors of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``color``); only active if ``spheres`` or ``facets`` are activated.\n\t``mask``\n\t\tSaves groupMasks of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``mask``); only active if ``spheres`` or ``facets`` are activated.\n\t``materialId``\n\t\tSaves materialID of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`; only active if ``spheres`` or ``facets`` are activated.\n\t``velocity``\n\t\tSaves linear and angular velocities of spherical particles as Vector3 and length(fields ``linVelVec``, ``linVelLen`` and ``angVelVec``, ``angVelLen`` respectively``); only effective with ``spheres``.\n\t``stress``\n\t\tSaves stresses of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`  as Vector3 and length; only active if ``spheres`` or ``facets`` are activated.\n\t``force``\n\t\tSaves force and torque of :yref:`spheres<Sphere>`, :yref:`facets<Facet>` and :yref:`boxes<Box>` as Vector3 and length (norm); only active if ``spheres``, ``facets`` or ``boxes`` are activated.\n\t``pericell``\n\t\tSaves the shape of the cell (simulation has to be periodic).\n\t``bstresses``\n\t\tSaves per-particle principal stresses (sigI >= sigII >= sigIII) and associated principal directions (dirI/II/III). Per-particle stress tensors are given by :yref:`bodyStressTensors<yade.utils.bodyStressTensors>` (positive values for tensile states).\n\n.. admonition:: Specific recorders\n\n\tThe following should only be activated in appropriate cases, otherwise crashes can occur due to violation of type presuppositions.\n\n\t``cpm``\n\t\tSaves data pertaining to the :yref:`concrete model<Law2_ScGeom_CpmPhys_Cpm>`: ``cpmDamage`` (normalized residual strength averaged on particle), ``cpmStress`` (stress on particle); ``intr`` is activated automatically by ``cpm``\n\t``wpm``\n\t\tSaves data pertaining to the :yref:`wire particle model<Law2_ScGeom_WirePhys_WirePM>`: ``wpmForceNFactor`` shows the loading factor for the wire, e.g. normal force divided by threshold normal force.\n\t``jcfpm``\n\t\tSaves data pertaining to the :yref:`rock (smooth)-jointed model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``damage`` is defined by :yref:`JCFpmState.tensBreak` + :yref:`JCFpmState.shearBreak`; ``intr`` is activated automatically by ``jcfpm``, and :yref:`on joint<JCFpmPhys.isOnJoint>` or :yref:`cohesive<JCFpmPhys.isCohesive>` interactions can be vizualized.\n\t``cracks``\n\t\tSaves other data pertaining to the :yref:`rock model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``cracks`` shows locations where cohesive bonds failed during the simulation, with their types (0/1  for tensile/shear breakages), their sizes (0.5*(R1+R2)), and their normal directions. The :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.recordCracks>` has to be activated, and Key attributes have to be consistent.\n\n"))
 		((string,Key,"",,"Necessary if :yref:`recorders<VTKRecorder.recorders>` contains 'cracks'. A string specifying the name of file 'cracks___.txt' that is considered in this case (see :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.Key>`)."))
 		((int,mask,0,,"If mask defined, only bodies with corresponding groupMask will be exported. If 0, all bodies will be exported.")),
 		/*ctor*/