Author: eudoxos
Date: 2008-08-25 09:58:04 +0200 (Mon, 25 Aug 2008)
New Revision: 1494

Added:
   trunk/gui/py/_utils.cpp
Modified:
   trunk/extra/SimpleScene.cpp
   trunk/extra/clump/Shop.cpp
   trunk/extra/clump/Shop.hpp
   trunk/gui/SConscript
   trunk/gui/py/PythonUI_rc.py
   trunk/gui/py/eudoxos.py
   trunk/gui/py/ipython.py
   trunk/gui/py/utils.py
Log:
1. Reimplement some loop-intensive functions from yade.utils in c++ for better 
performance (as yade._utils, imported into yade.utils automatically - 
transparent to the user)
2. Add poisson's ratio and Young's modulus estimation in yade.eudoxos based on 
linear regressions of position?\226?\134?\146displacement mapping along 
different axes
3. Rename Shop::ElasticWaveTimestepEstimate to Shop::PWaveTimeStep, wrapped in 
yade.utils



Modified: trunk/extra/SimpleScene.cpp
===================================================================
--- trunk/extra/SimpleScene.cpp 2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/extra/SimpleScene.cpp 2008-08-25 07:58:04 UTC (rev 1494)
@@ -156,7 +156,7 @@
        rootBody->bodies->insert(sphere);
        
        //@
-       rootBody->dt=.2*Shop::ElasticWaveTimestepEstimate(rootBody);
+       rootBody->dt=.2*Shop::PWaveTimeStep(rootBody);
 
        //@
        return true;

Modified: trunk/extra/clump/Shop.cpp
===================================================================
--- trunk/extra/clump/Shop.cpp  2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/extra/clump/Shop.cpp  2008-08-25 07:58:04 UTC (rev 1494)
@@ -1071,7 +1071,7 @@
        {0.370512,0.415453,0.055970,0.010546},
        {-1.,-1.,-1.,-1. } /* sentinel: non-positive radius */
 };
-
+#if 0
 Real Shop::ElasticWaveTimestepEstimate(shared_ptr<MetaBody> rootBody){
        Real minDt=std::numeric_limits<Real>::infinity();
        FOREACH(const shared_ptr<Body>& b, *rootBody->bodies){
@@ -1084,6 +1084,7 @@
        }
        return minDt;
 }
+#endif
 
 void Shop::GLDrawLine(Vector3r from, Vector3r to, Vector3r color){
        glEnable(GL_LIGHTING); glColor3v(color);
@@ -1109,9 +1110,10 @@
        glPopMatrix();
 
 }
-#if 0
-Real Shop::PWaveTimeStep(MetaBody* rb){
-       dt=std::numeric_limits<Real>::infinity();
+Real Shop::PWaveTimeStep(shared_ptr<MetaBody> _rb){
+       shared_ptr<MetaBody> rb=_rb;
+       if(!rb)rb=Omega::instance().getRootBody();
+       Real dt=std::numeric_limits<Real>::infinity();
        FOREACH(const shared_ptr<Body>& b, *rb->bodies){
                if(!b->physicalParameters || !b->geometricalModel) continue;
                shared_ptr<ElasticBodyParameters> 
ebp=dynamic_pointer_cast<ElasticBodyParameters>(b->physicalParameters);
@@ -1122,4 +1124,3 @@
        }
        return dt;
 }
-#endif

Modified: trunk/extra/clump/Shop.hpp
===================================================================
--- trunk/extra/clump/Shop.hpp  2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/extra/clump/Shop.hpp  2008-08-25 07:58:04 UTC (rev 1494)
@@ -79,9 +79,6 @@
                //! Save spheres in the current simulation into a text file
                static void saveSpheresToFile(string fileName);
 
-               //! Estimate timestep based on P-wave propagation speed
-               static Real ElasticWaveTimestepEstimate(shared_ptr<MetaBody>);
-
                static void GLDrawLine(Vector3r from, Vector3r to, Vector3r 
color=Vector3r(1,1,1));
                static void GLDrawArrow(Vector3r from, Vector3r to, Vector3r 
color=Vector3r(1,1,1));
                static void GLDrawText(std::string text, Vector3r pos, Vector3r 
color=Vector3r(1,1,1));
@@ -101,8 +98,7 @@
                        static Vector3r& globalStiffness(body_id_t, MetaBody* 
mb=NULL);
                        static Vector3r& globalRStiffness(body_id_t, MetaBody* 
mb=NULL);
                };
-               #if 0
-                       Real PWaveTimeStep(MetaBody* rb);
-               #endif
 
