← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2376: 1. Turn many fatal warnings in UniaxialStrainer to exceptions, remove some guess-logic

 

------------------------------------------------------------
revno: 2376
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Sun 2010-07-18 15:20:57 +0200
message:
  1. Turn many fatal warnings in UniaxialStrainer to exceptions, remove some guess-logic 
  2. Automatically disable live plots in batches.
  3. the concrete uniaxial test now has the scGeom switch
added:
  examples/concrete/dem3dof-scgeom.table
modified:
  core/main/yade-multi.in
  doc/sphinx/prog.rst
  examples/concrete/uniax.py
  pkg/dem/Engine/GlobalEngine/UniaxialStrainer.cpp
  pkg/dem/Engine/GlobalEngine/UniaxialStrainer.hpp
  pkg/dem/meta/ConcretePM.cpp
  py/plot.py


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'core/main/yade-multi.in'
--- core/main/yade-multi.in	2010-06-18 13:02:01 +0000
+++ core/main/yade-multi.in	2010-07-18 13:20:57 +0000
@@ -115,6 +115,7 @@
 	try:
 		server=HTTPServer(('',9080),HttpStatsServer)
 		import thread; thread.start_new_thread(server.serve_forever,())
+		print "http://localhost:9080 shows batch summary"
 	except socket.error:
 		print "WARN: Port 9080 occupied, not starting HTTP stats server"
 

=== modified file 'doc/sphinx/prog.rst'
--- doc/sphinx/prog.rst	2010-07-18 11:59:57 +0000
+++ doc/sphinx/prog.rst	2010-07-18 13:20:57 +0000
@@ -1194,6 +1194,8 @@
 
 .. [#log4cxxup] Because of (seemingly?) no upstream development of log4cxx and a few problems it has, Yade will very likely move to the hypothetical ``boost::logging`` library once it exists. The logging code will not have to be changed, however, as the log4cxx logic is hidden behind these macros.
 
+Log messages are classified by their *severity*, which is one of ``TRACE`` (tracing variables), ``DEBUG`` (generally uninsteresting messages useful for debugging), ``INFO`` (information messages -- only use sparingly), ``WARN`` (warning), ``FATAL`` (serious error, consider throwing an exception with description instead). Logging level determines which messages will be shown -- by default, ``INFO`` and higher will be shown; if you run yade with ``-v`` or ``-vv``, ``DEBUG`` and ``TRACE`` messages will be also enabled (with log4cxx).
+
 Every class using logging should create logger using these 2 macros (they expand to nothing if log4cxx is not used):
 
 ``DECLARE_LOGGER;``
@@ -1239,7 +1241,7 @@
 
 	Yade [4]: log.setLevel('',log.WARN)                        # sets logging level of all yade.* loggers (they inherit level from the parent logger, except when overridden)
 
-As of now, there is no python interface for performing logging into lo4cxx loggers themselves.
+As of now, there is no python interface for performing logging into log4cxx loggers themselves.
 
 .. _timing:
 

=== added file 'examples/concrete/dem3dof-scgeom.table'
--- examples/concrete/dem3dof-scgeom.table	1970-01-01 00:00:00 +0000
+++ examples/concrete/dem3dof-scgeom.table	2010-07-18 13:20:57 +0000
@@ -0,0 +1,17 @@
+#
+# for use with uniax.py
+#
+# shows the (unexplained) influence of geometry implementation on macroscopic
+# tension-compression test. The tests are shown to be "objective" WRT Δt by
+# using different dtSafety values -- the difference is therefore not that the
+# incremental implementation is more sensitive to Δt.
+#
+# Computations with ScGeom as (variably) faster regarding computational t/step,
+# but are less efficient in multi-threading
+# (that might be due to the implementation of Law2_ScGeom_CpmPhys_Cpm, though)
+#
+scGeom	dtSafety
+False	.8
+False .2
+True .8
+True .2

=== modified file 'examples/concrete/uniax.py'
--- examples/concrete/uniax.py	2010-07-06 11:47:43 +0000
+++ examples/concrete/uniax.py	2010-07-18 13:20:57 +0000
@@ -63,8 +63,13 @@
 
 	# isotropic confinement (should be negative)
 	isoPrestress=0,
+
+	# use the ScGeom variant
+	scGeom=True
 )
 
+from yade.params.table import *
+
 if 'description' in O.tags.keys(): O.tags['id']=O.tags['id']+O.tags['description']
 
 
