← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3469: Move function declarations of _utils.cpp into .hpp

 

------------------------------------------------------------
revno: 3469
committer: Anton Gladky <gladky.anton@xxxxxxxxx>
timestamp: Tue 2014-10-14 17:52:06 +0200
message:
  Move function declarations of _utils.cpp into .hpp
  
  Also aabbExtrema() was moved into Shop.hpp
added:
  py/_utils.hpp
modified:
  pkg/dem/Shop.hpp
  pkg/dem/Shop_01.cpp
  pkg/dem/Shop_02.cpp
  py/_utils.cpp


--
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/Shop.hpp'
--- pkg/dem/Shop.hpp	2014-09-03 17:34:07 +0000
+++ pkg/dem/Shop.hpp	2014-10-14 15:52:06 +0000
@@ -143,4 +143,8 @@
 		//! Change of size of a single sphere or a clump
 		// DEPREC, update wrt growParticles()
 		static void growParticle(Body::id_t bodyID, Real multiplier, bool updateMass);
+		
+		/* \todo implement groupMask */
+		static py::tuple aabbExtrema(Real cutoff=0.0, bool centers=false);
 };
+

=== modified file 'pkg/dem/Shop_01.cpp'
--- pkg/dem/Shop_01.cpp	2014-10-08 20:07:22 +0000
+++ pkg/dem/Shop_01.cpp	2014-10-14 15:52:06 +0000
@@ -42,7 +42,7 @@
 	#include"yade/pkg/common/Gl1_NormPhys.hpp"
 #endif
 
-#include"yade/py/_utils.cpp"
+#include "yade/py/_utils.hpp"
 
 
 CREATE_LOGGER(Shop);
@@ -324,7 +324,7 @@
 	Real V;
 	if(!scene->isPeriodic){
 		if(_volume<=0){// throw std::invalid_argument("utils.porosity must be given (positive) *volume* for aperiodic simulations.");
-		  py::tuple extrema = aabbExtrema(); //aabbExtrema() defined in _utils.cpp
+		  py::tuple extrema = aabbExtrema();
 		  V = py::extract<Real>( (extrema[1][0] - extrema[0][0])*(extrema[1][1] - extrema[0][1])*(extrema[1][2] - extrema[0][2]) );
 		}
 		else

=== modified file 'pkg/dem/Shop_02.cpp'
--- pkg/dem/Shop_02.cpp	2014-09-03 17:34:07 +0000
+++ pkg/dem/Shop_02.cpp	2014-10-14 15:52:06 +0000
@@ -503,3 +503,17 @@
 		else contact->refR2 = rad;
 	}
 }
+
+py::tuple Shop::aabbExtrema(Real cutoff, bool centers){
+	if(cutoff<0. || cutoff>1.) throw invalid_argument("Cutoff must be >=0 and <=1.");
+	Real inf=std::numeric_limits<Real>::infinity();
+	Vector3r minimum(inf,inf,inf),maximum(-inf,-inf,-inf);
+	FOREACH(const shared_ptr<Body>& b, *Omega::instance().getScene()->bodies){
+		shared_ptr<Sphere> s=YADE_PTR_DYN_CAST<Sphere>(b->shape); if(!s) continue;
+		Vector3r rrr(s->radius,s->radius,s->radius);
+		minimum=minimum.cwiseMin(b->state->pos-(centers?Vector3r::Zero():rrr));
+		maximum=maximum.cwiseMax(b->state->pos+(centers?Vector3r::Zero():rrr));
+	}
+	Vector3r dim=maximum-minimum;
+	return py::make_tuple(Vector3r(minimum+.5*cutoff*dim),Vector3r(maximum-.5*cutoff*dim));
+}

