Module dromosense.sencity

Expand source code
import numpy as np
from dromosense.constantes import kelvin
import math

class SenCityOne:
    """
    Cette classe réalise un premier couplage du système complet et nourrit un ensemble de vecteurs numpy:
    
    Tinj_sto : température du fluide de charge à l'injection dans le stockage
    
    Tsor_sto : température du fluide de charge après transit dans le stockage
    
    Tsor_pac : température du fluide de décharge au sortir de la PAC à la réinjection dans le stockage
    
    Tinj_pac : température du fluide de décharge à l'injection dans la PAC
    
    Tsable : température du stockage/sable
    
    diff : valeur de la dérivée de la température du stockage en °C/s ou K/s
    
    Tinj_dro : température d'injection dans le dromotherme
    
    Tsor_dro : température de sortie du dromotherme
    
    On initialise Tinj_dro et Tsor_dro à 10
    
    pertes : pertes instantannées dans le stockage en W (prérequis : nécessite l'utilisation de setPertes)
    
    agenda_dro et agenda_pac : agendas de fonctionnement du dromotherme et de la PAC
    
    Pgeo : puissance géothermique à extraire pour satisfaire le besoin du bâtiment en W
    
    par exemple, avec une PAC de COP 3, la puissance géothermique à extraire vaut 2/3 du besoin total du bâtiment
    
    Pour l'utiliser :
    
    ```
    # instanciation
    # RSB = route stock bâtiment
    RSB=SenCityOne(meteo.shape[0],3600)
    # définition du système
    RSB.set(eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac)
    # injection du besoin
    RSB.Pgeo = (COP-1) * besoin_total / COP
    # définition de la fenêtre de simulation et paramétrage des agendas
    simStart = i_summerStart
    simEnd=i_summerStart+365*24
    RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
    RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)
    for i in range(simStart,simEnd):
        if RSB.Pgeo[i]==0:
            RSB.agenda_pac[i]=0    
    # bouclage
    # dromo : échangeur dromotherme selon la classe OneDModel, traversé par un débit unitaire qdro_u en m3/s
    # unitaire s'entendant par mètre linéaire selon le profil en long
    for i in range (int(simStart),int(simEnd)):
        RSB.SystemLoop(i,qdro_u,dromo)
    ```
    """
    
    def __init__(self,size,step):
        """
        size : nombre de points pour la discrétisation temporelle
        
        step : pas de temps en secondes
        """
        self.simPertes = 0
        self.step=step
        
        self.Tinj_sto=np.zeros(size)
        self.Tsor_sto=np.zeros(size)
        
        self.Tsor_pac=np.zeros(size)
        self.Tinj_pac=np.zeros(size)
        
        self.Tsable=np.zeros(size)
        self.diff=np.zeros(size)
        
        self.Tinj_dro=10*np.ones(size)
        self.Tsor_dro=10*np.ones(size)

        self.agenda_dro=np.zeros(size)
        self.agenda_pac=np.zeros(size)
        
        self.pertes=np.zeros(size)
        
        self.Pgeo=np.zeros(size)
        
    def set(self,eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac):
        """
        paramètres permettant de caractériser le système couplé
        
        eff : efficacité de l'échangeur de séparation de réseaux
        
        k : coefficient du système géothermique équipant le stockage en W/K
        
        coeff : sans unité - rapport des conductivités thermiques des fluides circulant dans l'échangeur de séparation de réseaux (dromo/stockage)
        
        msto : débit massique du fluide dans le système géothermique du stockage en kg/s
        
        cpsto : capacité thermique du fluide circulant dans le système géothermique du stockage en J/(K.kg)
        
        msable : masse de sable humide (sable sec + eau ) en kg
        
        cpsable : capacité calorifique massique du sable humide en J/(K/kg)
        
        mpac : débit massique du fluide dans la PAC en kg/s
        
        cpac : capacité calorifique massique du fluide dans la PAC en J/(K.kg)
        
        """
        
        self.eff=eff
        self.k=k
        self.coeff=coeff
        self.msto=msto
        self.cpsto=cpsto
        self.msable=msable
        self.cpsable=cpsable
        self.mpac=mpac
        self.cpac=cpac
       
        
        """
        calcul de B et C - cf notebook
        """
        
        self.B = (msto * cpsto - k/2) * coeff * eff
        
        self.C = 1 - k / (2 * mpac *cpac)
        
        print("le k du système géothermique vaut {} W/K".format(k))
        print("coeff vaut {}".format(coeff))
        print("B vaut {} W/K".format(self.B))
        print("C vaut {}".format(self.C))

    def StockLoop(self,i):
        """
        réalise une itération sur la température du stockage
        
        calcule la dérivée de la température du massif de stockage en K/s ou °C/s
        
        retourne la valeur de Tsable[i+1]
        
        4 cas distincts :
        
        1) appel d'énergie en provenance du bâtiment + dromotherme en marche
        
        2) appel d'énergie en provenance du bâtiment + dromotherme arrêté
        
        3) pas d'appel d'énergie en provenance du bâtiment + dromotherme en marche
        
        4) pas d'appel d'énergie en provenance du bâtiment + dromotherme arrêté
        
        modélise les pertes dans le stockage si la méthode setPertes a été utilisée
        """
        
        if self.simPertes==0:
            
            self.pertes[i]=0
        
        else:
    
            pertes_Laterales=self.SL_iso*(self.Tsable[i]-self.Tsous_sol(-1.125,i))
            
            pertes_Base=self.SB_iso*(self.Tsable[i]-self.Tsous_sol(-2.25,i))
            
            self.pertes[i]=self.u_th*(pertes_Laterales+ pertes_Base)
        
        pac=self.agenda_pac[i]
        dro=self.agenda_dro[i]
        if pac==1 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i]) - self.Pgeo[i]-self.pertes[i]) / (self.msable * self.cpsable)
        if pac==1 and dro==0:
            der = (- self.Pgeo[i]-self.pertes[i])/ (self.msable * self.cpsable)
        if pac==0 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i])-self.pertes[i]) / (self.msable * self.cpsable)
        if pac==0 and dro==0:
            der = -self.pertes[i]/(self.msable * self.cpsable)
            #der =0
        
        self.diff[i+1]=der
        
        ## schéma de discrétisation
        return self.Tsable[i]+self.step*der

    def SystemLoop(self,i,qdro_u,dromo):
        """
        dromo : échangeur dromotherme simulé selon la classe OneDModel
        
        qdro_u : débit unitaire en m3/s traversant le dromotherme, unitaire s'entendant par mètre linéaire selon le profil en long
        
        1) On applique StockLoop avec les résutats de l'état précédant, ce qui nous permet de calculer Tsable[i]
        
        2) On met à jour les température d'injection et de sortie de la PAC
        
        3) On réalise ensuite une itération de dromotherme selon 2 cas distincts
        
        ********************************************************************************
        cas 1: le dromotherme est en marche
        
        le fluide circule avec un débit unitaire qdro_u
          
        Si Tsor_dro <= Tsable : goto cas 2 (dromotherme à l'arrêt) + on passe la valeur de agenda_dro[i] à 0
          
        Si Tsor_dro > Tsable : alimentation du stockage

        ********************************************************************************       
        cas 2: le dromotherme est à l'arrêt - débit nul
        
        l'échangeur de séparation de réseau ne tourne pas
        
        pas de prélèvement par l'échangeur de séparation de réseau
        
        `Tinj_dro[i] = Tsor_dro[i]`
        
        pas d'évolution des températures du stockage
        
        `Tsor_sto[i]=Tsor_sto[i-1]` et `Tinj_sto[i]=Tinj_sto[i-1]`
          
        """
        # étape 1    
        self.Tsable[i]=self.StockLoop(i-1)
        
        dro=self.agenda_dro[i]
        pac=self.agenda_pac[i]
        
        y = self.Tsable[i]
    
        # étape 2
        if pac == 1 :
            self.Tinj_pac[i] = y-self.C*self.Pgeo[i]/self.k
            self.Tsor_pac[i] = self.Tinj_pac[i]-self.Pgeo[i]/(self.mpac*self.cpac)
        else:
            self.Tinj_pac[i] = self.Tinj_pac[i-1]
            self.Tsor_pac[i] = self.Tsor_pac[i-1]
    
        # étape 3
        if dro == 1:
            dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,qdro_u)
            self.Tsor_dro[i]=dromo.T[i,1,-1]-kelvin
            if self.Tsor_dro[i] < y :
                #print("step {} y vaut {} et prev vaut {}".format(i,y,Tsor_dro[i]))
                self.agenda_dro[i] = 0
                self.Tinj_dro[i] = self.Tsor_dro[i]
                self.Tinj_sto[i] = self.Tinj_sto[i-1] 
                self.Tsor_sto[i] = self.Tsor_sto[i-1]
            else :
                self.Tsor_sto[i] = ( self.k * y + self.B * self.Tsor_dro[i] ) / ( self.k + self.B)
                self.Tinj_sto[i] = self.Tsor_sto[i] + self.coeff * self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
                self.Tinj_dro[i] = self.Tsor_dro[i] - self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
            
        else:
            dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,0)
            self.Tsor_dro[i] = dromo.T[i,1,-1]-kelvin
            self.Tinj_dro[i] = self.Tsor_dro[i]
            self.Tinj_sto[i] = self.Tinj_sto[i-1] 
            self.Tsor_sto[i] = self.Tsor_sto[i-1]

        
             
    def setPertes(self,Tmoy,Tamp,lambda_sable,rho_sable,e_iso,SL_iso,SB_iso,lambda_iso):   
        """
        paramètres à prendre en compte pour la modélisation des pertes
         
        Tmoy : Température moyenne annuelle du sous-sol en °C
        
        Tamp : l'amplitude annuelle de la température i.e Tmax-Tmin en °C
        
        tf : jour correspondant à la température minimale du sous-sol (18 janvier à Chambéry) en secondes écoulées depuis le début de l'année
        
        lambda_sable : conductivité thermique du sous-sol en W/(K.m)

        rho_sable : masse volumique du sable en kg/m^3
        
        lambda_iso : conductivité thermique de l'isolant autour du stockage en W/(K.m)
        
        SL_iso : surface de l'isolant le long des parois latéraux du stockage en m2
        
        SB_iso : surface de l'isolant posée à la base du stockage en m2
        
        e_iso : épaisseur de l'isolant en m
        
        """
        
        self.simPertes=1
         
        self.tf=18*24*3600
        # w pulsation exprimée en s-1
        self.w = 2*math.pi / (8760*3600)
         
        self.Tmoy=Tmoy 
        
        self.Tamp=Tamp
        
        self.SL_iso=SL_iso
        
        self.SB_iso=SB_iso

        # a diffusivité thermique du sous-sol, en m2/s
        a = lambda_sable / (self.cpsable * rho_sable)

        self.za = math.sqrt( 2 * a / self.w )
        
        self.u_th = lambda_iso / e_iso
        
    
    def Tsous_sol(self,z,i):
        """
        La température du sous-sol est une fonction sinusoidale, obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.
        
        La pulsation w a été ajustée dans setPertes pour que la période soit une année
        
        z : profondeur en mètres
        
        i : indice temporel dans la discrétisation
            
        """
        
        factor = math.cos(self.w * (self.step * i - self.tf) + z/self.za ) * math.exp(z /self.za)
            
        return self.Tmoy - self.Tamp * factor
    
    
    
    
    
        
    
    
    

