'////////////////////////////////////////////////////////////////////////////////////////
'////////////////////////////////////////////////////////////////////////////////////////

' MODULE 2
' fONCTIONS ET MACROS DE L'OUTIL

'////////////////////////////////////////////////////////////////////////////////////////
'////////////////////////////////////////////////////////////////////////////////////////


'Fonction qui va permettre de représenter les points calculés par le logiciel
Public Function debit_gaz(ByVal t As Double) As Double
Dim tabtps(1000) As Integer
Dim tabdebit(1000) As Double

Dim a, b, t1, t2, q1, q2, abc, max, choix As Double
Dim n As Integer

'C'est l'utilisateur qui va décider le nombre de point maximal qu'il met pour les données logiciel

max = Workbooks("Outil gaz.xls").Sheets("logiciel").Cells(12, 8).Value

'			/////////////////////////////////
'////////////////////max peut valoir jusqu'à 1000///////////////
'			/////////////////////////////////

'petite optimisation permettant d'éviter un surplus d'appel aux valeurs situees sur la feuille excel
For n = 9 To max
tabtps(n) = Workbooks("Outil gaz.xls").Sheets("logiciel").Cells(n, 3).Value
tabdebit(n) = Workbooks("Outil gaz.xls").Sheets("logiciel").Cells(n, 4).Value
Next n

For n = 9 To max

    a = tabtps(n)
    b = tabtps(n + 1)
    If t >= a And t <= b Then
        t1 = a
        t2 = b
        q1 = tabdebit(n)
        q2 = tabdebit(n + 1)
        
        If q1 > q2 Then
        abc = q1 * t / t
        'artifice de calcul pour garder le temps dans sa fonction pour ne pas avoir a changer la fonction suivante
        Else
        abc = q2 * t / t
        End If
        
        debit_gaz = abc
        End If
Next n
     
