Commit 9072edf4 authored by Václav Šmilauer's avatar Václav Šmilauer
Browse files

1. replace {pre,post}ProcessAttributes by {pre,post}{Save,Load} (not virtual)

2. change attribute specification adding and additional attribute flags (read-only from python, not saved, should call postLoad after changing value from python)
3. Macros cleanup in Serializable
4. Support clang for compilation (more than 2x faster) https://yade-dem.org/wiki/Compilation_with_LLVM/clang
(documentation not yet update to reflect those changes fully, sorry)
parent a75a1829
......@@ -149,11 +149,13 @@ opts.AddVariables(
('realVersion','Revision (usually bzr revision); guessed automatically unless specified',None),
('CPPPATH', 'Additional paths for the C preprocessor (colon-separated)','/usr/include/vtk-5.0:/usr/include/vtk-5.2:/usr/include/vtk-5.4:/usr/include/eigen2'), # hardy has vtk-5.0
('LIBPATH','Additional paths for the linker (colon-separated)',None),
('libstdcxx','Specify libstdc++ location by hand (opened dynamically at startup); only needed when compiling with clang',None),
('QT4DIR','Directory where Qt4 is installed','/usr/share/qt4'),
('PATH','Path (not imported automatically from the shell) (colon-separated)',None),
('CXX','The c++ compiler','g++'),
('CXXFLAGS','Additional compiler flags for compilation (like -march=core2).',None,None,Split),
('march','Architecture to use with -march=... when optimizing','native',None,None),
BoolVariable('mono','[experimental] Build only one shared library and make all other files (python objects, for instance) only be symlinks.',0),
#('SHLINK','Linker for shared objects','g++'),
('SHCCFLAGS','Additional compiler flags for linking (for plugins).',None,None,Split),
BoolVariable('QUAD_PRECISION','typedef Real as long double (=quad)',0),
......@@ -276,6 +278,10 @@ def CheckCXX(context):
return ret
def CheckLibStdCxx(context):
context.Message('Finding libstdc++ library... ')
if context.env.has_key('libstdcxx') and context.env['libstdcxx']:
l=context.env['libstdcxx']
context.Result(l+' (specified by the user)')
return l
ret=os.popen(context.env['CXX']+' -print-file-name=libstdc++.so').readlines()[0][:-1]
context.env['libstdcxx']=ret
context.Result(ret)
......@@ -388,6 +394,7 @@ if not env.GetOption('clean'):
if 'gts' in env['features']:
env.ParseConfig('pkg-config gts --cflags --libs');
ok=conf.CheckLibWithHeader('gts','gts.h','c++','gts_object_class();',autoadd=1)
env.Append(CPPDEFINES='PYGTS_HAS_NUMPY')
if not ok: featureNotOK('gts')
if 'log4cxx' in env['features']:
ok=conf.CheckLibWithHeader('log4cxx','log4cxx/logger.h','c++','log4cxx::Logger::getLogger("");',autoadd=1)
......@@ -399,7 +406,7 @@ if not env.GetOption('clean'):
ok=conf.CheckLibWithHeader('CGAL','CGAL/Exact_predicates_inexact_constructions_kernel.h','c++','CGAL::Exact_predicates_inexact_constructions_kernel::Point_3();')
env.Append(CXXFLAGS='-frounding-math') # required by cgal, otherwise we get assertion failure at startup
if not ok: featureNotOK('cgal')
env.Append(LIBS='yade-support')
if not env['mono']: env.Append(LIBS='yade-support')
env.Append(CPPDEFINES=['YADE_'+f.upper().replace('-','_') for f in env['features']])
......@@ -487,7 +494,7 @@ if env['PLATFORM']=='darwin':
#env.Append(LINKFLAGS=['-Z']) # ?? FIXME
env.Append(FRAMEWORKS=['CoreServices','Carbon'])
else:
env.Append(LINKFLAGS=['-rdynamic','-z','origin'])
env.Append(LINKFLAGS=['-rdynamic','-Wl,-z,origin'])
if not env['debug']: env.Append(SHLINKFLAGS=['-W,--strip-all'])
# makes dynamic library loading easier (no LD_LIBRARY_PATH) and perhaps faster
......@@ -606,8 +613,12 @@ def linkPlugins(plugins):
env['linkPlugins']=linkPlugins
env['buildPlugs']=buildPlugs
# read top-level SConscript file. It is used only so that build_dir is set. This file reads all necessary SConscripts
env.SConscript(dirs=['.'],build_dir=buildDir,duplicate=0)
if env['mono']:
env.SConscript('SConscript-mono',build_dir=buildDir,duplicate=0)
else:
# read top-level SConscript file. It is used only so that build_dir is set. This file reads all necessary SConscripts
env.SConscript(dirs=['.'],build_dir=buildDir,duplicate=0)
#################################################################################
## remove plugins that are in the target dir but will not be installed now
......
......@@ -63,23 +63,19 @@ class Body: public Serializable{
friend class BodyContainer;
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Body,Serializable,"A particle, basic element of simulation; interacts with other bodies.",
((Body::id_t,id,Body::ID_NONE,"[will be overridden]"))
((Body::id_t,id,Body::ID_NONE,Attr::pyReadonly,"Unique id of this body."))
((int,groupMask,1,"Bitmask for determining interactions."))
((int,flags,FLAG_DYNAMIC|FLAG_BOUNDED,"DO NOT ACCESS DIRECTLY; documented below"))
((int,groupMask,1,,"Bitmask for determining interactions."))
((int,flags,FLAG_DYNAMIC|FLAG_BOUNDED,Attr::pyReadonly,"Bits of various body-related flags. *Do not access directly*. In c++, use isDynamic/setDynamic, isBounded/setBounded. In python, use :yref:`Body.dynamic` and :yref:`Body.bounded`."))
((shared_ptr<Material>,material,,":yref:`Material` instance associated with this body."))
((shared_ptr<State>,state,new State,"Physical :yref:`state<State>`."))
((shared_ptr<Shape>,shape,,"Geometrical :yref:`Shape`."))
((shared_ptr<Bound>,bound,,":yref:`Bound`, approximating volume for the purposes of collision detection."))
((shared_ptr<Material>,material,,,":yref:`Material` instance associated with this body."))
((shared_ptr<State>,state,new State,,"Physical :yref:`state<State>`."))
((shared_ptr<Shape>,shape,,,"Geometrical :yref:`Shape`."))
((shared_ptr<Bound>,bound,,,":yref:`Bound`, approximating volume for the purposes of collision detection."))
((int,clumpId,Body::ID_NONE,"[will be overridden]")),
((int,clumpId,Body::ID_NONE,Attr::pyReadonly,"Id of clump this body makes part of; invalid number if not part of clump; see :yref:`Body::isStandalone`, :yref:`Body::isClump`, :yref:`Body::isClumpMember` properties. \n\n This property is not meant to be modified directly from Python, use :yref:`O.bodies.appendClumped<BodyContainer.appendClumped>` instead.")),
/* ctor */,
/* py */
// make those read-only from python
.def_readonly("id",&Body::id,"Unique id of this body") // overwrites automatic def_readwrite("id",...) earlier
.def_readonly("clumpId",&Body::clumpId,"Id of clump this body makes part of; invalid number if not part of clump; see :yref:`Body::isStandalone`, :yref:`Body::isClump`, :yref:`Body::isClumpMember` properties. \n\n This property is not meant to be modified directly from Python, use :yref:`O.bodies.appendClumped<BodyContainer.appendClumped>` instead.")
.def_readonly("flags",&Body::flags,"Bits of various body-related flags. *Do not access directly*. In c++, use isDynamic/setDynamic, isBounded/setBounded. In python, use :yref:`Body.dynamic` and :yref:`Body.bounded`. :ydefault:`FLAG_DYNAMIC | FLAG_BOUNDED` ")
//
.def_readwrite("mat",&Body::material,"Shorthand for :yref:`Body::material`")
.add_property("isDynamic",&Body::isDynamic,&Body::setDynamic,"Deprecated synonym for :yref:`Body::dynamic` |ydeprecated|")
......
......@@ -21,17 +21,16 @@
class Bound: public Serializable, public Indexable{
public:
Vector3r min,max;
YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(Bound,Serializable,"Object bounding part of space taken by associated body; might be larger, used to optimalize collision detection",
((Vector3r,color,Vector3r(1,1,1),"Color for rendering this object")),
((Vector3r,color,Vector3r(1,1,1),,"Color for rendering this object"))
((Vector3r,min,Vector3r(NaN,NaN,NaN),(Attr::noSave | Attr::pyReadonly),"Lower corner of box containing this bound (and the :yref:`Body` as well)"))
((Vector3r,max,Vector3r(NaN,NaN,NaN),(Attr::noSave | Attr::pyReadonly),"Lower corner of box containing this bound (and the :yref:`Body` as well)"))
,
/*deprec*/ ((diffuseColor,color,"For consistency with Shape.color")),
/* init */,
/* ctor*/ min=max=Vector3r::Zero(),
/* ctor*/,
/*py*/
YADE_PY_TOPINDEXABLE(Bound)
// we want those to be accessible from python, but not serialized
.def_readonly("min",&Bound::min,"Lower corner of box containing this bound (and the :yref:`Body` as well)")
.def_readonly("max",&Bound::max,"Upper corner of box containing this bound (and the :yref:`Body` as well)")
);
REGISTER_INDEX_COUNTER(Bound);
};
......
......@@ -90,16 +90,16 @@ class Cell: public Serializable{
Matrix3r getTrsf(){ return trsf; }
void setTrsf(const Matrix3r& m){ trsf=m; integrateAndUpdate(0); }
void postProcessAttributes(bool deserializing){ if(deserializing) integrateAndUpdate(0); }
void postLoad(Cell&){ integrateAndUpdate(0); }
Vector3r wrapShearedPt_py(const Vector3r& pt){ return wrapShearedPt(pt);}
Vector3r wrapPt_py(const Vector3r& pt){ return wrapPt(pt);}
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Cell,Serializable,"Parameters of periodic boundary conditions. Only applies if O.isPeriodic==True.",
((Vector3r,refSize,Vector3r(1,1,1),"[will be overridden below]"))
((Matrix3r,trsf,Matrix3r::Identity(),"[will be overridden below]"))
((Matrix3r,velGrad,Matrix3r::Zero(),"Velocity gradient of the transformation; used in NewtonIntegrator."))
((Matrix3r,Hsize,Matrix3r::Zero(),"The current period size (one column per box edge) |yupdate|")),
((Vector3r,refSize,Vector3r(1,1,1),,"[will be overridden below]"))
((Matrix3r,trsf,Matrix3r::Identity(),,"[will be overridden below]"))
((Matrix3r,velGrad,Matrix3r::Zero(),,"Velocity gradient of the transformation; used in NewtonIntegrator."))
((Matrix3r,Hsize,Matrix3r::Zero(),,"The current period size (one column per box edge) |yupdate|")),
/*ctor*/ integrateAndUpdate(0),
/*py*/
......
......@@ -16,6 +16,3 @@ Functor::~Functor(){}; // vtable
Dispatcher::~Dispatcher(){}
//void Dispatcher::postProcessAttributes(bool deserializing){
// FOREACH(const shared_ptr<Functor>& f, functors) add(f);
//}
......@@ -40,15 +40,15 @@ Because we need literal functor and class names for registration in python, we p
#define _YADE_DIM_DISPATCHER_FUNCTOR_DOC_ATTRS_CTOR_PY(Dim,DispatcherT,FunctorT,doc,attrs,ctor,py) \
typedef FunctorT FunctorType; \
void updateScenePtr(){ FOREACH(shared_ptr<FunctorT> f, functors){ f->scene=scene; }} \
virtual void postProcessAttributes(bool deserializing){ if(deserializing) { clearMatrix(); FOREACH(shared_ptr<FunctorT> f, functors) add(static_pointer_cast<FunctorT>(f)); } } \
void postLoad(DispatcherT&){ clearMatrix(); FOREACH(shared_ptr<FunctorT> f, functors) add(static_pointer_cast<FunctorT>(f)); } \
virtual void add(FunctorT* f){ add(shared_ptr<FunctorT>(f)); } \
virtual void add(shared_ptr<FunctorT> f){ bool dupe=false; string fn=f->getClassName(); FOREACH(const shared_ptr<FunctorT>& f, functors) { if(fn==f->getClassName()) dupe=true; } if(!dupe) functors.push_back(f); addFunctor(f); } \
BOOST_PP_CAT(_YADE_DISPATCHER,BOOST_PP_CAT(Dim,D_FUNCTOR_ADD))(FunctorT,f) \
boost::python::list functors_get(void) const { boost::python::list ret; FOREACH(const shared_ptr<FunctorT>& f, functors){ ret.append(f); } return ret; } \
void functors_set(const vector<shared_ptr<FunctorT> >& ff){ functors.clear(); FOREACH(const shared_ptr<FunctorT>& f, ff) add(f); postProcessAttributes(true); } \
void functors_set(const vector<shared_ptr<FunctorT> >& ff){ functors.clear(); FOREACH(const shared_ptr<FunctorT>& f, ff) add(f); postLoad(*this); } \
void pyHandleCustomCtorArgs(python::tuple& t, python::dict& d){ if(python::len(t)==0)return; if(python::len(t)!=1) throw invalid_argument("Exactly one list of " BOOST_PP_STRINGIZE(FunctorT) " must be given."); typedef std::vector<shared_ptr<FunctorT> > vecF; vecF vf=boost::python::extract<vecF>(t[0])(); functors_set(vf); t=python::tuple(); } \
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(DispatcherT,Dispatcher,"Dispatcher calling :yref:`functors<" BOOST_PP_STRINGIZE(FunctorT) ">` based on received argument type(s).\n\n" doc, \
((vector<shared_ptr<FunctorT> >,functors,,"Functors active in the dispatch mechanism [overridden below].")) /*additional attrs*/ attrs, \
((vector<shared_ptr<FunctorT> >,functors,,,"Functors active in the dispatch mechanism [overridden below].")) /*additional attrs*/ attrs, \
/*ctor*/ ctor, /*py*/ py .add_property("functors",&DispatcherT::functors_get,&DispatcherT::functors_set,"Functors associated with this dispatcher." " :yattrtype:`vector<shared_ptr<" BOOST_PP_STRINGIZE(FunctorT) "> >` ") \
.def("dispMatrix",&DispatcherT::dump,python::arg("names")=true,"Return dictionary with contents of the dispatch matrix.").def("dispFunctor",&DispatcherT::getFunctor,"Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws."); \
)
......@@ -149,7 +149,7 @@ class Dispatcher1D : public Dispatcher,
typedef FunctorType functorType;
typedef DynLibDispatcher<TYPELIST_1(baseClass),FunctorType,typename FunctorType::ReturnType,typename FunctorType::ArgumentTypes,autoSymmetry> dispatcherBase;
shared_ptr<FunctorType> getFunctor(shared_ptr<baseClass> arg){ return getExecutor(arg); }
shared_ptr<FunctorType> getFunctor(shared_ptr<baseClass> arg){ return dispatcherBase::getExecutor(arg); }
python::dict dump(bool convertIndicesToNames){
python::dict ret;
FOREACH(const DynLibDispatcher_Item1D& item, dispatcherBase::dataDispatchMatrix1D()){
......@@ -200,7 +200,7 @@ class Dispatcher2D : public Dispatcher,
typedef baseClass2 argType2;
typedef FunctorType functorType;
typedef DynLibDispatcher<TYPELIST_2(baseClass1,baseClass2),FunctorType,typename FunctorType::ReturnType,typename FunctorType::ArgumentTypes,autoSymmetry> dispatcherBase;
shared_ptr<FunctorType> getFunctor(shared_ptr<baseClass1> arg1, shared_ptr<baseClass2> arg2){ return getExecutor(arg1,arg2); }
shared_ptr<FunctorType> getFunctor(shared_ptr<baseClass1> arg1, shared_ptr<baseClass2> arg2){ return dispatcherBase::getExecutor(arg1,arg2); }
python::dict dump(bool convertIndicesToNames){
python::dict ret;
FOREACH(const DynLibDispatcher_Item2D& item, dispatcherBase::dataDispatchMatrix2D()){
......
......@@ -47,7 +47,7 @@ class Engine: public Serializable{
DECLARE_LOGGER;
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Engine,Serializable,"Basic execution unit of simulation, called from the simulation loop (O.engines)",
((string,label,,"Textual label for this object; must be valid python identifier, you can refer to it directly from python.")),
((string,label,,,"Textual label for this object; must be valid python identifier, you can refer to it directly from python.")),
/* ctor */ scene=Omega::instance().getScene().get() ,
/* py */
.add_property("execTime",&Engine::timingInfo_nsec_get,&Engine::timingInfo_nsec_set,"Cummulative time this Engine took to run (only used if :yref:`O.timingEnabled<Omega.timingEnabled>`\\ ==\\ ``True``).")
......
......@@ -24,7 +24,7 @@ class Functor: public Serializable
Scene* scene;
virtual ~Functor(); // defined in Dispatcher.cpp
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Functor,Serializable,"Function-like object that is called by Dispatcher, if types of arguments match those the Functor declares to accept.",
((string,label,,"Textual label for this object; must be valid python identifier, you can refer to it directly fron python (must be a valid python identifier).")),
((string,label,,,"Textual label for this object; must be valid python identifier, you can refer to it directly fron python (must be a valid python identifier).")),
/*ctor*/,
.def_readonly("timingDeltas",&Functor::timingDeltas,"Detailed information about timing inside the Dispatcher itself. Empty unless enabled in the source code and O.timingEnabled==True.")
.add_property("bases",&Functor::getFunctorTypes,"Ordered list of types (as strings) this functor accepts.")
......
......@@ -8,6 +8,8 @@
#include "GroupRelationData.hpp"
#ifdef YADE_GROUP_RELATION_DATA
GroupRelationData::GroupRelationData() : ngrp_(2), npar_(0)
{
isActivated_ = false;
......@@ -294,19 +296,8 @@ void GroupRelationData::write(ostream & os)
}
*/
void GroupRelationData::preProcessAttributes(bool deserializing)
{
if(deserializing)
{
//
}
}
void GroupRelationData::postProcessAttributes(bool deserializing)
void GroupRelationData::postLoad(GroupRelationData&)
{
if(deserializing)
{
string cmdstring = "";
for (unsigned int i = 0 ; i< commands_.size() ; ++i)
cmdstring = cmdstring + commands_[i] + " ";
......@@ -317,9 +308,8 @@ void GroupRelationData::postProcessAttributes(bool deserializing)
cout << istr.str() << endl;
read(istr);
}
}
#endif
......@@ -8,6 +8,13 @@
#pragma once
// conditionally disable GroupRelationData, remove the #if 0 to re-enable
// is anyone using those? Vincent?
#if 0
#define YADE_GROUP_RELATION_DATA
#include<yade/lib-serialization/Serializable.hpp>
#include <iostream>
......@@ -104,9 +111,9 @@ public:
REGISTER_ATTRIBUTES(Serializable,(commands_));
REGISTER_CLASS_AND_BASE(GroupRelationData,Serializable);
protected : virtual void preProcessAttributes (bool deserializing);
public : virtual void postProcessAttributes (bool deserializing);
public:
void postLoad(GroupRelationData&);
};
REGISTER_SERIALIZABLE(GroupRelationData);
#endif
......@@ -61,18 +61,16 @@ class Interaction : public Serializable
void init();
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Interaction,Serializable,"Interaction between pair of bodies.",
((Body::id_t,id1,0,"[override below]"))
((Body::id_t,id2,0,"[override below]"))
((long,iterMadeReal,-1,"Step number at which the interaction was fully (in the sense of interactionGeometry and interactionPhysics) created. (Should be touched only by :yref:`InteractionPhysicsDispatcher` and :yref:`InteractionDispatchers`, therefore they are made friends of Interaction"))
((shared_ptr<InteractionGeometry>,interactionGeometry,,"Geometry part of the interaction."))
((shared_ptr<InteractionPhysics>,interactionPhysics,,"Physical (material) part of the interaction."))
((Vector3i,cellDist,Vector3i(0,0,0),"Distance of bodies in cell size units, if using periodic boundary conditions; id2 is shifted by this number of cells from its :yref:`State::pos` coordinates for this interaction to exist. Assigned by the collider.\n\n.. warning::\n\t(internal) cellDist must survive Interaction::reset(), it is only initialized in ctor. Interaction that was cancelled by the constitutive law, was reset() and became only potential must have the priod information if the geometric functor again makes it real. Good to know after few days of debugging that :-)")),
((Body::id_t,id1,0,Attr::pyReadonly,":yref:`Id<Body::id>` of the first body in this interaction."))
((Body::id_t,id2,0,Attr::pyReadonly,":yref:`Id<Body::id>` of the first body in this interaction."))
((long,iterMadeReal,-1,,"Step number at which the interaction was fully (in the sense of interactionGeometry and interactionPhysics) created. (Should be touched only by :yref:`InteractionPhysicsDispatcher` and :yref:`InteractionDispatchers`, therefore they are made friends of Interaction"))
((shared_ptr<InteractionGeometry>,interactionGeometry,,,"Geometry part of the interaction."))
((shared_ptr<InteractionPhysics>,interactionPhysics,,,"Physical (material) part of the interaction."))
((Vector3i,cellDist,Vector3i(0,0,0),,"Distance of bodies in cell size units, if using periodic boundary conditions; id2 is shifted by this number of cells from its :yref:`State::pos` coordinates for this interaction to exist. Assigned by the collider.\n\n.. warning::\n\t(internal) cellDist must survive Interaction::reset(), it is only initialized in ctor. Interaction that was cancelled by the constitutive law, was reset() and became only potential must have the priod information if the geometric functor again makes it real. Good to know after few days of debugging that :-)")),
/* ctor */ init(),
/*py*/
.def_readwrite("geom",&Interaction::interactionGeometry,"Shorthand for :yref:`Interaction::interactionGeometry`")
.def_readwrite("phys",&Interaction::interactionPhysics,"Shorthand for :yref:`Interaction::interactionPhysics`")
.def_readonly("id1",&Interaction::id1,":yref:`Id<Body::id>` of the first body in this interaction.")
.def_readonly("id2",&Interaction::id2,":yref:`Id<Body::id>` of the second body in this interaction.")
.add_property("isReal",&Interaction::isReal,"True if this interaction has both geom and phys; False otherwise.")
);
};
......
......@@ -138,17 +138,18 @@ struct compPtrInteraction{
}
};
void InteractionContainer::preProcessAttributes(bool deserializing){
if(deserializing) { interaction.clear(); return; }
void InteractionContainer::preSave(InteractionContainer&){
FOREACH(const shared_ptr<Interaction>& I, *this){
if(I->interactionGeometry || I->interactionPhysics) interaction.push_back(I);
// since requestErase'd interactions have no interaction physics/geom, they are not saved
}
if(serializeSorted) std::sort(interaction.begin(),interaction.end(),compPtrInteraction());
}
void InteractionContainer::postSave(InteractionContainer&){ interaction.clear(); }
void InteractionContainer::postProcessAttributes(bool deserializing){
if(!deserializing){interaction.clear(); return;}
void InteractionContainer::preLoad(InteractionContainer&){ interaction.clear(); }
void InteractionContainer::postLoad(InteractionContainer&){
clear();
FOREACH(const shared_ptr<Interaction>& I, interaction){ insert(I); }
interaction.clear();
......
......@@ -133,8 +133,11 @@ class InteractionContainer: public Serializable{
return ret;
}
virtual void preProcessAttributes(bool deserializing);
virtual void postProcessAttributes(bool deserializing);
void preLoad(InteractionContainer&);
void postLoad(InteractionContainer&);
void preSave(InteractionContainer&);
void postSave(InteractionContainer&);
REGISTER_ATTRIBUTES(Serializable,(interaction)(serializeSorted));
REGISTER_CLASS_AND_BASE(InteractionContainer,Serializable);
......
#include<stdexcept>
#include<yade/core/Material.hpp>
#include<yade/core/Scene.hpp>
#include<boost/foreach.hpp>
#ifndef FOREACH
#define FOREACH BOOST_FOREACH
......
......@@ -35,13 +35,12 @@ class Material: public Serializable, public Indexable{
static const shared_ptr<Material> byLabel(const std::string& label, shared_ptr<Scene> scene) {return byLabel(label,scene.get());}
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Material,Serializable,"Material properties of a :yref:`body<Body>`.",
((int,id,((void)"not shared",-1),"[id of shared material, overridden below]"))
((string,label,,"Textual identifier for this material; can be used for shared materials lookup in :yref:`MaterialContainer`."))
((Real,density,1000,"Density of the material [kg/m³]")),
((int,id,((void)"not shared",-1),Attr::pyReadonly,"Numeric id of this material; is non-negative only if this Material is shared (i.e. in O.materials), -1 otherwise. This value is set automatically when the material is inserted to the simulation via :yref:`O.materials.append<MaterialContainer.append>`. (This id was necessary since before boost::serialization was used, shared pointers were not tracked properly; it might disappear in the future)"))
((string,label,,,"Textual identifier for this material; can be used for shared materials lookup in :yref:`MaterialContainer`."))
((Real,density,1000,,"Density of the material [kg/m³]")),
/* ctor */,
/*py*/
.def("newAssocState",&Material::newAssocState,"Return new :yref:`State` instance, which is associated with this :yref:`Material`. Some materials have special requirement on :yref:`Body::state` type and calling this function when the body is created will ensure that they match. (This is done automatically if you use utils.sphere, … functions from python).")
.def_readonly("id",&Material::id,"Numeric id of this material; is non-negative only if this Material is shared (i.e. in O.materials), -1 otherwise. This value is set automatically when the material is inserted to the simulation via :yref:`O.materials.append<MaterialContainer.append>`. (This id is necessary since yade::serialization doesn't track shared pointers, but might disappear in the future)")
YADE_PY_TOPINDEXABLE(Material)
);
REGISTER_INDEX_COUNTER(Material);
......
......@@ -15,7 +15,7 @@ class PartialEngine: public Engine{
public:
virtual ~PartialEngine() {};
YADE_CLASS_BASE_DOC_ATTRS(PartialEngine,Engine,"Engine affecting only particular bodies in the simulation, defined by *subscribedBodies*.",
((std::vector<int>,subscribedBodies,,":yref:`Ids<Body::id>` of bodies affected by this PartialEngine."))
((std::vector<int>,subscribedBodies,,,":yref:`Ids<Body::id>` of bodies affected by this PartialEngine."))
);
};
REGISTER_SERIALIZABLE(PartialEngine);
......
......@@ -55,7 +55,6 @@ env.Install('$PREFIX/lib/yade$SUFFIX/lib',[
'yade-support',
'rt', # realtime lib, for clock_gettime
]+
([env['QGLVIEWER_LIB']] if 'qt3' in env['features'] else [])+
(['yade-opengl'] if 'opengl' in env['features'] else [])
,
)
......
......@@ -58,7 +58,7 @@ Scene::Scene(): bodies(new BodyContainer), interactions(new InteractionContainer
void Scene::postProcessAttributes(bool deserializing){
void Scene::postLoad(Scene&){
/* since yade::serialization doesn't properly handle shared pointers, iterate over all bodies and make materials shared again, if id>=0 */
FOREACH(const shared_ptr<Body>& b, *bodies){
if(!b) continue; // erased body
......
......@@ -17,9 +17,10 @@
#include"Material.hpp"
#include"DisplayParameters.hpp"
#include"ForceContainer.hpp"
#include"GroupRelationData.hpp"
#include"InteractionContainer.hpp"
#include"GroupRelationData.hpp"
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif
......@@ -54,7 +55,9 @@ class Scene: public Serializable{
//! "hash maps" of display parameters (since yade::serialization has no support for maps, emulate it via vector of strings in format key=value)
vector<shared_ptr<DisplayParameters> > dispParams;
shared_ptr<GroupRelationData> grpRelationData;
#ifdef YADE_GROUP_RELATION_DATA
shared_ptr<GroupRelationData> grpRelationData;
#endif
Scene();
......@@ -82,11 +85,14 @@ class Scene: public Serializable{
bool needsInitializers;
// for GL selection
Body::id_t selectedBody;
protected :
virtual void postProcessAttributes(bool deserializing);
void postLoad(Scene&);
REGISTER_ATTRIBUTES(Serializable,
(tags)
(grpRelationData)
#ifdef YADE_GROUP_RELATION_DATA
(grpRelationData)
#endif
(engines)
(initializers)
(bodies)
......
......@@ -24,9 +24,9 @@ class Shape: public Serializable, public Indexable {
#endif
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Shape,Serializable,"Geometry of a body",
((Vector3r,color,Vector3r(1,1,1),"Color for rendering (normalized RGB)."))
((bool,wire,false,"Whether this Shape is rendered using color surfaces, or only wireframe (can still be overridden by global config of the renderer)."))
((bool,highlight,false,"Whether this Shape will be highlighted when rendered.")),
((Vector3r,color,Vector3r(1,1,1),,"Color for rendering (normalized RGB)."))
((bool,wire,false,,"Whether this Shape is rendered using color surfaces, or only wireframe (can still be overridden by global config of the renderer)."))
((bool,highlight,false,,"Whether this Shape will be highlighted when rendered.")),
/*ctor*/,
/*py*/ YADE_PY_TOPINDEXABLE(Shape)
);
......
......@@ -61,17 +61,17 @@ class State: public Serializable, public Indexable{
//State(): se3(Vector3r::Zero(),Quaternionr::Identity()),pos(se3.position),vel(Vector3r::Zero()),accel(Vector3r::Zero()),mass(0.),ori(se3.orientation),angVel(Vector3r::Zero()),angAccel(Vector3r::Zero()),angMom(Vector3r::Zero()),inertia(Vector3r::Zero()),refPos(Vector3r::Zero()),refOri(Quaternionr::Identity()),blockedDOFs(DOF_NONE){}
YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(State,Serializable,"State of a body (spatial configuration, internal variables).",
((Se3r,se3,Se3r(Vector3r::Zero(),Quaternionr::Identity()),"Position and orientation as one object."))
((Vector3r,vel,Vector3r::Zero(),"Current linear velocity."))
((Vector3r,accel,Vector3r::Zero(),"Current acceleration."))
((Real,mass,0,"Mass of this body"))
((Vector3r,angVel,Vector3r::Zero(),"Current angular velocity"))
((Vector3r,angAccel,Vector3r::Zero(),"Current angular acceleration"))
((Vector3r,angMom,Vector3r::Zero(),"Current angular momentum"))
((Vector3r,inertia,Vector3r::Zero(),"Inertia of associated body, in local coordinate system."))
((Vector3r,refPos,Vector3r::Zero(),"Reference position"))
((Quaternionr,refOri,Quaternionr::Identity(),"Reference orientation"))
((unsigned,blockedDOFs,,"[Will be overridden]")),
((Se3r,se3,Se3r(Vector3r::Zero(),Quaternionr::Identity()),,"Position and orientation as one object."))
((Vector3r,vel,Vector3r::Zero(),,"Current linear velocity."))
((Vector3r,accel,Vector3r::Zero(),,"Current acceleration."))
((Real,mass,0,,"Mass of this body"))
((Vector3r,angVel,Vector3r::Zero(),,"Current angular velocity"))
((Vector3r,angAccel,Vector3r::Zero(),,"Current angular acceleration"))
((Vector3r,angMom,Vector3r::Zero(),,"Current angular momentum"))
((Vector3r,inertia,Vector3r::Zero(),,"Inertia of associated body, in local coordinate system."))
((Vector3r,refPos,Vector3r::Zero(),,"Reference position"))
((Quaternionr,refOri,Quaternionr::Identity(),,"Reference orientation"))
((unsigned,blockedDOFs,,,"[Will be overridden]")),
/* additional initializers */
((pos,se3.position))
((ori,se3.orientation)),
......
......@@ -24,8 +24,8 @@ class TimeStepper: public GlobalEngine{
YADE_CLASS_BASE_DOC_ATTRS(
TimeStepper,GlobalEngine,"Engine defining time-step (fundamental class)",
((bool,active,true,"is the engine active?"))
((unsigned int,timeStepUpdateInterval,1,"dt update interval")));
((bool,active,true,,"is the engine active?"))
((unsigned int,timeStepUpdateInterval,1,,"dt update interval")));
};
REGISTER_SERIALIZABLE(TimeStepper);
......
......@@ -113,12 +113,17 @@ def ydefault_role(role,rawtext,text,lineno,inliner,options={},content=[]):
def yattrtype_role(role,rawtext,text,lineno,inliner,options={},content=[]):
"Handle the :yattrtype:`something` role. fixSignature handles it now in the member signature itself, this merely expands to nothing."
return [],[]
# FIXME: should return readable representation of bits of the number (yade.wrapper.AttrFlags enum)
def yattrflags_role(role,rawtext,text,lineno,inliner,options={},content=[]):
"Handle the :yattrflags:`something` role. fixSignature handles it now in the member signature itself."
return [],[]
from docutils.parsers.rst import roles
roles.register_canonical_role('yref', yaderef_role)
roles.register_canonical_role('ysrc', yadesrc_role)
roles.register_canonical_role('ydefault', ydefault_role)
roles.register_canonical_role('yattrtype', yattrtype_role)
roles.register_canonical_role('yattrflags', yattrflags_role)
## http://sphinx.pocoo.org/config.html#confval-rst_epilog
......@@ -170,6 +175,7 @@ def fixDocstring(app,what,name,obj,options,lines):
for i in range(0,len(lines)):
lines[i]=lines[i].replace(':ydefault:``','')
lines[i]=lines[i].replace(':yattrtype:``','')
lines[i]=lines[i].replace(':yattrflags:``','')
#lines[i]=re.sub(':``',':` `',lines[i])
# remove signature of boost::python function docstring, which is the first line of the docstring
if isBoostFunc(what,obj):
......
......@@ -85,7 +85,7 @@ class AttrEditor_Int(AttrEditor,QSpinBox):
def __init__(self,parent,getter,setter):
AttrEditor.__init__(self,getter,setter)
QSpinBox.__init__(self,parent)
self.setRange(int(-1e10),int(1e10)); self.setSingleStep(1);
self.setRange(int(-1e9),int(1e9)); self.setSingleStep(1);
self.valueChanged.connect(self.update)
def refresh(self): self.setValue(self.getter())
def update(self): self.trySetter(self.value())
......@@ -209,7 +209,7 @@ class AttrEditor_MatrixXi(AttrEditor,QFrame):
self.grid=QGridLayout(self); self.grid.setSpacing(0); self.grid.setMargin(0)
for row,col in itertools.product(range(self.rows),range(self.cols)):
w=QSpinBox()
w.setRange(int(-1e10),int(1e10)); w.setSingleStep(1);
w.setRange(int(-1e9),int(1e9)); w.setSingleStep(1);
self.grid.addWidget(w,row,col);
w.valueChanged.connect(self.update)
self.refresh()
......@@ -537,7 +537,10 @@ class NewSerializableDialog(QDialog):
self.setWindowTitle('Create new object of type %s'%baseClassName)
self.layout=QVBoxLayout(self)
self.combo=QComboBox(self)
childs=list(yade.system.childClasses(baseClassName,includeBase=includeBase)); childs.sort()
childs=list(yade.system.childClasses(baseClassName,includeBase=False)); childs.sort()
if includeBase:
self.combo.addItem(baseClassName)
self.combo.insertSeparator(1000)
self.combo.addItems(childs)
self.combo.currentIndexChanged.connect(self.comboSlot)
self.scroll=QScrollArea(self)
......
......@@ -14,53 +14,55 @@
#include<yade/lib-base/Math.hpp>
// disable temporarily
//#include<boost/static_assert.hpp><