← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2294: 1. Remove old io code in Omega

 

------------------------------------------------------------
revno: 2294
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Thu 2010-06-17 23:13:59 +0200
message:
  1. Remove old io code in Omega
  2. Update yade.eudoxos 
  3. Fix bug in pack.randomDensePack loading memoized scaled periodic packing from (backported to 0.50 as well)
modified:
  core/Omega.cpp
  py/_eudoxos.cpp
  py/eudoxos.py
  py/pack/pack.py
  scripts/test/wm3-wrap.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/Omega.cpp'
--- core/Omega.cpp	2010-05-30 13:41:00 +0000
+++ core/Omega.cpp	2010-06-17 21:13:59 +0000
@@ -258,52 +258,31 @@
 	LOG_DEBUG("Loading simulation from stream.");
 	resetScene();
 	RenderMutexLock lock;
-	#ifdef YADE_SERIALIZE_USING_BOOST
-		yade::ObjectIO::load<typeof(scene),boost::archive::xml_iarchive>(stream,"scene",scene);
-	#else
-		IOFormatManager::loadFromStream("XMLFormatManager",stream,"scene",scene);
-	#endif
+	yade::ObjectIO::load<typeof(scene),boost::archive::xml_iarchive>(stream,"scene",scene);
 }
 
 void Omega::saveSimulationToStream(std::ostream& stream){
 	LOG_DEBUG("Saving simulation to stream.");
-	#ifdef YADE_SERIALIZE_USING_BOOST
-		yade::ObjectIO::save<typeof(scene),boost::archive::xml_oarchive>(stream,"scene",scene);
-	#else
-		IOFormatManager::saveToStream("XMLFormatManager",stream,"scene",scene);
-	#endif
+	yade::ObjectIO::save<typeof(scene),boost::archive::xml_oarchive>(stream,"scene",scene);
 }
 
 void Omega::loadSimulation(){
-
-	if(Omega::instance().getSimulationFileName().size()==0) throw runtime_error("Empty simulation filename to load.");
-	if(!filesystem::exists(simulationFileName) && !algorithm::starts_with(simulationFileName,":memory")) throw runtime_error("Simulation file to load doesn't exist: "+simulationFileName);
+	if(simulationFileName.size()==0) throw runtime_error("Empty simulation filename to load.");
+	bool isMem=algorithm::starts_with(simulationFileName,":memory:");
+	if(!isMem && !filesystem::exists(simulationFileName)) throw runtime_error("Simulation file to load doesn't exist: "+simulationFileName);
+	if(isMem && memSavedSimulations.count(simulationFileName)==0) throw runtime_error("Cannot load nonexistent memory-saved simulation "+simulationFileName);
 	
 	LOG_INFO("Loading file " + simulationFileName);
 	{
-		if(algorithm::ends_with(simulationFileName,".xml") || algorithm::ends_with(simulationFileName,".xml.gz") || algorithm::ends_with(simulationFileName,".xml.bz2")){
-			joinSimulationLoop(); // stop current simulation if running
-			resetScene();
-			RenderMutexLock lock;
-			#ifdef YADE_SERIALIZE_USING_BOOST
-				yade::ObjectIO::load(simulationFileName,"scene",scene);
-			#else
-				IOFormatManager::loadFromFile("XMLFormatManager",simulationFileName,"scene",scene);
-			#endif
-		}
-		else if(algorithm::starts_with(simulationFileName,":memory:")){
-			if(memSavedSimulations.count(simulationFileName)==0) throw runtime_error("Cannot load nonexistent memory-saved simulation "+simulationFileName);
+		joinSimulationLoop(); // stop current simulation if running
+		resetScene();
+		RenderMutexLock lock;
+		if(isMem){
 			istringstream iss(memSavedSimulations[simulationFileName]);
-			joinSimulationLoop();
-			resetScene();
-			RenderMutexLock lock;
-			#ifdef YADE_SERIALIZE_USING_BOOST
-				yade::ObjectIO::load<typeof(scene),boost::archive::binary_iarchive>(iss,"scene",scene);
-			#else
-				IOFormatManager::loadFromStream("XMLFormatManager",iss,"scene",scene);
-			#endif
+			yade::ObjectIO::load<typeof(scene),boost::archive::binary_iarchive>(iss,"scene",scene);
+		} else {
+			yade::ObjectIO::load(simulationFileName,"scene",scene);
 		}
-		else throw runtime_error("Extension of file to load not recognized "+simulationFileName);
 	}
 
 	if( scene->getClassName() != "Scene") throw runtime_error("Wrong file format (scene is not a Scene!?) in "+simulationFileName);
@@ -320,26 +299,15 @@
 	if(name.size()==0) throw runtime_error("Name of file to save has zero length.");
 	LOG_INFO("Saving file " << name);
 
-	if(algorithm::ends_with(name,".xml") || algorithm::ends_with(name,".xml.bz2")){
-		#ifdef YADE_SERIALIZE_USING_BOOST
-			yade::ObjectIO::save(name,"scene",scene);
-		#else
-			FormatChecker::format=FormatChecker::XML;
-			IOFormatManager::saveToFile("XMLFormatManager",name,"scene",scene);
-		#endif
-	}
-	else if(algorithm::starts_with(name,":memory:")){
+	if(algorithm::starts_with(name,":memory:")){
 		if(memSavedSimulations.count(simulationFileName)>0) LOG_INFO("Overwriting in-memory saved simulation "<<name);
 		ostringstream oss;
-		#ifdef YADE_SERIALIZE_USING_BOOST
-			yade::ObjectIO::save<typeof(scene),boost::archive::binary_oarchive>(oss,"scene",scene);
-		#else
-			IOFormatManager::saveToStream("XMLFormatManager",oss,"scene",scene);
-		#endif
+		yade::ObjectIO::save<typeof(scene),boost::archive::binary_oarchive>(oss,"scene",scene);
 		memSavedSimulations[name]=oss.str();
 	}
 	else {
-		throw runtime_error("File format not recognized: `"+name+"' (admissible filename patterns: :memory:* *.xml *.xml.bz2)");
+		// handles automatically the XML/binary distinction as well as gz/bz2 compression
+		yade::ObjectIO::save(name,"scene",scene); 
 	}
 }
 

=== modified file 'py/_eudoxos.cpp'
--- py/_eudoxos.cpp	2010-06-08 22:25:00 +0000
+++ py/_eudoxos.cpp	2010-06-17 21:13:59 +0000
@@ -138,7 +138,7 @@
 	shared_ptr<GridContainer<FlatInteraction> > grid;
 	Real thetaSpan;
 	int axis;
-	SpiralInteractionLocator2d(Real dH_dTheta, int _axis, Real theta0): axis(_axis){
+	SpiralInteractionLocator2d(Real dH_dTheta, int _axis, Real periodStart, Real theta0): axis(_axis){
 		Scene* scene=Omega::instance().getScene().get();
 		Real inf=std::numeric_limits<Real>::infinity();
 		Vector2r lo=Vector2r(inf,inf), hi(-inf,-inf);
@@ -151,7 +151,7 @@
 			CpmPhys* ph=dynamic_cast<CpmPhys*>(i->interactionPhysics.get());
 			if(!ge || !ph) continue;
 			Real r,h,theta;
-			boost::tie(r,h,theta)=Shop::spiralProject(ge->contactPoint,dH_dTheta,axis,NaN,theta0);
+			boost::tie(r,h,theta)=Shop::spiralProject(ge->contactPoint,dH_dTheta,axis,periodStart,theta0);
 			lo=lo.cwise().min(Vector2r(r,h)); hi=hi.cwise().max(Vector2r(r,h));
 			minD0=min(minD0,ge->refLength); maxD0=max(maxD0,ge->refLength);
 			minTheta=min(minTheta,theta); maxTheta=max(maxTheta,theta);
@@ -176,10 +176,11 @@
 		}
 		return ret;
 	}
-	// return macroscopic stress around interactions that project around given point
+	// return macroscopic stress around interactions that project around given point and their average omega
 	// stresses are rotated around axis back by theta angle
-	Matrix3r macroStressAroundPt(const Vector2r& pt, Real radius){
+	python::tuple macroAroundPt(const Vector2r& pt, Real radius){
 		Matrix3r ss(Matrix3r::Zero());
+		Real omegaCumm=0, kappaCumm=0; int nIntr=0;
 		FOREACH(const Vector2i& v, grid->circleFilter(pt,radius)){
 			FOREACH(const FlatInteraction& fi, grid->grid[v[0]][v[1]]){
 				if((pow(fi.r-pt[0],2)+pow(fi.h-pt[1],2))>radius*radius) continue; // too far
@@ -198,13 +199,18 @@
 				for(int i=0; i<3; i++) for(int j=0;j<3; j++){
 					ss(i,j)+=d*A*(sigmaN*n[i]*n[j]+.5*(sigmaT[i]*n[j]+sigmaT[j]*n[i]));
 				}
+				omegaCumm+=phys->omega; kappaCumm+=phys->kappaD;
+				nIntr++;
 			}
 		}
 		// divide by approx spatial volume over which we averaged:
 		// spiral cylinder with two half-spherical caps at ends
 		ss*=1/((4/3.)*Mathr::PI*pow(radius,3)+Mathr::PI*pow(radius,2)*(thetaSpan*pt[0]-2*radius)); 
-		return ss;
+		return python::make_tuple(nIntr,ss,omegaCumm/nIntr,kappaCumm/nIntr);
 	}
+	Vector2r getLo(){ return grid->getLo(); }
+	Vector2r getHi(){ return grid->getHi(); }
+
 };
 
 #ifdef YADE_VTK
@@ -263,7 +269,7 @@
 		}
 		return ret;
 	}