End Function
Public Function masse_rejet(ByVal t As Double, ByVal i As Double, ByVal pas As Double) As Double
'
'
'
'*****************************************************
' Cette fonction calcule le rejet de masse Mi pour la ième bouffée
' Elle prend en arguments le pas et le temps
'*****************************************************
'
'
'On aurait pu prendre i au lieu de temps. Mais dans ce cas, il serait plus difficile de
'calculer le rejet de masse d'une bouffée partielle. (dans la cas où le temps choisi par
'l'utilisateur n'est pas multiple du pas.)


Dim M, ti, ti1 As Double


If (i * pas) < t Then
ti = i * pas
ti1 = (i - 1) * pas

M = debit_gaz(0.5 * (ti1 + ti)) * (ti - ti1)

Else
ti1 = (i - 1) * pas
ti = t

M = debit_gaz(0.5 * (ti1 + ti)) * (ti - ti1)

End If

masse_rejet = M

End Function



'***********************************************************
'Fonction qui calcule le taux de changement
'***********************************************************

'Cette fonction prend comme argument la durée de rejet, donc indirectement
'la distance et la vitesse du vent

Public Function Taux_chgmtgaz(t_transfert As Double) As Double


X = t_transfert
y = 6 * X ^ 3 - 3 * X ^ 2 + 3 * X + 3
    If y < 100 Then
    Taux_chgmtgaz = y
    Else
    Taux_chgmtgaz = 100
    
    End If

'Cette équation a été démontrée et vérifiée dans un programme précédent



End Function





Public Function sigmax(ByVal t As Double) As Double
'Public Function sigmax(ByVal t As Double, ByVal coef_diffusion As Double) As Double

'************************************************************
'Cette fonction calcul le sigmax, c'est à dire l'écart type  en fonction du temps
'Par la formulation de Doury
'************************************************************
    
    Select Case t
        Case 0 To 240
            sigmaxd = (0.405 * t) ^ 0.859
        Case 240 To 97000
            sigmaxd = (0.135 * t) ^ 1.13
        Case 97000 To 508000
            sigmaxd = 0.463 * t
        Case 508000 To 1300000
            sigmaxd = (6.5 * t) ^ 0.824
        Case Is > 1300000
            sigmaxd = (200000 * t) ^ 0.5
    End Select
    
    'REMARQUE !
    'Le calcul est le même dans les deux cas pour sigmax et sigmay.
    
sigmax = sigmaxd

End Function





Public Function sigmaz(t As Double, coef_diffusion As Double) As Double

'************************************************************
'Cette fonction calcul le sigmaz, c'est à dire l'écart type  en fonction du temps
'Par la formulation de Doury
'************************************************************

'Les arguments de cette fonction sont le temps et le type de diffusion
'On rappelle que :
'coef = 0 équivaut à diffusion lente
'coef = 1 équivaut à diffusion normale
'Il est toujours plus simple de manipuler des chiffres binaires que des String

    '*************************
    'Diffusion faible
    '*************************
    If coef_diffusion = 0 Then
    sigmazd = (0.2 * t) ^ 0.5
    
     Else
    '*************************
    'Diffusion normale
    '*************************
    
    Select Case t
        Case 0 To 240
            sigmazd = (0.42 * t) ^ 0.814
        Case 240 To 3280
            sigmazd = t ^ 0.685
        Case Is > 3280
            sigmazd = (20 * t) ^ 0.5
    End Select
    End If

sigmaz = sigmazd

End Function





Public Function duree_transfert(ByVal X As Double, ByVal y As Double, ByVal z As Double, ByVal u As Double) As Double
'Fonction qui permet de calculer le temps de transfert


' On va traiter le cas u=0 directement dans la feuille utilisateur.
' C'est à dire que ce programme ne devrait jamais avoir le cas u=0

Dim Distance As Double
Dim t As Double

Distance = Sqr(X * X + y * y + z * z)
t = Distance / u
duree_transfert = t

End Function






Public Function concentration(ByVal X As Double, ByVal y As Double, ByVal z As Double, ByVal x0 As Double, ByVal y0 As Double, ByVal z0 As Double, ByVal diffusion As Double, ByVal alpha As Double, ByVal vent As Double, ByVal pas_bouffées As Double, ByVal t As Double) As Double

'*******************************************************
'Fonction Concentration, qui peut déterminer pour tout temps et en tout point
'la concentration de substance chimique par la méthode Multi-bouffées
'*******************************************************

' Elle prend pour arguments :
'- x0, y0, z0 : coordonnées du point source du produit
'- x,y,z : coordonnées du point où on calcule la concentration
'- diffusion : si lente ou normale
'- alpha : coefficient de reflection du sol
'- vent : Vitesse du vent supposé dans la direction x
'- pas_bouffées : La durée des bouffées
'- t : Le temps où l'on veut connaitre la concentration

Dim n, Mi, Ci, sigx, sigy, sigz, ti, INP As Double
'n représente le nombre de bouffées, la dernière bouffée compte meme si elle n'est que partielle

'			//////////////////////////////////////
'////////////////////////n peut valoir jusqu'à 1000//////////////////////////////
    			//////////////////////////////////////

        ' Cette petite condition qui suit permets de calculer l'arrondi à l'entier supérieur
        ' C'est à dire que 3.5 -> 4   2.1 -> 3   mais 3 -> 3
        If Int(t / pas_bouffées) = (t / pas_bouffées) Then
        n = t / pas_bouffées
        Else
        n = Int(t / pas_bouffées) + 1
        End If


Dim i As Integer

Ci = 0

    For i = 1 To n
    Mi = masse_rejet(t, i, pas_bouffées)
    ti = pas_bouffées * i
       
        sigx = sigmax(t - ti)
        't-ti signifie bien le temps depuis emission
        sigy = sigx
           If sigx = 0 Then
           sigx = sigmax(1)
          sigy = sigx
          End If
            'Si t-ti =0, cela arrive à la fin de chaque boucle, on prend les sigmas pour une valeur de t=1
            'pour éviter de diviser par 0
    
        sigz = sigmaz(t - ti, diffusion)
            If sigz = 0 Then
           sigz = sigmaz(1, diffusion)
            End If
            'Idem que pour les sigx et sigy, on ne peut pas avoir t =0 donc on le prend égal à 1

    INP = (Mi / ((2 * 3.14159265) ^ (3 / 2) * sigx * sigy * sigz)) * Exp(-0.5 * ((X - x0 - (vent * (t - ti))) ^ 2 / (sigx ^ 2) + (y - y0) ^ 2 / (sigy ^ 2) + (z - z0) ^ 2 / (sigz ^ 2))) + alpha * Exp(-0.5 * (z + z0) ^ 2 / (sigz ^ 2)) * Exp(-0.5 * ((X - x0 - (vent * (t - ti))) ^ 2 / (sigx ^ 2) + (y - y0) ^ 2 / (sigy ^ 2)))
  
    Ci = Ci + INP

    concentration = Ci
    
    Next i
   
End Function


'		////////////////////////////////////////////////
'////////////Fonction noyau dans laquelle tout est réalisé/////////////////////
'		////////////////////////////////////////////////

Sub CalculRimp()
 Application.EnableEvents = False
 Application.Calculation = xlCalculationManual
 Application.ScreenUpdating = False
 
 'Permet d'optimiser les calculs

'*******************************************
'Calcul de la concentration dans la fiche de résultats à partir des valeurs de la fiche tampon
'Calcul l'intégrale de c(t)dt
'
'*******************************************

' données pour le calcul de la concentration
Dim x0, y0, z0, diffusion, alpha, vent, pas_bouffées, t, pas_integration, Seuil_eq, T0, n As Double
Dim X, y, z, resultC, resultR, c_courant, c_int, t_int, Ca, Cb As Double
c_int = 0
Dim i, j As Integer

z0 = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(9, 2).Value
x0 = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(10, 2).Value
y0 = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(11, 2).Value
diffusion = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(27, 1).Value
alpha = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(24, 2).Value
vent = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(20, 2).Value
pas_bouffées = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(9, 10).Value
t = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(20, 5).Value


' Données supplémentaires pour le calcul du Rimpact
pas_integration = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(11, 10).Value
T0 = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(37, 7).Value

    'i = 0
    'On laisse le i=0 pour les cas où l'on veut un calcul pour une seule distance
    For i = 0 To 9
    'Calcul du R pour les differentes distances
    'Ici 9 représente le nombre de points où l'on veut calculer R
    'Récupération des données qui varient en fonction de la distance
            Seuil_eq = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(43, 4 + i).Value
            X = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(15, 2 + i).Value
            CTA = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(5, 14 + i).Value
            
            'Coefficeint de correction de la concentration
            coef = Workbooks("Outil gaz.xls").Sheets("Tampon").Cells(27, 12 + i).Value
            
    If X = 0 Then
            Ctot = 0
            'Si l'utilisateur n'a pas rentré de valeurs de X ou qu'il l'a mise nulle, on suppoese qu'il ne voulait
            'pas calculer de valeurs de C et R en ce point.
            'Cela permet de réduire le temps de calcul si on veut juste des valeurs en quelques points
            
            Else
            
            'Initialisation
            Ca = 0
            Ctot = 0
    
                'Calcul du nombre d'intervalles d'intégration
                If Int(t / pas_integration) = (t / pas_integration) Then
                nj = t / pas_integration
                'Cas où on a pas d'intervalle partiel mais que des intervalle de la taille de notre pas

'			/////////////////////////////////
'/////////////////////nj peut valoir jusqu'à 7500///////////////////////
'			/////////////////////////////////   


                Else
                nj = Int(t / pas_integration) + 1
                'Cas où l'on a à la fin un intervalle qui n'est pas de longueur du pas mais plus petit
    
                End If
                
    MsgBox "pre boucle temps concentration_MB"
    Dim StartTime As Double, EndTime As Double
    'Stores start time in variable "StartTime"
    StartTime = Timer
    
                    For j = 1 To nj
                    'Il s'agit ici de l'intégrale temporelle de C
                    'Pour Chaque point on va calculer la concentration à différents temps
                    t_int = pas_integration * j
                    
                        If t_int > t Then
                        t_int = t
                        End If
                        'Si le dernier intervalle est un intervalle partiel, on ne prend en compte que la partir <t
                
                                If t_int < 3600 Then
                                n = 3
                                Else
                                n = 1
                                End If
                                'La constante de Haber vaut 3 pour t inférieur à 3600s
                                'et 1 pour t> 3600s
                
                    c_courant = concentration(X, y, z, x0, y0, z0, diffusion, alpha, vent, pas_bouffées, t_int)
                  
                    a = (j - 1) * pas_integration
                    b = j * pas_integration
        
                        If b > t Then
                        b = t
                        End If
                        'b prend pour valeur max t.
                        'Idem que precedemment, intervient dans le cas d'intervalles partiels

                    Cb = c_courant
                    Cb = Cb * 1000000
                    'Conversion de Kg à mg et prise en compte de la concentration equivalente du au chgmt
        
                    Integrale = (b - a) * ((Ca) ^ n + (Cb) ^ n) * 0.5
                    'Intégration par méthode des trapèzes

                    Ctot = Ctot + Integrale
                    'On calcul une intégrale donc on sommes toutes les contributions
                    Ca = Cb
  
                    Next j
            
        End If
        
       'Stores end time in variable "EndTime"
        EndTime = Timer
        'Shows Message Box with elapsed time
       MsgBox "Execution time in seconds: " + Format$(EndTime - StartTime)
     
    'Calcul du R
    resultR = (Ctot) / ((Seuil_eq ^ n) * T0)
  Workbooks("Outil gaz.xls").Sheets("Résultats concis").Cells(16, 2 + i) = resultR
    
    resultC = concentration(X, y, z, x0, y0, z0, diffusion, alpha, vent, pas_bouffées, t) * coef
    Workbooks("Outil gaz.xls").Sheets("Résultats concis").Cells(15, 2 + i) = resultC
    
    Next i
    'Ne pas oublier de mettre ce terme en commentaire quand on met i=0 au début de la boucle

Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.Calculate

End Sub
