Author: eudoxos
Date: 2009-08-10 13:32:23 +0200 (Mon, 10 Aug 2009)
New Revision: 1933
Added:
trunk/pkg/dem/DataClass/SpherePack.cpp
trunk/pkg/dem/DataClass/SpherePack.hpp
trunk/scripts/test/periodic-compress.py
Modified:
trunk/extra/PeriodicInsertionSortCollider.cpp
trunk/extra/PeriodicInsertionSortCollider.hpp
trunk/extra/SConscript
trunk/lib/SConscript
trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.cpp
trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.hpp
trunk/pkg/dem/meta/Shop.cpp
trunk/pkg/dem/meta/Shop.hpp
trunk/py/SConscript
trunk/py/_packSpheres.cpp
trunk/py/_utils.cpp
trunk/py/yadeWrapper/yadeWrapper.cpp
trunk/scripts/test/periodic-grow.py
Log:
1. Add PeriIsoCompressor for periodic isotropic compression; see
scripts/test/periodic-compress.py. Not so much slower than regular triax, nice
surprise.
2. Make SpherePack standalone class (previously just in python's _packSpheres),
add the function to generate cloud of spheres, both periodic and non-periodic.
_packSpheres wrapper is update, but otherwise not changed.
3. Fix python-less compilation for se3 interpolator engine
4. Add Omega().runEngine()
5. Fix some compilation/linking issues.
Modified: trunk/extra/PeriodicInsertionSortCollider.cpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-09 17:17:53 UTC
(rev 1932)
+++ trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-10 11:32:23 UTC
(rev 1933)
@@ -16,7 +16,7 @@
using namespace std;
-YADE_PLUGIN((PeriodicInsertionSortCollider))
+YADE_PLUGIN((PeriodicInsertionSortCollider)(PeriIsoCompressor))
CREATE_LOGGER(PeriodicInsertionSortCollider);
// return floating value wrapped between x0 and x1 and saving period number to
period
@@ -348,3 +348,70 @@
}
}
}
+
+
+
+
+
+/***********************************************************************************************************
+******************************* PeriIsoCompressor
*********************************************************/
+#include<yade/pkg-dem/Shop.hpp>
+
+
+CREATE_LOGGER(PeriIsoCompressor);
+void PeriIsoCompressor::action(MetaBody* rb){
+ if(!rb->isPeriodic){ LOG_FATAL("Being used on non-periodic
simulation!"); throw; }
+ if(state>=stresses.size()) return;
+ // initialize values
+ if(charLen<0){
+ BoundingVolume* bv=Body::byId(0,rb)->boundingVolume.get();
+ if(!bv){ LOG_FATAL("No charLen defined and body #0 has no
boundingVolume"); throw; }
+ const Vector3r sz=bv->max-bv->min;
+ charLen=(sz[0]+sz[1]+sz[2])/3.;
+ LOG_INFO("No charLen defined, taking avg bbox size of body #0 =
"<<charLen);
+ }
+ if(maxDisplPerStep<0) maxDisplPerStep=1e-2*charLen; // this should be
tuned somehow…
+ const long& step=rb->currentIteration;
+ Vector3r cellSize=rb->cellMax-rb->cellMin; //unused: Real
cellVolume=cellSize[0]*cellSize[1]*cellSize[2];
+ Vector3r
cellArea=Vector3r(cellSize[1]*cellSize[2],cellSize[0]*cellSize[2],cellSize[0]*cellSize[1]);
+ if(((step%globalUpdateInt)==0) || avgStiffness<0 || sigma[0]<0 ||
sigma[1]<0 || sigma[2]<0){
+ Vector3r sumForces=Shop::totalForceInVolume(avgStiffness,rb);
+
sigma=Vector3r(sumForces[0]/cellArea[0],sumForces[1]/cellArea[1],sumForces[2]/cellArea[2]);
+ LOG_TRACE("Updated sigma="<<sigma<<",
avgStiffness="<<avgStiffness);
+ }
+ Real sigmaGoal=stresses[state]; assert(sigmaGoal>0);
+ // expansion of cell in this step (absolute length)
+ Vector3r cellGrow(Vector3r::ZERO);
+ // is the stress condition satisfied in all directions?
+ bool allStressesOK=true;
+ Vector3r cg_;
+ for(int axis=0; axis<3; axis++){
+ // Δσ=ΔεE=(Δl/l)×(l×K/A) ↔ Δl=Δσ×A/K
+ // FIXME: either NormalShearInteraction::{kn,ks} is computed
wrong or we have dimensionality problem here
+ // FIXME: that is why the fixup 1e-2 is needed here
+ // FIXME: or perhaps maxDisplaPerStep=1e-2*charLen is too big??
+
cellGrow[axis]=1e-4*(sigma[axis]-sigmaGoal)*cellArea[axis]/(avgStiffness>0?avgStiffness:1);
+ if(abs(cellGrow[axis])>maxDisplPerStep)
cellGrow[axis]=Mathr::Sign(cellGrow[axis])*maxDisplPerStep;
+ // crude way of predicting sigma, for steps when it is not
computed from intrs
+ if(avgStiffness>0) sigma[axis]-=cellGrow[axis]*avgStiffness;
+ if(abs((sigma[axis]-sigmaGoal)/sigmaGoal)>5e-3)
allStressesOK=false;
+ }
+ TRVAR4(cellGrow,sigma,sigmaGoal,avgStiffness);
+ rb->cellMin-=.5*cellGrow; rb->cellMax+=.5*cellGrow;
+ // handle state transitions
+ if(allStressesOK){
+ if((step%globalUpdateInt)==0)
currUnbalanced=Shop::unbalancedForce(/*useMaxForce=*/false,rb);
+ if(currUnbalanced<maxUnbalanced){
+ state+=1;
+ // sigmaGoal reached and packing stable
+ if(state==stresses.size()){ // no next stress to go for
+ LOG_INFO("Finished");
+ #ifdef YADE_PYTHON
+ if(!doneHook.empty()){
LOG_DEBUG("Running doneHook: "<<doneHook); PyGILState_STATE gstate;
gstate=PyGILState_Ensure(); PyRun_SimpleString(doneHook.c_str());
PyGILState_Release(gstate); }
+ #endif
+ } else { LOG_INFO("Loading to "<<sigmaGoal<<" done,
starting going to "<<stresses[state]<<" now"); }
+ } else {
+ if((step%globalUpdateInt)==0)
LOG_DEBUG("Stress="<<sigma<<", goal="<<sigmaGoal<<",
unbalanced="<<currUnbalanced);
+ }
+ }
+}
Modified: trunk/extra/PeriodicInsertionSortCollider.hpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-09 17:17:53 UTC
(rev 1932)
+++ trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-10 11:32:23 UTC
(rev 1933)
@@ -138,3 +138,29 @@
DECLARE_LOGGER;
};
REGISTER_SERIALIZABLE(PeriodicInsertionSortCollider);
+
+/* Simple engine for compressing random cloud of spheres until
+it reaches given average stress and then goes back to given residual stress
+*/
+class PeriIsoCompressor: public StandAloneEngine{
+ Real avgStiffness; Real maxDisplPerStep; Vector3r sumForces, sigma;
+ public:
+ //! Stresses that should be reached, one after another
+ vector<Real> stresses;
+ //! Characteristic length, should be something like mean particle
diameter (default -1=invalid value))
+ Real charLen;
+ //! if actual unbalanced force is smaller than this number, the packing
is considered stable (default 1e-4)
+ Real maxUnbalanced, currUnbalanced;
+ //! how often to recompute average stress, stiffness and unbalanced
force (default 100)
+ int globalUpdateInt;
+ //! Where are we at in the process
+ size_t state;
+ //! python command to be run when reaching the last specified stress
+ string doneHook;
+ void action(MetaBody*);
+ PeriIsoCompressor(): avgStiffness(-1), maxDisplPerStep(-1),
sumForces(Vector3r::ZERO), sigma(Vector3r::ZERO), charLen(-1),
maxUnbalanced(1e-4), currUnbalanced(-1), globalUpdateInt(100), state(0){}
+
REGISTER_ATTRIBUTES(StandAloneEngine,(stresses)(charLen)(maxUnbalanced)(globalUpdateInt)(state)(doneHook));
+ DECLARE_LOGGER;
+ REGISTER_CLASS_AND_BASE(PeriIsoCompressor,StandAloneEngine);
+};
+REGISTER_SERIALIZABLE(PeriIsoCompressor);
Modified: trunk/extra/SConscript
===================================================================
--- trunk/extra/SConscript 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/extra/SConscript 2009-08-10 11:32:23 UTC (rev 1933)
@@ -6,7 +6,7 @@
import os.path, os
env.Install('$PREFIX/lib/yade$SUFFIX/extra',[
-
env.SharedLibrary('PeriodicInsertionSortCollider',['PeriodicInsertionSortCollider.cpp'],LIBS=env['LIBS']+linkPlugins(['InsertionSortCollider'])),
+
env.SharedLibrary('PeriodicInsertionSortCollider',['PeriodicInsertionSortCollider.cpp'],LIBS=env['LIBS']+linkPlugins(['InsertionSortCollider','Shop'])),
])
Modified: trunk/lib/SConscript
===================================================================
--- trunk/lib/SConscript 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/lib/SConscript 2009-08-10 11:32:23 UTC (rev 1933)
@@ -59,7 +59,7 @@
'factory/ClassFactory.cpp','factory/DynLibManager.cpp','factory/FactoryExceptions.cpp',
'multimethods/Indexable.cpp','multimethods/MultiMethodsExceptions.cpp',
'serialization-xml/XMLFormatManager.cpp','serialization-xml/XMLSaxParser.cpp','serialization/Archive.cpp',
-
'serialization/IOFormatManager.cpp','serialization/IOManagerExceptions.cpp','serialization/FormatChecker.cpp','serialization/Serializable.cpp','serialization/SerializableSingleton.cpp','serialization/SerializationExceptions.cpp']))
+
'serialization/IOFormatManager.cpp','serialization/IOManagerExceptions.cpp','serialization/FormatChecker.cpp','serialization/Serializable.cpp','serialization/SerializableSingleton.cpp','serialization/SerializationExceptions.cpp']),LIBS=['dl'])
#######################
###### 3rd party libs
Modified: trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.cpp
===================================================================
--- trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.cpp 2009-08-09
17:17:53 UTC (rev 1932)
+++ trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.cpp 2009-08-10
11:32:23 UTC (rev 1933)
@@ -31,6 +31,8 @@
if(t>=1.){
done=true;
LOG_DEBUG("Goal reached.");
- if(!goalHook.empty()){ PyGILState_STATE gstate;
gstate=PyGILState_Ensure(); PyRun_SimpleString(goalHook.c_str());
PyGILState_Release(gstate); }
+ #ifdef YADE_PYTHON
+ if(!goalHook.empty()){ PyGILState_STATE gstate;
gstate=PyGILState_Ensure(); PyRun_SimpleString(goalHook.c_str());
PyGILState_Release(gstate); }
+ #endif
}
}
Modified: trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.hpp
===================================================================
--- trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.hpp 2009-08-09
17:17:53 UTC (rev 1932)
+++ trunk/pkg/common/Engine/DeusExMachina/Se3Interpolator.hpp 2009-08-10
11:32:23 UTC (rev 1933)
@@ -4,7 +4,9 @@
#include<yade/core/DeusExMachina.hpp>
#include<yade/core/PhysicalParameters.hpp>
#include<yade/pkg-common/RigidBodyParameters.hpp>
-#include<Python.h>
+#ifdef YADE_PYTHON
+ #include<Python.h>
+#endif
/* Engine interpolating between starting (current) and goal (given) se3, both
position and orientation.
*
Added: trunk/pkg/dem/DataClass/SpherePack.cpp
===================================================================
--- trunk/pkg/dem/DataClass/SpherePack.cpp 2009-08-09 17:17:53 UTC (rev
1932)
+++ trunk/pkg/dem/DataClass/SpherePack.cpp 2009-08-10 11:32:23 UTC (rev
1933)
@@ -0,0 +1,113 @@
+// © 2009 Václav Šmilauer <[email protected]>
+
+#include<yade/pkg-dem/SpherePack.hpp>
+
+#include<yade/core/Omega.hpp>
+#include<yade/core/MetaBody.hpp>
+#include<yade/pkg-common/InteractingSphere.hpp>
+#include<yade/pkg-dem/Shop.hpp>
+
+#include <boost/random/linear_congruential.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/variate_generator.hpp>
+
+#include<yade/core/Timing.hpp>
+
+// not a serializable in the sense of YADE_PLUGIN
+
+CREATE_LOGGER(SpherePack);
+
+using namespace std;
+using namespace boost;
+
+#ifdef YADE_PYTHON
+ // if we need explicit conversions at a few places
+ python::tuple vec2tuple(const Vector3r& v){return
boost::python::make_tuple(v[0],v[1],v[2]);}
+ Vector3r tuple2vec(const python::tuple& t){return
Vector3r(python::extract<double>(t[0])(),python::extract<double>(t[1])(),python::extract<double>(t[2])());}
+ Vector3r tuple2vec(python::tuple& t){return
Vector3r(python::extract<double>(t[0])(),python::extract<double>(t[1])(),python::extract<double>(t[2])());}
+
+ void SpherePack::fromList(const python::list& l){
+ pack.clear();
+ size_t len=python::len(l);
+ for(size_t i=0; i<len; i++){
+ const python::tuple&
t=python::extract<python::tuple>(l[i]);
+ //python::extract<python::tuple> tup(t[0]);
+ //if(tup.check()) {
pack.push_back(Sph(tuple2vec(tup()),python::extract<double>(t[1]))); continue;}
+ python::extract<Vector3r> vec(t[0]);
+ if(vec.check()) {
pack.push_back(Sph(vec(),python::extract<double>(t[1]))); continue; }
+ PyErr_SetString(PyExc_TypeError, "List elements must be
(tuple or Vector3, float)!");
+ python::throw_error_already_set();
+ }
+ };
+
+ python::list SpherePack::toList() const {
+ python::list ret;
+ FOREACH(const Sph& s, pack)
ret.append(python::make_tuple(s.c,s.r));
+ return ret;
+ };
+
+ python::list SpherePack::toList_pointsAsTuples() const {
+ python::list ret;
+ FOREACH(const Sph& s, pack)
ret.append(python::make_tuple(vec2tuple(s.c),s.r));
+ return ret;
+ };
+#endif
+
+void SpherePack::fromFile(string file) {
+ typedef pair<Vector3r,Real> pairVector3rReal;
+ vector<pairVector3rReal> ss;
+ Vector3r mn,mx;
+ ss=Shop::loadSpheresFromFile(file,mn,mx);
+ pack.clear();
+ FOREACH(const pairVector3rReal& s, ss)
pack.push_back(Sph(s.first,s.second));
+}
+
+void SpherePack::toFile(const string fname) const {
+ ofstream f(fname.c_str());
+ if(!f.good()) throw runtime_error("Unable to open file `"+fname+"'");
+ FOREACH(const Sph& s, pack) f<<s.c[0]<<" "<<s.c[1]<<" "<<s.c[2]<<"
"<<s.r<<endl;
+ f.close();
+};
+
+void SpherePack::fromSimulation() {
+ pack.clear();
+ MetaBody* rootBody=Omega::instance().getRootBody().get();
+ FOREACH(const shared_ptr<Body>& b, *rootBody->bodies){
+ shared_ptr<InteractingSphere>
intSph=dynamic_pointer_cast<InteractingSphere>(b->interactingGeometry);
+ if(!intSph) continue;
+
pack.push_back(Sph(b->physicalParameters->se3.position,intSph->radius));
+ }
+}
+
+long SpherePack::makeCloud(Vector3r mn, Vector3r mx, Real rMean, Real
rRelFuzz, size_t num, bool periodic){
+ static boost::minstd_rand randGen(TimingInfo::getNow(/* get the number
even if timing is disabled globally */ true));
+ static boost::variate_generator<boost::minstd_rand&,
boost::uniform_real<> > rnd(randGen, boost::uniform_real<>(0,1));
+ const size_t maxTry=1000;
+ Vector3r size=mx-mn;
+ if(periodic)(cellSize=size);
+ for(size_t i=0; i<num; i++) {
+ size_t t;
+ for(t=0; t<maxTry; ++t){
+ Real r=(rnd()-.5)*rRelFuzz+rMean; 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).SquaredLength()) { 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.SquaredLength()){ overlap=true; break; }
+ }
+ }
+ if(!overlap) { pack.push_back(Sph(c,r)); break; }
+ }
+ if (t==maxTry) {
+ LOG_WARN("Exceeded "<<maxTry<<" tries to insert
non-overlapping sphere to packing. Only "<<i<<" spheres was added, although you
requested "<<num);
+ return i;
+ }
+ }
+ return pack.size();
+}
+
Added: trunk/pkg/dem/DataClass/SpherePack.hpp
===================================================================
--- trunk/pkg/dem/DataClass/SpherePack.hpp 2009-08-09 17:17:53 UTC (rev
1932)
+++ trunk/pkg/dem/DataClass/SpherePack.hpp 2009-08-10 11:32:23 UTC (rev
1933)
@@ -0,0 +1,100 @@
+// © 2009 Václav Šmilauer <[email protected]>
+
+#include<vector>
+#include<string>
+using namespace std; // sorry
+
+#ifdef YADE_PYTHON
+ #include<boost/python.hpp>
+ #include<yade/extra/boost_python_len.hpp>
+ using namespace boost;
+#endif
+
+#include<boost/foreach.hpp>
+#ifndef FOREACH
+ #define FOREACH BOOST_FOREACH
+#endif
+
+#include<yade/lib-base/Logging.hpp>
+#include<yade/lib-base/yadeWm3Extra.hpp>
+
+/*! Class representing geometry of spherical packing, with some utility
functions.
+
+*/
+class SpherePack{
+ // return coordinate wrapped to x0…x1, relative to x0; don't care about
period
+ // copied from PeriodicInsertionSortCollider
+ Real cellWrapRel(const Real x, const Real x0, const Real x1){
+ Real xNorm=(x-x0)/(x1-x0);
+ return (xNorm-floor(xNorm))*(x1-x0);
+ }
+public:
+ struct Sph{
+ Vector3r c; Real r;
+ Sph(const Vector3r& _c, Real _r): c(_c), r(_r){};
+ #ifdef YADE_PYTHON
+ python::tuple asTuple() const { return
python::make_tuple(c,r); }
+ #endif
+ };
+ std::vector<Sph> pack;
+ Vector3r cellSize;
+ SpherePack(): cellSize(Vector3r::ZERO){};
+ #ifdef YADE_PYTHON
+ SpherePack(const python::list& l):cellSize(Vector3r::ZERO){
fromList(l); }
+ #endif
+ // add single sphere
+ void add(const Vector3r& c, Real r){ pack.push_back(Sph(c,r)); }
+
+ // I/O
+ #ifdef YADE_PYTHON
+ void fromList(const python::list& l);
+ python::list toList() const;
+ python::list toList_pointsAsTuples() const;
+ #endif
+ void fromFile(const string file);
+ void toFile(const string file) const;
+ void fromSimulation();
+
+ // random generation
+ long makeCloud(Vector3r min, Vector3r max, Real rMean, Real rFuzz,
size_t num, bool periodic=false);
+
+ // spatial characteristics
+ Vector3r dim() const {Vector3r mn,mx; aabb(mn,mx); return mx-mn;}
+ #ifdef YADE_PYTHON
+ python::tuple aabb_py() const { Vector3r mn,mx; aabb(mn,mx);
return python::make_tuple(mn,mx); }
+ #endif
+ void aabb(Vector3r& mn, Vector3r& mx) const {
+ Real inf=std::numeric_limits<Real>::infinity();
mn=Vector3r(inf,inf,inf); mx=Vector3r(-inf,-inf,-inf);
+ FOREACH(const Sph& s, pack){ Vector3r r(s.r,s.r,s.r);
mn=componentMinVector(mn,s.c-r); mx=componentMaxVector(mx,s.c+r);}
+ }
+ Vector3r midPt() const {Vector3r mn,mx; aabb(mn,mx); return .5*(mn+mx);}
+ Real relDensity() const {
+ Real sphVol=0; Vector3r dd=dim();
+ FOREACH(const Sph& s, pack) sphVol+=pow(s.r,3);
+ sphVol*=(4/3.)*Mathr::PI;
+ return sphVol/(dd[0]*dd[1]*dd[2]);
+ }
+
+ // transformations
+ void translate(const Vector3r& shift){ FOREACH(Sph& s, pack)
s.c+=shift; }
+ void rotate(const Vector3r& axis, Real angle){ Vector3r mid=midPt();
Quaternionr q(axis,angle); FOREACH(Sph& s, pack) s.c=q*(s.c-mid)+mid; }
+ void scale(Real scale){ Vector3r mid=midPt(); FOREACH(Sph& s, pack)
{s.c=scale*(s.c-mid)+mid; s.r*=abs(scale); } }
+
+ // iteration
+ #ifdef YADE_PYTHON
+ size_t len() const{ return pack.size(); }
+ python::tuple getitem(size_t idx){ if(idx<0 ||
idx>=pack.size()) throw runtime_error("Index "+lexical_cast<string>(idx)+" out
of range 0.."+lexical_cast<string>(pack.size()-1)); return pack[idx].asTuple();
}
+ struct iterator{
+ const SpherePack& sPack; size_t pos;
+ iterator(const SpherePack& _sPack): sPack(_sPack),
pos(0){}
+ iterator iter(){ return *this;}
+ python::tuple next(){
+ if(pos==sPack.pack.size()){
PyErr_SetNone(PyExc_StopIteration); python::throw_error_already_set(); }
+ return sPack.pack[pos++].asTuple();
+ }
+ };
+ SpherePack::iterator getIterator() const{ return
SpherePack::iterator(*this);};
+ #endif
+ DECLARE_LOGGER;
+};
+
Modified: trunk/pkg/dem/meta/Shop.cpp
===================================================================
--- trunk/pkg/dem/meta/Shop.cpp 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/pkg/dem/meta/Shop.cpp 2009-08-10 11:32:23 UTC (rev 1933)
@@ -85,22 +85,25 @@
}
-/*! Compute sum of forces in the whole simulation.
+/*! Compute sum of forces in the whole simulation and averages stiffness.
Designed for being used with periodic cell, where diving the resulting
components by
areas of the cell will give average stress in that direction.
Requires all .isReal() interaction to have interactionPhysics deriving from
NormalShearInteraction.
*/
-Vector3r Shop::totalForceInVolume(MetaBody* _rb){
+Vector3r Shop::totalForceInVolume(Real& avgIsoStiffness, MetaBody* _rb){
MetaBody* rb=_rb ? _rb : Omega::instance().getRootBody().get();
- Vector3r ret(Vector3r::ZERO);
+ Vector3r force(Vector3r::ZERO); Real stiff=0; long n=0;
FOREACH(const shared_ptr<Interaction>&I, *rb->interactions){
if(!I->isReal()) continue;
NormalShearInteraction*
nsi=YADE_CAST<NormalShearInteraction*>(I->interactionPhysics.get());
-
ret+=Vector3r(abs(nsi->normalForce[0]+nsi->shearForce[0]),abs(nsi->normalForce[1]+nsi->shearForce[1]),abs(nsi->normalForce[2]+nsi->shearForce[2]));
+
force+=Vector3r(abs(nsi->normalForce[0]+nsi->shearForce[0]),abs(nsi->normalForce[1]+nsi->shearForce[1]),abs(nsi->normalForce[2]+nsi->shearForce[2]));
+ stiff+=(1/3.)*nsi->kn+(2/3.)*nsi->ks; // count kn in one
direction and ks in the other two
+ n++;
}
- return ret;
+ avgIsoStiffness= n>0 ? (1./n)*stiff : -1;
+ return force;
}
Real Shop::unbalancedForce(bool useMaxForce, MetaBody* _rb){
@@ -1167,3 +1170,4 @@
return x0+xxNorm*(x1-x0);
}
+
Modified: trunk/pkg/dem/meta/Shop.hpp
===================================================================
--- trunk/pkg/dem/meta/Shop.hpp 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/pkg/dem/meta/Shop.hpp 2009-08-10 11:32:23 UTC (rev 1933)
@@ -94,7 +94,7 @@
//! Get unbalanced force of the whole simulation
static Real unbalancedForce(bool useMaxForce=false, MetaBody*
_rb=NULL);
static Real kineticEnergy(MetaBody* _rb=NULL);
- static Vector3r totalForceInVolume(MetaBody *_rb=NULL);
+ static Vector3r totalForceInVolume(Real& avgIsoStiffness,
MetaBody *_rb=NULL);
//! create transientInteraction between 2 bodies, using
existing MetaEngine in Omega
static shared_ptr<Interaction>
createExplicitInteraction(body_id_t id1, body_id_t id2);
Modified: trunk/py/SConscript
===================================================================
--- trunk/py/SConscript 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/py/SConscript 2009-08-10 11:32:23 UTC (rev 1933)
@@ -18,7 +18,7 @@
LIBS=env['LIBS']+(['_gts__python-module'] if 'GTS' in
env['features'] else []),
),
env.SharedLibrary('_packSpheres',['_packSpheres.cpp'],SHLIBPREFIX='',LIBS=env['LIBS']+[
- linkPlugins(['Shop']),
+ linkPlugins(['Shop','SpherePack']),
]),
env.SharedLibrary('_packObb',['_packObb.cpp'],SHLIBPREFIX=''),
env.File('utils.py'),
Modified: trunk/py/_packSpheres.cpp
===================================================================
--- trunk/py/_packSpheres.cpp 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/py/_packSpheres.cpp 2009-08-10 11:32:23 UTC (rev 1933)
@@ -1,132 +1,7 @@
// 2009 © Václav Šmilauer <[email protected]>
-#include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
-#include<yade/lib-base/Logging.hpp>
-#include<yade/lib-base/yadeWm3.hpp>
-#include<yade/lib-base/yadeWm3Extra.hpp>
-// #include<yade/gui-py/_utils.hpp> // will be: yade/lib-py/_utils.hpp> at
some point
-#include<Wm3Vector3.h>
-#include<yade/core/Omega.hpp>
-#include<yade/core/MetaBody.hpp>
-#include<yade/pkg-common/InteractingSphere.hpp>
+#include<yade/pkg-dem/SpherePack.hpp>
-#include<yade/pkg-dem/Shop.hpp>
-
-using namespace boost;
-using namespace std;
-#ifdef LOG4CXX
- log4cxx::LoggerPtr
logger=log4cxx::Logger::getLogger("yade.pack.spheres");
-#endif
-
-// copied from _packPredicates.cpp :-(
-python::tuple vec2tuple(const Vector3r& v){return
boost::python::make_tuple(v[0],v[1],v[2]);}
-Vector3r tuple2vec(const python::tuple& t){return
Vector3r(python::extract<double>(t[0])(),python::extract<double>(t[1])(),python::extract<double>(t[2])());}
-Vector3r tuple2vec(python::tuple& t){return
Vector3r(python::extract<double>(t[0])(),python::extract<double>(t[1])(),python::extract<double>(t[2])());}
-
-struct SpherePack{
- struct Sph{ Vector3r c; Real r; Sph(const Vector3r& _c, Real _r):
c(_c), r(_r){};
- python::tuple asTuple() const { return python::make_tuple(c,r);
}
- };
- vector<Sph> pack;
- SpherePack(){};
- SpherePack(const python::list& l){ fromList(l); }
- // add single sphere
- void add(const Vector3r& c, Real r){ pack.push_back(Sph(c,r)); }
- // I/O
- void fromList(const python::list& l);
- python::list toList() const;
- python::list toList_pointsAsTuples() const;
- void fromFile(const string file);
- void toFile(const string file) const;
- void fromSimulation();
- // spatial characteristics
- Vector3r dim() const {Vector3r mn,mx; aabb(mn,mx); return mx-mn;}
- python::tuple aabb_py() const { Vector3r mn,mx; aabb(mn,mx); return
python::make_tuple(mn,mx); }
- void aabb(Vector3r& mn, Vector3r& mx) const {
- Real inf=std::numeric_limits<Real>::infinity();
mn=Vector3r(inf,inf,inf); mx=Vector3r(-inf,-inf,-inf);
- FOREACH(const Sph& s, pack){ Vector3r r(s.r,s.r,s.r);
mn=componentMinVector(mn,s.c-r); mx=componentMaxVector(mx,s.c+r);}
- }
- Vector3r midPt() const {Vector3r mn,mx; aabb(mn,mx); return .5*(mn+mx);}
- Real relDensity() const {
- Real sphVol=0; Vector3r dd=dim();
- FOREACH(const Sph& s, pack) sphVol+=pow(s.r,3);
- sphVol*=(4/3.)*Mathr::PI;
- return sphVol/(dd[0]*dd[1]*dd[2]);
- }
- // transformations
- void translate(const Vector3r& shift){ FOREACH(Sph& s, pack)
s.c+=shift; }
- void rotate(const Vector3r& axis, Real angle){ Vector3r mid=midPt();
Quaternionr q(axis,angle); FOREACH(Sph& s, pack) s.c=q*(s.c-mid)+mid; }
- void scale(Real scale){ Vector3r mid=midPt(); FOREACH(Sph& s, pack)
{s.c=scale*(s.c-mid)+mid; s.r*=abs(scale); } }
- // iteration
- size_t len() const{ return pack.size(); }
- python::tuple getitem(size_t idx){ if(idx<0 || idx>=pack.size()) throw
runtime_error("Index "+lexical_cast<string>(idx)+" out of range
0.."+lexical_cast<string>(pack.size()-1)); return pack[idx].asTuple(); }
- struct iterator{
- const SpherePack& sPack; size_t pos;
- iterator(const SpherePack& _sPack): sPack(_sPack), pos(0){}
- iterator iter(){ return *this;}
- python::tuple next(){
- if(pos==sPack.pack.size()-1){
PyErr_SetNone(PyExc_StopIteration); python::throw_error_already_set(); }
- return sPack.pack[pos++].asTuple();
- }
- };
- SpherePack::iterator getIterator() const{ return
SpherePack::iterator(*this);};
-};
-
-void SpherePack::fromList(const python::list& l){
- pack.clear();
- size_t len=python::len(l);
- for(size_t i=0; i<len; i++){
- const python::tuple& t=python::extract<python::tuple>(l[i]);
- python::extract<python::tuple> tup(t[0]);
- if(tup.check()) {
pack.push_back(Sph(tuple2vec(tup()),python::extract<double>(t[1]))); continue;}
- python::extract<Vector3r> vec(t[0]);
- if(vec.check()) {
pack.push_back(Sph(vec(),python::extract<double>(t[1]))); continue; }
- PyErr_SetString(PyExc_TypeError, "List elements must be (tuple
or Vector3, float)!");
- python::throw_error_already_set();
- }
-};
-
-python::list SpherePack::toList() const {
- python::list ret;
- FOREACH(const Sph& s, pack) ret.append(python::make_tuple(s.c,s.r));
- return ret;
-};
-
-python::list SpherePack::toList_pointsAsTuples() const {
- python::list ret;
- FOREACH(const Sph& s, pack)
ret.append(python::make_tuple(vec2tuple(s.c),s.r));
- return ret;
-};
-
-void SpherePack::fromFile(string file) {
- typedef pair<Vector3r,Real> pairVector3rReal;
- vector<pairVector3rReal> ss;
- Vector3r mn,mx;
- ss=Shop::loadSpheresFromFile(file,mn,mx);
- pack.clear();
- FOREACH(const pairVector3rReal& s, ss)
pack.push_back(Sph(s.first,s.second));
-}
-
-void SpherePack::toFile(const string fname) const {
- ofstream f(fname.c_str());
- if(!f.good()) throw runtime_error("Unable to open file `"+fname+"'");
- FOREACH(const Sph& s, pack) f<<s.c[0]<<" "<<s.c[1]<<" "<<s.c[2]<<"
"<<s.r<<endl;
- f.close();
-};
-
-void SpherePack::fromSimulation() {
- pack.clear();
- MetaBody* rootBody=Omega::instance().getRootBody().get();
- FOREACH(const shared_ptr<Body>& b, *rootBody->bodies){
- shared_ptr<InteractingSphere>
intSph=dynamic_pointer_cast<InteractingSphere>(b->interactingGeometry);
- if(!intSph) continue;
-
pack.push_back(Sph(b->physicalParameters->se3.position,intSph->radius));
- }
-}
-
-
-
BOOST_PYTHON_MODULE(_packSpheres){
python::class_<SpherePack>("SpherePack","Set of spheres as centers and
radii",python::init<python::optional<python::list>
>(python::args("list"),"Empty constructor, optionally taking list [
((cx,cy,cz),r), … ] for initial data." ))
.def("add",&SpherePack::add,"Add single sphere to packing,
given center as 3-tuple and radius")
@@ -136,9 +11,11 @@
.def("load",&SpherePack::fromFile,"Load packing from external
text file (current data will be discarded).")
.def("save",&SpherePack::toFile,"Save packing to external text
file (will be overwritten).")
.def("fromSimulation",&SpherePack::fromSimulation,"Make packing
corresponding to the current simulation. Discards current data.")
+
.def("makeCloud",&SpherePack::makeCloud,python::args("minCorner","maxCorner","rMean","rRelFuzz","num","periodic"),"Create
random packing encosed in box given by minCorner and maxCorner, containing num
spheres. Returns number of created spheres, which can be < num if the packing
is too tight.")
.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.")
.def("center",&SpherePack::midPt,"Return coordinates of the
bounding box center.")
+ .def_readonly("cellSize",&SpherePack::cellSize,"Size of
periodic cell; is Vector3(0,0,0) if not periodic.")
.def("relDensity",&SpherePack::relDensity,"Relative packing
density, measured as sum of spheres' volumes / aabb volume.\n(Sphere overlaps
are ignored.)")
.def("translate",&SpherePack::translate,"Translate all spheres
by given vector.")
.def("rotate",&SpherePack::rotate,"Rotate all spheres around
packing center (in terms of aabb()), given axis and angle of the rotation.")
Modified: trunk/py/_utils.cpp
===================================================================
--- trunk/py/_utils.cpp 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/py/_utils.cpp 2009-08-10 11:32:23 UTC (rev 1933)
@@ -396,7 +396,7 @@
BOOST_PYTHON_FUNCTION_OVERLOADS(unbalancedForce_overloads,Shop::unbalancedForce,0,1);
Real Shop__kineticEnergy(){return Shop::kineticEnergy();}
-Vector3r Shop__totalForceInVolume(){return Shop::totalForceInVolume();}
+python::tuple Shop__totalForceInVolume(){Real stiff; Vector3r
ret=Shop::totalForceInVolume(stiff); return python::make_tuple(ret,stiff); }
BOOST_PYTHON_MODULE(_utils){
// http://numpy.scipy.org/numpydoc/numpy-13.html mentions this must be
done in module init, otherwise we will crash
@@ -420,7 +420,7 @@
def("sumBexTorques",sumBexTorques);
def("forcesOnPlane",forcesOnPlane);
def("forcesOnCoordPlane",forcesOnCoordPlane);
- def("totalForceInVolume",Shop__totalForceInVolume);
+ def("totalForceInVolume",Shop__totalForceInVolume,"Return summed forces
on all interactions and average isotropic stiffness, as tuple (Vector3,float)");
def("createInteraction",Shop__createExplicitInteraction);
def("spiralProject",spiralProject,spiralProject_overloads(args("axis","periodStart","theta0")));
def("pointInsidePolygon",pointInsidePolygon);
Modified: trunk/py/yadeWrapper/yadeWrapper.cpp
===================================================================
--- trunk/py/yadeWrapper/yadeWrapper.cpp 2009-08-09 17:17:53 UTC (rev
1932)
+++ trunk/py/yadeWrapper/yadeWrapper.cpp 2009-08-10 11:32:23 UTC (rev
1933)
@@ -462,6 +462,7 @@
signal(SIGSEGV,termHandler); /* unset the handler that runs gdb
and prints backtrace */
exit(status);
}
+ void runEngine(const shared_ptr<Engine>& e){
e->action(OMEGA.getRootBody().get()); }
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(omega_run_overloads,run,0,2);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(omega_saveTmp_overloads,saveTmp,0,1);
@@ -648,6 +649,7 @@
#ifdef YADE_BOOST_SERIALIZATION
.def("saveXML",&pyOmega::saveXML,"[EXPERIMENTAL]
function saving to XML file using boost::serialization.")
#endif
+ .def("runEngine",&pyOmega::runEngine,"Run given engine exactly
once; simulation time, step number etc. will not be incremented (use only if
you know what you do).")
;
python::class_<pyTags>("TagsWrapper",python::init<pyTags&>())
.def("__getitem__",&pyTags::getItem)
Added: trunk/scripts/test/periodic-compress.py
===================================================================
--- trunk/scripts/test/periodic-compress.py 2009-08-09 17:17:53 UTC (rev
1932)
+++ trunk/scripts/test/periodic-compress.py 2009-08-10 11:32:23 UTC (rev
1933)
@@ -0,0 +1,27 @@
+O.periodicCell=(0,0,0),(20,20,20)
+from yade import pack,log,timing
+p=pack.SpherePack()
+p.makeCloud(O.periodicCell[0],O.periodicCell[1],1,.5,700,True)
+for sph in p:
+ O.bodies.append(utils.sphere(sph[0],sph[1],density=1000,dynamic=True))
+
+#log.setLevel("PeriIsoCompressor",log.TRACE)
+O.timingEnabled=True
+O.engines=[
+ BexResetter(),
+
BoundingVolumeMetaEngine([InteractingSphere2AABB(),MetaInteractingGeometry2AABB()]),
+ PeriodicInsertionSortCollider(),
+ InteractionDispatchers(
+ [ef2_Sphere_Sphere_Dem3DofGeom()],
+ [SimpleElasticRelationships()],
+ [Law2_Dem3Dof_Elastic_Elastic()],
+ ),
+ PeriIsoCompressor(charLen=.1,stresses=[50e9,1e8],doneHook="print
'FINISHED'; O.pause() "),
+ NewtonsDampedLaw(damping=.4)
+]
+O.dt=utils.PWaveTimeStep()
+O.saveTmp()
+from yade import qt; qt.Controller(); qt.View()
+O.run()
+O.wait()
+timing.stats()
Modified: trunk/scripts/test/periodic-grow.py
===================================================================
--- trunk/scripts/test/periodic-grow.py 2009-08-09 17:17:53 UTC (rev 1932)
+++ trunk/scripts/test/periodic-grow.py 2009-08-10 11:32:23 UTC (rev 1933)
@@ -32,7 +32,7 @@
step=(mx-mn); step=Vector3(.002*step[0],.002*step[1],.002*step[2])
O.periodicCell=mn+step,mx-step
if (i%10==0):
- F=utils.totalForceInVolume()
+ F,stiff=utils.totalForceInVolume()
dim=mx-mn; A=Vector3(dim[1]*dim[2],dim[0]*dim[2],dim[0]*dim[1])
avgStress=sum([F[i]/A[i] for i in 0,1,2])/3.
print 'strain',(cubeSize-dim[0])/cubeSize,'avg. stress
',avgStress,'unbalanced ',utils.unbalancedForce()
_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help : https://help.launchpad.net/ListHelp
_______________________________________________
yade-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/yade-dev