-	python::tuple macroAroundPt(const Vector3r& pt, Real radius){
+	python::tuple macroAroundPt(const Vector3r& pt, Real radius, Real forceVolume=-1){
 		Matrix3r ss(Matrix3r::Zero());
 		vtkIdList *ids=vtkIdList::New();
 		locator->FindPointsWithinRadius(radius,(const double*)(&pt),ids);
@@ -283,7 +289,8 @@
 			}
 			omegaCumm+=phys->omega; kappaCumm+=phys->kappaD;
 		}
-		ss*=1/((4/3.)*Mathr::PI*pow(radius,3));
+		Real volume=(forceVolume>0?forceVolume:(4/3.)*Mathr::PI*pow(radius,3));
+		ss*=1/volume;
 		return py::make_tuple(ss,omegaCumm/numIds,kappaCumm/numIds);
 	}
 	py::tuple getBounds(){ return py::make_tuple(mn,mx);}
@@ -301,15 +308,18 @@
 #ifdef YADE_VTK
 	py::class_<InteractionLocator>("InteractionLocator","Locate all (real) interactions in space by their :yref:`contact point<Dem3DofGeom::contactPoint>`. When constructed, all real interactions are spatially indexed (uses vtkPointLocator internally). Use intrsWithinDistance to use those data. \n\n.. note::\n\tData might become inconsistent with real simulation state if simulation is being run between creation of this object and spatial queries.")
 		.def("intrsAroundPt",&InteractionLocator::intrsAroundPt,((python::arg("point"),python::arg("maxDist"))),"Return list of real interactions that are not further than *maxDist* from *point*.")