Classes

class SenCityOne (size, step)

Cette classe réalise un premier couplage du système complet et nourrit un ensemble de vecteurs numpy:

Tinj_sto : température du fluide de charge à l'injection dans le stockage

Tsor_sto : température du fluide de charge après transit dans le stockage

Tsor_pac : température du fluide de décharge au sortir de la PAC à la réinjection dans le stockage

Tinj_pac : température du fluide de décharge à l'injection dans la PAC

Tsable : température du stockage/sable

diff : valeur de la dérivée de la température du stockage en °C/s ou K/s

Tinj_dro : température d'injection dans le dromotherme

Tsor_dro : température de sortie du dromotherme

On initialise Tinj_dro et Tsor_dro à 10

pertes : pertes instantannées dans le stockage en W (prérequis : nécessite l'utilisation de setPertes)

agenda_dro et agenda_pac : agendas de fonctionnement du dromotherme et de la PAC

Pgeo : puissance géothermique à extraire pour satisfaire le besoin du bâtiment en W

par exemple, avec une PAC de COP 3, la puissance géothermique à extraire vaut 2/3 du besoin total du bâtiment

Pour l'utiliser :

# instanciation
# RSB = route stock bâtiment
RSB=SenCityOne(meteo.shape[0],3600)
# définition du système
RSB.set(eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac)
# injection du besoin
RSB.Pgeo = (COP-1) * besoin_total / COP
# définition de la fenêtre de simulation et paramétrage des agendas
simStart = i_summerStart
simEnd=i_summerStart+365*24
RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)
for i in range(simStart,simEnd):
    if RSB.Pgeo[i]==0:
        RSB.agenda_pac[i]=0    
