yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #04905
[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()