module TUBEIRA_GERAL

! sigla = TUB_GER_

! objetivo: gerar perfil de tubeira e malha

! versão original 1.0 (28 Mai 99)

! programador: Carlos Henrique Marchi
! local:       SINMEC/UFSC - Florianópolis - SC

! versão atual    1.2 ( 6 Dez 99)

! última alteração =   17 Fev 00

!-------------------------------------------------

! RELAÇÃO DAS ROTINAS DESTE MÓDULO:

  ! TUB_GER_area_parede
  ! TUB_GER_area_transversal
  ! TUB_GER_escreve_binario
  ! TUB_GER_escreve_texto
  ! TUB_GER_executa
  ! TUB_GER_garganta
  ! TUB_GER_grafico_tubeira
  ! TUB_GER_le_dados
  ! TUB_GER_le_inicio

!-------------------------------------------------

! rotinas onde são lidos ARQUIVOS de dados neste MÓDULO:

  ! TUB_GER_le_dados
  ! TUB_GER_le_inicio

!-------------------------------------------------

! rotinas onde são gerados ARQUIVOS neste MÓDULO:

  ! TUB_GER_escreve_binario
  ! TUB_GER_executa
  ! TUB_GER_grafico_tubeira

!-------------------------------------------------

use ARQUIVO            ! versão 1.2 (19 Jan 00)

use TUBEIRA_NOMES      !            (19 Jan 00)

use PLOTA              ! versão 1.2 (19 Jan 00)

use TUBEIRA_COS_CAMARA ! versão 1.0 (20 Jan 00)

use TUBEIRA_PARABOLICA ! versão 1.1 (19 Jan 00)

! -----------------------------------------------

implicit none

! -----------------------------------------------

contains

! -----------------------------------------------

  subroutine TUB_GER_area_parede ( n, xe, re, rp, sn_tot, sn )

    integer,intent(in) :: n ! número total de volumes de controle + 2

    real*8,dimension(:),intent(in)  :: xe ! coordenada espacial na face leste do volume de controle
    real*8,dimension(:),intent(in)  :: re ! raio na face leste do volume de controle
    real*8,dimension(:),intent(in)  :: rp ! raio no centro do volume de controle

    real*8,intent(out) :: sn_tot ! área total da parede da tubeira (m2)

    real*8,dimension(:),intent(out) :: sn ! área da parede da tubeira

    real*8 :: pi ! constante matemática
    real*8 :: dl ! comprimento da parede do volume
    real*8 :: pw ! perímetro médio da parede do volume 

    pi = dacos(-1.0d0)

    sn_tot = 0.0d0

    do i = 2, n-1
       pw = 2.0d0 * pi * rp(i)
       dl = dsqrt ( (xe(i)-xe(i-1))**2 + (re(i)-re(i-1))**2 )
       sn(i) = pw * dl
       sn_tot = sn_tot + sn(i)
    end do

    sn(1) = sn(2)
    sn(n) = sn(n-1)

  end subroutine TUB_GER_area_parede

!-------------------------------------------------

  subroutine TUB_GER_area_transversal ( r, s )

    real*8,dimension(:),intent(in)  :: r ! raio

    real*8,dimension(:),intent(out) :: s ! área

    real*8 :: pi ! constante matemática

    pi = dacos(-1.0d0)

    s = pi * ( r ** 2 )

  end subroutine TUB_GER_area_transversal

