Source code for woo.pre.psdrender

from woo.dem import *
from woo.fem import *
import woo.core
import woo.dem
import woo.pyderived
import woo.models
import math
from minieigen import *



[docs]class PsdRender(woo.core.Preprocessor,woo.pyderived.PyWooObject): '''Preprocessor for creating layer with given PSD and passing it to POV-Ray for rendering.''' _classTraits=None _PAT=woo.pyderived.PyAttrTrait _attrTraits=[ _PAT(Vector2,'size',(.2,.3),unit='m',doc='Region to be rendered (the particle area will be larger by :obj:`sizeExtraRel`'), _PAT(float,'sizeExtraRel',.2,doc='Enlarge particle area by this much, relative to size.'), _PAT(woo.dem.ParticleGenerator,'gen',woo.dem.PsdSphereGenerator(psdPts=[(.007,0),(0.009,.2),(0.012,.5),(0.016,.9),(.02,1)]),doc='Particle generator'), _PAT(float,'relHt',2,doc='Bed height relative to largest particle diameter (computed via mass, supposing porosity of :obj:`porosity`)'), _PAT(Vector3,'gravity',(0,0,-9.81),doc='Gravity acceleration.'), _PAT(float,'porosity',.4,doc='Approximate porosity to convert bed height (:obj:`relHt`) to mass; it will not influence porosity itself, which is given almost exclusively geometrically.'), _PAT(int,'stepPeriod',200,doc='Periodicity for the factory.'), _PAT(float,'dtSafety',.7,doc='Safety factor for timestep.'), _PAT(float,'maxUnbalanced',.5,doc='Unbalanced force/energy to wait for before declared settled.'), _PAT(woo.models.ContactModelSelector,'model',woo.models.ContactModelSelector(name='linear',damping=.5,numMat=(1,1),matDesc=['particles'],mats=[woo.dem.FrictMat(density=2e3,young=5e6,tanPhi=0.)]),doc='Contact model and material type; since the simulation is trivial, this has practically no influence, except of friction: less (or zero) friction will make the packing more compact.'), _PAT(bool,'povEnable',True,doc='Enable POV-Ray export.'), _PAT(Vector3,'camPos',(0,0,.5),doc='Camera position; x, y components determine offset from bed normal; z is height above the highest particle center.'), _PAT(str,'out','/tmp/{tid}',doc='Prefix for outputs (:obj:`woo.core.Scene.tags` are expanded).'), _PAT(int,'imgDim',2000,doc='Larger image dimension when the scene is rendered; the scene can be re-rendered by calling POV-Ray by hand anytime with arbitrary resolution.'), _PAT(str,'povLights','''// light_source{<-8,-20,30> color rgb .75} // light_source{<25,-12,12> color rgb .44} light_source{<-.5,-.5,10> color White area_light <1,0,0>,<0,1,0>, 5, 5 adaptive 1 jitter } ''',doc='Default light specifications for POV-Ray'), _PAT(bool,'saveShapePack',True,'Create a .shapepack file with particle geometries.'), ]
[docs] def __new__(klass,**kw): self=super().__new__(klass) self.wooPyInit(PsdRender,woo.core.Preprocessor,**kw) return self
def __init__(self,**kw): woo.core.Preprocessor.__init__(self) self.wooPyInit(PsdRender,woo.core.Preprocessor,**kw)
[docs] def __call__(self): woo.master.usesApi=10104 pre=self S=woo.core.Scene(fields=[woo.dem.DemField(gravity=pre.gravity)],pre=pre.deepcopy(),dtSafety=pre.dtSafety) S.trackEnergy=True mat=pre.model.mats[0] lxy=(1+pre.sizeExtraRel)*pre.size bedHt=pre.relHt*pre.gen.minMaxDiam()[1] boxHt=2*bedHt mass=bedHt*(1-pre.porosity)*mat.density*lxy[0]*lxy[1] print('Need to generate %g kg to create layer of %g m (ρ=%g kg/m³, solid ratio %g)'%(mass,bedHt,mat.density,1-pre.porosity)) box=AlignedBox3((-lxy[0]/2,-lxy[1]/2,0),(lxy[0]/2,lxy[1]/2,2*bedHt)) S.dem.par.add(woo.dem.Wall.makeBox(box,mat=mat)) S.engines=woo.dem.DemField.minimalEngines(model=pre.model)+[ woo.dem.BoxInlet(box=box,generator=pre.gen,maxMass=mass,massRate=0,stepPeriod=pre.stepPeriod,label='inlet',atMaxAttempts='ignore',doneHook='engine.dead=True',materials=[mat]), woo.core.PyRunner(pre.stepPeriod,'woo.pre.psdrender.checkSettled(S)') ] return S
[docs]def checkSettled(S): if not S.lab.inlet.dead: return #unb=woo.utils.unbalancedEnergy(S) #print('Unbalanced energy: ',unb) unb=woo.utils.unbalancedForce(S) print('Unbalanced force:',unb) if unb>S.pre.maxUnbalanced: return else: finalize(S)
[docs]def finalize(S): import math, subprocess, os.path S.stop() print('Finished.') out2=S.expandTags(S.pre.out) # do not export walls at all pov=POVRayExport(mask=woo.dem.DemField.defaultOutletBit,masks=[woo.dem.DemField.defaultOutletBit],textures=['particles'],out=out2) if S.pre.saveShapePack: sp=woo.dem.ShapePack() sp.fromDem(S,S.dem,mask=woo.dem.DemField.defaultOutletBit) sp.saveTxt(out2+'.shapepack') if S.pre.povEnable: bedZ=max([p.pos[2] for p in S.dem.par]) camAngle=math.degrees(2*math.atan(.5*min(S.pre.size)/S.pre.camPos[2])) out2base=os.path.basename(out2).encode() pov(S) pmaster=b''' #version 3.7; #include"colors.inc" #include"metals.inc" #include"textures.inc" global_settings{ assumed_gamma 2.2 } camera{ location<%g,%g,%g> sky y right y*image_width/image_height up y look_at <0,0,0> angle %g } background{rgb .2} '''%(S.pre.camPos[0],S.pre.camPos[1],bedZ+S.pre.camPos[2],camAngle)+S.pre.povLights.encode()+b''' #declare o=<0,0,0>; #declare nan=1e12; #declare RndTexA=seed(12345); #declare RndTexB=seed(54321); #declare RndTexC=seed(23659); #declare RndTexD=seed(33333); #macro woo_tex_particles(rgb0,rgb1,diam) #declare dark=.7; #if(diam<9e-3) #declare c=<1,dark,dark>; #else #if(diam<16e-3) #declare c=<dark,1,dark>; #else #declare c=<dark,dark,1>; #end #end #declare c=<1,1,1>; texture{ pigment { crackle form <-1,1,0> scale 1e-4 metric 2 color_map { [0 color .6*c] [1 color c] } } normal { granite .1 scale 1e-2 turbulence .5 bump_size .4 translate <rand(RndTexA),rand(RndTexB),rand(RndTexC)> } finish { reflection .001 specular .00 ambient .3 diffuse .5 phong 1 phong_size 50 } } #end #include "%s_static.inc" #include concat(concat("%s_frame_",str(frame_number,-5,0)),".inc") '''%(out2base,out2base) outMaster=out2+'_master.pov' print('Writing out to '+outMaster) with open(outMaster,'wb') as m: m.write(pmaster) ratio=S.pre.size[0]/S.pre.size[1] if ratio>1: px=(S.pre.imgDim,int(S.pre.imgDim/ratio)) else: px=(int(S.pre.imgDim*ratio),S.pre.imgDim) cmd=['povray','+W%d'%px[0],'+H%d'%px[1],'+A','-kff0',outMaster] print('Running: cd "'+os.path.dirname(out2)+'"; povray '.join(cmd)) subprocess.call(cmd,cwd=os.path.dirname(out2))