# bouclage
# dromo : échangeur dromotherme selon la classe OneDModel, traversé par un débit unitaire qdro_u en m3/s
# unitaire s'entendant par mètre linéaire selon le profil en long
for i in range (int(simStart),int(simEnd)):
    RSB.SystemLoop(i,qdro_u,dromo)

size : nombre de points pour la discrétisation temporelle

step : pas de temps en secondes

Expand source code
class SenCityOne:
    """
    Cette classe réalise un premier couplage du système complet et nourrit un ensemble de vecteurs numpy:
    
    Tinj_sto : température du fluide de charge à l'injection dans le stockage
    
    Tsor_sto : température du fluide de charge après transit dans le stockage
    
    Tsor_pac : température du fluide de décharge au sortir de la PAC à la réinjection dans le stockage
    
    Tinj_pac : température du fluide de décharge à l'injection dans la PAC
    
    Tsable : température du stockage/sable
    
    diff : valeur de la dérivée de la température du stockage en °C/s ou K/s
    
    Tinj_dro : température d'injection dans le dromotherme
    
    Tsor_dro : température de sortie du dromotherme
    
    On initialise Tinj_dro et Tsor_dro à 10
    
    pertes : pertes instantannées dans le stockage en W (prérequis : nécessite l'utilisation de setPertes)
    
    agenda_dro et agenda_pac : agendas de fonctionnement du dromotherme et de la PAC
    
    Pgeo : puissance géothermique à extraire pour satisfaire le besoin du bâtiment en W
    
    par exemple, avec une PAC de COP 3, la puissance géothermique à extraire vaut 2/3 du besoin total du bâtiment
    
    Pour l'utiliser :
    
    ```
    # instanciation
    # RSB = route stock bâtiment
    RSB=SenCityOne(meteo.shape[0],3600)
    # définition du système
    RSB.set(eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac)
    # injection du besoin
    RSB.Pgeo = (COP-1) * besoin_total / COP
    # définition de la fenêtre de simulation et paramétrage des agendas
    simStart = i_summerStart
    simEnd=i_summerStart+365*24
    RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
    RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)
    for i in range(simStart,simEnd):
        if RSB.Pgeo[i]==0:
            RSB.agenda_pac[i]=0    
    # bouclage
    # dromo : échangeur dromotherme selon la classe OneDModel, traversé par un débit unitaire qdro_u en m3/s
    # unitaire s'entendant par mètre linéaire selon le profil en long
    for i in range (int(simStart),int(simEnd)):
        RSB.SystemLoop(i,qdro_u,dromo)
    ```
    """
    
    def __init__(self,size,step):
        """
        size : nombre de points pour la discrétisation temporelle
        
        step : pas de temps en secondes
        """
        self.simPertes = 0
        self.step=step
        
        self.Tinj_sto=np.zeros(size)
        self.Tsor_sto=np.zeros(size)
        
        self.Tsor_pac=np.zeros(size)
        self.Tinj_pac=np.zeros(size)
        
        self.Tsable=np.zeros(size)
        self.diff=np.zeros(size)
        
        self.Tinj_dro=10*np.ones(size)
        self.Tsor_dro=10*np.ones(size)

        self.agenda_dro=np.zeros(size)
        self.agenda_pac=np.zeros(size)
        
        self.pertes=np.zeros(size)
        
        self.Pgeo=np.zeros(size)
        
    def set(self,eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac):
        """
        paramètres permettant de caractériser le système couplé
        
        eff : efficacité de l'échangeur de séparation de réseaux
        
        k : coefficient du système géothermique équipant le stockage en W/K
        
        coeff : sans unité - rapport des conductivités thermiques des fluides circulant dans l'échangeur de séparation de réseaux (dromo/stockage)
        
        msto : débit massique du fluide dans le système géothermique du stockage en kg/s
        
        cpsto : capacité thermique du fluide circulant dans le système géothermique du stockage en J/(K.kg)
        
        msable : masse de sable humide (sable sec + eau ) en kg
        
        cpsable : capacité calorifique massique du sable humide en J/(K/kg)
        
        mpac : débit massique du fluide dans la PAC en kg/s
        
        cpac : capacité calorifique massique du fluide dans la PAC en J/(K.kg)
        
        """
        
        self.eff=eff
        self.k=k
        self.coeff=coeff
        self.msto=msto
        self.cpsto=cpsto
        self.msable=msable
        self.cpsable=cpsable
        self.mpac=mpac
        self.cpac=cpac
       
        
        """
        calcul de B et C - cf notebook
        """
        
        self.B = (msto * cpsto - k/2) * coeff * eff
        
        self.C = 1 - k / (2 * mpac *cpac)
        
        print("le k du système géothermique vaut {} W/K".format(k))
        print("coeff vaut {}".format(coeff))
        print("B vaut {} W/K".format(self.B))
        print("C vaut {}".format(self.C))

    def StockLoop(self,i):
        """
        réalise une itération sur la température du stockage
        
        calcule la dérivée de la température du massif de stockage en K/s ou °C/s
        
        retourne la valeur de Tsable[i+1]
        
        4 cas distincts :
        
        1) appel d'énergie en provenance du bâtiment + dromotherme en marche
        
        2) appel d'énergie en provenance du bâtiment + dromotherme arrêté
        
        3) pas d'appel d'énergie en provenance du bâtiment + dromotherme en marche
        
        4) pas d'appel d'énergie en provenance du bâtiment + dromotherme arrêté
        
        modélise les pertes dans le stockage si la méthode setPertes a été utilisée
        """
        
        if self.simPertes==0:
            
            self.pertes[i]=0
        
        else:
    
            pertes_Laterales=self.SL_iso*(self.Tsable[i]-self.Tsous_sol(-1.125,i))
            
            pertes_Base=self.SB_iso*(self.Tsable[i]-self.Tsous_sol(-2.25,i))
            
            self.pertes[i]=self.u_th*(pertes_Laterales+ pertes_Base)
        
        pac=self.agenda_pac[i]
        dro=self.agenda_dro[i]
        if pac==1 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i]) - self.Pgeo[i]-self.pertes[i]) / (self.msable * self.cpsable)
        if pac==1 and dro==0:
            der = (- self.Pgeo[i]-self.pertes[i])/ (self.msable * self.cpsable)
        if pac==0 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i])-self.pertes[i]) / (self.msable * self.cpsable)
        if pac==0 and dro==0:
            der = -self.pertes[i]/(self.msable * self.cpsable)
            #der =0
        
        self.diff[i+1]=der
        
        ## schéma de discrétisation
        return self.Tsable[i]+self.step*der

    def SystemLoop(self,i,qdro_u,dromo):
        """
        dromo : échangeur dromotherme simulé selon la classe OneDModel
        
        qdro_u : débit unitaire en m3/s traversant le dromotherme, unitaire s'entendant par mètre linéaire selon le profil en long
        
        1) On applique StockLoop avec les résutats de l'état précédant, ce qui nous permet de calculer Tsable[i]
        
        2) On met à jour les température d'injection et de sortie de la PAC
        
        3) On réalise ensuite une itération de dromotherme selon 2 cas distincts
        
        ********************************************************************************
        cas 1: le dromotherme est en marche
        
        le fluide circule avec un débit unitaire qdro_u
          
        Si Tsor_dro <= Tsable : goto cas 2 (dromotherme à l'arrêt) + on passe la valeur de agenda_dro[i] à 0
          
        Si Tsor_dro > Tsable : alimentation du stockage

        ********************************************************************************       
        cas 2: le dromotherme est à l'arrêt - débit nul
        
        l'échangeur de séparation de réseau ne tourne pas
        
        pas de prélèvement par l'échangeur de séparation de réseau
        
        `Tinj_dro[i] = Tsor_dro[i]`
        
        pas d'évolution des températures du stockage
        
        `Tsor_sto[i]=Tsor_sto[i-1]` et `Tinj_sto[i]=Tinj_sto[i-1]`
          
        """
        # étape 1    
        self.Tsable[i]=self.StockLoop(i-1)
        
        dro=self.agenda_dro[i]
        pac=self.agenda_pac[i]
        
        y = self.Tsable[i]
    
        # étape 2
        if pac == 1 :
            self.Tinj_pac[i] = y-self.C*self.Pgeo[i]/self.k
            self.Tsor_pac[i] = self.Tinj_pac[i]-self.Pgeo[i]/(self.mpac*self.cpac)
        else:
            self.Tinj_pac[i] = self.Tinj_pac[i-1]
            self.Tsor_pac[i] = self.Tsor_pac[i-1]
    
        # étape 3
        if dro == 1:
            dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,qdro_u)
            self.Tsor_dro[i]=dromo.T[i,1,-1]-kelvin
            if self.Tsor_dro[i] < y :
                #print("step {} y vaut {} et prev vaut {}".format(i,y,Tsor_dro[i]))
                self.agenda_dro[i] = 0
                self.Tinj_dro[i] = self.Tsor_dro[i]
                self.Tinj_sto[i] = self.Tinj_sto[i-1] 
                self.Tsor_sto[i] = self.Tsor_sto[i-1]
            else :
                self.Tsor_sto[i] = ( self.k * y + self.B * self.Tsor_dro[i] ) / ( self.k + self.B)
                self.Tinj_sto[i] = self.Tsor_sto[i] + self.coeff * self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
                self.Tinj_dro[i] = self.Tsor_dro[i] - self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
            
        else:
            dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,0)
            self.Tsor_dro[i] = dromo.T[i,1,-1]-kelvin
            self.Tinj_dro[i] = self.Tsor_dro[i]
            self.Tinj_sto[i] = self.Tinj_sto[i-1] 
            self.Tsor_sto[i] = self.Tsor_sto[i-1]

        
             
    def setPertes(self,Tmoy,Tamp,lambda_sable,rho_sable,e_iso,SL_iso,SB_iso,lambda_iso):   
        """
        paramètres à prendre en compte pour la modélisation des pertes
         
        Tmoy : Température moyenne annuelle du sous-sol en °C
        
        Tamp : l'amplitude annuelle de la température i.e Tmax-Tmin en °C
        
        tf : jour correspondant à la température minimale du sous-sol (18 janvier à Chambéry) en secondes écoulées depuis le début de l'année
        
        lambda_sable : conductivité thermique du sous-sol en W/(K.m)

        rho_sable : masse volumique du sable en kg/m^3
        
        lambda_iso : conductivité thermique de l'isolant autour du stockage en W/(K.m)
        
        SL_iso : surface de l'isolant le long des parois latéraux du stockage en m2
        
        SB_iso : surface de l'isolant posée à la base du stockage en m2
        
        e_iso : épaisseur de l'isolant en m
        
        """
        
        self.simPertes=1
         
        self.tf=18*24*3600
        # w pulsation exprimée en s-1
        self.w = 2*math.pi / (8760*3600)
         
        self.Tmoy=Tmoy 
        
        self.Tamp=Tamp
        
        self.SL_iso=SL_iso
        
        self.SB_iso=SB_iso

        # a diffusivité thermique du sous-sol, en m2/s
        a = lambda_sable / (self.cpsable * rho_sable)

        self.za = math.sqrt( 2 * a / self.w )
        
        self.u_th = lambda_iso / e_iso
        
    
    def Tsous_sol(self,z,i):
        """
        La température du sous-sol est une fonction sinusoidale, obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.
        
        La pulsation w a été ajustée dans setPertes pour que la période soit une année
        
        z : profondeur en mètres
        
        i : indice temporel dans la discrétisation
            
        """
        
        factor = math.cos(self.w * (self.step * i - self.tf) + z/self.za ) * math.exp(z /self.za)
            
        return self.Tmoy - self.Tamp * factor

