├── src ├── .DS_Store ├── build_macarm.sh ├── build_winx64.cmd ├── mod_fg.f ├── mod_troat.f ├── mod_jack.f ├── mod_prop.f ├── mod_gg.f ├── plate.f ├── mod_coef.f ├── mod_corr.f ├── heat.f ├── mod_httr.f ├── mod_cline.f ├── kinddefine.f ├── mod_param.f ├── mod_coord.f ├── mod_contr.f ├── mod_work.f ├── input.txt ├── fmv.f ├── toric.f ├── conic.f ├── sorce.f ├── scond.f ├── xyz.f ├── twixt.f ├── license.txt ├── fvdge.f ├── cubic.f ├── splind.f ├── ofeld.f ├── neo.f ├── trans.f ├── main.f ├── perfc.f ├── bound.f └── axial.f.old ├── assets ├── Contours.png ├── Flow_Angles.png ├── Flow_Angles_At_Throat.png ├── Nozzle_Characteristics.png ├── Throat_Characteristics.png ├── Boundary_Layer_Thickness.png └── Boundary_Layer_Temperature.png ├── conturpy ├── bin │ ├── contur.exe │ └── contur-macarm64 ├── doc │ └── Example.pdf ├── __init__.py ├── create_report.py ├── run_contur.py ├── plot_results.py ├── create_input_cards.py └── read_output.py ├── Example.ipynb ├── .gitignore └── README.md /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /assets/Contours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Contours.png -------------------------------------------------------------------------------- /assets/Flow_Angles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Flow_Angles.png -------------------------------------------------------------------------------- /conturpy/bin/contur.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/conturpy/bin/contur.exe -------------------------------------------------------------------------------- /conturpy/doc/Example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/conturpy/doc/Example.pdf -------------------------------------------------------------------------------- /conturpy/bin/contur-macarm64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/conturpy/bin/contur-macarm64 -------------------------------------------------------------------------------- /src/build_macarm.sh: -------------------------------------------------------------------------------- 1 | gfortran -O2 -std=legacy -J ../build/macarm64/ -o ../build/macarm64/contur_macarm64 *.f -------------------------------------------------------------------------------- /assets/Flow_Angles_At_Throat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Flow_Angles_At_Throat.png -------------------------------------------------------------------------------- /assets/Nozzle_Characteristics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Nozzle_Characteristics.png -------------------------------------------------------------------------------- /assets/Throat_Characteristics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Throat_Characteristics.png -------------------------------------------------------------------------------- /assets/Boundary_Layer_Thickness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Boundary_Layer_Thickness.png -------------------------------------------------------------------------------- /assets/Boundary_Layer_Temperature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noahess/conturpy/HEAD/assets/Boundary_Layer_Temperature.png -------------------------------------------------------------------------------- /src/build_winx64.cmd: -------------------------------------------------------------------------------- 1 | call "%ONEAPI_ROOT%\setvars.bat" 2 | ifort -O2 -f77rtl -o ..\build\win64\contur.exe *.f 3 | del *.mod 4 | del *.obj -------------------------------------------------------------------------------- /src/mod_fg.f: -------------------------------------------------------------------------------- 1 | module fg 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),save :: gc,gd,ge,gf,gh,gi,ha,hb,hc,he 5 | end module fg 6 | 7 | -------------------------------------------------------------------------------- /src/mod_troat.f: -------------------------------------------------------------------------------- 1 | module troat 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),dimension(6,51),save :: fc 5 | end module troat 6 | 7 | -------------------------------------------------------------------------------- /src/mod_jack.f: -------------------------------------------------------------------------------- 1 | module jack 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),dimension(30),save :: sj,xj,yj,aj 5 | end module jack 6 | 7 | -------------------------------------------------------------------------------- /src/mod_prop.f: -------------------------------------------------------------------------------- 1 | module prop 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),save :: ar,zo,ro,visc,vism,sfoa,xbl,conv 5 | end module prop 6 | -------------------------------------------------------------------------------- /src/mod_gg.f: -------------------------------------------------------------------------------- 1 | module gg 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),save :: gam,gm,g1,g2,g3,g4,g5,g6,g7,g8,g9,ga,rga,qt 5 | end module gg 6 | -------------------------------------------------------------------------------- /src/plate.f: -------------------------------------------------------------------------------- 1 | subroutine plate 2 | ! dummy to be modified for special calculations for flexible plate 3 | use jack 4 | implicit none 5 | end subroutine plate 6 | -------------------------------------------------------------------------------- /src/mod_coef.f: -------------------------------------------------------------------------------- 1 | module coef 2 | use kinddefine 3 | implicit none 4 | integer(kind=K4),save :: ne 5 | real(kind=K8),dimension(5,200),save :: e 6 | end module coef 7 | 8 | -------------------------------------------------------------------------------- /src/mod_corr.f: -------------------------------------------------------------------------------- 1 | module corr 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),dimension(200),save :: dla,rco,dax,drx,sl 5 | real(kind=K8),save :: dr2 6 | end module corr 7 | -------------------------------------------------------------------------------- /src/heat.f: -------------------------------------------------------------------------------- 1 | subroutine heat 2 | ! dummy to be modified for special calculations of heat transfer 3 | use httr, only:qfun,qfunw 4 | implicit none 5 | qfunw=qfun 6 | end subroutine heat 7 | -------------------------------------------------------------------------------- /src/mod_httr.f: -------------------------------------------------------------------------------- 1 | module httr 2 | use kinddefine 3 | implicit none 4 | integer(kind=K4),save :: ipq,ij,iv,iw 5 | real(kind=K8),save :: hair,taw,twq,tw,twat,qfun,qfunw 6 | end module httr 7 | 8 | -------------------------------------------------------------------------------- /src/mod_cline.f: -------------------------------------------------------------------------------- 1 | module cline 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),dimension(5,150),save :: axis,taxi 5 | real(kind=K8),save :: wip,x1,frip,zonk,seo,cse 6 | end module cline 7 | 8 | -------------------------------------------------------------------------------- /src/kinddefine.f: -------------------------------------------------------------------------------- 1 | module kinddefine 2 | implicit none 3 | integer, parameter :: K3 = SELECTED_CHAR_KIND("DEFAULT") 4 | integer, parameter :: K4 = SELECTED_INT_KIND( 9 ) 5 | integer, parameter :: K8 = SELECTED_REAL_KIND( 15, 307 ) 6 | end module kinddefine 7 | -------------------------------------------------------------------------------- /src/mod_param.f: -------------------------------------------------------------------------------- 1 | module param 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),save :: etad,rc,amach,bmach,cmach,emach,gmach,frc,sf 5 | real(kind=K8),save :: wwo,wwop,qm,we,cbet,xe,eta,epsi,bpsi,xo,yo 6 | real(kind=K8),save :: rrc,sdo,xb,xc,ah,pp,se,tye,xa 7 | end module param 8 | 9 | -------------------------------------------------------------------------------- /src/mod_coord.f: -------------------------------------------------------------------------------- 1 | module coord 2 | use kinddefine 3 | implicit none 4 | real(kind=K8),dimension(200),save :: s,fs,waltan,sd 5 | real(kind=K8),dimension(200),save :: wmn,ttr,dmdx,spr,bta 6 | real(kind=K8),dimension(200),save :: dpx,secd,sref 7 | real(kind=K8),save :: xbin,xcin,gma,gmb,gmc,gmd 8 | end module coord 9 | 10 | -------------------------------------------------------------------------------- /src/mod_contr.f: -------------------------------------------------------------------------------- 1 | module contr 2 | use kinddefine 3 | implicit none 4 | character(len=4,kind=K3),dimension(3) :: itle 5 | character(len=4,kind=K3) :: mc 6 | integer(kind=K4),save :: ie,lr,it,jb,jq,jx,kat,kbl,king,ko,lv 7 | integer(kind=K4),save :: nocon,in,mcp,ip,iq,ise,jc,m,mp,mq,n,np 8 | integer(kind=K4),save :: nf,nut,nr,lc,md,mf,mt,nd,nt 9 | end module contr 10 | 11 | -------------------------------------------------------------------------------- /src/mod_work.f: -------------------------------------------------------------------------------- 1 | module work 2 | use kinddefine 3 | implicit none 4 | integer(kind=K8),save :: noup,npct,nodo 5 | real(kind=K8),dimension(5,200),save :: wall 6 | real(kind=K8),dimension(200),save :: wax,way,wan 7 | real(kind=K8),dimension(5,150),save :: a,b,fclast 8 | real(kind=K8),dimension(400),save :: e,z,x,y,yst 9 | real(kind=K8),dimension(250),save :: wtn 10 | end module work 11 | 12 | -------------------------------------------------------------------------------- /src/input.txt: -------------------------------------------------------------------------------- 1 | Mach 6.5 0 2 | 1.4 1716.563 1. 0.896 2.2696E-08198.72 0 1000. 3 | 60. 6. 0 0 6.5 0.13 60. 0 4 | 61 41 0 10 0 61 69 -61 0 0 1 0 1 0 -45 18 5 | 50 85 50 6 | 70. 1000. 540. 540. 0.38 0 0 0 1 5 7 | 1000. 50. 80. 0.1 0 0 0 0 8 | -------------------------------------------------------------------------------- /conturpy/__init__.py: -------------------------------------------------------------------------------- 1 | from .create_input_cards import ConturSettings 2 | from .read_output import ConturResult 3 | from .run_contur import ConturApplication 4 | from .plot_results import gen_bl_thickness_plot, gen_bl_temperature_plot, gen_noz_characteristics, \ 5 | gen_throat_characteristics, gen_contours, gen_flow_angles, gen_flow_angles_throat 6 | from .create_report import save_all 7 | 8 | __all__ = ["ConturSettings", "ConturResult", "ConturApplication", 9 | "gen_bl_temperature_plot", "gen_bl_thickness_plot", "gen_noz_characteristics", "gen_throat_characteristics", 10 | "gen_contours", "gen_flow_angles", "gen_flow_angles_throat", "save_all"] 11 | -------------------------------------------------------------------------------- /src/fmv.f: -------------------------------------------------------------------------------- 1 | function fmv(pma) 2 | ! to obtain mach number from prandtl meyer angle 3 | use kinddefine 4 | use gg, only:g2,g7,g9 5 | ! 6 | implicit none 7 | integer(kind=K4) :: i 8 | real(kind=K8) :: ang,fmv,one,rem,third,vm,z,zbet 9 | real(kind=K8),intent(in) :: pma 10 | one=1.d+0 11 | third=one/3.d+0 12 | vm=(dasin(one)*(pma/(g2-one))**2)**third 13 | z=one+.895d+0*((g7*(g2-one))**2)**third*dtan(vm) 14 | do i=1,100 15 | zbet=dsqrt(z*z-one) 16 | ang=g2*datan(zbet/g2)-datan(zbet) 17 | rem=(ang-pma)*z*(z*z+g9)/g9/zbet 18 | if (dabs(rem) .lt. 1.d-10) goto 2 19 | z=z-rem 20 | enddo 21 | 2 fmv=z-rem 22 | end function fmv 23 | -------------------------------------------------------------------------------- /src/toric.f: -------------------------------------------------------------------------------- 1 | function toric(wip,se) 2 | ! to obtain throat radius of curvature from velocity gradient 3 | use kinddefine 4 | use fg, only:gc,gd,ge,gf 5 | use gg, only:gam,g7,qt 6 | implicit none 7 | real(kind=K8) :: ie,ff,fiv,fp,fw,one,thr,tk,toric,tr2,trr 8 | real(kind=K8),intent(in) :: se,wip 9 | data one/1.d+0/,thr/3.d+0/,fiv/5.d+0/ 10 | ie=one/qt-one 11 | fw=wip*se*dsqrt(qt*(gam+one)) 12 | trr=fw*(one+(gc+(thr*gc**2-gd)*fw**2)*fw**2) 13 | 1 tr2=trr**2 14 | tk=(one-g7*(one+(ge+gf*tr2)*tr2)*tr2**2/(45.d+0+3*ie))**qt 15 | ff=fw/tk-trr*(one-tr2*(gc-gd*tr2)) 16 | fp=one-tr2*(thr*gc-fiv*gd*tr2) 17 | trr=trr+ff/fp 18 | if(dabs(ff).gt.1.d-1) go to 1 19 | toric=one/trr**2 20 | end function toric 21 | -------------------------------------------------------------------------------- /src/conic.f: -------------------------------------------------------------------------------- 1 | subroutine conic(xm,b) 2 | ! to obtain mach number derivatives in radial flow 3 | use kinddefine 4 | use gg, only:g5,g6,g8,ga,qt 5 | implicit none 6 | real(kind=K8),dimension(4),intent(out) :: b 7 | real(kind=K8),intent(in) :: xm 8 | real(kind=K8) :: area,bmm,c2,c4,cmm,dmm,four,one,thr,two 9 | real(kind=K8) :: xmm,xmm1,xmm2 10 | data one/1.d+0/,two/2.d+0/,thr/3.d+0/,four/4.d+0/ 11 | xmm=xm*xm 12 | xmm1=xmm-one 13 | xmm2=xmm1**2 14 | bmm=one+g8*xmm 15 | area=(g6+g5*xmm)**ga/xm 16 | b(1)=area**qt 17 | b(2)=xm*bmm/qt/xmm1/b(1) 18 | c2=two-(one+thr*g8)/qt 19 | c4=g8/qt-one 20 | cmm=xmm*(c2+xmm*c4)-one-one/qt 21 | b(3)=b(2)*cmm/xmm2/b(1) 22 | dmm=(four*c4*xmm+two*c2)/cmm-four/xmm1 23 | b(4)=b(3)*(b(3)/b(2)+xm*b(2)*dmm-one/b(1)) 24 | end subroutine conic 25 | -------------------------------------------------------------------------------- /src/sorce.f: -------------------------------------------------------------------------------- 1 | subroutine sorce(w,b) 2 | ! to obtain velocity derivatives in radial flow 3 | use kinddefine 4 | use gg, only:g1,g7,g9,qt 5 | implicit none 6 | real(kind=K8) :: al,area,axw,aww,c2,c4,cww,dww,four,one,thr,two,ww 7 | real(kind=K8) :: ww1 8 | real(kind=K8),intent(in) :: w 9 | real(kind=K8),dimension(4),intent(out) :: b 10 | data one/1.d+0/,two/2.d+0/,thr/3.d+0/,four/4.d+0/ 11 | ww=w*w 12 | al=g7*g9 13 | aww=al-ww 14 | ww1=ww-one 15 | area=(((al-one)/aww)**g1)/w 16 | b(1)=area**qt 17 | axw=al*ww1*b(1) 18 | b(2)=w*aww/axw/qt 19 | c2=thr/qt+al*(two-one/qt) 20 | c4=al+one/qt 21 | cww=ww*(c2-ww*c4)-al*(one+one/qt) 22 | b(3)=b(2)*cww/axw/ww1 23 | dww=(two*c2-four*c4*ww)/cww-four/ww1 24 | b(4)=b(3)*(b(3)/b(2)+w*b(2)*dww-one/b(1)) 25 | end subroutine sorce 26 | -------------------------------------------------------------------------------- /src/scond.f: -------------------------------------------------------------------------------- 1 | subroutine scond(a,b,c,king) 2 | ! to obtain parabolic derivative of curve (unequally spaced points) 3 | use kinddefine 4 | implicit none 5 | integer(kind=K4),intent(in) :: king 6 | integer(kind=K4) :: k,n 7 | real(kind=K8),dimension(150),intent(in) :: a,b 8 | real(kind=K8),dimension(150),intent(out) :: c 9 | real(kind=K8) :: qf,qo,qst,s,sf,so,t,t0,tf 10 | n=king-1 11 | do k=2,n 12 | s=a(k)-a(k-1) 13 | t=a(k+1)-a(k) 14 | c(k)=((b(k+1)-b(k))*s*s+(b(k)-b(k-1))*t*t)/(s*s*t+s*t*t) 15 | enddo 16 | so=a(2)-a(1) 17 | t0=a(3)-a(2) 18 | qo=so+t0 19 | c(1)=(-t0*(qo+so)*b(1)+qo*qo*b(2)-so*so*b(3))/qo/so/t0 20 | sf=a(king-1)-a(king-2) 21 | tf=a(king)-a(king-1) 22 | qf=sf+tf 23 | qst=qf*sf*tf 24 | c(king)=(sf*(qf+tf)*b(king)-qf*qf*b(king-1)+tf*tf*b(king-2))/qst 25 | end subroutine scond 26 | -------------------------------------------------------------------------------- /src/xyz.f: -------------------------------------------------------------------------------- 1 | subroutine xyz(xx,yy,yyp,yypp) 2 | ! compute y,y',y'' for a curve described by cubic's e(5,*) 3 | ! where (1) = x-max (2) = high order coefficient. 4 | use kinddefine 5 | use coef, only:e 6 | implicit none 7 | integer(kind=K4) :: k 8 | real(kind=K8),intent(in) :: xx 9 | real(kind=K8),intent(out) :: yy,yyp,yypp 10 | real(kind=K8) :: a1,a2,a3,az,t,s,r,x,y,yp,ypp,zero 11 | data zero/0.0d+0/ 12 | x=xx 13 | if(x.ge.e(1,1)) goto 2 14 | 1 y=zero 15 | yp=zero 16 | ypp=zero 17 | goto 5 18 | 2 do k=2,200 19 | if(x.le.e(1,k)) goto 4 20 | enddo 21 | goto 1 22 | 4 a3=e(2,k) 23 | a2=e(3,k) 24 | a1=e(4,k) 25 | az=e(5,k) 26 | t=a2+a2 27 | s=a3*3.0d+0 28 | r=s+s 29 | y=az+x*(a1+x*(a2+x*a3)) 30 | yp=a1+x*(t+x*s) 31 | ypp=t+r*x 32 | 5 yy=y 33 | yyp=yp 34 | yypp=ypp 35 | end subroutine xyz 36 | -------------------------------------------------------------------------------- /src/twixt.f: -------------------------------------------------------------------------------- 1 | subroutine twixt(s,gma,gmb,gmc,gmd,xbl,kat,kbl) 2 | ! to determine interpolation coefficients 3 | use kinddefine 4 | implicit none 5 | integer(kind=K4) :: j,l 6 | integer(kind=K4),intent(in) :: kat 7 | integer(kind=K4),intent(out) :: kbl 8 | real(kind=K8) :: ds,dst,dstu,dt,dtu,du,xbb 9 | real(kind=K8),intent(out) :: gma,gmb,gmc,gmd 10 | real(kind=K8),intent(in) :: xbl 11 | real(kind=K8),dimension(200),intent(in) :: s 12 | do l=1,kat 13 | if(s(kat-l).lt.xbl) goto 2 14 | enddo 15 | 2 j=kat-l+1 16 | xbb=s(j)-xbl 17 | kbl=j+1 18 | du=s(j+1)-s(j) 19 | dt=s(j)-s(j-1) 20 | ds=s(j-1)-s(j-2) 21 | dst=ds+dt 22 | dstu=dst+du 23 | dtu=dt+du 24 | gma=-xbb*(dt-xbb)*(du+xbb)/ds/dst/dstu 25 | gmb=xbb*(dst-xbb)*(du+xbb)/ds/dt/dtu 26 | gmc=(dst-xbb)*(dt-xbb)*(du+xbb)/dst/dt/du 27 | gmd=-xbb*(dst-xbb)*(dt-xbb)/dstu/dtu/du 28 | end subroutine twixt 29 | -------------------------------------------------------------------------------- /src/license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021 Aldo Rona 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /src/fvdge.f: -------------------------------------------------------------------------------- 1 | subroutine fvdge(x,y,ds,dy) 2 | ! 3 | use kinddefine 4 | implicit none 5 | real(kind=K8),dimension(5),intent(in) :: x,y 6 | real(kind=K8),intent(out) :: ds,dy 7 | real(kind=K8) :: a1,a3,f1,f2,f3,fx,h,two 8 | real(kind=K8) :: x1,x2,x3,x4,x5,x21,x32,x43,x54 9 | real(kind=K8) :: y1,y2,y3,y4,y5,yp21,yp32,yp43,yp54,ypp1,ypp2,ypp3 10 | real(kind=K8) :: z13 11 | data h/0.5d+0/,two/2.0d+0/ 12 | ! 13 | x1=x(1) 14 | x2=x(2) 15 | x3=x(3) 16 | x4=x(4) 17 | x5=x(5) 18 | ! 19 | y1=y(1) 20 | y2=y(2) 21 | y3=y(3) 22 | y4=y(4) 23 | y5=y(5) 24 | ! 25 | ! find delta-y 26 | f1=(x3-x1)*(x3-x2) 27 | f1=two/f1 28 | ! 29 | f2=(x4-x3)*(x3-x2) 30 | f2=-two/f2 31 | ! 32 | f3=(x5-x3)*(x4-x3) 33 | f3=two/f3 34 | ! 35 | z13=x1+x2+x2-x4-x4-x5 36 | a1=(x2+x3-x4-x5)/z13 37 | a3=(x1+x2-x3-x4)/z13 38 | ! 39 | yp21=(y2-y1)/(x2-x1) 40 | yp32=(y3-y2)/(x3-x2) 41 | yp43=(y4-y3)/(x4-x3) 42 | yp54=(y5-y4)/(x5-x4) 43 | ! 44 | x21=h*(x2+x1) 45 | x32=h*(x3+x2) 46 | x43=h*(x4+x3) 47 | x54=h*(x5+x4) 48 | ! 49 | ypp1=(yp32-yp21)/(x32-x21) 50 | ypp2=(yp43-yp32)/(x43-x32) 51 | ypp3=(yp54-yp43)/(x54-x43) 52 | ds=a1*ypp1+a3*ypp3-ypp2 53 | fx=f2-a1*f1-a3*f3 54 | dy=ds/fx 55 | ! 56 | end subroutine fvdge 57 | -------------------------------------------------------------------------------- /src/cubic.f: -------------------------------------------------------------------------------- 1 | function cubic(ea,eb,ec,ed) 2 | use kinddefine 3 | ! 4 | implicit none 5 | integer(kind=K4) :: ia,ib,ic 6 | real(kind=K8),intent(in) :: ea,eb,ec,ed 7 | real(kind=K8) :: a,aa,b,cba,cbb,cbc,cbt1,cbt2,csa,csna,cubic,e3 8 | real(kind=K8) :: one,q,q1,qr,r1,rq,thr,two,zro 9 | ! to obtain positive real root of cubic equation 10 | data zro/0.d+0/,one/1.d+0/,two/2.d+0/,thr/3.d+0/ 11 | e3=eb/thr 12 | q1=ea*ec/thr-e3**2 13 | r1=ea*(e3*ec-ea*ed)/two-e3**3 14 | qr=q1**3+r1**2 15 | rq=dsqrt(dabs(qr)) 16 | q=dsqrt(dabs(q1)) 17 | b=dsign(one,r1) 18 | cbb=-one 19 | cbc=-one 20 | cbt1=zro 21 | cbt2=zro 22 | a=zro 23 | if (qr .gt. zro) goto 1 24 | if (qr .ne. zro) a=dasin(-rq/q1/q)/thr 25 | csa=dcos(a) 26 | csna=dsqrt(thr)*dsin(a) 27 | cba=(two*b*q*csa-e3)/ea 28 | cbb=-(b*q*(csa+csna)+e3)/ea 29 | cbc=-(b*q*(csa-csna)+e3)/ea 30 | goto 2 31 | 1 if (r1+rq .ne. zro) cbt1=dsign(dexp(dlog(dabs(r1+rq))/thr),r1+rq) 32 | if (r1-rq .ne. zro) cbt2=dsign(dexp(dlog(dabs(r1-rq))/thr),r1-rq) 33 | cba=(cbt1+cbt2-e3)/ea 34 | 2 ia=dsign(one,cba) 35 | ib=dsign(one,cbb) 36 | ic=dsign(one,cbc) 37 | if (ia+ib+ic+1) 11,3,7 38 | 3 if (ia .eq. 1) goto 5 39 | if (ib .eq. 1) goto 6 40 | 4 cubic=cbc 41 | return 42 | 5 cubic=cba 43 | return 44 | 6 cubic=cbb 45 | return 46 | 7 if (ia+2*ib+3*ic-2) 8,9,10 47 | 8 if (cba .gt. cbb) goto 6 48 | goto 5 49 | 9 if (cba .gt. cbc) goto 4 50 | goto 5 51 | 10 if (cbb .gt. cbc) goto 4 52 | goto 6 53 | 11 aa=a*9.d+1/dasin(one) 54 | write (2,12) ea,eb,ec,ed,q1,r1,qr,rq,q,aa,cba,cbb,cbc 55 | cubic=-one 56 | return 57 | ! 58 | 12 format ('O','EA=',e14.7,' EB=',e14.7,' EC=',e14.7,' ED=',e14.7, 59 | &' Q1=',e14.7,' R1=',e14.7,' QR=',e14.7,' RQ=',e14.7,' Q=',e1 60 | &4.7,', AA=',e14.7,',CBA=',e14.7,',CBB=',e14.7,',CBC=',e14.7 /) 61 | end function cubic 62 | -------------------------------------------------------------------------------- /src/splind.f: -------------------------------------------------------------------------------- 1 | subroutine splind(x,y,tn2,tnl,l) 2 | ! compute cubic coefficients for a curve x-y 3 | use kinddefine 4 | use coef, only:e,ne 5 | implicit none 6 | integer(kind=K4),intent(in) :: l 7 | integer(kind=K4) :: j,k,n 8 | real(kind=K8),dimension(300) :: a,b,c,d,dx,dy,g,sb,xm 9 | real(kind=K8),dimension(l),intent(in) :: x,y 10 | real(kind=K8),intent(in) :: tn2,tnl 11 | real(kind=K8) :: dxr,one,p,px,pxx,pxxx,q,qx,qxx,qxxx,r,s,six,sw 12 | real(kind=K8):: thr,xj,xk,zero 13 | data zero/0.0d+0/,one/1.d+0/,thr/3.d+0/,six/6.d+0/ 14 | ! call orez (e,5*200) 15 | ! call orez (a,9*300) 16 | e(:,:)=0.0d0 17 | a(:)=0.0d0 18 | b(:)=0.0d0 19 | c(:)=0.0d0 20 | d(:)=0.0d0 21 | dx(:)=0.0d0 22 | dy(:)=0.0d0 23 | g(:)=0.0d0 24 | sb(:)=0.0d0 25 | xm(:)=0.0d0 26 | ! 27 | dx(1)=zero 28 | dy(1)=zero 29 | n=l-1 30 | do k=2,l 31 | dx(k)=x(k)-x(k-1) 32 | dy(k)=y(k)-y(k-1) 33 | enddo 34 | ! 35 | b(1)=dx(2)/thr 36 | c(1)=dx(2)/six 37 | d(1)=dy(2)/dx(2)-tn2 38 | a(l)=dx(l)/six 39 | b(l)=dx(l)/thr 40 | d(l)=tnl-dy(l)/dx(l) 41 | a(1)=zero 42 | do k=2,n 43 | a(k)=dx(k)/six 44 | b(k)=(dx(k)+dx(k+1))/thr 45 | d(k)=dy(k+1)/dx(k+1)-dy(k)/dx(k) 46 | c(k)=dx(k+1)/six 47 | enddo 48 | sw=one/b(1) 49 | sb(1)=sw*c(1) 50 | g(1)=sw*d(1) 51 | do k=2,l 52 | sw=one/(b(k)-a(k)*sb(k-1)) 53 | sb(k)=sw*c(k) 54 | g(k)=sw*(d(k)-a(k)*g(k-1)) 55 | enddo 56 | xm(l)=g(l) 57 | do k=1,n 58 | j=l-k 59 | xm(j)=g(j)-sb(j)*xm(j+1) 60 | enddo 61 | do k=2,l 62 | dxr=one/dx(k) 63 | q=dxr/six 64 | p=-xm(k-1)*q 65 | q=q*xm(k) 66 | r=dx(k)*xm(k-1)/six-dxr*y(k-1) 67 | s=y(k)*dxr-dx(k)*xm(k)/six 68 | xk=x(k) 69 | px=xk*p 70 | pxx=px*xk 71 | pxxx=pxx*xk 72 | xj=x(k-1) 73 | qx=xj*q 74 | qxx=qx*xj 75 | qxxx=qxx*xj 76 | e(2,k)=p+q 77 | e(3,k)=-thr*(px+qx) 78 | e(4,k)=thr*(pxx+qxx)+r+s 79 | e(5,k)=-pxxx-qxxx-r*xk-s*xj 80 | enddo 81 | do k=2,l 82 | e(1,k)=x(k) 83 | enddo 84 | e(1,1)=x(1) 85 | ne=l 86 | end subroutine splind 87 | -------------------------------------------------------------------------------- /conturpy/create_report.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | import matplotlib.pyplot as plt 4 | from .plot_results import gen_bl_thickness_plot, gen_bl_temperature_plot, gen_noz_characteristics, \ 5 | gen_throat_characteristics, gen_contours, gen_flow_angles, gen_flow_angles_throat 6 | 7 | 8 | def save_table(table, directory, base_name, section_num, table_num=None): 9 | header = ",".join(table.headers) 10 | table_name_section = "" if table_num is None else f"_{table_num}" 11 | filename = f"{base_name}_{section_num}" + table_name_section + ".csv" 12 | np.savetxt(os.path.join(directory, filename), table.to_numpy(), delimiter=',', header=header) 13 | 14 | 15 | def save_group(subsection, base_name, directory): 16 | for idx, individual in enumerate(subsection): 17 | if len(individual.tables) > 1: 18 | for table_num, table in enumerate(individual.tables): 19 | save_table(table, directory, base_name, idx, table_num) 20 | elif len(individual.tables) == 1: 21 | save_table(individual.tables[0], directory, base_name, idx) 22 | 23 | 24 | def save_all(r, directory): 25 | if not os.path.exists(directory): 26 | os.mkdir(directory) 27 | 28 | names = ['IntermediateLeftCharacteristic', 29 | 'BoundaryLayerCalculations', 30 | 'NozzleContour', 31 | 'InviscidContour', 32 | 'IntermediateRightCharacteristic', 33 | 'UpstreamContour', 34 | 'ThroatVelocityDistribution', 35 | 'ThroatCharacteristic', 36 | 'CoordinatesAndDerivatives'] 37 | for name in names: 38 | subsection = [x for x in r.sections if x.class_name.replace('Contur', '') == name] 39 | save_group(subsection, name, directory) 40 | 41 | plot_functions = [gen_bl_thickness_plot, gen_bl_temperature_plot, gen_noz_characteristics, 42 | gen_throat_characteristics, gen_contours, gen_flow_angles, gen_flow_angles_throat] 43 | plot_fun_names = ["Boundary_Layer_Thickness.png", "Boundary_Layer_Temperature.png", "Nozzle_Characteristics.png", 44 | "Throat_Characteristics.png", "Contours.png", "Flow_Angles.png", "Flow_Angles_At_Throat.png"] 45 | 46 | for plot_fun, plot_name in zip(plot_functions, plot_fun_names): 47 | f, ax = plot_fun(r) 48 | f.savefig(os.path.join(directory, plot_name)) 49 | plt.close() 50 | -------------------------------------------------------------------------------- /src/ofeld.f: -------------------------------------------------------------------------------- 1 | subroutine ofeld(a,b,c,nocon) 2 | ! to obtain points in characteristic network 3 | use kinddefine 4 | use contr, only:ie 5 | implicit none 6 | ! 7 | interface 8 | function fmv(psi) 9 | use kinddefine 10 | implicit none 11 | real(kind=K8) :: fmv 12 | real(kind=K8), intent(in) :: psi 13 | end function fmv 14 | end interface 15 | ! 16 | integer(kind=K4) :: i 17 | integer(kind=K4),intent(out) :: nocon 18 | real(kind=K8),dimension(5),intent(in) :: a,b 19 | real(kind=K8),dimension(5),intent(out) :: c 20 | real(kind=K8) :: a1,a2,a3,dtn,fm3,fsy1,fsy2,fsy3,half,hdpsi,hpsi3 21 | real(kind=K8) :: ht3,one,p1,p2,psi3 22 | real(kind=K8) :: t1,t2,t3,temp,tn2,tna,tnb,tni,told,two,x3,y3,zro 23 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,half/5.d-1/ 24 | a1=dasin(one/a(3)) 25 | a2=dasin(one/b(3)) 26 | t1=a(5) 27 | t2=b(5) 28 | if (ie .eq. 0) goto 8 29 | if (a(2) .eq. zro) goto 5 30 | fsy1=dsin(a(5))/a(2)/a(3) 31 | goto 6 32 | 5 t1=zro 33 | fsy1=a(5) 34 | 6 if (b(2) .eq. zro) goto 7 35 | fsy2=dsin(b(5))/b(2)/b(3) 36 | goto 8 37 | 7 t2=zro 38 | fsy2=b(5) 39 | 8 tni=dtan(t1-a1) 40 | if (b(3) .ne. one) tn2=dtan(t2+a2) 41 | i=-1 42 | hdpsi=half*(a(4)-b(4)) 43 | ht3=half*(t1+t2)+hdpsi 44 | t3=ht3-half*ie*hdpsi 45 | hpsi3=half*(a(4)+b(4)+t1-t2) 46 | psi3=hpsi3+half*ie*(t1-t2) 47 | c(3)=fmv(psi3) 48 | told=t3 49 | 1 i=i+1 50 | fm3=c(3) 51 | a3=dasin(one/c(3)) 52 | tna=half*(tni+dtan(t3-a3)) 53 | if (b(3) .ne. one) tnb=half*(dtan(t3+a3)+tn2) 54 | if (b(3) .eq. one) tnb=two*dtan(t3+a3) 55 | dtn=tnb-tna 56 | x3=(b(1)*tnb-a(1)*tna+a(2)-b(2))/dtn 57 | y3=(a(2)*tnb-b(2)*tna+(b(1)-a(1))*tna*tnb)/dtn 58 | if ((ie .eq. 0) .or. (dabs(y3) .lt. 1.d-9)) goto 4 59 | fsy3=dsin(t3)/y3/fm3 60 | p1=half*(fsy1+fsy3)*(x3-a(1))*dsqrt(one+tna**2) 61 | p2=half*(fsy2+fsy3)*(x3-b(1))*dsqrt(one+tnb**2) 62 | t3=ht3+half*(p1-p2) 63 | psi3=hpsi3+half*(p1+p2) 64 | c(3)=fmv(psi3) 65 | if (dabs(t3-told) .gt. 1.d-9) goto 2 66 | if (dabs(c(3)-fm3) .lt. 1.d-9) goto 4 67 | 2 if (i .eq. 40) goto 3 68 | temp=t3 69 | t3=(t3+told)*half 70 | told=temp 71 | goto 1 72 | 3 nocon=1 73 | 4 c(1)=x3 74 | c(2)=y3 75 | c(4)=psi3 76 | c(5)=t3 77 | end subroutine ofeld 78 | -------------------------------------------------------------------------------- /conturpy/run_contur.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import subprocess 3 | import os 4 | import shutil 5 | import glob 6 | from pathlib import Path 7 | from .read_output import ConturResult 8 | 9 | 10 | class ConturApplication(object): 11 | def __init__(self, location=os.getcwd(), timeout=0.5, executable=None): 12 | self.location = location 13 | self.timeout = timeout 14 | 15 | if executable is None: 16 | bin_path = Path(__file__).parent.joinpath('bin/') 17 | plat = platform.system() 18 | if plat == 'Windows': 19 | executable = bin_path.joinpath('contur.exe') 20 | elif plat == 'Darwin' and platform.machine() == 'arm64': 21 | executable = bin_path.joinpath('contur_macarm64') 22 | else: 23 | raise Exception(f"Platform {plat} is not supported") 24 | self.executable = executable 25 | self._expected_to_exist = False 26 | 27 | def run(self): 28 | assert self._exists 29 | try: 30 | subprocess.check_output(self.executable, timeout=self.timeout, cwd=self.location) 31 | success = True 32 | except subprocess.TimeoutExpired: 33 | success = False 34 | return success 35 | 36 | def _run_single_file(self, file, output_dir, refine_amt=21): 37 | shutil.copyfile(file, os.path.join(self.location, 'input.txt')) 38 | success = self.run() 39 | if success: 40 | flag, newfile = self._move_output(like_source_fn=file, dest_folder=output_dir) 41 | os.remove(file) 42 | 43 | if flag == 1: 44 | return ConturResult(newfile, refine_amt=refine_amt) 45 | else: 46 | return None 47 | 48 | def batch_input_files(self, file_list, output_dir=os.getcwd(), refine_amt=21): 49 | results = [] 50 | for file in file_list: 51 | results.append(self._run_single_file(file, output_dir, refine_amt=refine_amt)) 52 | results = [x for x in results if x is not None] 53 | self.clean_wd() 54 | return results 55 | 56 | def batch_input_folder(self, folder, output_dir=os.getcwd(), refine_amt=21): 57 | results = [] 58 | for file in glob.glob(os.path.join(folder, '*.txt')): 59 | results.append(self._run_single_file(file, output_dir, refine_amt=refine_amt)) 60 | results = [x for x in results if x is not None] 61 | self.clean_wd() 62 | return results 63 | 64 | @staticmethod 65 | def _move_output(dest_fn=None, like_source_fn=None, dest_folder=None, 66 | src=os.path.join(os.getcwd(), 'output.txt')): 67 | if not os.path.exists(src): 68 | return -1, None 69 | if like_source_fn is not None: 70 | dest_fn = os.path.split(like_source_fn)[-1].replace('.txt', '_result.txt') 71 | else: 72 | dest_fn = 'output.txt' if dest_fn is None else dest_fn 73 | 74 | dest_folder = os.getcwd() if dest_folder is None else dest_folder 75 | newfile = os.path.join(dest_folder, dest_fn) 76 | shutil.copyfile(src, newfile) 77 | 78 | return 1, newfile 79 | 80 | def clean_wd(self, wd=None): 81 | if wd is None: 82 | wd = self.location 83 | input_file = os.path.join(wd, 'input.txt') 84 | output_file = os.path.join(wd, 'output.txt') 85 | 86 | if os.path.exists(input_file): 87 | os.remove(input_file) 88 | if os.path.exists(output_file): 89 | os.remove(output_file) 90 | 91 | def _exists(self): 92 | if not self._expected_to_exist: 93 | exists = os.path.exists(self.executable) 94 | if exists: 95 | self._expected_to_exist = True 96 | return True 97 | else: 98 | return False 99 | else: 100 | return True 101 | 102 | def __repr__(self): 103 | if self._exists(): 104 | return f"CONTUR Executable at {self.executable}" 105 | else: 106 | return f"CONTUR Executable NOT FOUND (expected at {self.executable})" 107 | -------------------------------------------------------------------------------- /src/neo.f: -------------------------------------------------------------------------------- 1 | subroutine neo 2 | ! 3 | ! smooth by linear second derivative 4 | ! 5 | use kinddefine 6 | use work, only: wall,wax,way,wan,nodo,noup,npct,e,z,x,y,yst,wtn 7 | use contr, only: itle,jq,iq,n,np,nut 8 | ! 9 | implicit none 10 | ! 11 | interface 12 | subroutine fvdge(x,y,ds,dy) 13 | use kinddefine 14 | implicit none 15 | real(kind=K8),dimension(5),intent(in) :: x,y 16 | real(kind=K8),intent(out) :: ds,dy 17 | end subroutine fvdge 18 | ! 19 | subroutine scond(a,b,c,king) 20 | use kinddefine 21 | implicit none 22 | integer(kind=K4),intent(in) :: king 23 | real(kind=K8),dimension(150),intent(in) :: a,b 24 | real(kind=K8),dimension(150),intent(out) :: c 25 | end subroutine scond 26 | end interface 27 | ! 28 | integer(kind=K4) :: lim,lm,lu,lus,j,k,m,maxej 29 | integer(kind=K4) :: notm 30 | real(kind=K8) :: conv,emax,error,one,smp,test,tni,two,zero 31 | character(len=4,kind=K3) :: j0,j1,jn 32 | ! COMMON /WORK/ WALL(5,200),WAX(200),WAY(200),WAN(200),E(400),Z(400) 33 | ! 1,X(400),Y(400),YST(400),WTN(250) 34 | ! COMMON /CONTR/ ITLE(3),IE,LR,IT,JB,JQ,JX,KAT,KBL,KING,KO,LV,NOCON, 35 | ! 1IN,MC,MCP,IP,IQ,ISE,JC,M,MP,MQ,N,NP,NR,NUT,NF 36 | data zero/0.0d+0/,one/1.d+0/,two/2.d+0/ 37 | data j0/' UP'/,j1/'DOWN'/ 38 | ! 39 | conv=90.d+0/dasin(one) 40 | tni=dtan(wall(5,1)) 41 | ! 42 | if (jq.eq.0.or.iq.lt.0) read (1,14,end=13) noup,npct,nodo 43 | if (jq .gt. 0) goto 2 44 | jn=j0 45 | lim=nut 46 | notm=noup 47 | do j=1,lim 48 | x(j+1)=wax(j) 49 | y(j+1)=way(j) 50 | yst(j+1)=y(j+1) 51 | enddo 52 | x(1)=two*x(2)-x(3) 53 | y(1)=y(3) 54 | x(lim+2)=two*x(lim+1)-x(lim) 55 | y(lim+2)=y(lim+1)+tni*(x(lim+2)-x(lim+1)) 56 | goto 4 57 | 2 lim=n+np-1 58 | notm=nodo 59 | jn=j1 60 | do j=1,lim 61 | x(j+1)=wall(1,j) 62 | y(j+1)=wall(2,j) 63 | yst(j+1)=y(j+1) 64 | enddo 65 | x(1)=two*x(2)-x(3) 66 | y(1)=y(2)-tni*(x(2)-x(1)) 67 | x(lim+2)=two*x(lim+1)-x(lim) 68 | y(lim+2)=y(lim+1) 69 | 4 lus=1+(lim-3)/6 70 | if (notm .eq. 0) return 71 | yst(1)=y(1) 72 | yst(lim+2)=y(lim+2) 73 | smp=1.d-2*npct 74 | write (2,16) itle,jn,notm,smp 75 | ! I HAVE NOT UNDERSTOOD WHY m IS KEPT IN THE COMMON BLOCK contr 76 | do m=1,notm 77 | ! call orez(e,800) 78 | e(:)=0.0d0 79 | z(:)=0.0d0 80 | ! 81 | do k=3,lim 82 | call fvdge (x(k-2:k+2),y(k-2:k+2),e(k),z(k)) 83 | enddo 84 | e(1)=zero 85 | e(2)=zero 86 | e(lim+1)=zero 87 | e(lim+2)=zero 88 | ! search array and find max error 89 | do lu=1,lus 90 | emax=zero 91 | do k=3,lim 92 | test=dabs(e(k)) 93 | if (emax .gt. test) goto 6 94 | j=k 95 | emax=test 96 | 6 continue 97 | enddo 98 | ! apply correction 99 | e(j)=zero 100 | e(j+1)=zero 101 | e(j+2)=zero 102 | e(j-1)=zero 103 | e(j-2)=zero 104 | y(j)=y(j)+smp*z(j) 105 | enddo 106 | enddo 107 | ! 108 | error=zero 109 | do j=1,lim 110 | k=j+1 111 | e(k)=y(k)-yst(k) 112 | if (error .lt. dabs(e(k))) maxej=j 113 | if (error .lt. dabs(e(k))) error=dabs(e(k)) 114 | write (2,15) j,x(k),y(k),yst(k),e(k),j 115 | if (mod(j,10) .eq. 0) write (2,17) 116 | enddo 117 | write (2,19) error,maxej 118 | ! 119 | lm=lim-1 120 | call scond (x,y,wtn,lim+2) 121 | if (jq .eq. 1) goto 11 122 | do j=2,lm 123 | way(j)=y(j+1) 124 | wan(j)=conv*datan(wtn(j+1)) 125 | enddo 126 | return 127 | ! 128 | 11 do j=2,lm 129 | wall(2,j)=y(j+1) 130 | wall(5,j)=datan(wtn(j+1)) 131 | enddo 132 | return 133 | ! 134 | 13 write (2,18) 135 | stop 136 | ! 137 | 14 format (3i5) 138 | 15 format (1x,20x,i5,2x,0p4f13.7,i8) 139 | 16 format (1x,3a4,2x,a4,'STREAM CONTOUR, SMOOTHED',i5,' TIMES WITH FA 140 | &CTOR=',f4.2//35x,'X',11x,'Y-CALC',7x,'Y-IN',10x,'DIFF' /) 141 | 17 format (1x) 142 | 18 format ('0',10x,'CARD NOT AVAILABLE FOR NEGATIVE NF') 143 | 19 format (1x,26x,'MAX. ABSOLUTE ERROR =',1pg15.6,' AT POINT ',i5/) 144 | end subroutine neo 145 | -------------------------------------------------------------------------------- /Example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "serious-literature", 6 | "metadata": { 7 | "pycharm": { 8 | "name": "#%% md\n" 9 | } 10 | }, 11 | "source": [ 12 | "# Example Usage of ConturPy\n", 13 | "## Noah Stockwell 4/17/2022" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "id": "serial-luxury", 19 | "metadata": { 20 | "pycharm": { 21 | "name": "#%% md\n" 22 | } 23 | }, 24 | "source": [ 25 | "This repository depends on numpy and scipy. Pandas is required to use ConturTable.to_pandas() routine which is exposed for the user, but not implemented in this example.\n", 26 | "\n", 27 | "Although ConturPy consists of many files, only ConturSettings and ConturApplication are required to do most standard work with Contur. ConturSettings provides a class-based interface to create input cards for Contur and ConturApplication provides the runtime and results for the compiled Contur executable. " 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "initial-multiple", 34 | "metadata": { 35 | "pycharm": { 36 | "name": "#%%\n" 37 | } 38 | }, 39 | "outputs": [], 40 | "source": [ 41 | "from conturpy import ConturSettings, ConturApplication" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "id": "satisfied-marina", 47 | "metadata": { 48 | "pycharm": { 49 | "name": "#%% md\n" 50 | } 51 | }, 52 | "source": [ 53 | "First, we must create the input parameters for Contur. Below, input cards for designing a Mach 5 nozzle are created programmatically." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "id": "thirty-ending", 60 | "metadata": { 61 | "pycharm": { 62 | "name": "#%%\n" 63 | } 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "c = ConturSettings()\n", 68 | "\n", 69 | "dmach = 7.0 # design mach\n", 70 | "throat_radius = 0.65 / 2 # inches\n", 71 | "\n", 72 | "# Card 1: the title of the simulation\n", 73 | "c[\"ITLE\"] = f\"Mach {dmach}\"\n", 74 | "\n", 75 | "# Card 2 contains gas properties. As air is the assumed working fluid, no changes are required\n", 76 | "\n", 77 | "# Card 3: key design parameters\n", 78 | "c[\"ETAD\"] = 60 # Angle at point D\n", 79 | "c[\"RC\"] = 6.0 # Radius of curvature at throat [multiple of throat radius]\n", 80 | "c[\"CMC\"] = dmach # Design mach\n", 81 | "c[\"SF\"] = throat_radius\n", 82 | "\n", 83 | "# Card 6 (B): stagnation and heat transfer properties\n", 84 | "c[\"PPQ\"] = 120 # Stagnation pressure [psia]\n", 85 | "c[\"TO\"] = 1000 # Stagnation temperature [R]\n", 86 | "c[\"TWT\"] = 540 # Wall temperature [R]\n", 87 | "c[\"TWAT\"] = 540 # Water-cooling temp [R] (suggest setting to TWT since water cooling not assumed)\n", 88 | "\n", 89 | "# Card 7 (D): interpolation parameters\n", 90 | "c[\"XLOW\"] = 0 # Point to begin interpolating contour [in]\n", 91 | "c[\"XEND\"] = 20 # Point to end interpolating contour [in]\n", 92 | "c[\"XINC\"] = .1 # Increment to interpolate by [in]\n", 93 | "\n", 94 | "# Create the input text file and save it to 'm5.0.txt' in the folder 'inputcards'\n", 95 | "c.print_to_input(file_name=f'm{dmach:.1f}.txt', output_directory='inputcards')" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "id": "hidden-effect", 101 | "metadata": { 102 | "pycharm": { 103 | "name": "#%% md\n" 104 | } 105 | }, 106 | "source": [ 107 | "Next, initialize and run the Contur executable for all files in the 'inputcards' folder and send all outputs to the 'outputs' folder. All files used as inputs are automatically removed. A ConturResults instance is created for every input and returned.\n", 108 | "\n", 109 | "Contur's boundary layer output is unusual and the author could not figure out how to treat this subsection. Attempting to read boundary layer output will often throw a warning about un-formatted extra Contur array outputs, but this is fine as no data is lost." 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "id": "deluxe-physics", 116 | "metadata": { 117 | "collapsed": false, 118 | "jupyter": { 119 | "outputs_hidden": false 120 | }, 121 | "pycharm": { 122 | "name": "#%%\n" 123 | } 124 | }, 125 | "outputs": [], 126 | "source": [ 127 | "ca = ConturApplication()\n", 128 | "res = ca.batch_input_folder('inputcards', output_dir='outputs')" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "id": "analyzed-projection", 134 | "metadata": { 135 | "pycharm": { 136 | "name": "#%% md\n" 137 | } 138 | }, 139 | "source": [ 140 | "Lastly, for every ConturResult (we only have one from Mach 5.0), save plots and data in .csv files to a subfolder under the 'outputs' folder titled 'nozzle_5.0/'\n", 141 | "\n", 142 | "The cell starts with %%capture to prevent drawing of half-finished plots" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": null, 148 | "outputs": [], 149 | "source": [ 150 | "%%capture\n", 151 | "\n", 152 | "for r in res:\n", 153 | " r.save_all(f\"outputs/nozzle_{r.design_mach}\")" 154 | ], 155 | "metadata": { 156 | "collapsed": false, 157 | "pycharm": { 158 | "name": "#%%\n" 159 | } 160 | } 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "id": "operating-shoulder", 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "%%capture\n", 170 | "\n", 171 | "for r in res:\n", 172 | " r.save_all(f\"outputs/nozzle_{r.design_mach}\")" 173 | ] 174 | } 175 | ], 176 | "metadata": { 177 | "kernelspec": { 178 | "display_name": "Python 3", 179 | "language": "python", 180 | "name": "python3" 181 | }, 182 | "language_info": { 183 | "codemirror_mode": { 184 | "name": "ipython", 185 | "version": 3 186 | }, 187 | "file_extension": ".py", 188 | "mimetype": "text/x-python", 189 | "name": "python", 190 | "nbconvert_exporter": "python", 191 | "pygments_lexer": "ipython3", 192 | "version": "3.8.5" 193 | } 194 | }, 195 | "nbformat": 4, 196 | "nbformat_minor": 5 197 | } -------------------------------------------------------------------------------- /conturpy/plot_results.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib as mplt 3 | import matplotlib.pyplot as plt 4 | from scipy.interpolate import interp1d 5 | 6 | 7 | def subtract_bl(bl_x, bl_y, noz_x, noz_y): 8 | bl_y_interp_f = interp1d(bl_x, bl_y, kind='linear', bounds_error=False) 9 | bl_y_interp = bl_y_interp_f(noz_x) 10 | return noz_y - bl_y_interp 11 | 12 | 13 | def get_noz_plot(ax=None): 14 | fig = None 15 | if ax is None: 16 | fig, ax = plt.subplots(1, 1, figsize=(8, 4), dpi=300, tight_layout=True, facecolor='w') 17 | ax.set_xlabel('X [Inches]') 18 | ax.set_ylabel('Y [Inches]') 19 | ax.set_ylim([0, None]) 20 | ax.grid() 21 | 22 | if fig is None: 23 | return ax 24 | else: 25 | return fig, ax 26 | 27 | 28 | def line_colormap(x, y, cv, norm, colormap='jet'): 29 | points = np.array([x, y]).T.reshape(-1, 1, 2) 30 | segments = np.concatenate([points[:-1], points[1:]], axis=1) 31 | lc = mplt.collections.LineCollection(segments, norm=norm, cmap=colormap) 32 | lc.set_array(cv) 33 | return lc 34 | 35 | 36 | def gen_bl_thickness_plot(r): 37 | f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y = prepare_bl_plot(r) 38 | 39 | bl_delta = bl_res.DELTA 40 | bl_delta_star = bl_res.DELTAstar__1 41 | bl_theta = bl_res.THETA_1 42 | 43 | f, ax = get_noz_plot() 44 | ax.plot(noz_x, noz_y, c='k', label='Wall Contour') 45 | ax.plot(noz_x, subtract_bl(bl_x, bl_delta, noz_x, noz_y), c='darkorange', label='Delta') 46 | ax.plot(noz_x, subtract_bl(bl_x, bl_delta_star, noz_x, noz_y), c='dodgerblue', label='Delta Star') 47 | ax.plot(noz_x, subtract_bl(bl_x, bl_theta, noz_x, noz_y), c='blueviolet', label='Theta') 48 | ax.legend() 49 | ax.set_title('Boundary Layer Thickness') 50 | 51 | ax.set_xlim([noz_x.min(), noz_x.max()]) 52 | noz_y_rng = noz_y.ptp() 53 | ax.set_ylim([0 - .1 * noz_y_rng, noz_y.max() + .2 * noz_y_rng]) 54 | 55 | return f, ax 56 | 57 | 58 | def prepare_bl_plot(r): 59 | noz_geom = r.refine_coordinates(21) 60 | 61 | bl_res = [x for x in r.bl_calculations if 'X' in x.tables[0].headers][1].tables[0] 62 | bl_cor = [x for x in r.bl_calculations if 'STA_IN' in x.tables[0].headers][0].tables[0] 63 | 64 | bl_x = bl_cor.STA_IN 65 | plot_msk = noz_geom[:, 0] <= r.nozzle_length 66 | noz_x = noz_geom[plot_msk, 0] 67 | noz_y = noz_geom[plot_msk, 1] 68 | 69 | f, ax = get_noz_plot() 70 | 71 | return f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y 72 | 73 | 74 | def gen_bl_temperature_plot(r): 75 | f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y = prepare_bl_plot(r) 76 | 77 | t_norm = mplt.colors.Normalize(vmin=bl_res.TE.min(), vmax=bl_res.TE.max()) 78 | interp_wall_temp = interp1d(bl_x, bl_res.TW, kind='linear', bounds_error=False) 79 | interp_surf_temp = interp1d(bl_x, bl_res.TE, kind='linear', bounds_error=False) 80 | wall_temp_l = line_colormap(noz_x, noz_y, interp_wall_temp(noz_x), t_norm) 81 | surf_temp_l = line_colormap(noz_x, subtract_bl(bl_x, bl_res.DELTAstar__1, noz_x, noz_y), 82 | interp_surf_temp(noz_x), t_norm) 83 | 84 | ax.add_collection(wall_temp_l) 85 | ax.add_collection(surf_temp_l) 86 | 87 | ax.set_xlim([noz_x.min(), noz_x.max()]) 88 | noz_y_rng = noz_y.ptp() 89 | ax.set_ylim([0 - .1 * noz_y_rng, noz_y.max() + .2 * noz_y_rng]) 90 | 91 | cbar = plt.colorbar(surf_temp_l) 92 | cbar.set_label('Temperature [Rankine]') 93 | ax.set_title('Wall and External Temperature') 94 | 95 | return f, ax 96 | 97 | 98 | # noinspection DuplicatedCode 99 | def gen_noz_characteristics(r): 100 | f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y = prepare_bl_plot(r) 101 | d_mach = r.design_mach 102 | 103 | m_norm = mplt.colors.Normalize(vmin=1, vmax=d_mach) 104 | 105 | lc = None 106 | for char in r.characteristics: 107 | char_tab = char.tables[0] 108 | lc = line_colormap(char_tab.X_IN, char_tab.Y_IN, char_tab.Mach, m_norm) 109 | ax.add_collection(lc) 110 | 111 | ax.plot(noz_x, subtract_bl(bl_x, bl_res.DELTAstar__1, noz_x, noz_y), ls='--', c='k', label='Delta Star') 112 | ax.plot(noz_x, noz_y, ls='-', c='k', label='Wall') 113 | ax.set_xlim([noz_x.min(), noz_x.max()]) 114 | noz_y_rng = noz_y.ptp() 115 | ax.set_ylim([0 - .1 * noz_y_rng, noz_y.max() + .2 * noz_y_rng]) 116 | ax.legend() 117 | cbar = plt.colorbar(lc) 118 | cbar.set_label('Mach') 119 | 120 | ax.set_title('Characteristics') 121 | 122 | return f, ax 123 | 124 | 125 | # noinspection DuplicatedCode 126 | def gen_throat_characteristics(r): 127 | f, ax = gen_noz_characteristics(r) 128 | _, _, _, _, _, noz_x, noz_y = prepare_bl_plot(r) 129 | 130 | ax.set_xlim([noz_x.min(), noz_x.min() + 2 * noz_y.min()]) 131 | ax.set_ylim([0, 1.5 * noz_y.min()]) 132 | ax.set_title('Throat Characteristics') 133 | 134 | return f, ax 135 | 136 | 137 | # noinspection DuplicatedCode 138 | def gen_contours(r): 139 | f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y = prepare_bl_plot(r) 140 | d_mach = r.contours[0].tables[0].Mach[0] 141 | 142 | m_norm = mplt.colors.Normalize(vmin=1, vmax=d_mach) 143 | 144 | lc = None 145 | for contour in r.contours: 146 | if len(contour.tables) > 0: 147 | contour_tab = contour.tables[0] 148 | if "X_IN" in contour_tab.headers: 149 | y_vals = np.zeros(contour_tab.X_IN.shape) 150 | if "Y_IN" in contour_tab.headers: 151 | y_vals = contour_tab.Y_IN 152 | lc = line_colormap(contour_tab.X_IN, y_vals, contour_tab.Mach, m_norm) 153 | ax.add_collection(lc) 154 | 155 | ax.plot(noz_x, subtract_bl(bl_x, bl_res.DELTAstar__1, noz_x, noz_y), ls='--', c='k', label='Delta Star') 156 | ax.plot(noz_x, noz_y, ls='-', c='k', label='Wall') 157 | ax.set_xlim([noz_x.min(), noz_x.max()]) 158 | noz_y_rng = noz_y.ptp() 159 | ax.set_ylim([0 - .1 * noz_y_rng, noz_y.max() + .2 * noz_y_rng]) 160 | ax.legend() 161 | cbar = plt.colorbar(lc) 162 | cbar.set_label('Mach') 163 | 164 | ax.set_title('Contours') 165 | 166 | return f, ax 167 | 168 | 169 | # noinspection DuplicatedCode 170 | def gen_flow_angles(r, width=.0015, scale=80): 171 | xv = np.hstack([char.tables[0].X_IN for char in r.characteristics]) 172 | yv = np.hstack([char.tables[0].Y_IN for char in r.characteristics]) 173 | mn = np.hstack([char.tables[0].Mach for char in r.characteristics]) 174 | theta_u = np.hstack([char.tables[0].FLOW_ANG__D for char in r.characteristics]) 175 | uv = np.cos(theta_u * np.pi / 180) 176 | wv = np.sin(theta_u * np.pi / 180) 177 | 178 | f, ax, bl_res, bl_cor, bl_x, noz_x, noz_y = prepare_bl_plot(r) 179 | 180 | qv = ax.quiver(xv, yv, uv, wv, mn, cmap='jet', scale_units='width', width=width, scale=scale) 181 | ax.plot(noz_x, subtract_bl(bl_x, bl_res.DELTAstar__1, noz_x, noz_y), ls='--', c='k', label='Delta Star') 182 | ax.plot(noz_x, noz_y, ls='-', c='k', label='Wall') 183 | ax.set_xlim([noz_x.min(), noz_x.max()]) 184 | noz_y_rng = noz_y.ptp() 185 | ax.set_ylim([0 - .1 * noz_y_rng, noz_y.max() + .2 * noz_y_rng]) 186 | 187 | ax.set_title('Flow Angles') 188 | 189 | ax.legend() 190 | cbar = plt.colorbar(qv) 191 | cbar.set_label('Mach') 192 | 193 | return f, ax 194 | 195 | 196 | # noinspection DuplicatedCode 197 | def gen_flow_angles_throat(r, width=.0025, scale=25): 198 | f, ax = gen_flow_angles(r, width=width, scale=scale) 199 | _, _, _, _, _, noz_x, noz_y = prepare_bl_plot(r) 200 | 201 | ax.set_xlim([noz_x.min(), noz_x.min() + 2 * noz_y.min()]) 202 | ax.set_ylim([0, 1.5 * noz_y.min()]) 203 | ax.set_title('Throat Flow Angles') 204 | 205 | return f, ax 206 | -------------------------------------------------------------------------------- /conturpy/create_input_cards.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def reduce_g(num): 5 | g_str = f"{num:<.10G}" 6 | 7 | if '.' not in g_str: 8 | g_str += '.' 9 | 10 | while len(g_str) > 10: 11 | if 'E' in g_str: 12 | sp_str = g_str.split('E') 13 | g_str = sp_str[0][:-1] + 'E' + sp_str[1] 14 | else: 15 | g_str = g_str[:-1] 16 | 17 | while len(g_str) < 10: 18 | g_str += ' ' 19 | 20 | return g_str 21 | 22 | 23 | class ConturCard(object): 24 | def __init__(self, labels=None, values=None, widths=None, aligns=None): 25 | self.card_labels = [] if labels is None else labels 26 | self.card_values = [] if values is None else values 27 | self.card_widths = [] if widths is None else widths 28 | self.card_aligns = [] if aligns is None else aligns 29 | 30 | def print(self) -> str: 31 | aligns = self.card_aligns 32 | widths = self.card_widths 33 | 34 | if len(self.card_aligns) == 0: 35 | aligns = ["<" for _ in range(len(self.card_labels))] 36 | elif len(self.card_aligns) == 1: 37 | aligns = [self.card_aligns[0] for _ in range(len(self.card_labels))] 38 | 39 | if len(self.card_widths) == 1: 40 | widths = [self.card_widths[0] for _ in range(len(self.card_labels))] 41 | 42 | return "".join([f"{val:{aligns[idx]}{widths[idx]}}" if widths[idx] != -1 else reduce_g(val) 43 | for idx, val in enumerate(self.card_values)]) 44 | 45 | def to_dict(self): 46 | return dict(zip(self.card_labels, self.card_values)) 47 | 48 | def __repr__(self): 49 | return self.to_dict() 50 | 51 | def __str__(self): 52 | return "".join([f"{label}: {value}\n" for label, value in zip(self.card_labels, self.card_values)]) 53 | 54 | def __getitem__(self, label: str): 55 | if label in self.card_labels: 56 | return self.card_values[self.card_labels.index(label)] 57 | else: 58 | raise AttributeError(f"Card label {label} not found") 59 | 60 | def __setitem__(self, label, value): 61 | if label in self.card_labels: 62 | self.card_values[self.card_labels.index(label)] = value 63 | else: 64 | raise AttributeError(f"Card label {label} not found") 65 | 66 | 67 | class ConturCard1(ConturCard): 68 | def print(self) -> str: 69 | return f" {self.card_values[0]:^10.10s} {self.card_values[1]:<2d}" 70 | 71 | 72 | class ConturSettings(object): 73 | def __init__(self, smooth_inviscid_contour=True, include_bl=True, bl_use_characteristics=True, use_spline=True, 74 | smooth_before_spline=False): 75 | 76 | self._smooth_inviscid_contour = smooth_inviscid_contour 77 | self._include_bl = include_bl 78 | self._bl_use_characteristics = bl_use_characteristics 79 | self._use_spline = use_spline 80 | self._smooth_before_spline = smooth_before_spline 81 | 82 | self._card1 = ConturCard1( 83 | ["ITLE", "JD"], 84 | ["Title", 0], 85 | ["10.10s", "2d"], 86 | ["^", "<"]) 87 | 88 | self._card2 = ConturCard( 89 | ["GAM", "AR", "ZO", "RO", "VISC", "VISM", "SFOA", "XBL"], 90 | [1.40, 1716.563, 1.0, 0.896, 2.26968E-8, 198.72, 0, 1000], 91 | [-1]) 92 | 93 | self._card3 = ConturCard( 94 | ["ETAD", "RC", "FMACH", "BMACH", "CMC", "SF", "PP", "XC"], 95 | [60, 6.0, 0, 0, 0, -1 * 3, 0, 0], 96 | [-1]) 97 | 98 | self._card4 = ConturCard( 99 | ["MT", "NT", "IX", "IN", "IQ", "MD", "ND", "NF", "MP", "MQ", "JB", "JX", "JC", "IT", "LR", "NX"], 100 | [61, 41, 0, 10, 0, 61, 69, -61, 0, 0, 1, 0, 1, 0, -25, 13], 101 | ["5d"] 102 | ) 103 | 104 | self._cardA = ConturCard( 105 | ["NOUP", "NPCT", "NODO"], 106 | [50, 85, 50], 107 | ["5d"]) 108 | 109 | self._cardB = ConturCard( 110 | ["PPQ", "TO", "TWT", "TWAT", "QFUN", "ALPH", "IHT", "IR", "ID", "LV"], 111 | [90, 1030, 540, 540, 0, 0, 0, 0, 1, 5], 112 | [-1, -1, -1, -1, -1, -1, "5d", "5d", "5d", "5d"]) 113 | 114 | self._cardC = ConturCard( 115 | ["ETAD", "QM", "XJ"], 116 | [60, 0, 0], 117 | [-1] 118 | ) 119 | 120 | self._cardD = ConturCard( 121 | ["XST", "XLOW", "XEND", "XINC", "BJ", "XMID", "XINC2", "CN"], 122 | [1000, 0, 50, 2, 0, 0, 0, 0], 123 | [-1]) 124 | 125 | self._card_deck = [self._card1, self._card2, self._card3, self._card4, self._cardA, self._cardB, 126 | self._cardC, self._cardD] 127 | self._str_fields = [card.card_labels for card in self._card_deck] 128 | 129 | def get_deck(self) -> str: 130 | card5 = None 131 | card6 = None 132 | card7 = None 133 | 134 | if self._smooth_inviscid_contour: 135 | card5 = self._cardA 136 | elif self._include_bl and self._bl_use_characteristics and not self._smooth_inviscid_contour: 137 | card5 = self._cardB 138 | elif self._card4["JX"] > 0 and not self._smooth_inviscid_contour: 139 | card5 = self._cardC 140 | elif self._card4["JX"] <= 0 and self._card4["JB"] <= 0 and not self._smooth_inviscid_contour: 141 | card5 = self._cardD 142 | 143 | # noinspection PyChainedComparisons 144 | if self._include_bl and self._bl_use_characteristics and self._smooth_inviscid_contour: 145 | card6 = self._cardB 146 | elif (self._card4["JB"] > 0 and self._card4["LV"] <= 0 and not self._smooth_inviscid_contour) or \ 147 | self._smooth_before_spline: 148 | card6 = self._cardD 149 | 150 | if self._include_bl and not self._bl_use_characteristics and self._smooth_inviscid_contour: 151 | card7 = self._cardB 152 | elif self._smooth_inviscid_contour and self._include_bl and self._use_spline: 153 | card7 = self._cardD 154 | 155 | return "".join([ 156 | self._card1.print() + "\n", 157 | self._card2.print() + "\n", 158 | self._card3.print() + "\n", 159 | self._card4.print() + "\n", 160 | card5.print() + "\n" if card5 is not None else "", 161 | card6.print() + "\n" if card6 is not None else "", 162 | card7.print() + "\n" if card7 is not None else "", 163 | ]) 164 | 165 | def print_to_input(self, file_name=None, output_directory=None): 166 | file_name = 'input.txt' if file_name is None else file_name 167 | file_path = file_name if output_directory is None else os.path.join(output_directory, file_name) 168 | with open(file_path, 'w') as out_file: 169 | out_file.write(self.get_deck()) 170 | 171 | def __getitem__(self, label: str): 172 | is_present = [label in row for row in self._str_fields] 173 | 174 | if not any(is_present): 175 | raise AttributeError(f"Card label {label} not found") 176 | 177 | return self._card_deck[is_present.index(True)][label] 178 | 179 | def __setitem__(self, label: str, value): 180 | is_present = [label in row for row in self._str_fields] 181 | 182 | if not any(is_present): 183 | raise AttributeError(f"Card label {label} not found") 184 | 185 | self._card_deck[is_present.index(True)][label] = value 186 | 187 | 188 | if __name__ == "__main__": 189 | throat_radius = 0.26 / 2 190 | 191 | for design_mach in [4, 4.5, 5, 5.3, 5.5, 5.7, 6.0, 6.2, 6.5]: 192 | c = ConturSettings() 193 | 194 | c["ITLE"] = f"Mach {design_mach}" 195 | 196 | c["ETAD"] = 60 197 | c["RC"] = 6.0 198 | c["CMC"] = design_mach 199 | c["SF"] = throat_radius 200 | 201 | c["PPQ"] = 70 202 | c["TO"] = 1000 203 | c["TWT"] = 540 204 | c["TWAT"] = 540 205 | 206 | c["XLOW"] = 0 207 | c["XEND"] = 100 208 | c["XINC"] = .1 209 | 210 | c.print_to_input(file_name=f'm{design_mach:.1f}.txt') 211 | -------------------------------------------------------------------------------- /src/trans.f: -------------------------------------------------------------------------------- 1 | subroutine trans(rto,tk,wo,amn,amp,ampp,w,awp,awpp,cwoppp,axn) 2 | ! to determine throat characteristic 3 | use kinddefine 4 | use gg, only:gam,g2,g5,g6,g7,g8,ga,qt 5 | use contr, only:itle,ie,lr 6 | use troat 7 | implicit none 8 | ! 9 | interface 10 | function fmv(psi) 11 | use kinddefine 12 | implicit none 13 | real(kind=K8) :: fmv 14 | real(kind=K8), intent(in) :: psi 15 | end function fmv 16 | ! 17 | function cubic(ea,eb,ec,ed) 18 | use kinddefine 19 | implicit none 20 | real(kind=K8) :: cubic 21 | real(kind=K8), intent(in) :: ea,eb,ec,ed 22 | end function cubic 23 | end interface 24 | ! 25 | integer(kind=K4) :: i,j,jj,k,kk,nn 26 | real(kind=K8) :: add,amn,amp,ampp,as,awop,awopp,awoppp,awp,awpp 27 | real(kind=K8) :: axn,bet,bs,cs,bx,cwoppp,duy,dxi,eit,four,fma,fmu 28 | real(kind=K8) :: fsa,fsb,fsc,fsy,fsy1,gb,gk,gt,gu,gv,gz,half,hoppp 29 | real(kind=K8) :: hvppp,one,p1,psi,psi1,px,rc,rto,s1,s2,s3,six,sum 30 | real(kind=K8) :: t,t1,thr,tk,tlv,tn1,tn2,tna,trhv,two 31 | real(kind=K8) :: u22,u23,u42,u43,u63,up0,up2,uy 32 | real(kind=K8) :: v02,v03,v22,v23,v42,v43,v63,vo,vp,vpp,vy 33 | real(kind=K8) :: w,wo,wop,wopp,wwo,wy,x,x1,xm,xmp,xmpp,xot,xx1,xxi 34 | real(kind=K8) :: xw,xwp,xwpp,y,y1,y4,y6,ym,yy,zro 35 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,six/6.d+0/,half/5.d-1/ 36 | data trhv/1.5d+0/,thr/3.d+0/,four/4.d+0/,eit/8.d+0/,tlv/1.2d+1/ 37 | nn=iabs(lr) 38 | jj=240/(nn-1) 39 | if(mod(jj,2).ne.0) jj=jj+1 40 | if(jj.lt.10) jj=10 41 | kk=jj*nn-jj 42 | gb=ie/eit 43 | gk=(gam*(gam+2.25d+0*ie-16.5d+0)+2.25d+0*(2+ie))/tlv 44 | gu=one-gam/trhv 45 | gv=(half*(5-3*ie)*gam+ie)/(9-ie) 46 | gz=dsqrt(qt*(gam+one)) 47 | u22=gb+gam/thr/(3-ie) 48 | u42=(gam+(4-ie)*trhv)/six/(3-ie) 49 | if (ie.eq.0) goto 1 50 | gt=(gam*(gam*92.d+0+180.d+0)-9.d+0)/1152.d+0 51 | u23=(gam*(304.d+0*gam+255.d+0)-54.d+0)/1728.d+0 52 | u43=(gam*(388.d+0*gam+777.d+0)+153.d+0)/2304.d+0 53 | u63=(gam*(556.d+0*gam+1737.d+0)+3069.d+0)/10368.d+0 54 | up0=(gam*(52.d+0*gam+75.d+0)-9.d+0)/192.d+0 55 | up2=(gam*(52.d+0*gam+51.d+0)+327.d+0)/384.d+0 56 | v02=(28.d+0*gam-15.d+0)/288.d+0 57 | v22=(20.d+0*gam+27.d+0)/96.d+0 58 | v42=(gam/thr+one)/thr 59 | v03=(gam*(7100.d+0*gam+2151.d+0)+2169.d+0)/82944.d+0 60 | v23=(gam*(3424.d+0*gam+4071.d+0)-972.d+0)/13824.d+0 61 | v43=(gam*(3380.d+0*gam+7551.d+0)+3771.d+0)/13824.d+0 62 | v63=(gam*(6836.d+0*gam+23031.d+0)+30627.d+0)/82944.d+0 63 | goto 2 64 | 1 gt=(gam*(gam*134.d+0+429.d+0)+123.d+0)/4320.d+0 65 | u23=(gam*(854.d+0*gam+807.d+0)+279.d+0)/12960.d+0 66 | u43=(gam*(194.d+0*gam+549.d+0)-63.d+0)/2592.d+0 67 | u63=(gam*(362.d+0*gam+1449.d+0)+3177.d+0)/12960.d+0 68 | up0=(gam*(26.d+0*gam+51.d+0)-27.d+0)/144.d+0 69 | up2=(gam*(26.d+0*gam+27.d+0)+237.d+0)/288.d+0 70 | v02=(34.d+0*gam-75.d+0)/1080.d+0 71 | v22=(10.d+0*gam+15.d+0)/108.d+0 72 | v42=(22.d+0*gam+75.d+0)/360.d+0 73 | v03=(gam*(7570.d+0*gam+3087.d+0)+23157.d+0)/544320.d+0 74 | v23=(gam*(5026.d+0*gam+7551.d+0)-4923.d+0)/77760.d+0 75 | v43=(gam*(2254.d+0*gam+6153.d+0)+2979.d+0)/25920.d+0 76 | v63=(gam*(6574.d+0*gam+26481.d+0)+40059.d+0)/181440.d+0 77 | 2 wwo=wo+(half+(u42-u22+(u63-u43+u23)/rto)/rto)/rto 78 | wop=(one-(gb-gt/rto)/rto)/dsqrt(rto) 79 | wopp=(gu-gv/rto)/rto 80 | hoppp=gk/rto/dsqrt(rto) 81 | hvppp=(3*ie-(10-3*ie)*gam)/four/rto/dsqrt(rto) 82 | amn=wwo/dsqrt(g7-g8*wwo**2) 83 | bet=dsqrt(amn**2-one) 84 | psi1=g2*datan(bet/g2)-datan(bet) 85 | p1=zro 86 | t1=zro 87 | x1=zro 88 | y1=one 89 | fsy1=zro 90 | tn2=-one/bet 91 | fc(1,nn)=x1 92 | fc(2,nn)=y1 93 | fc(3,nn)=amn 94 | fc(4,nn)=psi1 95 | fc(5,nn)=zro 96 | fc(6,nn)=zro 97 | bx=one 98 | sum=zro 99 | fsa=(ie+1)*amn/(g6+g5*amn**2)**ga 100 | do j=1,kk 101 | y=dfloat(kk-j)/kk 102 | if(ie.eq.1) bx=y+y 103 | yy=y*y 104 | tn1=tn2 105 | vo=(((yy*(yy*(yy*v63-v43)+v23)-v03)/rto+yy*(yy*v42-v22)+v02)/rto+ 106 | &half*(yy-one)/(3-ie))/rto 107 | vp=(one+((yy*(two*gam+3*(4-ie))-two*gam-trhv*ie)/(3-ie)/thr+(yy*( 108 | &six*u63*yy-four*u43)+two*u23)/rto)/rto)/dsqrt(rto) 109 | vpp=two*(one+(two*up2*yy-up0)/rto)/rto 110 | ! iterate for x and mach number from characteristic equations 111 | do i=1,10 112 | tna=half*(tn1+tn2) 113 | x=x1+(y-y1)/tna 114 | dxi=dsqrt((y-y1)**2+(x-x1)**2) 115 | xot=x/gz 116 | vy=gz*(vo+xot*(vp+xot*(half*vpp+xot*hvppp/thr)))/dsqrt(rto) 117 | w=amn/dsqrt(g6+g5*amn**2) 118 | t=dasin(vy*y/w) 119 | fsy=ie*vy/w/amn 120 | p1=half*(fsy1+fsy)*dxi 121 | 3 psi=p1+psi1+t1-t 122 | fma=fmv(psi) 123 | if(dabs(amn-fma).lt.1.d-10) goto 5 124 | fmu=dasin(one/fma) 125 | tn2=dtan(t-fmu) 126 | amn=fma 127 | enddo 128 | ! iteration complete 129 | 5 if(mod(j,2).eq.0) goto 6 130 | as=y1-y 131 | fsb=bx/dsin(fmu-t)/(g6+g5*fma**2)**ga 132 | goto 7 133 | 6 bs=y1-y 134 | cs=as+bs 135 | s1=(two-bs/as)*cs/six 136 | s3=(two-as/bs)*cs/six 137 | s2=cs-s1-s3 138 | fsc=bx/dsin(fmu-t)/(g6+g5*fma**2)**ga 139 | add=s1*fsa+s2*fsb+s3*fsc 140 | sum=add+sum 141 | fsa=fsc 142 | 7 x1=x 143 | y1=y 144 | t1=t 145 | fsy1=fsy 146 | psi1=psi 147 | if(mod(j,jj).ne.0) goto 8 148 | k=nn-j/jj 149 | fc(1,k)=x 150 | fc(2,k)=y 151 | fc(3,k)=fma 152 | fc(4,k)=psi 153 | fc(5,k)=t 154 | fc(6,k)=sum 155 | 8 enddo 156 | do j=1,nn 157 | fc(1,j)=fc(1,j)/tk 158 | fc(2,j)=fc(2,j)/tk 159 | fc(6,j)=one-fc(6,j)/sum 160 | enddo 161 | axn=fc(1,1) 162 | awop=wop*tk/gz 163 | awopp=wopp*(tk/gz)**2 164 | awoppp=two*hoppp*(tk/gz)**3 165 | cwoppp=six*(w-wo-axn*(awop+axn*awopp/two))/axn**3 166 | if(cwoppp.lt.awoppp) cwoppp=awoppp 167 | awp=awop+axn*(awopp+axn*cwoppp/two) 168 | awpp=awopp+axn*cwoppp 169 | amp=awp*g7*(amn/w)**3 170 | ampp=amp*(awpp/awp+thr*g5*amp*w*w/amn) 171 | if(lr.gt.0) return 172 | lr=nn 173 | rc=rto-one 174 | write (2,12) itle,rc,awop,awopp,awoppp 175 | do j=1,nn 176 | y=dfloat(j-1)/(nn-1) 177 | yy=y*y 178 | y4=yy**2 179 | y6=yy**3 180 | duy=(half*yy+(u42*y4-u22*yy+(u63*y6-u43*y4+u23*yy)/rto)/rto)/rto 181 | uy=wo+duy 182 | vo=(((yy*(yy*(yy*v63-v43)+v23)-v03)/rto+yy*(yy*v42-v22)+v02)/rto+ 183 | &half*(yy-one)/(3-ie))/rto 184 | vy=gz*vo*y/dsqrt(rto) 185 | wy=dsqrt(uy**2+vy**2) 186 | ym=wy/dsqrt(g7-g8*wy**2) 187 | write (2,13) y,uy,vy,wy,ym 188 | if(mod(j,10).eq.0) write (2,14) 189 | enddo 190 | xx1=cubic(cwoppp/six,awopp/two,awop,wo-one) 191 | xxi=cubic(awoppp/six,awopp/two,awop,wo-w) 192 | write (2,15) xx1,xxi,w,cwoppp,tk 193 | write (2,16) 194 | px=axn+1.d-1 195 | do j=1,11 196 | x=.1d+0*(j-1) 197 | xw=wo+x*(awop+x*(awopp/two+x*cwoppp/six)) 198 | xwp=awop+x*(awopp+x*cwoppp/two) 199 | xwpp=awopp+x*cwoppp 200 | xm=xw/dsqrt(g7-g8*xw**2) 201 | xmp=xwp*g7*(xm/xw)**3 202 | xmpp=xmp*(xwpp/xwp+thr*g5*xmp*xw*xw/xm) 203 | if(x.lt.axn.or.x.gt.px) goto 11 204 | write (2,18) axn,w,awp,awpp,amn,amp,ampp 205 | 11 write (2,17) x,xw,xwp,xwpp,xm,xmp,xmpp 206 | enddo 207 | return 208 | ! 209 | 12 format (1x,8x,3a4,' THROAT VELOCITY DISTRIBUTION, X=O, RC=',f10.6/ 210 | &/10x,'DERIVATIVES TAKEN WITH RESPECT TO X/Y*, WOP=',f11.8//10x,'WO 211 | &PP=',1pe15.7,5x,'WOPPP=',e15.7//10x,'Y/YO',7x,'U/A*',10x,'V/A*',11 212 | &x,'W',11x,'MACH NO.'/) 213 | 13 format (1x,f14.4,4f14.8) 214 | 14 format (1x) 215 | 15 format (1x,9x,'FROM CUBIC, X/Y* =',f11.8,' FOR W= 1.0'//22x,'X/Y* 216 | &=',f11.8,' FOR W=',f11.8 //10x,'CORRECTED WOPPP=',1pe15.7//10x,'RM 217 | &ASS = Y*/YO =',0pf13.10//) 218 | 16 format (1x,9x,'AXIAL VELOCITY DISTRIBUTION, Y=0'//10x,'X/Y*',9x,'W 219 | &',17x,'WP',16x,'WPP',15x,'M',17x,'MP',16x,'MPP'/) 220 | 17 format (1x,f13.3,1p6e18.7) 221 | 18 format (1x,f16.8,1pe15.7,5e18.7) 222 | end subroutine trans 223 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd 364 | /src/.ipynb_checkpoints/ 365 | /legacy/python/search40/ 366 | /legacy/python/search45/ 367 | /legacy/python/search50/ 368 | /legacy/python/search53/ 369 | /legacy/python/search57/ 370 | /legacy/python/search60/ 371 | /legacy/python/search62/ 372 | /legacy/python/SolidWorks/ 373 | /legacy/python/outputs/ 374 | /legacy/python/inputcards/ 375 | /legacy/.ipynb_checkpoints/ 376 | /legacy/.ipynb_checkpoints/ 377 | /.idea/ 378 | /build/ 379 | /legacy/python/.ipynb_checkpoints/ 380 | /legacy/ 381 | /outputs/ 382 | /inputcards/ 383 | /.ipynb_checkpoints/ 384 | .DS_Store -------------------------------------------------------------------------------- /src/main.f: -------------------------------------------------------------------------------- 1 | ! main part of 2 | ! program contur(input,output,unit(1)=input,unit(2)=output) 3 | ! 4 | ! nozzle contour program vev00028 for axisymmetric or planar flow 5 | ! with radial flow region and/or with center-line velocity or mach 6 | ! number distributions defined by polynomials. 7 | ! 8 | ! correction applied for growth of turbulent boundary layer. 9 | ! perfect gas is assumed with constant specific heat ratio, gam, 10 | ! compressibility factor, zo, and recovery factor, ro, as inputs. 11 | ! also input is gas constant, ar, in sq ft per sq second per deg r. 12 | ! if vism is sutherlands temperature, viscosity follows sutherlands 13 | ! law above vism, but is linear with temperature below vism. 14 | ! if (vism .le. 1.d+0) viscosity=visc*temperature**vism mai 15 | ! 16 | program contur 17 | use kinddefine 18 | use gg, only:gam,gm,g1,g2,g3,g4,g5,g6,g7,g8,g9,ga,rga,qt 19 | use coord, only:dmdx,dpx,fs,s,sd,spr,ttr,waltan,wmn 20 | use corr, only:dr2,rco,drx,sl 21 | use prop, only:ar,zo,ro,visc,vism,sfoa,xbl,conv 22 | use param, only:ah,cmach,qm 23 | use jack, only:aj,sj,xj,yj 24 | use contr, only:itle,ie,it,jb,jq,jx,kat,kbl,king,ko,lv,nocon 25 | ! 26 | implicit none 27 | ! 28 | interface 29 | subroutine splind(x,y,tn2,tnl,l) 30 | use kinddefine 31 | implicit none 32 | integer(kind=K4),intent(in) :: l 33 | real(kind=K8),dimension(1),intent(in) :: x,y 34 | real(kind=K8),intent(in) :: tn2,tnl 35 | end subroutine splind 36 | ! 37 | subroutine xyz(xx,yy,yyp,yypp) 38 | use kinddefine 39 | implicit none 40 | real(kind=K8),intent(in) :: xx 41 | real(kind=K8),intent(out) :: yy,yyp,yypp 42 | end subroutine xyz 43 | end interface 44 | ! 45 | integer(kind=K4) :: ipp,jd,jj,k,kap,kup,nc 46 | real(kind=K8) :: bj,cn,csk,curv 47 | real(kind=K8) :: dy,one,slong,snk,tmax,two 48 | real(kind=K8) :: x,xend,xinc,xinc2 49 | real(kind=K8) :: xlow,xmax,xmid,xst,xx,ymax,yy,yyp,yypp,wang,zro 50 | character(len=4,kind=K3) :: l1,l2,l3,l4,l5,la,lb 51 | character(len=8,kind=K3) ::dc1,dc2,dc3,dc4,dc5,dc6,dc7,dca,dcb,dcc 52 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,dc7/'CURVATUR'/ 53 | data dc1/' D2Y/DX2'/,dc2/' '/,dc3/' ANGLE'/ 54 | data dc4/' DY/DX'/,dc5/' DY/DS'/,dc6/' DX/DS'/ 55 | data l1/' X'/,l2/' Y'/,l3/' S'/,l4/' '/,l5/'DIFF'/ 56 | conv=90.d+0/dasin(one) 57 | it=0 58 | nc=0 59 | la=l1 60 | lb=l4 61 | dca=dc4 62 | dcb=dc2 63 | jj=1000 64 | dcc=dc1 65 | ! 66 | open(unit=1,file='input.txt',status='old',access='sequential', 67 | &form='formatted',action='read',blank='null') 68 | open(unit=2,file='output.txt',status='unknown',access='sequential' 69 | &,form='formatted',action='write') 70 | 1 read (1,30,end=24) itle,jd 71 | if (itle(1) .eq. l4) goto 24 72 | ie=1+jd 73 | qt=one/(1+ie) 74 | ! 75 | read (1,28) gam,ar,zo,ro,visc,vism,sfoa,xbl 76 | ! for gamma=1.4, g9=5, g8=.2, g7=1.2, g6=5/6, g5=1/6, g4=1/sqrt(6), 77 | ! g3=1.5, g2=sqrt(6), g1=2.5 78 | gm=gam-one 79 | g1=one/gm 80 | g9=two*g1 81 | g8=one/g9 82 | g7=one+g8 83 | g6=one/g7 84 | g5=g8*g6 85 | rga=two*g5 86 | ga=one/rga 87 | g4=dsqrt(g5) 88 | g3=ga/two 89 | g2=one/g4 90 | if (ie .eq. 0) ah=zo 91 | if (ie .eq. 0) zo=one 92 | qm=one 93 | jx=0 94 | 2 jq=0 95 | lv=0 96 | 3 call axial 97 | if (lv .lt. 0) goto 1 98 | call perfc 99 | if (nocon .ne. 0) goto 24 100 | if ((jq .gt. 0) .or. (jx .gt. 0)) goto 3 101 | if (jb .gt. 0) call bound 102 | if (xbl .eq. 1.d+3) goto 5 103 | if (it .lt. 1) goto 4 104 | la=l3 105 | dca=dc5 106 | dcc=dc7 107 | kup=it 108 | kap=kup+1 109 | xend=zro 110 | ! 111 | read (1,28,end=24) (sj(k),k=1,kup),xst 112 | csk=one/dsqrt(one+drx(kat)**2) 113 | snk=csk*drx(kat) 114 | call splind(sl,rco,zro,snk,kat) 115 | goto 6 116 | 4 if (lv .gt. 0) goto 24 117 | if (jx .lt. 0) goto 1 118 | goto 2 119 | 5 continue 120 | ! 121 | read (1,28,end=24) xst,xlow,xend,xinc,bj,xmid,xinc2,cn 122 | if (xst .eq. xbl) xst=s(1) 123 | nc=cn-one 124 | if (jb .le. 0) call splind(s,fs,waltan(1),waltan(king),king) 125 | if (jb .gt. 0) call splind(s,rco,drx(1),drx(kat),kat) 126 | if (xend .gt. zro) goto 6 127 | lb=l5 128 | dcb=dc4 129 | 6 slong=s(king)-s(1) 130 | ipp=0 131 | write (2,25) itle,slong 132 | write (2,31) la,l2,dca,dc3,dcc,dcb,lb 133 | if (jb .gt. 0) goto 7 134 | write (2,26) xst,fs(1),waltan(1),zro,sd(1) 135 | xmax=slong+xst 136 | ymax=fs(king) 137 | tmax=waltan(king) 138 | goto 8 139 | 7 write (2,26) xst,rco(1),drx(1),zro,dr2 140 | xmax=s(kat)-s(1)+xst 141 | ymax=rco(kat) 142 | tmax=drx(kat) 143 | 8 if (it .gt. 0) goto 11 144 | jb=int(bj) 145 | if (xend .gt. zro) goto 10 146 | if (jb .lt. 0) goto 9 147 | kup=king-1 148 | kap=king-1 149 | goto 11 150 | 9 kup=-jb 151 | kap=kup+1 152 | ! 153 | read (1,28,end=24) (sj(k),k=1,kup) 154 | goto 11 155 | 10 if (xinc .gt. zro) kup=(xend-xlow)/xinc+1.d-2 156 | if (xmid .ne. zro) jj=(xmid-xlow)/xinc+1.d-2 157 | if (xmid .ne. zro) kup=jj+(xend-xmid)/xinc2+1.d-2 158 | if (jb .gt. 10) kup=jb 159 | if (jb .gt. 10) xinc=slong/bj 160 | kap=(xmax-xlow)/xinc+1 161 | if (xmid .ne. zro) kap=jj+(xmax-xmid)/xinc2+1 162 | 11 do k=1,kup 163 | if (xend .eq. zro) goto 12 164 | x=xlow+k*xinc 165 | if (k .gt. jj) x=xmid+(k-jj)*xinc2 166 | goto 13 167 | 12 if ((it .lt. 1) .and. (jb .ge.0)) x=s(k+1) 168 | if ((it .gt. 0) .or. (jb .lt.0)) x=sj(k) 169 | 13 xx=x-xst+s(1) 170 | if (k .lt. kap) call xyz(xx,yy,yyp,yypp) 171 | if (k .eq. kap) x=xmax 172 | if (k .ge. kap) yy=ymax 173 | if (k .ge. kap) yyp=tmax 174 | if (k .ge. kap) yypp=zro 175 | if (it .lt. 1) goto 16 176 | if (ipp .gt. 0) goto 14 177 | yj(k)=yy 178 | aj(k)=dasin(yyp) 179 | wang=conv*aj(k) 180 | curv=yypp/dcos(aj(k)) 181 | write (2,26) x,yy,yyp,wang,curv 182 | goto 18 183 | 14 yy=yy-s(1)+xst 184 | xj(k)=yy 185 | wang=conv*dacos(yyp) 186 | write (2,26) x,yy,yyp,wang 187 | goto 18 188 | 16 wang=conv*datan(yyp) 189 | if ((xend .eq. zro) .and. (jb .ge. 0)) dy=yyp-waltan(k+1) 190 | if (jb .le. 0) goto 17 191 | fs(k+1)=yy 192 | waltan(k+1)=yyp 193 | sd(k+1)=yypp 194 | 17 if (xend.gt.zro.or.jb.lt.0) write (2,26) x,yy,yyp,wang,yypp 195 | if (xend.eq.zro.and.jb.ge.0) write (2,26) x,yy,yyp,wang,yypp,dy 196 | 18 if (mod(k,10) .eq. 0) write (2,29) 197 | if (mod(k,50) .ne. 0) goto 19 198 | write (2,25) itle,slong 199 | write (2,31) la,l2,dca,dc3,dcc,dcb,lb 200 | 19 continue 201 | enddo 202 | if ((it .gt. 0) .and. (ipp .eq. 1)) call plate 203 | if (ipp .ge. nc) goto 20 204 | ipp=ipp+1 205 | write (2,25) itle,slong 206 | write (2,31) la,l2,dca,dc3,dcc 207 | write (2,26) xst,rco(1),drx(1),zro,dr2 208 | goto 11 209 | 20 if ((ipp .gt. 0) .or. (jx .lt. 0)) goto 1 210 | if (it .eq. 0) goto 21 211 | ipp=1 212 | call splind(sl,s,one,csk,kat) 213 | write (2,29) 214 | write (2,31) l3,l1,dc6,dc3 215 | write (2,26) xst,xst,one,zro 216 | goto 11 217 | 21 if (jb) 1,2,22 218 | 22 call splind(s,wmn,dmdx(1),dmdx(king),king) 219 | do k=1,kup 220 | x=xlow+k*xinc 221 | if (xend .eq. zro) x=s(k+1) 222 | xx=x-xst+s(1) 223 | if (k .lt. kap) call xyz(xx,yy,yyp,yypp) 224 | if (k .ge. kap) yy=cmach 225 | if (k .ge. kap) yyp=zro 226 | s(k+1)=x 227 | wmn(k+1)=yy 228 | ttr(k+1)=one+g8*yy**2 229 | spr(k+1)=one/ttr(k+1)**(one+g1) 230 | dmdx(k+1)=yyp 231 | dpx(k+1)=-gam*yy*yyp*spr(k+1)/ttr(k+1) 232 | enddo 233 | s(1)=xst 234 | kat=kup+1 235 | kbl=kat+4 236 | ko=1 237 | call bound 238 | if (jb .eq. 7) stop 239 | if (jb .gt. 10) goto 1 240 | write (2,25) itle,slong 241 | write (2,31) l1,l2,dc4 242 | write (2,27) (s(k),rco(k),drx(k),k=1,kat) 243 | goto 1 244 | 24 close(1) 245 | close(2) 246 | stop 247 | ! 248 | 25 format (1x,9x,3a4,'COORDINATES AND DERIVATIVES, LENGTH=',f12.7/) 249 | 26 format (1x,8x,2f15.6,1p4e20.8) 250 | 27 format (10(9x,0P2f15.6,1pe20.8/)) 251 | 28 format (8e10.3) 252 | 29 format (1x) 253 | 30 format (3a4,i3) 254 | 31 format (1x,14x,a4,'(IN)',7x,a4,'(IN)',6x,a8,12x,a8,14x,a8,9x,a8,2x 255 | &,a4 /) 256 | end program contur 257 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ConturPy: Python Hypersonic Nozzle Design 2 | 3 | 4 | ## Introduction 5 | ConturPy is a python library that provides an interface to J. C. Sivells' CONTUR program for supersonic and hypersonic 6 | nozzle design. 7 | 8 | This repository provides compiled binaries for both Windows x86 and Apple Silicon, tested on an AMD Ryzen R3900XT and an 9 | Apple M1 on MacOS. Other architectures will need to compile the Fortran code from src and provide an explicit path to the 10 | executable through the `executable` keyword argument for `ContourApplication`. 11 | 12 | ## Background 13 | The code largely relies on Sivells' CONTUR code ported to 14 | modern Fortran by F.-L. Zavalan [here](https://github.com/aldorona/contur), many thanks to F. Zavalan and A. Rona. 15 | The axial.f source file has been modified from their port, however: S. Schneider notes in 16 | [NASA CR 197286](https://ntrs.nasa.gov/api/citations/19950015019/downloads/19950015019.pdf) 17 | that Sivells' code does not produce streamlines when ETAD is not 60. Schneider fixed the problem by modifying the AXIAL 18 | subroutine by duplicating lines 111 and 112 above line 43. The same change has been made to the axial.f source file. 19 | 20 | ## Dependencies 21 | - numpy >~ 1.22 22 | - matplotlib >~ 3.5 23 | 24 | ## Usage 25 | ConturPy is designed to do 4 things: 26 | 1. Create input cards for CONTUR 27 | 2. Wrap the CONTUR executable 28 | 3. Interpret the CONTUR results 29 | 4. Create images and tables for all CONTUR outputs 30 | 31 | --- 32 | ### Creating input cards 33 | ConturPy provides the `ConturSettings` class that produces input cards in the format that CONTUR accepts. To start, 34 | create an instance of the `ConturSettings` class: 35 | 36 | ```python 37 | from conturpy import ConturSettings 38 | cs = ConturSettings() 39 | ``` 40 | `ConturSettings` accepts multiple keyword arguments which are not covered here. Once the object is created, assign 41 | values to each of the input fields and save the file to a convenient location: 42 | 43 | ```python 44 | from conturpy import ConturSettings 45 | cs = ConturSettings() 46 | 47 | dmach = 6.0 # design mach 48 | throat_radius = 0.65 / 2 # inches 49 | 50 | # Card 1: the title of the simulation 51 | cs["ITLE"] = f"Mach {dmach}" 52 | 53 | # Card 2 contains gas properties. As air is the assumed working fluid, no changes are required 54 | 55 | # Card 3: key design parameters 56 | cs["ETAD"] = 60 # Angle at point D 57 | cs["RC"] = 6.0 # Radius of curvature at throat [multiple of throat radius] 58 | cs["CMC"] = dmach # Design mach 59 | cs["SF"] = throat_radius 60 | 61 | # Card 6 (B): stagnation and heat transfer properties 62 | cs["PPQ"] = 120 # Stagnation pressure [psia] 63 | cs["TO"] = 1000 # Stagnation temperature [R] 64 | cs["TWT"] = 540 # Wall temperature [R] 65 | cs["TWAT"] = 540 # Water-cooling temp [R] (suggest setting to TWT since water cooling not assumed) 66 | 67 | # Card 7 (D): interpolation parameters 68 | cs["XLOW"] = 0 # Point to begin interpolating contour [in] 69 | cs["XEND"] = 20 # Point to end interpolating contour [in] 70 | cs["XINC"] = .1 # Increment to interpolate by [in] 71 | 72 | # Create the input text file and save it to 'm5.0.txt' in the folder 'inputcards' 73 | # ! Important ! the folder for output_directory must already exist 74 | cs.print_to_input(file_name=f'm{dmach:.1f}.txt', output_directory='inputcards') 75 | ``` 76 | 77 | --- 78 | ### Running CONTUR 79 | Once your input cards have been created, `ConturApplication` wraps CONTUR and can process the input cards, producing 80 | CONTUR output text files and instances of the `ConturResult` class. ConturApplication provides three methods for running 81 | CONTUR: 82 | 1. `ConturApplication.run()` runs CONTUR in the current working directory: `input.txt` is read and `output.txt` is 83 | created. Returns `True` if CONTUR doesn't timeout, else `False`. 84 | 2. `ConturApplication.batch_input_files(file_list, output_dir=os.getcwd(), refine_amt=21)` takes every file name in 85 | `file_list`, runs CONTUR in the local directory, and saves the outputs to the directory `output_dir` by appending 86 | `_result.txt` to the original input file name. This returns a list of `ConturResults` for every successful input, 87 | interpolating between the coordinates by `refine_amt` many points. 88 | 3. `ConturApplication.batch_input_folder(folder, output_dir=os.getcwd(), refine_amt=21)` takes every file in 89 | `folder`, runs CONTUR in the local directory, and saves the outputs to the directory `output_dir` by appending 90 | `_result.txt` to the original input file name. This returns a list of `ConturResults` for every successful input, 91 | interpolating between the coordinates by `refine_amt` many points. 92 | 93 | If running on an architecture other than Windows x86_64 or Apple Silicon ARM_64, CONTUR must be compiled from the files 94 | in the `src/` directory and `ConturApplication` must be created with the `executable=path_to_executable` argument. 95 | 96 | Continuing the example from above: 97 | 98 | ```python 99 | from conturpy import ConturApplication 100 | 101 | ca = ConturApplication() 102 | res = ca.batch_input_folder('inputcards', output_dir='outputs') 103 | 104 | print(res) 105 | >> [ConturResult: 106 | 4317 raw lines 107 | 76 output sections] 108 | ``` 109 | 110 | 111 | --- 112 | ### Reading CONTUR's Output 113 | ConturPy reads CONTUR's output by creating an instance of the `ConturResult` class by calling 114 | `ConturResult(filename, refine_amt=21)` where `filename` is the filename of the file produced by CONTUR, `refine_amt` is 115 | the number of interpolated points to create between each point on the wall contour defined in the output file. 116 | 117 | `ConturResult` provides the following attributes: 118 | 1. `ConturResult.title`: the title of the simulation from the input card "ITLE" 119 | 2. `ConturResult.nozzle_length`: the length of the nozzle from throat to exit, in inches 120 | 3. `ConturResult.design_mach`: the design Mach number 121 | 4. `ConturResult.coordinates`: the wall coordinates, interpolated if `refine_amt > 1` 122 | 5. `ConturResult.sections`: a list of all identified sections in the output 123 | 6. `ConturResult.characteristics`: a list of all identified characteristics 124 | 7. `ConturResult.contours`: a list of all identified contours 125 | 8. `ConturResult.bl_calculations`: a list of all identified boundary layer calculations 126 | 127 | `ConturResult` also provides the `ConturResult.save_all(directory)` method which generates `.csv` files for every 128 | identified table and `.png` files for every plotting function. 129 | 130 | Each section in `ConturResult.sections` is a class derived from `BaseConturOutput` and provides the raw text, all 131 | identified parameters converted to Python numeric types, and all identified tables. For example: 132 | 133 | ```python 134 | r = res[0] 135 | 136 | print(r.sections[1]) 137 | >> ConturInviscidContour: 138 | 64 lines 139 | 8 parameter groups 140 | 1 tables 141 | 142 | print(r.sections[1].parameters[0]) 143 | >> [('CMACH', 6.0), ('BMACH', 6.0), ('EPSI/ETA', 0.0), ('(N)', 41.0), ('(M)', 61.0)] 144 | 145 | print(r.sections[1].tables[0]) 146 | >> ConturTable(POINT X X_IN Mach DM_over_DX D2M_over_DX2 D3M_over_DX3 W_Q_over_Astar DW_over_DX D2W_over_DX2 D3W_over_DX3 147 | 1 18.8308 6.12002 7 3.83627e-16 2.07123e-17 0.014919 2.33333 1.18404e-17 6.39269e-19 0.000460461 148 | 2 18.2311 5.92512 6.99948 0.00261014 -0.00858423 0.0137102 2.33332 8.05763e-05 -0.000265081 0.000424048 149 | 3 17.6361 5.73172 6.99593 0.0100753 -0.0163861 0.0125107 2.33321 0.000311459 -0.000507767 0.000392708 150 | 4 17.0456 5.53984 6.98671 0.0218612 -0.0234213 0.0113207 2.33292 0.000678228 -0.000732403 0.000369841 151 | 5 16.46 5.3495 6.96952 0.0374515 -0.0297055 0.0101402 2.33239 0.00116972 -0.000944884 0.000357716 152 | 6 15.8792 5.16075 6.94244 0.0563482 -0.0352548 0.00896961 2.33154 0.00177865 -0.00115207 0.000357903 153 | 7 15.3034 4.97361 6.90387 0.0780716 -0.0400855 0.00780897 2.33031 0.00250193 -0.00136143 0.000371642 154 | ... 155 | 39 0.68614 0.22299 1.24954 0.449063 0.0611029 -0.021654 1.19489 0.327238 -0.039429 -0.0443235 156 | 40 0.46225 0.15023 1.15057 0.434836 0.0660015 -0.0221053 1.12072 0.334891 -0.0286535 -0.0518158 157 | 41 0.30914 0.10047 1.08478 0.42447 0.0694097 -0.0224139 1.06915 0.338652 -0.0203596 -0.0564415 ) 158 | 159 | ``` 160 | 161 | The `ConturTable` object also provides `.to_numpy()` and `.to_pandas()` methods to convert the table to other formats. 162 | Pandas must be installed to call `.to_pandas()` 163 | 164 | 165 | --- 166 | ### Report Generation 167 | ConturPy can generate `.csv` files for all `ConturTable` instances, as well as create various plots. Each individual 168 | plot and table can be saved, however `ConturResult.save_all(directory)` is fast enough and the results are small enough 169 | that it is suggested to simply call the `save_all` method. 170 | 171 | Some example plots for a Mach 5.0 nozzle are below: 172 | 173 | ![Nozzle Characteristic Lines](assets/Nozzle_Characteristics.png) 174 | > Identified characteristics, colored by Mach number, superimposed on the nozzle contour and boundary layer thickness. 175 | 176 | ![Throat Characteristic Lines](assets/Throat_Characteristics.png) 177 | > Close-up of the characteristics at the throat, including the bent sonic line. 178 | 179 | ![Boundary Layer Thickness](assets/Boundary_Layer_Thickness.png) 180 | > Boundary layer thickness as a function of the streamwise station. 181 | 182 | ![Boundary Layer and Wall Temperature](assets/Boundary_Layer_Temperature.png) 183 | > Wall & boundary layer temperature as a function of streamwise station. 184 | 185 | ![Contours](assets/Contours.png) 186 | > Flow contours. 187 | 188 | ![Flow Angles](assets/Flow_Angles.png) 189 | > Flow angles as calculated on the characteristic lines. Radial flow is clearly visible. 190 | 191 | ![Flow Angles at Throat](assets/Flow_Angles_At_Throat.png) 192 | > Closeup of the flow angles at the throat. 193 | 194 | ## Input Card Defaults 195 | 196 | ### Card 1 197 | | Key | Default | Author's Notes | 198 | | -- | -- | -- | 199 | | ITLE | "Title" | The title. The maximum length is 10 characters. ConturSettings center-aligns the title. | 200 | | JD | 0 | Axisymmetric or planar nozzle. Set to 0 for axisymmetric or -1 for planar nozzle. | 201 | 202 | ### Card 2 203 | | Key | Default | Author's Notes | 204 | | -- | -- | -- | 205 | | GAM | 1.4 | Ratio of specific heats. | 206 | | AR | 1716.563 | Gas constant in ft^2/sec^2 * R | 207 | | ZO | 1 | Compressability factor for axisymmetric nozzle. Untested: half distance (in) between walls and assumed compressability factor of 1 | 208 | | RO | 0.896 | Turbulent boundary layer recovery factor (see Sivells' paper) | 209 | | VISC | 2.27E-08 | Constant in viscosity law (see Sivells' paper) | 210 | | VISM | 198.72 | Constant in viscosity law (see Sivells' paper) | 211 | | SFOA | 0 | If zero: 3rd or 4th degree velocity distribution depending on IX. If negative: absolute value is distance from throat to point G (see Sivells' paper). If positive: distance from throat to point A (see Sivells' paper). | 212 | | XBL | 1000 | Where to start interpolating. If 1000, use spline fit to get evenly spaced points on wall contour. | 213 | 214 | 215 | 216 | ### Card 3 217 | | Key | Default | Author's Notes | 218 | | -- | -- | -- | 219 | | ETAD | 60 | Inflection angle for radial flow. If ETAD=60, the entire centerline velocity distribution is specified; IQ=1 and IX=0 on card 4. | 220 | | RC | 6 | The radius of curvature of the throat: multiples of throat radius. Suggest in the neighborhood of 5.5-6.0 | 221 | | FMACH | 0 | If ETAD is not 60, Mach number at point F (see Sivells' paper) | 222 | | BMACH | 0 | If ETAD is not 60, Mach number at point B (see Sivells' paper) | 223 | | CMC | 0 | The design mach number at point C (see Sivells' paper). This should be the design mach number of the nozzle. If ETAD is not 0, check Sivells' paper as this parameter is important. | 224 | | SF | -3 | If positive, the nozzle has this as the throat radius (or half height) in inches. If 0, the nozzle has radius (or half height) 1 inch. If negative, the nozzle has this as the exit radius (or half height) in inches. | 225 | | PP | 0 | Location of point A (see Sivells' paper). Strongly suggest setting to 0 (driven dimension) unless user is positive they want to specify location A. | 226 | | XC | 0 | Nondimensional distance from radial source to point C (see Sivells' paper). Suggest 0 (4th degree velocity distribution). | 227 | 228 | 229 | ### Card 4 230 | | Key | Default | Author's Notes | 231 | | -- | -- | -- | 232 | | MT | 61 | Number of points on characteristic CD if ETAD=60 or EG if ETAD is not 60 (see Sivells' paper). Must be odd. | 233 | | NT | 41 | Number of points on axis IE (see Sivells' paper). Make sure abs(LR) + abs(NT) extless{}= 149. Must be odd. | 234 | | IX | 0 | Unsure the impact of this parameter (see Sivells' paper). | 235 | | IN | 10 | If nonzero, the downstream value of the second derivative of velocity at point B is 0.1 * IN times the transonic value if ETAD=60 or 0.1 * abs(IN) times the radial value if ETAD is not 60. Use 0 for throat only. Suggest 10. | 236 | | IQ | 0 | If ETAD is not 60, 0 for complete contour, 1 for throat only, and -1 for downstream only. | 237 | | MD | 61 | Number of points on characteristic AB (see Sivells' paper). No more than 125. Must be odd. | 238 | | ND | 69 | Number of points on axis BC (see Sivells' paper). No more than 150. | 239 | | NF | -61 | Number of points on characteristic CD if ETAD is not 60. See Sivells' paper if using. | 240 | | MP | 0 | Number of points on section GA (see Sivells' paper) if FMACH is not equal to BMACH. Sivells notes "Usually not known for initial calculation" | 241 | | MQ | 0 | Number of points downstream of point D if parallel contour desired. Negative to stop inviscid printout. | 242 | | JB | 1 | If positive: number of boundary layer calculations before spline fit. Negative impact is unknown, see Sivells' paper. Suggest 1. | 243 | | JX | 0 | Positive calculates streamlines. If XBL = 1000, spline fit after invisid calculation if JX=0 or repeat of calculation if negative. If XBL is not 1000, repeat calculations. | 244 | | JC | 1 | If not zero, print out inviscid characteristics for every JC characteristic. Positive for upstream and negative for downstream. | 245 | | IT | 0 | Unsure. | 246 | | LR | -25 | Number of points on throat characteristic. Negative prints out transonic solution. If 0, M=1 at point I. See NT. | 247 | | NX | 13 | Logarithmic spacing for upstream contour. 10 is closer spacing and 20 is further spacing. Between 10 or 20. Suggest 13. | 248 | 249 | 250 | ### Card A 251 | | Key | Default | Author's Notes | 252 | | -- | -- | -- | 253 | | NOUP | 50 | Unsure. | 254 | | NPCT | 85 | Unsure. | 255 | | NODO | 50 | Unsure. | 256 | 257 | ### Card B 258 | | Key | Default | Author's Notes | 259 | | -- | -- | -- | 260 | | PPQ | 90 | Stagnation pressure in PSIA | 261 | | TO | 1030 | Stagnation temperature in Rankine | 262 | | TWT | 540 | Throat wall temperature in Rankine | 263 | | TWAT | 540 | Wall temperature at point D | 264 | | QFUN | 0 | If specified, heat transfer function at throat (see Sivells' paper) | 265 | | ALPH | 0 | See Sivells' paper: temperature distribution in boundary layer (either 0 or 1). Suggest 0 for parabolic distribution. | 266 | | IHT | 0 | Unused. | 267 | | IR | 0 | Unsure. | 268 | | ID | 1 | If 1, axisymmetric effects are inculded in boundary layer parameters. Negative suppresses printout of boundary layer calculations. | 269 | | LV | 5 | The number of times the boundary-layer solution is iterated. Sivells reccomends 5. | 270 | 271 | ### Card C 272 | | Key | Default | Author's Notes | 273 | | -- | -- | -- | 274 | | ETAD | 60 | Unsure. | 275 | | QM | 0 | Unsure. | 276 | | XJ | 0 | Unsure. | 277 | 278 | 279 | ### Card D 280 | | Key | Default | Author's Notes | 281 | | -- | -- | -- | 282 | | XST | 1000 | Where to place the throat. If 1000, uses PP to place point A. | 283 | | XLOW | 0 | Where to start interpolation for wall contour (in). Anything before the throat gives bad data. | 284 | | XEND | 50 | Where to end interpolation for wall contour (in). If zero, unsure. | 285 | | XINC | 2 | Increments for interpolation wall contour (in) | 286 | | BJ | 0 | Unsure. | 287 | | XMID | 0 | Unsure. | 288 | | XINC2 | 0 | Unsure. | 289 | | CN | 0 | Unsure. | 290 | -------------------------------------------------------------------------------- /src/perfc.f: -------------------------------------------------------------------------------- 1 | subroutine perfc 2 | ! 3 | ! to obtain the inviscid contour of the nozzle 4 | ! 5 | use kinddefine 6 | use gg, only:gam,g1,g2,g4,g5,g6,g7,g8,ga,qt 7 | use cline, only:axis,taxi,frip,zonk,seo,cse 8 | use coord, only:s,fs,waltan,sd,wmn,ttr,dmdx,spr,dpx,secd,xbin,xcin 9 | &,gma,gmb,gmc,gmd 10 | use work, only:wall,wax,way,wan,a,b,fclast 11 | use prop, only:xbl,conv 12 | use param, only:etad,rc,amach,bmach,cmach,emach,gmach,sf,wwo,wwop, 13 | &qm,cbet,xe,eta,epsi,bpsi,xo,yo,rrc,sdo,xb,xc,ah,se,tye,xa 14 | use troat 15 | use contr, only:itle,ie,lr,it,jb,jq,kat,kbl,king,ko,nocon,mc,ip,iq 16 | &,ise,jc,m,mp,mq,n,np,nf,nut 17 | ! 18 | implicit none 19 | ! 20 | interface 21 | function fmv(psi) 22 | use kinddefine 23 | implicit none 24 | real(kind=K8) :: fmv 25 | real(kind=K8), intent(in) :: psi 26 | end function fmv 27 | ! 28 | subroutine ofeld(a,b,c,nocon) 29 | use kinddefine 30 | implicit none 31 | integer(kind=K4),intent(out) :: nocon 32 | real(kind=K8),dimension(5),intent(in) :: a,b 33 | real(kind=K8),dimension(5),intent(out) :: c 34 | end subroutine ofeld 35 | ! 36 | subroutine scond(a,b,c,king) 37 | use kinddefine 38 | implicit none 39 | integer(kind=K4),intent(in) :: king 40 | real(kind=K8),dimension(150),intent(in) :: a,b 41 | real(kind=K8),dimension(150),intent(out) :: c 42 | end subroutine scond 43 | ! 44 | subroutine twixt(s,gma,gmb,gmc,gmd,xbl,kat,kbl) 45 | use kinddefine 46 | implicit none 47 | integer(kind=K4),intent(in) :: kat 48 | integer(kind=K4),intent(out) :: kbl 49 | real(kind=K8),intent(out) :: gma,gmb,gmc,gmd 50 | real(kind=K8),intent(in) :: xbl 51 | real(kind=K8),dimension(200),intent(in) :: s 52 | end subroutine twixt 53 | end interface 54 | ! 55 | integer(kind=K4) :: i,ib,ichara,icy,inc,iprnt,j,jj,k,kan,kc,kit,kt 56 | integer(kind=K4) :: kut,l,last,lastp,lin,line,ll,lp,lq,lt,nag,nk 57 | integer(kind=K4) :: nl,nn 58 | real(kind=K8),dimension(6,150) :: chara 59 | real(kind=K8),dimension(150) :: su 60 | real(kind=K8),dimension(200) :: wdx,wtan,scdf 61 | real(kind=K8),dimension(100) :: yi 62 | real(kind=K8) :: add,an,as,bdd,bs,bx,ci,cpsi,cs,cy,cyp 63 | real(kind=K8) :: del,dhp,dm,dmxx,dn,dpxx,dsx,dydx,em,f,fn,fsx,half 64 | real(kind=K8) :: hs,la,one,ps,psi,r,rl,s1,s2,s3,sa,sb,sc,sdx 65 | real(kind=K8) :: six,sne,sprx,ss,st,sum1 66 | real(kind=K8) :: sumax,t,t1,t2,t3,thr,tne,tt,two,wmnx,x,xbet,xinch 67 | real(kind=K8) :: xm,xmu,xmur,xs,xs2,xs3,y,ye,yinch,ypx,ys,zro 68 | character(len=4,kind=K3) :: ifr,iwl,lst,ibl 69 | ! COMMON /GG/ GAM,GM,G1,G2,G3,G4,G5,G6,G7,G8,G9,GA,RGA,QT 70 | ! COMMON /CLINE/ AXIS(5,150),TAXI(5,150),WIP,X1,FRIP,ZONK,SEO,CSE 71 | ! COMMON /COORD/ S(200),FS(200),WALTAN(200),SD(200),WMN(200),TTR(200 72 | ! 1),DMDX(200),SPR(200),DPX(200),SECD(200),XBIN,XCIN,GMA,GMB,GMC,GMD 73 | ! COMMON /WORK/ WALL(5,200),WAX(200),WAY(200),WAN(200),A(5,150),B(5, 74 | ! 1150),FCLAST(5,150) 75 | ! COMMON /PROP/ AR,ZO,RO,VISC,VISM,SFOA,XBL,CONV 76 | ! COMMON /PARAM/ ETAD,RC,AMACH,BMACH,CMACH,EMACH,GMACH,FRC,SF,WWO,WW 77 | ! 1OP,QM,WE,CBET,XE,ETA,EPSI,BPSI,XO,YO,RRC,SDO,XB,XC,AH,PP,SE,TYE,XA 78 | ! COMMON /TROAT/ FC(6,51) 79 | ! COMMON /CONTR/ ITLE(3),IE,LR,IT,JB,JQ,JX,KAT,KBL,KING,KO,LV,NOCON, 80 | ! 1IN,MC,MCP,IP,IQ,ISE,JC,M,MP,MQ,N,NP,NF,NUT 81 | ! DIMENSION CHARA(6,150), SU(150), WDX(200), WTAN(200), SCDF(200), YI 82 | ! 1(100) 83 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,six/6.d+0/,half/5.d-1/ 84 | data ifr/'FIRS'/,iwl/'WALL'/,lst/'LAST'/,ibl/' '/,thr/3.d+0/ 85 | ! call orez (a,4*750+250) 86 | a(:,:)=0.0d0 87 | b(:,:)=0.0d0 88 | fclast(:,:)=0.0d0 89 | wall(:,:)=0.0d0 90 | ! 91 | chara(:,:)=0.0d0 92 | su(:)=0.0d0 93 | wdx(:)=0.0d0 94 | wtan(:)=0.0d0 95 | scdf(:)=0.0d0 96 | yi(:)=0.0d0 97 | ! 98 | cpsi=g2*datan(g4*cbet)-datan(cbet) 99 | if (jq.gt.0) goto 6 100 | if (lr.eq.0) goto 4 101 | ! 102 | ! throat characteristic values 103 | sumax=(se/seo)**(ie+1) 104 | if (qm.eq.one) sumax=one 105 | lq=zonk*(lr-1)+1 106 | nl=n+lq-1 107 | do j=1,lq 108 | if (qm.ne.one) goto 1 109 | fc(1,j)=fc(1,j)*se+xo 110 | fc(2,j)=fc(2,j)*se 111 | 1 fclast(1,j)=fc(1,j) 112 | fclast(2,j)=fc(2,j) 113 | fclast(3,j)=fc(3,j) 114 | fclast(4,j)=fc(4,j) 115 | fclast(5,j)=fc(5,j) 116 | if (mq.lt.0) goto 3 117 | if (j.gt.1) goto 2 118 | write (2,93) itle 119 | write (2,99) ibl 120 | 2 xmu=conv*dasin(one/fclast(3,j)) 121 | psi=conv*fclast(4,j) 122 | an=conv*fclast(5,j) 123 | xinch=sf*fclast(1,j)+frip 124 | yinch=sf*fclast(2,j) 125 | write (2,103) j,(fclast(k,j),k=1,3),xmu,psi,an,xinch,yinch 126 | if (mod(j,10).eq.0) write (2,98) 127 | 3 su(j)=fc(6,j)/sumax 128 | enddo 129 | 4 if (ise.eq.0) goto 8 130 | ! 131 | ! initial characteristic values if non-radial flow 132 | do k=1,m 133 | a(2,k)=(k-1)*tye/(m-1) 134 | a(1,k)=a(2,k)*cbet+xe 135 | a(3,k)=cmach 136 | a(4,k)=cpsi 137 | a(5,k)=zro 138 | enddo 139 | goto 10 140 | ! 141 | ! final characteristic values if radial flow 142 | 6 nl=n+np-1 143 | fn=np-1 144 | do jj=1,np 145 | if (ie.eq.0) f=(jj-1)/fn 146 | if (ie.eq.1) f=two*dsin(half*eta*(jj-1)/fn)/se 147 | fclast(2,jj)=f*tye 148 | fclast(1,jj)=fclast(2,jj)*cbet+xc 149 | fclast(3,jj)=cmach 150 | fclast(4,jj)=cpsi 151 | fclast(5,jj)=zro 152 | su(jj)=f**(ie+1) 153 | enddo 154 | ! 155 | ! initial characteristic values if radial flow 156 | 8 em=eta/(m-1) 157 | do k=1,m 158 | t=(k-1)*em 159 | if (ip.eq.0) xm=fmv(epsi+t/qt) 160 | if (ip.ne.0) xm=fmv(bpsi-t/qt) 161 | r=((g6+g5*xm**2)**ga/xm)**qt 162 | xbet=dsqrt(xm**2-one) 163 | a(1,k)=r*dcos(t) 164 | a(2,k)=r*dsin(t) 165 | a(3,k)=xm 166 | a(4,k)=g2*datan(g4*xbet)-datan(xbet) 167 | a(5,k)=t 168 | enddo 169 | if (ie.eq.1 .and. ip.eq.0) a(5,1)=taxi(5,1) 170 | if (ie.eq.1 .and. ip.ne.0) a(5,1)=axis(5,1) 171 | 10 do j=1,5 172 | wall(j,1)=a(j,m) 173 | enddo 174 | line=1 175 | if (mq.lt.0) goto 14 176 | if (ise.eq.1) goto 12 177 | if (jq.eq.0) write (2,91) itle 178 | if (jq.eq.1) write (2,94) itle 179 | goto 13 180 | 12 write (2,102) itle 181 | 13 write (2,106) line 182 | 14 su(1)=zro 183 | if (ie.eq.0) bx=one/se 184 | nn=1 185 | do k=1,m 186 | do j=1,5 187 | b(j,k)=a(j,k) 188 | enddo 189 | enddo 190 | last=m-1 191 | goto 20 192 | 16 last=m 193 | line=2 194 | if (ip.ne.0) goto 38 195 | 17 do j=1,5 196 | b(j,1)=taxi(j,line) 197 | enddo 198 | do j=1,last 199 | k=j 200 | call ofeld(a(1,k),b(1,k),b(1,k+1),nocon) 201 | if (nocon.ne.0) goto 83 202 | enddo 203 | 20 lastp=last+1 204 | if (line.lt.lastp) lp=line 205 | nk=1+lp/52 206 | la=conv*dasin(one/b(3,nn)) 207 | iprnt=0 208 | ichara=0 209 | if (jc.eq.0) go to 21 210 | kc=iabs(jc) 211 | if (jc.gt.0 .and. jq.ne.0) go to 21 212 | if (jc.lt.0 .and. jq.eq.0) go to 21 213 | ichara=1 214 | if (kc.gt.100 .and. kc.lt.101+line) iprnt=1 215 | if (nn.eq.1 .and. mod(line-1,kc).eq.0) iprnt=1 216 | if (nn.gt.1 .and. mod(nn-1,kc).eq.0) iprnt=1 217 | 21 do j=nn,lastp 218 | if (ie.eq.1) bx=two*b(2,j)/se**2 219 | xm=b(3,j) 220 | xmur=dasin(one/xm) 221 | xmu=conv*xmur 222 | psi=b(4,j)*conv 223 | an=b(5,j)*conv 224 | if (b(2,j).eq.zro) an=zro 225 | if (ip.eq.0.or.la.gt.45) goto 22 226 | s(j)=b(1,nn)-b(1,j) 227 | ! mass integration with respect to x 228 | dsx=one/dcos(b(5,j)-xmur) 229 | if (b(2,j).eq.zro) dsx=xm/dsqrt(xm**2-one) 230 | goto 23 231 | 22 s(j)=b(2,j)-b(2,nn) 232 | ! mass integration with respect to y 233 | if (ip.eq.0) dsx=one/dsin(xmur+b(5,j)) 234 | if (ip.ne.0) dsx=one/dsin(xmur-b(5,j)) 235 | if (b(2,j).eq.zro) dsx=xm 236 | 23 if (ichara.eq.0 .or. j.ne.line) goto 24 237 | chara(1,j)=b(1,j) 238 | chara(2,j)=b(2,j) 239 | chara(3,j)=xm 240 | chara(4,j)=xmu 241 | chara(5,j)=psi 242 | chara(6,j)=an 243 | 24 fs(j)=dsx*bx/(g6+g5*xm**2)**ga 244 | if (mq.ge.0 .and. line.eq.1) goto 25 245 | if (iprnt.eq.0) goto 27 246 | if (j.gt.nn) goto 25 247 | if (ip.eq.0) write (2,104) itle 248 | if (ip.ne.0) write (2,105) itle 249 | write (2,106) line 250 | 25 if ((nk.gt.1) .and. (mod(j,nk).eq.0)) goto 26 251 | xinch=sf*b(1,j)+frip 252 | yinch=sf*b(2,j) 253 | write (2,103) j,b(1,j),b(2,j),xm,xmu,psi,an,xinch,yinch 254 | 26 if (mod(j,10*nk).eq.0) write (2,98) 255 | 27 continue 256 | enddo 257 | ! 258 | ! integration and interpolation for mass flow 259 | sa=zro 260 | sb=zro 261 | sc=zro 262 | sum1=su(nn) 263 | kan=(lastp-nn)/2 264 | do j=1,kan 265 | k=nn+2*j 266 | kt=k 267 | as=s(k-1)-s(k-2) 268 | bs=s(k)-s(k-1) 269 | cs=as+bs 270 | s1=(two-bs/as)*cs/six 271 | s3=(two-as/bs)*cs/six 272 | s2=cs-s1-s3 273 | add=s1*fs(k-2)+s2*fs(k-1)+s3*fs(k) 274 | sum1=add+sum1 275 | if (line.eq.1) goto 28 276 | del=one-sum1 277 | if (del) 30,29,28 278 | 28 continue 279 | enddo 280 | if (line.eq.1) write (2,96) sum1 281 | if (line.eq.1) goto 16 282 | bs=s(k+1)-s(k) 283 | kt=k+1 284 | dn=two*del/bs 285 | sc=dn/(fs(k)+dsqrt(fs(k)**2+(fs(kt)-fs(k))*dn)) 286 | sb=one-sc 287 | goto 34 288 | 29 sc=one 289 | goto 34 290 | 30 s2=bs*(two+cs/as)/six 291 | s3=bs*(two+as/cs)/six 292 | s1=bs-s2-s3 293 | bdd=s1*fs(k-2)+s2*fs(k-1)+s3*fs(k) 294 | if (bdd+del) 31,32,33 295 | 31 dn=two*(add+del)/as 296 | sb=dn/(fs(k-2)+dsqrt(fs(k-2)**2+(fs(k-1)-fs(k-2))*dn)) 297 | sa=one-sb 298 | go to 34 299 | 32 sb=one 300 | go to 34 301 | 33 dn=two*del/bs 302 | sc=one+dn/(fs(k)+dsqrt(fs(k)**2+(fs(k)-fs(k-1))*dn)) 303 | sb=one-sc 304 | 34 do j=1,5 305 | wall(j,line)=b(j,kt-2)*sa+b(j,kt-1)*sb+b(j,kt)*sc 306 | enddo 307 | if (iprnt.eq.1) write (2,107) (wall(j,line),j=1,3) 308 | last=kt 309 | if (n-line) 42,41,36 310 | 36 line=line+1 311 | do k=1,5 312 | do l=1,150 313 | a(k,l)=b(k,l) 314 | enddo 315 | enddo 316 | if (ip.eq.0) go to 17 317 | 38 do j=1,5 318 | b(j,1)=axis(j,line) 319 | enddo 320 | do j=1,last 321 | k=j 322 | call ofeld (b(1,k),a(1,k),b(1,k+1),nocon) 323 | if (nocon.ne.0) goto 83 324 | enddo 325 | goto 20 326 | 41 if (ip.ne.0) goto 42 327 | if (lr.eq.0.or.it.ne.0) goto 49 328 | 42 if (line.eq.nl-1) goto 48 329 | nn=nn+1 330 | line=line+1 331 | do k=1,5 332 | do l=1,150 333 | a(k,l)=b(k,l) 334 | enddo 335 | enddo 336 | do k=1,5 337 | do l=1,150 338 | b(k,l)=fclast(k,l) 339 | enddo 340 | enddo 341 | if ((lr.ne.0).and.(jq.eq.0)) goto 46 342 | do j=nn,last 343 | k=j 344 | call ofeld(b(1,k),a(1,k),b(1,k+1),nocon) 345 | if (nocon.ne.0) goto 83 346 | enddo 347 | goto 20 348 | 46 do j=nn,last 349 | k=j 350 | call ofeld(a(1,k),b(1,k),b(1,k+1),nocon) 351 | if (nocon.ne.0) go to 83 352 | enddo 353 | goto 20 354 | 48 if (ip.ne.0) goto 64 355 | ! 356 | ! integration of slopes 357 | 49 ib=1 358 | if (iabs(jb).gt.1) ib=2 359 | lt=0 360 | if (it.ne.0) lt=ib 361 | nut=(line-1)/ib+2-lt 362 | wall(1,line+1)=xo 363 | wall(5,line+1)=zro 364 | yi(nut)=wall(2,1) 365 | y=yi(nut) 366 | lin=2*((line-lt)/2) 367 | do j=2,lin,2 368 | i=nut-j 369 | ss=wall(1,j)-wall(1,j-1) 370 | tt=wall(1,j+1)-wall(1,j) 371 | st=ss+tt 372 | s1=ss*(two+tt/st)/six 373 | s2=ss*(two+st/tt)/six 374 | s3=ss-s1-s2 375 | t3=tt*(two+ss/st)/six 376 | t2=tt*(two+st/ss)/six 377 | t1=tt-t2-t3 378 | y=y+s1*dtan(wall(5,j-1))+s2*dtan(wall(5,j))+s3*dtan(wall(5,j+1)) 379 | if (ib.eq.1) yi(i+1)=y 380 | y=y+t1*dtan(wall(5,j-1))+t2*dtan(wall(5,j))+t3*dtan(wall(5,j+1)) 381 | if (ib.eq.1) yi(i)=y 382 | if (ib.eq.2) yi(i+j/2)=y 383 | enddo 384 | if (lr.ne.0.and.line.eq.lin) goto 51 385 | x=wall(1,line-lt)-xo 386 | yi(1)=yi(2)-x*(dtan(wall(5,line-lt))+half*x*sdo)/thr 387 | 51 do l=2,nut 388 | jj=1+ib*(nut-l) 389 | wax(l)=wall(1,jj) 390 | way(l)=wall(2,jj) 391 | wmn(l)=wall(3,jj) 392 | wan(l)=conv*wall(5,jj) 393 | waltan(l)=dtan(wall(5,jj)) 394 | enddo 395 | wax(1)=xo 396 | way(1)=yo 397 | wan(1)=zro 398 | wmn(1)=wwo/dsqrt(g7-g8*wwo**2) 399 | waltan(1)=zro 400 | if (nf.ge.0) goto 54 401 | ! 402 | ! smooth upstream contour if desired 403 | call neo 404 | do j=1,nut 405 | waltan(j)=dtan(wan(j)/conv) 406 | enddo 407 | 54 call scond (wax,waltan,secd,nut) 408 | secd(1)=sdo 409 | secd(nut)=zro 410 | ko=nut+mp 411 | if (mp.eq.0) goto 56 412 | ! 413 | ! radial flow section coordinates 414 | sne=dsin(eta) 415 | tne=dtan(eta) 416 | dm=(amach-gmach)/mp 417 | do l=1,mp 418 | ll=nut+l 419 | wmn(ll)=gmach+l*dm 420 | rl=((g5*wmn(ll)**2+g6)**ga/wmn(ll))**qt 421 | wax(ll)=rl*cse 422 | way(ll)=rl*sne 423 | wan(ll)=etad 424 | waltan(ll)=tne 425 | secd(ll)=zro 426 | enddo 427 | 56 if (mq.lt.0) goto 60 428 | if (jc.le.0) goto 58 429 | write (2,105) itle 430 | write (2,99) lst 431 | do k=1,lp,nk 432 | i=(k-1)/nk+1 433 | xinch=sf*chara(1,k)+frip 434 | yinch=sf*chara(2,k) 435 | write (2,103) k,(chara(j,k),j=1,6),xinch,yinch 436 | if (mod(i,10).eq.0) write (2,98) 437 | enddo 438 | 58 if (ise.eq.0) write (2,91) itle 439 | if (ise.eq.1) write (2,102) itle 440 | write (2,84) rc,etad,amach,bmach,cmach,emach,mc,ah 441 | if (nocon.ne.0) goto 59 442 | write (2,100) iwl 443 | write (2,85) (k,wax(k),way(k),wmn(k),wan(k),waltan(k),secd(k),k=1, 444 | &nut) 445 | if ((lr.eq.0) .and. (n.lt.42)) goto 59 446 | if ((lr.ne.0) .and. (n+lr.lt.27)) goto 59 447 | nocon=1 448 | goto 58 449 | 59 write (2,87) 450 | nocon=0 451 | ! 452 | ! comparison of contour with parabola and hyperbola 453 | 60 do j=1,nut 454 | xs=(wax(j)-xo)/yo 455 | xs2=xs**2 456 | xs3=xs**3 457 | ys=way(j)/yo 458 | ye=yi(j)/yo 459 | ps=one+half*xs2*rrc 460 | dhp=one+xs2*rrc 461 | hs=dsqrt(dhp) 462 | if (j.gt.1) goto 61 463 | if (mq.lt.0) goto 62 464 | write (2,88) j,xs,ys,ye,ps,hs 465 | goto 62 466 | 61 ypx=waltan(j)/xs 467 | cy=(ps-ys)/xs3 468 | ci=(ps-ye)/xs3 469 | if (j.eq.2) icy=int(1.d+6*(dabs(cy)-dabs(ci)),K4) 470 | if (mq.lt.0) go to 63 471 | cyp=(rrc-ypx)/xs/thr 472 | write (2,88) j,xs,ys,ye,ps,hs,cy,ci,cyp 473 | 62 if (mod(j,10).eq.0) write (2,98) 474 | enddo 475 | 63 write (2,97) icy 476 | if (iq.gt.0) goto 70 477 | jq=1 478 | return 479 | 64 line=nl 480 | do j=1,5 481 | wall(j,nl)=fclast(j,np) 482 | enddo 483 | ! 484 | ! smooth downstream contour if desired 485 | if (nf.lt.0) call neo 486 | do j=1,nl 487 | wdx(j)=wall(1,j) 488 | wtan(j)=dtan(wall(5,j)) 489 | enddo 490 | call scond (wdx,wtan,scdf,nl) 491 | scdf(1)=zro 492 | scdf(nl)=zro 493 | if (jc.ge.0) goto 68 494 | write (2,104) itle 495 | write (2,99) ifr 496 | do k=1,lp,nk 497 | i=(k-1)/nk+1 498 | xinch=sf*chara(1,k)+frip 499 | yinch=sf*chara(2,k) 500 | write (2,103) k,(chara(j,k),j=1,6),xinch,yinch 501 | if (mod(i,10).eq.0) write (2,98) 502 | enddo 503 | 68 if (iq.lt.0) ko=1 504 | nag=ko-1 505 | king=line+nag 506 | do l=1,line 507 | wax(nag+l)=wall(1,l) 508 | way(nag+l)=wall(2,l) 509 | wmn(nag+l)=wall(3,l) 510 | wan(nag+l)=conv*wall(5,l) 511 | waltan(nag+l)=wtan(l) 512 | secd(nag+l)=scdf(l) 513 | enddo 514 | if (mq.lt.0) goto 71 515 | write (2,94) itle 516 | write (2,84) rc,etad,amach,bmach,cmach,emach,mc,ah 517 | write (2,100) iwl 518 | write (2,85) (k,wax(k),way(k),wmn(k),wan(k),waltan(k),secd(k),k=ko 519 | &,king) 520 | goto 71 521 | 70 king=ko 522 | ! 523 | ! application of scale factor to non-dimensional coordinates 524 | 71 do k=1,king 525 | s(k)=sf*wax(k)+frip 526 | fs(k)=sf*way(k) 527 | ttr(k)=one+g8*wmn(k)**2 528 | spr(k)=one/ttr(k)**(one+g1) 529 | sd(k)=secd(k)/sf 530 | enddo 531 | if (ise.eq.1) xbin=zro 532 | if (ise.eq.0) xbin=xb*sf+frip 533 | xcin=xc*sf+frip 534 | call scond (s,wmn,dmdx,king) 535 | dmdx(1)=g7*wwop*wmn(1)**3/wwo**3/sf 536 | if (mp.eq.0 .or. iq.lt.0) go to 74 537 | do k=nut,ko 538 | dmdx(k)=wmn(k)*ttr(k)/(wmn(k)**2-one)/qt/sf/wax(k) 539 | enddo 540 | goto 75 541 | 74 if (ise.eq.0) dmdx(ko)=amach*ttr(ko)/(amach**2-one)/qt/sf/xa 542 | 75 if (iq.lt.1 .or. ise.eq.1) dmdx(king)=zro 543 | do k=1,king 544 | dpx(k)=-gam*wmn(k)*dmdx(k)*spr(k)/ttr(k) 545 | enddo 546 | jq=0 547 | kat=king 548 | if (iabs(mq).lt.2) goto 78 549 | ! 550 | ! extension of parallel-flow contour 551 | kit=king+1 552 | kat=king+iabs(mq) 553 | kut=s(king)+half 554 | inc=s(king)-s(king-1) 555 | if (inc.lt.1) inc=1 556 | do k=kit,kat 557 | s(k)=kut+(k-king)*inc 558 | fs(k)=fs(king) 559 | wmn(k)=wmn(king) 560 | ttr(k)=ttr(king) 561 | spr(k)=spr(king) 562 | wan(k)=zro 563 | waltan(k)=zro 564 | dmdx(k)=zro 565 | dpx(k)=zro 566 | sd(k)=zro 567 | enddo 568 | 78 if (xbl.eq.zro) goto 79 569 | if (s(king-1).lt.xbl) goto 79 570 | ! 571 | ! interpolate for values at specified station 572 | call twixt (s,gma,gmb,gmc,gmd,xbl,king,kbl) 573 | goto 80 574 | 79 kbl=kat+4 575 | 80 if (jb.gt.0) return 576 | if (ise.eq.0) goto 81 577 | write (2,102) itle 578 | write (2,92) rc,se,xcin 579 | goto 82 580 | 81 if (iq.gt.0) write (2,91) itle 581 | if (iq.le.0) write (2,95) itle,xbin,xcin,sf 582 | write (2,84) rc,etad,amach,bmach,cmach,emach,mc,ah 583 | 82 write (2,89) 584 | write (2,90) (k,s(k),fs(k),waltan(k),sd(k),wmn(k),dmdx(k),spr(k),d 585 | &px(k),k=1,king) 586 | if (kbl.gt.kat) return 587 | j=kbl-1 588 | fsx=gma*fs(j-2)+gmb*fs(j-1)+gmc*fs(j)+gmd*fs(j+1) 589 | wmnx=gma*wmn(j-2)+gmb*wmn(j-1)+gmc*wmn(j)+gmd*wmn(j+1) 590 | dmxx=gma*dmdx(j-2)+gmb*dmdx(j-1)+gmc*dmdx(j)+gmd*dmdx(j+1) 591 | dydx=gma*waltan(j-2)+gmb*waltan(j-1)+gmc*waltan(j)+gmd*waltan(j+1) 592 | sdx=gma*sd(j-2)+gmb*sd(j-1)+gmc*sd(j)+gmd*sd(j+1) 593 | sprx=gma*spr(j-2)+gmb*spr(j-1)+gmc*spr(j)+gmd*spr(j+1) 594 | dpxx=gma*dpx(j-2)+gmb*dpx(j-1)+gmc*dpx(j)+gmd*dpx(j+1) 595 | write (2,101) xbl,fsx,dydx,sdx,wmnx,dmxx,sprx,dpxx 596 | return 597 | 83 write (2,86) ip,nn,line,j 598 | return 599 | ! 600 | 84 format (1x,' RC=',f11.6,3x,'ETAD=',f8.4,' DEG',3x,'AMACH=',f10.7,3 601 | &x,'BMACH=',f10.7,3x,'CMACH=',f10.7,3x,'EMACH=',f10.7,3x,A4,'H=',f1 602 | &1.7/) 603 | 85 format (10(8x,i3,2x,1p6e15.7/)) 604 | 86 format ('0','OFELD,IP=',i3,', NN=',i3,', LINE=',i3,', POINT=',i3) 605 | 87 format (1x,9x,'POINT X/YO',8x,'Y/YO',7x,'INT.Y/YO',7x,'PAR/YO',7x, 606 | &'HYP/YO C(Y)',11x,'C(YI)',10x,'C(YP)'/) 607 | 88 format (1x,9x,i3,5f13.7,1p3e15.6) 608 | 89 format (1x,9x,'POINT',7x,'X(IN)',9x,'Y(IN)',9x,'DY/DX',8x,'D2Y/DX2 609 | &',7x,'MACH NO.',7x,'DM/DX',9x,'PE/PO',11x,'DPR/DX'/) 610 | 90 format (10(10x,i3,2x,0p6f14.7,1p2e16.5/)) 611 | 91 format (1x,3a4,' UPSTREAM CONTOUR'/) 612 | 92 format (1x,' RC=',f11.7,', STREAMLINE RATIO=',f11.8,', TEST 613 | &CONE BEGINS AT',f12.7,' IN.'/) 614 | 93 format (1x,3a4,' THROAT CHARACTERISTIC') 615 | 94 format (1x,3a4,' DOWNSTREAM CONTOUR'/) 616 | 95 format ('1',3a4,' INVISCID NOZZLE CONTOUR, RADIAL FLOW ENDS AT',f1 617 | &1.6,' IN., TEST CONE BEGINS AT',f11.6,' IN., SCALE FACTOR=',f9.4/) 618 | 96 format (1x,8x,'MASS =',f13.10/) 619 | 97 format (1x,9x,'ICY =',i13) 620 | 98 format (1x) 621 | 99 format (1x,8x,a4/8x,'POINT',8x,'X',14x,'Y',10x,'MACH NO. MACH 622 | & ANG.(D) PSI (D) FLOW ANG.(D) X(IN)',9x,'Y(IN)'/) 623 | 100 format (1x,8x,a4/8x,'POINT',8x,'X',14x,'Y',10x,'MACH NO. FLOW 624 | & ANG.(D) WALTAN',9x,'SECDIF'/) 625 | 101 format ('0',14x,6f14.7,1p2e16.5) 626 | 102 format ('1',3a4,' INVISCID CONTOUR'/) 627 | 103 format (1x,i10,2x,1p6e15.7,0p2f14.7) 628 | 104 format (1x,3a4,' INTERMEDIATE LEFT CHARACTERISTIC'/) 629 | 105 format (1x,3a4,' INTERMEDIATE RIGHT CHARACTERISTIC'/) 630 | 106 format (1x,' CHARACT',i4/8x,'POINT',8x,'X',14x,'Y',10x,'MACH NO. 631 | & MACH ANG.(D) PSI (D) FLOW ANG.(D) X(IN)',9X,'Y( 632 | &IN)'/) 633 | 107 format (1x,' CONTOUR ',1p3e15.7/) 634 | end subroutine perfc 635 | -------------------------------------------------------------------------------- /src/bound.f: -------------------------------------------------------------------------------- 1 | subroutine bound 2 | ! 3 | ! to obtain the correction due to the turbulent boundary layer 4 | ! 5 | use kinddefine 6 | use gg, only:gam,g1,g7,g9,ga,qt 7 | use coord, only:s,fs,waltan,sd,wmn,ttr,dmdx,spr,bta,sref,xbin,xcin 8 | &,gma,gmb,gmc,gmd 9 | use corr, only:dla,rco,dax,drx,sl,dr2 10 | use prop, only:ar,zo,ro,visc,vism,xbl,conv 11 | use param, only:etad,rc,amach,bmach,cmach,emach,frc,sf,ah 12 | use httr, only:hair,taw,twq,tw,twat,qfun,qfunw,ipq,ij,iv,iw 13 | use contr, only:itle,ie,it,kat,kbl,king,ko,lv,in,mc,mcp 14 | ! 15 | implicit none 16 | ! 17 | interface 18 | subroutine scond(a,b,c,king) 19 | use kinddefine 20 | implicit none 21 | integer(kind=K4),intent(in) :: king 22 | real(kind=K8),dimension(150),intent(in) :: a,b 23 | real(kind=K8),dimension(150),intent(out) :: c 24 | end subroutine scond 25 | ! 26 | subroutine twixt(s,gma,gmb,gmc,gmd,xbl,kat,kbl) 27 | use kinddefine 28 | implicit none 29 | integer(kind=K4),intent(in) :: kat 30 | integer(kind=K4),intent(out) :: kbl 31 | real(kind=K8),intent(out) :: gma,gmb,gmc,gmd 32 | real(kind=K8),intent(in) :: xbl 33 | real(kind=K8),dimension(200),intent(in) :: s 34 | end subroutine twixt 35 | end interface 36 | ! 37 | integer(kind=K4) :: i,id,ieo,iht,im,ipp,ir,ithx,j,k,kor,l,ld 38 | real(kind=K8) :: add,alf,alph,alpha,arc,asca,asec 39 | real(kind=K8) :: bdd,bet,bma,bmb,bmc 40 | real(kind=K8) :: c1,c2,c3,capi,cdd,ch,chair,cf 41 | real(kind=K8) :: cf1,cf2,cf3,cfi,cfik,cfk 42 | real(kind=K8) :: cfs,cfsk,cmu,cth,ctha,cthb,cthc 43 | real(kind=K8) :: da,db,dc,dd2,ddd,de,dela,delta,delst,df,dg 44 | real(kind=K8) :: dh,di,dj,dl,dlab,dlst,dlta,dltb,dltbl,dltc 45 | real(kind=K8) :: dm,dn,dor,dot,doti,dotr 46 | real(kind=K8) :: ds,dsm,dsod,dsrod,dst,dstu,dsttu,dsu 47 | real(kind=K8) :: dt,dth,dtha,dthb,dthc,dthk,dts,dtsu,dtu,dtus,du 48 | real(kind=K8) :: dut,dxs,emu,fcc,fmy,four,fpcp,frd,fsi,fxcf 49 | real(kind=K8) :: h,ha,half,hb,hbl,hi,hr,hu,hw 50 | real(kind=K8) :: one,ppq,pps,qma,qmb,qmc,qmd,raj,rcob,rcv,rdel 51 | real(kind=K8) :: rdlg,rdli,rdlx,redl,redlg,reo,reoa,reob,reobl 52 | real(kind=K8) :: reoc,reoft,reth,rethg 53 | real(kind=K8) :: rho,rhoe,roy,rthg,rthx,rtig 54 | real(kind=K8) :: rthi,rtii,s1,s2,s3,sa,sb,sbin,sc,scfi,scin,scu 55 | real(kind=K8) :: scw,six,sma,smb,smc,smd,ss 56 | real(kind=K8) :: suma,sumb,sumc,sumd,st,str 57 | real(kind=K8) :: t0,tair,tc,te,ten 58 | real(kind=K8) :: th,tha,thbl,thm,thr,thu,tlv 59 | real(kind=K8) :: tp,tr,trpi,tt,twd,two,twt,un 60 | real(kind=K8) :: ve,wmu,xbl1,xcf,xn,xna,xnb,xnbl,xnc,xst 61 | real(kind=K8) :: ybl,yoh,yoha,ysec,yst,zro 62 | real(kind=K8),dimension(16) :: d,z 63 | real(kind=K8),dimension(200) :: cds,rw,scv,sk 64 | character(len=4,kind=K3) :: ly,ls 65 | character(len=8,kind=K3) :: dd,dk 66 | ! COMMON /GG/ GAM,GM,G1,G2,G3,G4,G5,G6,G7,G8,G9,GA,RGA,QT 67 | ! COMMON /CORR/ DLA(200),RCO(200),DAX(200),DRX(200),SL(200),DR2 68 | ! COMMON /COORD/ S(200),FS(200),WALTAN(200),SD(200),WMN(200),TTR(200 69 | ! 1),DMDX(200),SPR(200),BTA(200),SREF(200),XBIN,XCIN,GMA,GMB,GMC,GMD 70 | ! COMMON /PROP/ AR,ZO,RO,VISC,VISM,SFOA,XBL,CONV 71 | ! COMMON /PARAM/ ETAD,RC,AMACH,BMACH,CMACH,EMACH,GMACH,FRC,SF,WWO,WW 72 | ! 1OP,QM,WE,CBET,XE,ETA,EPSI,BPSI,XO,YO,RRC,SDO,XB,XC,AH,PP,SE,TYE,XA 73 | ! COMMON /HTTR/ HAIR,TAW,TWQ,TW,TWAT,QFUN,QFUNW,IPQ,IJ,IV,IW 74 | ! COMMON /CONTR/ ITLE(3),IE,LR,IT,JB,JQ,JX,KAT,KBL,KING,KO,LV,NOCON, 75 | ! 1IN,MC,MCP 76 | ! DIMENSION Z(16), D(16), SCV(200), SK(200), CDS(200), RW(200) 77 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,six/6.d+0/,half/5.d-1/ 78 | data thr/3.d+0/,four/4.d+0/,ten/1.d+1/,tlv/1.2d+1/ 79 | data cf1/3.865d-2/,cf2/4.561d+0/,cf3/5.46d-1/,fsi/3.17897971d+0/ 80 | data ly/' Y'/,ls/' S'/,dd/'D2Y/DX2 '/,dk/' CURV. '/ 81 | data z(1)/.052995325d-1/,z(4)/.1222977958d+0/,z(7)/.3591982246d+0/ 82 | data z(2)/.277124885d-1/,z(5)/.1910618778d+0/,z(8)/.4524937451d+0/ 83 | data z(3)/.671843988d-1/,z(6)/.2709916112d+0/ 84 | data d(1)/.135762297d-1/,d(2)/.31126762d-1/,d(3)/.475792558d-1/ 85 | data d(4)/.623144856d-1/,d(5)/.747979944d-1/,d(6)/.845782597d-1/ 86 | data d(7)/.913017075d-1/,d(8)/.947253052d-1/ 87 | do j=9,16 88 | d(j)=d(17-j) 89 | z(j)=one-z(17-j) 90 | enddo 91 | do j=1,kat 92 | sref(j)=s(j) 93 | enddo 94 | sbin=xbin 95 | scin=xcin 96 | trpi=conv/90.d+0 97 | fcc=2.05d+0+dlog(.41d+0) 98 | chair=gam*g1*ar/ro/ro/777.64885d+0 99 | if (it .eq. 0) xbl1=xbl 100 | ! 101 | 3 read (1,66,end=65) ppq,t0,twt,twat,qfun,alph,iht,ir,ld,lv 102 | ! 103 | pps=ppq 104 | rho=144.d+0*pps/zo/ar/t0 105 | id=iabs(ld) 106 | kor=ko 107 | if (iabs(in) .eq. 10) kor=1 108 | if (mcp .lt. 0) kor=king 109 | roy=one 110 | if (ie .eq. 0) hw=ah 111 | if ((id .eq. 0) .or. (ie .eq. 1)) hw=zro 112 | if (hw .eq. zro) yoh=zro 113 | if (hw .eq. zro) yoha=zro 114 | alf=dabs(alph) 115 | arc=frc 116 | if (iht .lt. 0) arc=frc**(ie+1) 117 | ipq=0 118 | iw=1 119 | if (lv .ne. 0) iw=iabs(lv) 120 | do j=1,kat 121 | s(j)=sref(j) 122 | sl(j)=s(j) 123 | rw(j)=fs(j) 124 | rco(j)=fs(j) 125 | scw=dsqrt(one+waltan(j)**2) 126 | sk(j)=sd(j)/scw**3 127 | if (kat .eq. king) goto 4 128 | if (s(j) .lt. xbl) kbl=j+2 129 | 4 drx(j)=waltan(j) 130 | enddo 131 | if (kbl .gt. kat) kbl=kat+4 132 | 5 do iv=1,iw 133 | if ((iv .gt. 1) .and. (iv .lt. iw)) goto 15 134 | if (ld .ge. 0) write (2,80) itle,pps,t0 135 | if (alph .gt. zro) goto 6 136 | alpha=zro 137 | if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,71,advance="no") 138 | goto 7 139 | 6 alpha=alph 140 | if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,70,advance="no") 141 | 7 if (ir .eq. 2) goto 13 142 | if (alf .eq. one) goto 8 143 | if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,75,advance="no") 144 | goto 9 145 | 8 if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,72,advance="no") 146 | 9 if (ir) 10,11,12 147 | 10 if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,74) 148 | goto 14 149 | 11 if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,73) 150 | goto 14 151 | 12 if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,76) 152 | goto 14 153 | 13 if ((ld .ge. 0) .or. (ppq .eq. zro)) write (2,77) 154 | 14 if (ppq .eq. zro) goto 60 155 | 15 capi=.55d+0 156 | ipp=0 157 | ij=1 158 | do j=1,kat 159 | bet=ttr(j)-one 160 | str=one/ttr(j) 161 | te=t0*str 162 | raj=wmn(j)*(g7*str)**ga 163 | if (iht .ge. 0) raj=raj**qt 164 | scw=dsqrt(one+drx(j)**2) 165 | emu=visc*te*dsqrt(te)/(te+vism) 166 | if (te .lt. vism) emu=half*visc*te/dsqrt(vism) 167 | if (vism .le. one) emu=visc*te**vism 168 | taw=te*(one+ro*bet) 169 | rhoe=rho*str**g1 170 | ve=wmn(j)*dsqrt(gam*ar*te) 171 | reo=rhoe*ve/emu/tlv 172 | if (hw .gt. zro) yoh=fs(j)/hw 173 | if (ie .eq. 0 .and. hw .gt. zro) roy=(hw/fs(j)+one)*trpi 174 | k=j 175 | if (j .eq. 1) goto 19 176 | if (j .gt. kor) k=j-kor+1 177 | if (k-3) 16,17,18 178 | 16 ds=s(j)-s(j-1) 179 | smd=half*ds 180 | goto 19 181 | 17 dt=s(j)-s(j-1) 182 | dst=ds+dt 183 | sma=dst*(two-dt/ds)/six 184 | smc=dst*(two-ds/dt)/six 185 | smb=dst-sma-smc 186 | hb=h 187 | if (iv .gt. 1) goto 19 188 | bma=two/ds/dst 189 | bmb=-two/ds/dt 190 | bmc=two/dt/dst 191 | goto 19 192 | 18 du=s(j)-s(j-1) 193 | dt=s(j-1)-s(j-2) 194 | ds=s(j-2)-s(j-3) 195 | dst=ds+dt 196 | dstu=dst+du 197 | dtu=dt+du 198 | dut=du-dt 199 | dts=ds-dt 200 | dtus=dt+two*(du-ds) 201 | dtsu=dt+two*(ds-du) 202 | dsttu=two*(dst+dtu) 203 | ha=hb 204 | hb=h 205 | qma=half*ds*(one-ds*(thr+(dtu+du)/dst)/dstu/six) 206 | qmb=half*ds*(one+ds*(two+(dst+dt)/dtu)/dt/six) 207 | qmc=-ds**3*(one+(dtu+du)/dst)/dt/du/tlv 208 | qmd=ds**3*(dst+dt)/du/dtu/dstu/tlv 209 | sma=half*ds+(dut*dtu**3/ds-ds*ds*(ds+dsttu))/dst/dstu/tlv 210 | smb=half*dst+(ds*ds*(dsttu-ds)/dt+dt*dt*dtus/ds-du**3*(dstu+dst) 211 | &/ds/dt)/dtu/tlv 212 | smc=half*dtu+(dt*dt*dtsu/du+du*du*(dsttu-du)/dt-ds**3*(dstu+dtu) 213 | &/dt/du)/dst/tlv 214 | smd=half*du+(dts*dst**3/du-du*du*(du+dsttu))/dtu/dstu/tlv 215 | 19 if (twt .ne. zro) goto 20 216 | tw=taw 217 | goto 21 218 | 20 twd=(arc*raj-one)*(twt-twat)/(arc-one) 219 | if (twd .lt. zro) twd=zro 220 | tw=twd+twat 221 | 21 wmu=visc*tw*dsqrt(tw)/(tw+vism) 222 | if (vism .le. one) wmu=visc*tw**vism 223 | dl=tw/te 224 | dm=alpha*(taw-tw)/te 225 | dn=one-dl-dm 226 | da=alf*(taw-tw) 227 | db=da+tw-te 228 | if (db) 22,23,24 229 | 22 dg=dsqrt(-db*te) 230 | dh=dsqrt(-db*tw) 231 | di=(two*(dg+te-tw)-da)/(two*dh+da) 232 | dj=dlog(di) 233 | tp=-db/dj/dj 234 | goto 25 235 | 23 tp=(dsqrt(te)+dsqrt(tw))**2/four 236 | goto 25 237 | 24 dc=dsqrt(da*da+four*tw*db) 238 | df=dasin((db+tw-te)/dc) 239 | de=dasin(da/dc) 240 | tp=db/(df+de)/(df+de) 241 | 25 if (ir) 26,27,28 242 | 26 frd=tw*emu/wmu/tp 243 | goto 29 244 | 27 frd=emu/wmu 245 | goto 29 246 | 28 frd=te*emu/wmu/dsqrt(tp*tw) 247 | 29 if (ipp .gt. 0) goto 31 248 | rthi=1.d-2*reo*fs(1) 249 | rtii=rthi 250 | rdli=ten*rthi 251 | if (ir .eq. 1) goto 32 252 | 30 rthg=dlog10(rthi) 253 | cfi=cf1/(rthg+cf2)/(rthg-cf3) 254 | 31 if (ir .ne. 2) goto 33 255 | scfi=dsqrt(cfi) 256 | tc=tw+17.2d+0*scfi*da-305.d+0*cfi*db 257 | cmu=visc*tc*dsqrt(tc)/(tc+vism) 258 | if (vism .le. one) cmu=visc*tc**vism 259 | tp=tw*cmu/wmu 260 | frd=emu/cmu 261 | goto 33 262 | 32 rdlg=dlog10(rdli) 263 | cfi=0.0444d+0/(rdlg+4.6221d+0)/(rdlg-1.4402d+0) 264 | 33 cf=cfi*te/tp 265 | cfs=cf*scw 266 | rtig=dlog10(rtii) 267 | xcf=.41d+0*dsqrt((rtig+cf2)*(rtig-cf3)/cf1) 268 | 34 c3=two+capi*(fsi+1.5d+0*capi) 269 | c2=one+capi 270 | c1=c2-c3/xcf 271 | fxcf=xcf+dlog(c1/rtii)-fcc-two*capi 272 | fpcp=(xcf-fsi-thr*capi)/xcf/c1-two 273 | capi=capi-fxcf/fpcp 274 | if (dabs(fxcf) .gt. 1.d-8) goto 34 275 | doti=xcf/c1 276 | xn=half*(doti+dsqrt(doti*(doti-six)+one)-thr) 277 | hi=one+two/xn 278 | suma=zro 279 | sumb=zro 280 | sumc=zro 281 | sumd=zro 282 | do l=1,16 283 | un=z(l)**xn 284 | tr=dl+z(l)*(dm+z(l)*dn) 285 | add=d(l)*xn*un/tr 286 | bdd=add*z(l) 287 | cdd=add*un 288 | ddd=bdd*un 289 | suma=suma+add 290 | sumb=sumb+bdd 291 | sumc=sumc+cdd 292 | sumd=sumd+ddd 293 | enddo 294 | dot=one/(suma-sumb) 295 | dsod=one-suma 296 | dsm=half-sumc 297 | thm=sumc-sumd 298 | hu=dsod*dot 299 | if (ipp .gt. 0) goto 36 300 | h=hu 301 | dotr=dot 302 | 36 fmy=(h+two-g9*bet)*dmdx(j)*str/wmn(j)+id*drx(j)/(rw(j)+hw) 303 | if (j.eq.1) th=cfs/fmy 304 | if (k.eq.2) th=(tha+smd*(dtha+cfs))/(one+smd*fmy) 305 | if (k.eq.3) th=(tha+sma*dtha+smb*dthb+smc*cfs)/(one+smc*fmy) 306 | if (k.gt.3) th=(tha+sma*dtha+smb*dthb+smc*dthc+smd*cfs)/(one+smd 307 | &*fmy) 308 | delst=h*th 309 | asec=delst+dsqrt(id*delst**2+(fs(j)*scw*roy)**2) 310 | dor=id*dotr*th/asec 311 | dsrod=dsod-dor*dsm 312 | ipp=1 313 | dotr=one/(one/dot-thm*dor) 314 | hr=dsrod*dotr 315 | if (dabs(h-hr) .lt. 5.d-7) goto 37 316 | h=hr 317 | goto 36 318 | 37 delta=dotr*th 319 | thu=delta/dot 320 | dsu=delta*dsod 321 | rdel=reo*delta 322 | rtii=rdel/doti 323 | rdlx=frd*rdel 324 | rthx=rdlx/dot 325 | if (rthx .lt. 100.d+0) goto 38 326 | if (ir .eq. 1) goto 39 327 | if (dabs(one-rthx/rthi) .lt. 1.d-6) goto 41 328 | rthi=rthx 329 | goto 30 330 | 38 write (2,88) rthx,reo,frd,th,delta,dot 331 | return 332 | 39 if (dabs(one-rdlx/rdli) .lt. 1.d-6) goto 40 333 | rdli=rdlx 334 | goto 32 335 | 40 rthg=half*(dsqrt((cf2+cf3)**2+four*cf1/cf1)-cf2+cf3) 336 | rthx=ten**rthg 337 | 41 if (j .gt. 1) goto 42 338 | dth=zro 339 | hair=rhoe*ve*cf*chair 340 | tair=hair 341 | if (twat.eq.twt .or. qfun.eq.zro) goto 46 342 | twq=(hair*taw+qfun*(twat-15.d+0))/(hair+qfun) 343 | call heat 344 | if (ipq .gt. 100) goto 65 345 | if (dabs(tw-twq).lt.1.d-2.and.dabs(qfun-qfunw).lt.1.d-5) goto 46 346 | twt=twat+(twq-twat)*(arc-one)/(arc*raj-one) 347 | qfun=qfunw 348 | goto 20 349 | 42 dth=cfs-th*fmy 350 | if (dth .lt. zro) dth=zro 351 | if (j .eq. kor) goto 46 352 | if (k-3) 43,45,44 353 | 43 dthb=dth 354 | goto 47 355 | 44 tha=tha+qma*dtha+qmb*dthb+qmc*dthc+qmd*dth 356 | dtha=dthb 357 | dthb=dthc 358 | if (k .gt. 5) goto 45 359 | scu=dsqrt(one+drx(j-2)**2) 360 | dela=ha*tha 361 | if ((ie .eq. 1).or.(id .eq. 0)) ysec=fs(j-2)*scu 362 | if ((ie .eq. 0).and.(hw .gt. zro)) ysec=scu*(fs(j-2)+hw)*trpi 363 | if (hw .gt. zro) yoha=fs(j-2)/hw 364 | asca=dela+dsqrt(id*dela**2+ysec**2) 365 | rw(j-2)=asca/scu 366 | dla(j-2)=scu*(asca-ysec)*(one+yoha) 367 | rco(j-2)=fs(j-2)+dla(j-2) 368 | 45 dthc=dth 369 | goto 47 370 | 46 tha=th 371 | dtha=dth 372 | if ((iv .gt. 1) .and. (iv .lt. iw)) goto 47 373 | if (j .eq. 1 .and. ld .ge. 0) write (2,82) 374 | 47 cds(j)=asec-scw*fs(j)*roy 375 | dla(j)=scw*cds(j)*(one+yoh) 376 | rco(j)=fs(j)+dla(j) 377 | rw(j)=asec/scw 378 | if (iv .lt. iw) goto 48 379 | bta(j)=-dmdx(j)*dsu/wmn(j)/ttr(j)/scw/cfi 380 | if (j.eq.1 .or. j.gt.ko .or. iht.eq.0) goto 48 381 | if (mod(j,iht) .ne. 1) goto 48 382 | ij=j 383 | hair=rhoe*ve*cf*chair 384 | call heat 385 | 48 if (ld.lt.0) goto 56 386 | if ((iv.gt.1).and.(iv.lt.iw)) goto 56 387 | cfik=2000.d+0*cfi 388 | cfk=2000.d+0*cf 389 | cfsk=2000.d+0*cfs 390 | dthk=1000.d+0*dth 391 | cth=two*th/(one+dsqrt(one-two*th*id/asec)) 392 | ch=cds(j)/cth 393 | ieo=int(reo+half) 394 | ithx=int(rthx+half) 395 | write (2,83) j,tw,te,taw,tp,ieo,ithx,frd,cfik,cfk,cfsk,h,hi,fmy, 396 | &dthk,th,delta,delst 397 | if (j.lt.kbl-3) goto 54 398 | if (j-kbl+2) 49,50,51 399 | 49 ctha=cth 400 | xna=xn 401 | dlta=delta 402 | reoa=reo 403 | goto 55 404 | 50 cthb=cth 405 | xnb=xn 406 | dltb=delta 407 | reob=reo 408 | goto 55 409 | 51 if (j-kbl) 52,53,54 410 | 52 cthc=cth 411 | xnc=xn 412 | dltc=delta 413 | reoc=reo 414 | goto 55 415 | 53 if (it.gt.0) goto 55 416 | dlst=gma*cds(j-3)+gmb*cds(j-2)+gmc*cds(j-1)+gmd*cds(j) 417 | thbl=gma*ctha+gmb*cthb+gmc*cthc+gmd*cth 418 | hbl=dlst/thbl 419 | dltbl=gma*dlta+gmb*dltb+gmc*dltc+gmd*delta 420 | reobl=gma*reoa+gmb*reob+gmc*reoc+gmd*reo 421 | reoft=tlv*reobl 422 | reth=thbl*reobl 423 | redl=dltbl*reobl 424 | rethg=dlog10(reth) 425 | redlg=dlog10(redl) 426 | xnbl=gma*xna+gmb*xnb+gmc*xnc+gmd*xn 427 | goto 55 428 | 54 if ((j.gt.3) .and. (mod(j,10).ne.0)) goto 56 429 | 55 write (2,86) s(j),dsu,thu,cth,hu,h,ch,xn 430 | 56 continue 431 | enddo 432 | rw(1)=rco(1) 433 | call scond(s,dla,dax,kat) 434 | do j=1,kat 435 | drx(j)=waltan(j)+dax(j) 436 | enddo 437 | if ((it.gt.0) .or. (ld.lt.0)) goto 58 438 | if ((iv.gt.1) .and. (iv.lt.iw)) goto 58 439 | if (kbl .le. kat) write(2,85) xbl1,dlst,thbl,hbl,xnbl,dltbl,reoft 440 | &,reth,rethg,redl,redlg 441 | if (kbl.le.kat) goto 58 442 | hbl=cds(kat)/cth 443 | reoft=tlv*reo 444 | reth=cth*reo 445 | redl=delta*reo 446 | rethg=dlog10(reth) 447 | redlg=dlog10(redl) 448 | if(kbl.gt.kat) write(2,85) s(kat),cds(kat),cth,hbl,xn,delta,reoft 449 | &,reth,rethg,redl,redlg 450 | 58 continue 451 | enddo 452 | dd2=bma*dla(1)+bmb*dla(2)+bmc*dla(3) 453 | dr2=sd(1)+dd2 454 | dxs=dax(1)/dr2 455 | xst=s(1)-dxs 456 | yst=rco(1)-half*dax(1)**2/dr2 457 | scw=dsqrt(one+dax(1)**2) 458 | dr2=dr2/scw**3 459 | rcv=one/dr2/yst 460 | if (it.gt.0) xbin=sbin-xst 461 | if (it.gt.0) xcin=scin-xst 462 | write (2,78) itle,xbin,xcin,sf 463 | ppq=zro 464 | write (2,67) rc,etad,amach,bmach,cmach,emach,mc,ah 465 | if (twt.ne.zro) goto 59 466 | write (2,81) pps,t0 467 | goto 5 468 | 59 write (2,79) pps,t0,twt,twat,tair 469 | goto 5 470 | 60 if (it.eq.0) goto 63 471 | do k=1,kat 472 | s(k)=sref(k)-xst 473 | scv(k)=dsqrt(one+drx(k)**2) 474 | enddo 475 | scv(1)=one 476 | sl(1)=zro 477 | im=(kat-1)/2 478 | do i=1,im 479 | j=2*i 480 | ss=s(j)-s(j-1) 481 | if (i.eq.1) ss=s(2) 482 | tt=s(j+1)-s(j) 483 | st=ss+tt 484 | s1=(two-tt/ss)*st/six 485 | s3=(two-ss/tt)*st/six 486 | s2=st-s1-s3 487 | sa=(two+tt/st)*ss/six 488 | sb=(two+st/tt)*ss/six 489 | sc=ss-sa-sb 490 | sl(j)=sl(j-1)+sa*scv(j-1)+sb*scv(j)+sc*scv(j+1) 491 | sl(j+1)=sl(j-1)+s1*scv(j-1)+s2*scv(j)+s3*scv(j+1) 492 | enddo 493 | xst=zro 494 | write (2,68) ls,dk 495 | write (2,69) (k,s(k),sl(k),dla(k),rco(k),waltan(k),sk(k),dax(k),dr 496 | &x(k),wmn(k),dmdx(k),spr(k),bta(k),k=1,kat) 497 | if (kbl.gt.kat) goto 64 498 | call twixt (sl,gma,gmb,gmc,gmd,xbl,kat,kbl) 499 | xbl1=gma*s(kbl-3)+gmb*s(kbl-2)+gmc*s(kbl-1)+gmd*s(kbl) 500 | dlab=gma*dla(kbl-3)+gmb*dla(kbl-2)+gmc*dla(kbl-1)+gmd*dla(kbl) 501 | rcob=gma*rco(kbl-3)+gmb*rco(kbl-2)+gmc*rco(kbl-1)+gmd*rco(kbl) 502 | write (2,89) xbl1,xbl,dlab,rcob,gma,gmb,gmc,gmd 503 | goto 64 504 | 63 write (2,68) ly,dd 505 | write (2,69) (k,s(k),fs(k),dla(k),rco(k),waltan(k),sd(k),dax(k),dr 506 | &x(k),wmn(k),dmdx(k),spr(k),bta(k),k=1,kat) 507 | if (kbl.gt.kat) goto 64 508 | call twixt (s,gma,gmb,gmc,gmd,xbl1,kat,kbl) 509 | dlab=gma*dla(kbl-3)+gmb*dla(kbl-2)+gmc*dla(kbl-1)+gmd*dla(kbl) 510 | rcob=gma*rco(kbl-3)+gmb*rco(kbl-2)+gmc*rco(kbl-1)+gmd*rco(kbl) 511 | ybl=rcob-dlab 512 | write (2,84) xbl1,ybl,dlab,rcob,gma,gmb,gmc,gmd 513 | 64 write (2,87) xst,yst,dd2,dr2,rcv 514 | s(1)=xst 515 | rco(1)=yst 516 | drx(1)=zro 517 | if (xbl .eq. 1.d+3) return 518 | if (lv .gt. 0) goto 3 519 | 65 continue 520 | if (j .eq. 1) write (2,90) ipq,qfunw,twt 521 | return 522 | ! 523 | 66 format (6e10.3,4i5) 524 | 67 format (1x,' RC=',f11.6,3x,'ETAD=',f8.4,' DEG',3x,'AMACH=',f10.7,3 525 | &x,'BMACH=',f10.7,3x,'CMACH=',f10.7,3x,'EMACH=',f10.7,3x,a4,'H=',f1 526 | &1.7/) 527 | 68 format (1x,7x,'STA(IN) ',a4,'(IN) DELR(IN) R(IN) DY/DX 528 | & ',a8,' DA/DX DR/DX MACH NO. DM/DX PE/PO',7x,'B 529 | &ETA'/) 530 | 69 format (10(i4,0p2f11.6,2f11.7,4f10.7,f11.7,f10.7,1p2e12.4/)) 531 | 70 format (1x,5x,'QUADRATIC TEMPERATURE DISTRIBUTION') 532 | 71 format (1x,5x,'PARABOLIC TEMPERATURE DISTRIBUTION') 533 | 72 format (1x,5x,'SPALDING-CHI REFERENCE TEMPERATURE') 534 | 73 format (1x,5x,'VAN DRIEST REFERENCE REYNOLDS NUMBER'/) 535 | 74 format (1x,5x,'COLES LAW REFERENCE REYNOLDS NUMBER'/) 536 | 75 format (1x,5x,'MODIF. SPALDING-CHI REFERENCE TEMP') 537 | 76 format ('+',83x,'REFERENCE REYNOLDS NUMBER BASED ON DELTA'/) 538 | 77 format ('+',44x,'MODIFIED COLES TRANSFORMATION'/) 539 | 78 format (1x,3a4,'NOZZLE CONTOUR, RADIAL FLOW ENDS AT STA',f12.7,', 540 | &TEST CONE BEGINS AT STA',f12.7,', SCALE FACTOR =',f13.8/) 541 | 79 format (1x,1x,'STAG. PRESSURE=',f5.0,' PSI, STAG. TEMPERATURE=',f5 542 | &.0,' DEG R, THROAT TEMP.=',f5.0,' DEG R, WALL TEMP.=',f4.0,' DEG R 543 | &, THROAT HT COEF.=',f8.5//) 544 | 80 format (1x,3a4,'BOUNDARY LAYER CALCULATIONS, STAGNATION PRESSURE=' 545 | &,f5.0,'PSI, STAGNATION TEMPERATURE=',f5.0,' DEG R, N BASED ON RE,D 546 | &ELTA'//) 547 | 81 format (1x,5x,'STAG. PRESSURE=',f5.0,' PSI STAG. TEMPERATURE=',f5. 548 | &0,' DEG R ADIABATIC WALL TEMPERATURE'//) 549 | 82 format (1x,5x,'TW TE TAW TP RE/IN RTHI',4x,'FRD',5x 550 | &,'KCF1',4x,'KCF',5x,'RCFS',5x,'H',6x,'HI',5x,'FMY KTHP THETA-1 551 | & DELTA DELTA*-1'/) 552 | 83 format (1x,i3,2f6.1,f7.1,f6.1,i9,i7,4f8.5,f8.4,f7.4,2f8.5,f9.6,f7. 553 | &4,f9.6) 554 | 84 format (1x,'STA',2f11.6,2f11.7,7x,'INTERPOLATION COEFFICIENTS,',f1 555 | &2.8,',',f11.8,',',f11.8,',',f12.8/) 556 | 85 format (1x,' X=',f7.3,', DELTA*=',f10.7,', THETA=',f9.7,', 557 | & H=',f10.6,', N=',f10.7,', DELTA=',f11.7,', RE/FT=',f11.0//3 558 | &5x,'RE,THETA=',f9.0,', LOG=',f8.5,',',16x,'RE,DELTA=',f11.0,', 559 | & LOG=',f8.5/) 560 | 86 format (1x,3x,'X=',f7.3,', DSU=',f8.5,', THU=',f9.7,', CTH=' 561 | &,f9.7,', HU=',f10.6,', H=',f10.6,', CH=',f10.6,', N=',f8.5 562 | &) 563 | 87 format (1x,'STA',f11.6,' Y*=',f11.7,', D2A/DX2=',f12.9,', 564 | & D2R/DX2=',f12.9,', VISCID RC=',f14.8/) 565 | 88 format (1x,'RTHX=',1pe12.5,', REO=',e12.5,', FRO=',0pf8.5,', TH=', 566 | &f8.5,', DELTA=',f8.5,', DOT=',f9.5) 567 | 89 format (1x,'STA',2f11.6,2f11.7,7x,'INTERPOLATION COEFFICIENTS,',f1 568 | &2.8,',',f11.8,',',f11.8,',',f12.8/) 569 | 90 format ('0',' ITERATION',i4,', QFUN =',f8.5,', THROAT TEMP = 570 | &',f6.1/) 571 | end subroutine bound 572 | -------------------------------------------------------------------------------- /conturpy/read_output.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from .create_report import save_all 3 | 4 | 5 | def read_param(line, find_str, ntype=float): 6 | numeric_vals = [".", "-", *[str(x) for x in range(10)]] 7 | 8 | substr = '' 9 | idx = line.find(find_str) + len(find_str) - 1 10 | search = True 11 | while search and idx < len(line): 12 | idx += 1 13 | char = line[idx] 14 | 15 | if len(substr) == 0 and char == ' ': 16 | pass 17 | elif char in numeric_vals: 18 | substr += char 19 | elif char in ['E', 'e'] and idx < len(line) - 1 and \ 20 | (line[idx + 1] in numeric_vals or line[idx + 1] == '+'): 21 | substr += char 22 | elif char == '+' and idx > 0 and line[idx - 1] in ['e', 'E']: 23 | pass 24 | else: 25 | search = False 26 | 27 | if substr != '': 28 | return ntype(substr) 29 | else: 30 | return None 31 | 32 | 33 | def read_array(in_lines): 34 | # noinspection SpellCheckingInspection 35 | non_numeric_chars = "ABCDFGHIJKLMNOPQRSTUVWXYZabcdfghijklmnopqrstuvwxyz" 36 | search = True 37 | idx = 0 38 | data = [] 39 | 40 | while search and idx < len(in_lines) - 1: 41 | idx += 1 42 | line = in_lines[idx] 43 | 44 | if line.strip() == '': 45 | pass 46 | elif any([x in non_numeric_chars for x in line]): 47 | search = False 48 | else: 49 | piece = np.fromstring(line, sep=' ') 50 | 51 | if not data: 52 | data = [piece] 53 | elif data[0].shape != piece.shape: 54 | search = False 55 | else: 56 | data.append(piece) 57 | if data: 58 | return np.vstack(data), idx 59 | else: 60 | return None 61 | 62 | 63 | def _read_until_next_blank(line, idx): 64 | res = "" 65 | while idx >= 0 and (line[idx] != ' ' or (line[idx] == ' ' and res == "")): 66 | char = line[idx] 67 | res = char + res 68 | idx -= 1 69 | return res 70 | 71 | 72 | def get_params(line): 73 | param_list = [] 74 | for k in range(len(line) - 1, -1, -1): 75 | char = line[k] 76 | if char == '=' and k > 0: 77 | find_str = _read_until_next_blank(line, k - 1) + '=' 78 | param_list.append((find_str[:-1].strip(), read_param(line, find_str, ntype=float))) 79 | return param_list 80 | 81 | 82 | def read_table_line(line): 83 | if len(line.strip()) < 1: 84 | return None 85 | 86 | for num in range(10): 87 | line = line.replace(f"{num}-", f"{num} -") 88 | line_sections = [section for section in line.split(' ') if section.strip() != ''] 89 | try: 90 | table_line = [float(section) for section in line_sections] 91 | except ValueError: 92 | return None 93 | return np.array(table_line) 94 | 95 | 96 | def identify_tables(lines): 97 | table_lines = [read_table_line(line) for line in lines] 98 | table_idx = np.zeros((len(lines),)) 99 | 100 | line1 = table_lines[0] 101 | line2 = table_lines[1] 102 | 103 | tables = [] 104 | 105 | if line1 is not None: 106 | table_idx[0] = 1 107 | 108 | if line2 is not None: 109 | if len(line1) == len(line2): 110 | table_idx[1] = 1 111 | num_tables = 1 112 | else: 113 | table_idx[1] = 2 114 | num_tables = 2 115 | else: 116 | num_tables = 1 117 | elif line2 is not None: 118 | table_idx[1] = 1 119 | num_tables = 1 120 | else: 121 | num_tables = 0 122 | 123 | for kdx, line3 in enumerate(table_lines[2:]): 124 | idx = kdx + 2 125 | if line2 is not None and line3 is not None: 126 | if len(line2) == len(line3): 127 | table_idx[idx] = table_idx[idx - 1] 128 | else: 129 | num_tables += 1 130 | table_idx[idx] = num_tables 131 | elif line1 is not None and line3 is not None: 132 | if len(line1) == len(line3): 133 | table_idx[idx] = table_idx[idx - 2] 134 | else: 135 | pass 136 | elif line3 is not None: 137 | num_tables += 1 138 | table_idx[idx] = num_tables 139 | 140 | line1 = line2 141 | line2 = line3 142 | 143 | for table_num in range(1, num_tables + 1): 144 | start_idx = np.argwhere(table_idx == table_num)[0][0] 145 | header = None 146 | table = None 147 | if start_idx > 1: 148 | template_line = lines[start_idx] 149 | changes = np.argwhere(np.diff(np.array([char == ' ' for char in template_line]))) 150 | middle_ends = changes[1::2].flatten() + 1 151 | text_slices = np.array([[0, *middle_ends], [*middle_ends, len(template_line)]]).T 152 | header = [lines[start_idx - 2][text_slice[0]:text_slice[1]].strip() for text_slice in text_slices] 153 | table = np.vstack([table_line for idx, table_line in enumerate(table_lines) if 154 | table_idx[idx] == table_num and table_line is not None]) 155 | tables.append((header, table)) 156 | return tables, table_idx 157 | 158 | 159 | class ConturTable(object): 160 | def __init__(self, data, headers=None): 161 | self.data = data 162 | 163 | if headers is not None: 164 | if len(self.data) == 0: 165 | import warnings 166 | warnings.warn("Data and Header length must match: table read failed") 167 | self.headers = [] 168 | elif len(headers) != len(self.data[0]): 169 | import warnings 170 | warnings.warn("Data and Header length must match: table read failed") 171 | headers = ["" for _ in range(len(self.data[0]))] 172 | self.headers = self.clean_headers(headers) 173 | else: 174 | self.headers = self.clean_headers(headers) 175 | 176 | for idx, header in enumerate(self.headers): 177 | setattr(self, header, self.data[:, idx]) 178 | 179 | def __repr__(self): 180 | row_min = [max(12, len(header) + 2) for header in self.headers] 181 | header_print = "".join([f"{s:<{row_min[idx]}s}" for idx, s in enumerate(self.headers)]) 182 | 183 | if self.data.shape[0] < 10: 184 | data_print = "\n".join( 185 | [" " + "".join([f"{cell:<{row_min[idx]}g}" for idx, cell in enumerate(row)]) for row in 186 | self.data]) 187 | else: 188 | data_print = "\n".join( 189 | [" " + "".join([f"{cell:<{row_min[idx]}g}" for idx, cell in enumerate(row)]) for row in 190 | self.data[:7]]) 191 | data_print += "\n ...\n" 192 | data_print += "\n".join( 193 | [" " + "".join([f"{cell:<{row_min[idx]}g}" for idx, cell in enumerate(row)]) for row in 194 | self.data[-3:]]) 195 | 196 | return "ConturTable(" + header_print + '\n' + data_print + ")" 197 | 198 | def to_numpy(self): 199 | return self.data 200 | 201 | def to_pandas(self): 202 | import pandas as pd 203 | return pd.DataFrame(data=self.data, columns=self.headers) 204 | 205 | @staticmethod 206 | def clean_headers(headers): 207 | clean_headers = [] 208 | # noinspection SpellCheckingInspection 209 | allowable_first_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 210 | allowable_next_chars = allowable_first_chars + "0123456789" 211 | not_allowed_ends = ["_"] 212 | 213 | special_replace_dict = {"MACH NO.": "Mach"} 214 | replace_dict = {".": "_", "*": "star_", "/": "_over_", "+": "_plus_"} 215 | 216 | count_unnamed = 0 217 | 218 | for header in headers: 219 | for key in special_replace_dict: 220 | header = header.replace(key, special_replace_dict[key]) 221 | 222 | if len(header) > 0: 223 | clean_header = header[0] if header[0] in allowable_first_chars else "_" 224 | else: 225 | clean_header = f"Untitled{count_unnamed}" 226 | count_unnamed += 1 227 | 228 | if len(header) > 1: 229 | for char in header[1:]: 230 | if char in allowable_next_chars: 231 | clean_header += char 232 | elif char in replace_dict: 233 | clean_header += replace_dict[char] 234 | else: 235 | clean_header += '_' 236 | 237 | while clean_header[-1] in not_allowed_ends: 238 | clean_header = clean_header[:-1] 239 | 240 | if clean_header == 'POI': 241 | clean_header = 'POINT' 242 | elif clean_header.replace('_', '') == 'NTX': 243 | clean_header = 'X' 244 | elif clean_header.replace('_', '') == 'NTXoverYO': 245 | clean_header = 'X_over_YO' 246 | 247 | clean_headers.append(clean_header) 248 | 249 | for idx in range(len(headers)): 250 | header = headers[idx] 251 | 252 | same_msk = np.array([x == header for x in headers]) 253 | if np.sum(same_msk) > 1: 254 | for kdx in range(len(same_msk)): 255 | if same_msk[kdx]: 256 | headers[kdx] = "" 257 | 258 | for idx in range(len(headers)): 259 | header = headers[idx] 260 | if len(header) == 0: 261 | headers[idx] = f"Untitled{count_unnamed}" 262 | count_unnamed += 1 263 | 264 | return clean_headers 265 | 266 | 267 | def dispatch_section(section, name): 268 | parsers = { 269 | 'NOZZLE CONTOUR': parse_nozzle_contour, 270 | 'UPSTREAM CONTOUR': parse_upstream_contour, 271 | 'INTERMEDIATE RIGHT CHARACTERISTIC': parse_intermediate_right_characteristic, 272 | 'INTERMEDIATE LEFT CHARACTERISTIC': parse_intermediate_left_characteristic, 273 | 'BOUNDARY LAYER CALCULATIONS': parse_boundary_layer_calculations, 274 | 'INVISCID CONTOUR': parse_inviscid_contour, 275 | 'THROAT VELOCITY DISTRIBUTION': parse_throat_velocity_distribution, 276 | 'THROAT CHARACTERISTIC': parse_throat_characteristic, 277 | 'COORDINATES AND DERIVATIVES': parse_coordinates_and_derivatives} 278 | parser_list = [key for key in parsers] 279 | 280 | section_title = section[0].replace(name, '').strip() 281 | matching_keys = np.array([key in section_title for key in parser_list]) 282 | num_matches = np.sum(matching_keys) 283 | 284 | if num_matches == 0: 285 | raise NotImplementedError 286 | elif num_matches == 1: 287 | matching_name = parser_list[np.argwhere(matching_keys)[0][0]] 288 | return parsers[matching_name](section) 289 | elif "FROM THROAT CHARACTERISTIC" in section_title and "INVISCID CONTOUR" in section_title: 290 | return parse_inviscid_contour(section) 291 | else: 292 | raise Exception("Multiple matches: parsing ambiguous") 293 | 294 | 295 | class BaseConturOutput(object): 296 | def __init__(self, raw, parameters=None, tables=None): 297 | self.raw = raw 298 | self.parameters = parameters 299 | self.tables = tables 300 | self.class_name = "BaseConturOutput" 301 | 302 | def __repr__(self): 303 | return f"{self.class_name}:\n" \ 304 | f"{len(self.raw):15g} lines\n" \ 305 | f"{len(self.parameters):15g} parameter groups\n" \ 306 | f"{len(self.tables):15g} tables" 307 | 308 | 309 | class ConturOutput(BaseConturOutput): 310 | def __init__(self, raw, class_name): 311 | tables, table_idx = identify_tables(raw) 312 | parameters = [] 313 | 314 | next_table = 1 315 | for idx, line in enumerate(raw): 316 | this_table = table_idx[idx] 317 | if this_table != 0: 318 | if idx == 0: 319 | parameters.append([(f"Table {this_table:.0f}",)]) 320 | elif idx > 0 and this_table == next_table: 321 | parameters.append([(f"Table {this_table:.0f}",)]) 322 | next_table += 1 323 | if this_table == 0: 324 | possible_param = get_params(line) 325 | if len(possible_param) > 0: 326 | parameters.append(possible_param) 327 | 328 | tables = [ConturTable(data, header) for header, data in tables] 329 | 330 | super().__init__(raw, parameters, tables) 331 | self.class_name = class_name 332 | 333 | 334 | class ConturUpstreamContour(BaseConturOutput): 335 | def __init__(self, raw): 336 | tables, table_idx = identify_tables(raw) 337 | parameters = [] 338 | 339 | next_table = 1 340 | for idx, line in enumerate(raw): 341 | this_table = table_idx[idx] 342 | if this_table != 0: 343 | if idx == 0: 344 | parameters.append([(f"Table {this_table:.0f}",)]) 345 | elif idx > 0 and this_table == next_table: 346 | parameters.append([(f"Table {this_table:.0f}",)]) 347 | next_table += 1 348 | if this_table == 0: 349 | possible_param = get_params(line) 350 | if len(possible_param) > 0: 351 | parameters.append(possible_param) 352 | 353 | tables = [ConturTable(tables[0][1], ["POINT", *tables[0][0][1:5], "POINT1"])] 354 | 355 | super().__init__(raw, parameters, tables) 356 | self.class_name = "ConturUpstreamContour" 357 | 358 | 359 | class ConturInviscidContour(BaseConturOutput): 360 | def __init__(self, raw): 361 | tables, table_idx = identify_tables(raw) 362 | parameters = [] 363 | 364 | next_table = 1 365 | for idx, line in enumerate(raw): 366 | this_table = table_idx[idx] 367 | if this_table != 0: 368 | if idx == 0: 369 | parameters.append([(f"Table {this_table:.0f}",)]) 370 | elif idx > 0 and this_table == next_table: 371 | parameters.append([(f"Table {this_table:.0f}",)]) 372 | next_table += 1 373 | if this_table == 0: 374 | possible_param = get_params(line) 375 | if len(possible_param) > 0: 376 | parameters.append(possible_param) 377 | 378 | fixed_tables = [] 379 | for table_num, table in enumerate(tables): 380 | if table[1].shape[1] != len(table[0]): 381 | header = [x.strip() for x in raw[np.argwhere(table_idx == table_num + 1)[0][0] - 2].split(' ') 382 | if x.strip() != ''] 383 | fixed_tables.append(ConturTable(table[1], header)) 384 | else: 385 | fixed_tables.append(ConturTable(table[1], table[0])) 386 | 387 | if len(fixed_tables) == 2 and 'C(Y)' in raw[4]: 388 | header = ["POINT", "X/YO", "Y/YO", "INT.Y/YO", "PAR/YO", "HYP/YO", "C(Y)", "C(YI)", "C(YP)"] 389 | 390 | tab1 = fixed_tables[0].to_numpy() 391 | tab2 = fixed_tables[1].to_numpy() 392 | 393 | data = np.zeros((tab2.shape[0] + 1, tab2.shape[1])) 394 | data[1:] = tab2 395 | data[0, :tab1.shape[1]] = tab1 396 | data[0, tab1.shape[1]:] = np.nan 397 | 398 | fixed_tables = [ConturTable(data, headers=header)] 399 | 400 | super().__init__(raw, parameters, fixed_tables) 401 | self.class_name = "ConturInviscidContour" 402 | 403 | 404 | class ConturBoundaryLayerCalculations(BaseConturOutput): 405 | def __init__(self, raw): 406 | tables, table_idx = identify_tables(raw) 407 | parameters = [] 408 | 409 | next_table = 1 410 | for idx, line in enumerate(raw): 411 | this_table = table_idx[idx] 412 | if this_table != 0: 413 | if idx == 0: 414 | parameters.append([(f"Table {this_table:.0f}",)]) 415 | elif idx > 0 and this_table == next_table: 416 | parameters.append([(f"Table {this_table:.0f}",)]) 417 | next_table += 1 418 | if this_table == 0: 419 | possible_param = get_params(line) 420 | if len(possible_param) > 0: 421 | parameters.append(possible_param) 422 | 423 | data_arr = tables[0][1] 424 | header_arr = tables[0][0] 425 | 426 | extra_headers = [x[0] for x in parameters[-3]] 427 | table_header = [*header_arr, *extra_headers] 428 | 429 | table_dat = np.zeros((data_arr.shape[0], data_arr.shape[1] + len(extra_headers))) 430 | table_dat[:data_arr.shape[0], :data_arr.shape[1]] = data_arr 431 | 432 | table_row_idx = 0 433 | warning_thrown = False 434 | for idx, _ in enumerate(raw): 435 | if table_idx[idx] == 1: 436 | try: 437 | extra_dats = np.array([x[1] for x in self._get_next_param_group(raw, idx)]) 438 | table_dat[table_row_idx, data_arr.shape[1]:] = extra_dats 439 | table_row_idx += 1 440 | except ValueError: 441 | if not warning_thrown: 442 | import warnings 443 | warnings.warn( 444 | f"Boundary Layer: Unable to add un-formatted extra CONTUR array output on line {idx}") 445 | warning_thrown = True 446 | 447 | table = ConturTable(table_dat, table_header) 448 | 449 | super().__init__(raw, parameters, [table]) 450 | self.class_name = "ConturBoundaryLayerCalculations" 451 | 452 | @staticmethod 453 | def _get_next_param_group(raw, idx): 454 | search = True 455 | params = [] 456 | while search and idx < len(raw) - 1: 457 | idx += 1 458 | params = get_params(raw[idx]) 459 | if len(params) > 0: 460 | search = False 461 | return params 462 | 463 | 464 | def parse_nozzle_contour(section): 465 | return ConturOutput(section, "ConturNozzleContour") 466 | 467 | 468 | def parse_upstream_contour(section): 469 | return ConturUpstreamContour(section) 470 | 471 | 472 | def parse_intermediate_right_characteristic(section): 473 | co = ConturOutput(section, "ConturIntermediateRightCharacteristic") 474 | new_headers = co.tables[0].headers 475 | new_headers[0] = "POINT" 476 | new_headers[1] = "X" 477 | co.tables[0] = ConturTable(co.tables[0].data, new_headers) 478 | return co 479 | 480 | 481 | def parse_intermediate_left_characteristic(section): 482 | co = ConturOutput(section, "ConturIntermediateLeftCharacteristic") 483 | new_headers = co.tables[0].headers 484 | new_headers[0] = "POINT" 485 | new_headers[1] = "X" 486 | co.tables[0] = ConturTable(co.tables[0].data, new_headers) 487 | return co 488 | 489 | 490 | def parse_boundary_layer_calculations(section): 491 | if 'STA' in section[5]: 492 | return ConturOutput(section, "ConturBoundaryLayerCalculations") 493 | else: 494 | return ConturBoundaryLayerCalculations(section) 495 | 496 | 497 | def parse_inviscid_contour(section): 498 | return ConturInviscidContour(section) 499 | 500 | 501 | def parse_throat_velocity_distribution(section): 502 | return ConturOutput(section, "ConturThroatVelocityDistribution") 503 | 504 | 505 | def parse_throat_characteristic(section): 506 | co = ConturOutput(section, "ConturThroatCharacteristic") 507 | new_headers = co.tables[0].headers 508 | new_headers[0] = "POINT" 509 | new_headers[1] = "X" 510 | co.tables[0] = ConturTable(co.tables[0].data, new_headers) 511 | return co 512 | 513 | 514 | def parse_coordinates_and_derivatives(section): 515 | return ConturOutput(section, "ConturCoordinatesAndDerivatives") 516 | 517 | 518 | def post_process(contur_results): 519 | coords = [x for x in contur_results if x.class_name == "ConturCoordinatesAndDerivatives"] 520 | 521 | if not coords: 522 | import warnings 523 | warnings.warn("Unable to post-process Contur") 524 | 525 | failed_obj = BaseConturOutput("", [], ConturTable(np.array([]), [])) 526 | failed_obj.class_name = "ConturCoordinatesAndDerivatives" 527 | contur_results.append(failed_obj) 528 | 529 | return contur_results 530 | 531 | full_coords = [ConturTable(np.vstack([coord.tables[0].data for coord in coords if len(coord.tables) > 0]), 532 | coords[0].tables[0].headers)] 533 | full_text = [coord.raw for coord in coords] 534 | full_params = [x for coord in coords for x in coord.parameters] 535 | coord_obj = BaseConturOutput(full_text, full_params, full_coords) 536 | coord_obj.class_name = "ConturCoordinatesAndDerivatives" 537 | 538 | consolidated_results = [x for x in contur_results if x.class_name != "ConturCoordinatesAndDerivatives"] 539 | consolidated_results.append(coord_obj) 540 | 541 | return consolidated_results 542 | 543 | 544 | def get_project_title(lines): 545 | return lines[0][10:20] 546 | 547 | 548 | def get_project_slices(lines, title): 549 | section_slices = [idx for idx, line in enumerate(lines) if title in line] 550 | return np.vstack([section_slices, [*section_slices[1:], len(lines)]]).T 551 | 552 | 553 | class ConturResult(object): 554 | def __init__(self, filename, refine_amt=21): 555 | with open(filename, 'r') as in_file: 556 | self.raw = in_file.readlines() 557 | 558 | self.title = get_project_title(self.raw) 559 | section_slices = get_project_slices(self.raw, self.title) 560 | 561 | self.sections = [] 562 | for idx, sec in enumerate(section_slices): 563 | try: 564 | self.sections.append(dispatch_section(self.raw[sec[0]:sec[1]], self.title)) 565 | except IndexError: 566 | import warnings 567 | warnings.warn(f"Unable to parse {self.title}") 568 | except AttributeError: 569 | import warnings 570 | warnings.warn(f"Unable to parse {self.title}") 571 | 572 | self.sections = post_process(self.sections) 573 | 574 | try: 575 | self.nozzle_length = self.sections[-1].parameters[0][0][1] 576 | except IndexError: 577 | self.nozzle_length = None 578 | except TypeError: 579 | self.nozzle_length = None 580 | 581 | self.characteristics = [x for x in self.sections if 'Characteristic' in x.class_name] 582 | self.contours = [x for x in self.sections if 'Contour' in x.class_name] 583 | self.bl_calculations = [x for x in self.sections if 'BoundaryLayer' in x.class_name] 584 | 585 | self.characteristic_tables = [] 586 | for characteristic in self.characteristics: 587 | if len(characteristic.tables) == 0: 588 | pass 589 | elif len(characteristic.tables) == 1: 590 | self.characteristic_tables.append(characteristic.tables[0].to_numpy()) 591 | else: 592 | import warnings 593 | warnings.warn("Too many characteristic tables: none imported for this section") 594 | 595 | try: 596 | self.design_mach = self.contours[0].tables[0].Mach[0] 597 | except IndexError: 598 | self.design_mach = None 599 | except AttributeError: 600 | self.design_mach = None 601 | except TypeError: 602 | self.design_mach = None 603 | 604 | self.contour_tables = [] 605 | for contour in self.contours: 606 | if len(contour.tables) == 0: 607 | pass 608 | elif len(contour.tables) == 1: 609 | self.contour_tables.append(contour.tables[0].to_numpy()) 610 | else: 611 | import warnings 612 | warnings.warn("Too many contour tables: none imported for this section") 613 | 614 | self.bl_tables = [] 615 | for bl in self.bl_calculations: 616 | if len(bl.tables) == 0: 617 | pass 618 | elif len(bl.tables) == 1: 619 | self.bl_tables.append(bl.tables[0].to_numpy()) 620 | else: 621 | import warnings 622 | warnings.warn("Too many boundary layer tables: none imported for this section") 623 | 624 | try: 625 | self._coordinates = \ 626 | [x for x in self.sections if x.class_name == 'ConturCoordinatesAndDerivatives'][0].tables[0] 627 | if (isinstance(refine_amt, int) or isinstance(refine_amt, float)) and refine_amt > 1: 628 | self.coordinates = self.refine_coordinates(refine_amt) 629 | else: 630 | self.coordinates = self._coordinates 631 | except IndexError: 632 | self._coordinates = None 633 | self.coordinates = None 634 | except TypeError: 635 | self._coordinates = None 636 | self.coordinates = None 637 | 638 | @staticmethod 639 | def _cubic_spline(x1, x2, y1, y2, s1, s2, n_pts=21): 640 | pow0 = np.array([3, 2, 1, 0]) 641 | pow1 = np.array([2, 1, 0, 0]) 642 | 643 | k0 = np.array([1, 1, 1, 1]) 644 | k1 = np.array([3, 2, 1, 0]) 645 | 646 | mat_a = np.array([k0 * x1 ** pow0, k1 * x1 ** pow1, k0 * x2 ** pow0, k1 * x2 ** pow1]) 647 | mat_b = np.array([y1, s1, y2, s2]) 648 | 649 | coefficients = np.linalg.solve(mat_a, mat_b) 650 | 651 | x_vals = np.linspace(x1, x2, n_pts) 652 | y_vals = np.sum(coefficients * x_vals[:, None] ** pow0, axis=1) 653 | 654 | return x_vals, y_vals 655 | 656 | def refine_coordinates(self, n_pts=21): 657 | arr = self._coordinates.to_numpy() 658 | arr = arr[arr[:, 0].argsort()] 659 | x = arr[:, 0] 660 | y = arr[:, 1] 661 | s = arr[:, 2] 662 | return np.vstack([np.vstack(self._cubic_spline( 663 | x[idx], x[idx + 1], 664 | y[idx], y[idx + 1], 665 | s[idx], s[idx + 1], 666 | n_pts 667 | )).T for idx in range(len(x) - 1)]) 668 | 669 | def __repr__(self): 670 | return f"ConturResult:\n{len(self.raw):15g} raw lines\n{len(self.sections):15g} output sections" 671 | 672 | def save_all(self, directory): 673 | return save_all(self, directory) 674 | -------------------------------------------------------------------------------- /src/axial.f.old: -------------------------------------------------------------------------------- 1 | subroutine axial 2 | ! 3 | ! to obtain the axial distributiun of velocity and/or mach number 4 | ! 5 | use kinddefine 6 | use fg, only:gc,gd,ge,gf,gh,gi,hb,hc,he 7 | use gg, only:gam,gm,g2,g4,g5,g6,g7,g8,g9,ga,rga,qt 8 | use cline, only:wip,x1,frip,zonk,seo,cse,axis,taxi 9 | use prop, only:sfoa,conv 10 | use param, only: etad,rc,amach,bmach,cmach,emach,gmach,frc,sf,wwo, 11 | &wwop,qm,we,cbet,xe,eta,epsi,bpsi,xo,yo,rrc,sdo,xb,xc,ah,pp,se,tye, 12 | &xa 13 | use contr,only:itle,ie,lr,it,jb,jq,jx,lv,nocon,in,mc,mcp,ip,iq,ise 14 | &,jc,m,mp,mq,n,np,nf,nr,lc,md,mf,mt,nd,nt 15 | implicit none 16 | ! 17 | interface 18 | function cubic(ea,eb,ec,ed) 19 | use kinddefine 20 | implicit none 21 | real(kind=K8) :: cubic 22 | real(kind=K8),intent(in) :: ea,eb,ec,ed 23 | end function cubic 24 | ! 25 | function fmv(psi) 26 | use kinddefine 27 | implicit none 28 | real(kind=K8) :: fmv 29 | real(kind=K8), intent(in) :: psi 30 | end function fmv 31 | ! 32 | function toric(wip,se) 33 | use kinddefine 34 | implicit none 35 | real(kind=K8) :: toric 36 | real(kind=K8),intent(in) :: se,wip 37 | end function toric 38 | ! 39 | subroutine conic(xm,b) 40 | use kinddefine 41 | implicit none 42 | real(kind=K8),dimension(4),intent(out) :: b 43 | real(kind=K8),intent(in) :: xm 44 | end subroutine conic 45 | ! 46 | subroutine scond(a,b,c,king) 47 | use kinddefine 48 | implicit none 49 | integer(kind=K4),intent(in) :: king 50 | real(kind=K8),dimension(150),intent(in) :: a,b 51 | real(kind=K8),dimension(150),intent(out) :: c 52 | end subroutine scond 53 | ! 54 | subroutine sorce(w,b) 55 | use kinddefine 56 | implicit none 57 | real(kind=K8),intent(in) :: w 58 | real(kind=K8),dimension(4),intent(out) :: b 59 | end subroutine sorce 60 | ! 61 | subroutine trans(rto,tk,wo,amn,amp,ampp,w,awp,awpp,cwoppp,axn) 62 | use kinddefine 63 | implicit none 64 | real(kind=K8) :: rto,tk,wo,amn,amp,ampp,w,awp,awpp,cwoppp,axn 65 | end subroutine trans 66 | end interface 67 | ! 68 | integer(kind=K4) :: ix,j,k,l,n0,n3,n4,n5,nx 69 | real(kind=K8) :: aa,ab,abcm,aem,am,amp,ampp,amsq 70 | real(kind=K8) :: apsi,awp,awpp,awppp,bbet,bmp,bmpp,bppp 71 | real(kind=K8) :: c2,c3,c4,cm,cbm,cmc,cmp,cpp,cppp,dw,dx 72 | real(kind=K8) :: ea,eb,ebet,ec,ed,eit,eoe,ew 73 | real(kind=K8) :: fbet,fftn,fiv,fmach,fn,four,fpsi,fq,fxw 74 | real(kind=K8) :: gj,gk,gmm,gmp,gpsi,gq,gr,gs,gw,gwp,gww 75 | real(kind=K8) :: h,half,hh,om,one,q 76 | real(kind=K8) :: ra,rg,rmach,rt,sev,six,sm,smpp,smppp,sxty 77 | real(kind=K8) :: ten,thr,tk,tlv,trty,two,tyin 78 | real(kind=K8) :: w,wap,wapp,wb,xbc,wbp,wbpp,wc,wcb 79 | real(kind=K8) :: wcp,wep,wepp,weppp,whp,whpp 80 | real(kind=K8) :: wi,wipp,wippp,wm,wo,woppp,wp,wpp,wppp 81 | real(kind=K8) :: wrppp,wspp,wsppp 82 | real(kind=K8) :: x1in,xain,xbcm,xbcmn,xbcmx,xbcn,xbet,xbin 83 | real(kind=K8) :: xcin,xd,xdin,xi,xie 84 | real(kind=K8) :: xiin,xinch,xj,xm,xmp,xmpp,xmppp,xmw 85 | real(kind=K8) :: xo1,xoi,xoin,yain,zro 86 | real(kind=K8),dimension(4) :: d 87 | real(kind=K8),dimension(6) :: c 88 | real(kind=K8),dimension(150) :: ax,axm,axmp 89 | character(len=4,kind=K3) :: iaxis,m1,m2 90 | data zro/0.0d+0/,one/1.d+0/,two/2.d+0/,six/6.d+0/,half/5.d-1/ 91 | data thr/3.d+0/,four/4.d+0/,fiv/5.d+0/,ten/1.d+1/,tlv/1.2d+1/ 92 | data sev/7.d+0/,eit/8.d+0/,fftn/1.5d+1/,trty/3.d+1/,sxty/6.d+1/ 93 | data m1/'GMAC'/,m2/'2-D '/,iaxis/'AXIS'/ 94 | data n3/4h 3RD/,n4/4h 4TH/,n5/4h 5TH/,n0/4h-DEG/ 95 | ! npi=9.d+1/conv 96 | ! if (jq.eq.0.and.jx.eq.0) call orez(axis,2*750) 97 | if (jq.eq.0.and.jx.eq.0) then 98 | axis(:,:)=0.0d0 99 | taxi(:,:)=0.0d0 100 | endif 101 | if (jq .gt. 0) goto 50 102 | if (jx .eq. 0) goto 2 103 | ! 104 | ! card used to obtain internal streamlines (jx > 0) 105 | ! 106 | read (1,93,end=91) etad,qm,xj 107 | ! 108 | jx=int(xj,K4) 109 | if (etad .eq. sxty) goto 1 110 | eta=etad/conv 111 | if (ie .eq. 0) se=eta 112 | if (ie .eq. 1) se=two*dsin(half*eta) 113 | cse=dcos(eta) 114 | apsi=bpsi-eta/qt 115 | amach=fmv(apsi) 116 | ra=((g6+g5*amach**2)**ga/amach)**qt 117 | gpsi=epsi+eta/qt 118 | gmach=fmv(gpsi) 119 | rg=((g6+g5*gmach**2)**ga/gmach)**qt 120 | mp=one+thr*(ra-rg) 121 | goto 14 122 | 1 se=qm*seo 123 | goto 14 124 | ! 125 | ! constants used in transonic solution 126 | 2 gc=(two*gam/qt-thr)/six/(3+ie) 127 | ge=(thr*(8+ie)-four*gam/qt)/thr/(7+ie) 128 | gh=(fftn+(2-6*ie)*gam)/tlv/(5+ie) 129 | gj=(gam*(gam+9.25d+0*ie-26.5d+0)+.75d+0*(6-ie))/tlv/(3-ie) 130 | gk=(gam*(gam+2.25d+0*ie-16.5d+0)+2.25d+0*(2+ie))/six 131 | gr=(fftn-(1+9*ie)*gam)/(15+ie)/18.d+0 132 | hb=(14.d+0*gam-75.d+0+18*ie)/(270.d+0+18*ie) 133 | if (ie .eq. 0) goto 3 134 | gd=(gm*(652.d+0*gm+1319.d+0)+1000.d+0)/6912.d+0 135 | gf=(3612.d+0+gm*(751.d+0+gm*754.d+0))/2880.d+0 136 | gi=(909.d+0+gam*(270.d+0+gam*412.d+0))/10368.d+0 137 | gs=(gam*(gam*2708.d+0+2079.d+0)+2115.d+0)/82944.d+0 138 | hc=(gam*(2364.d+0*gam-3915.d+0)+14337.d+0)/82944.d+0 139 | he=(gam*(64.d+0*gam+117.d+0)-1026.d+0)/1152.d+0 140 | goto 4 141 | ! 142 | ! axisym flow, ie=1, qt=0.5, gam=1.4, gc=0.10833333, gd=0.236099537, 143 | ! ge=0.65833333, gf=1.40036111, gh=0.13055556, gi=0.2020177469, 144 | ! gj=0.76833333, gk=-1.87333333, gr=0.003472222, gs=0.1245814043, 145 | ! hb=0.12986111, hc=0.1626331019, he=-0.6395486111 146 | ! 147 | 3 gd=(gm*(32.d+0*gm-14.d+0)+221.d+0)/1080.d+0 148 | gf=(4230.d+0+gm*(211.d+0+gm*334.d+0))/3780.d+0 149 | gi=(738.d+0+gam*(273.d+0-gam*82.d+0))/7560.d+0 150 | gs=(gam*(gam*782.d+0+3507.d+0)+7767.d+0)/272160.d+0 151 | hc=(gam*(274.d+0*gam-861.d+0)+4464.d+0)/17010.d+0 152 | he=(gam*(32.d+0*gam+87.d+0)-561.d+0)/540.d+0 153 | ! 154 | ! planar flow, ie=0, qt=1.0,gam=1.4, gc=-0.011111, gd=0.2041851852, 155 | ! ge=0.8761904762, gf=1.155513228, gh=0.29666667, gi=0.1269153439, 156 | ! gj=-0.85111111, gk=-2.7733333, gr=0.05037037037, gs=0.05221017049, 157 | ! hb=-0.2051851852, hc=0.2231416814, he=-0.6971851852 158 | ! 159 | ! card used to establish inviscid parameters 160 | ! 161 | 4 read (1,93,end=91) etad,rc,fmach,bmach,cmc,sf,pp,xc 162 | ! 163 | ! card used to control calculations 164 | ! 165 | read (1,92) mt,nt,ix,in,iq,md,nd,nf,mp,mq,jb,jx,jc,it,lr,nx 166 | ! 167 | lc=int(xc,K4) 168 | if (xc .gt. one) lc=int(xc+one,K4) 169 | nr=six*rc 170 | mf=fmach 171 | if (ie .eq. 1) mc=m1 172 | if (ie .eq. 0) mc=m2 173 | nocon=0 174 | eta=etad/conv 175 | if (ie .eq. 0) se=eta 176 | if (ie .eq. 1) se=two*dsin(half*eta) 177 | if (etad .eq. sxty) se=one 178 | seo=se 179 | ise=int(se,K4) 180 | cse=dcos(eta) 181 | rt=rc+one 182 | am=one 183 | wi=one 184 | wipp=zro 185 | mcp=cmc 186 | cmach=dabs(cmc) 187 | cbet=dsqrt(cmach*cmach-one) 188 | frc=((g6+g5*cmach**2)**ga/cmach)**qt 189 | tye=frc*se 190 | if (sf .lt. zro) sf=-sf/tye 191 | if (ise .eq. 0) goto 5 192 | ! 193 | ! non-radial flow at inflection point 194 | iq=1 195 | amach=cmach 196 | bmach=cmach 197 | emach=cmach 198 | fmach=cmach 199 | gmach=cmach 200 | if (ie .eq. 1) am=gmach 201 | we=g2*emach/dsqrt(emach**2+g9) 202 | dw=we-wi 203 | xo=zro 204 | eoe=zro 205 | goto 15 206 | ! 207 | ! radial flow at inflection point 208 | 5 if (in .eq. 0) goto 6 209 | if ((lc .lt. 0) .and. (in .lt. 0)) in=-1 210 | if ((lc .eq. 0) .or. (mcp .lt. 0)) in=isign(10,in) 211 | 6 bbet=dsqrt(bmach*bmach-one) 212 | bpsi=g2*datan(g4*bbet)-datan(bbet) 213 | if (fmach) 9,8,7 214 | 7 fbet=dsqrt(fmach*fmach-one) 215 | fpsi=g2*datan(g4*fbet)-datan(fbet) 216 | goto 10 217 | 8 fmach=-bpsi/eta 218 | if (bpsi/eta .gt. 7.5d+0) fmach=-7.5d+0 219 | 9 fpsi=-fmach*eta 220 | fmach=fmv(fpsi) 221 | 10 epsi=fpsi-two*eta/qt 222 | emach=fmv(epsi) 223 | we=g2*emach/dsqrt(emach*emach+g9) 224 | dw=we-wi 225 | call sorce(we,d) 226 | xe=d(1) 227 | wep=d(2) 228 | wepp=d(3) 229 | wrppp=d(4) 230 | if (nr .ne. 0) goto 15 231 | if ((lr .ne. 0) .or. (iq .lt. 0)) goto 11 232 | if (ix .eq. 0) write (2,106) itle,n3 233 | if (ix .ne. 0) write (2,106) itle,n4 234 | ! 235 | ! iteration to determine rc if not specified (nr = 0) 236 | 11 ea=wrppp 237 | eb=-fiv*wepp-wipp 238 | ec=tlv*wep 239 | ed=-tlv*dw 240 | xie=cubic(ea,eb,ec,ed) 241 | if (xie .le. zro) goto 89 242 | 12 wip=two*(we-one)/xie-wep+(wepp-wipp)*xie/six 243 | 13 nocon=nocon+1 244 | if (nocon .gt. 100) goto 90 245 | 14 rt=toric(wip,se) 246 | rc=rt-one 247 | 15 tk=(one-g7*(one+(ge+gf/rt)/rt)/rt**2/(15+ie)/thr)**qt 248 | yo=se/tk 249 | aa=dsqrt(qt*(gam+one)*rt) 250 | if (qm .ne. one) goto 19 251 | whpp=(one-gam/1.5d+0+gj/rt)/(aa*yo)**2 252 | if ((nr .ne. 0) .or. (ise.eq. 1)) goto 18 253 | if (dabs(whpp-wipp) .lt. 1.d-10) goto 18 254 | wipp=whpp 255 | if (ix) 11,17,16 256 | 16 ea=gk/(aa*yo)**3 257 | eb=thr*(wipp+wepp) 258 | ec=-tlv*wep 259 | ed=tlv*dw 260 | xie=cubic(ea,eb,ec,ed) 261 | if (xie .le. zro) goto 89 262 | goto 12 263 | 17 h=(eit*wip+sev*wep)/(thr*wipp-two*wepp) 264 | hh=trty*dw/(thr*wipp-two*wepp) 265 | xie=hh/(dsqrt(h*h+hh)+h) 266 | wip=wep-half*xie*(wepp+wipp) 267 | goto 13 268 | ! 269 | ! iteration for rc completed, remainder of transonic values computed 270 | 18 wip=(one-(gc-gd/rt)/rt)/yo/aa 271 | whp=wip 272 | wipp=whpp 273 | amp=g7*wip 274 | ampp=g7*(whpp+thr*g8*wip**2) 275 | 19 xoi=yo*dsqrt(g7/two/(9-ie)/rt)*(one+(gh+gi/rt)/rt) 276 | if (qm .ne. one) goto 21 277 | if (ise .eq. 1) xi=xoi 278 | xo1=xoi 279 | wo=one-(half/(3-ie)+(gr+gs/rt)/rt)/rt 280 | om=wo/dsqrt(g7-g8*wo**2) 281 | woppp=gk/(aa*yo)**3 282 | if (lr .eq. 0) goto 21 283 | ! 284 | ! call for throat characteristic values 285 | call trans (rt,tk,wo,am,amp,ampp,wi,awp,awpp,awppp,xi) 286 | if ((nx .lt. 0) .and. (nt.lt.0)) goto 87 287 | if (nx .lt. 0) goto 4 288 | amp=amp/se 289 | ampp=ampp/se**2 290 | wap=awp/se 291 | wapp=awpp/se**2 292 | woppp=awppp/se**3 293 | if (ise .eq. 1) goto 21 294 | dw=we-wi 295 | xoi=xi*se 296 | if (nr .gt. 0) goto 20 297 | x1=xe-xie 298 | xo=xe-xie-xo1 299 | c2=xie*wip 300 | c3=half*wipp*xie**2 301 | c4=we-one-c2-c3 302 | if (ix .ne. 0) c4=four*c4+two*c3+c2-xie*wep 303 | if (iq .lt. 0) goto 20 304 | write (2,110) itle,n4,lr 305 | write (2,96) xie,c2,c3,c4,x1 306 | 20 wip=wap 307 | wipp=wapp 308 | 21 wwo=one+(one/(ie+3)-(hb-hc/rt)/rt)/rt 309 | wwop=(one+(one-ie/eit-he/rt)/rt)/yo/aa 310 | rrc=one/rc 311 | sdo=rrc/yo 312 | zonk=qm+1.0d-03 313 | np=zonk*(iabs(nf)-1)+1 314 | if (sf .gt. zro) goto 22 315 | sf=one/yo 316 | 22 if (iq .lt. 0) goto 31 317 | ip=0 318 | jq=0 319 | m=zonk*(mt-1)+1 320 | n=nt 321 | if (qm .eq. one) goto 23 322 | xo=x1-xoi 323 | return 324 | !23 call orez (c,6) 325 | 23 c(:)=0.0d0 326 | if (ise .eq. 0) goto 31 327 | ! 328 | ! length of axial distribution for non-radial flow 329 | x1=xoi 330 | aem=emach-am 331 | c(1)=am 332 | if (lc) 25,24,27 333 | 24 amsq=amp**2+aem*ampp*four/thr 334 | if (lr .eq. 0) write (2,122) itle,n4,n0 335 | if (lr .ne. 0) write (2,107) itle,n4,n0,lr 336 | if (amsq .lt. zro) goto 28 337 | xie=four*aem/(dsqrt(amsq)+amp) 338 | xe=xie+xi 339 | c(5)=thr*aem-amp*xie 340 | goto 26 341 | 25 xie=thr*aem/amp 342 | xe=xie+xi 343 | if (lr .eq. 0) write (2,122) itle,n3,n0 344 | if (lr .ne. 0) write (2,107) itle,n3,n0,lr 345 | 26 c(2)=amp*xie 346 | c(3)=six*aem-thr*c(2) 347 | c(4)=thr*c(2)-eit*aem 348 | goto 46 349 | 27 if (lc .eq. 1) goto 29 350 | xe=xc/tk 351 | xie=fiv*aem/(dsqrt(amp**2+in*aem*ampp/eit)+amp) 352 | if (xe .gt. xi+xie) xe=xi+xie 353 | xie=xe-xi 354 | c(2)=amp*xie 355 | c(3)=half*in*ampp*xie**2/ten 356 | c(4)=ten*aem-six*c(2)-thr*c(3) 357 | c(5)=-fftn*aem+eit*c(2)+thr*c(3) 358 | c(6)=six*aem-thr*c(2)-c(3) 359 | if (lr .eq. 0) write (2,122) itle,n5,n0 360 | if (lr .ne. 0) write (2,107) itle,n5,n0,lr 361 | goto 46 362 | 28 c(2)=two*aem 363 | c(4)=-c(2) 364 | c(5)=aem 365 | xie=two*aem/amp 366 | xe=xie+xi 367 | goto 46 368 | ! if xc=1 then read the centerline mach distribution from point b 369 | ! to point c. see explanatory note on xc page 54 in adec-tr-87-63 370 | 29 do j=1,nt 371 | k=nt+1-j 372 | read(9) ax(k),axm(k),axmp(k) 373 | if (j .eq. 1) dx=xi-ax(k) 374 | axis(1,k)=ax(k)+dx 375 | enddo 376 | axm(nt)=am 377 | axmp(nt)=amp 378 | xe=axis(1,1) 379 | xie=xe-xi 380 | if (lr .eq. 0) write (2,122) itle,n5,n0 381 | if (lr .ne. 0) write (2,107) itle,n5,n0,lr 382 | goto 46 383 | ! 384 | ! length of upstream axial distribution for radial flow 385 | 31 if (sfoa .eq. zro) goto 32 386 | if (lr .eq. 0) write (2,106) itle,n5 387 | if (lr .ne. 0) write (2,110) itle,n5,lr 388 | goto 44 389 | 32 if (lr .eq. 0) goto 33 390 | if ((nr .eq. 0) .and. (ix .eq. 0)) goto 41 391 | if ((nr .eq. 0) .and. (ix .ne. 0)) mf=0 392 | if (mf .ne. 0) goto 40 393 | if ((iq .lt. 0) .or. (nr .eq. 0)) goto 35 394 | if (ix .eq. 0) write (2,110) itle,n3,lr 395 | if (ix .ne. 0) write (2,110) itle,n4,lr 396 | goto 35 397 | 33 if (mf .eq. 0) goto 34 398 | if (nr .eq. 0) goto 45 399 | if (iq .ge. 0) write (2,106) itle,n4 400 | goto 41 401 | ! 402 | ! iteration for emach if not specified (mf = 0) 403 | 34 if (iq .lt. 0) goto 35 404 | if (ix .eq. 0) write (2,106) itle,n3 405 | if (ix .ne. 0) write (2,106) itle,n4 406 | 35 if (nocon .gt. 100) goto 90 407 | if (ix) 41,36,37 408 | 36 xie=six*dw/(dsqrt((wip+wep+wep)**2-six*dw*wepp)+wip+wep+wep) 409 | fxw=half*xie*(wepp+wipp)/(wep-wip) 410 | if (fxw .le. zro) ew=we+.1d+0 411 | if (fxw .le. zro) goto 39 412 | if (fxw .lt. one) ew=wi+dw*(four+fxw**2)/fiv 413 | if ((fxw .gt. one) .or. (ie .eq. 0)) ew=wi+dw*(9.d+0+fxw)/ten 414 | goto 39 415 | 37 ea=woppp 416 | eb=fiv*wipp+wepp 417 | ec=tlv*wip 418 | ed=-tlv*dw 419 | xie=cubic(ea,eb,ec,ed) 420 | if (xie .gt. zro) goto 38 421 | ew=we-.1d+0 422 | if (ew .gt. wi) goto 39 423 | write (2,113) 424 | goto 4 425 | 38 ew=wi+half*xie*(wip+wep+xie*(wipp-wepp)/six) 426 | 39 we=ew 427 | ! if (we .gt. g2) go to 79 428 | if (we .gt. g2) then 429 | write (2,119) 430 | write (2,126) 431 | stop 432 | endif 433 | if (dabs(ew-dw-wi) .lt. 1.d-9) goto 43 434 | dw=we-wi 435 | call sorce(we,d) 436 | xe=d(1) 437 | wep=d(2) 438 | wepp=d(3) 439 | wrppp=d(4) 440 | nocon=nocon+1 441 | goto 35 442 | 40 if (iq .lt. 0) goto 41 443 | write (2,110) itle,n4,lr 444 | 41 h=thr*(wep+wip)/(wipp-wepp) 445 | hh=tlv*dw/(wipp-wepp) 446 | xie=hh/(dsqrt(h*h+hh)+h) 447 | if (mf) 44,42,45 448 | 42 ew=wi+xie*(wip+thr*wep-xie*(wepp-xie*wrppp/six))/four 449 | goto 39 450 | 43 emach=we/dsqrt(g7-g8*we*we) 451 | ! 452 | ! iteration for emach completed 453 | ebet=dsqrt(emach*emach-one) 454 | epsi=g2*datan(g4*ebet)-datan(ebet) 455 | fpsi=epsi+two*eta/qt 456 | fmach=fmv(fpsi) 457 | 44 if (bmach .gt. fmach) goto 45 458 | bmach=fmach 459 | bpsi=fpsi 460 | mp=0 461 | 45 gpsi=fpsi-eta/qt 462 | gmach=fmv(gpsi) 463 | if (ie .eq. 1) ah=gmach 464 | rg=((g6+g5*gmach**2)**ga/gmach)**qt 465 | apsi=bpsi-eta/qt 466 | amach=fmv(apsi) 467 | ra=((g6+g5*amach**2)**ga/amach)**qt 468 | xa=ra*cse 469 | if (sfoa .gt. zro) xie=sfoa/sf+xe-xa-xoi 470 | if (sfoa .lt. zro) xie=xe-sfoa/sf-rg*cse-xoi 471 | xi=xe-xie 472 | xo=xi-xoi 473 | x1=xo+xo1 474 | if (iq .lt. 0) goto 48 475 | xb=((g6+g5*bmach**2)**ga/bmach)**qt 476 | if (lc .lt. 2) xc=((g6+g5*cmach**2)**ga/cmach)**qt 477 | c(1)=wi 478 | c(2)=xie*wip 479 | c(3)=half*wipp*xie*xie 480 | c(4)=ten*dw-xie*(four*wep-half*xie*wepp)-six*c(2)-thr*c(3) 481 | c(5)=xie*(sev*wep+eit*wip-xie*(wepp-thr*wipp/two))-fftn*dw 482 | c(6)=six*dw-thr*xie*(wep+wip)+half*xie*xie*(wepp-wipp) 483 | if (mf .eq. 0 .and. ix .eq. 0) c(5)=zro 484 | if (nr .eq. 0 .and. ix .eq. 0 .and. lr .eq. 0) c(5)=zro 485 | if (sfoa .eq. zro) c(6)=zro 486 | eoe=epsi/eta 487 | wippp=six*c(4)/xie/xie/xie 488 | weppp=six*(c(4)+four*c(5)+ten*c(6))/xie/xie/xie 489 | 46 write (2,99) m,n,eoe,bmach,cmach,gam,etad,rc,sf 490 | write (2,102) se,tk,wwo,wwop,emach,fmach,mc,ah 491 | if (lr .ne. 0) write (2,123) wi,wap,wapp,am,amp,ampp 492 | if (ise.eq.1 .and. lr.eq.0) write (2,123) wi,wip,whpp,am,amp,ampp 493 | if (ise .eq. 1) goto 47 494 | write (2,101) wi,wip,wipp,wippp,woppp 495 | write (2,98) we,wep,wepp,weppp,wrppp 496 | 47 write (2,94) c(1),c(2),c(3),c(4),c(5),c(6) 497 | write (2,95) xoi,xi,xo,yo,xie,xe,nocon 498 | if (ise .eq. 1) xc=xe 499 | if (ise .eq. 1) xa=xe+tye*cbet 500 | 48 nocon=0 501 | wip=whp 502 | if (qm .ne. one) goto 49 503 | if (pp .lt. zro) frip=zro 504 | if (pp .eq. zro) frip=-xo*sf 505 | if (pp .gt. zro) frip=pp-sf*xa 506 | if (iq .lt. 0) goto 50 507 | xoin=sf*xo+frip 508 | x1in=sf*x1+frip 509 | xiin=sf*xi+frip 510 | write (2,125) om,xoin,x1in,am,xiin 511 | if (iq .gt. 0) goto 67 512 | 49 if (n) 87,50,68 513 | 50 m=zonk*(md-1)+1 514 | jq=1 515 | n=nd 516 | ip=in 517 | if (qm .ne. one) return 518 | ! call orez(c,6) 519 | c(:)=0.0d0 520 | if (iq .lt. 0) goto 51 521 | if (mq .ge. 0 .and. n .gt. 0) goto 51 522 | write (2,104) 523 | goto 52 524 | 51 write (2,105) 525 | 52 if (ip) 53,67,58 526 | ! 527 | ! length of downstream velocity distribution, radial flow 528 | 53 wc=g2*cmach/dsqrt(cmach*cmach+g9) 529 | wb=g2*bmach/dsqrt(bmach*bmach+g9) 530 | wcb=wc-wb 531 | call sorce(wb,d) 532 | xb=d(1) 533 | wbp=d(2) 534 | wspp=d(3) 535 | wsppp=d(4) 536 | c(1)=wb 537 | wcp=zro 538 | if (lc) 54,55,56 539 | 54 xbc=thr*wcb/wbp 540 | wbpp=-two*wbp/xbc 541 | write (2,109) itle,n3 542 | goto 57 543 | 55 wbpp=wspp 544 | if (mcp .lt. 0) write (2,109) itle,n3 545 | if (mcp .lt. 0) xbcn=thr*wcb/wbp 546 | if (mcp .lt. 0) xbcm=-two*wbp/wbpp 547 | if (mcp .gt. 0) write (2,109) itle,n4 548 | if (mcp .gt. 0) xbcn=four*wcb/wbp 549 | if (mcp .gt. 0) xbcm=-thr*wbp/wbpp 550 | abcm=one-xbcn/xbcm 551 | if (abcm .lt. zro) goto 88 552 | xbc=xbcn/(dsqrt(abcm)+one) 553 | goto 57 554 | 56 wbpp=-wspp*ip/ten 555 | if (mcp.gt.0) xbcmn=cubic(wsppp/thr,thr*wbpp,tlv*wbp,-two*ten*wcb) 556 | if (mcp.lt.0) xbcmn=cubic(wsppp/six,wbpp,thr*wbp,-four*wcb) 557 | xbcmx=fiv*wcb/(dsqrt(wbp**2-ip*wcb*wspp/eit)+wbp) 558 | if (xc .gt. xb+xbcmx) xc=xb+xbcmx 559 | if (xc .lt. xb+xbcmn) xc=xb+xbcmn 560 | xbc=xc-xb 561 | if (mcp .lt. 0) write (2,109) itle,n4 562 | if (mcp .gt. 0) write (2,109) itle,n5 563 | 57 c(2)=xbc*wbp 564 | c(3)=half*xbc*xbc*wbpp 565 | if (mcp .lt. 0) c(4)=four*wcb-thr*c(2)-two*c(3) 566 | if (mcp .lt. 0) c(5)=-thr*wcb+two*c(2)+c(3) 567 | if (mcp .gt. 0) c(4)=ten*wcb-six*c(2)-thr*c(3) 568 | if (mcp .gt. 0) c(5)=-fftn*wcb+eit*c(2)+thr*c(3) 569 | if (mcp .gt. 0) c(6)=six*wcb-thr*c(2)-c(3) 570 | if (lc .lt. 0) c(5)=zro 571 | if (lc .le. 0) c(6)=zro 572 | xc=xb+xbc 573 | goto 63 574 | ! 575 | ! length of downstream mach no. distribution, radial flow 576 | 58 call conic(bmach,d) 577 | xb=d(1) 578 | bmp=d(2) 579 | smpp=d(3) 580 | smppp=d(4) 581 | cbm=cmach-bmach 582 | c(1)=bmach 583 | bmpp=smpp*ip/ten 584 | if (lc .ne. 0) goto 59 585 | if (mcp .lt. 0) write (2,108) itle,n3 586 | if (mcp .lt. 0) xbcn=thr*cbm/bmp 587 | if (mcp .lt. 0) xbcm=-two*bmp/bmpp 588 | if (mcp .gt. 0) write (2,108) itle,n4 589 | if (mcp .gt. 0) xbcn=four*cbm/bmp 590 | if (mcp .gt. 0) xbcm=-thr*bmp/bmpp 591 | abcm=one-xbcn/xbcm 592 | if (abcm .lt. zro) goto 88 593 | xbc=xbcn/(dsqrt(abcm)+one) 594 | xc=xb+xbc 595 | goto 62 596 | 59 if (lc .ne. 1) goto 61 597 | do k=1,nd 598 | read (9) ax(k),axm(k),axmp(k) 599 | if (k .eq. 1) dx=xb-ax(1) 600 | axis(1,k)=ax(k)+dx 601 | enddo 602 | if (axmp(2) .eq. zro) call scond(ax,axm,axmp,nd) 603 | axm(1)=bmach 604 | axmp(1)=bmp 605 | xc=axis(1,nd) 606 | xbc=xc-xb 607 | write (2,111) itle 608 | goto 63 609 | 61 if (mcp.gt.0) xbcmn=cubic(smppp/thr,thr*bmpp,tlv*bmp,-two*ten*cbm) 610 | if (mcp.lt.0) xbcmn=cubic(smppp/six,bmpp,thr*bmp,-four*cbm) 611 | xbcmx=fiv*cbm/(dsqrt(bmp**2+ip*cbm*smpp/eit)+bmp) 612 | if (xc .gt. xb+xbcmx) xc=xb+xbcmx 613 | if (xc .lt. xb+xbcmn) xc=xb+xbcmn 614 | xbc=xc-xb 615 | if (mcp .lt. 0) write (2,108) itle,n4 616 | if (mcp .gt. 0) write (2,108) itle,n5 617 | 62 c(2)=xbc*bmp 618 | c(3)=half*xbc*xbc*bmpp 619 | if (mcp .lt. 0) c(4)=four*cbm-thr*c(2)-two*c(3) 620 | if (mcp .lt. 0) c(5)=-thr*cbm+two*c(2)+c(3) 621 | if (mcp .gt. 0) c(4)=ten*cbm-six*c(2)-thr*c(3) 622 | if (mcp .gt. 0) c(5)=-fftn*cbm+eit*c(2)+thr*c(3) 623 | if (mcp .gt. 0) c(6)=six*cbm-thr*c(2)-c(3) 624 | if (lc .le. 0) c(6)=zro 625 | 63 cpp=zro 626 | cmp=zro 627 | if (mcp .lt. 0) cpp=(two*c(3)+six*c(4)+tlv*c(5))/xbc**2 628 | bppp=six*c(4)/xbc/xbc/xbc 629 | cppp=six*(c(4)+four*c(5)+ten*c(6))/xbc/xbc/xbc 630 | xd=xc+tye*cbet 631 | write (2,100) m,n,np,gam,etad,rc,sf 632 | if (ip) 64,67,65 633 | 64 write (2,116) wb,wbp,wbpp,bppp,wspp,wc,wcp,cpp,cppp,wsppp 634 | goto 66 635 | 65 write (2,117) bmach,bmp,bmpp,bppp,smpp,cmach,cmp,cpp,cppp,smppp 636 | 66 write (2,94) c(1),c(2),c(3),c(4),c(5),c(6) 637 | write (2,118) amach,xa,xb,xbc,xc,xd 638 | xain=sf*xa+frip 639 | yain=sf*xa*dtan(eta) 640 | xbin=sf*xb+frip 641 | xcin=sf*xc+frip 642 | xdin=sf*xd+frip 643 | tyin=sf*tye 644 | write (2,120) xain,yain,xbin,xcin,xdin,tyin 645 | ! the n=0 goto 4 on next line will fail with a single input card 646 | 67 if (n) 87,4,68 647 | 68 if (mq .lt. 0) goto 69 648 | ! 649 | ! calculate axial distribution 650 | write (2,103) iaxis 651 | !69 fn=n-1 652 | 69 fn=real(n-1,k8) 653 | l=int((n+40)/41,K4) 654 | if (ip .ne. 0) xie=xbc 655 | if (ip .ne. 0) xi=xb 656 | q=zro 657 | do k=1,n 658 | if (ise .eq. 1 .and. lc .eq. 1) goto 72 659 | if (ip .ne. 0) goto 70 660 | if (nx .eq. 0) q=((n-k)/fn)**2 661 | if (nx .ne. 0) q=((n-k)/fn)**(nx*1.d-1) 662 | goto 71 663 | 70 if (lc .eq. 1) goto 72 664 | q=(k-1)/fn 665 | 71 axis(1,k)=xie*q+xi 666 | 72 rmach=one 667 | if (ise .eq. 1) goto 75 668 | if (axis(1,k) .lt. one+1.d-9) goto 74 669 | ab=axis(1,k)**(rga/qt) 670 | if (ab .lt. two) sm=((one+dsqrt(ab*gm-gm))**ga)**2 671 | if (ab .ge. two) sm=(ab/g5)**g7 672 | ! if (ab .ge. two) sm=(ab/gs)**g7 673 | 73 cm=sm**g5 674 | fq=sm*(g6+g5*sm-cm*ab)/(sm-one)/g5/g6 675 | sm=sm-fq 676 | if (dabs(fq) .gt. 1.d-9) goto 73 677 | rmach=dsqrt(sm) 678 | 74 if (ip .lt. 1) goto 78 679 | 75 if (lc .eq. 1) goto 76 680 | xm=c(1)+q*(c(2)+q*(c(3)+q*(c(4)+q*(c(5)+q*c(6))))) 681 | if (ise .eq. 1 .or. k .eq. 1) goto 77 682 | if (rmach .lt. xm) write (2,124) k,rmach,xm 683 | goto 77 684 | 76 xm=axm(k) 685 | 77 xmp=(c(2)+q*(two*c(3)+q*(thr*c(4)+q*(four*c(5)+q*fiv*c(6)))))/xie 686 | if (lc .eq. 1) xmp=axmp(k) 687 | xmpp=two*(c(3)+q*(thr*c(4)+q*(six*c(5)+q*ten*c(6))))/xie/xie 688 | xmppp=six*(c(4)+q*(four*c(5)+ten*q*c(6)))/xie/xie/xie 689 | gmm=xm*xm+g9 690 | gq=dsqrt(gmm) 691 | w=g2*xm/gq 692 | wm=g9*g2/gq/gmm 693 | wp=wm*xmp 694 | wpp=wm*(xmpp-thr*xm*xmp*xmp/gmm) 695 | gmp=fiv*xm*xm*xmp*xmp/gmm-thr*xm*xmpp-xmp*xmp 696 | wppp=wm*(xmppp+thr*xmp*gmp/gmm) 697 | if (mq .lt. 0) goto 83 698 | if (mod(k-1,l) .ne. 0) goto 83 699 | goto 82 700 | 78 w=c(1)+q*(c(2)+q*(c(3)+q*(c(4)+q*(c(5)+q*c(6))))) 701 | wp=(c(2)+q*(two*c(3)+q*(thr*c(4)+q*(four*c(5)+q*fiv*c(6)))))/xie 702 | wpp=two*(c(3)+q*(thr*c(4)+q*(six*c(5)+q*ten*c(6))))/xie/xie 703 | wppp=six*(c(4)+q*(four*c(5)+ten*q*c(6)))/xie/xie/xie 704 | gww=g7-w*w*g8 705 | if (gww .gt. zro) goto 80 706 | 79 write (2,119) 707 | goto 4 708 | 80 gw=dsqrt(gww) 709 | xm=w/gw 710 | if (k .eq. 1 .or. k .eq. n) goto 81 711 | if (ip .eq. 0 .and. rmach .gt. xm) write (2,124) k,rmach,xm 712 | if (ip .ne. 0 .and. rmach .lt. xm) write (2,124) k,rmach,xm 713 | 81 xmw=g7/gw/gww 714 | xmp=xmw*wp 715 | xmpp=xmw*(wpp+thr*g8*w*wp*wp/gww) 716 | gwp=fiv*w*w*wp*wp*g8/gww+thr*w*wpp+wp*wp 717 | xmppp=xmw*(wppp+thr*wp*g8*gwp/gww) 718 | if (mq .lt. 0) goto 83 719 | if (mod(k-1,l) .ne. 0) goto 83 720 | 82 xinch=sf*axis(1,k)+frip 721 | write (2,97) k,axis(1,k),xinch,xm,xmp,xmpp,xmppp,w,wp,wpp,wppp 722 | if (mod(k+l-1,10*l) .eq. 0) write (2,115) 723 | 83 axis(3,k)=xm 724 | axis(2,k)=zro 725 | axis(5,k)=ie*half*(xm-one/xm)*wp/w 726 | xbet=dsqrt(xm**2-one) 727 | axis(4,k)=g2*datan(g4*xbet)-datan(xbet) 728 | enddo 729 | if (iq .eq. 0 .and. ip .eq. 0 .and. m .le. 0) goto 50 730 | ! the n=0 goto 4 on next line will fail with a single input card 731 | if (m) 87,4,85 732 | 85 if (ip .ne. 0) return 733 | do k=1,n 734 | do j=1,5 735 | taxi(j,k)=axis(j,k) 736 | enddo 737 | enddo 738 | return 739 | 87 lv=-1 740 | return 741 | 88 write (2,114) 742 | goto 4 743 | 89 write (2,112) 744 | goto 4 745 | 90 write (2,121) nocon 746 | goto 4 747 | 91 stop 748 | ! 749 | 92 format (16i5) 750 | 93 format (8f10.3) 751 | 94 format (1x,9x,'C1=',f11.7,3x,'C2=',f12.8,3x,'C3=',1pe15.7,3x,'C4=' 752 | &,e15.7,3x,'C5=',e15.7,3x,'C6=',e15.7/) 753 | 95 format (1x,9x,'XOI=',f12.8,3x,'XI=',f12.8,3x,'XO=',f12.8,3x,'YO=', 754 | &f12.8,3x,'XIE=',f12.8,3x,'XE=',f12.8,i5,' ITERATIONS'/) 755 | 96 format (1x,4x,'CURVE FROM MACH 1, XIE=',f12.8,' C2=',f12.8,' 756 | & C3=',1pe15.7,' C4=',e15.7,' X1=',0pf12.8/) 757 | 97 format (1x,i3,2f10.5,f10.6,1p3e14.6,0pf10.6,1p3e14.6) 758 | 98 format (1x,9x,'WE=',f12.8,4x,'WEP=',f12.8,4x,'WEPP=',1pe15.7,4x,'W 759 | &EPPP=',e15.7,4x,'WRPPP=',e15.7/) 760 | 99 format (1x,4x,'NO. OF POINTS ON 1ST CHAR. (M)=',i3,5x,'NO. OF POIN 761 | &TS ON AXIS (N)=',i3,5x,'EPSI/ETA=',f8.5,4x,'BMACH=',f9.5,4x,'CMACH 762 | &=',f9.5//5x,'GAMMA=',f7.4,5x,'INFLECTION ANG. (ETA)=',f8.4,2x,'DEG 763 | &REES',5x,'RAD. OF CURV. (RC)=',f11.6,5x,'SCALE FACTOR (SF)=',f13.8 764 | &/) 765 | 100 format (1x,4x,'NO. OF POINTS ON 1ST CHAR. (M)=',i3,5x,'NO. OF POIN 766 | &TS ON AXIS (N)=',i3,5x,'NO. OF POINTS ON LAST CHAR. (NP)=',I3//5x, 767 | &'GAMMA=',f7.4,5x,'INFLECTION ANG. (ETA)=',f8.4,2x,'DEGREES',5x,'RA 768 | &D. OF CURV. (RC)=',f13.8,5x,'SCALE FACTOR (SF)=',f11.6/) 769 | 101 format (1x,9x,'WI=',f12.8,4x,'WIP=',f12.8,4x,'WIPP=',1pe15.7,4x,'W 770 | &IPPP=',e15.7,4x,'WOPPP=',e15.7/) 771 | 102 format (1x,4x,'Y*=',f10.8,4x,'RMASS=',f10.8,4x,'WWO=',f10.7,4x,'WW 772 | &OP=',f11.8,4x,'EMACH=',f8.5,4x,'FMACH=',f10.7,4x,a4,'H=',f9.5/) 773 | 103 format (1x,1x,a4/' POINT',4x,'X',7x,'X(IN)',3x,'MACH NO.',4x,'DM/D 774 | &X',8x,'D2M/DX2',7x,'D3M/DX3',7x,'W=Q/A*',5x,'DW/DX',8x,'D2W/DX2',7 775 | &x,'D3W/DX3'/) 776 | 104 format ('0',//) 777 | 105 format (1x) 778 | 106 format (1x,3a4,' THROAT CONTOUR,',a4,'-DEG AXIAL VELOCITY DISTRIBU 779 | &TION FROM SONIC POINT'/) 780 | 107 format ('1',3a4,' INVISCID CONTOUR,',a4,a4,'AXIAL MACH NUMBER DIST 781 | &RIBUTION FROM THROAT CHARACTERISTIC WHICH HAS',i4,' POINTS'/) 782 | 108 format (1x,3a4,' DOWNSTREAM CONTOUR,',a4,'-DEG AXIAL MACH NUMBER D 783 | &ISTRIBUTION'/) 784 | 109 format (1x,3a4,' DOWNSTREAM CONTOUR,',a4,'-DEG AXIAL VELOCITY DIST 785 | &RIBUTION'/) 786 | 110 format (1x,3a4,' THROAT CONTOUR,',a4,'-DEG AXIAL VELOCITY DISTRIBU 787 | &TION FROM THROAT CHARACTERISTIC WHICH HAS',i4,' POINTS'/) 788 | 111 format (1x,3a4,' DOWNSTREAM CONTOUR'/) 789 | 112 format (1x,'SOLUTION TO CUBIC EQUATION IS NEGATIVE') 790 | 113 format (1x,'RC IS TOO LARGE TO ALLOW A SOLUTION') 791 | 114 format (1x,'BMACH IS TOO SMALL TO ALLOW A SOLUTION') 792 | 115 format (1x) 793 | 116 format ('0',9x,'WB=',f12.8,4x,'WBP=',f12.8,4x,'WBPP=',1pe15.7,4x,' 794 | &WBPPP=',e15.7,5x,'WSPP=',e15.7//10x,'WC=',0pf12.8,4x,'WCP=',f12.8, 795 | &4x,'WCPP=',1pe15.7,4x,'WCPPP=',e15.7,4x,'WSPPP=',e15.7) 796 | 117 format (1x,9x,'BMACH=',f9.5,4x,'BMP=',f12.8,4x,'BMPP=',1pe15.7,4x, 797 | &'BMPPP=',e15.7,5x,'SMPP=',e15.7//10x,'CMACH=',0pf9.5,4x,'CMP=',f12 798 | &.8,4x,'CMPP=',1pe15.7,4x,'CMPPP=',e15.7,4x,'SMPPP=',e15.7/) 799 | 118 format (1x,9x,'AMACH=',f11.7,4x,'XA=',f11.7,4x,'XB=',f11.7,4x,'XBC 800 | &=',f11.7,4x,'XC=',f12.7,4x,'XD=',f12.7/) 801 | 119 format ('0','VELOCITY GREATER THAN THEORETICAL MAXIMUM VALUE') 802 | 120 format (1x,9x,'XA(IN)=',f11.7,', YA(IN)=',f11.7,', XB(IN)=',f12.7, 803 | &', XC(IN)=',f12.7,', XD(IN)=',f12.7,', YD(IN)=',f11.7/) 804 | 121 format ('1','NO CONVERGENCE IN',i4,'ITERATIONS') 805 | 122 format ('1',3a4,' INVISCID CONTOUR,',a4,a4,' AXIAL MACH NUMBER DIS 806 | &TRIBUTION FROM SONIC POINT'/) 807 | 123 format (1x,9x,'WI=',f12.8,4x,'WIP=',f12.8,4x,'WIPP=',1pe15.7,4x,'M 808 | &I=',0pf12.8,4x,'MIP=',f12.8,4x,'MIPP=',1pe15.7/) 809 | 124 format (1x,i3,' RMACH=',2f12.8) 810 | 125 format (1x,9x,'MACH',f11.8,' AT',f11.7,' IN., MACH 1 AT',f11.7,' 811 | & IN., MACH',f11.8,' AT',f11.7,' IN.'/) 812 | 126 format (1x,'CHANGE CARD 3 INPUT MACH NUMBER'/) 813 | end subroutine axial 814 | --------------------------------------------------------------------------------