blender with open foam

25
Combined Use of Blender with OpenFOAM G. Douglas Baldwin Abstract Blender from blender.org contains a powerful, widely accepted, open source, surface mesh generation tool that was developed for the digital arts community.  Furthermore, Blender includes a robust and well documented Python application programming interface (API) which facilitates the development of user tools for mesh manipulation, layered manifolds, and import/export. The author developed a Python script and technique for manipulating and exporting Blender objects into CalculiX for hexagonal grid generation, which are then exported into OpenFOAM format.  The benefit of this approach is that manifolds allow absolute control of maximum cell growth rates from the boundary layer out to the edge of the computational domain, while also directing the path of stacked hexagonal cells to avoid skew.  This technique was used to streamline an aircraft fuselage using a pure hexagonal grid with OpenFOAM, and then import the grid into Scientific Simulations NSU3D for authoritative drag analysis. The technique is ripe with possibilities for developing meshes for many classes of simulations. Highlights of the hexahedral grids used in the aircraft streamlining effort will be shown and discussed below, followed by an illustrative grid that combines hexahedral cells at the boundary layer with tetrahedral cells in the bulk flow.  This paper will conclude with a copy of the Python script and a discussion of how it may be further developed.  The author has no intention at this time of leading further development of this script due to other demands on his time.  It is hoped that others too will find value in this approach and perhaps carry it forward. Fuselage Streamlining In general, Blender meshes are comprised of both triangles and quadrilaterals.  For the fuselage streamlining project, it was decided to use exclusively quadrilaterals for the surface.  Illustrations of the final surface are provided below.  Notice the pink vertices.  The only verticies defined by the user are those shown in pink.  All of the other verticies are automatically generated by Blender when the subsurf modifier is applied to the object.  The strength of the lines connecting any two pink verticies is controlled by the crease feature.  It is not the purpose of this paper to provide a tutorial on Blender, subsurf, and crease.  Many excellent Blender tutorials are readily available on the internet.  Notice however the technique of having evenly space pink verticies to maintain a relatively consistent grid size. The close-up illustration below reveals better the individual quadrilateral elements automatically generated by the Blender subsurf modifier.  Also note the two different colored Blender materials used on the object.  These Blender materials eventually translate to OpenFOAM patches.  The decision to have two patches for this fuselage model is unrelated to the present topic and will not be discussed further to avoid a confusing digression. Presented at the 3 rd  OpenFOAM Workshop, Milan, Italy, 10-11 July 2008.

Upload: styleworker

Post on 02-Oct-2015

26 views

Category:

Documents


2 download

DESCRIPTION

Blender With Open Foam

TRANSCRIPT

  • 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