=== modified file 'py/_utils.cpp'
--- py/_utils.cpp	2014-10-09 00:16:52 +0000
+++ py/_utils.cpp	2014-10-14 15:52:06 +0000
@@ -1,39 +1,9 @@
-#include<yade/pkg/dem/Shop.hpp>
-#include<yade/core/Scene.hpp>
-#include<yade/core/Omega.hpp>
-#include<yade/pkg/dem/ScGeom.hpp>
-#include<yade/pkg/dem/DemXDofGeom.hpp>
-#include<yade/pkg/common/Facet.hpp>
-#include<yade/pkg/dem/Tetra.hpp>
-#include<yade/pkg/common/Sphere.hpp>
-#include<yade/pkg/common/NormShearPhys.hpp>
-#include<yade/lib/computational-geometry/Hull2d.hpp>
-#include<yade/lib/pyutil/doc_opts.hpp>
-#include<yade/pkg/dem/ViscoelasticPM.hpp>
-
-#include<numpy/ndarrayobject.h>
-
-namespace py = boost::python;
+#include <yade/py/_utils.hpp>
 
 bool isInBB(Vector3r p, Vector3r bbMin, Vector3r bbMax){return p[0]>bbMin[0] && p[0]<bbMax[0] && p[1]>bbMin[1] && p[1]<bbMax[1] && p[2]>bbMin[2] && p[2]<bbMax[2];}
 
