!===============================================================================
! User source terms definition.
!
! 1) Momentum equation (coupled solver)
! 2) Species transport
! 3) Turbulence (k-epsilon, k-omega, Rij-epsilon, v2-f, Spalart-Allmaras)
!===============================================================================

!-------------------------------------------------------------------------------

!                      Code_Saturne version 4.0.5
!                      --------------------------
! This file is part of Code_Saturne, a general-purpose CFD tool.
!
! Copyright (C) 1998-2016 EDF S.A.
!
! This program is free software; you can redistribute it and/or modify it under
! the terms of the GNU General Public License as published by the Free Software
! Foundation; either version 2 of the License, or (at your option) any later
! version.
!
! This program is distributed in the hope that it will be useful, but WITHOUT
! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
! FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
! details.
!
! You should have received a copy of the GNU General Public License along with
! this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
! Street, Fifth Floor, Boston, MA 02110-1301, USA.

!-------------------------------------------------------------------------------

!===============================================================================
! Purpose:
! -------

!> \file cs_user_source_terms.f90
!>
!> \brief Additional right-hand side source terms
!>
!> \brief Additional right-hand side source terms for velocity components equation
!> (Navier-Stokes)
!>
!> \section ustsnv_use  Usage
!>
!> The additional source term is decomposed into an explicit part (\c crvexp) and
!> an implicit part (\c crvimp) that must be provided here.
!> The resulting equation solved by the code for a velocity is:
!> \f[
!>  \rho \norm{\vol{\celli}} \DP{\vect{u}} + ....
!>   = \tens{crvimp} \cdot \vect{u} + \vect{crvexp}
!> \f]
!>
!> Note that \c crvexp and \c crvimp are defined after the Finite Volume integration
!> over the cells, so they include the "volume" term. More precisely:
!>   - crvexp is expressed in kg.m/s2
!>   - crvimp is expressed in kg/s
!>
!> The \c crvexp and \c crvimp arrays are already initialized to 0
!> before entering the
!> the routine. It is not needed to do it in the routine (waste of CPU time).
!>
!> \remark The additional force on \f$ x_i \f$ direction is given by
!>  \c crvexp(i, iel) + vel(j, iel)* crvimp(j, i).
!>
!> For stability reasons, Code_Saturne will not add -crvimp directly to the
!> diagonal of the matrix, but Max(-crvimp,0). This way, the crvimp term is
!> treated implicitely only if it strengthens the diagonal of the matrix.
!> However, when using the second-order in time scheme, this limitation cannot
!> be done anymore and -crvimp is added directly. The user should therefore test
!> the negativity of crvimp by himself.
!>
!> When using the second-order in time scheme, one should supply:
!>   - crvexp at time n
!>   - crvimp at time n+1/2
!>
!> The selection of cells where to apply the source terms is based on a
!> \ref getcel command. For more info on the syntax of the \ref getcel command,
!> refer to the user manual or to the comments on the similar command
!> \ref getfbr in the routine \ref cs_user_boundary_conditions.
!
!-------------------------------------------------------------------------------

!-------------------------------------------------------------------------------
! Arguments
!______________________________________________________________________________.
!  mode           name          role                                           !
!______________________________________________________________________________!
!> \param[in]     nvar          total number of variables
!> \param[in]     nscal         total number of scalars
!> \param[in]     ncepdp        number of cells with head loss terms
!> \param[in]     ncesmp        number of cells with mass source terms
!> \param[in]     ivar          index number of the current variable
!> \param[in]     icepdc        index number of cells with head loss terms
!> \param[in]     icetsm        index number of cells with mass source terms
!> \param[in]     itypsm        type of mass source term for each variable
!>                               (see \ref cs_user_mass_source_terms)
!> \param[in]     dt            time step (per cell)
!> \param[in]     ckupdc        head loss coefficient
!> \param[in]     smacel        value associated to each variable in the mass
!>                               source terms or mass rate (see
!>                               \ref cs_user_mass_source_terms)
!> \param[out]    crvexp        explicit part of the source term
!> \param[out]    crvimp        implicit part of the source term
!_______________________________________________________________________________



!===============================================================================


!===============================================================================
! Purpose:
! -------

!    User subroutine.

!    Additional right-hand side source terms for scalar equations (user
!     scalars and specific physics scalars).

