← Back to team overview

yade-dev team mailing list archive

Re: [Branch ~yade-pkg/yade/git-trunk] Rev 3687: Merge branch 'master' of github.com:yade/trunk

 

Hello,
is this ok, or did I do something wrong? the same question for the next
noreply message..
Thanks
Jan


2013/9/8 <noreply@xxxxxxxxxxxxx>

> Merge authors:
>   Anton Gladky (gladky-anton)
>   Bruno Chareyre (bruno-chareyre)
>   Klaus Thoeni (klaus.thoeni)
> ------------------------------------------------------------
> revno: 3687 [merge]
> committer: Jan Stransky <jan.stransky@xxxxxxxxxxx>
> timestamp: Sun 2013-09-08 13:19:06 +0200
> message:
>   Merge branch 'master' of github.com:yade/trunk
> removed:
>   examples/test/CundallStrackTest.py
>   examples/test/Dem3DofGeom.py
>   pkg/dem/Dem3DofGeom_FacetSphere.cpp
>   pkg/dem/Dem3DofGeom_FacetSphere.hpp
>   pkg/dem/Dem3DofGeom_SphereSphere.cpp
>   pkg/dem/Dem3DofGeom_SphereSphere.hpp
>   pkg/dem/Dem3DofGeom_WallSphere.cpp
>   pkg/dem/Dem3DofGeom_WallSphere.hpp
>   py/_eudoxos.cpp
>   py/eudoxos.py
> added:
>   scripts/checks-and-tests/checks/DEM-PFV-check.py
>   scripts/checks-and-tests/checks/data/100spheres
> modified:
>   CMakeLists.txt
>   cMake/FindMetis.cmake
>   core/Clump.cpp
>   core/ForceContainer.hpp
>   core/main/main.py.in
>   doc/references.bib
>   doc/sphinx/formulation.rst
>   doc/sphinx/introduction.rst
>   doc/sphinx/prog.rst
>   doc/sphinx/references.bib
>   doc/sphinx/templates/index.html
>   doc/sphinx/user.rst
>   doc/yade-articles.bib
>   doc/yade-conferences.bib
>   doc/yade-theses.bib
>   pkg/common/Cylinder.hpp
>   pkg/dem/ConcretePM.cpp
>   pkg/dem/DemXDofGeom.cpp
>   pkg/dem/DemXDofGeom.hpp
>   pkg/dem/DomainLimiter.cpp
>   pkg/dem/FlowEngine.cpp
>   pkg/dem/FlowEngine.hpp
>   pkg/dem/HertzMindlin.cpp
>   pkg/dem/HertzMindlin.hpp
>   pkg/dem/Shop.cpp
>   pkg/dem/Shop.hpp
>   pkg/dem/VTKRecorder.hpp
>   pkg/dem/ViscoelasticCapillarPM.cpp
>   pkg/dem/ViscoelasticPM.cpp
>   pkg/dem/ViscoelasticPM.hpp
>   py/CMakeLists.txt
>   py/_extraDocs.py
>   py/_utils.cpp
>   py/system.py
>   py/tests/__init__.py
>   scripts/checks-and-tests/checks/README
>   scripts/checks-and-tests/checks/checkGravity.py
>   scripts/checks-and-tests/checks/checkList.py
>   scripts/checks-and-tests/checks/checkTestDummy.py
>   scripts/checks-and-tests/checks/checkTestTriax.py
>   scripts/checks-and-tests/checks/checkWirePM.py
>
>
> --
> lp:yade
> https://code.launchpad.net/~yade-pkg/yade/git-trunk
>
> Your team Yade developers is subscribed to branch lp:yade.
> To unsubscribe from this branch go to
> https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
>
> === modified file 'CMakeLists.txt'
> --- CMakeLists.txt      2013-08-15 12:52:44 +0000
> +++ CMakeLists.txt      2013-09-05 07:52:37 +0000
> @@ -380,7 +380,6 @@
>  SET (pyExecutable ${PYTHON_EXECUTABLE})
>  SET (profile "default")
>  SET (sourceRoot "${CMAKE_CURRENT_SOURCE_DIR}")
> -SET (libstdcxx "/usr/lib/libstdc++.so.6")     #This is a hack, which is
> not needed for modern systems. Should be deleted.
>  #====================================
>
>  CONFIGURE_FILE(core/main/yade-batch.in"${CMAKE_BINARY_DIR}/bins/yade${SUFFIX}-batch")
> @@ -409,6 +408,7 @@
>  MESSAGE(STATUS "Disabled features:${DISABLED_FEATS}")
>  IF (DEBUG)
>    MESSAGE(STATUS "Debug build")
> +  SET (debugbuild " (debug build)")
>  ELSE (DEBUG)
>    MESSAGE(STATUS "Optimized build")
>  ENDIF (DEBUG)
>
> === modified file 'cMake/FindMetis.cmake'
> --- cMake/FindMetis.cmake       2013-06-26 18:15:55 +0000
> +++ cMake/FindMetis.cmake       2013-08-30 13:49:57 +0000
> @@ -5,8 +5,8 @@
>  #  METIS_LIBRARY, libraries to link against to use GL2PS.
>  #  METIS_FOUND, If false, do not try to use GL2PS.
>
> -FIND_PATH(METIS_INCLUDE_DIR metis.h)
> -FIND_LIBRARY(METIS_LIBRARY NAMES metis )
> +FIND_PATH(METIS_INCLUDE_DIR metis.h PATHS /usr/include/metis)
> +FIND_LIBRARY(METIS_LIBRARY NAMES metis PATHS /usr/lib)
>
>  # handle the QUIETLY and REQUIRED arguments and set LOKI_FOUND to TRUE if
>  # all listed variables are TRUE
>
> === modified file 'core/Clump.cpp'
> --- core/Clump.cpp      2013-07-05 07:33:47 +0000
> +++ core/Clump.cpp      2013-08-30 06:19:46 +0000
> @@ -119,7 +119,7 @@
>                                 const Sphere* sphere1 = YADE_CAST<Sphere*>
> (subBody1->shape.get());
>                                 const Sphere* sphere2 = YADE_CAST<Sphere*>
> (subBody2->shape.get());
>                                 Real un =
> (sphere1->radius+sphere2->radius) - dist.norm();
> -                               if (un > 0.) {intersecting = true; break;}
> +                               if (un >
> -0.001*min(sphere1->radius,sphere2->radius)) {intersecting = true; break;}
>                         }
>                 }
>         }
>
> === modified file 'core/ForceContainer.hpp'
> --- core/ForceContainer.hpp     2013-08-22 18:35:55 +0000
> +++ core/ForceContainer.hpp     2013-08-26 21:41:10 +0000
> @@ -72,7 +72,7 @@
>                 // dummy function to avoid template resolution failure
>                 friend class boost::serialization::access; template<class
> ArchiveT> void serialize(ArchiveT & ar, unsigned int version){}
>         public:
> -               ForceContainer(): size(0),
> permSize(0),syncedSizes(true),synced(true),moveRotUsed(false),_zero(Vector3r::Zero()),syncCount(0),lastReset(0){
> +               ForceContainer(): size(0),
> permSize(0),syncedSizes(true),synced(true),moveRotUsed(false),permForceUsed(false),_zero(Vector3r::Zero()),syncCount(0),lastReset(0){
>                         nThreads=omp_get_max_threads();
>                         for(int i=0; i<nThreads; i++){
>                                 _forceData.push_back(vvector());
> _torqueData.push_back(vvector());
> @@ -220,7 +220,7 @@
>                 // dummy function to avoid template resolution failure
>                 friend class boost::serialization::access; template<class
> ArchiveT> void serialize(ArchiveT & ar, unsigned int version){}
>         public:
> -               ForceContainer(): size(0), permSize(0),
> moveRotUsed(false), syncCount(0), lastReset(0){}
> +               ForceContainer(): size(0), permSize(0),
> moveRotUsed(false), permForceUsed(false), syncCount(0), lastReset(0){}
>                 const Vector3r& getForce(Body::id_t id){ensureSize(id);
> return _force[id];}
>                 void  addForce(Body::id_t id,const Vector3r&
> f){ensureSize(id); _force[id]+=f;}
>                 const Vector3r& getTorque(Body::id_t id){ensureSize(id);
> return _torque[id];}
>
> === modified file 'core/main/main.py.in'
> --- core/main/main.py.in        2013-05-07 09:21:35 +0000
> +++ core/main/main.py.in        2013-09-05 07:52:37 +0000
> @@ -11,7 +11,7 @@
>  # get yade path (allow YADE_PREFIX to override)
>  prefix,suffix='${runtimePREFIX}' if not os.environ.has_key('YADE_PREFIX')
> else os.environ['YADE_PREFIX'],'${SUFFIX}'
>  # duplicate some items from yade.config here, so that we can increase
> verbosity when the c++ part is booting
> -features,version='${features}'.split(' '),'${realVersion}'
> +features,version,debugbuild='${features}'.split(' '),'${realVersion}','
> ${debugbuild}'
>
>  libPATH='${LIBRARY_OUTPUT_PATH}'
>  if (libPATH[1:] == '{LIBRARY_OUTPUT_PATH}'): libPATH='lib'
> @@ -52,11 +52,17 @@
>  par.add_argument('--performance',help='Starts a test to measure the
> productivity',dest='performance',action='store_true')
>
>  par.add_argument('script',nargs='?',default='',type=str,help=argparse.SUPPRESS)
>  par.add_argument('args',nargs=argparse.REMAINDER,help=argparse.SUPPRESS)
> # see argparse doc, par.disable_interspersed_args() from optargs module
> +par.add_argument('-l',help='import libraries at startup before importing
> yade libs. May be used when the ordering of imports matter (see e.g.
> https://bugs.launchpad.net/yade/+bug/1183402/comments/3). The option can
> be use multiple times, as in "yade -llib1
> -llib2"',default=None,action='append',dest='impLibraries',type=str)
>  opts=par.parse_args()
>  args = opts.args
>
> +if opts.impLibraries:
> +       sys.path.append('.')
> +       for lib in opts.impLibraries:
> +               __import__(lib)
> +
>  if opts.version:
> -       print 'Yade version: %s'%version
> +       print 'Yade version: %s%s'%(version,debugbuild)
>         sys.exit(0)
>
>  if opts.script:
> @@ -109,7 +115,7 @@
>  else: os.environ['OMP_NUM_THREADS']='1'
>
>  if __name__ == "__main__": # do not print this while importing yade in
> other python application
> -       sys.stderr.write('Welcome to Yade '+version+'\n')
> +       sys.stderr.write('Welcome to Yade '+version+debugbuild+'\n')
>
>  # initialization and c++ plugins import
>  import yade
>
> === modified file 'doc/references.bib'
> --- doc/references.bib  2013-08-14 08:01:55 +0000
> +++ doc/references.bib  2013-08-28 10:26:24 +0000
> @@ -580,18 +580,6 @@
>         url = "http://www.refdoc.fr/Detailnotice?idarticle=7435486";
>  }
>
> -@article{Thoeni2013,
> -       author = "K. Thoeni and C. Lambert and A. Giacomini and S.W.
> Sloan",
> -       doi = "10.1016/j.compgeo.2012.10.014",
> -       issn = "0266-352X",
> -       journal = "Computers and Geotechnics",
> -       pages = "158--169",
> -       title = "{Discrete modelling of hexagonal wire meshes with a
> stochastically distorted contact model}",
> -       url = "
> http://www.sciencedirect.com/science/article/pii/S0266352X12002121";,
> -       volume = "49",
> -       year = "2013"
> -}
> -
>  @article{Luding2008,
>         year={2008},
>         issn={1434-5021},
>
> === modified file 'doc/sphinx/formulation.rst'
> --- doc/sphinx/formulation.rst  2013-05-14 21:24:11 +0000
> +++ doc/sphinx/formulation.rst  2013-08-29 10:30:31 +0000
> @@ -314,8 +314,6 @@
>  -------------
>  In order to keep $\vec{u}_T$ consistent (e.g. that $\vec{u}_T$ must be
> constant if two spheres retain mutually constant configuration but move
> arbitrarily in space), then either $\vec{u}_T$ must track spheres' spatial
> motion or must (somehow) rely on sphere-local data exclusively.
>
> -These two possibilities lead to two algorithms of computing shear
> strains. They should give the same results (disregarding numerical
> imprecision), but there is a trade-off between computational cost of the
> incremental method and robustness of the total one.
> -
>  Geometrical meaning of shear strain is shown in `fig-shear-2d`_.
>
>  .. _fig-shear-2d:
> @@ -323,9 +321,7 @@
>
>         Evolution of shear displacement $\vec{u}_T$ due to mutual motion
> of spheres, both linear and rotational. Left configuration is the initial
> contact, right configuration is after displacement and rotation of one
> particle.
>
> -Incremental algorithm
> -^^^^^^^^^^^^^^^^^^^^^
> -The incremental algorithm is widely used in DEM codes and is described
> frequently ([Luding2008]_, [Alonso2004]_). Yade implements this algorithm
> in the :yref:`ScGeom` class. At each step, shear displacement $\uT$ is
> updated; the update increment can be decomposed in 2 parts: motion of the
> interaction (i.e. $\vec{C}$ and $\vec{n}$) in global space and mutual
> motion of spheres.
> +The classical incremental algorithm is widely used in DEM codes and is
> described frequently ([Luding2008]_, [Alonso2004]_). Yade implements this
> algorithm in the :yref:`ScGeom` class. At each step, shear displacement
> $\uT$ is updated; the update increment can be decomposed in 2 parts: motion
> of the interaction (i.e. $\vec{C}$ and $\vec{n}$) in global space and
> mutual motion of spheres.
>
>  #. Contact moves dues to changes of the spheres' positions $\vec{C}_1$
> and $\vec{C}_2$, which updates current $\currC$ and $\currn$ as per
> :eq:`eq-contact-point` and :eq:`eq-contact-normal`. $\prevuT$ is
> perpendicular to the contact plane at the previous step $\prevn$ and must
> be updated so that $\prevuT+(\Delta\uT)=\curruT\perp\currn$; this is done
> by perpendicular projection to the plane first (which might decrease
> $|\uT|$) and adding what corresponds to spatial rotation of the interaction
> instead:
>
> @@ -353,74 +349,6 @@
>
>  .. math:: \curruT=\prevuT+(\Delta\uT)_1 + (\Delta\uT)_2 + (\Delta\uT)_3.
>
> -.. _sect-formulation-total-shear:
> -
> -Total algorithm
> -^^^^^^^^^^^^^^^
> -The following algorithm, aiming at stabilization of response even with
> large rotation speeds or $\Delta t$ approaching stability limit, was
> designed in [Smilauer2010b]_. (A similar algorithm based on total
> formulation, which covers additionally bending and torsion, was proposed in
> [Wang2009]_.) It is based on tracking original contact points (with zero
> shear) in the particle-local frame.
> -
> -In this section, variable symbols implicitly denote their current values
> unless explicitly stated otherwise.
> -
> -Shear strain may have two sources: mutual rotation of spheres or
> transversal displacement of one sphere with respect to the other. Shear
> strain does not change if both spheres move or rotate but are not in linear
> or angular motion mutually. To accurately and reliably model this
> situation, for every new contact the initial contact point $\bar{\vec{C}}$
> is mapped into local sphere coordinates ($\vec{p}_{01}$, $\vec{p}_{02}$).
> As we want to determine the distance between both points (i.e. how long the
> trajectory in on both spheres' surfaces together), the shortest path from
> current $\vec{C}$ to the initial locally mapped point on the sphere's
> surface is „unrolled“ to the contact plane ($\vec{p}'_{01}$,
> $\vec{p}'_{02}$); then we can measure their linear distance $\uT$ and
> define shear strain $\vec{\eps}_T=\uT/d_0$ (fig. `fig-shear-displacement`_).
> -
> -More formally, taking $\bar{\vec{C}}_i$, $\bar{q}_i$ for the sphere
> initial positions and orientations (as quaterions) in global coordinates,
> the initial sphere-local contact point *orientation* (relative to
> sphere-local axis $\hat{x}$) is remembered:
> -
> -.. math::
> -       :nowrap:
> -
> -       \begin{align*}
> -               \bar{\vec{n}}&=\normalized{{\vec{C}}_1-{\vec{C}}_2}, \\
> -               \bar{q}_{01}&=\Align(\hat x,\bar{q}_1^*\bar{\vec{n}}
> \bar{q}_1^{**}), \\
> -               \bar{q}_{02}&=\Align(\hat x,\bar{q}_2^* (-\bar{\vec{n}})
> \bar{q}_2^{**}).
> -       \end{align*}
> -
> -.. (See \autoref{sect-quaternions} for definition of $\Align$.)
> -
> -
> -After some spheres motion, the original point can be "unrolled" to the
> current contact plane:
> -
> -.. math::
> -       :nowrap:
> -
> -       \begin{align*}
> -               q&=\Align(\vec{n},q_1 \bar{q}_{01} \hat x (q_1
> \bar{q}_{01})^*) \quad\hbox{(auxiliary)} \\
> -               \vec{p}'_{01}&=q_{\theta}d_1(q_{\vec{u}} \times \vec{n})
> -       \end{align*}
> -
> -where $q_{\vec{u}}$, $q_{\theta}$ are axis and angle components of $q$
> and $p_{01}'$ is the unrolled point. Similarly,
> -
> -.. math::
> -       :nowrap:
> -
> -       \begin{align*}
> -               q&=\Align(\vec{n},q_2 \bar{q}_{02} \hat x (q_2
> \bar{q}_{02})^*) \\
> -               \vec{p}'_{02}&=q_{\theta}d_1(q_{\vec{u}} \times
> (-\vec{n})).
> -       \end{align*}
> -
> -Shear displacement and strain are then computed easily:
> -
> -.. math::
> -       :nowrap:
> -
> -       \begin{align*}
> -               \uT&=\vec{p}'_{02}-\vec{p}'_{01} \\
> -               \vec{\eps}_T&=\frac{\uT}{d_0}
> -       \end{align*}
> -
> -When using material law with plasticity in shear, it may be necessary to
> limit maximum shear strain, in which case the mapped points are moved
> closer together to the requested distance (without changing
> $\hat{\vec{u}}_T$). This allows us to remember the previous strain
> direction and also avoids summation of increments of plastic strain at
> every step (`fig-shear-slip`_).
> -
> -.. _fig-shear-displacement:
> -.. figure:: fig/shear-displacement.*
> -
> -       Shear displacement computation for two spheres in relative motion.
> -
> -
> -.. _fig-shear-slip:
> -.. figure:: fig/shear-slip.*
> -
> -       Shear plastic slip for two spheres.
> -
> -This algorithm is straightforwardly modified to facet-sphere
> interactions. In Yade, it is implemented by :yref:`Dem3DofGeom` and related
> classes.
>
>  .. _sect-formulation-stress-cundall:
>
>
> === modified file 'doc/sphinx/introduction.rst'
> --- doc/sphinx/introduction.rst 2013-08-14 08:01:55 +0000
> +++ doc/sphinx/introduction.rst 2013-08-29 10:30:31 +0000
> @@ -343,7 +343,7 @@
>  :yref:`IGeom`
>         holding geometrical configuration of the two particles in
> collision; it is updated automatically as the particles in question move
> and can be queried for various geometrical characteristics, such as
> penetration distance or shear strain.
>
> -       Based on combination of types of :yref:`Shapes<Shape>` of the
> particles, there might be different storage requirements; for that reason,
> a number of derived classes exists, e.g. for representing geometry of
> contact between :yref:`Sphere+Sphere<Dem3DofGeom_SphereSphere>`,
> :yref:`Facet+Sphere<Dem3DofGeom_FacetSphere>` etc.
> +       Based on combination of types of :yref:`Shapes<Shape>` of the
> particles, there might be different storage requirements; for that reason,
> a number of derived classes exists, e.g. for representing geometry of
> contact between :yref:`Sphere+Sphere<ScGeom>`,
> :yref:`Cylinder+Sphere<CylScGeom>` etc. Note, however, that it is possible
> to represent many type of contacts with the basic sphere-sphere geometry
> (for instance in :yref:`Ig2_Wall_Sphere_ScGeom`).
>  :yref:`IPhys`
>         representing non-geometrical features of the interaction; some are
> computed from :yref:`Materials<Material>` of the particles in contact using
> some averaging algorithm (such as contact stiffness from Young's moduli of
> particles), others might be internal variables like damage.
>
>
> === modified file 'doc/sphinx/prog.rst'
> --- doc/sphinx/prog.rst 2013-08-14 08:01:55 +0000
> +++ doc/sphinx/prog.rst 2013-08-29 10:30:31 +0000
> @@ -872,7 +872,7 @@
>
>  .. code-block:: c++
>
> -       class Ig2_Facet_Sphere_Dem3DofGeom: public IGeomFunctor{
> +       class Ig2_Facet_Sphere_ScGeom: public IGeomFunctor{
>            public:
>
>            // override the IGeomFunctor::go
> @@ -914,7 +914,7 @@
>
>  If no functor is able to accept given types (first condition violated) or
> multiple functors have the same distance (in condition 2), an exception is
> thrown.
>
> -This resolution mechanism makes it possible, for instance, to have a
> hierarchy of :yref:`Dem3DofGeom` classes (for different combination of
> shapes: :yref:`Dem3DofGeom_SphereSphere`, :yref:`Dem3DofGeom_FacetSphere`,
> :yref:`Dem3DofGeom_WallSphere`), but only provide a :yref:`LawFunctor`
> accepting ``Dem3DofGeom``, rather than having different laws for each shape
> combination.
> +This resolution mechanism makes it possible, for instance, to have a
> hierarchy of :yref:`ScGeom` classes (for different combination of shapes),
> but only provide a :yref:`LawFunctor` accepting ``ScGeom``, rather than
> having different laws for each shape combination.
>
>  .. note:: Performance implications of dispatch resolution are relatively
> low. The dispatcher lookup is only done once, and uses fast lookup matrix
> (1D or 2D); then, the functor found for this type(s) is cached within the
> ``Interaction`` (or ``Body``) instance. Thus, regular functor call costs
> the same as dereferencing pointer and calling virtual method. There is
> `blueprint <
> https://blueprints.launchpad.net/yade/+spec/devirtualize-functor-calls>`__
> to avoid virtual function call as well.
>
>
> === modified file 'doc/sphinx/references.bib'
> --- doc/sphinx/references.bib   2013-06-06 09:27:41 +0000
> +++ doc/sphinx/references.bib   2013-08-28 10:38:02 +0000
> @@ -305,12 +305,5 @@
>         doi = "10.1016/S0378-4371(99)00183-1",
>         url = "
> http://www.sciencedirect.com/science/article/pii/S0378437199001831";,
>         author = "Y.C. Zhou and B.D. Wright and R.Y. Yang and B.H. Xu and
> A.B. Yu",
> -       keywords = "Static sandpiles",
> -       keywords = "Granular compaction",
> -       keywords = "Dynamics and kinematics of a particle and a system of
> particles",
> -       keywords = "Granular flow",
> -       keywords = "Mixing",
> -       keywords = "Segregation and stratification",
> -       keywords = "Granular systems "
>  }
>
>
> === modified file 'doc/sphinx/templates/index.html'
> --- doc/sphinx/templates/index.html     2013-02-26 19:28:47 +0000
> +++ doc/sphinx/templates/index.html     2013-08-30 19:39:27 +0000
> @@ -8,6 +8,12 @@
>     Yade is located at <a href="https://www.yade-dem.org";>www.yade-dem.org</a>,
> which contains <a href="https://www.yade-dem.org/doc/";>this
> documentation</a> and <a href="https://www.yade-dem.org/wiki/";>wiki</a>.
> Development is kindly hosted at <a href="http://www.launchpad.net/yade";>launchpad</a>;
> it is used for <a href="http://code.launchpad.net/yade";>source code</a>,
> <a href="http://bugs.launchpad.net/yade";>bug tracking</a>, <a href="
> http://blueprints.launchpad.net/yade";>planning</a>, <a href="
> https://launchpad.net/~yade-pkg/+archive/snapshots";>package</a> and <a
> href="https://launchpad.net/yade/+download";>source</a> downloads</a> and
> more.
>    </p>
>    <p>
> +  Since March 2012 Yade is using GIT as VCS and placing the source code on
> +  <a href="https://github.com/yade/trunk";>github</a>. The Launchpad is
> importing
> +  source code several times per day for the further buiding of
> "daily"-packages
> +  for Ubuntu.
> +  </p>
> +  <p>
>     Please make sure you read the <a href="{{ pathto("citing")
> }}">"Acknowledging Yade"</a> section if you plan to cite Yade in
> publications.
>    </p>
>    <p>
>
> === modified file 'doc/sphinx/user.rst'
> --- doc/sphinx/user.rst 2013-08-22 18:35:55 +0000
> +++ doc/sphinx/user.rst 2013-08-29 10:30:31 +0000
> @@ -418,7 +418,7 @@
>  #. Approximate collision detection is adjusted so that approximate
> contacts are detected also between particles within the interaction radius.
> This consists in setting value of :yref:`Bo1_Sphere_Aabb.aabbEnlargeFactor`
> to the interaction radius value.
>
>  #. The geometry functor (``Ig2``)
> -   would normally say that "there is no contact" if given 2 spheres that
> are not in contact. Therefore, the same value as for
> :yref:`Bo1_Sphere_Aabb.aabbEnlargeFactor` must be given to it. (Either
> :yref:`Ig2_Sphere_Sphere_Dem3DofGeom.distFactor` or
> :yref:`Ig2_Sphere_Sphere_ScGeom.interactionDetectionFactor`, depending on
> the functor that is in use.
> +   would normally say that "there is no contact" if given 2 spheres that
> are not in contact. Therefore, the same value as for
> :yref:`Bo1_Sphere_Aabb.aabbEnlargeFactor` must be given to it
> (:yref:`Ig2_Sphere_Sphere_ScGeom.interactionDetectionFactor` ).
>
>     Note that only :yref:`Sphere` + :yref:`Sphere` interactions are
> supported; there is no parameter analogous to
> :yref:`distFactor<Ig2_Sphere_Sphere_ScGeom.interactionDetectionFactor>` in
> :yref:`Ig2_Facet_Sphere_ScGeom`. This is on purpose, since the interaction
> radius is meaningful in bulk material represented by sphere packing,
> whereas facets usually represent boundary conditions which should be exempt
> from this dense interaction network.
>
> @@ -576,12 +576,7 @@
>
>     Again, missing combination will cause given shape combinations to
> freely interpenetrate one another.
>
> -#. :yref:`IGeom` type accepted by the ``Law2`` functor (below); it is the
> first part of functor's name after ``Law2`` (for instance,
> :yref:`Law2_ScGeom_CpmPhys_Cpm` accepts :yref:`ScGeom`). This is (for most
> cases) either :yref:`Dem3DofGeom` (total shear formulation) or
> :yref:`ScGeom` (incremental shear formulation). For :yref:`Dem3DofGeom`,
> the above example would simply change to::
> -
> -      InteractionLoop([
> -         Ig2_Sphere_Sphere_Dem3DofGeom(),
> -         Ig2_Facet_Sphere_Dem3DofGeom()
> -      ],[],[])
> +#. :yref:`IGeom` type accepted by the ``Law2`` functor (below); it is the
> first part of functor's name after ``Law2`` (for instance,
> :yref:`Law2_ScGeom_CpmPhys_Cpm` accepts :yref:`ScGeom`).
>
>  Ip2 functors
>  ^^^^^^^^^^^^
> @@ -693,29 +688,35 @@
>  Imposing motion and forces
>  --------------------------
>
> -* If a degree of freedom is blocked and a velocity is assigned along that
> direction (translational or rotational velocity), then the body will move
> at constant velocity. This is the simpler and recommended method to impose
> the motion of a body. This, for instance, will result in a constant
> velocity along $x$::
> +Imposed velocity
> +^^^^^^^^^^^^^^^^
> +
> +If a degree of freedom is blocked and a velocity is assigned along that
> direction (translational or rotational velocity), then the body will move
> at constant velocity. This is the simpler and recommended method to impose
> the motion of a body. This, for instance, will result in a constant
> velocity along $x$::
>
>         O.bodies.append(utils.sphere((0,0,0),1))
>         O.bodies[0].state.blockedDOFs='x'
>         O.bodies[0].state.vel=(10,0,0)
>
> -  Conversely, modifying the position directly is likely to break Yade's
> algorithms, especially those related to collision detection and contact
> laws, as they are based oon bodies velocities. Therefore, unless you really
> know what you are doing, don't do that for imposing a motion::
> +Conversely, modifying the position directly is likely to break Yade's
> algorithms, especially those related to collision detection and contact
> laws, as they are based oon bodies velocities. Therefore, unless you really
> know what you are doing, don't do that for imposing a motion::
>
>         O.bodies.append(utils.sphere((0,0,0),1))
>         O.bodies[0].state.blockedDOFs='x'
>         O.bodies[0].state.pos=10*O.dt #REALLY BAD! Don't assign position
>
> -* Applying a force or a torque on a body is done via functions of the
> :yref:`ForceContainer`. It is as simple as this::
> +Imposed force
> +^^^^^^^^^^^^^
> +
> +Applying a force or a torque on a body is done via functions of the
> :yref:`ForceContainer`. It is as simple as this::
>
>         O.forces.addF(0,(1,0,0)) #applies for one step
>
> -  By default, the force applies for one time step only, and is resetted
> at the beginning of each step. For this reason, imposing a force at the
> begining of one step will have no effect at all, since it will be
> immediatly resetted. The only way is to place a :yref:`PyRunner` inside the
> simulation loop.
> +By default, the force applies for one time step only, and is resetted at
> the beginning of each step. For this reason, imposing a force at the
> begining of one step will have no effect at all, since it will be
> immediatly resetted. The only way is to place a :yref:`PyRunner` inside the
> simulation loop.
>
> -  Applying the force permanently is possible with an optional argument
> (in this case it does not matter if the command comes at the begining of
> the time step)::
> +Applying the force permanently is possible with an optional argument (in
> this case it does not matter if the command comes at the begining of the
> time step)::
>
>         O.forces.addF(0,(1,0,0),permanent=True) #applies permanently
>
> -  The force  will persist across iterations, until it is overwritten by
> another call to ``O.forces.addF(id,f,True)`` or erased by
> ``O.forces.reset(resetAll=True)``. The permanent force on a body can be
> checked with ``O.forces.permF(id)``.
> +The force  will persist across iterations, until it is overwritten by
> another call to ``O.forces.addF(id,f,True)`` or erased by
> ``O.forces.reset(resetAll=True)``. The permanent force on a body can be
> checked with ``O.forces.permF(id)``.
>
>  Boundary controllers
>  --------------------
> @@ -1049,7 +1050,7 @@
>  By editing the generated .gnuplot file you can plot any of the added Data
> afterwards.
>
>
> -* Data file is saved (compressed using bzip2) separately from the gnuplot
> file, so any other programs can be used to process them. In particular, the
> ``numpy.genfromtxt`` (documented `here <
> http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html>`_)
> can be useful to import those data back to python; the decompression
> happens automatically.
> +* Data file is saved (compressed using bzip2) separately from the gnuplot
> file, so any other programs can be used to process them. In particular, the
> ``numpy.genfromtxt`` (`documented here <
> http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html>`_)
> can be useful to import those data back to python; the decompression
> happens automatically.
>
>  * The gnuplot file can be run through gnuplot to produce the figure; see
> :yref:`yade.plot.saveGnuplot` documentation for details.
>
> @@ -1470,7 +1471,7 @@
>  .. figure:: fig/micro-domains.*
>
>  Micro-strain
> -""""""""""""
> +------------
>  Below is an output of the :yref:`defToVtk<TesselationWrapper::defToVtk>`
> function visualized with paraview (in this case Yade's TesselationWrapper
> was used to process experimental data obtained on sand by Edward Ando at
> Grenoble University, 3SR lab.). The output is visualized with paraview, as
> explained in the previous section. Similar results can be generated from
> simulations:
>
>  .. code-block:: python
> @@ -1493,7 +1494,7 @@
>  .. figure:: fig/localstrain.*
>
>  Micro-stress
> -""""""""""""
> +------------
>  Stress fields can be generated by combining the volume returned by
> TesselationWrapper to per-particle stress given by
> :yref:`bodyStressTensors`. Since the stress $\sigma$ from bodyStressTensor
> implies a division by the volume $V_b$ of the solid particle, one has to
> re-normalize it in order to obtain the micro-stress as defined in
> [Catalano2013a]_ (equation 39 therein), i.e. $\overline{\sigma}^k =
> \sigma^k \times V_b^k / V_{\sigma}^k$ where $V_{\sigma}^k$ is the volume
> assigned to particle $k$ in the tesselation. For instance:
>
>  .. code-block:: python
>
> === modified file 'doc/yade-articles.bib'
> --- doc/yade-articles.bib       2013-08-14 08:01:55 +0000
> +++ doc/yade-articles.bib       2013-08-26 21:57:21 +0000
> @@ -30,7 +30,7 @@
>         url = {http://arxiv.org/pdf/1304.4895.pdf}
>  }
>
> -@article {Chareyre2012a,
> +@article{Chareyre2012a,
>         author = {Chareyre, B. and Cortis, A. and Catalano, E. and
> Barthélemy, E.},
>         title = {Pore-Scale Modeling of Viscous Flow and Induced Forces in
> Dense Sphere Packings},
>         journal = {Transport in Porous Media},
> @@ -359,15 +359,15 @@
>  }
>
>  @article{Puckett2011,
> -       title = {Local origins of volume fraction fluctuations in dense
> granular materials},
> -       author = {Puckett, J.G. and Lechenault, F. and Daniels, K.E.},
> -       journal = {Physical Review E},
> -       volume = {83},
> -       issue = {4},
> -       pages = {041301},
> -       year = {2011},
> -       doi = {10.1103/PhysRevE.83.041301},
> -       url = {http://link.aps.org/doi/10.1103/PhysRevE.83.041301}
> +       title = {Local origins of volume fraction fluctuations in dense
> granular materials},
> +       author = {Puckett, J.G. and Lechenault, F. and Daniels, K.E.},
> +       journal = {Physical Review E},
> +       volume = {83},
> +       issue = {4},
> +       pages = {041301},
> +       year = {2011},
> +       doi = {10.1103/PhysRevE.83.041301},
> +       url = {http://link.aps.org/doi/10.1103/PhysRevE.83.041301}
>  }
>
>  @article{Sayeed2011,
>
> === modified file 'doc/yade-conferences.bib'
> --- doc/yade-conferences.bib    2013-08-14 08:01:55 +0000
> +++ doc/yade-conferences.bib    2013-08-26 21:53:51 +0000
> @@ -563,7 +563,7 @@
>         doi = {10.1063/1.4812158}
>  }
>
> -@InProceedings{ Hadda2013,
> +@InProceedings{ Hadda2013b,
>         author = {Nejib Hadda and François Nicot and Luc Sibille and
> Farhang Radjai and Antoinette Tordesillas and Félix Darve},
>         title = {A multiscale description of failure in granular
> materials},
>         publisher = {AIP},
> @@ -590,3 +590,14 @@
>         url = {https://www.yade-dem.org/publi/APC000495.pdf},
>         doi = {10.1063/1.4811976}
>  }
> +
> +@InProceedings{Maurin2013,
> +  title={Discrete element modelling of bedload transport},
> +  author={Maurin, Raphael and Chareyre, Bruno and Chauchat, Julien and
> Frey, Philippe},
> +  booktitle={Proceedings of THESIS 2013, Two-pHase modElling for Sediment
> dynamIcS in Geophysical Flows},
> +  adress = {Chatou, France},
> +  pages={6p},
> +  url = {https://www.yade-dem.org/publi/Maurin_et_al_THESIS_meta.pdf},
> +  year={2013}
> +}
> +
>
> === modified file 'doc/yade-theses.bib'
> --- doc/yade-theses.bib 2013-08-19 17:51:24 +0000
> +++ doc/yade-theses.bib 2013-08-28 10:38:02 +0000
> @@ -101,6 +101,14 @@
>         author = {Benoit Charlas},
>         school = {Université de Grenoble},
>         title = {Etude du comportement mécanique d'un hydrure
> intermétallique utilisé pour le stockage d'hydrogène},
> -       year = {2013}
> +       year = {2013},
> +       url = {
> https://www.yade-dem.org/w/images/8/89/These_BenoitCharlas.pdf}
>  }
>
> +@phdthesis{Catalano2012,
> +       author = {Emanuele Catalano},
> +       school = {Université de Grenoble},
> +       title = {A pore-scale coupled hydromechanical model for biphasic
> granular media},
> +       year = {2012},
> +       url = {https://yade-dem.org/publi/Catalano_Thesis.pdf}
> +}
> \ No newline at end of file
>
> === removed file 'examples/test/CundallStrackTest.py'
> --- examples/test/CundallStrackTest.py  2013-03-28 11:13:12 +0000
> +++ examples/test/CundallStrackTest.py  1970-01-01 00:00:00 +0000
> @@ -1,21 +0,0 @@
> -# -*- coding: utf-8 -*-
> -
> -
> -O.engines=[
> -       ForceResetter(),
> -       InsertionSortCollider([Bo1_Sphere_Aabb(),]),
> -       IGeomDispatcher([Ig2_Sphere_Sphere_Dem3DofGeom()]),
> -       IPhysDispatcher([Ip2_2xFrictMat_CSPhys()]),
> -       LawDispatcher([Law2_Dem3Dof_CSPhys_CundallStrack()]),
> -       NewtonIntegrator(damping = 0.01,gravity=[0,0,-9.81])
> -]
> -
> -
> -
> -O.bodies.append(sphere([0,0,6],1,fixed=False, color=[0,1,0]))
> -O.bodies.append(sphere([0,0,0],1,fixed=True, color=[0,0,1]))
> -O.dt=.2*PWaveTimeStep()
> -
> -from yade import qt
> -qt.Controller()
> -qt.View()
>
> === removed file 'examples/test/Dem3DofGeom.py'
> --- examples/test/Dem3DofGeom.py        2013-03-28 16:15:54 +0000
> +++ examples/test/Dem3DofGeom.py        1970-01-01 00:00:00 +0000
> @@ -1,40 +0,0 @@
> -"Script showing shear interaction between facet/wall and sphere."
> -O.bodies.append([
> -       #sphere([0,0,0],1,dynamic=False,color=(0,1,0),wire=True),
> -
> facet(([2,2,1],[-2,0,1],[2,-2,1]),fixed=True,color=(0,1,0),wire=False),
> -       #wall([0,0,1],axis=2,color=(0,1,0)),
> -       sphere([-1,0,2],1,fixed=False,color=(1,0,0),wire=True),
> -])
> -O.engines=[
> -       ForceResetter(),
> -       InsertionSortCollider([
> -               Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()
> -       ]),
> -       IGeomDispatcher([
> -               Ig2_Sphere_Sphere_Dem3DofGeom(),
> -               Ig2_Facet_Sphere_Dem3DofGeom(),
> -               Ig2_Wall_Sphere_Dem3DofGeom()
> -       ]),
> -       RotationEngine(rotationAxis=[0,1,0],angularVelocity=10,ids=[1]),
> -       TranslationEngine(translationAxis=[1,0,0],velocity=10,ids=[1]),
> -       NewtonIntegrator()#gravity=(0,0,-10))
> -]
> -O.miscParams=[
> -
> Gl1_Dem3DofGeom_SphereSphere(normal=True,rolledPoints=True,unrolledPoints=True,shear=True,shearLabel=True),
> -
> Gl1_Dem3DofGeom_FacetSphere(normal=False,rolledPoints=True,unrolledPoints=True,shear=True,shearLabel=True),
> -
> Gl1_Dem3DofGeom_WallSphere(normal=False,rolledPoints=True,unrolledPoints=True,shear=True,shearLabel=True),
> -       Gl1_Sphere(wire=True)
> -]
> -
> -try:
> -       from yade import qt
> -       renderer=qt.Renderer()
> -       renderer.wire=True
> -       renderer.intrGeom=True
> -       qt.Controller()
> -       qt.View()
> -except ImportError: pass
> -
> -O.dt=1e-6
> -O.saveTmp('init')
> -O.run(1)
>
> === modified file 'pkg/common/Cylinder.hpp'
> --- pkg/common/Cylinder.hpp     2013-05-29 09:48:51 +0000
> +++ pkg/common/Cylinder.hpp     2013-08-29 10:30:31 +0000
> @@ -265,7 +265,7 @@
>  public:
>      //OpenMPAccumulator<Real> plasticDissipation;
>      virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys,
> Interaction* I);
> -
>  YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ChCylGeom6D_CohFrictPhys_CohesionMoment,LawFunctor,"Law
> for linear compression, and Mohr-Coulomb plasticity surface without
> cohesion.\nThis law implements the classical linear elastic-plastic law
> from [CundallStrack1979]_ (see also [Pfc3dManual30]_). The normal force is
> (with the convention of positive tensile forces) $F_n=\\min(k_n u_n, 0)$.
> The shear force is $F_s=k_s u_s$, the plasticity condition defines the
> maximum value of the shear force : $F_s^{\\max}=F_n\\tan(\\phi)$, with
> $\\phi$ the friction angle.\n\n.. note::\n This law uses :yref:`ScGeom`;
> there is also functionally equivalent
> :yref:`Law2_Dem3DofGeom_FrictPhys_CundallStrack`, which uses
> :yref:`Dem3DofGeom` (sphere-box interactions are not implemented for the
> latest).\n\n.. note::\n This law is well tested in the context of triaxial
> simulation, and has been used for a number of published results (see e.g.
> [Scholtes2009b]_ and other papers from the same authors). It is generalised
> by :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`, which adds cohesion
> and moments at contact.",
> +
>  YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ChCylGeom6D_CohFrictPhys_CohesionMoment,LawFunctor,"Law
> for linear compression, and Mohr-Coulomb plasticity surface without
> cohesion.\nThis law implements the classical linear elastic-plastic law
> from [CundallStrack1979]_ (see also [Pfc3dManual30]_). The normal force is
> (with the convention of positive tensile forces) $F_n=\\min(k_n u_n, 0)$.
> The shear force is $F_s=k_s u_s$, the plasticity condition defines the
> maximum value of the shear force : $F_s^{\\max}=F_n\\tan(\\phi)$, with
> $\\phi$ the friction angle.\n\n.. note::\n This law is well tested in the
> context of triaxial simulation, and has been used for a number of published
> results (see e.g. [Scholtes2009b]_ and other papers from the same authors).
> It is generalised by :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`,
> which adds cohesion and moments at contact.",
>                                        ((bool,neverErase,false,,"Keep
> interactions even if particles go away from each other (only in case
> another constitutive law is in the scene, e.g.
> :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
>
>  ((bool,traceEnergy,false,Attr::hidden,"Define the total energy dissipated
> in plastic slips at all contacts."))
>
>  ((int,plastDissipIx,-1,(Attr::hidden|Attr::noSave),"Index for plastic
> dissipation (with O.trackEnergy)"))
>
> === modified file 'pkg/dem/ConcretePM.cpp'
> --- pkg/dem/ConcretePM.cpp      2013-08-23 15:21:20 +0000
> +++ pkg/dem/ConcretePM.cpp      2013-08-26 21:42:20 +0000
> @@ -345,7 +345,7 @@
>         Vector3r& Fs(phys->Fs); /* for python access */
>         const bool& isCohesive(phys->isCohesive);
>
> -       Vector3r& epsTPl(phys->epsTPl);
> +//     Vector3r& epsTPl(phys->epsTPl);
>
>         #ifdef CPM_MATERIAL_MODEL
>                 Real& epsNPl(phys->epsNPl);
> @@ -589,7 +589,7 @@
>                         }
>                 }
>         }
> -       Real tr;
> +//     Real tr;
>         FOREACH(shared_ptr<Body> B, *scene->bodies){
>                 if (!B) continue;
>                 const Body::id_t& id = B->getId();
>
> === removed file 'pkg/dem/Dem3DofGeom_FacetSphere.cpp'
> --- pkg/dem/Dem3DofGeom_FacetSphere.cpp 2011-02-14 08:05:09 +0000
> +++ pkg/dem/Dem3DofGeom_FacetSphere.cpp 1970-01-01 00:00:00 +0000
> @@ -1,221 +0,0 @@
> -// © Václav Šmilauer <eudoxos@xxxxxxxx>
> -#include "Dem3DofGeom_FacetSphere.hpp"
> -#include<yade/pkg/common/Sphere.hpp>
> -#include<yade/pkg/common/Facet.hpp>
> -YADE_PLUGIN((Dem3DofGeom_FacetSphere)
> -       #ifdef YADE_OPENGL
> -               (Gl1_Dem3DofGeom_FacetSphere)
> -       #endif
> -               (Ig2_Facet_Sphere_Dem3DofGeom));
> -
> -CREATE_LOGGER(Dem3DofGeom_FacetSphere);
> -Dem3DofGeom_FacetSphere::~Dem3DofGeom_FacetSphere(){}
> -
> -void Dem3DofGeom_FacetSphere::setTgPlanePts(const Vector3r& p1new, const
> Vector3r& p2new){
> -       TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());
> -
> cp1pt=se31.orientation.conjugate()*(turnPlanePt(p1new,normal,se31.orientation*localFacetNormal)+contactPoint-se31.position);
> -
> cp2rel=se32.orientation.conjugate()*Dem3DofGeom_SphereSphere::rollPlanePtToSphere(p2new,effR2,-normal);
> -       TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());
> -}
> -
> -void Dem3DofGeom_FacetSphere::relocateContactPoints(const Vector3r& p1,
> const Vector3r& p2){
> -       //TRVAR2(p2.norm(),effR2);
> -       if(p2.squaredNorm()>pow(effR2,2)){
> -               setTgPlanePts(Vector3r::Zero(),p2-p1);
> -       }
> -}
> -
> -Real Dem3DofGeom_FacetSphere::slipToDisplacementTMax(Real
> displacementTMax){
> -       //FIXME: not yet tested
> -       // negative or zero: reset shear
> -       if(displacementTMax<=0.){
> setTgPlanePts(Vector3r(0,0,0),Vector3r(0,0,0)); return displacementTMax;}
> -       // otherwise
> -       Vector3r p1=contPtInTgPlane1(), p2=contPtInTgPlane2();
> -       Real currDistSq=(p2-p1).squaredNorm();
> -       if(currDistSq<pow(displacementTMax,2)) return 0; // close enough,
> no slip needed
> -       //Vector3r diff=.5*(sqrt(currDistSq)/displacementTMax-1)*(p2-p1);
> setTgPlanePts(p1+diff,p2-diff);
> -       Real scale=displacementTMax/sqrt(currDistSq);
> setTgPlanePts(scale*p1,scale*p2);
> -       return (displacementTMax/scale)*(1-scale);
> -}
> -
> -CREATE_LOGGER(Ig2_Facet_Sphere_Dem3DofGeom);
> -bool Ig2_Facet_Sphere_Dem3DofGeom::go(const shared_ptr<Shape>& cm1, const
> shared_ptr<Shape>& cm2, const State& state1, const State& state2, const
> Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
> -       Facet* facet=static_cast<Facet*>(cm1.get());
> -       Real sphereRadius=static_cast<Sphere*>(cm2.get())->radius;
> -
> -       // IGeomFunctor::go(cm1,cm2,state1,state2,shift2,force,c);
> -
> -       #if 1
> -               /* new code written from scratch, to make sure the
> algorithm is correct; it is about the same speed
> -                       as sega's algo below, but seems more readable to
> me.
> -                       The FACET_TOPO thing is still missing here but can
> be copied literally once it is tested */
> -               // begin facet-local coordinates
> -                       Vector3r
> cogLine=state1.ori.conjugate()*(state2.pos+shift2-state1.pos); // connect
> centers of gravity
> -                       //TRVAR4(state1.pos,state1.ori,state2.pos,cogLine);
> -                       Vector3r normal=facet->normal;
> -                       Real planeDist=normal.dot(cogLine);
> -                       if(planeDist<0){normal*=-1; planeDist*=-1; }
> -                       if(planeDist>sphereRadius && !c->isReal() &&
> !force) { /* LOG_TRACE("Sphere too far ("<<planeDist<<") from plane"); */
> return false;  }
> -                       Vector3r planarPt=cogLine-planeDist*normal; //
> project sphere center to the facet plane
> -                       Real normDotPt[3];
> -                       Vector3r contactPt(Vector3r::Zero());
> -                       for(int i=0; i<3; i++)
> normDotPt[i]=facet->ne[i].dot(planarPt-facet->vertices[i]);
> -                       short
> w=(normDotPt[0]>0?1:0)+(normDotPt[1]>0?2:0)+(normDotPt[2]>0?4:0);
> -
> //TRVAR4(planarPt,normDotPt[0],normDotPt[1],normDotPt[2]);
> -                       //TRVAR2(normal,cogLine);
> -
> //TRVAR3(facet->vertices[0],facet->vertices[1],facet->vertices[2]);
> -                       switch(w){
> -                               case 0: contactPt=planarPt; break; //
> inside triangle
> -                               case 1:
> contactPt=getClosestSegmentPt(planarPt,facet->vertices[0],facet->vertices[1]);
> break; // +-- (n1)
> -                               case 2:
> contactPt=getClosestSegmentPt(planarPt,facet->vertices[1],facet->vertices[2]);
> break; // -+- (n2)
> -                               case 4:
> contactPt=getClosestSegmentPt(planarPt,facet->vertices[2],facet->vertices[0]);
> break; // --+ (n3)
> -                               case 3: contactPt=facet->vertices[1];
> break; // ++- (v1)
> -                               case 5: contactPt=facet->vertices[0];
> break; // +-+ (v0)
> -                               case 6: contactPt=facet->vertices[2];
> break; // -++ (v2)
> -                               case 7: throw logic_error("Impossible
> triangle intersection?"); // +++ (impossible)
> -                               default: throw logic_error("Nonsense
> intersection value!");
> -                       }
> -                       normal=cogLine-contactPt; // called normal, but it
> is no longer the facet's normal (for compat)
> -                       //TRVAR3(normal,contactPt,sphereRadius);
> -                       if(!c->isReal() &&
> normal.squaredNorm()>sphereRadius*sphereRadius && !force) { /*
> LOG_TRACE("Sphere too far from closest point"); */ return false; } // fast
> test before sqrt
> -                       Real norm=normal.norm(); normal/=norm; // normal
> is unit vector now
> -                       Real penetrationDepth=sphereRadius-norm;
> -       #else
> -               /* This code was mostly copied from
> InteractingFacet2InteractinSphere4SpheresContactGeometry */
> -               // begin facet-local coordinates
> -                       Vector3r
> contactLine=state1.ori.Conjugate()*(state2.pos+shift2-state1.pos);
> -                       Vector3r normal=facet->normal;
> -                       Real L=normal.Dot(contactLine); // height/depth of
> sphere's center from facet's plane
> -                       if(L<0){normal*=-1; L*=-1;}
> -                       if(L>sphereRadius && !c->isReal()) return false;
> // sphere too far away from the plane
> -
> -                       Vector3r contactPt=contactLine-L*normal; //
> projection of sphere's center to facet's plane (preliminary contact point)
> -                       const Vector3r* edgeNormals=facet->ne; // array[3]
> of edge normals (in facet plane)
> -                       int edgeMax=0; Real
> distMax=edgeNormals[0].Dot(contactPt);
> -                       for(int i=1; i<3; i++){
> -                               Real dist=edgeNormals[i].Dot(contactPt);
> -                               if(distMax<dist){edgeMax=i; distMax=dist;}
> -                       }
> -                       //TRVAR2(distMax,edgeMax);
> -                       // OK, what's the logic here? Copying from
> IF2IS4SCG…
> -                       Real sphereRReduced=shrinkFactor*sphereRadius;
> -                       Real inCircleR=facet->icr-sphereRReduced;
> -                       Real penetrationDepth;
> -                       if(inCircleR<0){inCircleR=facet->icr;
> sphereRReduced=0;}
> -                       if(distMax<inCircleR){// contact with facet's
> surface
> -                               penetrationDepth=sphereRadius-L;
> -                               normal.normalize();
> -                       } else { // contact with the edge
> -
> contactPt+=edgeNormals[edgeMax]*(inCircleR-distMax);
> -                               bool noVertexContact=false;
> -
> //TRVAR3(edgeNormals[edgeMax],inCircleR,distMax);
> -                               // contact with vertex no. edgeMax
> -                               // FIXME: this is the original version,
> but why (edgeMax-1)%3? IN that case, edgeNormal to edgeMax would never be
> tried
> -                               //    if     (contactPt.Dot(edgeNormals[
>      (edgeMax-1)%3])>inCircleR)
> contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
> -                               if     (contactPt.Dot(edgeNormals[
>  edgeMax      ])>inCircleR)
> contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
> -                               // contact with vertex no. edgeMax+1
> -                               else
> if(contactPt.Dot(edgeNormals[edgeMax=(edgeMax+1)%3])>inCircleR)
> contactPt=facet->vu[edgeMax]*(facet->vl[edgeMax]-sphereRReduced);
> -                               // contact with edge no. edgeMax
> -                               else noVertexContact=true;
> -                               normal=contactLine-contactPt;
> -                               #ifdef FACET_TOPO
> -                                       if(noVertexContact &&
> facet->edgeAdjIds[edgeMax]!=Body::ID_NONE){
> -                                               // find angle between our
> normal and the facet's normal (still local coords)
> -                                               Quaternionr q;
> q.Align(facet->normal,normal); AngleAxisr aa(q);
> -                                               assert(aa.angle()>=0 &&
> aa.angle()<=Mathr::PI);
> -
> if(edgeNormals[edgeMax].Dot(aa.axis())<0) aa.angle()*=-1.;
> -                                               bool
> negFace=normal.Dot(facet->normal)<0; // contact in on the negative facet's
> face
> -                                               Real
> halfAngle=(negFace?-1.:1.)*facet->edgeAdjHalfAngle[edgeMax];
> -                                               if(halfAngle<0 &&
> aa.angle()>halfAngle) return false; // on concave boundary, and if in the
> other facet's sector, no contact
> -                                               // otherwise the contact
> will be created
> -                                       }
> -                               #endif
> -
> //TRVAR4(contactLine,contactPt,normal,normal.norm());
> -
> //TRVAR3(se31.orientation*contactLine,se31.position+se31.orientation*contactPt,se31.orientation*normal);
> -                               Real norm=normal.norm(); normal/=norm;
> -                               penetrationDepth=sphereRadius-norm;
> -                               //TRVAR1(penetrationDepth);
> -                       }
> -               // end facet-local coordinates
> -       #endif
> -
> -       if(penetrationDepth<0 && !c->isReal()) return false;
> -
> -
> -       shared_ptr<Dem3DofGeom_FacetSphere> fs;
> -       Vector3r normalGlob=state1.ori*normal;
> -       bool isNew=false;
> -       if(c->geom) fs=YADE_PTR_CAST<Dem3DofGeom_FacetSphere>(c->geom);
> -       else {
> -               // LOG_TRACE("Creating new Dem3DofGeom_FacetSphere");
> -               fs=shared_ptr<Dem3DofGeom_FacetSphere>(new
> Dem3DofGeom_FacetSphere());
> -               c->geom=fs;
> -               isNew=true;
> -               fs->effR2=sphereRadius-penetrationDepth;
> -               fs->refR1=-1; fs->refR2=sphereRadius;
> -               // postponed till below, to avoid numeric issues
> -               // see https://lists.launchpad.net/yade-dev/msg02794.html
> -               // since displacementN() is computed from fs->contactPoint,
> -               // it was returning something like +1e-16 at the very
> first step
> -               // when it was created ⇒ the constitutive law was erasing
> the
> -               // contact as soon as it was created.
> -               // fs->refLength=…
> -               fs->cp1pt=contactPt; // facet-local intial contact point
> -               fs->localFacetNormal=facet->normal;
> -
> fs->cp2rel.setFromTwoVectors(Vector3r::UnitX(),state2.ori.conjugate()*(-normalGlob));
> // initial sphere-local center-contactPt orientation WRT +x
> -               fs->cp2rel.normalize();
> -       }
> -       fs->se31=state1.se3; fs->se32=state2.se3;
> fs->se32.position+=shift2;
> -       fs->normal=normalGlob;
> -
> fs->contactPoint=state2.pos+shift2+(-normalGlob)*(sphereRadius-penetrationDepth);
> -       // this refLength computation mimics what displacementN() does
> inside
> -       // displcementN will therefore return exactly zero at the step the
> contact
> -       // was created, which is what we want
> -       if(isNew)
> fs->refLength=(state2.pos+shift2-fs->contactPoint).norm();
> -       return true;
> -}
> -
> -#ifdef YADE_OPENGL
> -
> -       #include<yade/lib/opengl/OpenGLWrapper.hpp>
> -       #include<yade/lib/opengl/GLUtils.hpp>
> -
> -       bool Gl1_Dem3DofGeom_FacetSphere::normal=false;
> -       bool Gl1_Dem3DofGeom_FacetSphere::rolledPoints=false;
> -       bool Gl1_Dem3DofGeom_FacetSphere::unrolledPoints=false;
> -       bool Gl1_Dem3DofGeom_FacetSphere::shear=false;
> -       bool Gl1_Dem3DofGeom_FacetSphere::shearLabel=false;
> -
> -       void Gl1_Dem3DofGeom_FacetSphere::go(const shared_ptr<IGeom>& ig,
> const shared_ptr<Interaction>& ip, const shared_ptr<Body>& b1, const
> shared_ptr<Body>& b2, bool wireFrame){
> -               Dem3DofGeom_FacetSphere* fs =
> static_cast<Dem3DofGeom_FacetSphere*>(ig.get());
> -               const Se3r& se31=b1->state->se3,se32=b2->state->se3;
> -               const Vector3r& pos1=se31.position; const Vector3r&
> pos2=se32.position;
> -               const Quaternionr& ori1=se31.orientation; const
> Quaternionr& ori2=se32.orientation;
> -               const Vector3r& contPt=fs->contactPoint;
> -
> -               if(normal){
> -
> GLUtils::GLDrawArrow(contPt,contPt+fs->refLength*fs->normal); // normal of
> the contact
> -               }
> -               // sphere center to point on the sphere
> -               if(rolledPoints){
> -                       //cerr<<pos1<<" "<<pos1+ori1*fs->cp1pt<<"
> "<<contPt<<endl;
> -
> GLUtils::GLDrawLine(pos1+ori1*fs->cp1pt,contPt,Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(pos2,pos2+(ori2*fs->cp2rel*Vector3r::UnitX()*fs->effR2),Vector3r(0,1,.5));
> -               }
> -               // contact point to projected points
> -               if(unrolledPoints||shear){
> -                       Vector3r ptTg1=fs->contPtInTgPlane1(),
> ptTg2=fs->contPtInTgPlane2();
> -                       if(unrolledPoints){
> -                               //TRVAR3(ptTg1,ptTg2,ss->normal)
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg1,Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg2,Vector3r(0,1,.5));
> GLUtils::GLDrawLine(pos2,contPt+ptTg2,Vector3r(0,1,.5));
> -                       }
> -                       if(shear){
> -
> GLUtils::GLDrawLine(contPt+ptTg1,contPt+ptTg2,Vector3r(1,1,1));
> -                               if(shearLabel)
> GLUtils::GLDrawNum(fs->displacementT().norm(),contPt,Vector3r(1,1,1));
> -                       }
> -               }
> -       }
> -
> -#endif
> -
>
> === removed file 'pkg/dem/Dem3DofGeom_FacetSphere.hpp'
> --- pkg/dem/Dem3DofGeom_FacetSphere.hpp 2013-08-23 15:21:20 +0000
> +++ pkg/dem/Dem3DofGeom_FacetSphere.hpp 1970-01-01 00:00:00 +0000
> @@ -1,80 +0,0 @@
> -#pragma once
> -#include<yade/pkg/dem/DemXDofGeom.hpp>
> -// for static roll/unroll functions in Dem3DofGeom_SphereSphere
> -#include<yade/pkg/dem/Dem3DofGeom_SphereSphere.hpp>
> -#include<yade/pkg/common/Sphere.hpp>
> -#include<yade/pkg/common/Facet.hpp>
> -
> -class Dem3DofGeom_FacetSphere: public Dem3DofGeom{
> -       //! turn planePt in plane with normal0 around line passing through
> origin to plane with normal1
> -       static Vector3r turnPlanePt(const Vector3r& planePt, const
> Vector3r& normal0, const Vector3r& normal1){ Quaternionr q;
> q.setFromTwoVectors(normal0,normal1); return q*planePt; }
> -
> -       Vector3r contPtInTgPlane1() const { return
> turnPlanePt(se31.position+se31.orientation*cp1pt-contactPoint,se31.orientation*localFacetNormal,normal);
> }
> -       Vector3r contPtInTgPlane2() const { return
> Dem3DofGeom_SphereSphere::unrollSpherePtToPlane(se32.orientation*cp2rel,effR2,-normal);}
> -
> -       public:
> -               virtual ~Dem3DofGeom_FacetSphere();
> -               /******* API ********/
> -               virtual Real displacementN(){ return
> (se32.position-contactPoint).norm()-refLength;}
> -               virtual Vector3r displacementT(){ relocateContactPoints();
> return contPtInTgPlane2()-contPtInTgPlane1(); }
> -               virtual Real slipToDisplacementTMax(Real displacementTMax);
> -               /***** end API ******/
> -
> -               void setTgPlanePts(const Vector3r&, const Vector3r&);
> -               void relocateContactPoints(){
> relocateContactPoints(contPtInTgPlane1(),contPtInTgPlane2()); }
> -               void relocateContactPoints(const Vector3r& p1, const
> Vector3r& p2);
> -
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(Dem3DofGeom_FacetSphere,Dem3DofGeom,"Class
> representing facet+sphere in contact which computes 3 degrees of freedom
> (normal and shear deformation).",
> -               ((Vector3r,cp1pt,,,"Reference contact point on the facet
> in facet-local coords."))
> -               ((Quaternionr,cp2rel,,,"Orientation between +x and the
> reference contact point (on the sphere) in sphere-local coords"))
> -               ((Vector3r,localFacetNormal,,,"Unit normal of the facet
> plane in facet-local coordinates"))
> -               ((Real,effR2,,,"Effective radius of sphere")),
> -               /*ctor*/ createIndex();
> -       );
> -       REGISTER_CLASS_INDEX(Dem3DofGeom_FacetSphere,Dem3DofGeom);
> -       DECLARE_LOGGER;
> -       friend class Gl1_Dem3DofGeom_FacetSphere;
> -       friend class Ig2_Facet_Sphere_Dem3DofGeom;
> -};
> -REGISTER_SERIALIZABLE(Dem3DofGeom_FacetSphere);
> -
> -#ifdef YADE_OPENGL
> -       #include<yade/pkg/common/GLDrawFunctors.hpp>
> -       class Gl1_Dem3DofGeom_FacetSphere:public GlIGeomFunctor{
> -               public:
> -                       virtual void go(const shared_ptr<IGeom>&,const
> shared_ptr<Interaction>&,const shared_ptr<Body>&,const
> shared_ptr<Body>&,bool wireFrame);
> -               RENDERS(Dem3DofGeom_FacetSphere);
> -
> YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_Dem3DofGeom_FacetSphere,GlIGeomFunctor,"Render
> interaction of facet and sphere (represented by Dem3DofGeom_FacetSphere)",
> -                       ((bool,normal,false,,"Render interaction normal"))
> -                       ((bool,rolledPoints,false,,"Render points rolled
> on the sphere & facet (original contact point)"))
> -                       ((bool,unrolledPoints,false,,"Render original
> contact points unrolled to the contact plane"))
> -                       ((bool,shear,false,,"Render shear line in the
> contact plane"))
> -                       ((bool,shearLabel,false,,"Render shear magnitude
> as number"))
> -               );
> -       };
> -       REGISTER_SERIALIZABLE(Gl1_Dem3DofGeom_FacetSphere);
> -#endif
> -
> -#include<yade/pkg/common/Dispatching.hpp>
> -class Ig2_Facet_Sphere_Dem3DofGeom:public IGeomFunctor{
> -       Vector3r getClosestSegmentPt(const Vector3r& P, const Vector3r& A,
> const Vector3r& B){
> -               // algo:
> http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
> -               Vector3r BA=B-A;
> -               Real u=(P.dot(BA)-A.dot(BA))/(BA.squaredNorm());
> -               return A+min((Real)1.,max((Real)0.,u))*BA;
> -       }
> -       public:
> -               virtual bool go(const shared_ptr<Shape>& cm1, const
> shared_ptr<Shape>& cm2, const State& state1, const State& state2, const
> Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
> -               virtual bool goReverse( const shared_ptr<Shape>& cm1,
> const shared_ptr<Shape>& cm2, const State& state1, const State& state2,
> const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>&
> c){
> -                       c->swapOrder(); return
> go(cm2,cm1,state2,state1,-shift2,force,c);
> -                       LOG_ERROR("!! goReverse maybe doesn't work in
> Ig2_Facet_Sphere_Dem3DofGeom. IGeomDispatcher should swap interaction
> members first and call go(...) afterwards.");
> -               }
> -
> -       FUNCTOR2D(Facet,Sphere);
> -       DEFINE_FUNCTOR_ORDER_2D(Facet,Sphere);
> -
> YADE_CLASS_BASE_DOC_ATTRS(Ig2_Facet_Sphere_Dem3DofGeom,IGeomFunctor,"Compute
> geometry of facet-sphere contact with normal and shear DOFs. As in all
> other Dem3DofGeom-related classes, total formulation of both shear and
> normal deformations is used. See :yref:`Dem3DofGeom_FacetSphere` for more
> information.",
> -               // unused: ((Real,shrinkFactor,0.,,"Reduce the facet's
> size, probably to avoid singularities at common facets' edges (?)"))
> -       );
> -       DECLARE_LOGGER;
> -};
> -REGISTER_SERIALIZABLE(Ig2_Facet_Sphere_Dem3DofGeom);
> -
>
> === removed file 'pkg/dem/Dem3DofGeom_SphereSphere.cpp'
> --- pkg/dem/Dem3DofGeom_SphereSphere.cpp        2010-12-13 12:11:43 +0000
> +++ pkg/dem/Dem3DofGeom_SphereSphere.cpp        1970-01-01 00:00:00 +0000
> @@ -1,196 +0,0 @@
> -#include "Dem3DofGeom_SphereSphere.hpp"
> -
> -#include<yade/pkg/common/Sphere.hpp>
> -#include<yade/core/Omega.hpp>
> -YADE_PLUGIN((Dem3DofGeom_SphereSphere)
> -       #ifdef YADE_OPENGL
> -               (Gl1_Dem3DofGeom_SphereSphere)
> -       #endif
> -       (Ig2_Sphere_Sphere_Dem3DofGeom));
> -
> -
> -Dem3DofGeom_SphereSphere::~Dem3DofGeom_SphereSphere(){}
> -
> -/*! Project point from sphere surface to tangent plane,
> - * such that the angle of shortest arc from (1,0,0) pt on the sphere to
> the point itself is the same
> - * as the angle of segment of the same length on the tangent plane.
> - *
> - * This function is (or should be) inverse of ScGeom::rollPlanePtToSphere.
> - *
> - * @param fromXtoPtOri gives orientation of the vector from sphere center
> to the sphere point from the global +x axis.
> - * @param radius the distance from sphere center to the contact plane
> - * @param planeNormal unit vector pointing away from the sphere center,
> determining plane orientation on which the projected point lies.
> - * @returns The projected point coordinates (with origin at the contact
> point).
> - */
> -Vector3r Dem3DofGeom_SphereSphere::unrollSpherePtToPlane(const
> Quaternionr& fromXtoPtOri, const Real& radius, const Vector3r& planeNormal){
> -       Quaternionr normal2pt;
> normal2pt.setFromTwoVectors(planeNormal,fromXtoPtOri*Vector3r::UnitX());
> -       AngleAxisr aa(normal2pt);
> -       return (aa.angle()*radius) /* length */
> *(aa.axis().cross(planeNormal)) /* direction: both are unit vectors */;
> -}
> -
> -/*! Project point from tangent plane to the sphere.
> - *
> - * This function is (or should be) inverse of
> ScGeom::unrollSpherePtToPlane.
> - *
> - * @param planePt point on the tangent plane, with origin at the contact
> point (i.e. at sphere center + normal*radius)
> - * @param radius sphere radius
> - * @param planeNormal _unit_ vector pointing away from sphere center
> - * @returns orientation that transforms +x axis to the vector between
> sphere center and point on the sphere that corresponds to planePt.
> - *
> - * @note It is not checked whether planePt relly lies on the tangent
> plane. If not, result will be incorrect.
> - */
> -Quaternionr Dem3DofGeom_SphereSphere::rollPlanePtToSphere(const Vector3r&
> planePt, const Real& radius, const Vector3r& planeNormal){
> -       if (planePt!=Vector3r::Zero()) {
> -               Quaternionr normal2pt;
> -               Vector3r axis=planeNormal.cross(planePt); axis.normalize();
> -               Real angle=planePt.norm()/radius;
> -               normal2pt=Quaternionr(AngleAxisr(angle,axis));
> -               Quaternionr ret; return
> ret.setFromTwoVectors(Vector3r::UnitX(),normal2pt*planeNormal);
> -       } else {
> -               Quaternionr ret; return
> ret.setFromTwoVectors(Vector3r::UnitX(),planeNormal);
> -       }
> -}
> -
> -
> -
> -/* Set contact points on both spheres such that their projection is the
> one given
> - * (should be on the plane passing through origin and oriented with
> normal; not checked!)
> - */
> -void Dem3DofGeom_SphereSphere::setTgPlanePts(Vector3r p1new, Vector3r
> p2new){
> -       cp1rel=ori1.conjugate()*rollPlanePtToSphere(p1new,effR1,normal);
> -       cp2rel=ori2.conjugate()*rollPlanePtToSphere(p2new,effR2,-normal);
> -}
> -
> -
> -
> -/*! Perform slip of the projected contact points so that their distance
> becomes equal (or remains smaller) than the given one.
> - * The slipped distance is returned.
> - */
> -Real Dem3DofGeom_SphereSphere::slipToDisplacementTMax(Real
> displacementTMax){
> -       // very close, reset shear
> -       if(displacementTMax<=0.){
> setTgPlanePts(Vector3r(0,0,0),Vector3r(0,0,0)); return displacementTMax;}
> -       // otherwise
> -       Vector3r p1=contPtInTgPlane1(), p2=contPtInTgPlane2();
> -       Real currDistSq=(p2-p1).squaredNorm();
> -       if(currDistSq<pow(displacementTMax,2)) return 0; // close enough,
> no slip needed
> -       Vector3r diff=.5*(displacementTMax/sqrt(currDistSq)-1)*(p2-p1);
> -       setTgPlanePts(p1-diff,p2+diff);
> -       return 2*diff.norm();
> -}
> -
> -
> -/* Move contact point on both spheres in such way that their relative
> position (displacementT) is the same;
> - * this should be done regularly to ensure that the angle doesn't go over
> π, since then quaternion would
> - * flip axis and the point would project on other side of the tangent
> plane piece. */
> -void Dem3DofGeom_SphereSphere::relocateContactPoints(){
> -       relocateContactPoints(contPtInTgPlane1(),contPtInTgPlane2());
> -}
> -
> -/*! Like Dem3DofGeom_SphereSphere::relocateContactPoints(), but use
> already computed tangent plane points. */
> -void Dem3DofGeom_SphereSphere::relocateContactPoints(const Vector3r& p1,
> const Vector3r& p2){
> -       Vector3r midPt=(effR1/(effR1+effR2))*(p1+p2); // proportionally to
> radii, so that angle would be the same
> -       if((p1.squaredNorm()>pow(effR1,2) ||
> p2.squaredNorm()>pow(effR2,2)) &&
> midPt.squaredNorm()>pow(min(effR1,effR2),2)){
> -               //cerr<<"RELOCATION with displacementT="<<displacementT();
> // should be the same before and after relocation
> -               setTgPlanePts(p1-midPt,p2-midPt);
> -               //cerr<<" → "<<displacementT()<<endl;
> -       }
> -}
> -
> -
> -
> -#ifdef YADE_OPENGL
> -       #include<yade/lib/opengl/OpenGLWrapper.hpp>
> -       #include<yade/lib/opengl/GLUtils.hpp>
> -       bool Gl1_Dem3DofGeom_SphereSphere::normal=false;
> -       bool Gl1_Dem3DofGeom_SphereSphere::rolledPoints=false;
> -       bool Gl1_Dem3DofGeom_SphereSphere::unrolledPoints=false;
> -       bool Gl1_Dem3DofGeom_SphereSphere::shear=false;
> -       bool Gl1_Dem3DofGeom_SphereSphere::shearLabel=false;
> -
> -       void Gl1_Dem3DofGeom_SphereSphere::go(const shared_ptr<IGeom>& ig,
> const shared_ptr<Interaction>& ip, const shared_ptr<Body>& b1, const
> shared_ptr<Body>& b2, bool wireFrame){
> -               Dem3DofGeom_SphereSphere* ss =
> static_cast<Dem3DofGeom_SphereSphere*>(ig.get());
> -               //const Se3r&
> se31=b1->physicalParameters->dispSe3,se32=b2->physicalParameters->dispSe3;
> -               const Se3r& se31=b1->state->se3,se32=b2->state->se3;
> -               const Vector3r& pos1=se31.position,pos2=se32.position;
> -               Vector3r& contPt=ss->contactPoint;
> -
> -               if(normal){
> -
> GLUtils::GLDrawArrow(contPt,contPt+ss->normal*.5*ss->refLength); // normal
> of the contact
> -               }
> -               #if 0
> -                       // never used, since bending/torsion not used
> -                       //Vector3r
> contPt=se31.position+(ss->effR1/ss->refLength)*(se32.position-se31.position);
> // must be recalculated to not be unscaled if scaling displacements ...
> -                       GLUtils::GLDrawLine(pos1,pos2,Vector3r(.5,.5,.5));
> -                       Vector3r bend; Real tors;
> -                       ss->bendingTorsionRel(bend,tors);
> -
> GLUtils::GLDrawLine(contPt,contPt+10*ss->radius1*(bend+ss->normal*tors),Vector3r(1,0,0));
> -                       #if 0
> -
> GLUtils::GLDrawNum(bend[0],contPt-.2*ss->normal*ss->radius1,Vector3r(1,0,0));
> -
> GLUtils::GLDrawNum(bend[1],contPt,Vector3r(0,1,0));
> -
> GLUtils::GLDrawNum(bend[2],contPt+.2*ss->normal*ss->radius1,Vector3r(0,0,1));
> -
> GLUtils::GLDrawNum(tors,contPt+.5*ss->normal*ss->radius2,Vector3r(1,1,0));
> -                       #endif
> -               #endif
> -               // sphere center to point on the sphere
> -               if(rolledPoints){
> -
> GLUtils::GLDrawLine(pos1,pos1+(ss->ori1*ss->cp1rel*Vector3r::UnitX()*ss->effR1),Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(pos2,pos2+(ss->ori2*ss->cp2rel*Vector3r::UnitX()*ss->effR2),Vector3r(0,1,.5));
> -               }
> -               //TRVAR4(pos1,ss->ori1,pos2,ss->ori2);
> -
> //TRVAR2(ss->cp2rel,pos2+(ss->ori2*ss->cp2rel*Vector3r::UnitX()*ss->effR2));
> -               // contact point to projected points
> -               if(unrolledPoints||shear){
> -                       Vector3r ptTg1=ss->contPtInTgPlane1(),
> ptTg2=ss->contPtInTgPlane2();
> -                       if(unrolledPoints){
> -                               //TRVAR3(ptTg1,ptTg2,ss->normal)
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg1,Vector3r(0,.5,1));
> GLUtils::GLDrawLine(pos1,contPt+ptTg1,Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg2,Vector3r(0,1,.5));
> GLUtils::GLDrawLine(pos2,contPt+ptTg2,Vector3r(0,1,.5));
> -                       }
> -                       if(shear){
> -
> GLUtils::GLDrawLine(contPt+ptTg1,contPt+ptTg2,Vector3r(1,1,1));
> -                               if(shearLabel)
> GLUtils::GLDrawNum(ss->displacementT().norm(),contPt,Vector3r(1,1,1));
> -                       }
> -               }
> -       }
> -#endif
> -
> -CREATE_LOGGER(Ig2_Sphere_Sphere_Dem3DofGeom);
> -
> -bool Ig2_Sphere_Sphere_Dem3DofGeom::go(const shared_ptr<Shape>& cm1,
> const shared_ptr<Shape>& cm2, const State& state1, const State& state2,
> const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>&
> c){
> -       Sphere *s1=static_cast<Sphere*>(cm1.get()),
> *s2=static_cast<Sphere*>(cm2.get());
> -       Vector3r normal=(state2.pos+shift2)-state1.pos;
> -       Real
> penetrationDepthSq=pow((distFactor>0?distFactor:1.)*(s1->radius+s2->radius),2)-normal.squaredNorm();
> -       if (penetrationDepthSq<0 && !c->isReal() && !force){
> -               return false;
> -       }
> -
> -       Real dist=normal.norm(); normal/=dist; /* normal is unit vector
> now */
> -       shared_ptr<Dem3DofGeom_SphereSphere> ss;
> -       if(c->geom) ss=YADE_PTR_CAST<Dem3DofGeom_SphereSphere>(c->geom);
> -       else {
> -               ss=shared_ptr<Dem3DofGeom_SphereSphere>(new
> Dem3DofGeom_SphereSphere());
> -               c->geom=ss;
> -
> -               // constants
> -               if(distFactor>0) ss->refLength=dist;
> -               else ss->refLength=s1->radius+s2->radius;
> -               ss->refR1=s1->radius; ss->refR2=s2->radius;
> -
> -               Real penetrationDepth=s1->radius+s2->radius-ss->refLength;
> -
> -               if(scene->iter<=10){
> -                       ss->effR1=s1->radius-.5*penetrationDepth;
> ss->effR2=s2->radius-.5*penetrationDepth;
> -               } else {ss->effR1=s1->radius; ss->effR2=s2->radius;}
> -
> -               // for bending only:
> ss->initRelOri12=state1.ori.Conjugate()*state2.ori;
> -               // quasi-constants
> -
> ss->cp1rel.setFromTwoVectors(Vector3r::UnitX(),state1.ori.conjugate()*normal);
> -
> ss->cp2rel.setFromTwoVectors(Vector3r::UnitX(),state2.ori.conjugate()*(-normal));
> -               ss->cp1rel.normalize(); ss->cp2rel.normalize();
> -       }
> -       ss->normal=normal;
> -
> ss->contactPoint=state1.pos+(ss->effR1-.5*(ss->refLength-dist))*ss->normal;
> -       ss->se31=state1.se3; ss->se32=state2.se3;
> ss->se32.position+=shift2;
> -       return true;
> -}
> -
>
> === removed file 'pkg/dem/Dem3DofGeom_SphereSphere.hpp'
> --- pkg/dem/Dem3DofGeom_SphereSphere.hpp        2011-01-09 16:34:50 +0000
> +++ pkg/dem/Dem3DofGeom_SphereSphere.hpp        1970-01-01 00:00:00 +0000
> @@ -1,80 +0,0 @@
> -#pragma once
> -#include<yade/pkg/dem/DemXDofGeom.hpp>
> -#include<yade/pkg/common/Sphere.hpp>
> -
> -class Dem3DofGeom_SphereSphere: public Dem3DofGeom{
> -       public:
> -               // auxiliary functions; the quaternion magic is all in here
> -               static Vector3r unrollSpherePtToPlane(const Quaternionr&
> fromXtoPtOri, const Real& radius, const Vector3r& normal);
> -               static Quaternionr rollPlanePtToSphere(const Vector3r&
> planePt, const Real& radius, const Vector3r& normal);
> -       private:
> -               Vector3r contPtInTgPlane1() const { return
> unrollSpherePtToPlane(ori1*cp1rel,effR1,normal); }
> -               Vector3r contPtInTgPlane2() const { return
> unrollSpherePtToPlane(ori2*cp2rel,effR2,-normal);}
> -               void setTgPlanePts(Vector3r p1new, Vector3r p2new);
> -               void relocateContactPoints();
> -               void relocateContactPoints(const Vector3r& tgPlanePt1,
> const Vector3r& tgPlanePt2);
> -       public:
> -               //! shorthands
> -               const Vector3r &pos1; const Quaternionr &ori1; const
> Vector3r &pos2; const Quaternionr &ori2;
> -               virtual ~Dem3DofGeom_SphereSphere();
> -
> -               /********* API **********/
> -               Real displacementN(){ return (pos2-pos1).norm()-refLength;
> }
> -               Vector3r displacementT() {
> -                       // enabling automatic relocation decreases overall
> simulation speed by about 3%; perhaps: bool largeStrains ... ?
> -                       #if 1
> -                               Vector3r p1=contPtInTgPlane1(),
> p2=contPtInTgPlane2(); relocateContactPoints(p1,p2); return p2-p1; // shear
> before relocation, but that is OK
> -                       #else
> -                               return
> contPtInTgPlane2()-contPtInTgPlane1();
> -                       #endif
> -               }
> -               virtual Real slipToDisplacementTMax(Real displacementTMax);
> -               /********* end API ***********/
> -
> -
> YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(Dem3DofGeom_SphereSphere,Dem3DofGeom,"Class
> representing 2 spheres in contact which computes 3 degrees of freedom
> (normal and shear deformation).",
> -               ((Real,effR1,,,"Effective radius of sphere #1; can be
> smaller/larger than refR1 (the actual radius), but quasi-constant
> throughout interaction life"))
> -               ((Real,effR2,,,"Same as effR1, but for sphere #2."))
> -               ((Quaternionr,cp1rel,,,"Sphere's #1 relative orientation
> of the contact point with regards to sphere-local +x axis
> (quasi-constant)"))
> -               ((Quaternionr,cp2rel,,,"Same as cp1rel, but for sphere
> #2.")),
> -               /* extra initializers */
> ((pos1,se31.position))((ori1,se31.orientation))((pos2,se32.position))((ori2,se32.orientation)),
> -               /*ctor*/ createIndex(); ,
> -               /*py*/
> -       );
> -       REGISTER_CLASS_INDEX(Dem3DofGeom_SphereSphere,Dem3DofGeom);
> -       friend class Gl1_Dem3DofGeom_SphereSphere;
> -       friend class Ig2_Sphere_Sphere_Dem3DofGeom;
> -};
> -REGISTER_SERIALIZABLE(Dem3DofGeom_SphereSphere);
> -
> -#ifdef YADE_OPENGL
> -       #include<yade/pkg/common/GLDrawFunctors.hpp>
> -       class Gl1_Dem3DofGeom_SphereSphere:public GlIGeomFunctor{
> -               public:
> -                       virtual void go(const shared_ptr<IGeom>&,const
> shared_ptr<Interaction>&,const shared_ptr<Body>&,const
> shared_ptr<Body>&,bool wireFrame);
> -               RENDERS(Dem3DofGeom_SphereSphere);
> -
> YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_Dem3DofGeom_SphereSphere,GlIGeomFunctor,"Render
> interaction of 2 spheres (represented by Dem3DofGeom_SphereSphere)",
> -                       ((bool,normal,false,,"Render interaction normal"))
> -                       ((bool,rolledPoints,false,,"Render points rolled
> on the spheres (tracks the original contact point)"))
> -                       ((bool,unrolledPoints,false,,"Render original
> contact points unrolled to the contact plane"))
> -                       ((bool,shear,false,,"Render shear line in the
> contact plane"))
> -                       ((bool,shearLabel,false,,"Render shear magnitude
> as number"))
> -               );
> -       };
> -       REGISTER_SERIALIZABLE(Gl1_Dem3DofGeom_SphereSphere);
> -#endif
> -
> -#include<yade/pkg/common/Dispatching.hpp>
> -class Ig2_Sphere_Sphere_Dem3DofGeom:public IGeomFunctor{
> -       public:
> -               virtual bool go(const shared_ptr<Shape>& cm1, const
> shared_ptr<Shape>& cm2, const State& state1, const State& state2, const
> Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
> -               virtual bool goReverse( const shared_ptr<Shape>&, const
> shared_ptr<Shape>&, const State&, const State&, const Vector3r& shift2,
> const bool& force, const shared_ptr<Interaction>&){throw
> runtime_error("goReverse on symmetric functor should never be called!");}
> -       FUNCTOR2D(Sphere,Sphere);
> -       DEFINE_FUNCTOR_ORDER_2D(Sphere,Sphere);
> -       DECLARE_LOGGER;
> -
> YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_Sphere_Dem3DofGeom,IGeomFunctor,
> -               "Functor handling contact of 2 spheres, producing
> Dem3DofGeom instance",
> -               ((Real,distFactor,-1,,"Factor of sphere radius such that
> sphere \"touch\" if their centers are not further than distFactor*(r1+r2);
> if negative, equilibrium distance is the sum of the sphere's radii."))
> -       );
> -};
> -REGISTER_SERIALIZABLE(Ig2_Sphere_Sphere_Dem3DofGeom);
> -
>
> === removed file 'pkg/dem/Dem3DofGeom_WallSphere.cpp'
> --- pkg/dem/Dem3DofGeom_WallSphere.cpp  2010-12-13 12:11:43 +0000
> +++ pkg/dem/Dem3DofGeom_WallSphere.cpp  1970-01-01 00:00:00 +0000
> @@ -1,117 +0,0 @@
> -// © 2009 Václav Šmilauer <eudoxos@xxxxxxxx>
> -#include<yade/pkg/dem/Dem3DofGeom_WallSphere.hpp>
> -#include<yade/pkg/common/Sphere.hpp>
> -#include<yade/pkg/common/Wall.hpp>
> -YADE_PLUGIN((Dem3DofGeom_WallSphere)
> -       #ifdef YADE_OPENGL
> -               (Gl1_Dem3DofGeom_WallSphere)
> -       #endif
> -               (Ig2_Wall_Sphere_Dem3DofGeom));
> -
> -CREATE_LOGGER(Dem3DofGeom_WallSphere);
> -Dem3DofGeom_WallSphere::~Dem3DofGeom_WallSphere(){}
> -
> -void Dem3DofGeom_WallSphere::setTgPlanePts(const Vector3r& p1new, const
> Vector3r& p2new){
> -       TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());
> -       cp1pt=p1new+contactPoint-se31.position;
> -
> cp2rel=se32.orientation.conjugate()*Dem3DofGeom_SphereSphere::rollPlanePtToSphere(p2new,effR2,-normal);
> -       TRVAR3(cp1pt,cp2rel,contPtInTgPlane2()-contPtInTgPlane1());
> -}
> -
> -void Dem3DofGeom_WallSphere::relocateContactPoints(const Vector3r& p1,
> const Vector3r& p2){
> -       //TRVAR2(p2.norm(),effR2);
> -       if(p2.squaredNorm()>pow(effR2,2)){
> -               setTgPlanePts(Vector3r::Zero(),p2-p1);
> -       }
> -}
> -
> -Real Dem3DofGeom_WallSphere::slipToDisplacementTMax(Real
> displacementTMax){
> -       //FIXME: not yet tested
> -       // negative or zero: reset shear
> -       if(displacementTMax<=0.){
> setTgPlanePts(Vector3r(0,0,0),Vector3r(0,0,0)); return displacementTMax;}
> -       // otherwise
> -       Vector3r p1=contPtInTgPlane1(), p2=contPtInTgPlane2();
> -       Real currDistSq=(p2-p1).squaredNorm();
> -       if(currDistSq<pow(displacementTMax,2)) return 0; // close enough,
> no slip needed
> -       //Vector3r diff=.5*(sqrt(currDistSq)/displacementTMax-1)*(p2-p1);
> setTgPlanePts(p1+diff,p2-diff);
> -       Real scale=displacementTMax/sqrt(currDistSq);
> setTgPlanePts(scale*p1,scale*p2);
> -       return (displacementTMax/scale)*(1-scale);
> -}
> -
> -CREATE_LOGGER(Ig2_Wall_Sphere_Dem3DofGeom);
> -bool Ig2_Wall_Sphere_Dem3DofGeom::go(const shared_ptr<Shape>& cm1, const
> shared_ptr<Shape>& cm2, const State& state1, const State& state2, const
> Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c){
> -       Wall* wall=static_cast<Wall*>(cm1.get());
> -       Real sphereRadius=static_cast<Sphere*>(cm2.get())->radius;
> -
> -       Real dist=(state2.pos+shift2)[wall->axis]-state1.pos[wall->axis];
> -       if(!c->isReal() && abs(dist)>sphereRadius && !force){
> /*LOG_DEBUG("dist="<<dist<<", returning false");*/ return false; } // wall
> and sphere too far from each other
> -
> -       // contact point is sphere center projected onto the wall
> -       Vector3r contPt=state2.pos;
> contPt[wall->axis]=state1.pos[wall->axis];
> -       Vector3r normalGlob(0.,0.,0.);
> -       // wall interacting from both sides: normal depends on sphere's
> position
> -       assert(wall->sense==-1 || wall->sense==0 || wall->sense==1);
> -       if(wall->sense==0) normalGlob[wall->axis]=dist>0?1.:-1.;
> -       else normalGlob[wall->axis]=wall->sense==1?1.:-1;
> -
> -       shared_ptr<Dem3DofGeom_WallSphere> ws;
> -       if(c->geom) ws=YADE_PTR_CAST<Dem3DofGeom_WallSphere>(c->geom);
> -       else {
> -               ws=shared_ptr<Dem3DofGeom_WallSphere>(new
> Dem3DofGeom_WallSphere());
> -               c->geom=ws;
> -               ws->effR2=abs(dist);
> -               ws->refR1=-1; ws->refR2=sphereRadius;
> -               ws->refLength=ws->effR2;
> -               ws->cp1pt=contPt-state1.pos; // initial contact point
> relative to wall position (orientation is global, since it is coincident
> with local for a wall)
> -               ws->cp2rel=Quaternionr::Identity();
> -
> ws->cp2rel.setFromTwoVectors(Vector3r::UnitX(),state2.ori.conjugate()*(-normalGlob));
> // initial sphere-local center-contactPt orientation WRT +x
> -               ws->cp2rel.normalize();
> -               //LOG_INFO(ws->cp1pt);
> -       }
> -       ws->se31=state1.se3; ws->se32=state2.se3;
> ws->se32.position+=shift2;
> -       ws->contactPoint=contPt;
> -       ws->normal=normalGlob;
> -       return true;
> -}
> -#ifdef YADE_OPENGL
> -
> -       #include<yade/lib/opengl/OpenGLWrapper.hpp>
> -       #include<yade/lib/opengl/GLUtils.hpp>
> -
> -       bool Gl1_Dem3DofGeom_WallSphere::normal=false;
> -       bool Gl1_Dem3DofGeom_WallSphere::rolledPoints=false;
> -       bool Gl1_Dem3DofGeom_WallSphere::unrolledPoints=false;
> -       bool Gl1_Dem3DofGeom_WallSphere::shear=false;
> -       bool Gl1_Dem3DofGeom_WallSphere::shearLabel=false;
> -
> -       void Gl1_Dem3DofGeom_WallSphere::go(const shared_ptr<IGeom>& ig,
> const shared_ptr<Interaction>& ip, const shared_ptr<Body>& b1, const
> shared_ptr<Body>& b2, bool wireFrame){
> -               Dem3DofGeom_WallSphere*
> ws=static_cast<Dem3DofGeom_WallSphere*>(ig.get());
> -               const Se3r& se31=b1->state->se3,se32=b2->state->se3;
> -               const Vector3r& pos1=se31.position; const Vector3r&
> pos2=se32.position;
> -               //const Quaternionr& ori1=se31.orientation;
> -               const Quaternionr& ori2=se32.orientation;
> -               const Vector3r& contPt=ws->contactPoint;
> -
> -               if(normal){
> -
> GLUtils::GLDrawArrow(contPt,contPt+ws->refLength*ws->normal); // normal of
> the contact
> -               }
> -               // sphere center to point on the sphere
> -               if(rolledPoints){
> -
> GLUtils::GLDrawLine(pos1+ws->cp1pt,contPt,Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(pos2,pos2+(ori2*ws->cp2rel*Vector3r::UnitX()*ws->effR2),Vector3r(0,1,.5));
> -               }
> -               // contact point to projected points
> -               if(unrolledPoints||shear){
> -                       Vector3r ptTg1=ws->contPtInTgPlane1(),
> ptTg2=ws->contPtInTgPlane2();
> -                       if(unrolledPoints){
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg1,Vector3r(0,.5,1));
> -
> GLUtils::GLDrawLine(contPt,contPt+ptTg2,Vector3r(0,1,.5));
> GLUtils::GLDrawLine(pos2,contPt+ptTg2,Vector3r(0,1,.5));
> -                       }
> -                       if(shear){
> -
> GLUtils::GLDrawLine(contPt+ptTg1,contPt+ptTg2,Vector3r(1,1,1));
> -                               if(shearLabel)
> GLUtils::GLDrawNum(ws->displacementT().norm(),contPt,Vector3r(1,1,1));
> -                       }
> -               }
> -       }
> -
> -#endif
>
> === removed file 'pkg/dem/Dem3DofGeom_WallSphere.hpp'
> --- pkg/dem/Dem3DofGeom_WallSphere.hpp  2011-01-09 16:34:50 +0000
> +++ pkg/dem/Dem3DofGeom_WallSphere.hpp  1970-01-01 00:00:00 +0000
> @@ -1,70 +0,0 @@
> -#pragma once
> -#include<yade/pkg/dem/DemXDofGeom.hpp>
> -// for static roll/unroll functions in Dem3DofGeom_SphereSphere
> -#include<yade/pkg/dem/Dem3DofGeom_SphereSphere.hpp>
> -#include<yade/pkg/common/Sphere.hpp>
> -#include<yade/pkg/common/Wall.hpp>
> -
> -class Dem3DofGeom_WallSphere: public Dem3DofGeom{
> -
> -       Vector3r contPtInTgPlane1() const { return
> se31.position+cp1pt-contactPoint; }
> -       Vector3r contPtInTgPlane2() const { return
> Dem3DofGeom_SphereSphere::unrollSpherePtToPlane(se32.orientation*cp2rel,effR2,-normal);}
> -
> -       public:
> -               virtual ~Dem3DofGeom_WallSphere();
> -               /******* API ********/
> -               virtual Real displacementN(){ return
> (se32.position-contactPoint).norm()-refLength;}
> -               virtual Vector3r displacementT(){ relocateContactPoints();
> return contPtInTgPlane2()-contPtInTgPlane1(); }
> -               virtual Real slipToDisplacementTMax(Real displacementTMax);
> -               /***** end API ******/
> -
> -               void setTgPlanePts(const Vector3r&, const Vector3r&);
> -               void relocateContactPoints(){
> relocateContactPoints(contPtInTgPlane1(),contPtInTgPlane2()); }
> -               void relocateContactPoints(const Vector3r& p1, const
> Vector3r& p2);
> -
> -
> YADE_CLASS_BASE_DOC_ATTRS_CTOR(Dem3DofGeom_WallSphere,Dem3DofGeom,"Representation
> of contact between wall and sphere, based on Dem3DofGeom.",
> -               ((Vector3r,cp1pt,,,"initial contact point on the wall,
> relative to the current contact point"))
> -               ((Quaternionr,cp2rel,,,"orientation between +x and the
> reference contact point (on the sphere) in sphere-local coords"))
> -               ((Real,effR2,,,"effective radius of sphere")),
> -               /*ctor*/ createIndex();
> -       );
> -       REGISTER_CLASS_INDEX(Dem3DofGeom_WallSphere,Dem3DofGeom);
> -       DECLARE_LOGGER;
> -       friend class Gl1_Dem3DofGeom_WallSphere;
> -       friend class Ig2_Wall_Sphere_Dem3DofGeom;
> -};
> -REGISTER_SERIALIZABLE(Dem3DofGeom_WallSphere);
> -
> -#ifdef YADE_OPENGL
> -       #include<yade/pkg/common/GLDrawFunctors.hpp>
> -       class Gl1_Dem3DofGeom_WallSphere:public GlIGeomFunctor{
> -               public:
> -                       virtual void go(const shared_ptr<IGeom>&,const
> shared_ptr<Interaction>&,const shared_ptr<Body>&,const
> shared_ptr<Body>&,bool wireFrame);
> -               RENDERS(Dem3DofGeom_WallSphere);
> -
> YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_Dem3DofGeom_WallSphere,GlIGeomFunctor,"Render
> interaction of wall and sphere (represented by Dem3DofGeom_WallSphere)",
> -                       ((bool,normal,false,,"Render interaction normal"))
> -                       ((bool,rolledPoints,false,,"Render points rolled
> on the spheres (tracks the original contact point)"))
> -                       ((bool,unrolledPoints,false,,"Render original
> contact points unrolled to the contact plane"))
> -                       ((bool,shear,false,,"Render shear line in the
> contact plane"))
> -                       ((bool,shearLabel,false,,"Render shear magnitude
> as number"))
> -               );
> -       };
> -       REGISTER_SERIALIZABLE(Gl1_Dem3DofGeom_WallSphere);
> -#endif
> -
> -#include<yade/pkg/common/Dispatching.hpp>
> -class Ig2_Wall_Sphere_Dem3DofGeom:public IGeomFunctor{
> -       public:
> -               virtual bool go(const shared_ptr<Shape>& cm1, const
> shared_ptr<Shape>& cm2, const State& state1, const State& state2, const
> Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
> -               virtual bool goReverse( const shared_ptr<Shape>& cm1,
> const shared_ptr<Shape>& cm2, const State& state1, const State& state2,
> const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>&
> c){
> -                       c->swapOrder(); return
> go(cm2,cm1,state2,state1,-shift2,force,c);
> -                       LOG_ERROR("!! goReverse might not work in
> Ig2_Wall_Sphere_Dem3DofGeom. IGeomDispatcher should swap interaction
> members first and call go(...) afterwards.");
> -               }
> -
> -       FUNCTOR2D(Wall,Sphere);
> -       DEFINE_FUNCTOR_ORDER_2D(Wall,Sphere);
> -
> YADE_CLASS_BASE_DOC(Ig2_Wall_Sphere_Dem3DofGeom,IGeomFunctor,"Create/update
> contact of :yref:`Wall` and :yref:`Sphere` (:yref:`Dem3DofGeom_WallSphere`
> instance)");
> -       DECLARE_LOGGER;
> -};
> -REGISTER_SERIALIZABLE(Ig2_Wall_Sphere_Dem3DofGeom);
> -
>
> === modified file 'pkg/dem/DemXDofGeom.cpp'
> --- pkg/dem/DemXDofGeom.cpp     2010-10-13 16:23:08 +0000
> +++ pkg/dem/DemXDofGeom.cpp     2013-08-29 10:30:31 +0000
> @@ -1,5 +1,3 @@
>  #include"DemXDofGeom.hpp"
> -YADE_PLUGIN((GenericSpheresContact)(Dem3DofGeom));
> -Real Dem3DofGeom::displacementN(){throw;}
> -Dem3DofGeom::~Dem3DofGeom(){}
> +YADE_PLUGIN((GenericSpheresContact));
>  GenericSpheresContact::~GenericSpheresContact(){}
>
> === modified file 'pkg/dem/DemXDofGeom.hpp'
> --- pkg/dem/DemXDofGeom.hpp     2011-01-24 14:45:35 +0000
> +++ pkg/dem/DemXDofGeom.hpp     2013-08-29 10:30:31 +0000
> @@ -2,12 +2,12 @@
>  #pragma once
>  #include<yade/core/IGeom.hpp>
>
> -/*! Abstract class that unites ScGeom and Dem3DofGeom,
> +/*! Abstract class that unites ScGeom and L3Geom,
>         created for the purposes of GlobalStiffnessTimeStepper.
>         It might be removed in the future. */
>  class GenericSpheresContact: public IGeom{
>         YADE_CLASS_BASE_DOC_ATTRS_CTOR(GenericSpheresContact,IGeom,
> -               "Class uniting :yref:`ScGeom` and :yref:`Dem3DofGeom`, for
> the purposes of :yref:`GlobalStiffnessTimeStepper`. (It might be removed
> inthe future). Do not use this class directly.",
> +               "Class uniting :yref:`ScGeom` and :yref:`L3Geom`, for the
> purposes of :yref:`GlobalStiffnessTimeStepper`. (It might be removed inthe
> future). Do not use this class directly.",
>                 ((Vector3r,normal,,,"Unit vector oriented along the
> interaction, from particle #1, towards particle #2. |yupdate|"))
>                 ((Vector3r,contactPoint,,,"some reference point for the
> interaction (usually in the middle). |ycomp|"))
>                 ((Real,refR1,,,"Reference radius of particle #1. |ycomp|"))
> @@ -19,45 +19,3 @@
>         virtual ~GenericSpheresContact(); // vtable
>  };
>  REGISTER_SERIALIZABLE(GenericSpheresContact);
> -
> -/*! Abstract base class for representing contact geometry of 2 elements
> that has 3 degrees of freedom:
> - *  normal (1 component) and shear (Vector3r, but in plane perpendicular
> to the normal)
> - */
> -class Dem3DofGeom: public GenericSpheresContact{
> -       public:
> -               virtual ~Dem3DofGeom();
> -
> -               // API that needs to be implemented in derived classes
> -               virtual Real displacementN();
> -               virtual Vector3r displacementT(){throw;}
> -               virtual Real slipToDisplacementTMax(Real
> displacementTMax){throw;}; // plasticity
> -               // reference radii, for contact stiffness computation; set
> to negative for nonsense values
> -               // end API
> -
> -               Real strainN(){
> -                       //if(!logCompression)
> -                       return displacementN()/refLength;
> -                       //else{Real dn=displacementN(); }
> -               }
> -               Vector3r strainT(){return displacementT()/refLength;}
> -               Real slipToStrainTMax(Real strainTMax){return
> slipToDisplacementTMax(strainTMax*refLength)/refLength;}
> -
> -
> YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Dem3DofGeom,GenericSpheresContact,
> -                       "Abstract base class for representing contact
> geometry of 2 elements that has 3 degrees of freedom: normal (1 component)
> and shear (Vector3r, but in plane perpendicular to the normal).",
> -                       ((Real,refLength,,,"some length used to convert
> displacements to strains. |ycomp|"))
> -                       ((bool,logCompression,false,,"make strain go to -∞
> for length going to zero (false by default)."))
> -                       ((Se3r,se31,,,"Copy of body #1 se3 (needed to
> compute torque from the contact, strains etc). |yupdate|"))
> -                       ((Se3r,se32,,,"Copy of body #2 se3. |yupdate|")),
> -                       createIndex();,
> -                       .def("displacementN",&Dem3DofGeom::displacementN)
> -                       .def("displacementT",&Dem3DofGeom::displacementT)
> -                       .def("strainN",&Dem3DofGeom::strainN)
> -                       .def("strainT",&Dem3DofGeom::strainT)
> -
> .def("slipToDisplacementTMax",&Dem3DofGeom::slipToDisplacementTMax)
> -
> .def("slipToStrainTMax",&Dem3DofGeom::slipToStrainTMax)
> -               );
> -               REGISTER_CLASS_INDEX(Dem3DofGeom,IGeom);
> -};
> -REGISTER_SERIALIZABLE(Dem3DofGeom);
> -
> -
>
> === modified file 'pkg/dem/DomainLimiter.cpp'
> --- pkg/dem/DomainLimiter.cpp   2013-08-23 15:21:20 +0000
> +++ pkg/dem/DomainLimiter.cpp   2013-08-29 10:30:31 +0000
> @@ -81,15 +81,14 @@
>         // test object types
>         GenericSpheresContact*
> gsc=dynamic_cast<GenericSpheresContact*>(I->geom.get());
>         ScGeom* scGeom=dynamic_cast<ScGeom*>(I->geom.get());
> -       Dem3DofGeom* d3dGeom=dynamic_cast<Dem3DofGeom*>(I->geom.get());
>         L3Geom* l3Geom=dynamic_cast<L3Geom*>(I->geom.get());
>         L6Geom* l6Geom=dynamic_cast<L6Geom*>(I->geom.get());
>         ScGeom6D* scGeom6d=dynamic_cast<ScGeom6D*>(I->geom.get());
>         bool hasRot=(l6Geom || scGeom6d);
>         //NormShearPhys* phys=dynamic_cast<NormShearPhys*>(I->phys.get());
>                      //Disabled because of warning
>         if(!gsc) throw std::invalid_argument("LawTester: IGeom of
> "+strIds+" not a GenericSpheresContact.");
> -       if(!scGeom && !d3dGeom && !l3Geom) throw
> std::invalid_argument("LawTester: IGeom of "+strIds+" is neither ScGeom,
> nor Dem3DofGeom, nor L3Geom (or L6Geom).");
> -       assert(!((bool)scGeom && (bool)d3dGeom && (bool)l3Geom)); //
> nonsense
> +       if(!scGeom && !l3Geom) throw std::invalid_argument("LawTester:
> IGeom of "+strIds+" is neither ScGeom, nor Dem3DofGeom, nor L3Geom (or
> L6Geom).");
> +       assert(!((bool)scGeom && (bool)l3Geom)); // nonsense
>         // get body objects
>         State *state1=Body::byId(id1,scene)->state.get(),
> *state2=Body::byId(id2,scene)->state.get();
>         scene->forces.sync();
> @@ -125,9 +124,7 @@
>                                 if(scGeom6d)
> uGeom.tail<3>()=-1.*Vector3r(scGeom6d->getTwist(),scGeom6d->getBending().dot(axY),scGeom6d->getBending().dot(axZ));
>                         }
>                         else{ // d3dGeom
> -                               throw runtime_error("LawTester:
> Dem3DofGeom not yet supported.");
> -                               // essentially copies code from ScGeom,
> which is not very nice indeed; oh well…
> -                               // Vector3r
> vRel=(state2->vel+state2->angVel.cross(-gsc->refR2*gsc->normal))-(state1->vel+state1->angVel.cross(gsc->refR1*gsc->normal));
> +                               throw runtime_error("Geom type not yet
> supported.");
>                         }
>                 }
>                 // update the transformation
>
> === modified file 'pkg/dem/FlowEngine.cpp'
> --- pkg/dem/FlowEngine.cpp      2013-07-26 18:16:04 +0000
> +++ pkg/dem/FlowEngine.cpp      2013-08-30 13:27:06 +0000
> @@ -21,6 +21,10 @@
>  #include <boost/date_time.hpp>
>  #include <boost/date_time/posix_time/posix_time.hpp>
>
> +#ifdef LINSOLV
> +#include <cholmod.h>
> +#endif
> +
>  #include "FlowEngine.hpp"
>
>  CREATE_LOGGER ( FlowEngine );
> @@ -219,6 +223,20 @@
>          flow->x_min = 1000.0, flow->x_max = -10000.0, flow->y_min =
> 1000.0, flow->y_max = -10000.0, flow->z_min = 1000.0, flow->z_max =
> -10000.0;
>  }
>
> +#ifdef LINSOLV
> +template<class Solver>
> +void FlowEngine::setForceMetis ( Solver& flow, bool force )
> +{
> +        if (force) {
> +               flow->eSolver.cholmod().nmethods=1;
> +               flow->eSolver.cholmod().method[0].ordering=CHOLMOD_METIS;
> +       } else cholmod_defaults(&(flow->eSolver.cholmod()));
> +}
> +
> +template<class Solver>
> +bool FlowEngine::getForceMetis ( Solver& flow ) {return
> (flow->eSolver.cholmod().nmethods==1);}
> +#endif
> +
>  template<class Solver>
>  void FlowEngine::Build_Triangulation ( Solver& flow )
>  {
>
> === modified file 'pkg/dem/FlowEngine.hpp'
> --- pkg/dem/FlowEngine.hpp      2013-08-22 18:35:55 +0000
> +++ pkg/dem/FlowEngine.hpp      2013-08-30 13:07:40 +0000
> @@ -59,6 +59,10 @@
>                 int ReTrg;
>                 int ellapsedIter;
>                 TPL void initSolver (Solver& flow);
> +               #ifdef LINSOLV
> +               TPL void setForceMetis (Solver& flow, bool force);
> +               TPL bool getForceMetis (Solver& flow);
> +               #endif
>                 TPL void Triangulate (Solver& flow);
>                 TPL void AddBoundary (Solver& flow);
>                 TPL void Build_Triangulation (double P_zero, Solver& flow);
> @@ -155,6 +159,13 @@
>                 #ifdef LINSOLV
>                 void            _exportMatrix(string filename)
> {exportMatrix(filename,solver);}
>                 void            _exportTriplets(string filename)
> {exportTriplets(filename,solver);}
> +               void            _setForceMetis (bool force)
> {setForceMetis(solver,force);}
> +               bool            _getForceMetis () {return getForceMetis
> (solver);}
> +               void            cholmodStats() {
> +                                       cerr << cholmod_print_common("PFV
> Cholmod factorization",&(solver->eSolver.cholmod()))<<endl;
> +                                       cerr << "cholmod method:" <<
> solver->eSolver.cholmod().selected<<endl;
> +                                       cerr << "METIS
> called:"<<solver->eSolver.cholmod().called_nd<<endl;}
> +               bool            metisUsed() {return
> bool(solver->eSolver.cholmod().called_nd);}
>                 #endif
>                 python::list    _getConstrictions(bool all) {return
> getConstrictions(all,solver);}
>                 python::list    _getConstrictionsFull(bool all) {return
> getConstrictionsFull(all,solver);}
> @@ -164,7 +175,7 @@
>                 virtual void action();
>                 virtual void backgroundAction();
>
> -
> YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(FlowEngine,PartialEngine,"An
> engine to solve flow problem in saturated granular media. Model description
> can be found in [Chareyre2012a]_ and [Catalano2013a]_. See the example
> script FluidCouplingPFV/oedometer.py. More documentation to come.\n\n..
> note::\n\t Multi-threading seems to work fine for Cholesky decomposition,
> but it fails for the solve phase in which -j1 is the fastest, here we
> specify thread numbers independently using
> :yref:`FlowEngine::numFactorizeThreads` and
> :yref:`FlowEngine::numSolveThreads`. These multhreading settings are only
> impacting the behaviour of openblas library and are relatively independant
> of :yref:`FlowEngine::multithread`. However, the settings have to be
> globally consistent. For instance, :yref:`FlowEngine::multithread`=True
> with  multithread
> :yref:`FlowEngine::numSolveThreads`=:yref:`FlowEngine::numFactorizeThreads`=4
> means that openblas will mobilize 8 processors at some point, if the system
> doesn't have so many procs. it will hurt performance.",
> +
> YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(FlowEngine,PartialEngine,"An
> engine to solve flow problem in saturated granular media. Model description
> can be found in [Chareyre2012a]_ and [Catalano2013a]_. See the example
> script FluidCouplingPFV/oedometer.py. More documentation to come.\n\n..
> note::Multi-threading seems to work fine for Cholesky decomposition, but it
> fails for the solve phase in which -j1 is the fastest, here we specify
> thread numbers independently using :yref:`FlowEngine::numFactorizeThreads`
> and :yref:`FlowEngine::numSolveThreads`. These multhreading settings are
> only impacting the behaviour of openblas library and are relatively
> independant of :yref:`FlowEngine::multithread`. However, the settings have
> to be globally consistent. For instance,
> :yref:`multithread<FlowEngine::multithread>` =True with
>  yref:`numFactorizeThreads<FlowEngine::numFactorizeThreads>` =
> yref:`numSolveThreads<FlowEngine::numSolveThreads>` = 4 implies that
> openblas will mobilize 8 processors at some point. If the system does not
> have so many procs. it will hurt performance.",
>
> ((bool,isActivated,true,,"Activates Flow Engine"))
>                                         ((bool,first,true,,"Controls the
> initialization/update phases"))
>                                         ((double, fluidBulkModulus,
> 0.,,"Bulk modulus of fluid (inverse of compressibility) K=-dP*V/dV [Pa].
> Flow is compressible if fluidBulkModulus > 0, else incompressible."))
> @@ -188,7 +199,7 @@
>                                         ((bool,clampKValues,true,,"If
> true, clamp local permeabilities in [minKdivKmean,maxKdivKmean]*globalK.
> This clamping can avoid singular values in the permeability matrix and may
> reduce numerical errors in the solve phase. It will also hide junk values
> if they exist, or bias all values in very heterogeneous problems. So, use
> this with care."))
>
> ((Real,minKdivKmean,0.0001,,"define the min K value (see
> :yref:`FlowEngine::clampKValues`)"))
>                                         ((Real,maxKdivKmean,100,,"define
> the max K value (see :yref:`FlowEngine::clampKValues`)"))
> -
> ((double,permeabilityFactor,0.0,,"permability multiplier"))
> +
> ((double,permeabilityFactor,1.0,,"permability multiplier"))
>                                         ((double,viscosity,1.0,,"viscosity
> of the fluid"))
>                                         ((double,stiffness,
> 10000,,"equivalent contact stiffness used in the lubrication model"))
>                                         ((int, useSolver, 0,, "Solver to
> use 0=G-Seidel, 1=Taucs, 2-Pardiso, 3-CHOLMOD"))
> @@ -217,6 +228,7 @@
>                                         #ifdef EIGENSPARSE_LIB
>                                         ((int, numSolveThreads, 1,,"number
> of openblas threads in the solve phase."))
>                                         ((int, numFactorizeThreads,
> 1,,"number of openblas threads in the factorization phase"))
> +//                                     ((bool, forceMetis, 0,,"If true,
> METIS is used for matrix preconditioning, else Cholmod is free to choose
> the best method (which may be METIS to, depending on the matrix). See
> ``nmethods`` in Cholmod documentation"))
>                                         #endif
>                                         ,
>                                         /*deprec*/
> @@ -240,7 +252,7 @@
>
> .def("clearImposedPressure",&FlowEngine::_clearImposedPressure,"Clear the
> list of points with pressure imposed.")
>
> .def("clearImposedFlux",&FlowEngine::_clearImposedFlux,"Clear the list of
> points with flux imposed.")
>
> .def("getCellFlux",&FlowEngine::_getCellFlux,(python::arg("cond")),"Get
> influx in cell associated to an imposed P (indexed using 'cond').")
> -
> .def("getBoundaryFlux",&FlowEngine::_getBoundaryFlux,(python::arg("boundary")),"Get
> total flux through boundary defined by its body id.\n\n.. note::\n\t The
> flux may be not zero even for no-flow condition. This artifact comes from
> cells which are incident to two or more boundaries (along the edges of the
> sample, typically). Such flux evaluation on impermeable boundary is just
> irrelevant, it does not imply that the boundary condition is not applied
> properly.")
> +
> .def("getBoundaryFlux",&FlowEngine::_getBoundaryFlux,(python::arg("boundary")),"Get
> total flux through boundary defined by its body id.\n\n.. note:: The flux
> may be not zero even for no-flow condition. This artifact comes from cells
> which are incident to two or more boundaries (along the edges of the
> sample, typically). Such flux evaluation on impermeable boundary is just
> irrelevant, it does not imply that the boundary condition is not applied
> properly.")
>
> .def("getConstrictions",&FlowEngine::_getConstrictions,(python::arg("all")=true),"Get
> the list of constriction radii (inscribed circle) for all finite facets (if
> all==True) or all facets not incident to a virtual bounding sphere (if
> all==False).  When all facets are returned, negative radii denote facet
> incident to one or more fictious spheres.")
>
> .def("getConstrictionsFull",&FlowEngine::_getConstrictionsFull,(python::arg("all")=true),"Get
> the list of constrictions (inscribed circle) for all finite facets (if
> all==True), or all facets not incident to a fictious bounding sphere (if
> all==False). When all facets are returned, negative radii denote facet
> incident to one or more fictious spheres. The constrictions are returned in
> the format {{cell1,cell2}{rad,nx,ny,nz}}")
>
> .def("saveVtk",&FlowEngine::saveVtk,"Save pressure field in vtk format.")
> @@ -261,6 +273,9 @@
>                                         #ifdef LINSOLV
>
> .def("exportMatrix",&FlowEngine::_exportMatrix,(python::arg("filename")="matrix"),"Export
> system matrix to a file with all entries (even zeros will displayed).")
>
> .def("exportTriplets",&FlowEngine::_exportTriplets,(python::arg("filename")="triplets"),"Export
> system matrix to a file with only non-zero entries.")
> +
> .def("cholmodStats",&FlowEngine::cholmodStats,"get statistics of cholmod
> solver activity")
> +
> .def("metisUsed",&FlowEngine::metisUsed,"check wether metis lib is
> effectively used")
> +
> .add_property("forceMetis",&FlowEngine::_getForceMetis,&FlowEngine::_setForceMetis,"If
> true, METIS is used for matrix preconditioning, else Cholmod is free to
> choose the best method (which may be METIS to, depending on the matrix).
> See ``nmethods`` in Cholmod documentation")
>                                         #endif
>                                         )
>                 DECLARE_LOGGER;
>
> === modified file 'pkg/dem/HertzMindlin.cpp'
> --- pkg/dem/HertzMindlin.cpp    2012-02-16 16:05:15 +0000
> +++ pkg/dem/HertzMindlin.cpp    2013-09-07 19:40:12 +0000
> @@ -31,8 +31,8 @@
>
>  void Ip2_FrictMat_FrictMat_MindlinPhys::go(const shared_ptr<Material>&
> b1,const shared_ptr<Material>& b2, const shared_ptr<Interaction>&
> interaction){
>         if(interaction->phys) return; // no updates of an already existing
> contact necessary
> -       shared_ptr<MindlinPhys> mindlinPhys(new MindlinPhys());
> -       interaction->phys = mindlinPhys;
> +       shared_ptr<MindlinPhys> contactPhysics(new MindlinPhys());
> +       interaction->phys = contactPhysics;
>         FrictMat* mat1 = YADE_CAST<FrictMat*>(b1.get());
>         FrictMat* mat2 = YADE_CAST<FrictMat*>(b2.get());
>
> @@ -64,20 +64,20 @@
>         Real Rmean = (Da+Db)/2.; // mean radius
>         Real Kno = 4./3.*E*sqrt(R); // coefficient for normal stiffness
>         Real Kso = 2*sqrt(4*R)*G/(2-V); // coefficient for shear stiffness
> -       Real frictionAngle = std::min(fa,fb);
> +       Real frictionAngle = (!frictAngle) ? std::min(fa,fb) :
> (*frictAngle)(mat1->id,mat2->id,mat1->frictionAngle,mat2->frictionAngle);
>
>         Real Adhesion = 4.*Mathr::PI*R*gamma; // calculate adhesion force
> as predicted by DMT theory
>
>         /* pass values calculated from above to MindlinPhys */
> -       mindlinPhys->tangensOfFrictionAngle = std::tan(frictionAngle);
> -       //mindlinPhys->prevNormal = scg->normal; // used to compute
> relative rotation
> -       mindlinPhys->kno = Kno; // this is just a coeff
> -       mindlinPhys->kso = Kso; // this is just a coeff
> -       mindlinPhys->adhesionForce = Adhesion;
> +       contactPhysics->tangensOfFrictionAngle = std::tan(frictionAngle);
> +       //contactPhysics->prevNormal = scg->normal; // used to compute
> relative rotation
> +       contactPhysics->kno = Kno; // this is just a coeff
> +       contactPhysics->kso = Kso; // this is just a coeff
> +       contactPhysics->adhesionForce = Adhesion;
>
> -       mindlinPhys->kr = krot;
> -       mindlinPhys->ktw = ktwist;
> -       mindlinPhys->maxBendPl = eta*Rmean; // does this make sense? why
> do we take Rmean?
> +       contactPhysics->kr = krot;
> +       contactPhysics->ktw = ktwist;
> +       contactPhysics->maxBendPl = eta*Rmean; // does this make sense?
> why do we take Rmean?
>
>         /* compute viscous coefficients */
>         if(en && betan) throw
> std::invalid_argument("Ip2_FrictMat_FrictMat_MindlinPhys: only one of en,
> betan can be specified.");
> @@ -86,13 +86,13 @@
>         // en or es specified, just compute alpha, otherwise alpha remains
> 0
>         if(en || es){
>                 Real logE = log((*en)(mat1->id,mat2->id));
> -               mindlinPhys->alpha =
> -sqrt(5/6.)*2*logE/sqrt(pow(logE,2)+pow(Mathr::PI,2))*sqrt(2*E*sqrt(R)); //
> (see Tsuji, 1992)
> +               contactPhysics->alpha =
> -sqrt(5/6.)*2*logE/sqrt(pow(logE,2)+pow(Mathr::PI,2))*sqrt(2*E*sqrt(R)); //
> (see Tsuji, 1992)
>         }
>
>         // betan specified, use that value directly; otherwise give zero
>         else{
> -               mindlinPhys->betan=betan ? (*betan)(mat1->id,mat2->id) : 0;
> -               mindlinPhys->betas=betas ? (*betas)(mat1->id,mat2->id) :
> mindlinPhys->betan;
> +               contactPhysics->betan=betan ? (*betan)(mat1->id,mat2->id)
> : 0;
> +               contactPhysics->betas=betas ? (*betas)(mat1->id,mat2->id)
> : contactPhysics->betan;
>         }
>  }
>
>
> === modified file 'pkg/dem/HertzMindlin.hpp'
> --- pkg/dem/HertzMindlin.hpp    2013-05-29 11:54:22 +0000
> +++ pkg/dem/HertzMindlin.hpp    2013-09-07 19:40:12 +0000
> @@ -86,6 +86,7 @@
>                         ((shared_ptr<MatchMaker>,es,,,"Shear coefficient
> of restitution $e_s$."))
>                         ((shared_ptr<MatchMaker>,betan,,,"Normal viscous
> damping coefficient $\\beta_n$."))
>                         ((shared_ptr<MatchMaker>,betas,,,"Shear viscous
> damping coefficient $\\beta_s$."))
> +                       ((shared_ptr<MatchMaker>,frictAngle,,,"Instance of
> :yref:`MatchMaker` determining how to compute the friction angle of an
> interaction. If ``None``, minimum value is used."))
>         );
>         DECLARE_LOGGER;
>  };
>
> === modified file 'pkg/dem/Shop.cpp'
> --- pkg/dem/Shop.cpp    2013-09-08 11:12:42 +0000
> +++ pkg/dem/Shop.cpp    2013-09-08 11:19:06 +0000
> @@ -581,44 +581,23 @@
>                 Vector3r normalStress,shearStress;
>                 if(!I->isReal()) continue;
>
> -               //NormShearPhys + Dem3DofGeom
> -               const NormShearPhys* physNSP =
> YADE_CAST<NormShearPhys*>(I->phys.get());
> -               //Dem3DofGeom*
> geom=YADE_CAST<Dem3DofGeom*>(I->geom.get());     //For the moment only for
> Dem3DofGeom!!!
> -               // FIXME: slower, but does not crash
> -               Dem3DofGeom*
> geomDDG=dynamic_cast<Dem3DofGeom*>(I->geom.get()); //For the moment only
> for Dem3DofGeom!!!
> -
> -               //FrictPhys + ScGeom
>                 const FrictPhys* physFP =
> YADE_CAST<FrictPhys*>(I->phys.get());
> -               ScGeom* geomScG=dynamic_cast<ScGeom*>(I->geom.get());
> +               ScGeom* geomScG=YADE_CAST<ScGeom*>(I->geom.get());
>
>                 const Body::id_t id1=I->getId1(), id2=I->getId2();
>
> -               if(((physNSP) and (geomDDG)) or ((physFP) and (geomScG))){
> -                       if ((physNSP) and (geomDDG)) {
> -                               Real
> minRad=(geomDDG->refR1<=0?geomDDG->refR2:(geomDDG->refR2<=0?geomDDG->refR1:min(geomDDG->refR1,geomDDG->refR2)));
> -                               Real crossSection=Mathr::PI*pow(minRad,2);
> -
> -
> normalStress=((1./crossSection)*geomDDG->normal.dot(physNSP->normalForce))*geomDDG->normal;
> -                               for(int i=0; i<3; i++){
> -                                       int ix1=(i+1)%3,ix2=(i+2)%3;
> -
> shearStress[i]=geomDDG->normal[ix1]*physNSP->shearForce[ix1]+geomDDG->normal[ix2]*physNSP->shearForce[ix2];
> -                                       shearStress[i]/=crossSection;
> -                               }
> -                       }       else if ((physFP) and (geomScG)) {
> -                               Real
> minRad=(geomScG->radius1<=0?geomScG->radius2:(geomScG->radius2<=0?geomScG->radius1:min(geomScG->radius1,geomScG->radius2)));
> -                               Real crossSection=Mathr::PI*pow(minRad,2);
> +               if((physFP) and (geomScG)){
> +                       Real
> minRad=(geomScG->radius1<=0?geomScG->radius2:(geomScG->radius2<=0?geomScG->radius1:min(geomScG->radius1,geomScG->radius2)));
> +                       Real crossSection=Mathr::PI*pow(minRad,2);
>
> -
> normalStress=((1./crossSection)*geomScG->normal.dot(physFP->normalForce))*geomScG->normal;
> -                               for(int i=0; i<3; i++){
> -                                       int ix1=(i+1)%3,ix2=(i+2)%3;
> -
> shearStress[i]=geomScG->normal[ix1]*physFP->shearForce[ix1]+geomScG->normal[ix2]*physFP->shearForce[ix2];
> -                                       shearStress[i]/=crossSection;
> -                               }
> +
> normalStress=((1./crossSection)*geomScG->normal.dot(physFP->normalForce))*geomScG->normal;
> +                       for(int i=0; i<3; i++){
> +                               int ix1=(i+1)%3,ix2=(i+2)%3;
> +
> shearStress[i]=geomScG->normal[ix1]*physFP->shearForce[ix1]+geomScG->normal[ix2]*physFP->shearForce[ix2];
> +                               shearStress[i]/=crossSection;
>                         }
> -
>                         bodyStates[id1].normStress+=normalStress;
>                         bodyStates[id2].normStress+=normalStress;
> -
>                         bodyStates[id1].shearStress+=shearStress;
>                         bodyStates[id2].shearStress+=shearStress;
>                 }
> @@ -818,33 +797,6 @@
>         return stressTensor/volume;
>  }
>
> -/*
> -Matrix3r Shop::stressTensorOfPeriodicCell(bool smallStrains){
> -       Scene* scene=Omega::instance().getScene().get();
> -       if (!scene->isPeriodic){ throw runtime_error("Can't compute stress
> of periodic cell in aperiodic simulation."); }
> -//     if (smallStrains){volume =
> scene->getVolume()cell->refSize[0]*scene->cell->refSize[1]*scene->cell->refSize[2];}
> -//     else volume =
> scene->cell->trsf.determinant()*scene->cell->refSize[0]*scene->cell->refSize[1]*scene->cell->refSize[2];
> -       // Using the function provided by Cell (BC)
> -       Real volume = scene->cell->getVolume();
> -       Matrix3r stress = Matrix3r::Zero();
> -       FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
> -               if(!I->isReal()) continue;
> -               Dem3DofGeom* geom=YADE_CAST<Dem3DofGeom*>(I->geom.get());
> -               NormShearPhys*
> phys=YADE_CAST<NormShearPhys*>(I->phys.get());
> -               Real l;
> -               if (smallStrains){l = geom->refLength;}
> -               else l=(geom->se31.position-geom->se32.position).norm();
> -               Vector3r& n=geom->normal;
> -               Vector3r& fT=phys->shearForce;
> -               Real fN=phys->normalForce.dot(n);
> -
> -               stress += l*(fN*n*n.transpose() + .5*(fT*n.transpose() +
> n*fT.transpose()));
> -       }
> -       stress/=volume;
> -       return stress;
> -}
> -*/
> -
>  void Shop::getStressLWForEachBody(vector<Matrix3r>& bStresses){
>         const shared_ptr<Scene>& scene=Omega::instance().getScene();
>         bStresses.resize(scene->bodies->size());
>
> === modified file 'pkg/dem/Shop.hpp'
> --- pkg/dem/Shop.hpp    2013-09-08 11:12:42 +0000
> +++ pkg/dem/Shop.hpp    2013-09-08 11:19:06 +0000
> @@ -127,8 +127,6 @@
>                 static Matrix3r getStress(Real volume=0);
>                 static Matrix3r getCapillaryStress(Real volume=0);
>                 static Matrix3r stressTensorOfPeriodicCell() {
> LOG_WARN("Shop::stressTensorOfPeriodicCelli is DEPRECATED: use getStress
> instead"); return Shop::getStress(); }
> -               //! This version is restricted to periodic BCs and Dem3Dof
> -               static Matrix3r stressTensorOfPeriodicCell(bool
> smallStrains=true);
>                 //! Compute overall ("macroscopic") stress of periodic
> cell, returning 2 tensors
>                 //! (contribution of normal and shear forces)
>                 static py::tuple normalShearStressTensors(bool
> compressionPositive=false, bool splitNormalTensor=false, Real
> thresholdForce=NaN);
>
> === modified file 'pkg/dem/VTKRecorder.hpp'
> --- pkg/dem/VTKRecorder.hpp     2013-04-24 19:49:00 +0000
> +++ pkg/dem/VTKRecorder.hpp     2013-08-29 10:30:31 +0000
> @@ -23,7 +23,7 @@
>                         ((bool,multiblock,false,,"Use multi-block
> (``.vtm``) files to store data, rather than separate ``.vtu`` files."))
>                 #endif
>                 ((string,fileName,"",,"Base file name; it will be appended
> with {spheres,intrs,facets}-243100.vtu (unless *multiblock* is ``True``)
> depending on active recorders and step number (243100 in this case). It can
> contain slashes, but the directory must exist already."))
> -
> ((vector<string>,recorders,vector<string>(1,string("all")),,"List of active
> recorders (as strings). ``all`` (the default value) enables all base and
> generic recorders.\n\n.. admonition:: Base recorders\n\n\tBase recorders
> save the geometry (unstructured grids) on which other data is defined. They
> are implicitly activated by many of the other recorders. Each of them
> creates a new file (or a block, if :yref:`multiblock
> <VTKRecorder.multiblock>` is set).\n\n\t``spheres``\n\t\tSaves positions
> and radii (``radii``) of :yref:`spherical<Sphere>`
> particles.\n\t``facets``\n\t\tSave :yref:`facets<Facet>` positions
> (vertices).\n\t``boxes``\n\t\tSave :yref:`boxes<Box>` positions
> (edges).\n\t``intr``\n\t\tStore interactions as lines between nodes at
> respective particles positions. Additionally stores magnitude of normal
> (``forceN``) and shear (``absForceT``) forces on interactions (the
> :yref:`geom<Interaction.geom> must be of type :yref:`NormShearPhys`).
> \n\n.. admonition:: Generic recorders\n\n\tGeneric recorders do not depend
> on specific model being used and save commonly useful
> data.\n\n\t``id``\n\t\tSaves id's (field ``id``) of spheres; active only if
> ``spheres`` is active.\n\t``mass``\n\t\tSaves masses (field ``mass``) of
> spheres; active only if ``spheres`` is active.\n\t``clumpId``\n\t\tSaves
> id's of clumps to which each sphere belongs (field ``clumpId``); active
> only if ``spheres`` is active.\n\t``colors``\n\t\tSaves colors of
> :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``color``);
> only active if ``spheres`` or ``facets`` are
> activated.\n\t``mask``\n\t\tSaves groupMasks of :yref:`spheres<Sphere>` and
> of :yref:`facets<Facet>` (field ``mask``); only active if ``spheres`` or
> ``facets`` are activated.\n\t``materialId``\n\t\tSaves materialID of
> :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`; only active if
> ``spheres`` or ``facets`` are activated.\n\t``velocity``\n\t\tSaves linear
> and angular velocities of spherical particles as Vector3 and length(fields
> ``linVelVec``, ``l
> ...
>
> [Zpráva zkrácena]

References