Author: eudoxos
Date: 2009-04-23 15:20:50 +0200 (Thu, 23 Apr 2009)
New Revision: 1758

Modified:
   trunk/extra/usct/UniaxialStrainControlledTest.cpp
   trunk/extra/usct/UniaxialStrainControlledTest.hpp
   trunk/gui/py/utils.py
   trunk/gui/py/yade-multi
Log:
1. Remove cruft from UniaxialStrainer, add the ability to set initial 
velocities to suppress inertia at the simulation beginning
2. Jobs in yade-multi can be automatically named after variables suffixed with !
3. yade-multi now shows and updates automatically some statistic on 
localhost:9080 using http



Modified: trunk/extra/usct/UniaxialStrainControlledTest.cpp
===================================================================
--- trunk/extra/usct/UniaxialStrainControlledTest.cpp   2009-04-22 06:57:45 UTC 
(rev 1757)
+++ trunk/extra/usct/UniaxialStrainControlledTest.cpp   2009-04-23 13:20:50 UTC 
(rev 1758)
@@ -20,7 +20,7 @@
        assert(posIds.size()>0);
        assert(negIds.size()>0);
        posCoords.clear(); negCoords.clear();
-       FOREACH(body_id_t id,posIds){ const shared_ptr<Body>& b=Body::byId(id); 
posCoords.push_back(b->physicalParameters->se3.position[axis]);
+       FOREACH(body_id_t id,posIds){ const shared_ptr<Body>& 
b=Body::byId(id,rootBody); 
posCoords.push_back(b->physicalParameters->se3.position[axis]);
                if(blockDisplacements && blockRotations) b->isDynamic=false;
                else{
                        shared_ptr<PhysicalParameters> 
&pp=b->physicalParameters;
@@ -28,7 +28,7 @@
                        if(blockRotations) 
pp->blockedDOFs|=PhysicalParameters::DOF_RXRYRZ;
                }
        }
-       FOREACH(body_id_t id,negIds){ const shared_ptr<Body>& b=Body::byId(id); 
negCoords.push_back(b->physicalParameters->se3.position[axis]);
+       FOREACH(body_id_t id,negIds){ const shared_ptr<Body>& 
b=Body::byId(id,rootBody); 
negCoords.push_back(b->physicalParameters->se3.position[axis]);
                if(blockDisplacements && blockRotations) b->isDynamic=false;
                else{
                        shared_ptr<PhysicalParameters> 
&pp=b->physicalParameters;
@@ -49,11 +49,43 @@
        assert(originalLength>0 && !isnan(originalLength));
 
        assert(!isnan(strainRate) || !isnan(absSpeed));
-       if(strainRate==0){ strainRate=absSpeed/originalLength; 
LOG_INFO("Computed new strainRate "<<strainRate); }
+       if(!isnan(std::numeric_limits<Real>::quiet_NaN())){ LOG_FATAL("NaN's 
are not properly supported (compiled, with -ffast-math?), which is required."); 
throw; }
 
-       initAccelTime_s=initAccelTime>=0 ? initAccelTime : 
Omega::instance().getTimeStep()*(-initAccelTime);
-       LOG_INFO("Strain speed will be "<<absSpeed<<", strain rate 
"<<strainRate<<", will be reached after "<<initAccelTime_s<<"s 
("<<initAccelTime_s/Omega::instance().getTimeStep()<<" steps).");
+       if(isnan(strainRate)){ strainRate=absSpeed/originalLength; 
LOG_INFO("Computed new strainRate "<<strainRate); }
+       else {absSpeed=strainRate*originalLength;}
 
+       if(!setSpeeds){
+               initAccelTime_s=initAccelTime>=0 ? initAccelTime : 
Omega::instance().getTimeStep()*(-initAccelTime);
+               LOG_INFO("Strain speed will be "<<absSpeed<<", strain rate 
"<<strainRate<<", will be reached after "<<initAccelTime_s<<"s 
("<<initAccelTime_s/Omega::instance().getTimeStep()<<" steps).");
+       } else {
+               /* set speed such that it is linear on the strained axis; 
transversal speed is not set, which can perhaps create some problems.
+                       Note: all bodies in the simulation will have their 
speed set, since there is no way to tell which ones are part of the specimen
+                       and which are not.
+
+                       Speeds will be linearly interpolated beween axis 
positions p0,p1 and velocities v0,v1.
+               */
+               initAccelTime_s=0;
+               LOG_INFO("Strain speed will be "<<absSpeed<<", strain rate 
"<<strainRate<<"; velocities will be set directly at the beginning.");
+               Real p0=axisCoord(negIds[0]), p1=axisCoord(posIds[0]); // limit 
positions
+               Real v0,v1; // speeds at p0, p1
+               switch(asymmetry){
+                       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;
+               }
+               assert(p1>p0);
+               FOREACH(const shared_ptr<Body>& b, *rootBody->bodies){
+                       // skip bodies on the boundary, since those will have 
their positions updated directly
+                       
if(std::find(posIds.begin(),posIds.end(),b->id)!=posIds.end() || 
std::find(negIds.begin(),negIds.end(),b->id)!=negIds.end()) { continue; }
+                       Real p=axisCoord(b->id);
+                       Real pNormalized=(p-p0)/(p1-p0);
+                       
YADE_CAST<ParticleParameters*>(b->physicalParameters.get())->velocity[axis]=pNormalized*(v1-v0)+v0;
+               }
+       }
+       
stressUpdateInterval=max(1,(int)(2e-5/(abs(strainRate)*Omega::instance().getTimeStep())));
+       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.
@@ -75,13 +107,10 @@
                }
        }
        assert(crossSectionArea>0);
-       prepareRecStream();
-#if 0
-       setupTransStrainSensors();
-#endif
 }
 
-void UniaxialStrainer::applyCondition(MetaBody* rootBody){
+void UniaxialStrainer::applyCondition(MetaBody* _rootBody){
+       rootBody=_rootBody;
        if(needsInit) init();
        // postconditions for initParams
        assert(posIds.size()==posCoords.size() && 
negIds.size()==negCoords.size() && originalLength>0 && crossSectionArea>0);
@@ -117,19 +146,18 @@
 
        Real axialLength=axisCoord(posIds[0])-axisCoord(negIds[0]);
        strain=axialLength/originalLength-1;
-       if(Omega::instance().getCurrentIteration()%400==0) 
TRVAR5(dAX,axialLength,originalLength,currentStrainRate,strain);
 
        // reverse if we're over the limit strain
        if(notYetReversed && limitStrain!=0 && ((currentStrainRate>0 && 
strain>limitStrain) || (currentStrainRate<0 && strain<limitStrain))) { 
currentStrainRate*=-1; notYetReversed=false; LOG_INFO("Reversed strain rate to 
"<<currentStrainRate); }
 
-       if(Omega::instance().getCurrentIteration()%10==0) {
-               computeAxialForce(rootBody);
+       // update forces and stresses
+       if(Omega::instance().getCurrentIteration()%stressUpdateInterval==0) {
+               computeAxialForce();
                avgStress=(sumPosForces+sumNegForces)/(2*crossSectionArea); // 
average nominal stress
-               if(!recordFile.empty() && recStream.good()) 
recStream<<Omega::instance().getCurrentIteration()<<" "<<strain<<" 
"<<avgStress<<endl; // <<" "<<avgTransStrain<<endl;
        }
 }
 
-void UniaxialStrainer::computeAxialForce(MetaBody* rootBody){
+void UniaxialStrainer::computeAxialForce(){
        sumPosForces=sumNegForces=0;
        rootBody->bex.sync();
        FOREACH(body_id_t id, negIds) 
sumNegForces+=rootBody->bex.getForce(id)[axis];
@@ -220,7 +248,6 @@
 #include<yade/pkg-common/LeapFrogPositionIntegrator.hpp>
 #include<yade/pkg-common/LeapFrogOrientationIntegrator.hpp>
 #include<yade/pkg-common/PersistentSAPCollider.hpp>
-#include<yade/pkg-dem/PositionOrientationRecorder.hpp>
 #include<yade/pkg-dem/GlobalStiffnessTimeStepper.hpp>
 #include<yade/pkg-common/PhysicalActionDamper.hpp>
 #include<yade/pkg-common/CundallNonViscousDamping.hpp>

Modified: trunk/extra/usct/UniaxialStrainControlledTest.hpp
===================================================================
--- trunk/extra/usct/UniaxialStrainControlledTest.hpp   2009-04-22 06:57:45 UTC 
(rev 1757)
+++ trunk/extra/usct/UniaxialStrainControlledTest.hpp   2009-04-23 13:20:50 UTC 
(rev 1758)
@@ -46,13 +46,12 @@
  */
 class UniaxialStrainer: public DeusExMachina {
        private:
+               MetaBody* rootBody;
                bool idInVector(body_id_t id, const vector<body_id_t>& 
V){for(size_t i=0; i<V.size(); i++){ if(V[i]==id) return true; } return false; 
}  // unused now
-               void computeAxialForce(MetaBody* rootBody);
+               void computeAxialForce();
 
-               ofstream recStream;
-               string recordFile;
                bool needsInit;
-               Real& axisCoord(body_id_t id){ return 
Body::byId(id)->physicalParameters->se3.position[axis]; };
+               Real& axisCoord(body_id_t id){ return 
Body::byId(id,rootBody)->physicalParameters->se3.position[axis]; };
                void init();
        public:
                virtual bool isActivated(){return active;}
@@ -71,6 +70,7 @@
                Real sumPosForces,sumNegForces;
                //! crossSection perpendicular to he strained axis, computed 
from AABB of MetaBody
                Real crossSectionArea;          //! Apply strain along x (0), y 
(1) or z(2) axis
+               //! The axis which is strained (0,1,2 for x,y,z)
                int axis;
                //! If 0, straining is symmetric for negIds and posIds; for 1 
(or -1), only posIds are strained and negIds don't move (or vice versa)
                int asymmetry;
@@ -84,6 +84,10 @@
                long idleIterations;
                //! Time for strain reaching the requested value (linear 
interpolation). If negative, the time is dt*(-initAccelTime), where dt is  the 
timestep at the first iteration.
                Real initAccelTime, initAccelTime_s /* value always in s, 
computed from initAccelTime */;
+               //! should we set speeds at the beginning directly, instead of 
increasing strain rate progressively?
+               bool setSpeeds;
+               //! how often to update forces (initialized automatically)
+               int stressUpdateInterval;
 
                /** bodies on which straining will be applied (on the positive 
and negative side of axis) */
                vector<body_id_t> posIds, negIds;
@@ -110,7 +114,7 @@
                Real strain, avgStress;
 
                virtual void applyCondition(MetaBody* rootBody);
-               UniaxialStrainer(){axis=2; asymmetry=0; currentStrainRate=0; 
originalLength=-1; limitStrain=0; notYetReversed=true; crossSectionArea=-1; 
needsInit=true; /* sensorsPusher=shared_ptr<UniaxialStrainSensorPusher>(); */ 
recordFile=""; strain=avgStress=/*avgTransStrain=*/0; blockRotations=false; 
blockDisplacements=false;  strainRate=0; 
absSpeed=stopStrain=numeric_limits<Real>::quiet_NaN(); active=true; 
idleIterations=0; initAccelTime=-200;};
+               UniaxialStrainer(){axis=2; asymmetry=0; currentStrainRate=0; 
originalLength=-1; limitStrain=0; notYetReversed=true; crossSectionArea=-1; 
needsInit=true; strain=avgStress=0; blockRotations=false; 
blockDisplacements=false; setSpeeds=false; 
strainRate=absSpeed=stopStrain=numeric_limits<Real>::quiet_NaN(); active=true; 
idleIterations=0; initAccelTime=-200;};
                virtual ~UniaxialStrainer(){};
                REGISTER_ATTRIBUTES(DeusExMachina,
                                (strainRate) 
@@ -128,14 +132,12 @@
                                (limitStrain) 
                                (notYetReversed) 
                                (crossSectionArea) 
-                               (recordFile) 
                                (strain) 
                                (avgStress) 
                                (blockDisplacements) 
                                (blockRotations) 
+                               (setSpeeds)
                );
-               void prepareRecStream(void){ if(!recordFile.empty()) 
recStream.open(recordFile.c_str()); }
-               void postProcessAttributes(bool deserializing){ 
if(deserializing) prepareRecStream(); }         
        REGISTER_CLASS_AND_BASE(UniaxialStrainer,DeusExMachina);
        DECLARE_LOGGER;
 };

Modified: trunk/gui/py/utils.py
===================================================================
--- trunk/gui/py/utils.py       2009-04-22 06:57:45 UTC (rev 1757)
+++ trunk/gui/py/utils.py       2009-04-23 13:20:50 UTC (rev 1758)
@@ -347,21 +347,30 @@
                o.tags['line']='l!'
        else:
                if not tableFileLine: tableFileLine=os.environ['PARAM_TABLE']
-               tableFile,tableLine=tableFileLine.split(':')
+               env=tableFileLine.split(':')
+               tableDesc=None
+               tableFile,tableLine=env[0],env[1]
+               if len(env)>2: tableDesc=env[3]
                o.tags['line']='l'+tableLine
                ll=[l.split('#')[0] for l in ['']+open(tableFile).readlines()]; 
names=ll[1].split(); values=ll[int(tableLine)].split()
                assert(len(names)==len(values))
+               if 'description' in names: 
O.tags['description']=values[names.index('description')]
+               else:
+                       bangCols=[i for i,h in enumerate(names) if h[-1]=='!']
+                       if len(bangCols)==0: bangCols=range(len(headings))
+                       for i in range(len(names)):
+                               if names[i][-1]=='!': names[i]=names[i][:-1] # 
strip trailing !
+                       O.tags['description']=','.join( 
names[col]+'='+('%g'%values[col] if isinstance(values[col],float) else 
str(values[col])) for col in bangCols)
                for i in range(len(names)):
-                       if names[i]=='description': 
o.tags['description']=values[i]
-                       else:
-                               if names[i] not in kw.keys():
-                                       if (not unknownOk) and 
names[i][0]!='!': raise NameError("Parameter `%s' has no default value 
assigned"%names[i])
-                               else: kw.pop(names[i])
-                               if names[i][0]!='!':
-                                       
exec('__builtin__.%s=%s'%(names[i],values[i])); 
tagsParams+=['%s=%s'%(names[i],values[i])]; dictParams[names[i]]=values[i]
+                       if names[i]=='description': continue
+                       if names[i] not in kw.keys():
+                               if (not unknownOk) and names[i][0]!='!': raise 
NameError("Parameter `%s' has no default value assigned"%names[i])
+                       else: kw.pop(names[i])
+                       if names[i][0]!='!':
+                               exec('%s=%s'%(names[i],values[i])) in 
__builtins__; tagsParams+=['%s=%s'%(names[i],values[i])]; 
dictParams[names[i]]=values[i]
        defaults=[]
        for k in kw.keys():
-               exec("__builtin__.%s=%s"%(k,repr(kw[k])))
+               exec("%s=%s"%(k,repr(kw[k]))) in __builtins__
                defaults+=["%s=%s"%(k,kw[k])]; dictDefaults[k]=kw[k]
        o.tags['defaultParams']=",".join(defaults)
        o.tags['params']=",".join(tagsParams)

Modified: trunk/gui/py/yade-multi
===================================================================
--- trunk/gui/py/yade-multi     2009-04-22 06:57:45 UTC (rev 1757)
+++ trunk/gui/py/yade-multi     2009-04-23 13:20:50 UTC (rev 1758)
@@ -23,9 +23,48 @@
 finished: %s
 """%(self.id,self.exitStatus,'OK' if self.exitStatus==0 else 
'FAILED',self.duration,self.command,time.asctime(time.localtime(self.started)),time.asctime(time.localtime(self.finished))));
                log.close()
+       def t2hhmmss(self,dt): return 
'%02d:%02d:%02d'%(dt//3600,(dt%3600)//60,(dt%60))
+       def htmlStats(self):
+               ret='<tr>'
+               ret+='<td>%s</td>'%self.id
+               if self.status=='PENDING': ret+='<td 
bgcolor="grey">(pending)</td>'
+               elif self.status=='RUNNING': ret+='<td 
bgcolor="yellow">%s</td>'%self.t2hhmmss(time.time()-self.started)
+               elif self.status=='DONE': ret+='<td 
bgcolor="%s">%s</td>'%('green' if self.exitStatus==0 else 'red',self.duration)
+               ret+='<td>%s</td>'%self.command
+               ret+='<td>%d</td>'%self.nSlots
+               ret+='</tr>'
+               return ret
 
+def globalHtmlStats():
+       ret='<h3>Jobs</h3>'
+       nFailed=len([j for j in jobs if j.status=='DONE' and j.exitStatus!=0])
+       ret+='<p><b>%d</b> total, <b>%d</b> <span 
style="background-color:yellow">running</span>, <b>%d</b> <span 
style="background-color:green">done</span>%s</p>'%(len(jobs),len([j for j in 
jobs if j.status=='RUNNING']), len([j for j in jobs if j.status=='DONE']),' 
(<b>%d <span style="background-color:red"><b>failed</b></span>)'%nFailed if 
nFailed>0 else '')
+       return ret
 
+from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
+import socket
+class HttpStatsServer(BaseHTTPRequestHandler):
+       def do_GET(self):
+               self.send_response(200)
+               self.send_header('Content-type','text/html')
+               self.send_header('refresh','5')
+               self.end_headers()
+               self.wfile.write('<HTML><TITLE>Yade-multi 
overview</TITLE><BODY>')
+               self.wfile.write(globalHtmlStats())
+               self.wfile.write('<TABLE 
border=1><tr><th>id</th><th>status</th><th>command</th><th>slots</th></tr>')
+               for j in jobs:
+                       self.wfile.write(j.htmlStats())
+               self.wfile.write('</TABLE></BODY></HTML>')
+               return
+       def log_request(self,req): pass
+def runHttpStatsServer():
+       try:
+               server=HTTPServer(('',9080),HttpStatsServer)
+               import thread; thread.start_new_thread(server.serve_forever,())
+       except socket.error:
+               print "WARN: Port 9080 occupied, not starting HTTP stats server"
 
+
 def runJob(job):
        job.status='RUNNING'
        job.started=time.time();
@@ -33,7 +72,7 @@
        job.exitStatus=os.system(job.command)
        job.finished=time.time()
        dt=job.finished-job.started;
-       job.duration='%02d:%02d:%02d'%(dt//3600,(dt%3600)//60,(dt%60))
+       job.duration=job.t2hhmmss(dt)
        strStatus='done   ' if job.exitStatus==0 else 'FAILED '
        job.status='DONE'
        print "#%d (%s%s) %s (exit status %d), duration %s, log 
%s"%(job.num,job.id,'' if job.nSlots==1 else 
'/%d'%job.nSlots,strStatus,job.exitStatus,job.duration,job.log)
@@ -117,8 +156,20 @@
        print "Will use lines ",', '.join([str(i)+' (%s)'%idStrings[i] for i in 
useLines])+'.'
        #print idStrings
 except ValueError:
-       idColumn=None
-       idStrings=None
+       # try to get idStrings from columns with trailing !
+       bangCols=[i for i,h in enumerate(headings) if h[-1]=='!']
+       if len(bangCols)==0:
+               print 'WARN: no headings with trailing !, will use all of them 
for description'
+               bangCols=range(len(headings))
+       for i in range(len(headings)):
+               if headings[i][-1]=='!': headings[i]=headings[i][:-1]
+       idStrings={}
+       for i in useLines:
+               newIdBase=','.join( headings[col]+'='+('%g'%values[i][col] if 
isinstance(values[i][col],float) else str(values[i][col])) for col in bangCols)
+               newId=newIdBase; j=1
+               while newId in idStrings.values():
+                       newId=newIdBase+'_%d_'%j; j+=1
+               idStrings[i]=newId
        print "Will use lines ",', '.join([str(i) for i in useLines])+'.'
 
 
@@ -140,6 +191,8 @@
 for job in jobs:
        print '   #%d (%s%s):'%(job.num,job.id,'' if job.nSlots==1 else 
'/%d'%job.nSlots),job.command
 
+runHttpStatsServer()
+
 # OK, go now
 if not dryRun: runJobs(jobs,maxJobs)
 


_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help   : https://help.launchpad.net/ListHelp
_______________________________________________
yade-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/yade-dev

Reply via email to