Methods

def StockLoop(self, i)

réalise une itération sur la température du stockage

calcule la dérivée de la température du massif de stockage en K/s ou °C/s

retourne la valeur de Tsable[i+1]

4 cas distincts :

1) appel d'énergie en provenance du bâtiment + dromotherme en marche

2) appel d'énergie en provenance du bâtiment + dromotherme arrêté

3) pas d'appel d'énergie en provenance du bâtiment + dromotherme en marche

4) pas d'appel d'énergie en provenance du bâtiment + dromotherme arrêté

modélise les pertes dans le stockage si la méthode setPertes a été utilisée

Expand source code
def StockLoop(self,i):
    """
    réalise une itération sur la température du stockage
    
    calcule la dérivée de la température du massif de stockage en K/s ou °C/s
    
    retourne la valeur de Tsable[i+1]
    
    4 cas distincts :
    
    1) appel d'énergie en provenance du bâtiment + dromotherme en marche
    
    2) appel d'énergie en provenance du bâtiment + dromotherme arrêté
    
    3) pas d'appel d'énergie en provenance du bâtiment + dromotherme en marche
    
    4) pas d'appel d'énergie en provenance du bâtiment + dromotherme arrêté
    
    modélise les pertes dans le stockage si la méthode setPertes a été utilisée
    """
    
    if self.simPertes==0:
        
        self.pertes[i]=0
    
    else:

        pertes_Laterales=self.SL_iso*(self.Tsable[i]-self.Tsous_sol(-1.125,i))
        
        pertes_Base=self.SB_iso*(self.Tsable[i]-self.Tsous_sol(-2.25,i))
        
        self.pertes[i]=self.u_th*(pertes_Laterales+ pertes_Base)
    
    pac=self.agenda_pac[i]
    dro=self.agenda_dro[i]
    if pac==1 and dro==1:
        der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i]) - self.Pgeo[i]-self.pertes[i]) / (self.msable * self.cpsable)
    if pac==1 and dro==0:
        der = (- self.Pgeo[i]-self.pertes[i])/ (self.msable * self.cpsable)
    if pac==0 and dro==1:
        der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i])-self.pertes[i]) / (self.msable * self.cpsable)
    if pac==0 and dro==0:
        der = -self.pertes[i]/(self.msable * self.cpsable)
        #der =0
    
    self.diff[i+1]=der
    
    ## schéma de discrétisation
    return self.Tsable[i]+self.step*der
