yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #03793
[Branch ~yade-dev/yade/trunk] Rev 2125: 1. TriaixalStressController: originally compilation fix, but Luc was faster; Bruno, I tried to re...
------------------------------------------------------------
revno: 2125
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Thu 2010-04-01 08:53:09 +0200
message:
1. TriaixalStressController: originally compilation fix, but Luc was faster; Bruno, I tried to replace on c-array with boost::array; if that works, you could use it for other c-arrays as well
2. Add yield surface query function from python to Law2_..._Cpm
3. Make plot support label translation via yade.plot.labels
4. make chunkSize very small for debian; add strip for the optimized build
modified:
SConstruct
debian/rules
lib/serialization/Serializable.hpp
pkg/dem/Engine/PartialEngine/ThreeDTriaxialEngine.hpp
pkg/dem/Engine/PartialEngine/TriaxialStateRecorder.hpp
pkg/dem/Engine/PartialEngine/TriaxialStressController.hpp
pkg/dem/meta/ConcretePM.cpp
pkg/dem/meta/ConcretePM.hpp
py/_eudoxos.cpp
py/plot.py
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'SConstruct'
--- SConstruct 2010-03-29 11:36:21 +0000
+++ SConstruct 2010-04-01 06:53:09 +0000
@@ -486,6 +486,7 @@
env.Append(FRAMEWORKS=['CoreServices','Carbon'])
else:
env.Append(LINKFLAGS=['-rdynamic','-z','origin'])
+ if not env['debug']: env.Append(SHLINKFLAGS=['-W,--strip-all'])
# makes dynamic library loading easier (no LD_LIBRARY_PATH) and perhaps faster
env.Append(RPATH=runtimeLibDirs)
=== modified file 'debian/rules'
--- debian/rules 2010-03-29 12:28:06 +0000
+++ debian/rules 2010-04-01 06:53:09 +0000
@@ -60,7 +60,7 @@
### (a) use fakeroot-tcp instead of fakeroot
### (b) use just 1 job
#debug build
- NO_SCONS_GET_RECENT= scons buildPrefix=debian runtimePREFIX=/usr version=${VERSION} brief=0 chunkSize=-1 linkStrategy=monolithic features=vtk,gts,log4cxx,opengl,openmp exclude=snow PREFIX=debian/yade${_VERSION}-dbg/usr variant=-dbg optimize=0 march= debug=1 CPPPATH=/usr/include/vtk-5.0:/usr/include/vtk-5.2:/usr/include/vtk-5.4
+ NO_SCONS_GET_RECENT= scons buildPrefix=debian runtimePREFIX=/usr version=${VERSION} brief=0 chunkSize=4 linkStrategy=monolithic features=vtk,gts,log4cxx,opengl,openmp exclude=snow PREFIX=debian/yade${_VERSION}-dbg/usr variant=-dbg optimize=0 march= debug=1 CPPPATH=/usr/include/vtk-5.0:/usr/include/vtk-5.2:/usr/include/vtk-5.4 jobs=1
#optimized build
NO_SCONS_GET_RECENT= scons PREFIX=debian/yade${_VERSION}/usr variant='' optimize=1 debug=0
#install platform-independent files (docs, scripts, examples)
@@ -97,8 +97,7 @@
# dh_installinfo
dh_installman
dh_link
- ## do NOT use this!!! debug builds need symbols, optimized builds don't have them at all
- #dh_strip
+ dh_strip --exclude=yade${_VERSION}-dbg # don't strip the debug package
dh_compress
dh_fixperms
# dh_perl
=== modified file 'lib/serialization/Serializable.hpp'
--- lib/serialization/Serializable.hpp 2010-03-30 10:51:31 +0000
+++ lib/serialization/Serializable.hpp 2010-04-01 06:53:09 +0000
@@ -116,14 +116,13 @@
// filter away 2nd element of a 2-tuple
#define _STRIPDOC2(x,y,z) (BOOST_PP_TUPLE_ELEM(2,0,z))
-#define YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,attrs,deprec,extras) \
+#define _YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,attrs,deprec,extras) \
REGISTER_ATTRIBUTES_DEPREC(thisClass,baseClass,BOOST_PP_SEQ_FOR_EACH(_STRIPDOC2,thisClass,attrs),deprec) \
REGISTER_CLASS_AND_BASE(thisClass,baseClass) \
/* accessors for deprecated attributes, with warnings */ BOOST_PP_SEQ_FOR_EACH(_ACCESS_DEPREC,thisClass,deprec) \
/* python class registration */ virtual void pyRegisterClass(python::object _scope) const { if(!checkPyClassRegistersItself(#thisClass)) return; boost::python::scope thisScope(_scope); YADE_SET_DOCSTRING_OPTS; boost::python::class_<thisClass,shared_ptr<thisClass>,boost::python::bases<baseClass>,boost::noncopyable>(#thisClass,docString).def("__init__",python::raw_constructor(Serializable_ctor_kwAttrs<thisClass>)).def("clone",&Serializable_clone<thisClass>,python::arg("attrs")=python::dict()) BOOST_PP_SEQ_FOR_EACH(_PYATTR_DEF,thisClass,attrs) BOOST_PP_SEQ_FOR_EACH(_PYATTR_DEPREC_DEF,thisClass,deprec) extras ; }
// use later: void must_use_both_YADE_CLASS_BASE_DOC_ATTRS_and_YADE_PLUGIN();
-#define YADE_CLASS_BASE_DOC_ATTRS_PY(thisClass,baseClass,docString,attrs,extras) \
- YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,attrs,extras)
+// #define YADE_CLASS_BASE_DOC_ATTRS_PY(thisClass,baseClass,docString,attrs,extras) YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,attrs,,extras)
#define _STRIPDECL4(x,y,z) (( BOOST_PP_TUPLE_ELEM(4,1,z),BOOST_PP_TUPLE_ELEM(4,3,z) " :ydefault:`" BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(4,2,z)) "`" ))
// return type name; (for declaration)
@@ -134,13 +133,11 @@
#define _DECLINI4(x,y,z) (( BOOST_PP_TUPLE_ELEM(4,1,z),BOOST_PP_TUPLE_ELEM(4,2,z) ))
-#define YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(thisClass,baseClass,docString,attrDecls,inits,ctor,extras) \
- YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(thisClass,baseClass,docString,attrDecls,,inits,ctor,extras)
// the most general here
#define YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(thisClass,baseClass,docString,attrDecls,deprec,inits,ctor,extras) \
public: BOOST_PP_SEQ_FOR_EACH(_ATTR_DECL,~,attrDecls) /* attribute declarations */ \
thisClass() BOOST_PP_IF(BOOST_PP_SEQ_SIZE(inits attrDecls),:,) BOOST_PP_SEQ_FOR_EACH_I(_ATTR_INI,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(inits attrDecls)), inits BOOST_PP_SEQ_FOR_EACH(_DECLINI4,~,attrDecls)) { ctor ; } /* ctor, with initialization of defaults */ \
- YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,BOOST_PP_SEQ_FOR_EACH(_STRIPDECL4,~,attrDecls),deprec,extras)
+ _YADE_CLASS_BASE_DOC_ATTRS_DEPREC_PY(thisClass,baseClass,docString,BOOST_PP_SEQ_FOR_EACH(_STRIPDECL4,~,attrDecls),deprec,extras)
#define _STATATTR_PY(x,thisClass,z) .def_readwrite(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(4,1,z)), &thisClass::BOOST_PP_TUPLE_ELEM(4,1,z), "|ystatic| :ydefault:`" BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(4,2,z)) "` " BOOST_PP_TUPLE_ELEM(4,3,z))
#define _STATATTR_DECL(x,y,z) static BOOST_PP_TUPLE_ELEM(4,0,z) BOOST_PP_TUPLE_ELEM(4,1,z);
@@ -195,6 +192,7 @@
#define YADE_CLASS_BASE_DOC_ATTRS(klass,base,doc,attrs) YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(klass,base,doc,attrs,,,)
#define YADE_CLASS_BASE_DOC_ATTRS_CTOR(klass,base,doc,attrs,ctor) YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(klass,base,doc,attrs,,ctor,)
#define YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(klass,base,doc,attrs,ctor,py) YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(klass,base,doc,attrs,,ctor,py)
+#define YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(klass,base,doc,attrs,inits,ctor,py) YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(klass,base,doc,attrs,,inits,ctor,py)
// for both fundamental and non-fundamental cases
#define REGISTER_SERIALIZABLE_GENERIC(name,isFundamental) \
=== modified file 'pkg/dem/Engine/PartialEngine/ThreeDTriaxialEngine.hpp'
--- pkg/dem/Engine/PartialEngine/ThreeDTriaxialEngine.hpp 2010-03-31 16:24:16 +0000
+++ pkg/dem/Engine/PartialEngine/ThreeDTriaxialEngine.hpp 2010-04-01 06:53:09 +0000
@@ -50,7 +50,7 @@
"The engine perform a triaxial compression with a control in direction 'i' in stress (if stressControl_i) else in strain.\n\n"
"For a stress control the imposed stress is specified by 'sigma_i' with a 'max_veli' depending on 'strainRatei'. To obtain the same strain rate in stress control than in strain control you need to set 'wallDamping = 0.8'.\n"
" For a strain control the imposed strain is specified by 'strainRatei'.\n"
- "With this engine you can also perform internal compaction by growing the size of particles by using :yref:TriaxialStressController::controlInternalStress . For that, just switch on 'internalCompaction=1' and fix sigma_iso=value of mean pressure that you want at the end of the internal compaction.\n"
+ "With this engine you can also perform internal compaction by growing the size of particles by using :yref:`TriaxialStressController::controlInternalStress`. For that, just switch on 'internalCompaction=1' and fix sigma_iso=value of mean pressure that you want at the end of the internal compaction.\n"
,
((Real, strainRate1,0,"target strain rate in direction 1 (./s)"))
((Real, currentStrainRate1,0,"current strain rate in direction 1 - converging to :yref:'ThreeDTriaxialEngine::strainRate1' (./s)"))
=== modified file 'pkg/dem/Engine/PartialEngine/TriaxialStateRecorder.hpp'
--- pkg/dem/Engine/PartialEngine/TriaxialStateRecorder.hpp 2010-03-31 16:24:16 +0000
+++ pkg/dem/Engine/PartialEngine/TriaxialStateRecorder.hpp 2010-04-01 06:53:09 +0000
@@ -32,7 +32,7 @@
virtual ~TriaxialStateRecorder ();
virtual void action();
- YADE_CLASS_BASE_DOC_ATTRS_CTOR(TriaxialStateRecorder,Recorder,"Engine recording triaxial variables (needs :yref:TriaxialCompressionEngine or :yref:ThreeDTriaxialEngine present in the simulation).",
+ YADE_CLASS_BASE_DOC_ATTRS_CTOR(TriaxialStateRecorder,Recorder,"Engine recording triaxial variables (needs :yref:`TriaxialCompressionEngin`e or :yref:`ThreeDTriaxialEngine` present in the simulation).",
((Real,porosity,1,"porosity of the packing [-]")), //Is it really needed to have this value as a serializable?
initRun=true;
);
=== modified file 'pkg/dem/Engine/PartialEngine/TriaxialStressController.hpp'
--- pkg/dem/Engine/PartialEngine/TriaxialStressController.hpp 2010-04-01 06:47:24 +0000
+++ pkg/dem/Engine/PartialEngine/TriaxialStressController.hpp 2010-04-01 06:53:09 +0000
@@ -12,6 +12,8 @@
#include<yade/core/Scene.hpp>
#include<yade/lib-base/Math.hpp>
+#include<boost/array.hpp>
+
class Scene;
class State;
@@ -37,7 +39,7 @@
int wall_id [6];
// vector<int> wall_id;
//! Stores the value of the translation at the previous time step, stiffness, and normal
- Vector3r previousTranslation [6];
+ boost::array<Vector3r,6> previousTranslation;
//! The value of stiffness (updated according to stiffnessUpdateInterval)
vector<Real> stiffness;
Real strain [3];
@@ -144,32 +146,24 @@
((Real,meanStress,0,""))
((Real,volumetricStrain,0,""))
,
-// /* extra initializers */
-// //((wall_id,vector<int>(6,0)))
-// ((wall_bottom_id,wall_id[0]))
-// ((wall_top_id,wall_id[1]))
-// ((wall_left_id,wall_id[2]))
-// ((wall_right_id,wall_id[3]))
-// ((wall_front_id,wall_id[4]))
-// ((wall_back_id,wall_id[5]))
+ /* extra initializers */
,
/* constructor */
first = true;
- stiffness.resize(6);
- for (int i=0; i<6; ++i){
-// wall_id[i] = 0;
- previousTranslation[i] = Vector3r::ZERO;
- stiffness[i] = 0;
- normal[i] = Vector3r::ZERO;
- strain[i]=0;}
- for (int i=0; i<3; ++i) strain[i] = 0;
- normal[wall_bottom].Y()=1;
- normal[wall_top].Y()=-1;
- normal[wall_left].X()=1;
- normal[wall_right].X()=-1;
- normal[wall_front].Z()=-1;
- normal[wall_back].Z()=1;
- porosity=1;
+ stiffness.resize(6);
+ previousTranslation.assign(Vector3r::ZERO);
+ for (int i=0; i<6; ++i){
+ normal[i] = stress[i] = force[i] = Vector3r::ZERO;
+ stiffness[i] = 0;
+ }
+ for (int i=0; i<3; ++i) strain[i] = 0;
+ normal[wall_bottom].Y()=1;
+ normal[wall_top].Y()=-1;
+ normal[wall_left].X()=1;
+ normal[wall_right].X()=-1;
+ normal[wall_front].Z()=-1;
+ normal[wall_back].Z()=1;
+ porosity=1;
,
.def_readonly("porosity",&TriaxialStressController::porosity,"")
.def_readonly("boxVolume",&TriaxialStressController::boxVolume,"")
=== modified file 'pkg/dem/meta/ConcretePM.cpp'
--- pkg/dem/meta/ConcretePM.cpp 2010-03-27 22:18:10 +0000
+++ pkg/dem/meta/ConcretePM.cpp 2010-04-01 06:53:09 +0000
@@ -186,6 +186,7 @@
else epsN+=sigmaSoft/E+(BC->isoPrestress-sigmaSoft)/(E*relKnSoft);
}
CPM_MATERIAL_MODEL
+ //cerr<<"kappaD="<<kappaD<<", epsN="<<epsN<<", neverDamage="<<neverDamage<<", epsCrackOnset="<<epsCrackOnset<<", epsFracture="<<epsFracture<<", omega="<<omega<<"="<<funcG(kappaD,epsCrackOnset,epsFracture,neverDamage);
#else
// simplified public model
epsN+=BC->isoPrestress/E;
@@ -225,6 +226,16 @@
applyForceAtContactPoint(BC->normalForce+BC->shearForce, contGeom->contactPoint, I->getId1(), contGeom->se31.position, I->getId2(), contGeom->se32.position, scene);
}
+Real Law2_Dem3DofGeom_CpmPhys_Cpm::yieldSigmaTMagnitude(Real sigmaN, Real omega, Real undamagedCohesion, Real tanFrictionAngle){
+#ifdef CPM_MATERIAL_MODEL
+ return CPM_YIELD_SIGMA_T_MAGNITUDE(sigmaN);
+#else
+ //return max((Real)0.,undamagedCohesion*(1-omega)-sigmaN*tanFrictionAngle);
+ throw std::runtime_error("Full CPM model not available in this build");
+#endif
+}
+
+
#ifdef YADE_OPENGL
/********************** Gl1_CpmPhys ****************************/
#include<yade/lib-opengl/OpenGLWrapper.hpp>
=== modified file 'pkg/dem/meta/ConcretePM.hpp'
--- pkg/dem/meta/ConcretePM.hpp 2010-03-20 12:40:44 +0000
+++ pkg/dem/meta/ConcretePM.hpp 2010-04-01 06:53:09 +0000
@@ -53,6 +53,8 @@
#include<yade/pkg-common/NormShearPhys.hpp>
#include<yade/pkg-common/LawFunctor.hpp>
+namespace py=boost::python;
+
/* Cpm state information about each body.
None of that is used for computation (at least not now), only for post-processing.
*/
@@ -176,22 +178,22 @@
if(kappaD<epsCrackOnset || neverDamage) return 0;
return 1.-(epsCrackOnset/kappaD)*exp(-(kappaD-epsCrackOnset)/epsFracture);
}
+ //! return |sigmaT| at plastic surface for given sigmaN etc; not used by the law itself
+ Real yieldSigmaTMagnitude(Real sigmaN, Real omega, Real undamagedCohesion, Real tanFrictionAngle);
void go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I, Scene* rootBody);
- // utility functions
- //! Update avgStress on all bodies (called from VTKRecorder and yade.eudoxos.particleConfinement)
- //! Might be anywhere else as well (static method)
- static void updateBodiesState(Scene*);
-
FUNCTOR2D(Dem3DofGeom,CpmPhys);
- YADE_CLASS_BASE_DOC_ATTRS(Law2_Dem3DofGeom_CpmPhys_Cpm,LawFunctor,"Constitutive law for the :ref:`cpm-model`.",
+ YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_Dem3DofGeom_CpmPhys_Cpm,LawFunctor,"Constitutive law for the :ref:`cpm-model`.",
((int,yieldSurfType,2,"yield function: 0: mohr-coulomb (original); 1: parabolic; 2: logarithmic, 3: log+lin_tension, 4: elliptic, 5: elliptic+log"))
((Real,yieldLogSpeed,.1,"scaling in the logarithmic yield surface (should be <1 for realistic results; >=0 for meaningful results)"))
((Real,yieldEllipseShift,NaN,"horizontal scaling of the ellipse (shifts on the +x axis as interactions with +y are given)"))
((Real,omegaThreshold,((void)">=1. to deactivate, i.e. never delete any contacts",1.),"damage after which the contact disappears (<1), since omega reaches 1 only for strain â+â"))
((Real,epsSoft,((void)"approximates confinement -20MPa precisely, -100MPa a little over, -200 and -400 are OK (secant)",-3e-3),"Strain at which softening in compression starts (non-negative to deactivate)"))
- ((Real,relKnSoft,.25,"Relative rigidity of the softening branch in compression (0=perfect elastic-plastic, <0 softening, >0 hardening)"))
+ ((Real,relKnSoft,.25,"Relative rigidity of the softening branch in compression (0=perfect elastic-plastic, <0 softening, >0 hardening)")),
+ /*ctor*/,
+ .def("funcG",&Law2_Dem3DofGeom_CpmPhys_Cpm::funcG,(py::arg("kappaD"),py::arg("epsCrackOnset"),py::arg("epsFracture"),py::arg("neverDamage")=false),"Damage evolution law, evaluating the :math:`\\omega` parameter. :math:`\\kappa_D` is historically maximum strain, *epsCrackOnset* (:math:`\\varepsilon_0`) = :yref:`CpmMat.epsCrackOnset`, *epsFracture* = :yref:`CpmMat.epsFracture`; if *neverDamage* is ``True``, the value returned will always be 0 (no damage).")
+ .def("yieldSigmaTMagnitude",&Law2_Dem3DofGeom_CpmPhys_Cpm::yieldSigmaTMagnitude,(py::arg("sigmaN"),py::arg("omega"),py::arg("undamagedCohesion"),py::arg("tanFrictionAngle")),"Return radius of yield surface for given material and state parameters; uses attributes of the current instance (*yieldSurfType* etc), change them before calling if you need that.")
);
DECLARE_LOGGER;
};
=== modified file 'py/_eudoxos.cpp'
--- py/_eudoxos.cpp 2010-03-22 12:32:38 +0000
+++ py/_eudoxos.cpp 2010-04-01 06:53:09 +0000
@@ -47,30 +47,6 @@
}
#endif
-/* yield surface for the CPM model; this is used only to make yield surface plot from python, for debugging */
-Real yieldSigmaTMagnitude(Real sigmaN, const shared_ptr<Law2_Dem3DofGeom_CpmPhys_Cpm>& functor){
- #ifdef CPM_YIELD_SIGMA_T_MAGNITUDE
- /* find first suitable interaction */
- Scene* rootBody=Omega::instance().getScene().get();
- shared_ptr<Interaction> I;
- FOREACH(I, *rootBody->interactions){
- if(I->isReal()) break;
- }
- if(!I->isReal()) {LOG_ERROR("No real interaction found, returning NaN!"); return NaN; }
- CpmPhys* BC=dynamic_cast<CpmPhys*>(I->interactionPhysics.get());
- if(!BC) {LOG_ERROR("Interaction physics is not a CpmPhys instance, returning NaN!"); return NaN;}
- const Real &omega(BC->omega); const Real& undamagedCohesion(BC->undamagedCohesion); const Real& tanFrictionAngle(BC->tanFrictionAngle);
- const Real& yieldLogSpeed(functor->yieldLogSpeed);
- const int& yieldSurfType(functor->yieldSurfType);
- const Real& yieldEllipseShift(functor->yieldEllipseShift);
- return CPM_YIELD_SIGMA_T_MAGNITUDE(sigmaN);
- #else
- LOG_FATAL("CPM model not available in this build.");
- throw;
- #endif
-}
-
-
// copied from _utils.cpp
Vector3r tuple2vec(const py::tuple& t){return Vector3r(py::extract<double>(t[0])(),py::extract<double>(t[1])(),py::extract<double>(t[2])());}
@@ -182,7 +158,6 @@
import_array();
YADE_SET_DOCSTRING_OPTS;
py::def("velocityTowardsAxis",velocityTowardsAxis,velocityTowardsAxis_overloads(py::args("axisPoint","axisDirection","timeToAxis","subtractDist","perturbation")));
- py::def("yieldSigmaTMagnitude",yieldSigmaTMagnitude);
// def("spiralSphereStresses2d",spiralSphereStresses2d,(python::arg("dH_dTheta"),python::arg("axis")=2));
py::def("particleConfinement",particleConfinement);
py::def("testNumpy",testNumpy);
=== modified file 'py/plot.py'
--- py/plot.py 2010-03-09 14:20:36 +0000
+++ py/plot.py 2010-04-01 06:53:09 +0000
@@ -16,13 +16,13 @@
data={} # global, common for all plots: {'name':[value,...],...}
plots={} # dictionary x-name -> (yspec,...), where yspec is either y-name or (y-name,'line-specification')
-plotsFilled={} # same as plots but with standalone plot specs filled to tuples (used internally only)
-plotLines={} # dictionary x-name -> Line2d objects (that hopefully still correspond to yspec in plots)
-needsFullReplot=True
+"Dictionary converting names in data to human-readable names (TeX names, for instance); if a variable is not specified, it is left untranslated."
+labels={}
+#plotLines={} # dictionary x-name -> Line2d objects (that hopefully still correspond to yspec in plots)
def reset():
- global data, plots, plotsFilled, plotLines, needsFullReplot
- data={}; plots={}; plotsFilled={}; plotLines={}; needsFullReplot=True;
+ global data, plots, labels # plotLines
+ data={}; plots={}; # plotLines={};
pylab.close('all')
def resetData():
@@ -31,32 +31,18 @@
# we could have a yplot class, that would hold: (yspec,...), (Line2d,Line2d,...) ?
-
plotDataCollector=None
from yade.wrapper import *
-# no longer used
-maxDataLen=1000
-## no longer used
-def reduceData(l):
- """If we have too much data, take every second value and double the step for DateGetterEngine. This will keep the samples equidistant.
- """
- if l>maxDataLen:
- global plotDataCollector
- if not plotDataCollector: plotDataCollector=O.labeledEngine('plotDataCollector') # will raise RuntimeError if not found
- if plotDataCollector.mayStretch: # may we double the period without getting over limits?
- plotDataCollector.stretchFactor=2. # just to make sure
- print "Reducing data: %d > %d"%(l,maxDataLen)
- for d in data: data[d]=data[d][::2]
- for attr in ['virtPeriod','realPeriod','iterPeriod']:
- if(plotDataCollector[attr]>0): plotDataCollector[attr]=2*plotDataCollector[attr]
-
def splitData():
"Make all plots discontinuous at this point (adds nan's to all data fields)"
addData({})
-
def reverseData():
+ """Reverse yade.plot.data order.
+
+ Useful for tension-compression test, where the initial (zero) state is loaded and, to make data continuous, last part must *end* in the zero state.
+ """
for k in data: data[k].reverse()
def addData(*d_in,**kw):
@@ -81,63 +67,61 @@
if name in d: data[name].append(d[name]) #numpy.append(data[name],[d[name]],1)
else: data[name].append(nan)
-def addPointTypeSpecifier(o):
+def _addPointTypeSpecifier(o):
"""Add point type specifier to simple variable name"""
if type(o) in [tuple,list]: return o
else: return (o,'')
-def tuplifyYAxis(pp):
+def _tuplifyYAxis(pp):
"""convert one variable to a 1-tuple"""
if type(pp) in [tuple,list]: return pp
else: return (pp,)
-
-def show(): plot()
-
-def plot():
- pylab.ion() ## # no interactive mode (hmmm, I don't know why actually...)
+def _xlateLabel(l):
+ "Return translated label; return l itself if not in the labels dict."
+ global labels
+ if l in labels.keys(): return labels[l]
+ else: return l
+
+def plot(noShow=False):
+ """Show current plot, returning the figure object.
+
+ If *noShow* is true, figure will not be shown on screen at all.
+
+ You can use
+
+ >>> from yade import plot
+ >>> plot.plot(noShow=True).saveFig('someFile.pdf')
+
+ to save the figure to file automatically.
+ """
+ if not noShow: pylab.ion() ## # no interactive mode (hmmm, I don't know why actually...)
for p in plots:
pylab.figure()
- plots_p=[addPointTypeSpecifier(o) for o in tuplifyYAxis(plots[p])]
- plotsFilled[p]=plots_p
+ plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
plots_p_y1,plots_p_y2=[],[]; y1=True
for d in plots_p:
if d[0]=='|||':
y1=False; continue
if y1: plots_p_y1.append(d)
else: plots_p_y2.append(d)
- plotLines[p]=pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[]))
- pylab.legend([_p[0] for _p in plots_p_y1],loc=('upper left' if len(plots_p_y2)>0 else 'best'))
- pylab.ylabel(','.join([_p[0] for _p in plots_p_y1]))
+ #plotLines[p]=
+ pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[]))
+ pylab.legend([_xlateLabel(_p[0]) for _p in plots_p_y1],loc=('upper left' if len(plots_p_y2)>0 else 'best'))
+ pylab.ylabel(','.join([_xlateLabel(_p[0]) for _p in plots_p_y1]))
if len(plots_p_y2)>0:
# try to move in the color palette a little further (magenta is 5th): r,g,b,c,m,y,k
origLinesColor=pylab.rcParams['lines.color']; pylab.rcParams['lines.color']='m'
# create the y2 axis
pylab.twinx()
- plotLines[p]+=[pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[]))]
- pylab.legend([_p[0] for _p in plots_p_y2],loc='upper right')
+ #plotLines[p]+=
+ [pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[]))]
+ pylab.legend([_xlateLabel(_p[0]) for _p in plots_p_y2],loc='upper right')
pylab.rcParams['lines.color']=origLinesColor
- pylab.ylabel(','.join([_p[0] for _p in plots_p_y2]))
- pylab.xlabel(p)
+ pylab.ylabel(','.join([_xlateLabel(_p[0]) for _p in plots_p_y2]))
+ pylab.xlabel(_xlateLabel(p))
if 'title' in O.tags.keys(): pylab.title(O.tags['title'])
- pylab.show()
+ if not noShow: pylab.show()
+ return pylab.gcf() # return current figure
updatePeriod=0
-def periodicUpdate(period):
- import time
- global updatePeriod
- while updatePeriod>0:
- doUpdate()
- time.sleep(updatePeriod)
-def startUpdate(period=10):
- global updatePeriod
- updatePeriod=period
- import threading
- threading.Thread(target=periodicUpdate,args=(period,),name='Thread-update').start()
-def stopUpdate():
- global updatePeriod
- updatePeriod=0
-def doUpdate():
- pylab.close('all')
- plot()
-
def saveGnuplot(baseName,term='wxt',extension=None,timestamp=False,comment=None,title=None,varData=False):
"""baseName: used for creating baseName.gnuplot (command file for gnuplot),
@@ -174,10 +158,10 @@
i=0
for p in plots:
# print p
- plots_p=[addPointTypeSpecifier(o) for o in tuplifyYAxis(plots[p])]
+ plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
if term in ['wxt','x11']: fPlot.write("set term %s %d persist\n"%(term,i))
else: fPlot.write("set term %s; set output '%s.%d.%s'\n"%(term,baseNameNoPath,i,extension))
- fPlot.write("set xlabel '%s'\n"%p)
+ fPlot.write("set xlabel '%s'\n"%_xlateLabel(p))
fPlot.write("set grid\n")
fPlot.write("set datafile missing 'nan'\n")
if title: fPlot.write("set title '%s'\n"%title)
@@ -187,13 +171,13 @@
y1=False; continue
if y1: plots_y1.append(d)
else: plots_y2.append(d)
- fPlot.write("set ylabel '%s'\n"%(','.join([_p[0] for _p in plots_y1])))
+ fPlot.write("set ylabel '%s'\n"%(','.join([_xlateLabel(_p[0]) for _p in plots_y1])))
if len(plots_y2)>0:
- fPlot.write("set y2label '%s'\n"%(','.join([_p[0] for _p in plots_y2])))
+ fPlot.write("set y2label '%s'\n"%(','.join([_xlateLabel(_p[0]) for _p in plots_y2])))
fPlot.write("set y2tics\n")
ppp=[]
- for pp in plots_y1: ppp.append(" %s using %d:%d title 'â %s(%s)' with lines"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,pp[0],p,))
- for pp in plots_y2: ppp.append(" %s using %d:%d title '%s(%s) â' with lines axes x1y2"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,pp[0],p,))
+ for pp in plots_y1: ppp.append(" %s using %d:%d title 'â %s(%s)' with lines"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,_xlateLabel(pp[0]),_xlateLabel(p),))
+ for pp in plots_y2: ppp.append(" %s using %d:%d title '%s(%s) â' with lines axes x1y2"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,_xlateLabel(pp[0]),_xlateLabel(p),))
fPlot.write("plot "+",".join(ppp)+"\n")
i+=1
fPlot.close()