Date post: | 02-Oct-2015 |
Category: |
Documents |
Upload: | styleworker |
View: | 26 times |
Download: | 2 times |
CombinedUseofBlenderwithOpenFOAMG.DouglasBaldwin
AbstractBlenderfromblender.orgcontainsapowerful,widelyaccepted,opensource,surfacemeshgenerationtoolthatwasdevelopedforthedigitalartscommunity.Furthermore,BlenderincludesarobustandwelldocumentedPythonapplicationprogramminginterface(API)whichfacilitatesthedevelopmentofusertoolsformeshmanipulation,layeredmanifolds,andimport/export.
TheauthordevelopedaPythonscriptandtechniqueformanipulatingandexportingBlenderobjectsintoCalculiXforhexagonalgridgeneration,whicharethenexportedintoOpenFOAMformat.Thebenefitofthisapproachisthatmanifoldsallowabsolutecontrolofmaximumcellgrowthratesfromtheboundarylayerouttotheedgeofthecomputationaldomain,whilealsodirectingthepathofstackedhexagonalcellstoavoidskew.ThistechniquewasusedtostreamlineanaircraftfuselageusingapurehexagonalgridwithOpenFOAM,andthenimportthegridintoScientificSimulationsNSU3Dforauthoritativedraganalysis.
Thetechniqueisripewithpossibilitiesfordevelopingmeshesformanyclassesofsimulations.Highlightsofthehexahedralgridsusedintheaircraftstreamliningeffortwillbeshownanddiscussedbelow,followedbyanillustrativegridthatcombineshexahedralcellsattheboundarylayerwithtetrahedralcellsinthebulkflow.ThispaperwillconcludewithacopyofthePythonscriptandadiscussionofhowitmaybefurtherdeveloped.Theauthorhasnointentionatthistimeofleadingfurtherdevelopmentofthisscriptduetootherdemandsonhistime.Itishopedthatotherstoowillfindvalueinthisapproachandperhapscarryitforward.
FuselageStreamliningIngeneral,Blendermeshesarecomprisedofbothtrianglesandquadrilaterals.Forthefuselagestreamliningproject,itwasdecidedtouseexclusivelyquadrilateralsforthesurface.Illustrationsofthefinalsurfaceareprovidedbelow.Noticethepinkvertices.Theonlyverticiesdefinedbytheuserarethoseshowninpink.AlloftheotherverticiesareautomaticallygeneratedbyBlenderwhenthesubsurfmodifierisappliedtotheobject.Thestrengthofthelinesconnectinganytwopinkverticiesiscontrolledbythecreasefeature.ItisnotthepurposeofthispapertoprovideatutorialonBlender,subsurf,andcrease.ManyexcellentBlendertutorialsarereadilyavailableontheinternet.Noticehoweverthetechniqueofhavingevenlyspacepinkverticiestomaintainarelativelyconsistentgridsize.ThecloseupillustrationbelowrevealsbettertheindividualquadrilateralelementsautomaticallygeneratedbytheBlendersubsurfmodifier.AlsonotethetwodifferentcoloredBlendermaterialsusedontheobject.TheseBlendermaterialseventuallytranslatetoOpenFOAMpatches.Thedecisiontohavetwopatchesforthisfuselagemodelisunrelatedtothepresenttopicandwillnotbediscussedfurthertoavoidaconfusingdigression.
Presentedatthe3rdOpenFOAMWorkshop,Milan,Italy,1011July2008.
ManifoldssurroundingthisfuselageobjectwerecreatedbyusingthePythonscriptthatwillbeprovidedtowardstheendofthispaper.Theprocedureforcreatingmanifoldsisthatacopyofthebaseobjectiscreatedbytheuser,andthenanautomaticalgorithmmoveseachpinkvertexalongitsnormalbyauserspecifiedamount,makingautomaticadjustmentsuntilallcomputergeneratedverticieshavealsomovedapproximatelyalongtheirnormalsbyapproximatelythesamedistance.Asabyproductofthisalgorithm,colorcodedrepresentationsofcellheight,aspectratio,andskewaregeneratedasavisualaidformanualtweakingofthemanifoldverticies.Thefirstmanifoldsurroundsthefuselage/baseobjectasshownintheillustrationbelow.
Thefollowingillustrationsshowthecolorcodedrepresentationsofcellheight,aspectratio,andskew,inthatorder.Thecolorcodesfortheseillustrationshavethefollowingmeanings.Fortheheightandaspectratioillustrations,bluerepresentstheminimumwithintherangeofvaluesandredrepresentsthemaximumwithintherangeofvalues.Forskew,bluethroughredrepresenttherangeofzerotoninetydegreesin12.5degreeincrements.
Thedesigngoalforthisfuselagegridwastohaveacellheightatthefuselagewithy+intherangeof1to10,andacellgrowthfactorof1.15extendingtotheedgeofthecomputationaldomain,whichwasapproximately10timesthereferencelengthawayfromthefuselageinalldirections.Aseriesoffourmanifoldswereneededtoavoidhighskewangles.Ascanbeseeninthefollowingtwoillustrations,themanifoldsfurtherawayfromthefuselagebecomebecomemorespherelike.Thefirstthreemanifoldsareshowninthecutawayillustrationbelow,followedbyanillustrationofthefourthmanifoldenclosingthethirdmanifold.Noticethatthefourthandlargestmanifoldhastwomaterialsassigned,shownasblueandred,whichrepresenttheinletpatchandtheoutletpatch.
TheuserinterfaceforthePythonscriptisshownbelow.Sofar,wehaveonlydiscussedthemanifoldgenerationcapabilitiesofthisscriptwhicharecontrolledbytheDisplacementSliderandtheApplybutton.TheunitsoftheDisplacementSliderareequivalenttotheaverageedgelengthofthemanifoldquads.Theprocedureforcreatingamanifoldisasfollows:1)duplicatethetheBlenderObject;2)whileinEditModeselecttheverticesthatwillbedisplaced;and3)clickontheApplybutton.Onlytheselectedverticeswillbedisplaced.ThestandardBlenderUndocommandcanbeusedtomovetheverticesbacktotheiroriginalpositionifneeded.
Thecolumnofbuttonsandslidersontheleftsideoftheuserinterfaceareusedtospecifythegridcharacteristics,andthentheExportbuttonispressedtoexporttheselectedmanifoldsasasolidgeometryinCalculiXformat.WhenthebuttonlabeledMeshtheboundarylayerhasbeendepressed,aboundarylayermanifoldwillbeautomaticallygeneratedfortheoriginal/baseobject,withadisplacementdistanceasspecifiedbytheDisplacementslider.ThisbuttonisusefulforrelativelysimplegeometrieswhenperformingmultipleiterationsofmeshgenerationandOpenFOAManalysis.Theverticesofthebaseobjectcanbetweaked,andthenanewboundarylayermanifoldisautomaticallyproducedeachtimetheExportbuttonisclicked.Formorecomplexgeometriessuchasthefuselageshownabove,theboundarylayermanifoldcanbemanuallygeneratedandthenmanuallytweakedeachtimethefuselageverticesaretweaked.
Thenexttwoslidersspecifythecellheight.TheslidernamedTargetmaxaspectratioisusedtospecifythedesiredaspectratioofthefirstcell.OpenFOAMrejectsmesheshavinganycellaspectratiothatisgreaterthan1000.Thissliderisusefulforachievingasmally+whilestayingwithinanaspectratioof1000.Duetothenatureofthemeshingalgorithms,theactualaspectratioofthefirstcellmaybeslightlylargerorsmallerthanthespecifiedtarget.ThesliderCellGrowthFactorisusedtospecifythemaximumcellheightgrowthbetweenanytwostackedcells,andappliestotheentirecomputationaldomainfromthefirstcellatthebaseobjectouttothelastmanifold.
ThenextthreebuttonsareusedtospecifyplanesofsymmetrynormaltotheX,Y,andZaxes,respectively.Undermostcircumstancestheseplanesofsymmetrywillneedtopassthroughtheorigin,butifnecessarytheycanbeoffsetbyusingtheaccompanyingsliders.TheunitsfortheseslidersareBlenderunits,whichforthepurposesofOpenFOAMwillusuallybemeters.Aswillbeseeninsubsequentillustrations,aplaneofsymmetrynormaltotheYaxiswasappliedwhenexportingthefuselagegrid.
WhentheExportbuttonisclicked,theuserisaskedtospecifythefolderandfilenamefortheCalculiX.fbdfile.Filegenerationusuallytakesonlyafewsecondsforlargemodels,andcertainlylessthanaminutefortheverylargestofmodels.IfBlenderisinitializedthroughacommandlineconsoleinterface,thensomeusefulstatisticsrelatedtotheresultingmeshareprintedinthisconsole.Also,theheight,aspectratio,andskewillustrationsasshownaboveareautomaticallygeneratedandplacedinBlenderslayers11,12,and13respectively.
TheexportedfilecannowbeloadedintoCalculixbyusingthecommand:cgxbfilename.fbd.ForlargergridsthisloadprocesscantakeaverylongtimebecauseCalculiXautomaticallygeneratesageometricbodyforeachpairofquadsateachpairofmanifolds.Aftergeneratingthegeometry,CalculiXautomaticallygeneratesthemeshwhichalsotakessometime.ImmediatelyafterthefilecompletesloadingintoCalculiX,youhaveameshreadytoexportinOpenFOAMformat.First,typeinthesavecommand;thiswillsaveyouthetroubleofhavingCalculiXregeneratethegeometryifyoueverneedtoloadthisfileagain.AsimplecommandforexportingtoOpenFOAMatestmeshis:sendallfoampatchall.WhenyouaresatisfiedwithcheckMesh,youwillthenwanttospecifytheindividualpatchesinyoursendcommand.ThesepatchesweredefinedearlierbyusingBlendermaterials.AnexamplesendcommandwithpatchesissendallfoampatchinletpatchoutletwallyourObject.Also,ifplane(s)ofsymmetrywereusedinBlender,thenoneextrastepisneededinCalculiXbeforesendingthemeshwithindividualpatchestoOpenFOAM.UsethecommandsetrsymmetrysenotSymmetrytoremovethenonsymmetryfacesfromthesymmetryset,andthenincludethephrasesymmetryPlanesymmetryinyoursendcommand,e.g.sendallfoampatchinletpatchoutletwallyourObjectsymmetryPlanesymmetry.VerylittleproficiencywithCalculiXisnecessary,thoughitwouldnothurttolearnsomeoftheotherfeaturesofthistool.
SampleparaFoamplotsofthefinalfuselagegridareshownbelow.
Theabovefourplotsshow:1)thesurfacequadsofthefuselage,2)thesymmetryplanecloseintothefuselage,revealingthefinestructureattheboundarylayer,3)thesymmetryplaneshowingthe1st,2nd,and3rdmanifolds,and4)thesymmetryplaneofthefullcomputationaldomain,outtothe4thmanifold.
AfterseveraliterationsbetweenBlenderandOpenFOAM,afuselagegeometryhavingnoflowseparationwasachieved.TheOpenFOAMLift/Dragtoolwasusedtoestimatethedragcoefficients.ThegridwasthendeliveredtoScientificSimulationsLLC,whereanimporttoolwasdevelopedforconvertingtheOpenFOAMpurehexgridintoaNSU3DgridforfurtherCFDanalysis.UsingthesameoperatingconditionsandsameSpalartAllmaraswallmodel,thedifferenceinpredicteddragwassignificant.NSU3D,whichhasbeenpubliclyvalidatedforthesekindsofstreamlinedfuselagesattheAIAACFDDragWorkshop,predicted30%lessdragthanOpenFOAM.Furthermore,NSU3Dacceptscellaspectratiosofatleast10,000,whichallowedforafinerresolutionofthegridatthewallwithouttheneedtofurtherrefinethefuselagesurfacemesh.Together,BlenderandOpenFOAMwereapowerfulcombinationoffreetoolsfordevelopingthisstreamlined,lowdragfuselage.
CombiningwithtetrahedralsCalculiXcanexporttoOpenFOAMonlypurehexahedralgrids,andassuchislimited.Somecasescannotbemodeledwithpurehex,stackedgrids.Forinstance,aneffortwasmadetousetheabovetechniquestodevelopasamplecoarsegridoftheAhmedwindtunnelexperiment.Unfortunately,thespacebetweenthebottomoftheautomobileandthetestsectionfloorbecamecrowedwithmanyhigh
aspectratiocells.Abetterapproachistohavequadrahedralsattheboundarylayercombinedwithtetrahedralsfillingtheremainderofthecomputationaldomain.Anattemptatcreatingsuchasamplegridwasundertaken,usingBlenderwithCalculiXfortheboundarylayerandNetgenforthebulkflowfield.Blenderimagesfromthisgridgenerationexperimentareshownbelow.ThefirstimageshowstheAhmedbodyandthefirstmanifold.ThesetwoobjectswereexportedtoCalculixusingthetechniquesdescribedabove.Thesecondimageshowsthetunnel,whichwascreatedbyextrudingacopyofthefirstmanifoldandadjustingitsverticies.
ThetunnelobjectwasexportedfromBlenderinstereolithography(STL)format,andthenreadintoNetgenfortetrahedralmeshgeneration.Sincethecavityofthetunnelobjectwasoriginallyacopyofthefirstmanifold,thisprovidesaperfectinterfaceforpotentiallyusingthestitchMeshtoolinOpenFOAM.BoththeCalculiXgeneratedboundarylayermeshandtheNetgenbulkflowmeshwerecombinedinOpenFOAMusingmergeMeshes.Animageofthecombinedmeshesisshownbelow,whichincludesthetunnelinletontheleft,thesymmetryplane,thesurfaceoftheAhmedbody,andthetunneloutletontheright.ThenextimageshowsthattheAhmedbodyhasaquadsurfacewithhexahedralcells.Followingthisisacloseupimageoftheinterfacebetweenthehexahedralcellsandthetetrahedralcells.Unfortunately,stitchMeshwasunabletoremovetheinterfacepatches.ItwouldappearthatstitchMeshisunderactivedevelopmentandshouldeventuallybecapableofremovingthisinterface.
FurtherusesandfurtherdevelopmentsBlenderhastheabilitytoimportSTLobjects,andthePythonscriptdescribedinthispapercanbeusedtocreateaboundarylayermeshontheseSTLobjects.OneapproachistoletCalculiXconverteachtrilateralintothreequadrilaterals,andthenusethetechniquesdescribedaboveforcreatingahexahedralmesh.AnotherapproachwouldbetomodifythePythonscripttohaveitoutputthehexahedralgriddirectlytoOpenFOAMformat,whichwoulddramaticallyspeedupthemeshgenerationprocess.DirectexportfromBlenderwouldallowgenerationofprismcells,whichcouldbestackeddirectlyontotheSTLtrilaterals.
AkeyarchitecturalfeatureoftheBlenderdatamodelprovidesthefoundationformanifolddevelopment.Eachmeshobjectincludesalinkedlistofvertices.Whenameshobjectiscopied,thenewmeshobjectcontainsthesameverticiesinthesamelinkedlistorder.Thecoordinatesoftheseverticiesmaybechangewithoutchangingtheirorderwithinthelinkedlist.Bystrategicplacementoftheverticiesofthenewmeshrelativetotheoriginalmesh,acollectionofuniform,lowskewhexahedralsand/orprismscanbegenerated.ThisarchitecturalfeaturewasexploitedtogeneratetheCalculiXbodiesfromtheBlendermanifolds.ThissamearchitecturalfeaturecouldbeexploitedtodirectlygenerateanOpenFOAMmeshcomprisedofhexahedralsand/orprismswithauniformgrowthfactorextendingfromthebodywalluptothefirstmanifold,orfurthertoasecondmanifold,etc.TheoutertwomanifoldscanthenbeexportedasanSTLmeshfortetrahedralmeshgenerationinNetgen.Blenderhasaveryefficientmeshmanipulationkernel,andwhencombinedwithPythonscriptscanrapidlyexportlargeobjects.Thescriptprovidedbelowisbothusefulasis,andpotentiallyevenmorevaluablewithadirectexporttoOpenFOAMcapability.
Alsoworthnoting,modificationstoCalculiXweredevelopedtoreducememoryallocationrequirementsandincreaseprecision.Amodificationwasneededwhengeneratingthefuselagegridinordertoavoidmallocerrorsona32bitmachine.ThemodifiedsourcefilenamedfoamFaces.cwaspostedtotheCalculiXsupportgroupsiteonYahoo.Also,CalculiXoutputsOpenFOAMgridcoordinatesinfloatformat,andtheformatstatementinthefilewrite2foam.ccaneasilybechangedtoexponentialformatforimprovedprecision.
ConclusionsAcombinationofBlenderandCalculixwasusedtogeneratepurehexahedralgridsforthepurposeofstreamlininganaircraftfuselage.Thistechniquecanpotentiallybeextendedtomixedhexahedral/tetrahedralgridsbyemployingNetgen.Furthermore,thePythonscriptforexportingBlendergeometryinCalculiXformatcouldthroughmodificationdirectlyexporttoOpenFOAMformat,whichwouldallowgenerationofastackedprismboundarylayergridontopofanSTLobject.ThisPythonscriptisveryusefulasis,anditsvaluetotheOpenFOAMcommunitycouldbesignificantlyenhancedbyaddingtheserelativelyminormodifications.
Pythonscript
#!BPY
#######################################################################Export_fbdv0.2forBlender
#ThisscriptletsyouexportmanifoldstoCalculixformat(.fbd)
#(c)2007G.DouglasBaldwin(dougATbaldwintechnologyDOTcom)#releasedunderBlenderArtisticLicense
######################################################################
"""Name:'CalculixExport(.fbd)...'Blender:Group:'Export'Tooltip:'ExportselectedobjectstoCalculixFormat(.fbd)'"""
__author__="DougBaldwin"__version__="0.2"
__bpydoc__="""\ThisscriptexportsmanifoldstoCalculixFormat(.fbd).
Usage:
Createabasemeshobject,thenmakeafirstcopyofthisobject.Afteracopyismadeverticesofanyobjectmayberepositioned,butvertices,lines,andfacesmayneitherbeaddednordeleted.Successivecopiesshouldbestretchedintoeverlargermanifolds.Thisscriptwillcreatea3DCalculixmeshsuccessivelyfromthebasemeshtothefirstcopy,thenfromthefirstcopytothesecondcopy,etc.
TheDisplacementbuttonisusefulforstretchingthemanifolds.Thisfunctiondisplacestheselectedverticesoftheselectedobjectinthedirectionnormaltothelocalsurface.
Thegoalistodisplacetheverticesofeachmanifoldgenerallynormaltoitsprecedingmesh,whilealsoreshapingasneeded.Graphicplotsoffirstcellheight,aspectratio,andskewareoutputtolayers11,12,and13.
BlenderMaterialnamesofthefirstandlastobjectwillbeexportedasCalculixsetsforgeneratingpatches.
TheGUIparametersTargetAspectRatioandGrowthFactorareusedforcalculatingthehexcellheightatthebasemeshobject,andtheratioofsuccessivecellheightsextendingtotheoutermostmanifold.ThevaluesTargetAspectRatioandGrowthFactorarethemaximumvaluesfortheentirehexmesh,regardlessofanyundulationsinthemanifolds.AspectRatioiscalculatedtobethesquarerootofthequadsurfacedividedbythefirstcellheightnormaltothequadsurface.
Symmetryplanesmaybetoggledon/offandpositionedalongtheX,Y,andZaxes.Ifoneormoresymmetryplanesaretoggledon,theexportedfilewillincludeasetofexternalsurfacescalled"symmetry".Symmetryplanesaregenerallyusefulonlywhenverticesofthebaseobjectandmanifoldslieonthesymmetryplane.
Selectallobjectstobeexported,withtheoutermostobjectactive.PresstheExportbuttontoexport,thenselectthefilelocationandfilename.PresstheExitbuttontoexitthescript.
"""
importBlenderfromBlenderimportScene,Window,Materialfrommathimportceil,log,sqrt,floor,acos,pi
#=================================#===WriteFBDCalculixFormat===#=================================fromBlender.BGLimport*fromBlender.Drawimport*importBPyMessagesimportbpy
#ParametersX_Plane=Create(0)Y_Plane=Create(1)Z_Plane=Create(0)X_Location=Create(0.0)Y_Location=Create(0.0)Z_Location=Create(0.0)growth=Create(1.15)aspect=Create(1000)mesh_BL=Create(0)
factor=Create(1.0)
#EventsEVENT_NOEVENT=1EVENT_EXPORT=2EVENT_EXIT=3EVENT_APPLY=4
#######################################################GUIdrawing######################################################defdraw():globalX_Plane,Y_Plane,Z_Plane,X_Location,Y_Location,Z_Locationglobalgrowth,aspect,mesh_BL,factorglobalEVENT_NOEVENT,EVENT_EXPORT,EVENT_EXIT
##########TitlesglClear(GL_COLOR_BUFFER_BIT)glRasterPos2d(8,183)Text("Exportwithoptionalsymmetryplane(s)")
glRasterPos2d(250,85)Text("Displaceselectedverticesnormaltothesubsurf")
#########ParametersGUIButtons
X_Plane=Toggle("X:",EVENT_NOEVENT,10,55,18,18,X_Plane.val,"ToggleXsymmetryplane");
X_Location=Slider("Location:",EVENT_NOEVENT,30,55,200,18,X_Location.val,20.000,20.0000,1,"Xplanelocation");
Y_Plane=Toggle("Y:",EVENT_NOEVENT,10,75,18,18,Y_Plane.val,"ToggleYsymmetryplane");
Y_Location=Slider("Location:",EVENT_NOEVENT,30,75,200,18,Y_Location.val,20.000,20.0000,1,"Yplanelocation");
Z_Plane=Toggle("Z:",EVENT_NOEVENT,10,95,18,18,Z_Plane.val,"ToggleZsymmetryplane");
Z_Location=Slider("Location:",EVENT_NOEVENT,30,95,200,18,Z_Location.val,20.000,20.0000,1,"Zplanelocation");
growth=Number("CellGrowthFactor:",EVENT_NOEVENT,10,115,220,18,growth.val,1.00,2.00,"Ratioofcellheightsindirectionnormaltothebaseobject")
aspect=Number("Targetmaxaspectratio:",EVENT_NOEVENT,10,135,220,18,aspect.val,100.0,2000.0,"Targetaspectratiooffirstcelllayer")
mesh_BL=Toggle("Meshtheboundarylayer",EVENT_NOEVENT,10,155,220,18,mesh_BL.val,"Generateameshextrudednormaltothebaseobject");
factor=Slider("Displacement:",EVENT_NOEVENT,250,55,260,18,factor.val,1.000,10.000,1,
"Magnituderelativetoaveragesubsurfedgelength");
#########ExportandExitButtonsglRasterPos2d(8,36)Text("Note:Selectallmanifolds")Button("Export",EVENT_EXPORT,10,10,80,18,"ExporttoCalculixfile")
Button("Apply",EVENT_APPLY,250,10,80,18,"Applydisplacementtotheactiveobject")
Button("Exit",EVENT_EXIT,430,10,80,18,"Exitscript")
defevent(evt,val):if(evt==QKEYandnotval):
Exit()
defbevent(evt):# globalEVENT_NOEVENT,EVENT_EXPORT,EVENT_EXIT
#########ManagesGUIeventsif(evt==EVENT_EXIT):
Exit()elif(evt==EVENT_EXPORT):
ifnotBlender.Object.GetSelected():BPyMessages.Error_NoActive()return
Blender.Window.FileSelector(write_ui,'FBDExport',Blender.sys.makename(ext='.fbd'))
Blender.Redraw()elif(evt==EVENT_APPLY):manDisplace(factor.val)
Register(draw,event,bevent)
defmanDisplace(factor):sce=bpy.data.scenes.activeob_act=sce.objects.activeifnotob_actorob_act.type!='Mesh':
BPyMessages.Error_NoMeshActive()return
is_editmode=Window.EditMode()Window.EditMode(0)Window.WaitCursor(1)
displace(ob_act,factor)
#Restoreeditmodeifitwasenabledifis_editmode:Window.EditMode(1)
Window.WaitCursor(0)
defwrite_ui(filename):globalgrowth,aspect,mesh_BL,factor
#openfileifnotfilename.lower().endswith('.fbd'):
filename+='.fbd'file=open(filename,'wb')file.write('asgnsC\n')#Calculixautogeneratedsurfacestobeginwith"C"
#initializevaluest=Blender.sys.time()me=[]ratio=[]bl=Nonescn=Scene.GetCurrent()obs=[obforobinscn.objects.context]obList=obs
ifmesh_BL.val==1:#createboundarylayerobjectscn.objects.selected=[obs[len(obs)1]]Blender.Object.Duplicate(mesh=1)bl=scn.objects.selected[0]#Selectverticesinbasemeshmesh=bl.getData(mesh=1)forvinmesh.verts:
v.sel=1displace(bl,factor.val)obList.insert(len(obList)1,bl)
n=len(obList)foriinrange(n):
me.append(Blender.Mesh.New())#createanewmeshme[i].getFromObject(obList[i],0,0)#getsubsurfmeshme[i].transform(obList[i].matrix)#scaleandrotateasneededwritePoints(file,me[i],i)#writemeshpointswriteLines(file,me[i],i)#writemeshlineswriteSurfaces(file,me[i],i)#writemeshsurfacesandpatchnamesifi!=0:
writeThickness(file,me[i],me[i1],i)writeBodies(file,me[i],me[i1],i)
#calculateandgeneratedivandbiaminH,maxH,ratio=heightAnalysis(me)dH=1.0/aspect.valforiinreversed(range(0,n1)):
dH=dH/ratio[i]height=0.0div=0whileheight=2:surfacePlots(obList,firstDiv,growth.val)
#generatesymmetrysetwhilealsogenerating3Dmeshmats=Blender.Material.get()formatinmats:
file.write('comp%sd\n'%mat.name)file.write('SETAnotSymmetryse%s\n'%mat.name)file.write('compnotSymmetryd\n')
file.write('eltyallhe8\n')file.write('meshall\n')file.write('setasymmetryseall\n')file.write('setrsymmetrysenotSymmetry\n')file.write('plotmeall\n')file.write('plussall\n')file.close()ifmesh_BL==1andn==2:
PupMenu('Returningboundarylayerobjectwithbaseobject')else:
ifbl!=None:scn.objects.unlink(bl)scn.objects.selected=obs#Timingthescriptisagoodwaytobeawareonanyspeedhitswhenscriptingprint'Scriptfinishedin%.2fseconds'%(Blender.sys.time()t)
defwritePoints(file,mi,i):#writeoutallpointsinthismesh
forvinmi.verts:file.write('PNTP%x%x'%(i,v.index))file.write('%.6f%.6f%.6f\n'%tuple(v.co))
defwriteLines(file,mi,i):#writeoutalllinesinthismeshforeinmi.edges:
file.write('LINEL%x%xP%x%xP%x%x1\n'%\(i,e.index,i,e.v1.index,i,e.v2.index))
defwriteThickness(file,m1,m0,i):forjinrange(len(m1.verts)):
m1vji=m1.verts[j].indexfile.write('LINEM%x%xP%x%xP%x%x2\n'%\(i,m1vji,i,m1vji,i1,m0.verts[j].index))file.write('SETA%s%slM%x%x\n'%\("thickness",i1,i,m1vji))
defheightAnalysis(me):ratio=[]foriinrange(len(me)2):
ratio.append(0.0)forf0,f1,f2inzip(me[i].faces,me[i+1].faces,me[i+2].faces):
upperH=abs((f0.centf1.cent)*(f0.no+f1.no)/2)lowerH=abs((f1.centf2.cent)*(f1.no+f2.no)/2)ratio[i]=max(ratio[i],upperH/lowerH)
n=len(me)2f0=me[n].faces[0]f1=me[n+1].faces[0]h=abs((f0.centf1.cent)*(f0.no+f1.no)/2)minH=hmaxH=hratio.append(h/sqrt(f1.area))forf0,f1inzip(me[n].faces,me[n+1].faces):
h=abs((f0.centf1.cent)*(f0.no+f1.no)/2)minH=min(minH,h)maxH=max(maxH,h)ratio[n]=min(ratio[n],h/sqrt(f1.area))
returnminH,maxH,ratio
defsurfacePlots(obs,firstDiv,growth):heights=[]aspectRatios=[]skews=[]mat=[]
factor=0foriinrange(firstDiv):
factor=factor+pow(growth,i)factor=1/factor
scn=Scene.GetCurrent()
meH=Blender.Mesh.New('height')#createanewmeshmeH.getFromObject(obs[len(obs)1],0,0)#getsubsurfmeshmeH.transform(obs[len(obs)1].matrix)#scaleandrotateasneededobH=scn.objects.new(meH)obH.layers=[11]
meAR=Blender.Mesh.New('aspectRatio')#createanewmeshmeAR.getFromObject(obH,1,0)#copymeshobAR=scn.objects.new(meAR)obAR.layers=[12]
meSkew=Blender.Mesh.New('skew')#createanewmeshmeSkew.getFromObject(obH,1,0)#copymeshobSkew=scn.objects.new(meSkew)obSkew.layers=[13]
me1=Blender.Mesh.New()#createanewmeshme1.getFromObject(obs[len(obs)2],0,0)#getsubsurfmeshme1.transform(obs[len(obs)2].matrix)#scaleandrotateasneeded
forf0,f1inzip(meH.faces,me1.faces):vC=f1.centf0.centheights.append(abs(vC*(f0.no+f1.no)/2)*factor)aspectRatios.append(sqrt(f0.area)/heights[len(heights)1])cosine=min(1,vC*f0.no/sqrt(vC*vC))skews.append(acos(cosine))
minH=min(heights)maxH=max(heights)minAR=min(aspectRatios)maxAR=max(aspectRatios)print"min/maxfirstcellheight",minH,maxHprint"min/maxfirstcellAR",minAR,maxAR
mat.append(Material.New())mat[0].rgbCol=[0.,0.,1.]mat.append(Material.New())mat[1].rgbCol=[0.,0.5,1.]mat.append(Material.New())mat[2].rgbCol=[0.,1.,1.]
mat.append(Material.New())mat[3].rgbCol=[0.,1.,5.]mat.append(Material.New())mat[4].rgbCol=[0.,1.,0.]mat.append(Material.New())mat[5].rgbCol=[1.,1.,0.]mat.append(Material.New())mat[6].rgbCol=[1.,0.5,0.]mat.append(Material.New())mat[7].rgbCol=[1.,0.,0.]
meH.materials=matmeAR.materials=matmeSkew.materials=mat
obH.setMaterials(mat)obAR.setMaterials(mat)obSkew.setMaterials(mat)
hRange=maxHminHforf0,hinzip(meH.faces,heights):
f0.mat=int(floor(7.999*(hminH)/hRange))ARRange=maxARminARforf0,ARinzip(meAR.faces,aspectRatios):
f0.mat=int(floor(7.999*(ARminAR)/ARRange))forf0,sinzip(meSkew.faces,skews):
ifs>pi/2.0:f0.mat=7else:f0.mat=int(floor(7.999*(2.0*s/pi)))
Blender.Redraw()
defwriteSurfaces(file,m,i):key_index={}foreinm.edges:
key_index[e.key]=e.indexforjinrange(len(m.faces)):
mfi=m.faces[j].indexfile.write('GSURA%x%x+BLEND'%(i,mfi))forkinm.faces[j].edge_keys:
file.write('+L%x%x'%(i,key_index[k]))file.write('\n')ifm.materials!=[]:
mat=m.materials[m.faces[j].mat]ifmat!=None:
file.write('SETA%ssA%x%x\n'%(mat.name,i,mfi))
defwriteBodies(file,m1,m0,i):globalX_Plane,Y_Plane,Z_Plane,X_Location,Y_Location,Z_Location
forjinrange(len(m1.faces)):m1fi=m1.faces[j].index#cutatsymmetryplanesasspecifiedbyGUIif((X_Plane.val==0orm1.faces[j].cent[0]>X_Location.val)and\(Y_Plane.val==0orm1.faces[j].cent[1]>Y_Location.val)and\(Z_Plane.val==0orm1.faces[j].cent[2]>Z_Location.val)):
file.write('bodyB%x%xA%x%xA%x%x\n'%\(i,m1fi,i,m1fi,\i1,m0.faces[j].index))file.write('SETAbodsbB%x%x\n'%\(i,m1fi))
defdisplace(ob,factor):
# Getsubsurfmeshandcalculateitsnormalsme0=Blender.Mesh.New()me0.getFromObject(ob,0,0)me0.calcNormals()
# Createdictionaryofsubsurfverticestofacesvert_faces=dict([(v.index,[])forvinme0.verts])forfinme0.faces:
forvinf.verts:vert_faces[v.index].append(f.index)
# Calculatetargetheightsofselectedsubsurfvertexnormalsheights=[]displacements=[]totalH=0nFaces=0forviinme0.verts.selected():
forfiinvert_faces[vi]:totalH+=sqrt(me0.faces[fi].area)nFaces+=1
hFace=totalH/nFacesforviinme0.verts.selected():
hTotal=0nFaces=0 forfiinvert_faces[vi]:
hTotal+=hFace/abs(me0.verts[vi].no*me0.faces[fi].no)nFaces+=1
hNormal=hTotal/nFacesheights.append(abs(hNormal*factor))
displacements.append(hNormal*factor)
loop=1count=0
# Iteratebasemeshdisplacementsneededtoachievetargetheightswhileloop==1andcount1e8:loop=1count+=1scn.objects.unlink(obCopy)
print"AverageErrorSquare=",sumErrorSquare/len(heights)print"Loopcount=",count
# Applydisplacementstobasemeshme=ob.getData(mesh=1)forvi,dinzip(me.verts.selected(),displacements):
me.verts[vi].co+=me.verts[vi].no*d
scn.objects.active=ob
Combined Use of Blender with OpenFOAMAbstractFuselage StreamliningCombining with tetrahedralsFurther uses and further developmentsConclusionsPython script