@@ -90,9 +95,9 @@
 	BoundDispatcher([Bo1_Sphere_Aabb(aabbEnlargeFactor=intRadius,label='is2aabb'),]),
 	InsertionSortCollider(sweepLength=.05*sphereRadius,nBins=5,binCoeff=5),
 	InteractionDispatchers(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg')],
+		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg') if not scGeom else Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=intRadius,label='ss2sc')],
 		[Ip2_CpmMat_CpmMat_CpmPhys()],
-		[Law2_Dem3DofGeom_CpmPhys_Cpm(epsSoft=0)], # deactivated
+		[Law2_Dem3DofGeom_CpmPhys_Cpm(epsSoft=0) if not scGeom else Law2_ScGeom_CpmPhys_Cpm()],
 	),
 	NewtonIntegrator(damping=damping,label='damper'),
 	CpmStateUpdater(realPeriod=1),
@@ -103,8 +108,7 @@
 #O.miscParams=[Gl1_CpmPhys(dmgLabel=False,colorStrain=False,epsNLabel=False,epsT=False,epsTAxes=False,normal=False,contactLine=True)]
 
 # plot stresses in ¼, ½ and ¾ if desired as well; too crowded in the graph that includes confinement, though
-plot.plots={'eps':('sigma','sigma.50'),'t':('eps')} #'sigma.25','sigma.50','sigma.75')}
-plot.maxDataLen=4000
+plot.plots={'eps':('sigma',)} #,'sigma.50')},'t':('eps')} #'sigma.25','sigma.50','sigma.75')}
 
 O.saveTmp('initial');
 
@@ -120,6 +124,7 @@
 		O.wait();
 		O.loadTmp('initial')
 		print "Reversing plot data"; plot.reverseData()
+	else: plot.plot()
 	strainer.strainRate=abs(strainRateTension) if mode=='tension' else -abs(strainRateCompression)
 	try:
 		from yade import qt
@@ -127,10 +132,12 @@
 		renderer.dispScale=(1000,1000,1000) if mode=='tension' else (100,100,100)
 	except ImportError: pass
 	print "init done, will now run."
-	O.step(); O.step(); # to create initial contacts
+	O.step(); # to create initial contacts
 	# now reset the interaction radius and go ahead
-	ss2d3dg.distFactor=-1.
+	if not scGeom: ss2d3dg.distFactor=-1.
+	else: ss2sc.interactionDetectionFactor=1.
 	is2aabb.aabbEnlargeFactor=-1.
+
 	O.run()
 
 def stopIfDamaged():

=== modified file 'pkg/dem/Engine/GlobalEngine/UniaxialStrainer.cpp'
--- pkg/dem/Engine/GlobalEngine/UniaxialStrainer.cpp	2010-06-08 21:22:07 +0000
+++ pkg/dem/Engine/GlobalEngine/UniaxialStrainer.cpp	2010-07-18 13:20:57 +0000
@@ -1,6 +1,7 @@
 // 2008 © Václav Šmilauer <eudoxos@xxxxxxxx> 
 #include"UniaxialStrainer.hpp"
 #include<boost/foreach.hpp>
+#include<stdexcept>
 
 #include<yade/core/Scene.hpp>
 #include<yade/core/InteractionContainer.hpp>
@@ -36,14 +37,14 @@
 	originalLength=axisCoord(posIds[0])-axisCoord(negIds[0]);
 	LOG_DEBUG("Reference particles: positive #"<<posIds[0]<<" at "<<axisCoord(posIds[0])<<"; negative #"<<negIds[0]<<" at "<<axisCoord(negIds[0]));
 	LOG_INFO("Setting initial length to "<<originalLength<<" (between #"<<negIds[0]<<" and #"<<posIds[0]<<")");
-	if(originalLength<=0) LOG_FATAL("Initial length is negative or zero (swapped reference particles?)! "<<originalLength);
+	if(originalLength<=0) throw runtime_error(("UniaxialStrainer: Initial length is negative or zero (swapped reference particles?)! "+lexical_cast<string>(originalLength)).c_str());
 	/* this happens is nan propagates from e.g. brefcom consitutive law in case 2 bodies have _exactly_ the same position
 	 * (the the normal strain is 0./0.=nan). That is an user's error, however and should not happen. */