+               //! Estimate timestep based on P-wave propagation speed
+               static Real PWaveTimeStep(shared_ptr<MetaBody> 
rb=shared_ptr<MetaBody>());
 };

Modified: trunk/gui/SConscript
===================================================================
--- trunk/gui/SConscript        2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/SConscript        2008-08-25 07:58:04 UTC (rev 1494)
@@ -52,7 +52,7 @@
        # python modules are one level deeper so that you can say: from 
yade.wrapper import *
        env.Install('$PREFIX/lib/yade$SUFFIX/gui/yade',[
                
env.SharedLibrary('wrapper',['py/yadeControl.cpp'],SHLIBPREFIX='',
-                       
LIBS=env['LIBS']+['yade-base','libboost_python','XMLFormatManager','yade-factory','yade-serialization','Shop',
+                       
LIBS=env['LIBS']+['libboost_python','XMLFormatManager','yade-factory','yade-serialization','Shop',
                                'BoundingVolumeMetaEngine',
                                'GeometricalModelMetaEngine',
                                'InteractingGeometryMetaEngine',
@@ -63,6 +63,8 @@
                                'ParallelEngine'
                        ],
                        ),
+               env.SharedLibrary('_utils',['py/_utils.cpp'],SHLIBPREFIX='',
+                       LIBS=env['LIBS']+['Shop','libboost_python']),
                env.SharedLibrary('log',['py/log.cpp'],SHLIBPREFIX=''),
                env.File('__init__.py','py'),
                env.File('utils.py','py'),

Modified: trunk/gui/py/PythonUI_rc.py
===================================================================
--- trunk/gui/py/PythonUI_rc.py 2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/py/PythonUI_rc.py 2008-08-25 07:58:04 UTC (rev 1494)
@@ -62,5 +62,3 @@
                import yade.qt
                yade.qt.close()
        except ImportError: pass
-
-

Added: trunk/gui/py/_utils.cpp
===================================================================
--- trunk/gui/py/_utils.cpp     2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/py/_utils.cpp     2008-08-25 07:58:04 UTC (rev 1494)
@@ -0,0 +1,63 @@
+#include<yade/extra/Shop.hpp>
+#include<boost/python.hpp>
+#include<yade/core/MetaBody.hpp>
+#include<yade/core/Omega.hpp>
+#include<yade/pkg-common/Sphere.hpp>
+using namespace boost::python;
+
+python::tuple vec2tuple(const Vector3r& v){return 
boost::python::make_tuple(v[0],v[1],v[2]);};
+
+/* \todo implement groupMask */
+python::tuple aabbExtrema(){
+       Real inf=std::numeric_limits<Real>::infinity();
+       Vector3r minimum(inf,inf,inf),maximum(-inf,-inf,-inf);
+       FOREACH(const shared_ptr<Body>& b, 
*Omega::instance().getRootBody()->bodies){
+               shared_ptr<Sphere> 
s=dynamic_pointer_cast<Sphere>(b->geometricalModel); if(!s) continue;
+               Vector3r rrr(s->radius,s->radius,s->radius);
+               
minimum=componentMinVector(minimum,b->physicalParameters->se3.position-rrr);
+               
maximum=componentMaxVector(maximum,b->physicalParameters->se3.position+rrr);
+       }
+       return python::make_tuple(vec2tuple(minimum),vec2tuple(maximum));
+}
+
+python::tuple negPosExtremeIds(int axis, Real distFactor=1.1){
+       python::tuple extrema=aabbExtrema();
+       Real 
minCoord=extract<double>(extrema[0][axis])(),maxCoord=extract<double>(extrema[1][axis])();
+       python::list minIds,maxIds;
+       FOREACH(const shared_ptr<Body>& b, 
*Omega::instance().getRootBody()->bodies){
+               shared_ptr<Sphere> 
s=dynamic_pointer_cast<Sphere>(b->geometricalModel); if(!s) continue;
+               
if(b->physicalParameters->se3.position[axis]-s->radius*distFactor<=minCoord) 
minIds.append(b->getId());
+               
if(b->physicalParameters->se3.position[axis]+s->radius*distFactor>=maxCoord) 
maxIds.append(b->getId());
+       }
+       return python::make_tuple(minIds,maxIds);
+}
+BOOST_PYTHON_FUNCTION_OVERLOADS(negPosExtremeIds_overloads,negPosExtremeIds,1,2);
+
+python::tuple coordsAndDisplacements(int axis){
+       python::list retCoord,retDispl;
+       FOREACH(const shared_ptr<Body>&b, 
*Omega::instance().getRootBody()->bodies){
+               retCoord.append(b->physicalParameters->se3.position[axis]);
+               
retDispl.append(b->physicalParameters->se3.position[axis]-b->physicalParameters->refSe3.position[axis]);
+       }
+       return python::make_tuple(retCoord,retDispl);
+}
+
+void setRefSe3(){
+       FOREACH(const shared_ptr<Body>& b, 
*Omega::instance().getRootBody()->bodies){
+               
b->physicalParameters->refSe3.position=b->physicalParameters->se3.position;
+               
b->physicalParameters->refSe3.orientation=b->physicalParameters->se3.orientation;
+       }
+}
+
+
+Real PWaveTimeStep(){return Shop::PWaveTimeStep();};
+
+BOOST_PYTHON_MODULE(_utils){
+       def("PWaveTimeStep",PWaveTimeStep);
+       def("aabbExtrema",aabbExtrema);
+       
def("negPosExtremeIds",negPosExtremeIds,negPosExtremeIds_overloads(args("axis","distFactor")));
+       def("coordsAndDisplacements",coordsAndDisplacements);
+       def("setRefSe3",setRefSe3);
+}
+
+

Modified: trunk/gui/py/eudoxos.py
===================================================================
--- trunk/gui/py/eudoxos.py     2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/py/eudoxos.py     2008-08-25 07:58:04 UTC (rev 1494)
@@ -4,7 +4,39 @@
 # I doubt there functions will be useful for anyone besides me.
 #
 
+def estimatePoissonYoung(principalAxis,stress=0,plot=False):
+       """Estimate Poisson's ration given the "principal" axis of straining.
+       For every base direction, homogenized strain is computed
+       (slope in linear regression on discrete function particle coordinate →
+       → particle displacement in the same direction as returned by
+       utils.coordsAndDisplacements) and, (if axis '0' is the strained 
+       axis) the poisson's ratio is given as -½(ε₁+ε₂)/ε₀.
 
+       Young's modulus is computed as σ/ε₀; if stress σ is not given (default 
0),
+       the result is 0.
+       """
+       dd=[] # storage for linear regression parameters
+       import pylab,numpy,stats
+       from yade import utils
+       for axis in [0,1,2]:
+               w,dw=utils.coordsAndDisplacements(axis)
+               l,ll=stats.linregress(w,dw)[0:2] # use only tangent and section
+               dd.append((l,ll,min(w),max(w)))
+               if plot: pylab.plot(w,dw,'.',label='xyz'[axis])
+       if plot:
+               for axis in [0,1,2]:
+                       dist=dd[axis][-1]-dd[axis][-2]
+                       
c=numpy.linspace(dd[axis][-2]-.2*dist,dd[axis][-1]+.2*dist)
+                       d=[dd[axis][0]*cc+dd[axis][1] for cc in c]
+                       pylab.plot(c,d,label='interp '+'xyz'[axis])
+               pylab.legend()
+               pylab.show()
+       otherAxes=(principalAxis+1)%3,(principalAxis+2)%3
+       avgTransHomogenizedStrain=.5*(dd[otherAxes[0]][0]+dd[otherAxes[1]][0])
+       principalHomogenizedStrain=dd[principalAxis][0]
+       return 
-avgTransHomogenizedStrain/principalHomogenizedStrain,stress/principalHomogenizedStrain
+
+
 def oofemTextExport():
        """Export simulation data in text format 
        

Modified: trunk/gui/py/ipython.py
===================================================================
--- trunk/gui/py/ipython.py     2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/py/ipython.py     2008-08-25 07:58:04 UTC (rev 1494)
@@ -16,4 +16,4 @@
 import IPython.ipapi
 ip=IPython.ipapi.get()
 
ip.set_hook('complete_command',yade_completers,re_key='.*\\b[a-zA-Z0-9_]+\[["\'][^"\'\]]*$')
-
+ip.options.profile='yade'

Modified: trunk/gui/py/utils.py
===================================================================
--- trunk/gui/py/utils.py       2008-08-22 23:01:31 UTC (rev 1493)
+++ trunk/gui/py/utils.py       2008-08-25 07:58:04 UTC (rev 1494)
@@ -4,6 +4,8 @@
 #
 # 2008 © Václav Šmilauer <[EMAIL PROTECTED]>
 
+#from yade._utils import *
+
 import math,random
 from yade.wrapper import *
 try: # use psyco if available
@@ -11,6 +13,10 @@
        psyco.full()
 except ImportError: pass
 
+# c++ implementations for performance reasons
+from yade._utils import *
+
+
 def 
sphere(center,radius,density=1,young=30e9,poisson=.3,frictionAngle=0.5236,dynamic=True,wire=False,color=[1,1,1],physParamsClass='BodyMacroParameters'):
        """Create default sphere, with given parameters. Physical properties 
such as mass and inertia are calculated automatically."""
        s=Body()
@@ -18,7 +24,7 @@
        
s.mold=InteractingGeometry('InteractingSphere',{'radius':radius,'diffuseColor':color})
        V=(4./3)*math.pi*radius**3
        inert=(2./5.)*V*density*radius**2
-       
s.phys=PhysicalParameters(physParamsClass,{'se3':[center[0],center[1],center[2],1,0,0,0],'mass':V*density,'inertia':[inert,inert,inert],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
+       
s.phys=PhysicalParameters(physParamsClass,{'se3':[center[0],center[1],center[2],1,0,0,0],'refSe3':[center[0],center[1],center[2],1,0,0,0],'mass':V*density,'inertia':[inert,inert,inert],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
        s.bound=BoundingVolume('AABB',{'diffuseColor':[0,1,0]})
        s['isDynamic']=dynamic
        return s
@@ -29,29 +35,11 @@
        
b.shape=GeometricalModel('Box',{'extents':extents,'diffuseColor':color,'wire':wire,'visible':True})
        
b.mold=InteractingGeometry('InteractingBox',{'extents':extents,'diffuseColor':color})
        mass=8*extents[0]*extents[1]*extents[2]*density
-       
b.phys=PhysicalParameters(physParamsClass,{'se3':[center[0],center[1],center[2],orientation[0],orientation[1],orientation[2],orientation[3]],'mass':mass,'inertia':[mass*4*(extents[1]**2+extents[2]**2),mass*4*(extents[0]**2+extents[2]**2),mass*4*(extents[0]**2+extents[1]**2)],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
+       
b.phys=PhysicalParameters(physParamsClass,{'se3':[center[0],center[1],center[2],orientation[0],orientation[1],orientation[2],orientation[3]],'refSe3':[center[0],center[1],center[2],orientation[0],orientation[1],orientation[2],orientation[3]],'mass':mass,'inertia':[mass*4*(extents[1]**2+extents[2]**2),mass*4*(extents[0]**2+extents[2]**2),mass*4*(extents[0]**2+extents[1]**2)],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
        b.bound=BoundingVolume('AABB',{'diffuseColor':[0,1,0]})
        b['isDynamic']=dynamic
        return b
 
-def negPosExtremes(axis,distFactor=1.1):
-       """Get 2 lists (negative and positive extremes) of sphere ids that are 
close to the boundary
-       in the direction of requested axis (0=x,1=y,2=z).
-
-       distFactor enlarges radius of the sphere, it can be considered 
'extremal' even if it doesn't touch the extreme.
-       """
-       inf=float('inf')
-       extremes=[inf,-inf]
-       ret=[[],[]]
-       o=Omega()
-       for b in o.bodies:
-               
extremes[1]=max(extremes[1],+b.shape['radius']+b.phys['se3'][axis])
-               
extremes[0]=min(extremes[0],-b.shape['radius']+b.phys['se3'][axis])
-       for b in o.bodies:
-               if 
b.phys['se3'][axis]-b.shape['radius']*distFactor<=extremes[0]: 
ret[0].append(b.id)
-               if 
b.phys['se3'][axis]+b.shape['radius']*distFactor>=extremes[1]: 
ret[1].append(b.id)
-       return ret
-
 def aabbWalls(extrema=None,thickness=None,oversizeFactor=1.5,**kw):
        """return 6 walls that will wrap existing packing;
        extrema are extremal points of the AABB of the packing (will be 
calculated if not specified)
@@ -74,23 +62,13 @@
                        walls[-1].shape['visible']=True
        return walls
 
-def aabbExtrema(consider=lambda body:True):
-       """return min and max points of an aabb around spherical packing 
(non-spheres are ignored)"""
-       inf=float('inf')
-       minimum,maximum=[inf,inf,inf],[-inf,-inf,-inf]
-       o=Omega()
-       for b in o.bodies:
-               if consider(b) and b.shape.name=='Sphere':
-                       
minimum=[min(minimum[i],b.phys['se3'][i]-b.shape['radius']) for i in range(3)]
-                       
maximum=[max(maximum[i],b.phys['se3'][i]+b.shape['radius']) for i in range(3)]
-       return minimum,maximum
 
-def perpendicularArea(axis,consider=lambda body: True):
+def perpendicularArea(axis):
        """return area perpendicular to given axis (0=x,1=y,2=z) generated by 
bodies
        for which the function consider returns True (defaults to returning 
True always)
        and which is of the type "Sphere"
        """
-       ext=aabbExtrema(consider)
+       ext=aabbExtrema()
        other=((axis+1)%3,(axis+2)%3)
        return 
(ext[1][other[0]]-ext[0][other[0]])*(ext[1][other[1]]-ext[0][other[1]])
 
@@ -107,19 +85,6 @@
                if onShapes and (b['isDynamic'] or not onlyDynamic): 
b.shape['diffuseColor']=color
                if onMolds  and (b['isDynamic'] or not onlyDynamic): 
b.mold['diffuseColor']=color
 
-def PWaveTimeStep():
-       """Estimate timestep by the elastic wave propagation speed (p-wave).
-       
-       Multiply the value returned by some safety factor < 1, since shear 
waves are not taken into account here."""
-       o=Omega()
-       dt=float('inf')
-       for b in o.bodies:
-               if not (b.phys and b.shape): continue
-               if not (b.phys.has_key('young') and b.shape.has_key('radius')): 
continue
-               density=b.phys['mass']/((4./3.)*math.pi*b.shape['radius']**3)
-               thisDt=b.shape['radius']/math.sqrt(b.phys['young']/density)
-               dt=min(dt,thisDt)
-       return dt
 
 def spheresFromFile(filename,scale=1.,wenjieFormat=False,**kw):
        """Load sphere coordinates from file, create spheres, insert them to 
the simulation.
@@ -150,3 +115,48 @@
                
out.write('%g\t%g\t%g\t%g\n'%(b.phys['se3'][0],b.phys['se3'][1],b.phys['se3'][2],b.shape['radius']))
        out.close()
 
+def negPosExtremes(**kw): raise DeprecationWarning("negPosExtremes is 
deprecated, use negPosExtremalIds instead.")
+
+# reimplemented in _utils in c++ (results verified to be identical)
+if 0:
+       def negPosExtremes(axis,distFactor=1.1):
+               """Get 2 lists (negative and positive extremes) of sphere ids 
that are close to the boundary
+               in the direction of requested axis (0=x,1=y,2=z).
+
+               distFactor enlarges radius of the sphere, it can be considered 
'extremal' even if it doesn't touch the extreme.
+               """
+               inf=float('inf')
+               extremes=[inf,-inf]
+               ret=[[],[]]
+               o=Omega()
+               for b in o.bodies:
+                       
extremes[1]=max(extremes[1],+b.shape['radius']+b.phys['se3'][axis])
+                       
extremes[0]=min(extremes[0],-b.shape['radius']+b.phys['se3'][axis])
+               for b in o.bodies:
+                       if 
b.phys['se3'][axis]-b.shape['radius']*distFactor<=extremes[0]: 
ret[0].append(b.id)
+                       if 
b.phys['se3'][axis]+b.shape['radius']*distFactor>=extremes[1]: 
ret[1].append(b.id)
+               return ret
+       def aabbExtrema(consider=lambda body:True):
+               """return min and max points of an aabb around spherical 
packing (non-spheres are ignored)"""
+               inf=float('inf')
+               minimum,maximum=[inf,inf,inf],[-inf,-inf,-inf]
+               o=Omega()
+               for b in o.bodies:
+                       if consider(b) and b.shape.name=='Sphere':
+                               
minimum=[min(minimum[i],b.phys['se3'][i]-b.shape['radius']) for i in range(3)]
+                               
maximum=[max(maximum[i],b.phys['se3'][i]+b.shape['radius']) for i in range(3)]
+               return minimum,maximum
+       def PWaveTimeStep():
+               """Estimate timestep by the elastic wave propagation speed 
(p-wave).
+               
+               Multiply the value returned by some safety factor < 1, since 
shear waves are not taken into account here."""
+               o=Omega()
+               dt=float('inf')
+               for b in o.bodies:
+                       if not (b.phys and b.shape): continue
+                       if not (b.phys.has_key('young') and 
b.shape.has_key('radius')): continue
+                       
density=b.phys['mass']/((4./3.)*math.pi*b.shape['radius']**3)
+                       
thisDt=b.shape['radius']/math.sqrt(b.phys['young']/density)
+                       dt=min(dt,thisDt)
+               return dt
+


_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to