← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 4153: remove pack.particleSD and variants, unmaintained and deprecated by makeCloud (functions kept tem...

 

------------------------------------------------------------
revno: 4153
committer: Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
timestamp: Wed 2014-09-03 17:59:54 +0200
message:
  remove pack.particleSD and variants, unmaintained and deprecated by makeCloud (functions kept temporarily but returning error)
modified:
  doc/sphinx/tutorial/06-periodic-triaxial-test.py
  pkg/dem/SpherePack.cpp
  py/pack/_packSpheres.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 'doc/sphinx/tutorial/06-periodic-triaxial-test.py'
--- doc/sphinx/tutorial/06-periodic-triaxial-test.py	2013-03-08 15:05:59 +0000
+++ doc/sphinx/tutorial/06-periodic-triaxial-test.py	2014-09-03 15:59:54 +0000
@@ -35,10 +35,6 @@
 if 0:
 	## uniform distribution
 	sp.makeCloud((0,0,0),(2,2,2),rMean=.1,rRelFuzz=.3,periodic=True)
-elif 0:
-	## per-fraction distribution
-	## passing: cummulative percentage
-	sp.particleSD2(radii=[.09,.1,.2],passing=[40,80,100],periodic=True,numSph=1000)
 else:
 	## create packing from clumps
 	# configuration of one clump

=== modified file 'pkg/dem/SpherePack.cpp'
--- pkg/dem/SpherePack.cpp	2014-07-03 07:16:58 +0000
+++ pkg/dem/SpherePack.cpp	2014-09-03 15:59:54 +0000
@@ -272,156 +272,21 @@
 	return py::make_tuple(edges,cumm);
 }
 
-/* possible enhacement: proportions parameter, so that the domain is not cube, but box with sides having given proportions */
+
 long SpherePack::particleSD2(const vector<Real>& radii, const vector<Real>& passing, int numSph, bool periodic, Real cloudPorosity, int seed){
-	typedef Eigen::Matrix<Real,Eigen::Dynamic,Eigen::Dynamic> MatrixXr;
-	typedef Eigen::Matrix<Real,Eigen::Dynamic,1> VectorXr;
-	
-	int dim=radii.size()+1;
-	if(passing.size()!=radii.size()) throw std::invalid_argument("SpherePack.particleSD2: radii and passing must have the same length.");
-	MatrixXr M=MatrixXr::Zero(dim,dim);
-	VectorXr rhs=VectorXr::Zero(dim);
-	/*
-	
-	We know percentages for each fraction (Δpi) and their radii (ri), and want to find
-	the number of sphere for each fraction Ni and total solid volume Vs. For each fraction,
-	we know that the volume is equal to Ni*(4/3*πri³), which must be equal to Vs*Δpi (Δpi is
-	relative solid volume of the i-th fraction).
-
-	The last equation says that total number of particles (sum of fractions) is equal to N,
-	which is the total number of particles requested by the user.
-
-	   N1     N2     N3    Vs       rhs
-
-	4/3πr₁³   0      0     -Δp₁   | 0
-	  0     4/3πr₂³  0     -Δp₂   | 0
-	  0       0    4/3πr₃³ -Δp₃   | 0
-     1       1      1      0     | N
-
-	*/
-	for(int i=0; i<dim-1; i++){
-		M(i,i)=(4/3.)*Mathr::PI*pow(radii[i],3);
-		M(i,dim-1)=-(passing[i]-(i>0?passing[i-1]:0))/100.;
-		M(dim-1,i)=1;
-	}
-	rhs[dim-1]=numSph;
-	// NumsVs=M^-1*rhs: number of spheres and volume of solids
-	VectorXr NumsVs(dim); NumsVs=M.inverse()*rhs;
-	Real Vs=NumsVs[dim-1]; // total volume of solids
-	Real Vtot=Vs/(1-cloudPorosity); // total volume of cell containing the packing
-	Vector3r cellSize=pow(Vtot,1/3.)*Vector3r().Ones(); // for now, assume always cubic sample
-	Real rMean=pow(Vs/(numSph*(4/3.)*Mathr::PI),1/3.); // make rMean such that particleSD will compute the right Vs (called a bit confusingly Vtot anyway) inversely
-	// cerr<<"Vs="<<Vs<<", Vtot="<<Vtot<<", rMean="<<rMean<<endl;
-	// cerr<<"cellSize="<<cellSize<<", rMean="<<rMean<<", numSph="<<numSph<<endl;
-	return particleSD(Vector3r::Zero(),cellSize,rMean,periodic,"",numSph,radii,passing,false);
+	//deprecated (https://bugs.launchpad.net/yade/+bug/1024443)
+	LOG_ERROR("particleSD2() has been removed. Please use makeCloud() instead.");
 };
 