-		.def("macroAroundPt",&InteractionLocator::macroAroundPt,((python::arg("point"),python::arg("maxDist"))),"Return tuple of averaged stress tensor (as Matrix3), average omega and average kappa values.")
+		.def("macroAroundPt",&InteractionLocator::macroAroundPt,((python::arg("point"),python::arg("maxDist"),python::arg("forceVolume")=-1)),"Return tuple of averaged stress tensor (as Matrix3), average omega and average kappa values. *forceVolume* can be used (if positive) rather than the sphere (with *maxDist* radius) volume for the computation. (This is useful if *point* and *maxDist* encompass empty space that you want to avoid.)")
 		.add_property("bounds",&InteractionLocator::getBounds,"Return coordinates of lower and uppoer corner of axis-aligned abounding box of all interactions")
 		.add_property("count",&InteractionLocator::getCnt,"Number of interactions held")
 	;
 #endif
 	py::class_<SpiralInteractionLocator2d>("SpiralInteractionLocator2d",
 		"Locate all real interactions in 2d plane (reduced by spiral projection from 3d, using ``Shop::spiralProject``, which is the same as :yref:`yade.utils.spiralProject`) using their :yref:`contact points<Dem3DofGeom::contactPoint>`. \n\n.. note::\n\tDo not run simulation while using this object.",
-		python::init<Real,int,Real>((python::arg("dH_dTheta"),python::arg("axis")=0,python::arg("theta0")=0),":Parameters:\n\n\tdH_dTheta: float\n\t\tSpiral inclination, i.e. height increase per 1 radian turn;\n\taxis: int\n\t\tAxis of rotation (0=x,1=y,2=z)\n\ttheta: float\n\t\tSpiral angle at zero height (theta intercept)\n\n")
+		python::init<Real,int,Real,Real>((python::arg("dH_dTheta"),python::arg("axis")=0,python::arg("periodStart")=NaN,python::arg("theta0")=0),":Parameters:\n\n\tdH_dTheta: float\n\t\tSpiral inclination, i.e. height increase per 1 radian turn;\n\taxis: int\n\t\tAxis of rotation (0=x,1=y,2=z)\n\ttheta: float\n\t\tSpiral angle at zero height (theta intercept)\n\nSee :yref:`yade.utils.spiralProject`.")
 	)
 		.def("intrsAroundPt",&SpiralInteractionLocator2d::intrsAroundPt,(python::arg("pt2d"),python::arg("radius")),"Return list of interaction objects that are not further from *pt2d* than *radius* in the projection plane")