!
! Usage
! -----
! The routine is called for each scalar, user or specific physisc. It is
! therefore necessary to test the value of the scalar number iscal to separate
! the treatments of the different scalars (if (iscal.eq.p) then ....).
!
! The additional source term is decomposed into an explicit part (crvexp) and
! an implicit part (crvimp) that must be provided here.
! The resulting equation solved by the code for a scalar f is:
!
!  rho*volume*df/dt + .... = crvimp*f + crvexp
!
!
! Note that crvexp and crvimp are defined after the Finite Volume integration
! over the cells, so they include the "volume" term. More precisely:
!   - crvexp is expressed in kg.[scal]/s, where [scal] is the unit of the scalar
!   - crvimp is expressed in kg/s
!
!
! The crvexp and crvimp arrays are already initialized to 0 before entering the
! the routine. It is not needed to do it in the routine (waste of CPU time).
!
! For stability reasons, Code_Saturne will not add -crvimp directly to the
! diagonal of the matrix, but Max(-crvimp,0). This way, the crvimp term is
! treated implicitely only if it strengthens the diagonal of the matrix.
! However, when using the second-order in time scheme, this limitation cannot
! be done anymore and -crvimp is added directly. The user should therefore test
! the negativity of crvimp by himself.
!
! When using the second-order in time scheme, one should supply:
!   - crvexp at time n
!   - crvimp at time n+1/2
!
!
! The selection of cells where to apply the source terms is based on a getcel
! command. For more info on the syntax of the getcel command, refer to the
! user manual or to the comments on the similar command getfbr in the routine
! cs_user_boundary_conditions.

! WARNING: If scalar is the temperature, the resulting equation
!          solved by the code is:
!
!  rho*Cp*volume*dT/dt + .... = crvimp*T + crvexp
!
!
! Note that crvexp and crvimp are defined after the Finite Volume integration
! over the cells, so they include the "volume" term. More precisely:
!   - crvexp is expressed in W
!   - crvimp is expressed in W/K
!

!
! STEEP SOURCE TERMS
!===================
! In case of a complex, non-linear source term, say F(f), for scalar f, the
! easiest method is to implement the source term explicitely.
!
!   df/dt = .... + F(f(n))
!   where f(n) is the value of f at time tn, the beginning of the time step.
!
! This yields :
!   crvexp = volume*F(f(n))
!   crvimp = 0
!
! However, if the source term is potentially steep, this fully explicit
! method will probably generate instabilities. It is therefore wiser to
! partially implicit the term by writing:
!
!   df/dt = .... + dF/df*f(n+1) - dF/df*f(n) + F(f(n))
!
! This yields:
!   crvexp = volume*( F(f(n)) - dF/df*f(n) )
!   crvimp = volume*dF/df

!-------------------------------------------------------------------------------
! Arguments
!______________________________________________________________________________________.
!  mode            name                 role                                           !
! _____________________________________________________________________________________!
!> \param[in]      nvar               total number of variables
!> \param[in]      nscal              total number of scalars
!> \param[in]      ncepdp             number of cells with head loss terms
!> \param[in]      ncesmp             number of cells with mass source terms
!> \param[in]      iscal              index number of the current scalar
!> \param[in]      icepdc             index number of cells with head loss terms
!> \param[in]      icetsm             index number of cells with mass source terms
!> \param[in]      itypsm             type of mass source term for each variable
!>                                     (see cs_user_mass_source_terms)
!> \param[in]      dt                 time step (per cell)
!> \param[in]      ckupdc             head loss coefficient
!> \param[in]      smacel             value associated to each variable in the mass
!>                                    source terms or mass rate
!>                                    (see cs_user_mass_source_terms)
!> \param[out]     crvexp             explicit part of the source term
!> \param[out]     crvimp             implicit part of the source term
!______________________________________________________________________________________!

subroutine ustssc &
 ( nvar   , nscal  , ncepdp , ncesmp ,                            &
   iscal  ,                                                       &
   icepdc , icetsm , itypsm ,                                     &
   dt     ,                                                       &
   ckupdc , smacel ,                                              &
   crvexp , crvimp )

!===============================================================================
! Module files
!===============================================================================

use paramx
use numvar
use entsor
use optcal
use cstphy
use parall
use period
use mesh
use field

!===============================================================================

implicit none

! Arguments

integer          nvar   , nscal
integer          ncepdp , ncesmp
integer          iscal

integer          icepdc(ncepdp)
integer          icetsm(ncesmp), itypsm(ncesmp,nvar)

double precision dt(ncelet)
double precision ckupdc(ncepdp,6), smacel(ncesmp,nvar)
double precision crvexp(ncelet), crvimp(ncelet)

! Local variables

character*80     chaine
integer          ivar, iiscvr,  iel
integer          ilelt, nlelt

double precision tauf, prodf, volf, pwatt

integer, allocatable, dimension(:) :: lstelt
double precision, dimension(:), pointer ::  cpro_rom

double precision vol
double precision, dimension(4) :: rej_xmin,rej_xmax,rej_ymin,rej_ymax,rej_zmin,rej_zmax

!===============================================================================



!===============================================================================
! 1. Initialization
!===============================================================================

! Rejet 1
rej_xmin(1)=260.d0
rej_xmax(1)=280.d0
rej_ymin(1)=200.d0
rej_ymax(1)=220.d0
rej_zmin(1)=  0.d0
rej_zmax(1)=  2.d0