def SystemLoop(self, i, qdro_u, dromo)

dromo : échangeur dromotherme simulé selon la classe OneDModel

qdro_u : débit unitaire en m3/s traversant le dromotherme, unitaire s'entendant par mètre linéaire selon le profil en long

1) On applique StockLoop avec les résutats de l'état précédant, ce qui nous permet de calculer Tsable[i]

2) On met à jour les température d'injection et de sortie de la PAC

3) On réalise ensuite une itération de dromotherme selon 2 cas distincts


cas 1: le dromotherme est en marche

le fluide circule avec un débit unitaire qdro_u

Si Tsor_dro <= Tsable : goto cas 2 (dromotherme à l'arrêt) + on passe la valeur de agenda_dro[i] à 0

Si Tsor_dro > Tsable : alimentation du stockage


cas 2: le dromotherme est à l'arrêt - débit nul

l'échangeur de séparation de réseau ne tourne pas

pas de prélèvement par l'échangeur de séparation de réseau

Tinj_dro[i] = Tsor_dro[i]

pas d'évolution des températures du stockage

Tsor_sto[i]=Tsor_sto[i-1] et Tinj_sto[i]=Tinj_sto[i-1]

Expand source code
def SystemLoop(self,i,qdro_u,dromo):
    """
    dromo : échangeur dromotherme simulé selon la classe OneDModel
    
    qdro_u : débit unitaire en m3/s traversant le dromotherme, unitaire s'entendant par mètre linéaire selon le profil en long
    
    1) On applique StockLoop avec les résutats de l'état précédant, ce qui nous permet de calculer Tsable[i]
    
    2) On met à jour les température d'injection et de sortie de la PAC
    
    3) On réalise ensuite une itération de dromotherme selon 2 cas distincts
    
    ********************************************************************************
    cas 1: le dromotherme est en marche
    
    le fluide circule avec un débit unitaire qdro_u
      
    Si Tsor_dro <= Tsable : goto cas 2 (dromotherme à l'arrêt) + on passe la valeur de agenda_dro[i] à 0
      
    Si Tsor_dro > Tsable : alimentation du stockage

    ********************************************************************************       
    cas 2: le dromotherme est à l'arrêt - débit nul
    
    l'échangeur de séparation de réseau ne tourne pas
    
    pas de prélèvement par l'échangeur de séparation de réseau
    
    `Tinj_dro[i] = Tsor_dro[i]`
    
    pas d'évolution des températures du stockage
    
    `Tsor_sto[i]=Tsor_sto[i-1]` et `Tinj_sto[i]=Tinj_sto[i-1]`
      
    """
    # étape 1    
    self.Tsable[i]=self.StockLoop(i-1)
    
    dro=self.agenda_dro[i]
    pac=self.agenda_pac[i]
    
    y = self.Tsable[i]

    # étape 2
    if pac == 1 :
        self.Tinj_pac[i] = y-self.C*self.Pgeo[i]/self.k
        self.Tsor_pac[i] = self.Tinj_pac[i]-self.Pgeo[i]/(self.mpac*self.cpac)
    else:
        self.Tinj_pac[i] = self.Tinj_pac[i-1]
        self.Tsor_pac[i] = self.Tsor_pac[i-1]

    # étape 3
    if dro == 1:
        dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,qdro_u)
        self.Tsor_dro[i]=dromo.T[i,1,-1]-kelvin
        if self.Tsor_dro[i] < y :
            #print("step {} y vaut {} et prev vaut {}".format(i,y,Tsor_dro[i]))
            self.agenda_dro[i] = 0
            self.Tinj_dro[i] = self.Tsor_dro[i]
            self.Tinj_sto[i] = self.Tinj_sto[i-1] 
            self.Tsor_sto[i] = self.Tsor_sto[i-1]
        else :
            self.Tsor_sto[i] = ( self.k * y + self.B * self.Tsor_dro[i] ) / ( self.k + self.B)
            self.Tinj_sto[i] = self.Tsor_sto[i] + self.coeff * self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
            self.Tinj_dro[i] = self.Tsor_dro[i] - self.eff * (self.Tsor_dro[i] - self.Tsor_sto[i])
        
    else:
        dromo.iterate(i,self.Tinj_dro[i-1]+kelvin,0)
        self.Tsor_dro[i] = dromo.T[i,1,-1]-kelvin
        self.Tinj_dro[i] = self.Tsor_dro[i]
        self.Tinj_sto[i] = self.Tinj_sto[i-1] 
        self.Tsor_sto[i] = self.Tsor_sto[i-1]