-// TODO: header, python wrapper, default params
-
 // Discrete particle size distribution
 long SpherePack::particleSD(Vector3r mn, Vector3r mx, Real rMean, bool periodic, string name, int numSph, const vector<Real>& radii, const vector<Real>& passing, bool passingIsNotPercentageButCount, int seed){
-	vector<Real> numbers;
-	if(!passingIsNotPercentageButCount){
-		Real Vtot=numSph*4./3.*Mathr::PI*pow(rMean,3.); // total volume of the packing (computed with rMean)
-		
-		// calculate number of spheres necessary per each radius to match the wanted psd
-		// passing has to contain increasing values
-		for (size_t i=0; i<radii.size(); i++){
-			Real volS=4./3.*Mathr::PI*pow(radii[i],3.);
-			if (i==0) {numbers.push_back(passing[i]/100.*Vtot/volS);}
-			else {numbers.push_back((passing[i]-passing[i-1])/100.*Vtot/volS);} // 
-			cout<<"fraction #"<<i<<" ("<<passing[i]<<"%, r="<<radii[i]<<"): "<<numbers[i]<<" spheres, fraction/cloud volumes "<<volS<<"/"<<Vtot<<endl;
-		}
-	} else {
-		FOREACH(Real p, passing) numbers.push_back(p);
-	}
-
-	static boost::minstd_rand randGen(seed!=0?seed:(int)TimingInfo::getNow(true));
-	static boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > rnd(randGen, boost::uniform_real<>(0,1));
-
-	const int maxTry=1000;
-	Vector3r size=mx-mn;
-	if(periodic)(cellSize=size);
-	for (int ii=(int)radii.size()-1; ii>=0; ii--){
-		Real r=radii[ii]; // select radius
-		for(int i=0; i<numbers[ii]; i++) { // place as many spheres as required by the psd for the selected radius into the free spot
-			int t;
-			for(t=0; t<maxTry; ++t){
-				Vector3r c;
-				if(!periodic) { for(int axis=0; axis<3; axis++) c[axis]=mn[axis]+r+(size[axis]-2*r)*rnd(); }
-				else { for(int axis=0; axis<3; axis++) c[axis]=mn[axis]+size[axis]*rnd(); }
-				size_t packSize=pack.size(); bool overlap=false;
-				if(!periodic){
-					for(size_t j=0; j<packSize; j++){ if(pow(pack[j].r+r,2) >= (pack[j].c-c).squaredNorm()) { overlap=true; break; } }
-				} else {
-					for(size_t j=0; j<packSize; j++){
-						Vector3r dr;
-						for(int axis=0; axis<3; axis++) dr[axis]=min(cellWrapRel(c[axis],pack[j].c[axis],pack[j].c[axis]+size[axis]),cellWrapRel(pack[j].c[axis],c[axis],c[axis]+size[axis]));
-						if(pow(pack[j].r+r,2)>= dr.squaredNorm()){ overlap=true; break; }
-					}
-				}
-				if(!overlap) { pack.push_back(Sph(c,r)); break; }
-			}
-			if (t==maxTry) {
-				if(numbers[ii]>0) LOG_WARN("Exceeded "<<maxTry<<" tries to insert non-overlapping sphere to packing. Only "<<i<<" spheres were added, although you requested "<<numbers[ii]<<" with radius "<<radii[ii]);
-				return i;
-			}
-		}
-	}
-	return pack.size();
+	//deprecated (https://bugs.launchpad.net/yade/+bug/1024443)
+	LOG_ERROR("particleSD() has been removed. Please use makeCloud() instead.");
 }
 