! Rejet 2
rej_xmin(2)=260.d0
rej_xmax(2)=280.d0
rej_ymin(2)=200.d0
rej_ymax(2)=220.d0
rej_zmin(2)= 35.d0
rej_zmax(2)= 50.d0

! Rejet 3
rej_xmin(3)=270.d0
rej_xmax(3)=275.d0
rej_ymin(3)=495.d0
rej_ymax(3)=500.d0
rej_zmin(3)=  0.d0
rej_zmax(3)=  2.d0

! Rejet 4
rej_xmin(4)=385.d0
rej_xmax(4)=390.d0
rej_ymin(4)=495.d0
rej_ymax(4)=500.d0
rej_zmin(4)=  0.d0
rej_zmax(4)=  2.d0

call vol_cells(rej_xmin(iscal),rej_xmax(iscal),rej_ymin(iscal),rej_ymax(iscal),&
rej_zmin(iscal),rej_zmax(iscal),vol,iscal)

call source_vol(rej_xmin(iscal),rej_xmax(iscal),rej_ymin(iscal),rej_ymax(iscal),&
rej_zmin(iscal),rej_zmax(iscal),vol,iscal)


return

!----
! End
!----

contains

! =====================================
! ================ subroutine vol_cells
! =====================================

subroutine vol_cells(xmin,xmax,ymin,ymax,zmin,zmax,vol,jjscal)
!
!   Calcule le volume associe a chaque rejet
!
    double precision, intent(in) :: xmin,xmax
    double precision, intent(in) :: ymin,ymax
    double precision, intent(in) :: zmin,zmax
    double precision, intent(out) :: vol
    integer,          intent(in) :: jjscal

    character*240                :: critere              ! pour y ecrire le critere de selection des faces de bord
    integer                      :: nlelttot  ! pour compter le nombre de faces en multi-proc
    integer ilelt, nlelt
    integer, allocatable, dimension(:) :: lstelt

    allocate(lstelt(ncel))

    critere=' '
    write(critere,3000) xmin,xmax,ymin,ymax,zmin,zmax

    call getcel (critere,nlelt,lstelt)

    if (ntcabs.le.ntpabs+1) then

      nlelttot=nlelt

      if (irangp.ge.0) then
        call parcpt(nlelttot)
      endif

      write(nfecra,3001) irangp,jjscal,nlelttot

    endif

    vol  = 0.0d0

    do ilelt = 1, nlelt
      vol  = vol  + volume(lstelt(ilelt))
    enddo

    if (irangp.ge.0) then
      call parsom (vol)
    endif

    if (ntcabs.eq.ntpabs+1) write(nfecra,3002) irangp,jjscal,vol

    deallocate(lstelt)

3000 format ('X >=', E12.5,' and X <=', E12.5,' and Y >=', E12.5,' and Y <=', E12.5,' and Z >=', E12.5,' and Z <=', E12.5)
3001 format ('--INPP-- Rang ',I3, ' Rejet ',I2,' Ncells ',I4)
3002 format ('--INPP-- Rang ',I3, ' Rejet ',I2,' Volume ',F10.2)

end subroutine vol_cells


! ======================================
! ================ subroutine source_vol
! ======================================

subroutine source_vol(xmin,xmax,ymin,ymax,zmin,zmax,vol,jjscal)
!
!   Remplit les conditions rejet pour chaque rejet
!
    double precision, intent(in) :: xmin,xmax
    double precision, intent(in) :: ymin,ymax
    double precision, intent(in) :: zmin,zmax
    integer,          intent(in) :: jjscal
    double precision, intent(in) :: vol

    character*240                :: critere              ! pour y ecrire le critere de selection des faces de bord
    integer iel
    double precision flucel
    integer ilelt, nlelt
    integer, allocatable, dimension(:) :: lstelt

    allocate(lstelt(ncel))

    critere=' '
    write(critere,3000) xmin,xmax,ymin,ymax,zmin,zmax

    call getcel (critere,nlelt,lstelt)

    flucel=0.0d0

    do ilelt = 1, nlelt
      iel=lstelt(ilelt)
      crvimp(iel)= 0.d0
      crvexp(iel)= 1.d0*volume(iel)/vol
      flucel = flucel+crvexp(iel)
    enddo

    if (ntcabs.le.ntpabs+1) then

      if (irangp.ge.0) then
        call parsom (flucel)
      endif

      write(nfecra,3001) irangp,jjscal,flucel

    endif

    deallocate(lstelt)

3000 format ('X >=', E12.5,' and X <=', E12.5,' and Y >=', E12.5,' and Y <=', E12.5,' and Z >=', E12.5,' and Z <=', E12.5)
3001 format ('--INPP-- Rang ',I3, ' Rejet ',I3,' Flux ',E12.5)
!----
! End
!----

end subroutine source_vol

end subroutine ustssc