-		.def("macroStressAroundPt",&SpiralInteractionLocator2d::macroStressAroundPt,(python::arg("pt2d"),python::arg("radius")),"Compute macroscopic stress around given point, rotating the interaction to the projection plane first. The formula used is\n\n.. math::\n\n    \\sigma_{ij}=\\frac{1}{V}\\sum_{IJ}d^{IJ}A^{IJ}\\left[\\sigma^{N,IJ}n_i^{IJ}n_j^{IJ}+\\frac{1}{2}\\left(\\sigma_i^{T,IJ}n_j^{IJ}+\\sigma_j^{T,IJ}n_i^{IJ}\\right)\\right]\n\nwhere the sum is taken over volume $V$ containing interactions $IJ$ between spheres $I$ and $J$;\n\n* $i$, $j$ indices denote Cartesian components of vectors and tensors,\n* $d^{IJ}$ is current distance between spheres $I$ and $J$,\n* $A^{IJ}$ is area of contact $IJ$,\n* $n$ is interaction normal (unit vector pointing from center of $I$ to the center of $J$)\n* $\\sigma^{N,IJ}$  is normal stress (as scalar) in contact $IJ$,\n* $\\sigma^{T,IJ}$ is shear stress in contact $IJ$ in global coordinates.\n\n$\\sigma^{T}$ and $n$ are transformed by angle $\\theta$ as given by :yref:`yade.utils.spiralProject`.");
+		.def("macroAroundPt",&SpiralInteractionLocator2d::macroAroundPt,(python::arg("pt2d"),python::arg("radius")),"Compute macroscopic stress around given point, rotating the interaction to the projection plane first. The formula used is\n\n.. math::\n\n    \\sigma_{ij}=\\frac{1}{V}\\sum_{IJ}d^{IJ}A^{IJ}\\left[\\sigma^{N,IJ}n_i^{IJ}n_j^{IJ}+\\frac{1}{2}\\left(\\sigma_i^{T,IJ}n_j^{IJ}+\\sigma_j^{T,IJ}n_i^{IJ}\\right)\\right]\n\nwhere the sum is taken over volume $V$ containing interactions $IJ$ between spheres $I$ and $J$;\n\n* $i$, $j$ indices denote Cartesian components of vectors and tensors,\n* $d^{IJ}$ is current distance between spheres $I$ and $J$,\n* $A^{IJ}$ is area of contact $IJ$,\n* $n$ is interaction normal (unit vector pointing from center of $I$ to the center of $J$)\n* $\\sigma^{N,IJ}$  is normal stress (as scalar) in contact $IJ$,\n* $\\sigma^{T,IJ}$ is shear stress in contact $IJ$ in global coordinates.\n\n$\\sigma^{T}$ and $n$ are transformed by angle $\\theta$ as given by :yref:`yade.utils.spiralProject`. \n\nAdditionaly, computes average of :yref:`CpmPhys.omega` ($\\bar\\omega$) and :yref:`CpmPhys.kappaD` ($\\bar\\kappa_D$). *N* is the number of interactions in the volume given. \n\n:Return: tuple of (*N*,$\\tens{\\sigma}$,$\\bar\\omega$,$\\bar\\kappa_D$).\n")
+		.add_property("lo",&SpiralInteractionLocator2d::getLo,"Return lower corner of the rectangle containing all interactions.")
+		.add_property("hi",&SpiralInteractionLocator2d::getHi,"Return upper corner of the rectangle containing all interactions.");
+
 }