-// 2d function
 long SpherePack::particleSD_2d(Vector2r mn, Vector2r mx, Real rMean, bool periodic, string name, int numSph, const vector<Real>& radii, const vector<Real>& passing, bool passingIsNotPercentageButCount, int seed){
-	vector<Real> numbers;
-	if(!passingIsNotPercentageButCount){
-		Real Vtot=numSph*4./3.*Mathr::PI*pow(rMean,3.); // total volume of the packing (computed with rMean)
-		
-		// calculate number of spheres necessary per each radius to match the wanted psd
-		// passing has to contain increasing values
-		for (size_t i=0; i<radii.size(); i++){
-			Real volS=4./3.*Mathr::PI*pow(radii[i],3.);
-			if (i==0) {numbers.push_back(passing[i]/100.*Vtot/volS);}
-			else {numbers.push_back((passing[i]-passing[i-1])/100.*Vtot/volS);} // 
-			cout<<"fraction #"<<i<<" ("<<passing[i]<<"%, r="<<radii[i]<<"): "<<numbers[i]<<" spheres, fraction/cloud volumes "<<volS<<"/"<<Vtot<<endl;
-		}
-	} else {
-		FOREACH(Real p, passing) numbers.push_back(p);
-	}
-
-	static boost::minstd_rand randGen(seed!=0?seed:(int)TimingInfo::getNow(true));
-	static boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > rnd(randGen, boost::uniform_real<>(0,1));
-
-	const int maxTry=1000;
-	Vector2r size=mx-mn; 
-	//if(periodic)(cellSize=size); in this case, it must be defined in py script as cell needs the third dimension
-	for (int ii=(int)radii.size()-1; ii>=0; ii--){
-		Real r=radii[ii]; // select radius
-		for(int i=0; i<numbers[ii]; i++) { // place as many spheres as required by the psd for the selected radius into the free spot
-			int t;
-			for(t=0; t<maxTry; ++t){
-				Vector3r c;
-				if(!periodic) { for(int axis=0; axis<2; axis++) c[axis]=mn[axis]+r+(size[axis]-2*r)*rnd(); }
-				else { for(int axis=0; axis<2; axis++) c[axis]=mn[axis]+size[axis]*rnd(); }
-				size_t packSize=pack.size(); bool overlap=false;
-				if(!periodic){
-					for(size_t j=0; j<packSize; j++){ if(pow(pack[j].r+r,2) >= (pack[j].c-c).squaredNorm()) { overlap=true; break; } }
-				} else {
-					for(size_t j=0; j<packSize; j++){
-						Vector3r dr=Vector3r::Zero();
-						for(int axis=0; axis<2; axis++) dr[axis]=min(cellWrapRel(c[axis],pack[j].c[axis],pack[j].c[axis]+size[axis]),cellWrapRel(pack[j].c[axis],c[axis],c[axis]+size[axis]));
-						if(pow(pack[j].r+r,2)>= dr.squaredNorm()){ overlap=true; break; }
-					}
-				}
-				if(!overlap) { pack.push_back(Sph(c,r)); break; }
-			}
-			if (t==maxTry) {
-				if(numbers[ii]>0) LOG_WARN("Exceeded "<<maxTry<<" tries to insert non-overlapping sphere to packing. Only "<<i<<" spheres were added, although you requested "<<numbers[ii]<<" with radius "<<radii[ii]);
-				return i;
-			}
-		}
-	}
-	return pack.size();
+	//deprecated (https://bugs.launchpad.net/yade/+bug/1024443)
+	LOG_ERROR("particleSD_2d() has been removed. Please use makeCloud() instead.");
 }
 
 long SpherePack::makeClumpCloud(const Vector3r& mn, const Vector3r& mx, const vector<shared_ptr<SpherePack> >& _clumps, bool periodic, int num, int seed){

=== modified file 'py/pack/_packSpheres.cpp'
--- py/pack/_packSpheres.cpp	2014-05-23 13:03:50 +0000
+++ py/pack/_packSpheres.cpp	2014-09-03 15:59:54 +0000
@@ -15,17 +15,19 @@
 		.def("load",&SpherePack::fromFile,(boost::python::arg("fileName")),"Load packing from external text file (current data will be discarded).")
 		.def("save",&SpherePack::toFile,(boost::python::arg("fileName")),"Save packing to external text file (will be overwritten).")
 		.def("fromSimulation",&SpherePack::fromSimulation,"Make packing corresponding to the current simulation. Discards current data.")
+		//The basic sphere generator
 		.def("makeCloud",&SpherePack::makeCloud,(boost::python::arg("minCorner")=Vector3r(Vector3r::Zero()),boost::python::arg("maxCorner")=Vector3r(Vector3r::Zero()),boost::python::arg("rMean")=-1,boost::python::arg("rRelFuzz")=0,boost::python::arg("num")=-1,boost::python::arg("periodic")=false,boost::python::arg("porosity")=0.65,boost::python::arg("psdSizes")=vector<Real>(),boost::python::arg("psdCumm")=vector<Real>(),boost::python::arg("distributeMass")=false,boost::python::arg("seed")=0,boost::python::arg("hSize")=Matrix3r(Matrix3r::Zero())),"Create random loose packing enclosed in a parallelepiped (also works in 2D if minCorner[k]=maxCorner[k] for one coordinate)."
 		"\nSphere radius distribution can be specified using one of the following ways:\n\n#. *rMean*, *rRelFuzz* and *num* gives uniform radius distribution in *rMean×(1 ± rRelFuzz)*. Less than *num* spheres can be generated if it is too high.\n#. *rRelFuzz*, *num* and (optional) *porosity*, which estimates mean radius so that *porosity* is attained at the end.  *rMean* must be less than 0 (default). *porosity* is only an initial guess for the generation algorithm, which will retry with higher porosity until the prescibed *num* is obtained.\n#. *psdSizes* and *psdCumm*, two arrays specifying points of the `particle size distribution <http://en.wikipedia.org/wiki/Particle_size_distribution>`__ function. As many spheres as possible are generated.\n#. *psdSizes*, *psdCumm*, *num*, and (optional) *porosity*, like above but if *num* is not obtained, *psdSizes* will be scaled down uniformly, until *num* is obtained (see :yref:`appliedPsdScaling<yade._packSpheres.SpherePack.appliedPsdScaling>`).\n\nBy default (with ``distributeMass==False``), the distribution is applied to particle radii. The usual sense of \"particle size distribution\" is the distribution of *mass fraction* (rather than particle count); this can be achieved with ``distributeMass=True``."
 		"\n\nIf *num* is defined, then sizes generation is deterministic, giving the best fit of target distribution. It enables spheres placement in descending size order, thus giving lower porosity than the random generation."
 		"\n\n:param Vector3 minCorner: lower corner of an axis-aligned box\n:param Vector3 maxCorner: upper corner of an axis-aligned box\n:param Matrix3 hSize: base vectors of a generalized box (arbitrary parallelepiped, typically :yref:`Cell::hSize`), superseeds minCorner and maxCorner if defined. For periodic boundaries only.\n:param float rMean: mean radius or spheres\n:param float rRelFuzz: dispersion of radius relative to rMean\n:param int num: number of spheres to be generated. If negavite (default), generate as many as possible with stochastic sizes, ending after a fixed number of tries to place the sphere in space, else generate exactly *num* spheres with deterministic size distribution.\n:param bool periodic: whether the packing to be generated should be periodic\n:param float porosity: initial guess for the iterative generation procedure (if *num*>1). The algorithm will be retrying until the number of generated spheres is *num*. The first iteration tries with the provided porosity, but next iterations increase it if necessary (hence an initialy high porosity can speed-up the algorithm). If *psdSizes* is not defined, *rRelFuzz* ($z$) and *num* ($N$) are used so that the porosity given ($\\rho$) is approximately achieved at the end of generation, $r_m=\\sqrt[3]{\\frac{V(1-\\rho)}{\\frac{4}{3}\\pi(1+z^2)N}}$. The default is $\\rho$=0.5. The optimal value depends on *rRelFuzz* or  *psdSizes*.\n:param psdSizes: sieve sizes (particle diameters) when particle size distribution (PSD) is specified\n:param psdCumm: cummulative fractions of particle sizes given by *psdSizes*; must be the same length as *psdSizes* and should be non-decreasing\n:param bool distributeMass: if ``True``, given distribution will be used to distribute sphere's mass rather than radius of them.\n:param seed: number used to initialize the random number generator.\n:returns: number of created spheres, which can be lower than *num* depending on the method used.\n")
 		.def("psd",&SpherePack::psd,(boost::python::arg("bins")=50,boost::python::arg("mass")=true),"Return `particle size distribution <http://en.wikipedia.org/wiki/Particle_size_distribution>`__ of the packing.\n:param int bins: number of bins between minimum and maximum diameter\n:param mass: Compute relative mass rather than relative particle count for each bin. Corresponds to :yref:`distributeMass parameter for makeCloud<yade.pack.SpherePack.makeCloud>`.\n:returns: tuple of ``(cumm,edges)``, where ``cumm`` are cummulative fractions for respective diameters  and ``edges`` are those diameter values. Dimension of both arrays is equal to ``bins+1``.")
-		// new psd
-		.def("particleSD",&SpherePack::particleSD,(boost::python::arg("minCorner"),boost::python::arg("maxCorner"),boost::python::arg("rMean"),boost::python::arg("periodic")=false,boost::python::arg("name"),boost::python::arg("numSph"),boost::python::arg("radii")=vector<Real>(),boost::python::arg("passing")=vector<Real>(),boost::python::arg("passingIsNotPercentageButCount")=false, boost::python::arg("seed")=0),"Create random packing enclosed in box given by minCorner and maxCorner, containing numSph spheres. Returns number of created spheres, which can be < num if the packing is too tight. The computation is done according to the given psd.")
-		.def("particleSD2",&SpherePack::particleSD2,(boost::python::arg("radii"),boost::python::arg("passing"),boost::python::arg("numSph"),boost::python::arg("periodic")=false,boost::python::arg("cloudPorosity")=.8,boost::python::arg("seed")=0),"Create random packing following the given particle size distribution (radii and volume/mass passing for each fraction) and total number of particles *numSph*. The cloud size (periodic or aperiodic) is computed from the PSD and is always cubic.")
-		.def("particleSD_2d",&SpherePack::particleSD_2d,(boost::python::arg("minCorner"),boost::python::arg("maxCorner"),boost::python::arg("rMean"),boost::python::arg("periodic")=false,boost::python::arg("name"),boost::python::arg("numSph"),boost::python::arg("radii")=vector<Real>(),boost::python::arg("passing")=vector<Real>(),boost::python::arg("passingIsNotPercentageButCount")=false,boost::python::arg("seed")=0),"Create random packing on XY plane, defined by minCorner and maxCorner, containing numSph spheres. Returns number of created spheres, which can be < num if the packing is too tight. The computation is done according to the given psd.")
-
+		//The variant for clumps
 		.def("makeClumpCloud",&SpherePack::makeClumpCloud,(boost::python::arg("minCorner"),boost::python::arg("maxCorner"),boost::python::arg("clumps"),boost::python::arg("periodic")=false,boost::python::arg("num")=-1,boost::python::arg("seed")=0),"Create random loose packing of clumps within box given by *minCorner* and *maxCorner*. Clumps are selected with equal probability. At most *num* clumps will be positioned if *num* is positive; otherwise, as many clumps as possible will be put in space, until maximum number of attempts to place a new clump randomly is attained.\n:param seed: number used to initialize the random number generator.")
+		// old unmaintained stuff, kept for the moment so it at least returns an error message
+		.def("particleSD",&SpherePack::particleSD,(boost::python::arg("minCorner"),boost::python::arg("maxCorner"),boost::python::arg("rMean"),boost::python::arg("periodic")=false,boost::python::arg("name"),boost::python::arg("numSph"),boost::python::arg("radii")=vector<Real>(),boost::python::arg("passing")=vector<Real>(),boost::python::arg("passingIsNotPercentageButCount")=false, boost::python::arg("seed")=0),"Not working. Use makeCloud instead.")
+		.def("particleSD2",&SpherePack::particleSD2,(boost::python::arg("radii"),boost::python::arg("passing"),boost::python::arg("numSph"),boost::python::arg("periodic")=false,boost::python::arg("cloudPorosity")=.8,boost::python::arg("seed")=0),"Not working. Use makeCloud instead.")
+		.def("particleSD_2d",&SpherePack::particleSD_2d,(boost::python::arg("minCorner"),boost::python::arg("maxCorner"),boost::python::arg("rMean"),boost::python::arg("periodic")=false,boost::python::arg("name"),boost::python::arg("numSph"),boost::python::arg("radii")=vector<Real>(),boost::python::arg("passing")=vector<Real>(),boost::python::arg("passingIsNotPercentageButCount")=false,boost::python::arg("seed")=0),"Not working. Use makeCloud instead.")
+		
 		//
 		.def("aabb",&SpherePack::aabb_py,"Get axis-aligned bounding box coordinates, as 2 3-tuples.")
 		.def("dim",&SpherePack::dim,"Return dimensions of the packing in terms of aabb(), as a 3-tuple.")