## *TEST* ## 'awk' PROGRAM NAME: feinp_generic2stl_awkprogTESTcrod_ctube ## ## in $FEDIR/scripts ## where FEDIR=/apps/nns_com/fea ## ## *** NEEDS TO BE MADE SIMILAR TO 'feinp_generic2stl_awkprog'. ## ######################################################################## ## PURPOSE: FOR TESTING OF REFORMATTING OF 'GENERIC' CROD/CTUBE RECORDS ## into an STL file. ## ## ** This awk-program READs a 'GENERIC' FE input file and ## ** EXTRACTs data from 'generic' GRID and 'generic' ELEMENT records ## ** (CROD & CTUBE only -- for test) into an STL output file. ## ## Each 'generic' ELEMENT record is expected to be a single ## 'free-format' record [fields are space(s)-separated], ## generally of the form ## elname eid pid g1 g2 g3 ... ## where elname is an element name like CBEAM ## eid = element-id (an integer) ## pid = property id, usually (an integer) ## gi's are ids of grid/node points (integers). ######################################################################### ## CALLED BY: TEST SCRIPT 'feinp_nas2stl_nogui_TESTawkprogs' ## in $FEDIR/scripts. ## ## *** To prepare for incorporation into ## 'feinp_generic2stl_awkprog' ## which is called in 'feinp_nas2stl_bygui' ## ## which is a "NASTRAN-to-STL" file creation utility. ## ## *** COMPARE THIS AWK-PROG WITH 'feinp_generic2stl_awkprog'. ## ## The 'generic' ELEMENT-info output file is used as input in ## 'feinp_nas2stl_bygui'. See that script for more info. ## ######################################################################## ## INPUT: GENERIC-FE input filename ## OUTPUT: stdout ######################################################################## ## TEST FILES: Test NASTRAN files with various elements are ## in directory /apps/nns_com/fea/demos_nas2stl. ## Some of these NASTRAN input files are from ## /apps/msc/msc70/msc70/nast/demo ## and /apps/msc/msc70/msc70/nast/tpl. ## Others may be from NNS NASTRAN users. ######################################################################## ## SUPPORTED ELEMENT RECORD TYPES BELOW: ## - CROD/CTUBE ######################################################################## ## MAINTENANCE HISTORY: ## Written by: B.Montandon O06 16Aug2000 'nasinp2stl_TESTcrod_ctube' ## test script+awkprog was created ## based on 'nasinp2stl_awkprog' ## and 'nasinp2stl_bygui' ## in $FEDIR/scripts ## Updated by: B.Montandon O06 13Sep2000 Extracted awkprog from ## 'nasinp2stl_TESTcrod_ctube' ## into this awkprog file. ######################################################################## ## SAMPLE INPUT FOR TESTING: ## (a simple one-rod/one-tube *generic,free-format* input) ## GRID 114 dummy 11.0 1.0 0.0 ## GRID 115 dummy 12.0 1.0 0.0 ## GRID 116 dummy 21.0 1.0 0.0 ## GRID 117 dummy 22.0 1.0 0.0 ## $ ## CROD 21 21 114 115 ## $ CTUBE 29 29 116 117 ## $ BEGIN { printf ("SOLID - FROM NASTRAN INPUT %-65s\n",FILE_IN); DEBUG=0; i=0; jrodtube=0; ## i is a GRID rec counter; ## jbeam is an element rec counter; jbar is an element rec counter. } { ######################################################################### ## REPLACE ADJACENT COMMAS IN NASTRAN RECS (ESP. GRID & element RECS) ## BY TWO COMMAS SEPARATED BY A DUMMY STRING --- ## I.E. IN *FREE-FORMAT* RECS REPLACE SUCCESSIVE COMMAS BY SOMETHING. ######################################################################### # gsub(/,,/,",0,") gsub(/,,/,",dummy,") ########################################################################### ## REPLACE EACH COMMA IN NASTRAN RECS (ESP. GRID & element RECS) BY A BLANK ## --- I.E. IN *FREE-FORMAT* RECS REPLACE EACH COMMA BY A BLANK. ########################################################################### gsub(/,/," ") ########################################################################### ## *GRID*-RECORD PROCESSING SECTION: ## SEE $FEDIR/script/nasinp2freeform_nodeinfo for a more robust ## parsing of GRID records into a *generic, free-format*. ########################################################################### ## LOOK FOR *GRID* IN THE FIRST FIELD. INCREMENT THE GRID-REC COUNT, i. ########################################################################### FLD1CAPS=toupper($1) if ( FLD1CAPS=="GRID" ) {i++ ## EXIT, WITH MSG TO OUTFILE, IF AN ELEMENT REC HAS BEEN ENCOUNTERED. if (j>0) { print "*ERROR: There are ELEMENT recs before GRID recs." print "*ERROR: *ALL* GRID recs must be before *ALL* element recs." exit } ## SEPARATE *SCRUNCHED-TOGETHER* GRID COORDS --- I.E. SEPARATE ## ANY OCCURRENCES OF A MINUS-SIGN IMMEDIATELY FOLLOWING A NUMERIC CHAR. gsub(/0-/,"0 -") gsub(/1-/,"1 -") gsub(/2-/,"2 -") gsub(/3-/,"3 -") gsub(/4-/,"4 -") gsub(/5-/,"5 -") gsub(/6-/,"6 -") gsub(/7-/,"7 -") gsub(/8-/,"8 -") gsub(/9-/,"9 -") ## EXIT, WITH MSG TO OUTFILE, IF A GRID REC HAS LESS THAN 6 FIELDS. if (NF<6) { print "*ERROR: There must be at least 6 fields in GRID recs:" print "*ERROR: String GRID, two integers, and 3 x,y,z coordinates." exit } ####################################### ## STORE THE GRID-ID in the g[.] array. ####################################### g[i]=$2 ################################################################ ## STORE THE 4th,5th,6th FIELDS IN THE gx[.],gy[.],gz[.] arrays. ################################################################ gx[i]=$4; gy[i]=$5; gz[i]=$6 ## *FOR TESTING* -- show the just-captured GRID data: if (DEBUG==1) { print "DEBUG - GRID READ: i="i" g[i]="g[i] print " gx[i]="gx[i]" gy[i]="gy[i]" gz[i]="gz[i] } next } ####################################################################### ## END OF if ( FLD1CAPS=="GRID" ) ## i.e. END OF the *GRID*-RECORD PROCESSING SECTION ####################################################################### ####################################################################### ## *CROD/TUBE*-RECORD PROCESSING SECTION: ####################################################################### ## LOOK FOR *CBEAM* or *CBAR* IN THE FIRST FIELD. ## INCREMENT THE ELEMENT-REC COUNT, jrodtube. ####################################################################### # FLD1CAPS=toupper($1) ## DONE ABOVE. if ( FLD1CAPS=="CROD" || FLD1CAPS=="crod" || \ FLD1CAPS=="CTUBE" || FLD1CAPS=="ctube") {jrodtube++ ################################################################ ## STORE THE *CROD/TUBE* ELEMENT-ID IN THE *e* VAR. ## STORE THE 4th, 5th FIELDS (two grid ids) IN THE ## g1, g2 VARS. ################################################################ e=$2; g1=$4; g2=$5; ## *FOR TESTING* -- show the just-captured *CROD/TUBE* data: if (DEBUG==1) { print "DEBUG - ELEMENT READ: j=element-count="j" e=elid="e print " g1=G1="g1" g2=G2="g2 } ################################################################### ## binary-SEARCH THE g[.] GRID-ID array FOR A MATCH, g[k], WITH g1. ## FOR A MATCH, SET x1,y1,z1 to gx[k],gy[k],gz[k]. ################################################################### k=binarySearch(g, i, g1) if ( k==-1 ) { print "*ERROR: NO GRID COORDS FOUND for GRID-id "g1" of CROD/TUBE-id "e"." next } else { x1=gx[k] ; y1=gy[k] ; z1=gz[k] ## *FOR TESTING* -- show the just-captured *CROD/TUBE* data: if (DEBUG==1) { print "FOUND g1="g1": at k="k" g[k]="g[k]" whose xyz coordinates" print "we use to set x1="x1" y1="y1" z1="z1 } } ################################################################### ## binary-SEARCH THE g[.] GRID-ID array FOR A MATCH, g[k], WITH g2. ## FOR A MATCH, SET x2,y2,z2 to gx[k],gy[k],gz[k]. ################################################################### k=binarySearch(g, i, g2) if ( k==-1 ) { print "*ERROR: NO GRID COORDS FOUND for GRID-id "g2" of CROD/TUBEx-id "e"." next } else { x2=gx[k] ; y2=gy[k] ; z2=gz[k] ## *FOR TESTING* -- show the just-captured *CROD/TUBE* data: if (DEBUG==1) { print "FOUND g2="g2": at k="k" g[k]="g[k]" whose xyz coordinates" print "we use to set x2="x2" y2="y2" z2="z2 } } ################################################################ ## STORE THE COMPONENTS OF THE G1->G2 VECTOR. ################################################################ g1g2x=x2-x1 g1g2y=y2-y1 g1g2z=z2-z1 ################################################################ ## GET THEIR ABSOLUTE VALUES. ################################################################ absg1g2x=g1g2x if (g1g2x<0) {absg1g2x=-g1g2x} absg1g2y=g1g2y if (g1g2y<0) {absg1g2y=-g1g2y} absg1g2z=g1g2z if (g1g2z<0) {absg1g2z=-g1g2z} ################################################################ ## FIND THE AXIS ON WHICH THE PROJECTION OF THE G1->G2 VECTOR ## IS SHORTEST. i.e. find the axis to which g1g2 is nearest ## being perpendicular. ################################################################ NEARPERP="X"; npx=1; npy=0; npz=0 if (absg1g2y < absg1g2x) {NEARPERP="Y"; npx=0; npy=1; npz=0} if (NEARPERP=="X") { if (absg1g2z < absg1g2x) {NEARPERP="Z"; npx=0; npy=0; npz=1} } else { if (absg1g2z < absg1g2y) {NEARPERP="Z"; npx=0; npy=0; npz=1} } ################################################################ ## FIND THE LENGTH OF THE ROD. ## AND SET A *radius* VALUE to 1/20th OF THE ROD LENGTH. ################################################################ len=sqrt( (g1g2x)^2 + (g1g2y)^2 + (g1g2z)^2 ) rad=len/40.0 # rad=len/5.0 ## FOR TESTING (for good visibility) ################################################################ ## CALCULATE A NORMAL TO THE ROD AND THE NEAR-PERP VECTOR ## (using pts 1,2,1+np) of THE CURRENT *CROD/TUBE* ELEMENT. ## It is in the z-direction of the rod local coordinate system. ################################################################ # ax=x2-x1; ay=y2-y1; az=z2-z1 ax=g1g2x; ay=g1g2y; az=g1g2z # bx=(x1+npx)-x1; by=(y1+npy)-y1; bz=(z1+npz)-z1 bx=npx; by=npy; bz=npz cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################ ## NORMALIZE THE COMPONENTS OF THE NORMAL TO THE ROD & NEAR-PERP ## which is the direction1 of a rod local coordinate system. ################################################################ norm1len=sqrt( (cx)^2 + (cy)^2 + (cz)^2 ) norm1x=cx/norm1len norm1y=cy/norm1len norm1z=cz/norm1len ################################################################ ## CALCULATE A NORMAL TO THE ROD AND ITS 'direction1' normal. ## (using pts 1,2,1+c) of THE CURRENT *CROD/TUBE* ELEMENT. ## It is in the y-direction of the rod local coordinate system. ################################################################ # ax=x2-x1; ay=y2-y1; az=z2-z1 ax=g1g2x; ay=g1g2y; az=g1g2z # bx=(x1+cx)-x1; by=(y1+cy)-y1; bz=(z1+cz)-z1 bx=cx; by=cy; bz=cz cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################### ## NORMALIZE THE COMPONENTS OF THIS direction2-NORMAL TO THE ROD. ################################################################### norm2len=sqrt( (cx)^2 + (cy)^2 + (cz)^2 ) norm2x=cx/norm2len norm2y=cy/norm2len norm2z=cz/norm2len ################################################################ ## TO ROUGHLY EMULATE THE ROD, WE NOW MAKE TWO INTERSECTING ## RECTANGLES WHOSE INTERSECTION IS THE ROD, VECTOR G1->G2. ################################################################ ################################################################ ## *MAKE RECTANGLE1* (ACTUALLY TWO LONG THIN TRIANGLES) ## IN THE PLANE OF THE ROD AND THE direction1 normal --- ## by making four points offset +/-rad in direction1. ################################################################ ## Make points a= (xa,ya,za) = (x1,y1,z1) - rad in dir1 ## b= (xb,yb,zb) = (x2,y2,z2) - rad in dir1 ## c= (xc,yc,zc) = (x2,y2,z2) + rad in dir1 ## d= (xd,yd,zd) = (x1,y1,z1) + rad in dir1. ## Make the two triangles from (a,b,c) and from (a,c,d). ################################################################ xa=x1-(rad*norm1x) ya=y1-(rad*norm1y) za=z1-(rad*norm1z) xb=x2-(rad*norm1x) yb=y2-(rad*norm1y) zb=z2-(rad*norm1z) xc=x2+(rad*norm1x) yc=y2+(rad*norm1y) zc=z2+(rad*norm1z) xd=x1+(rad*norm1x) yd=y1+(rad*norm1y) zd=z1+(rad*norm1z) ################################################################ ## CALCULATE THE FACET NORMAL OF TRIANGLE#1 (using pts a,b,c) ## of RECTANGLE#1 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ ax=xb-xa; ay=yb-ya; az=zb-za bx=xc-xa; by=yc-ya; bz=zc-za cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################ ## OUTPUT THE SET OF STL RECS CORRESPONDING TO TRIANGLE#1 ## of RECTANGLE#1 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ print "facet normal "cx" "cy" "cz print " outer loop" print " vertex "xa" "ya" "za print " vertex "xb" "yb" "zb print " vertex "xc" "yc" "zc print " endloop" print "endfacet" ################################################################ ## CALCULATE THE FACET NORMAL OF TRIANGLE#2 (using pts a,c,d) ## of RECTANGLE#1 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ ax=xc-xa; ay=yc-ya; az=zc-za bx=xd-xa; by=yd-ya; bz=zd-za cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################ ## OUTPUT THE SET OF STL RECS CORRESPONDING TO TRIANGLE#2 ## of RECTANGLE#1 THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ print "facet normal "cx" "cy" "cz print " outer loop" print " vertex "xa" "ya" "za print " vertex "xc" "yc" "zc print " vertex "xd" "yd" "zd print " endloop" print "endfacet" ################################################################ ## *MAKE RECTANGLE2* (ACTUALLY TWO LONG THIN TRIANGLES) ## IN THE PLANE OF THE ROD AND THE direction2 normal --- ## by making four points offset +/-rad in direction1. ################################################################ ## Make points a= (xa,ya,za) = (x1,y1,z1) - rad in dir2 ## b= (xb,yb,zb) = (x2,y2,z2) - rad in dir2 ## c= (xc,yc,zc) = (x2,y2,z2) + rad in dir2 ## d= (xd,yd,zd) = (x1,y1,z1) + rad in dir2. ## Make the two triangles from (a,b,c) and from (a,c,d). ################################################################ xa=x1-(rad*norm2x) ya=y1-(rad*norm2y) za=z1-(rad*norm2z) xb=x2-(rad*norm2x) yb=y2-(rad*norm2y) zb=z2-(rad*norm2z) xc=x2+(rad*norm2x) yc=y2+(rad*norm2y) zc=z2+(rad*norm2z) xd=x1+(rad*norm2x) yd=y1+(rad*norm2y) zd=z1+(rad*norm2z) ################################################################ ## CALCULATE THE FACET NORMAL OF TRIANGLE#1 (using pts a,b,c) ## of RECTANGLE#2 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ ax=xb-xa; ay=yb-ya; az=zb-za bx=xc-xa; by=yc-ya; bz=zc-za cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################ ## OUTPUT THE SET OF STL RECS CORRESPONDING TO TRIANGLE#1 ## of RECTANGLE#2 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ print "facet normal "cx" "cy" "cz print " outer loop" print " vertex "xa" "ya" "za print " vertex "xb" "yb" "zb print " vertex "xc" "yc" "zc print " endloop" print "endfacet" ################################################################ ## CALCULATE THE FACET NORMAL OF TRIANGLE#2 (using pts a,c,d) ## of RECTANGLE#2 of THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ ax=xc-xa; ay=yc-ya; az=zc-za bx=xd-xa; by=yd-ya; bz=zd-za cx=ay*bz-az*by cy=az*bx-ax*bz cz=ax*by-ay*bx ################################################################ ## OUTPUT THE SET OF STL RECS CORRESPONDING TO TRIANGLE#2 ## of RECTANGLE#2 THE CURRENT *CROD/TUBE* ELEMENT. ################################################################ print "facet normal "cx" "cy" "cz print " outer loop" print " vertex "xa" "ya" "za print " vertex "xc" "yc" "zc print " vertex "xd" "yd" "zd print " endloop" print "endfacet" next } ####################################################################### ## END OF if ( FLD1CAPS=="CROD" || ... || FLD1CAPS=="CTUBE" || ... ) ## i.e. END OF the *CROD/TUBE*-RECORD PROCESSING SECTION ####################################################################### } END { j=jrodtube if ( j==0 ) { print "*ERROR: No CROD or CTUBE elements were found in the input file." } printf ("ENDSOLID - 4 x %12d triangles generated from %12d CROD+CTUBE elements.\n",jrodtube,jrodtube) } ## START OF function *binarySearch* ######################################################################## ## NOTE: *function* statement is not recognized within ## awk BEGIN, *body=main*, and END sections. ######################################################################## ## ## DESCRIPTION OF A BINARY SEARCH ALGORITHM ## ## from http://www.ics.hawaii.edu/~yongsi/ics665/principle.html ## ## We have a sorted array A and a key K. Our task is to determine whether ## the key K is present in this array A. If we do find A[i] = K, ## return the array index i. Otherwise, return i = -1. ## ## The search Binary search works in the following way: ## ## 1. Compare K with the middle value (M) in remaiding part of array A. ## 2. If K = M, we are done. ## 3. If K < M, we continue our search to the lower end of array A and ## entirely ignore the other end. ## 4. If K > M, we continue, but confine ourselves to the higher end. ## ######################################################################## ## EXAMPLE: A = {1 3 4 6 8 9 11}. K = 4. ## ## M = 6 ## Compare K with 6. It is smaller. Continue search with A = 1 3 4. ## M = 3 ## Compare K with 3. It is bigger. Continue search with A = 3 4. (4 only?) ## M = 4 ## Compare K with 4. It is equal. We are done, we found K in A. ######################################################################## ## ## The algorithm (C-like) for Binary Search is listed below: ######################################################################## function binarySearch(ARRAY,ARRAY_SIZE,KEY, low,high,middle) { low=1 high=ARRAY_SIZE while ( low <= high ) { middle = int( (low+high)/2 ) ## FOR TESTING: # print "low= "low" high="high" middle="middle if ( KEY == ARRAY[ middle ] ) { return middle } else if ( KEY < ARRAY[ middle ] ) { high = middle - 1 } else { low = middle + 1 } } return -1 } ## END OF awk program ' ######################################################################### ## ADD SOME HOW/WHEN-GENERATED INFO TO THE END OF THE STL FILE. ######################################################################### ## echo "\ ## ENDSOLID - created via $FEDIR/scripts/feinp_generic2stl_awkprogTESTcrod_ctube ## ENDSOLID - `date '+%Y %b %d %a %T%p %Z'` on host $THISHOST ## ENDSOLID - Generated via 'generic,free-format' FE file $GENERIC_FE_FILE ## ENDSOLID - which was built from sorting the nodes file $NODESFILE ## ENDSOLID - and attaching the elements file $ELSFILE ## ENDSOLID - OUTPUT IS IN $OUTFILE ## " >> $OUTFILE