-/* \todo implement groupMask */
-py::tuple aabbExtrema(Real cutoff=0.0, bool centers=false){
-	if(cutoff<0. || cutoff>1.) throw invalid_argument("Cutoff must be >=0 and <=1.");
-	Real inf=std::numeric_limits<Real>::infinity();
-	Vector3r minimum(inf,inf,inf),maximum(-inf,-inf,-inf);
-	FOREACH(const shared_ptr<Body>& b, *Omega::instance().getScene()->bodies){
-		shared_ptr<Sphere> s=YADE_PTR_DYN_CAST<Sphere>(b->shape); if(!s) continue;
-		Vector3r rrr(s->radius,s->radius,s->radius);
-		minimum=minimum.cwiseMin(b->state->pos-(centers?Vector3r::Zero():rrr));
-		maximum=maximum.cwiseMax(b->state->pos+(centers?Vector3r::Zero():rrr));
-	}
-	Vector3r dim=maximum-minimum;
-	return py::make_tuple(Vector3r(minimum+.5*cutoff*dim),Vector3r(maximum-.5*cutoff*dim));
-}
-
-py::tuple negPosExtremeIds(int axis, Real distFactor=1.1){
-	py::tuple extrema=aabbExtrema();
+py::tuple negPosExtremeIds(int axis, Real distFactor){
+	py::tuple extrema=Shop::aabbExtrema();
 	Real minCoord=py::extract<double>(extrema[0][axis])(),maxCoord=py::extract<double>(extrema[1][axis])();
 	py::list minIds,maxIds;
 	FOREACH(const shared_ptr<Body>& b, *Omega::instance().getScene()->bodies){
@@ -43,9 +13,8 @@
 	}
 	return py::make_tuple(minIds,maxIds);
 }
-BOOST_PYTHON_FUNCTION_OVERLOADS(negPosExtremeIds_overloads,negPosExtremeIds,1,2);
 
-py::tuple coordsAndDisplacements(int axis,py::tuple Aabb=py::tuple()){
+py::tuple coordsAndDisplacements(int axis,py::tuple Aabb){
 	Vector3r bbMin(Vector3r::Zero()), bbMax(Vector3r::Zero()); bool useBB=py::len(Aabb)>0;
 	if(useBB){bbMin=py::extract<Vector3r>(Aabb[0])();bbMax=py::extract<Vector3r>(Aabb[1])();}
 	py::list retCoord,retDispl;
@@ -71,7 +40,7 @@
 Real PWaveTimeStep(){return Shop::PWaveTimeStep();};
 Real RayleighWaveTimeStep(){return Shop::RayleighWaveTimeStep();};
 
-py::tuple interactionAnglesHistogram(int axis, int mask=0, size_t bins=20, py::tuple aabb=py::tuple(), Real minProjLen=1e-6){
+py::tuple interactionAnglesHistogram(int axis, int mask, size_t bins, py::tuple aabb, Real minProjLen){
 	if(axis<0||axis>2) throw invalid_argument("Axis must be from {0,1,2}=x,y,z.");
 	Vector3r bbMin(Vector3r::Zero()), bbMax(Vector3r::Zero()); bool useBB=py::len(aabb)>0; if(useBB){bbMin=py::extract<Vector3r>(aabb[0])();bbMax=py::extract<Vector3r>(aabb[1])();}
 	Real binStep=Mathr::PI/bins; int axis2=(axis+1)%3, axis3=(axis+2)%3;
@@ -94,9 +63,8 @@
 	for(size_t i=0; i<(size_t)bins; i++){ val.append(cummProj[i]); binMid.append(i*binStep);}
 	return py::make_tuple(binMid,val);
 }
-BOOST_PYTHON_FUNCTION_OVERLOADS(interactionAnglesHistogram_overloads,interactionAnglesHistogram,1,4);
 
-py::tuple bodyNumInteractionsHistogram(py::tuple aabb=py::tuple()){
+py::tuple bodyNumInteractionsHistogram(py::tuple aabb){
 	Vector3r bbMin(Vector3r::Zero()), bbMax(Vector3r::Zero()); bool useBB=py::len(aabb)>0; if(useBB){bbMin=py::extract<Vector3r>(aabb[0])();bbMax=py::extract<Vector3r>(aabb[1])();}
 	const shared_ptr<Scene>& rb=Omega::instance().getScene();
 	vector<int> bodyNumIntr; bodyNumIntr.resize(rb->bodies->size(),0);
@@ -133,7 +101,6 @@
 	}
 	return py::make_tuple(num,count);
 }
-BOOST_PYTHON_FUNCTION_OVERLOADS(bodyNumInteractionsHistogram_overloads,bodyNumInteractionsHistogram,0,1);
 
 Vector3r inscribedCircleCenter(const Vector3r& v0, const Vector3r& v1, const Vector3r& v2)
 {
@@ -204,7 +171,7 @@
 /* Sum force acting on facets given by their ids in the sense of their respective normals.
    If axis is given, it will sum forces perpendicular to given axis only (not the the facet normals).
 */
-Real sumFacetNormalForces(vector<Body::id_t> ids, int axis=-1){
+Real sumFacetNormalForces(vector<Body::id_t> ids, int axis){
 	shared_ptr<Scene> rb=Omega::instance().getScene(); rb->forces.sync();
 	Real ret=0;
 	FOREACH(const Body::id_t id, ids){
@@ -339,20 +306,19 @@
 }
 
 
-py::tuple spiralProject(const Vector3r& pt, Real dH_dTheta, int axis=2, Real periodStart=std::numeric_limits<Real>::quiet_NaN(), Real theta0=0){
+py::tuple spiralProject(const Vector3r& pt, Real dH_dTheta, int axis, Real periodStart, Real theta0){
 	Real r,h,theta;
 	boost::tie(r,h,theta)=Shop::spiralProject(pt,dH_dTheta,axis,periodStart,theta0);
 	return py::make_tuple(py::make_tuple(r,h),theta);
 }
-//BOOST_PYTHON_FUNCTION_OVERLOADS(spiralProject_overloads,spiralProject,2,5);
 
 shared_ptr<Interaction> Shop__createExplicitInteraction(Body::id_t id1, Body::id_t id2){ return Shop::createExplicitInteraction(id1,id2,/*force*/true);}
 
 Real Shop__unbalancedForce(bool useMaxForce /*false by default*/){return Shop::unbalancedForce(useMaxForce);}
 py::tuple Shop__totalForceInVolume(){Real stiff; Vector3r ret=Shop::totalForceInVolume(stiff); return py::make_tuple(ret,stiff); }
-Real Shop__getSpheresVolume(int mask=-1){ return Shop::getSpheresVolume(Omega::instance().getScene(), mask=mask);}
-Real Shop__getSpheresMass(int mask=-1){ return Shop::getSpheresMass(Omega::instance().getScene(), mask=mask);}
-py::object Shop__kineticEnergy(bool findMaxId=false){
+Real Shop__getSpheresVolume(int mask){ return Shop::getSpheresVolume(Omega::instance().getScene(), mask=mask);}
+Real Shop__getSpheresMass(int mask){ return Shop::getSpheresMass(Omega::instance().getScene(), mask=mask);}
+py::object Shop__kineticEnergy(bool findMaxId){
 	if(!findMaxId) return py::object(Shop::kineticEnergy());
 	Body::id_t maxId;
 	Real E=Shop::kineticEnergy(NULL,&maxId);
@@ -374,16 +340,16 @@
 	return ret;
 }
 
-Real Shop__getPorosity(Real volume=-1){ return Shop::getPorosity(Omega::instance().getScene(),volume); }
-Real Shop__getVoxelPorosity(int resolution=200, Vector3r start=Vector3r(0,0,0),Vector3r end=Vector3r(0,0,0)){ return Shop::getVoxelPorosity(Omega::instance().getScene(),resolution,start,end); }
+Real Shop__getPorosity(Real volume){ return Shop::getPorosity(Omega::instance().getScene(),volume); }
+Real Shop__getVoxelPorosity(int resolution, Vector3r start,Vector3r end){ return Shop::getVoxelPorosity(Omega::instance().getScene(),resolution,start,end); }
 
 //Matrix3r Shop__stressTensorOfPeriodicCell(bool smallStrains=false){return Shop::stressTensorOfPeriodicCell(smallStrains);}
-py::tuple Shop__fabricTensor(bool splitTensor=false, bool revertSign=false, Real thresholdForce=NaN){return Shop::fabricTensor(splitTensor,revertSign,thresholdForce);}
-py::tuple Shop__normalShearStressTensors(bool compressionPositive=false, bool splitNormalTensor=false, Real thresholdForce=NaN){return Shop::normalShearStressTensors(compressionPositive,splitNormalTensor,thresholdForce);}
+py::tuple Shop__fabricTensor(bool splitTensor, bool revertSign, Real thresholdForce){return Shop::fabricTensor(splitTensor,revertSign,thresholdForce);}
+py::tuple Shop__normalShearStressTensors(bool compressionPositive, bool splitNormalTensor, Real thresholdForce){return Shop::normalShearStressTensors(compressionPositive,splitNormalTensor,thresholdForce);}
 
 py::list Shop__getStressLWForEachBody(){return Shop::getStressLWForEachBody();}
 
-py::list Shop__getBodyIdsContacts(Body::id_t bodyID=-1){return Shop::getBodyIdsContacts(bodyID);}
+py::list Shop__getBodyIdsContacts(Body::id_t bodyID){return Shop::getBodyIdsContacts(bodyID);}
 
 Real shiftBodies(py::list ids, const Vector3r& shift){
 	shared_ptr<Scene> rb=Omega::instance().getScene();
@@ -396,7 +362,7 @@
 	return 1;
 }
 
-void Shop__calm(int mask=-1){ return Shop::calm(Omega::instance().getScene(), mask=mask);}
+void Shop__calm(int mask){ return Shop::calm(Omega::instance().getScene(), mask=mask);}
 
 void setNewVerticesOfFacet(const shared_ptr<Body>& b, const Vector3r& v1, const Vector3r& v2, const Vector3r& v3) {
 	Vector3r center = inscribedCircleCenter(v1,v2,v3);
@@ -455,7 +421,7 @@
 	py::def("getSpheresMass",Shop__getSpheresMass,(py::arg("mask")=-1),"Compute the total mass of spheres in the simulation (might crash for now if dynamic bodies are not spheres), mask parameter is considered");
 	py::def("porosity",Shop__getPorosity,(py::arg("volume")=-1),"Compute packing porosity $\\frac{V-V_s}{V}$ where $V$ is overall volume and $V_s$ is volume of spheres.\n\n:param float volume: overall volume $V$. For periodic simulations, current volume of the :yref:`Cell` is used. For aperiodic simulations, the value deduced from utils.aabbDim() is used. For compatibility reasons, positive values passed by the user are also accepted in this case.\n");
 	py::def("voxelPorosity",Shop__getVoxelPorosity,(py::arg("resolution")=200,py::arg("start")=Vector3r(0,0,0),py::arg("end")=Vector3r(0,0,0)),"Compute packing porosity $\\frac{V-V_v}{V}$ where $V$ is a specified volume (from start to end) and $V_v$ is volume of voxels that fall inside any sphere. The calculation method is to divide whole volume into a dense grid of voxels (at given resolution), and count the voxels that fall inside any of the spheres. This method allows one to calculate porosity in any given sub-volume of a whole sample. It is properly excluding part of a sphere that does not fall inside a specified volume.\n\n:param int resolution: voxel grid resolution, values bigger than resolution=1600 require a 64 bit operating system, because more than 4GB of RAM is used, a resolution=800 will use 500MB of RAM.\n:param Vector3 start: start corner of the volume.\n:param Vector3 end: end corner of the volume.\n");
-	py::def("aabbExtrema",aabbExtrema,(py::arg("cutoff")=0.0,py::arg("centers")=false),"Return coordinates of box enclosing all bodies\n\n:param bool centers: do not take sphere radii in account, only their centroids\n:param float∈〈0…1〉 cutoff: relative dimension by which the box will be cut away at its boundaries.\n\n\n:return: (lower corner, upper corner) as (Vector3,Vector3)\n\n");
+	py::def("aabbExtrema",Shop::aabbExtrema,(py::arg("cutoff")=0.0,py::arg("centers")=false),"Return coordinates of box enclosing all bodies\n\n:param bool centers: do not take sphere radii in account, only their centroids\n:param float∈〈0…1〉 cutoff: relative dimension by which the box will be cut away at its boundaries.\n\n\n:return: (lower corner, upper corner) as (Vector3,Vector3)\n\n");
 	py::def("ptInAABB",isInBB,"Return True/False whether the point p is within box given by its min and max corners");
 	py::def("negPosExtremeIds",negPosExtremeIds,negPosExtremeIds_overloads(py::args("axis","distFactor"),"Return list of ids for spheres (only) that are on extremal ends of the specimen along given axis; distFactor multiplies their radius so that sphere that do not touch the boundary coordinate can also be returned."));
 	py::def("approxSectionArea",approxSectionArea,"Compute area of convex hull when when taking (swept) spheres crossing the plane at coord, perpendicular to axis.");

=== added file 'py/_utils.hpp'
--- py/_utils.hpp	1970-01-01 00:00:00 +0000
+++ py/_utils.hpp	2014-10-14 15:52:06 +0000
@@ -0,0 +1,148 @@
+#include<yade/pkg/dem/Shop.hpp>
+#include<yade/core/Scene.hpp>
+#include<yade/core/Omega.hpp>
+#include<yade/pkg/dem/ScGeom.hpp>
+#include<yade/pkg/dem/DemXDofGeom.hpp>
+#include<yade/pkg/common/Facet.hpp>
+#include<yade/pkg/dem/Tetra.hpp>
+#include<yade/pkg/common/Sphere.hpp>
+#include<yade/pkg/common/NormShearPhys.hpp>
+#include<yade/lib/computational-geometry/Hull2d.hpp>
+#include<yade/lib/pyutil/doc_opts.hpp>
+#include<yade/pkg/dem/ViscoelasticPM.hpp>
+
+#include<numpy/ndarrayobject.h>
+
+namespace py = boost::python;
+
+bool isInBB(Vector3r p, Vector3r bbMin, Vector3r bbMax);
+
+py::tuple negPosExtremeIds(int axis, Real distFactor=1.1);
+
+BOOST_PYTHON_FUNCTION_OVERLOADS(negPosExtremeIds_overloads,negPosExtremeIds,1,2);
+
+py::tuple coordsAndDisplacements(int axis,py::tuple Aabb=py::tuple());
+
+void setRefSe3();
+
+Real PWaveTimeStep();
+Real RayleighWaveTimeStep();
+
+py::tuple interactionAnglesHistogram(int axis, int mask=0, size_t bins=20, py::tuple aabb=py::tuple(), Real minProjLen=1e-6);
+BOOST_PYTHON_FUNCTION_OVERLOADS(interactionAnglesHistogram_overloads,interactionAnglesHistogram,1,4);
+
+py::tuple bodyNumInteractionsHistogram(py::tuple aabb=py::tuple());
+BOOST_PYTHON_FUNCTION_OVERLOADS(bodyNumInteractionsHistogram_overloads,bodyNumInteractionsHistogram,0,1);
+
+Vector3r inscribedCircleCenter(const Vector3r& v0, const Vector3r& v1, const Vector3r& v2);
+py::dict getViscoelasticFromSpheresInteraction(Real tc, Real en, Real es);
+
+/* reset highlight of all bodies */
+void highlightNone();
+
+/*!Sum moments acting on given bodies
+ *
+ * @param ids is the calculated bodies ids
+ * @param axis is the direction of axis with respect to which the moment is calculated.
+ * @param axisPt is a point on the axis.
+ *
+ * The computation is trivial: moment from force is is by definition r×F, where r
+ * is position relative to axisPt; moment from moment is m; such moment per body is
+ * projected onto axis.
+ */
+Real sumTorques(py::list ids, const Vector3r& axis, const Vector3r& axisPt);
+
+/* Sum forces acting on bodies within mask.
+ *
+ * @param ids list of ids
+ * @param direction direction in which forces are summed
+ *
+ */
+Real sumForces(py::list ids, const Vector3r& direction);
+
+/* Sum force acting on facets given by their ids in the sense of their respective normals.
+   If axis is given, it will sum forces perpendicular to given axis only (not the the facet normals).
+*/
+Real sumFacetNormalForces(vector<Body::id_t> ids, int axis=-1);
+
+/* Set wire display of all/some/none bodies depending on the filter. */
+void wireSome(string filter);
+void wireAll();
+void wireNone();
+void wireNoSpheres();
+
+
+/* Tell us whether a point lies in polygon given by array of points.
+ *  @param xy is the point that is being tested
+ *  @param vertices is Numeric.array (or list or tuple) of vertices of the polygon.
+ *         Every row of the array is x and y coordinate, numer of rows is >= 3 (triangle).
+ *
+ * Copying the algorithm from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
+ * is gratefully acknowledged:
+ *
+ * License to Use:
+ * Copyright (c) 1970-2003, Wm. Randolph Franklin
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers.
+ *   2. Redistributions in binary form must reproduce the above copyright notice in the documentation and/or other materials provided with the distribution.
+ *   3. The name of W. Randolph Franklin may not be used to endorse or promote products derived from this Software without specific prior written permission. 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://numpy.scipy.org/numpydoc/numpy-13.html told me how to use Numeric.array from c
+ */
+bool pointInsidePolygon(py::tuple xy, py::object vertices);
+
+/* Compute area of convex hull when when taking (swept) spheres crossing the plane at coord, perpendicular to axis.
+
+	All spheres that touch the plane are projected as hexagons on their circumference to the plane.
+	Convex hull from this cloud is computed.
+	The area of the hull is returned.
+
+*/
+Real approxSectionArea(Real coord, int axis);
+
+/* Find all interactions deriving from NormShearPhys that cross plane given by a point and normal
+	(the normal may not be normalized in this case, though) and sum forces (both normal and shear) on them.
+	
+	Returns a 3-tuple with the components along global x,y,z axes, which can be viewed as "action from lower part, towards
+	upper part" (lower and upper parts with respect to the plane's normal).
+
+	(This could be easily extended to return sum of only normal forces or only of shear forces.)
+*/
+Vector3r forcesOnPlane(const Vector3r& planePt, const Vector3r&  normal);
+
+/* Less general than forcesOnPlane, computes force on plane perpendicular to axis, passing through coordinate coord. */
+Vector3r forcesOnCoordPlane(Real coord, int axis);
+
+py::tuple spiralProject(const Vector3r& pt, Real dH_dTheta, int axis=2, Real periodStart=std::numeric_limits<Real>::quiet_NaN(), Real theta0=0);
+
+shared_ptr<Interaction> Shop__createExplicitInteraction(Body::id_t id1, Body::id_t id2);
+
+Real Shop__unbalancedForce(bool useMaxForce /*false by default*/);
+py::tuple Shop__totalForceInVolume();
+Real Shop__getSpheresVolume(int mask=-1);
+Real Shop__getSpheresMass(int mask=-1);
+py::object Shop__kineticEnergy(bool findMaxId=false);
+
+Real maxOverlapRatio();
+
+Real Shop__getPorosity(Real volume=-1);
+Real Shop__getVoxelPorosity(int resolution=200, Vector3r start=Vector3r(0,0,0),Vector3r end=Vector3r(0,0,0));
+
+//Matrix3r Shop__stressTensorOfPeriodicCell(bool smallStrains=false){return Shop::stressTensorOfPeriodicCell(smallStrains);}
+py::tuple Shop__fabricTensor(bool splitTensor=false, bool revertSign=false, Real thresholdForce=NaN);
+py::tuple Shop__normalShearStressTensors(bool compressionPositive=false, bool splitNormalTensor=false, Real thresholdForce=NaN);
+
+py::list Shop__getStressLWForEachBody();
+
+py::list Shop__getBodyIdsContacts(Body::id_t bodyID=-1);
+
+Real shiftBodies(py::list ids, const Vector3r& shift);
+
+void Shop__calm(int mask=-1);
+
+void setNewVerticesOfFacet(const shared_ptr<Body>& b, const Vector3r& v1, const Vector3r& v2, const Vector3r& v3);
+
+py::list intrsOfEachBody();
+
+py::list numIntrsOfEachBody();