-	if(isnan(originalLength)) LOG_FATAL("Initial length is NaN!");
+	if(isnan(originalLength)) throw logic_error("UniaxialStrainer: Initial length is NaN!");
 	assert(originalLength>0 && !isnan(originalLength));
 
 	assert(!isnan(strainRate) || !isnan(absSpeed));
-	if(!isnan(std::numeric_limits<Real>::quiet_NaN())){ LOG_FATAL("NaN's are not properly supported (compiled, with -ffast-math?), which is required."); throw; }
+	if(!isnan(std::numeric_limits<Real>::quiet_NaN())){ throw runtime_error("UniaxialStrainer: NaN's are not properly supported (compiled with -ffast-math?), which is required."); }
 
 	if(isnan(strainRate)){ strainRate=absSpeed/originalLength; LOG_INFO("Computed new strainRate "<<strainRate); }
 	else {absSpeed=strainRate*originalLength;}
@@ -66,7 +67,7 @@
 			case -1: v0=-absSpeed; v1=0; break;
 			case  0: v0=-absSpeed/2; v1=absSpeed/2; break;
 			case  1: v0=0; v1=absSpeed; break;
-			default: LOG_FATAL("Unknown asymmetry value "<<asymmetry<<" (should be -1,0,1)"); throw;
+			default: throw std::invalid_argument(("UniaxialStrainer: unknown asymmetry value "+lexical_cast<string>(asymmetry)+" (should be -1,0,1)").c_str());
 		}
 		assert(p1>p0);
 		// set speeds for particles on the boundary
@@ -78,31 +79,7 @@
 			b->state->vel[axis]=pNormalized*(v1-v0)+v0;
 		}
 	}
-	stressUpdateInterval=min(1000,max(1,(int)(1e-5/(abs(strainRate)*scene->dt))));
-	LOG_INFO("Stress will be updated every "<<stressUpdateInterval<<" steps.");
-
-	/* if we have default (<0) crossSectionArea, try to get it from root's Aabb;
-	 * this will not work if there are foreign bodies in the simulation,
-	 * in which case you must give the value yourself as engine attribute.
-	 *
-	 * A TODO option is to get crossSectionArea as average area of bounding boxes' of ABBBs
-	 * of posIds and negIds perpendicular to axis. That might be better, except for cases where
-	 * reference particles on either end do not coincide with the specimen cross-section.
-	 *
-	 * */
-	if(crossSectionArea<=0){
-		shared_ptr<Aabb> rbAABB;
-		if (Omega::instance().getScene()->bound && (rbAABB=dynamic_pointer_cast<Aabb>(Omega::instance().getScene()->bound))){
-			int axis2=(axis+1)%3, axis3=(axis+2)%3; // perpendicular axes indices
-			Vector3r size=rbAABB->max-rbAABB->min;
-			crossSectionArea=size[axis2]*size[axis3];
-			LOG_INFO("Setting crossSectionArea="<<crossSectionArea<<", using axes #"<<axis2<<" and #"<<axis3<<".");
-		} else {
-			crossSectionArea=1.;
-			LOG_WARN("No Axis Aligned Bounding BoxModel for scene, using garbage value ("<<crossSectionArea<<") for crossSectionArea!");
-		}
-	}
-	assert(crossSectionArea>0);
+	if(isnan(crossSectionArea)){ throw std::invalid_argument("UniaxialStrain.crossSectionArea must be specified."); }
 }
 
 void UniaxialStrainer::action(){

=== modified file 'pkg/dem/Engine/GlobalEngine/UniaxialStrainer.hpp'
--- pkg/dem/Engine/GlobalEngine/UniaxialStrainer.hpp	2010-04-13 21:09:57 +0000
+++ pkg/dem/Engine/GlobalEngine/UniaxialStrainer.hpp	2010-07-18 13:20:57 +0000
@@ -26,8 +26,6 @@
 		virtual bool isActivated(){ return active; }
 		Real sumPosForces,sumNegForces;
 		Real initAccelTime_s /* value always in s, computed from initAccelTime */;
-		//! how often to update forces (initialized automatically)
-		int stressUpdateInterval;
 		/** coordinates of pos/neg bodies in the direction of axis */
 		vector<Real> posCoords,negCoords;
 
@@ -47,12 +45,13 @@
 			((Real,originalLength,NaN,"Distance of reference bodies in the direction of axis before straining started (computed automatically) [m]"))
 			((Real,limitStrain,((void)"disabled",0),"Invert the sense of straining (sharply, without transition) one this value of strain is reached. Not effective if 0."))
 			((bool,notYetReversed,true,"Flag whether the sense of straining has already been reversed (only used internally).")) 
-			((Real,crossSectionArea,NaN,"crossSection perpendicular to he strained axis, computed from Aabb of Scene, or given explicitly [m²]"))
+			((Real,crossSectionArea,NaN,"crossSection perpendicular to he strained axis; must be given explicitly [m²]"))
 			((Real,strain,0,"Current strain value, elongation/originalLength |yupdate| [-]")) 
 			((Real,avgStress,0,"Current average stress  |yupdate| [Pa]"))
 			((bool,blockDisplacements,false,"Whether displacement of boundary bodies perpendicular to the strained axis are blocked of are free"))
 			((bool,blockRotations,false,"Whether rotations of boundary bodies are blocked."))
-			((bool,setSpeeds,false,"should we set speeds at the beginning directly, instead of increasing strain rate progressively?")),
+			((bool,setSpeeds,false,"should we set speeds at the beginning directly, instead of increasing strain rate progressively?"))
+			((int,stressUpdateInterval,10,"How often to recompute stress on supports.")),
 			/*ctor*/ needsInit=true;
 		);
 	DECLARE_LOGGER;