!-------------------------------------------------

  subroutine TUB_GER_escreve_binario

    select case ( sai_binario )

       case ( 1 ) ! escreve todos os parâmetros calculados

          ! para o programa MACH1D
          open ( unit_aux, file = trim(nome_caso)//'.tubeira.mach1d.bin', form='unformatted' )
          write ( unit_aux ) n, ng, xg, sg, rc
          write ( unit_aux ) xe, re, se, xp, rp, sp, sn
          close ( unit_aux )

          ! para o programa PAREDE
          open ( unit_aux, file = trim(nome_caso)//'.tubeira.parede.bin', form='unformatted' )
          write ( unit_aux ) n, sn_tot
          write ( unit_aux ) xe, xp, re
          close ( unit_aux )

    end select

  end subroutine TUB_GER_escreve_binario

! -----------------------------------------------

  subroutine TUB_GER_escreve_texto

    real*8 :: hmin, hmax, hmed, dx

    hmed = ( xp(n) - xp(1) ) / ( n - 2 )

    if ( tipo_malha == 1 ) then

       write ( unit_main, 1 ) hmed
       1 format ( //, t6, 'tamanho dos volumes de controle', /, &
                 1pe26.15,' = dx (m)')

    else

       hmin = xe(2) - xe(1)
       hmax = xe(2) - xe(1)
       do i = 1, n-2
          dx = xe(i+1) - xe(i)
          if ( dx < hmin ) hmin = dx
          if ( dx > hmax ) hmax = dx
       end do
       write ( unit_main, 2 ) hmin, hmed, hmax, hmax/hmin
       2 format ( //, t6, 'tamanhos dos volumes de controle', /, &
                 1pe26.15,' = mínimo (m)', /, &
                 1pe26.15,' = médio (m)', /, &
                 1pe26.15,' = máximo (m)', /, &
                 1pe26.15,' = máximo / mínimo' )

    end if

    write ( unit_main, 3 ) ng, xg, sg, rc

    3 format (  /, t6, 'dados da garganta da tubeira', /, &
                i6,20x,' = ponto da garganta', /, &
              1pe26.15,' = coordenada da garganta da tubeira (m)', /, &
              1pe26.15,' = área da garganta da tubeira (m2)', /, &
              1pe26.15,' = raio de curvatura na garganta da tubeira (m)' )

    write ( unit_main, 4 ) sn_tot
    4 format (/, 1pe26.15,' = área total da parede da tubeira (m2)')

    call ARQUIVO_escreve_campo_1D ( unit_main,       & ! unidade de arquivo para escrever
                            w_x_r_faces,             & ! freqüência de escrita
                            '*** X e RAIO *** (faces )                          ', & ! 50 colunas
                            ' ponto',                & !  6 colunas
                            'x (m)                ', & ! 21 colunas
                            'raio (m)             ', & ! 21 colunas
                            1,                       & ! número do ponto inicial
                            n-1,                     & ! número de dados a escrever
                            xe,                      & ! coordenada espacial
                            re                       ) ! variável a escrever

    call ARQUIVO_escreve_campo_1D ( unit_main,       & ! unidade de arquivo para escrever
                            w_x_r_nos,               & ! freqüência de escrita
                            '*** X e RAIO *** (nós)                             ', & ! 50 colunas
                            ' ponto',                & !  6 colunas
                            'x (m)                ', & ! 21 colunas
                            'raio (m)             ', & ! 21 colunas
                            1,                       & ! número do ponto inicial
                            n,                       & ! número de dados a escrever
                            xp,                      & ! coordenada espacial
                            rp                       ) ! variável a escrever

    call ARQUIVO_escreve_campo_1D ( unit_main,       & ! unidade de arquivo para escrever
                            w_se,                    & ! freqüência de escrita
                            '*** área transversal *** (faces)                   ', & ! 50 colunas
                            ' ponto',                & !  6 colunas
                            'x (m)                ', & ! 21 colunas
                            'área transversal (m2)', & ! 21 colunas
                            1,                       & ! número do ponto inicial
                            n-1,                     & ! número de dados a escrever
                            xe,                      & ! coordenada espacial
                            se                       ) ! variável a escrever

    call ARQUIVO_escreve_campo_1D ( unit_main,       & ! unidade de arquivo para escrever
                            w_sp,                    & ! freqüência de escrita
                            '*** área transversal *** (nós)                     ', & ! 50 colunas
                            ' ponto',                & !  6 colunas
                            'x (m)                ', & ! 21 colunas
                            'área transversal (m2)', & ! 21 colunas
                            2,                       & ! número do ponto inicial
                            n-1,                     & ! número de dados a escrever
                            xp,                      & ! coordenada espacial
                            sp                       ) ! variável a escrever

    call ARQUIVO_escreve_campo_1D ( unit_main,       & ! unidade de arquivo para escrever
                            w_sn,                    & ! freqüência de escrita
                            '*** área da parede *** (nós)                       ', & ! 50 colunas
                            ' ponto',                & !  6 colunas
                            'x (m)                ', & ! 21 colunas
                            'área da parede (m2)  ', & ! 21 colunas
                            2,                       & ! número do ponto inicial
                            n-1,                     & ! número de dados a escrever
                            xp,                      & ! coordenada espacial
                            sn                       ) ! variável a escrever

  end subroutine TUB_GER_escreve_texto 

! -----------------------------------------------

  subroutine TUB_GER_executa

    ! *** LEITURA DE DADOS ***

    ! arquivo de inicialização do programa TUBEIRA
    call TUB_GER_le_inicio ( unit_aux, inicio )

    ! dados do módulo ARQUIVO
    call ARQUIVO_le_inicio ( unit_aux, arquivo_nome_inicio_modulo )
    call ARQUIVO_passa_caso ( nome_caso )

    ! dados do módulo TUBEIRA_GERAL
    if ( lista_tub_ger == 1 ) call ARQUIVO_notepad_abre_dado ( nome_tub_ger )
    if ( le_tub_ger    == 1 ) call TUB_GER_le_dados ( unit_aux, nome_tub_ger )
    if ( copia_tub_ger == 1 ) call ARQUIVO_copia_arquivo ( nome_tub_ger )

    ! lê dados da tubeira selecionada

    select case ( tipo_tubeira )

       case ( 0 ) ! tabela de dados
          !call ARQUIVO_notepad_abre_dado ( nome_tabela )
          !call dados_tubeira_tabela ( unit_aux, n, nome_tabela )

       case ( 1 ) ! linear
          !call tubeira_linear (  )

       case ( 2 ) ! parabólica simétrica
          call TUB_PAR_le_inicio ( unit_aux, tub_par_nome_inicio_modulo, n )

       case ( 3 ) ! cossenoidal simétrica
          !call tubeira_cossenoidal (  )

       case ( 4 ) ! cossenoidal simétrica com câmara
          call TUB_COS_CAM_le_inicio ( unit_aux, tub_cos_cam_nome_inicio_modulo, n )

    end select

    ! *** ALOCAÇÃO DE MEMÓRIA ***

    allocate ( xp(n),   rp(n),   sp(n),  sn(n) )

    allocate ( xe(n-1), re(n-1), se(n-1) )

    ! *** CÁLCULO DOS PARÂMETROS DA TUBEIRA SELECIONADA ***

    select case ( tipo_tubeira )

       case ( 0 ) ! tabela de dados
          !call nos_faces_tubeira_tabela ( n, xp, rp, xe, re )

       case ( 2 ) ! parabólica simétrica
          if ( tipo_malha == 1 ) then
             call TUB_PAR_calcula_X_R_nos ( xp, rp )
             call TUB_PAR_calcula_X_R_faces ( xp, xe, re )
          end if
          call TUB_PAR_raio_curvatura ( rc )

       case ( 4 ) ! cossenoidal simétrica com câmara
          if ( tipo_malha == 1 ) then
             call TUB_COS_CAM_calcula_X_R_nos ( xp, rp )
             call TUB_COS_CAM_calcula_X_R_faces ( xp, xe, re )
          end if
          call TUB_COS_CAM_raio_curvatura ( rc )

    end select

    call TUB_GER_area_transversal ( rp, sp )

    call TUB_GER_area_transversal ( re, se )

    call TUB_GER_garganta ( n, xp, sp, xe, se, ng, xg, sg )

    call TUB_GER_area_parede ( n, xe, re, rp, sn_tot, sn )

  ! *** GERAÇÃO DOS ARQUIVOS DE SAÍDA ***

    call TUB_GER_escreve_binario

    if ( w_lista == 1 ) then
   
       call ARQUIVO_cria_arquivo ( unit_main, trim(nome_caso)//'.tubeira.txt' )

       write ( unit_main, 1 ) titulo
       1 format ( /, t6, a100, // )

       call ARQUIVO_escreve_data_hora ( unit_main )

       call TUB_GER_escreve_texto

       close ( unit_main )

       if ( lista_caso == 1 ) &
          call ARQUIVO_notepad_abre_saida ( unit_aux, trim(nome_caso)//'.tubeira.txt' )

    end if

    if ( w_grafico /= 0 ) call TUB_GER_grafico_tubeira

  end subroutine TUB_GER_executa

! -----------------------------------------------

  subroutine TUB_GER_garganta ( n, xp, sp, xe, se, ng, xg, sg )

    integer,intent(in) :: n ! número total de volumes de controle + 2

    real*8,dimension(:),intent(in) :: xp ! coordenada espacial no centro do volume de controle
    real*8,dimension(:),intent(in) :: sp ! área no centro do volume de controle
    real*8,dimension(:),intent(in) :: xe ! coordenada espacial na face leste do volume de controle
    real*8,dimension(:),intent(in) :: se ! área na face leste do volume de controle

    integer,intent(out) :: ng ! índice da garganta
    real*8, intent(out) :: xg ! coordenada da garganta
    real*8, intent(out) :: sg ! área da garganta

    sg = sp(n)

    do i = 1, n
       if ( sp(i) <= sg ) then
            sg = sp(i)
            ng = i
            xg = xp(i)
       end if
    end do

    do i = 1, n-1
       if ( se(i) <= sg ) then
            sg = se(i)
            ng = i
            xg = xe(i)
       end if
    end do

  end subroutine TUB_GER_garganta

!-------------------------------------------------

  subroutine TUB_GER_grafico_tubeira

    call PLOTA_copia_Wgnuplot

    ! dados do módulo PLOTA: nomes dos casos a plotar (sem as extensões)
    call PLOTA_le_inicio ( unit_aux, plota_nome_inicio_modulo )

    ! perfil da tubeira
    call ARQUIVO_grava_campo_1D ( unit_aux,             & ! unidade de arquivo para escrever
                          trim(nome_caso)//'.tubeira.grafico.dat', & ! nome do arquivo
                          w_grafico,                    & ! freqüência de escrita
                          1,                            & ! número do ponto inicial
                          n-1,                          & ! número de dados a escrever
                          xe,                           & ! dados da coluna 1
                          re                            ) ! dados da coluna 2

    call PLOTA_le_dados_gnu (  unit_aux, 'tubeira.grafico.ent' )
    call PLOTA_gera_gnu ( unit_aux, trim(nome_caso)//'.tubeira.grafico.gnu' )
    call PLOTA_executa_Wgnuplot ( unit_aux, trim(nome_caso)//'.tubeira.grafico.gnu' )

    ! malha da tubeira
    call ARQUIVO_cria_arquivo ( unit_aux, trim(nome_caso)//'.tubeira.grafico.dat' )
    do i = 1, n-1
       if ( i==1 .or. i==(n-1) .or. mod(i,w_grafico)==0 ) &
          write ( unit_aux, 1 ) xe(i), re(i)
    end do
    write ( unit_aux, 1 )
    do i = 1, n-1
       if ( i==1 .or. i==(n-1) .or. mod(i,w_grafico)==0 ) &
          write ( unit_aux, 1 ) xe(i), re(i)
          write ( unit_aux, 1 ) xe(i), 0.0d0
          write ( unit_aux, 1 )
    end do
    write ( unit_aux, 1 )
    do i = 2, n-1
       if ( i==1 .or. i==(n-1) .or. mod(i,w_grafico)==0 ) &
          write ( unit_aux, 1 ) xp(i), 0.0d0
    end do
    1 format ( 2 ( 1pe25.15 ) )
    close ( unit_aux )
    call PLOTA_le_dados_gnu (  unit_aux, 'tubeira.grafico.ent' )
    call PLOTA_gera_gnu ( unit_aux, trim(nome_caso)//'.tubeira.grafico.gnu' )
    call PLOTA_executa_Wgnuplot ( unit_aux, trim(nome_caso)//'.tubeira.grafico.gnu' )
 
  end subroutine TUB_GER_grafico_tubeira

! -----------------------------------------------

  subroutine TUB_GER_le_dados ( unit, nome )

    integer,      intent(in) :: unit ! unidade do arquivo
    character*(*),intent(in) :: nome ! nome do arquivo

    open ( unit, file = trim(nome) )

    read ( unit, * ) titulo
    read ( unit, * ) tipo_tubeira
    read ( unit, * ) tipo_malha
    read ( unit, * ) refino
    read ( unit, * ) sai_binario
    read ( unit, * ) w_lista
    read ( unit, * ) lista_caso
    read ( unit, * ) w_x_r_faces
    read ( unit, * ) w_x_r_nos
    read ( unit, * ) w_se
    read ( unit, * ) w_sp
    read ( unit, * ) w_sn
    read ( unit, * ) w_grafico

    if ( tipo_tubeira == 0 .or. refino == 0 .or. refino == 1 ) read ( unit, * ) nome_tabela

    close ( unit )

  end subroutine TUB_GER_le_dados

!-------------------------------------------------

  subroutine TUB_GER_le_inicio ( unit, nome )

    integer,      intent(in) :: unit ! unidade do arquivo
    character*(*),intent(in) :: nome ! nome do arquivo de dados de configuração do programa

    open ( unit, file = trim(nome) )

    read ( unit, * ) nome_tub_ger 
    read ( unit, * ) lista_tub_ger
    read ( unit, * ) le_tub_ger
    read ( unit, * ) copia_tub_ger

    read ( unit, * ) arquivo_nome_inicio_modulo  
    read ( unit, * ) plota_nome_inicio_modulo
    read ( unit, * ) tub_par_nome_inicio_modulo
    read ( unit, * ) tub_cos_cam_nome_inicio_modulo

    close ( unit )

  end subroutine TUB_GER_le_inicio

! -----------------------------------------------

end module TUBEIRA_GERAL