def Tsous_sol(self, z, i)

La température du sous-sol est une fonction sinusoidale, obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.

La pulsation w a été ajustée dans setPertes pour que la période soit une année

z : profondeur en mètres

i : indice temporel dans la discrétisation

Expand source code
def Tsous_sol(self,z,i):
    """
    La température du sous-sol est une fonction sinusoidale, obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.
    
    La pulsation w a été ajustée dans setPertes pour que la période soit une année
    
    z : profondeur en mètres
    
    i : indice temporel dans la discrétisation
        
    """
    
    factor = math.cos(self.w * (self.step * i - self.tf) + z/self.za ) * math.exp(z /self.za)
        
    return self.Tmoy - self.Tamp * factor
def set(self, eff, k, coeff, msto, cpsto, msable, cpsable, mpac, cpac)

paramètres permettant de caractériser le système couplé

eff : efficacité de l'échangeur de séparation de réseaux

k : coefficient du système géothermique équipant le stockage en W/K

coeff : sans unité - rapport des conductivités thermiques des fluides circulant dans l'échangeur de séparation de réseaux (dromo/stockage)

msto : débit massique du fluide dans le système géothermique du stockage en kg/s

cpsto : capacité thermique du fluide circulant dans le système géothermique du stockage en J/(K.kg)

