← Back to team overview

yade-users team mailing list archive

Function for sphere packing


Hello all,

I think some of you (Yuannian, Lionel,...) will be interested by the 
function "GenerateCloud" I have pasted at the end of this post, which 
generate a cloud of non-overlapping spheres inside a box (thanks to the 
number generator from Janek;)).
I use it in the triaxial test file generator, but I have not made it a 
member of TriaxialTest, so that it is easy to re-use by simply copy-paste.

The number of generated sphere can be arbitrary high. However, if you 
require a porosity that is too low (~less than 0.7), the number of 
grains will be less than "number".

It can be used this way (this is a code from TriaxialTest::generate()):

shared_ptr<Body> body;
    vector<BasicSphere> sphere_list;
    string output = GenerateCloud(sphere_list, lowerCorner, upperCorner, 
numberOfGrains, 0.3, 0.7);
    vector<BasicSphere>::iterator it = sphere_list.begin();
    vector<BasicSphere>::iterator it_end = sphere_list.end();
    for (;it!=it_end; ++it)
        cerr << "sphere (" << it->first << " " << it->second << endl;

Using this fonction together with TriaxialStressController, it is now 
possible to generate compact random assemblies in Yade :).
I am not completly satisfied by this method, so all this is still in 

BTW (Janek?...):
1) I want to increase the radii of spheres during the simulation, is it 
enough to multiply the radius by "r" and the size of the bounding boxes 
by the same "r"??
2) Is the group-mask stuff working currently?


// random
#include <boost/random/linear_congruential.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/normal_distribution.hpp>

using namespace boost;
using namespace std;

typedef pair<Vector3r, Real> BasicSphere;
//! make a list of spheres non-overlapping sphere
string GenerateCloud(vector<BasicSphere>& sphere_list, Vector3r 
lowerCorner, Vector3r upperCorner, long number, Real rad_std_dev, Real 

string GenerateCloud(vector<BasicSphere>& sphere_list, Vector3r 
lowerCorner, Vector3r upperCorner, long number, Real rad_std_dev, Real 
    typedef boost::minstd_rand StdGenerator;
    static StdGenerator generator;
    static boost::variate_generator<StdGenerator&, boost::uniform_real<> >
            random1(generator, boost::uniform_real<>(0,1));
        //         static boost::variate_generator<StdGenerator&, 
boost::normal_distribution<> >
        //         randomN(generator, 

    long tries = 1000; //nb of tries for positionning the next sphere
    Vector3r dimensions = upperCorner - lowerCorner;
    Real mean_radius = 
        //cerr << mean_radius;

    std::cerr << "generating aggregates ... ";
    long t, i;
    for (i=0; i<number; ++i) {
        BasicSphere s;
        for (t=0; t<tries; ++t) {
            s.second = (random1()-0.5)*rad_std_dev*mean_radius+mean_radius;
            s.first.x() = 
            s.first.y() = 
            s.first.z() = 
            bool overlap=false;
            for (long j=0; (j<i && !overlap); j++)
                if ( pow(sphere_list[j].second+s.second, 2) > 
(sphere_list[j].first-s.first).squaredLength()) overlap=true;
            if (!overlap)
        if (t==tries) return "More than " + lexical_cast<string>(tries) +
                    " tries while generating sphere number " +
                    lexical_cast<string>(i+1) + "/" + 
lexical_cast<string>(number) + ".";
    return "Generated a sample with " + lexical_cast<string>(number) + 
"spheres inside box of dimensions: ("
            + lexical_cast<string>(dimensions[0]) + ","
            + lexical_cast<string>(dimensions[1]) + ","
            + lexical_cast<string>(dimensions[2]) + ").";

Chareyre Bruno
Maître de conférence

Institut National Polytechnique de Grenoble
Laboratoire 3S (Soils Solids Structures) - bureau I08
BP 53 - 38041, Grenoble cedex 9 - France     
Tél :

Yade-users mailing list

Follow ups