# Pointwise V16 Glyph Script for generating grids around airfoils. # Airfoils are generated in DreeseCODE's DesignFOIL. # # Written by: Pointwise, Inc. (glyph@pointwise.com) # # Assumptions: # If only one curve in file, airfoil has closed TE. # If two curves in file, second curve closes TE. # Grid is in XZ plane. # O-grid topology # Outer boundary shape is undefined (is defined by the grid method). # Units are in inches. # # Initialization package require PWI_Glyph 2.0 pw::Application reset # Directory from which script is run set cwd [file dirname [info script]] # Segment file from DesignFOIL with airfoil shape # set fname "airfoils/CIRCLE_CLOSED_TE.dat" # set fname "airfoils/ELLIPSE_12PERCENT_CLOSED_TE.dat" # set fname "airfoils/FX60100_CLOSED_TE.dat" #FAILS NOT CLOSED set fname "airfoils/JOUKOWSKY_GENERIC_CLOSED_TE.dat" # set fname "airfoils/NACA0015_OPEN_TE.dat" # set fname "airfoils/NACA_23012_OPEN_TE.dat" #set fname "airfoils/NACA_65215_CLOSED_TE.dat" set fname "NACA23012_gridgen.dat" # USER PARAMETERS # Number of grid points around airfoil set af_dim 101 # Minimum grid spacing as percentage of chord set min_ds_pct 0.2 # First step size as percentage of minimum grid spacing set ds1_pct 20.0 # Outer boundary distance as percentage of chord set ff_pct 500.0 # Maximum number of extrusion steps set num_steps 101 # Minimum number of grids points on a blunt TE set min_te_pts 5 # CFD Solver # set cfd_solver "PLOT3D" # set cfd_solver "CFD++" # set cfd_solver "CGNS-STRUCT" # set cfd_solver "COBALT" set cfd_solver "FLUENT" # set cfd_solver "STAR-CCM+" # set cfd_solver "WIND" # CFD solver file # Note: Solvers automatically add extensions; others don't. if { $cfd_solver == "CFD++" } { set solver_file "CFD++_airfoil" } elseif { $cfd_solver == "CGNS-STRUCT" } { set solver_file "CGNS_airfoil.cgns" } elseif { $cfd_solver == "COBALT" } { set solver_file "COBALT_airfoil.inp" } elseif { $cfd_solver == "FLUENT" } { set solver_file "FLUENT_airfoil.cas" } elseif { $cfd_solver == "STAR-CCM+" } { set solver_file "STAR-CCM+_airfoil.inp" } elseif { $cfd_solver == "WIND" } { set solver_file "WIND_airfoil.cgd" } else { set cfd_solver "PLOT3D" set solver_file "PLOT3D_airfoil.x" } # Import the database. set DB [pw::Database import [file join $cwd $fname]] set N_db [llength $DB] if { $N_db == 1 } { # The airfoil consists of a single curve. set topo 1 } elseif { $N_db == 2 } { # The airfoil has two curves; second closes TE. set topo 2 } else { puts "BUG: Wrong number of entities in file." } set af_db [lindex $DB 0] if { $topo == 2 } { set te_db [lindex $DB 1] } # Airfoil is in XZ plane; reorient the view accordingly. pw::Display resetView +Y $af_db setRenderAttribute RenderMode Isolines # Find the LE (min X) and TE (max X) points on the airfoil. set af_seg [$af_db getSegment 1] set I_min 1 set I_max [$af_seg getPointCount] set LE_i [expr $I_min - 1] set LE_pt [list 9999.0 0 0] set TE_i [expr $I_max + 1] set TE_pt [list -9999.0 0 0] for {set i $I_min} {$i <= $I_max} {incr i} { set pt [$af_seg getXYZ -control $i] if { [lindex $pt 0] < [lindex $LE_pt 0] } { set LE_i $i set LE_pt $pt } if { [lindex $pt 0] > [lindex $TE_pt 0] } { set TE_i $i set TE_pt $pt } } # Compute chord as distance between LE and TE points. set dx [expr [lindex $TE_pt 0] - [lindex $LE_pt 0]] set dy [expr [lindex $TE_pt 1] - [lindex $LE_pt 1]] set dz [expr [lindex $TE_pt 2] - [lindex $LE_pt 2]] set D2 [expr $dx * $dx + $dy * $dy + $dz * $dz] set chord [expr sqrt($D2)] # Create a connector on the airfoil. set seg_af [pw::SegmentTrim create] set u 0 $seg_af addPoint [list $u 0 $af_db] set u 1 $seg_af addPoint [list $u 0 $af_db] set af_con [pw::Connector create] $af_con addSegment $seg_af $af_con setDimension $af_dim # Compute min. grid spacing relative to chord. set chord [expr [$af_con getLength -arc 1] / 2] set min_ds [expr $chord * $min_ds_pct / 100 ] if { $topo == 2 } { # Create and dimension a connector on the blunt TE. set seg_te [pw::SegmentTrim create] $seg_te addPoint [list 0 0 $te_db] $seg_te addPoint [list 1 0 $te_db] set te_con [pw::Connector create] $te_con addSegment $seg_te set te_length [$te_con getLength -arc 1] set te_dim [expr int($te_length / $min_ds) + 1] $te_con setDimension $te_dim if { $te_dim < $min_te_pts } { # if the number of grid points on the TE is less than the minimum # redimension to the minimum and recompute the minimum spacing set te_dim $min_te_pts $te_con setDimension $te_dim set min_ds [expr $te_length / 2] } } # Distribute grid points on the airfoil. # Cluster at the leading and trailing edges. set dist_af_con [pw::DistributionShape create] $dist_af_con setBeginSpacing $min_ds $dist_af_con setEndSpacing $min_ds $af_con setDistribution 1 $dist_af_con set LE_loc [expr [$af_con getLength -closest $LE_pt] / [$af_con getTotalLength]] $af_con addBreakPoint -arc $LE_loc $af_con setBreakPointSpacing 1 $min_ds # Extrude a domain from the connectors. # Set a limit on the farfield height. # First step size is a fraction of TE spacing. set ff_height [expr $chord * $ff_pct / 100] set ds1 [expr $min_ds * $ds1_pct / 100] if { $topo == 1 } { set af_cons [list $af_con] } else { set af_cons [list $af_con $te_con] } set af_edge [pw::Edge createFromConnectors -single $af_cons] set af_dom [pw::DomainStructured create] $af_dom addEdge $af_edge set myExtrusion [pw::Application begin ExtrusionSolver $af_dom] $af_dom setExtrusionSolverAttribute NormalInitialStepSize $ds1 $af_dom setExtrusionSolverAttribute NormalMarchingMode Plane $af_dom setExtrusionSolverAttribute NormalMarchingVector {0 1 0} $af_dom setExtrusionSolverAttribute NormalKinseyBarthSmoothing 3 $af_dom setExtrusionSolverAttribute StopAtHeight $ff_height $myExtrusion run $num_steps $myExtrusion end if { $cfd_solver == "PLOT3D" } { # Export a PLOT3D file (grid only, no BCs). pw::Grid export -type PLOT3D $af_dom [file join $cwd $solver_file] } else { # Export CFD solver file(s). (Some solvers write more than 1 file.) # eval "gg::aswExport [file join $cwd $solver_file] $options" } puts "Wrote file $solver_file" # # DISCLAIMER: # TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, POINTWISE DISCLAIMS # ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED # TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE, WITH REGARD TO THIS SCRIPT. TO THE MAXIMUM EXTENT PERMITTED # BY APPLICABLE LAW, IN NO EVENT SHALL POINTWISE BE LIABLE TO ANY PARTY # FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES # WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF # BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE # USE OF OR INABILITY TO USE THIS SCRIPT EVEN IF POINTWISE HAS BEEN # ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND REGARDLESS OF THE # FAULT OR NEGLIGENCE OF POINTWISE. #