msable : masse de sable humide (sable sec + eau ) en kg

cpsable : capacité calorifique massique du sable humide en J/(K/kg)

mpac : débit massique du fluide dans la PAC en kg/s

cpac : capacité calorifique massique du fluide dans la PAC en J/(K.kg)

Expand source code
def set(self,eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac):
    """
    paramètres permettant de caractériser le système couplé
    
    eff : efficacité de l'échangeur de séparation de réseaux
    
    k : coefficient du système géothermique équipant le stockage en W/K
    
    coeff : sans unité - rapport des conductivités thermiques des fluides circulant dans l'échangeur de séparation de réseaux (dromo/stockage)
    
    msto : débit massique du fluide dans le système géothermique du stockage en kg/s
    
    cpsto : capacité thermique du fluide circulant dans le système géothermique du stockage en J/(K.kg)
    
    msable : masse de sable humide (sable sec + eau ) en kg
    
    cpsable : capacité calorifique massique du sable humide en J/(K/kg)
    
    mpac : débit massique du fluide dans la PAC en kg/s
    
    cpac : capacité calorifique massique du fluide dans la PAC en J/(K.kg)
    
    """
    
    self.eff=eff
    self.k=k
    self.coeff=coeff
    self.msto=msto
    self.cpsto=cpsto
    self.msable=msable
    self.cpsable=cpsable
    self.mpac=mpac
    self.cpac=cpac
   
    
    """
    calcul de B et C - cf notebook
    """
    
    self.B = (msto * cpsto - k/2) * coeff * eff
    
    self.C = 1 - k / (2 * mpac *cpac)
    
    print("le k du système géothermique vaut {} W/K".format(k))
    print("coeff vaut {}".format(coeff))
    print("B vaut {} W/K".format(self.B))
    print("C vaut {}".format(self.C))
