yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #11240
[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.")