=== modified file 'pkg/dem/meta/ConcretePM.cpp'
--- pkg/dem/meta/ConcretePM.cpp	2010-07-18 11:59:57 +0000
+++ pkg/dem/meta/ConcretePM.cpp	2010-07-18 13:20:57 +0000
@@ -136,7 +136,7 @@
 	#include"../../../../brefcom-mm.hh"
 #endif
 
-#undef CPM_MATERIAL_MODEL
+// #undef CPM_MATERIAL_MODEL (force trunk version of the model)
 
 
 void Law2_Dem3DofGeom_CpmPhys_Cpm::go(shared_ptr<InteractionGeometry>& _geom, shared_ptr<InteractionPhysics>& _phys, Interaction* I){

=== modified file 'py/plot.py'
--- py/plot.py	2010-07-18 11:59:57 +0000
+++ py/plot.py	2010-07-18 13:20:57 +0000
@@ -25,8 +25,10 @@
 # see http://www.mail-archive.com/yade-dev@xxxxxxxxxxxxxxxxxxx/msg04320.html 
 # and https://lists.launchpad.net/yade-users/msg03289.html
 #
+hasDisplay=True # FIXME: this should be moved to yade.config/yade.runtime and initialized at startup properly
 if os.environ.has_key('PARAM_TABLE'):
 	matplotlib.use('Agg')
+	hasDisplay=False
 
 #matplotlib.use('TkAgg')
 #matplotlib.use('GTKAgg')
@@ -41,7 +43,7 @@
 labels={}
 "Dictionary converting names in data to human-readable names (TeX names, for instance); if a variable is not specified, it is left untranslated."
 
-live=True
+live=True if hasDisplay else False
 "Enable/disable live plot updating. Disabled by default for now, since it has a few rough edges."
 liveInterval=1
 "Interval for the live plot updating, in seconds."
@@ -132,15 +134,17 @@
 		pylab.figure()
 		plots_p=[addPointTypeSpecifier(o) for o in tuplifyYAxis(plots[p])]
 		plots_p_y1,plots_p_y2=[],[]; y1=True
-		missing={} # missing data columns
-		if p not in data.keys(): missing[p]=nan
+		missing=set() # missing data columns
+		if p not in data.keys(): missing.add(p)
 		for d in plots_p:
 			if d[0]=='|||' or d[0]==None:
 				y1=False; continue
 			if y1: plots_p_y1.append(d)
 			else: plots_p_y2.append(d)
-			if d[0] not in data.keys(): missing[d[0]]=nan
-		addData(missing)
+			if d[0] not in data.keys(): missing.add(d[0])
+		if len(data.keys())==0 or len(data[data.keys()[0]])==0: # no data at all yet, do not add garbage NaNs
+			for m in missing: data[m]=[]
+		else: addData(dict((m,nan) for m in missing))
 		# create y1 lines
 		for d in plots_p_y1:
 			line,=pylab.plot(data[p],data[d[0]],d[1])
@@ -206,6 +210,7 @@
 	createPlots()
 	global currLineRefs
 	if not noShow:
+		if not hasDisplay: return # would error out with some backends, such as Agg used in batches
 		if live:
 			import thread
 			thread.start_new_thread(liveUpdate,(time.time(),))