def setPertes(self, Tmoy, Tamp, lambda_sable, rho_sable, e_iso, SL_iso, SB_iso, lambda_iso)

paramètres à prendre en compte pour la modélisation des pertes

Tmoy : Température moyenne annuelle du sous-sol en °C

Tamp : l'amplitude annuelle de la température i.e Tmax-Tmin en °C

tf : jour correspondant à la température minimale du sous-sol (18 janvier à Chambéry) en secondes écoulées depuis le début de l'année

lambda_sable : conductivité thermique du sous-sol en W/(K.m)

rho_sable : masse volumique du sable en kg/m^3

lambda_iso : conductivité thermique de l'isolant autour du stockage en W/(K.m)

SL_iso : surface de l'isolant le long des parois latéraux du stockage en m2

SB_iso : surface de l'isolant posée à la base du stockage en m2

e_iso : épaisseur de l'isolant en m

Expand source code
def setPertes(self,Tmoy,Tamp,lambda_sable,rho_sable,e_iso,SL_iso,SB_iso,lambda_iso):   
    """
    paramètres à prendre en compte pour la modélisation des pertes
     
    Tmoy : Température moyenne annuelle du sous-sol en °C
    
    Tamp : l'amplitude annuelle de la température i.e Tmax-Tmin en °C
    
    tf : jour correspondant à la température minimale du sous-sol (18 janvier à Chambéry) en secondes écoulées depuis le début de l'année
    
    lambda_sable : conductivité thermique du sous-sol en W/(K.m)

    rho_sable : masse volumique du sable en kg/m^3
    
    lambda_iso : conductivité thermique de l'isolant autour du stockage en W/(K.m)
    
    SL_iso : surface de l'isolant le long des parois latéraux du stockage en m2
    
    SB_iso : surface de l'isolant posée à la base du stockage en m2
    
    e_iso : épaisseur de l'isolant en m
    
    """
    
    self.simPertes=1
     
    self.tf=18*24*3600
    # w pulsation exprimée en s-1
    self.w = 2*math.pi / (8760*3600)
     
    self.Tmoy=Tmoy 
    
    self.Tamp=Tamp
    
    self.SL_iso=SL_iso
    
    self.SB_iso=SB_iso

    # a diffusivité thermique du sous-sol, en m2/s
    a = lambda_sable / (self.cpsable * rho_sable)

    self.za = math.sqrt( 2 * a / self.w )
    
    self.u_th = lambda_iso / e_iso