=== modified file 'py/eudoxos.py'
--- py/eudoxos.py	2010-04-03 16:40:33 +0000
+++ py/eudoxos.py	2010-06-17 21:13:59 +0000
@@ -115,41 +115,41 @@
 def oofemTextExport(fName):
 	"""Export simulation data in text format 
 	
-	The format is line-oriented as follows:
-		# 3 lines of material parameters:
-		1. E G # elastic
-		2. epsCrackOnset relDuctility xiShear transStrainCoeff #tension; epsFr=epsCrackOnset*relDuctility
-		3. cohesionT tanPhi # shear
-		4. [number of spheres] [number of links]
-		5. id x y z r -1/0/1[on negative/no/positive boundary] # spheres
+	The format is line-oriented as follows::
+
+		E G                                                 # elastic material parameters
+		epsCrackOnset relDuctility xiShear transStrainCoeff # tensile parameters; epsFr=epsCrackOnset*relDuctility
+		cohesionT tanPhi                                    # shear parameters
+		number_of_spheres number_of_links
+		id x y z r boundary                                 # spheres; boundary: -1 negative, 0 none, 1 positive
 		…
-		n. id1 id2 contact_point_x cp_y cp_z A # interactions """
-	from yade.wrapper import Omega
+		id1 id2 cp_x cp_y cp_z A                            # interactions; cp = contact point; A = cross-section
+		
+	"""
 	material,bodies,interactions=[],[],[]
-	o=Omega()
 
 	f=open(fName,'w') # fail early on I/O problem
 
-	ph=o.interactions.nth(0).phys # some params are the same everywhere
-	material.append("%g %g"%(ph['E'],ph['G']))
-	material.append("%g %g %g %g"%(ph['epsCrackOnset'],ph['epsFracture'],1e50,0.0))
-	material.append("%g %g"%(ph['undamagedCohesion'],ph['tanFrictionAngle']))
+	ph=O.interactions.nth(0).phys # some params are the same everywhere
+	material.append("%g %g"%(ph.E,ph.G))
+	material.append("%g %g %g %g"%(ph.epsCrackOnset,ph.epsFracture,1e50,0.0))
+	material.append("%g %g"%(ph.undamagedCohesion,ph.tanFrictionAngle))
 
 	# need strainer for getting bodies in positive/negative boundary
-	strainers=[e for e in o.engines if e.name=='UniaxialStrainer']
+	strainers=[e for e in O.engines if e.name=='UniaxialStrainer']
 	if len(strainers)>0: strainer=strainers[0]
 	else: strainer=None
 
-	for b in o.bodies:
-		if strainer and b.id in strainer['negIds']: boundary=-1
-		elif strainer and b.id in strainer['posIds']: boundary=1
+	for b in O.bodies:
+		if not b.shape or b.shape.name!='Sphere': continue
+		if strainer and b.id in strainer.negIds: boundary=-1
+		elif strainer and b.id in strainer.posIds: boundary=1
 		else: boundary=0
-		bodies.append("%d %g %g %g %g %d"%(b.id,b.phys['se3'][0],b.phys['se3'][1],b.phys['se3'][2],b.mold['radius'],boundary))
+		bodies.append("%d %g %g %g %g %d"%(b.id,b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius,boundary))
 
-	for i in o.interactions:
-		if not i.geom or not i.phys: continue
-		cp=i.geom['contactPoint']
-		interactions.append("%d %d %g %g %g %g"%(i.id1,i.id2,cp[0],cp[1],cp[2],i.phys['crossSection']))
+	for i in O.interactions:
+		cp=i.geom.contactPoint
+		interactions.append("%d %d %g %g %g %g"%(i.id1,i.id2,cp[0],cp[1],cp[2],i.phys.crossSection))
 	
 	f.write('\n'.join(material+["%d %d"%(len(bodies),len(interactions))]+bodies+interactions))
 	f.close()
@@ -205,7 +205,7 @@
 	strainers=[e for e in o.engines if e.name=='UniaxialStrainer']
 	if len(strainers)>0:
 		strainer=strainers[0]
-		posIds,negIds=strainer['posIds'],strainer['negIds']
+		posIds,negIds=strainer.posIds,strainer.negIds
 	else: strainer=None
 	f=open(fileBase+'.in','w')
 	# header
@@ -220,19 +220,19 @@
 	f.write("Node 1 coords 3 0.0 0.0 0.0 bc 6 1 1 1 1 1 1\n")
 	f.write("Node 2 coords 3 0.0 0.0 0.0 bc 6 1 2 1 1 1 1\n")
 	for b in o.bodies:
-		f.write("Particle %d coords 3 %g %g %g rad %g"%(b.id+3,b.phys.refPos[0],b.phys.refPos[1],b.phys.refPos[2],b.mold['radius']))
+		f.write("Particle %d coords 3 %g %g %g rad %g"%(b.id+3,b.state.refPos[0],b.state.refPos[1],b.state.refPos[2],b.shape.radius))
 		if b.id in negIds: f.write(" dofType 6 1 1 1 1 1 1 masterMask 6 0 1 0 0 0 0 ")
 		elif b.id in posIds: f.write(" dofType 6 1 1 1 1 1 1 masterMask 6 0 2 0 0 0 0 0")
 		f.write('\n')
 	j=1
 	for i in inters:
-		f.write('CohSur3d %d nodes 2 %d %d mat 1 crossSect 1 area %g\n'%(j,i.id1+3,i.id2+3,i.phys['crossSection']))
+		f.write('CohSur3d %d nodes 2 %d %d mat 1 crossSect 1 area %g\n'%(j,i.id1+3,i.id2+3,i.phys.crossSection))
 		j+=1
 	# crosssection
 	f.write("SimpleCS 1 thick 1.0 width 1.0\n")
 	# material
 	ph=inters[0].phys
-	f.write("CohInt 1 kn %g ks %g e0 %g ef %g c 0. ksi %g coh %g tanphi %g damchartime %g damrateexp %g plchartime %g plrateexp %g d 1.0\n"%(ph['E'],ph['G'],ph['epsCrackOnset'],ph['epsFracture'],0.0,ph['undamagedCohesion'],ph['tanFrictionAngle'],ph['dmgTau'],ph['dmgRateExp'],ph['plTau'],ph['plRateExp']))
+	f.write("CohInt 1 kn %g ks %g e0 %g ef %g c 0. ksi %g coh %g tanphi %g damchartime %g damrateexp %g plchartime %g plrateexp %g d 1.0\n"%(ph.E,ph.G,ph.epsCrackOnset,ph.epsFracture,0.0,ph.undamagedCohesion,ph.tanFrictionAngle,ph.dmgTau,ph.dmgRateExp,ph.plTau,ph.plRateExp))
 	# boundary conditions
 	f.write('BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0\n')
 	f.write('BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 1.e-4\n')

=== modified file 'py/pack/pack.py'
--- py/pack/pack.py	2010-05-30 13:41:00 +0000
+++ py/pack/pack.py	2010-06-17 21:13:59 +0000
@@ -276,10 +276,10 @@
 		print "Found suitable packing in %s (radius=%g±%g,N=%g,dim=%g×%g×%g,%s,scale=%g), created %s"%(memoizeDb,R,rDev,NN,X,Y,Z,"periodic" if isPeri else "non-periodic",scale,time.asctime(time.gmtime(timestamp)))
 		c.execute('select pack from packings where timestamp=?',(timestamp,))
 		sp=SpherePack(cPickle.loads(str(c.fetchone()[0])))
+		sp.scale(scale);
 		if isPeri and wantPeri:
 			sp.cellSize=(X,Y,Z);
 			if fillPeriodic: sp.cellFill(Vector3(fullDim[0],fullDim[1],fullDim[2]));
-		sp.scale(scale);
 		#sp.cellSize=(0,0,0) # resetting cellSize avoids warning when rotating
 		return sp
 		#if orientation: sp.rotate(*orientation.toAxisAngle())

=== modified file 'scripts/test/wm3-wrap.py'
--- scripts/test/wm3-wrap.py	2010-06-03 10:12:50 +0000
+++ scripts/test/wm3-wrap.py	2010-06-17 21:13:59 +0000
@@ -1,13 +1,13 @@
 # constructors, constants as static objects
-x,y,z,one=Vector3().UNIT_X,Vector3().UNIT_Y,Vector3().UNIT_Z,Vector3().ONE
+x,y,z,one=Vector3.UnitX,Vector3.UnitY,Vector3.UnitZ,Vector3.One
 x2=Vector3(x)
 # conversions to sequence types
 list(x2)
 tuple(x2)
 # operations and operators
 x+y+z==one
-x.Dot(y)==0
-x.Cross(y)==z
+x.dot(y)==0
+x.cross(y)==z
 # methods
 one.norm()
 
@@ -23,5 +23,5 @@
 # inverse rotation
 q1.Conjugate()
 # convert to axis-angle representation
-axis,angle=q1.ToAxisAngle()
+axis,angle=q1.toAxisAngle()