seviprince / dromotherm

Code Python
MIT License
0 stars 1 forks source link

Prise en compte des pertes par conduction dans le stockage #15

Open seviprince opened 3 years ago

seviprince commented 3 years ago

Bonjour, J'ai fait de nouvelles simulations avec la prise en compte des pertes conductives. En effet, le premier cas de figure selon lequel on fait marcher le dromotherm sans consommation aucune revient à recharger indéfiniment le stockage. Mais nous devons prendre en compte les pertes par conduction pour que l'énergie emmagasinée soit "évacuée". pertes.pdf

J'ai donc ajouté le flux perdu par conduction à l'équation diff de Tsable dans le module sencity ( j'ai pas encore "commité " la version) Quand je fais

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é
        """
        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.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))) / (self.msable * self.cpsable)
        if pac==1 and dro==0:
            der = (- self.Pgeo[i]-(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso)) )/ (self.msable * self.cpsable)
        if pac==0 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i])-(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))) / (self.msable * self.cpsable)
        if pac==0 and dro==0:
            #der = -(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))
            der =0

        self.diff[i+1]=der

        ## schéma de discrétisation
        return self.Tsable[i]+self.step*der

J'obtiens pertes

Mais si je fais:

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é
        """
        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.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))) / (self.msable * self.cpsable)
        if pac==1 and dro==0:
            der = (- self.Pgeo[i]-(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso)) )/ (self.msable * self.cpsable)
        if pac==0 and dro==1:
            der = (self.msto * self.cpsto * (self.Tinj_sto[i] - self.Tsor_sto[i])-(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))) / (self.msable * self.cpsable)
        **if pac==0 and dro==0:
            der = -(self.Tsable[i]-Tsous_sol(1, i))/(e_iso/(lamda_iso*S_iso))
            #der =0**

        self.diff[i+1]=der

        ## schéma de discrétisation
        return self.Tsable[i]+self.step*der

j’obtiens un résultat très désordonné

pertes1

La différence provient du dernier cas if dro==0 and pac==0

Ma préoccupation est la suivante: Si le dromotherm et la pac sont à l'arrêt, devrait-on prendre en compte les pertes conductives??

alexandrecuer commented 3 years ago

pour la lisibilité, pourquoi ne pas calculer les pertes d'abord et les stocker dans une variable tu aurais pu faire :

pertes[i] = lamda_iso * S_iso * (self.Tsable[i]-Tsous_sol(1, i)) / e_iso

Il faut que le code tienne sur un écran, pas sur 2 ou 3, je n'arrive pas à lire.... donc il faut passer par des variables intermédiaires, structurer les choses : coder ce n'est pas utiliser une calculatrice

si j'avais éclaté les chose avec 4 cas, c'était juste pour le code soit lisible

Quel est l'ordre de grandeur des pertes ?

comment as-tu codé ta fonction Tsous_sol(z, i) ?

seviprince commented 3 years ago

Bonjour, Je vous enverrai le code mieux structuré. Les détails sur la température du sous-sol sont expliqués à la page 21 de la thèse de Xavier Moch qui a travaillé avec les données de Chambéry.

alexandrecuer commented 3 years ago

Tu peux poster ta fonction sur cette issue....est-ce que tu as mis step dedans?

seviprince commented 3 years ago

Bonjour, J'obtiens quelque chose de plus potable et mieux structurée avec des résultats plus convaincants:

Dans la classe SenCityOne, je fais:

def Tsous_sol(self,z,t):

        """
        La temérature du sous-sol est une fonction sinusoidale de période=une année et de pulsation w ,obtenue à partir de l'équation 

        de la propagation de la chaleur dans le sous-sol.

        """

        """
        Calcul de la difusivité thermique du sous-sol notée a et de la pulsation w

        """

        self.a=self.lambda_sable/(self.cpsable*self.rho_sable)

        self.w=2*math.pi/(8760*self.step)

        self.tf=18*24*self.step

        self.z=z

        return self.Tmoy-self.Tamp*math.cos(self.w*(t*self.step-self.tf)+self.z*math.sqrt(self.w/(2*self.a)))*np.exp(self.z*math.sqrt(self.w/(2*self.a)))
def pertes(self,i):
        return (self.Tsable[i]-self.Tsous_sol(1,i))/( self.e_iso/(self.lamba_iso* self.S_iso))
 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é
        """
        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)

        self.diff[i+1]=der

        ## schéma de discrétisation
        return self.Tsable[i]+self.step*der

Et je prends le soin de rajouter à def.set(....):

 def set(self,eff,k,coeff,msto,cpsto,msable,cpsable,mpac,cpac,Tmoy,Tamp,lambda_sable,rho_sable,e_iso,S_iso,lambda_iso):
        """
        Tmoy= Température moyenne annuelle du sous-sol

        Tamp= l'amplitude annulle de la température i.e Tmax-Tmin

        tf=Le jour correspondant à la température minimale du sous-sol ( le 18 janvier à chambéry)

        lambda_sable= conductivité thermique du sous-sol

        lambda_iso= conductivité thermique de l'isolant autour du stockage

        S_iso= surface de l'isolant'

        e_iso= épaisseur de l'isolant

        """
        self.Tmoy=Tmoy 
        self.Tamp=Tamp
        self.lambda_sable=lambda_sable
        self.rho_sable=rho_sable
        self.lamba_iso=lambda_iso
        self.e_iso=e_iso
        self.S_iso=S_iso

Dans couplage2.py je fais

Tmoy=11
Tamp=9.1
lambda_sable=1.7
rho_sable=1700
e_iso=0.02
S_iso=48
lambda_iso=0.038

RSB.set(eff,k,coeff,msto,cpsto,m_sable,Cp_sable,mpac,cpac,Tmoy,Tamp,lambda_sable,rho_sable,e_iso,S_iso,lambda_iso)

Et j'obtiens pour le premier cas: Recharge du stock durant l'été sans aucune consommation; pertes2

A partir de ce graphe, et sous réserve de vérification des données numériques, on constate que la température du stock ne peut dépasser 20°C si on tient en compte les pertes par conduction.

seviprince commented 3 years ago

Le graphique précédent est pour un isolant d'épaisseur 2cm (trop faible) Pour un isolant d'épaisseur 20 cm, on obtient: pertes3

Moins de pertes et température du stockage plus élevée ( 30°C ) environs

alexandrecuer commented 3 years ago

Jolie tentative de structuration, c'est bien mais il va falloir changer bien des choses....

1) Il serait intéressant que l'on puisse simuler avec ou sans pertes, histoire de pouvoir retrouver les résultats précédents....on ne va pas faire évoluer le code en se privant de celà...

2) Le mot clé self, que l'on utilise dans les classes pour faire référence à l'objet en cours ne sert que pour faire référence aux variables et méthodes destinées à être persistantes.. les variables locales n'ont pas à être précédées de self

Donc ta fonction sous-sol pourrait être :

a=self.lambda_sable/(self.cpsable*self.rho_sable)
w=2*math.pi/(8760*self.step)
tf=18*24*self.step
return self.Tmoy-self.Tamp*math.cos(w*(t*self.step-tf)+z*math.sqrt(w/(2*a)))*np.exp(z*math.sqrt(w/(2*a)))

quelques remarques :

Est-ce que tu a validé ta fonction Tsous_sol ?

As-tu remarqué que je n'injectes dans les classes que des méthodes validées sur des exemples. ?

As-tu construit un exemple simple te permettant de tracer Tsous_sol sur l'année ? hors de la classe je veux dire....

je lis dans la thèse Mohr que z dans la formule est exprimée négativement, toi tu l'exprimes positivement...je supposes que celà a un impact....

donc j'ai fait l'exercice en créant un exemple simple :

import math
import numpy as np
import matplotlib.pyplot as plt

# pas de temps en secondes
step=3600
npy=24*365
# conductivité en W/(K.m)
lambda_sable=1.7
# masse volumique du sable en kg/m3
rho_sable=1700
# capacité calorifique massique du sable humide en J/Kg.K
cpsable=1470.0 

# températures en degrés
Tmoy=11
Tamp=9.1

# a diffusivité thermique du sous-sol
# a est exprimée en m2/s
a = lambda_sable/(cpsable*rho_sable)
# w pulsation exprimée en 1/s
w = 2*math.pi/(npy*step)

# temps correspondant au point le plus froid de l'année
tf = 18*24*step

titre="diffusivité : {} m2/s - pulsation : {} s-1".format("%.2E" % a,"%.2E" % w)

# profondeur équivalente liée à a ??
za = math.sqrt( 2 * a / w )

def Tsous_sol(z,i):

    """
    La température du sous-sol est une fonction sinusoidale :
    - de période = une année
    - de pulsation w ,obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.

    z : profondeur en mètres

    i : indice temporel dans la discrétisation

    """

    factor = math.cos(w * (step * i - tf) + z/za ) * math.exp(z / za)

    return Tmoy - Tamp * factor 

pertes=np.zeros(npy)
z=-1
for i in range(pertes.shape[0]):
    pertes[i]=Tsous_sol(z,i)

plt.subplot(111)
plt.title("température du sous-sol à {} m de profondeur\n{}".format(z,titre))
plt.xlabel("temps - une unité = {} s".format(step))
plt.plot(pertes)
plt.show()

j'obtiens les graphes suivants, avec z=-1 :

image

avec z=1 : image

il semble donc qu'il faille prendre z négatif

ceci dit ton code est à reprendre et je pense qu'il va falloir que tu fasses des devoirs de vacances en python :-) voilà ce que j'ai trouvé et il y a un certificat de réussite à la clé : https://openclassrooms.com/fr/courses/235344-apprenez-a-programmer-en-python

seviprince commented 3 years ago

Bonjour monsieur, Merci pour vos remarques. Effectivement, monsieur Benoit et moi étions entrain de faire des tests de validation de la température du sous-sol. Et bien,c'est vrai on devrait prendre le z négativement.

seviprince commented 3 years ago

Voici une représentation des pertes Perte

alexandrecuer commented 3 years ago

Et je prends le soin de rajouter à def.set(....):

set est déjà bien chargée en variable par contre rajoute un booléen dans set pour indiquer s'il a simulation des pertes ou pas par exemple en rajoutant une ligne avec initialisation à 0 :

self.simPertes=0

je pense qu'il faut que tu fasses une méthode setPertes pour fixer les constantes liées aux pertes... dans cette méthode, outre le calcul de toutes les constantes, tu commenceras par :

self.simPertes=1
self.pertes=np.zeros(self.size)

et dans le init, tu rajoutes, pour pouvoir créer des vecteurs numpy hors de init :

self.size=size

Enfin, pas sûr qu'il y ait besoin d'une méthode pertes pour l'itération...le calcul est quant même très simple....

quant tu fais :

return (self.Tsable[i]-self.Tsous_sol(1,i))/( self.e_iso/(self.lamba_iso* self.S_iso))

je trouves mieux de faire :

return self.lamba_iso * self.S_iso * (self.Tsable[i]-self.Tsous_sol(1,i)) / self.e_iso

ainsi on économise des parenthèses et on est plus lisible

alexandrecuer commented 3 years ago

Voici une représentation des pertes Perte

des pertes négatives ?

seviprince commented 3 years ago

Oui Elles deviennent négatives quand le sous sol devient plus chaud que le stockage

alexandrecuer commented 3 years ago

Ok et au début de l'été notre stock est plus froid que le sous-sol....ca tient le route....Par contre on a initialisé le stock a zéro degré par construction mais sur le démonstrateur les températures de sous-sol et de stock seront égales à l'initialisation du processus....ce n'est qu'au bout d'un an qu'on aura un vrai découplage des températures de stock et de sous-solEnvoyé depuis mon smartphone Samsung Galaxy.

-------- Message d'origine -------- De : "> seviprince (par Internet, dépôt noreply@github.com)" notifications@github.com Date : 20/07/2020 12:05 (GMT+01:00) À : seviprince/dromotherm dromotherm@noreply.github.com Cc : Alexandre CUER alexandre.cuer@cerema.fr, Comment comment@noreply.github.com Objet : Re: [seviprince/dromotherm] Prise en compte des pertes par conduction dans le stockage (#15)

Oui

Elles deviennent négatives quand le sous sol devient plus chaud que le stockage

--

You are receiving this because you commented.

Reply to this email directly or view it on GitHub:

https://github.com/seviprince/dromotherm/issues/15#issuecomment-660933502

seviprince commented 3 years ago

temp

seviprince commented 3 years ago

Ok et au début de l'été notre stock est plus froid que le sous-sol....ca tient le route....Par contre on a initialisé le stock a zéro degré par construction mais sur le démonstrateur les températures de sous-sol et de stock seront égales à l'initialisation du processus....ce n'est qu'au bout d'un an qu'on aura un vrai découplage des températures de stock et de sous-solEnvoyé depuis mon smartphone Samsung Galaxy. -------- Message d'origine -------- De : "> seviprince (par Internet, dépôt noreply@github.com)" notifications@github.com Date : 20/07/2020 12:05 (GMT+01:00) À : seviprince/dromotherm dromotherm@noreply.github.com Cc : Alexandre CUER alexandre.cuer@cerema.fr, Comment comment@noreply.github.com Objet : Re: [seviprince/dromotherm] Prise en compte des pertes par conduction dans le stockage (#15) Oui Elles deviennent négatives quand le sous sol devient plus chaud que le stockage -- You are receiving this because you commented. Reply to this email directly or view it on GitHub: #15 (comment)

Donc je dois tracer les deux températures sur deux années et observer ce qui se passe à la deuxième année

seviprince commented 3 years ago

temp2

Tsous sol sur graphique 3

alexandrecuer commented 3 years ago

comment se fait-il que le besoin soit stipulé égal à 0 Kwh dans la légende ? alors qu'il ne l'est pas sur le graphique ? décris moi mieux ce que tu cherches à faire

seviprince commented 3 years ago

temp2

Tsous sol sur graphique 3

Dromotherm toute l'année sans consommation aucune juste pour voir les valeurs maxi de Tsable en été et en hiver. Je ne m'intéresse pas au graphe du besoin

seviprince commented 3 years ago

En fait je veux tester un autre usecase semblable au usecase 0 mais sur toute l'année

Voici ce que je fais


if usecase == 5:
    # ECS only pendant l'année
    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)
    heating = "ECS" 
seviprince commented 3 years ago

En ligne de commande

python couplage2.py False 5
alexandrecuer commented 3 years ago

OK, donc tu es sur un nouveau cas d'usage, dérivé du cas 2

if usecase == 4:
    # simulation annuelle
    simStart = i_summerStart
    simEnd=i_summerStart+365*24
    RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
    RSB.agenda_pac[simStart:simEnd]=np.zeros(simEnd-simStart)
    heating="Pas de besoin"

je sens que tu vas vouloir passer sur une simulation à 2 ans...... il faudrait faire un fichier couplage3.py qu'en dis-tu, plutôt que de bricoler sur couplage2.py

as-tu stabilisé le code vers quelque chose qui intègre mes remarques ou est-ce que tu veux que je le fasse ? je peux m'y atteler si tu veux continuer à chercher....

seviprince commented 3 years ago

mais je n'obtiens pas ce que je voulais usecase5

alexandrecuer commented 3 years ago

RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)

pas ones mais zeros ?

seviprince commented 3 years ago

OK, donc tu es sur un nouveau cas d'usage, dérivé du cas 2

if usecase == 4:
    # simulation annuelle
    simStart = i_summerStart
    simEnd=i_summerStart+365*24
    RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
    RSB.agenda_pac[simStart:simEnd]=np.zeros(simEnd-simStart)
   heating="Pas de besoin"

je sens que tu vas vouloir passer sur une simulation à 2 ans...... il faudrait faire un fichier couplage3.py qu'en dis-tu, plutôt que de bricoler sur couplage2.py

as-tu stabilisé le code vers quelque chose qui intègre mes remarques ou est-ce que tu veux que je le fasse ? je peux m'y atteler si tu veux continuer à chercher....

Je suis dans un fichier couplage3.py depuis hier. Je vais intégrer vos remarques tout à l'heure.

seviprince commented 3 years ago

En ligne de commande

python couplage2.py False 5

python couplage3.py False 5 plutot

seviprince commented 3 years ago

RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)

pas ones mais zeros ?

J'ai testé ça et ça donne le fichier un peu plus haut

seviprince commented 3 years ago

Ceci temp2

alexandrecuer commented 3 years ago

oui ca c'est OK mais il faut que tu rajoutes le label heating="pas de besoin" et pas heating="ECS"....et là on est d'accord :-)

alexandrecuer commented 3 years ago

relis bien le code il y a une partie où l'on donne des valeurs par défaut à heating pour que le titrage du graphe se fasse un peu automatiquement quant on ne renseigne pas heating dans les usecases, le soft utilise les paramètres de la ligne de commande pour générer heating il suit ce schéma très simple :

if ECSupply:
    heating = "chauffage+ECS"
else:
    heating = "chauffage"

ECSupply est le premier argument de la ligne de commande

quant on décide dans un usecase de donner une valeur singulière à heating, c'est parce qu'on sort de ce schéma simple....et là c'est le cas, donc il faut le mentionner pour que les graphes soient bien titrés mais il faut que la mention soit en concordance avec ce que l'on a codé

seviprince commented 3 years ago

usecase5_1

C'est bon??

alexandrecuer commented 3 years ago

oui :-) donc les pertes ont une influence mais assez minime si je comprends bien, si tu refais tourner le cas 2, tu as un rendement de 20% sans ECS et meilleur avec ?

alexandrecuer commented 3 years ago

tu vas vouloir faire les diagrammes de sankey, c'est celà ? je vois qu'il y a un générateur içi : https://sankey.csaladen.es/

seviprince commented 3 years ago

Oui c'est ça. Ca va me servir. Merci J'ai aussi téléchargé le logiciel e!sankey

alexandrecuer commented 3 years ago

l'avantage avec le logiciel enligne, c'est qu'il suffit de lui donner un fichier de ce type pour qu'il génère le diagramme

{"sankey":
    {"nodes":
        [ 
            {"name":"Oil","layer":0},
            {"name":"Natural Gas","layer":0},
            {"name":"Coal","fill":"seaGreen","layer":0},
            {"name":"Fossil Fuels","value":65,"layer":2},
            {"name":"Electricity","layer":2},
            {"name":"Energy","fill":"grey","layer":3} 
        ],
     "links":
        [ 
            {"source":0,"target":3,"value":15,"fill":"blue"},
            {"source":1,"target":3,"value":20},
            {"source":2,"target":3,"value":25},
            {"source":2,"target":4,"value":25},
            {"source":3,"target":5,"value":60},
            {"source":4,"target":5,"value":25},
            {"source":4,"target":4,"value":5} 
        ]
    }
}

et que ce genre de fichier peut être construit directement depuis python d'après tes résultats les nodes sont les noeuds dans l'ordre, numérotés de 0 à 5, et positionnés dans le plan en leur donnant un numéro de layer, plus le nombre est grand, plus on est vers la droite.... ensuite on crée des liens en affectant des poids et le soft se débrouille avec

seviprince commented 3 years ago

D'accord.

alexandrecuer commented 3 years ago

il y a mieux je crois....c'est tout prêt dans matplotlib

import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey

cf https://flothesof.github.io/sankey-tutorial-matplotlib.html

seviprince commented 3 years ago

il y a mieux je crois....c'est tout prêt dans matplotlib

import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey

cf https://flothesof.github.io/sankey-tutorial-matplotlib.html

Bien reçu.Merci

seviprince commented 3 years ago

Voici comment j'ai créé la méthode setPertes:

def setPertes(self,simPertes,Tmoy,Tamp,lambda_sable,rho_sable,cpsable,e_iso,SL_iso,SB_iso,lambda_iso):

        """
        simPertes= boléen(0 or 1) pour la sélection de la simulation avec ou sans pertes

        Tmoy= Température moyenne annuelle du sous-sol

        Tamp= l'amplitude annulle de la température i.e Tmax-Tmin

        tf=Le jour correspondant à la température minimale du sous-sol ( le 18 janvier à chambéry)

        lambda_sable= conductivité thermique du sous-sol

        lambda_iso= conductivité thermique de l'isolant autour du stockage

        SL_iso= surface de l'isolant le long des parois latéraux du stockage

        SB_iso= surface de l'isolant posée à la base du stockage

        e_iso= épaisseur de l'isolant

        """

        self.simPertes=simPertes

        self.tf=18*24*self.step

        self.Tmoy=Tmoy 

        self.Tamp=Tamp

        self.lambda_sable=lambda_sable

        self.cpsable=cpsable

        self.rho_sable=rho_sable

        self.lamba_iso=lambda_iso

        self.e_iso=e_iso

        self.SL_iso=SL_iso

        self.SB_iso=SB_iso

        self.a=self.lambda_sable/(self.cpsable*self.rho_sable)

        self.w=2*math.pi/(8760*self.step)

        self.u_th=self.lamba_iso/self.e_iso
def Tsous_sol(self,z,i):

        """
        La température du sous-sol est une fonction sinusoidale :
        - de période = une année
        - de pulsation w ,obtenue à partir de l'équation de la propagation de la chaleur dans le sous-sol.

        z : profondeur en mètres

        i : indice temporel dans la discrétisation

        """
        self.z=z

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

        factor = math.cos(self.w * (self.step * i - self.tf) + self.z/self.za ) * math.exp(self.z / self.za)

        return self.Tmoy - self.Tamp * factor
def pertes(self,i):

        """
        La temérature du sous-sol est une fonction sinusoidale de période=une année et de pulsation w ,obtenue à partir de l'équation 

        de la propagation de la chaleur dans le sous-sol.

        """

        """
        Calcul de la difusivité thermique du sous-sol notée a et de la pulsation w

        """
        if self.simPertes==0:

            return 0

        else:

            self.pertes_Laterales=self.SL_iso*(self.Tsable[i]-self.Tsous_sol(-1.125,i))

            self.pertes_Base=self.SB_iso*(self.Tsable[i]-self.Tsous_sol(-2.25,i))

            return   self.u_th*(self.pertes_Laterales+ self.pertes_Base)
 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é
        """

        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

Dans couplage3.py je fais:

Tmoy=11
Tamp=9.1
lambda_sable=1.7
rho_sable=1700
e_iso=0.2
SL_iso=40.5
SB_iso=20
lambda_iso=0.038

simPertes=0
RSB.setPertes(simPertes,Tmoy,Tamp,lambda_sable,rho_sable,Cp_sable,e_iso,SL_iso,SB_iso,lambda_iso)
RSB.set(eff,k,coeff,msto,cpsto,m_sable,Cp_sable,mpac,cpac)

Et j'obtiens: Sans pertes: sans Avec pertes avec

seviprince commented 3 years ago

Quand je fais un affichage sur plus de deux ans ( pour voir le comportement périodique des courbes), j'obtiens un truc désordonné: trois_annees

Je dois faire d'autres réglages au niveau de l'affichage?

alexandrecuer commented 3 years ago

Oui l'esprit est bien...mais tu me mets des self là où il n'y en a pas besoin

self c'est uniquement quant tu veux des variables de portée globale, ie accessibles à toutes les méthodes de la classe....

donc par exemple :

self.pertes_Laterales=self.SL_iso*(self.Tsable[i]-self.Tsous_sol(-1.125,i))

self.pertes_Base=self.SB_iso*(self.Tsable[i]-self.Tsous_sol(-2.25,i))

return   self.u_th*(self.pertes_Laterales+ self.pertes_Base)

c'est plutôt

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))

return   self.u_th*(pertes_Laterales+ pertes_Base)

il faut reprendre la docstring de pertes(self,i) tu peux mettre seulement

calcul des pertes latérales et à la base du stock

dans Tsous_sol(self,z,i), le code est :

self.z=z

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

factor = math.cos(self.w * (self.step * i - self.tf) + self.z/self.za ) * math.exp(self.z / self.za)

return self.Tmoy - self.Tamp * factor

il devrait plutôt être seulement :

factor = math.cos(self.w * (self.step * i - self.tf) + z/self.za ) * math.exp(z / self.za)

return self.Tmoy - self.Tamp * factor

et enfin, dans setPertes, tu peux enlever cpsable, car il est déjà fixé dans la méthode set de plus il ne sert à rien de passer simPertes en variable...à partir du moment où l'on invoque setPertes, c'est que le booléen simPertes va valoir 1 il n'est pas utile de "globaliser" lamba_iso, e_iso, rho_sable et lambda_sable il faut par contre rajouter un vecteur global pour stocker les pertes car sinon, tu auras du mal à faire ton diagramme de Sankey :-)

def setPertes(self,Tmoy,Tamp,lambda_sable,rho_sable, e_iso,SL_iso,SB_iso,lambda_iso):

        """      
        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.pertes=np.zeros(self.size)

        self.tf=18*24*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)

        # w pulsation exprimée en s-1
        self.w = 2*math.pi / (8760*3600)

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

        self.u_th = lamba_iso / e_iso

dans le init, il faudrait bien sûr rajouter :

self.size=size

et dans set il faudrait mettre

self.simPertes = 0

tu peux peut-être faire une branche pertes et ensuite on mergera avec master

je vois pas trop l'intérêt de la fonction pertes perso....j'aurais plutôt mis le code correspondant dans StockLoop, auquel il faut rajouter l'instruction pour nourrir pertes[i]

à l'instanciation, tu fais setPertes avant set...ce n'est pas trop la logique des choses...il faudrait faire dans l'autre sens set est prioritaire : sans set, le système n'existe pas...setPertes par contre est complètement optionnelle donc il faut corriger

on aurait donc : avec pertes

RSB.set(eff,k,coeff,msto,cpsto,m_sable,Cp_sable,mpac,cpac)
RSB.setPertes(Tmoy, Tamp, lambda_sable, rho_sable, e_iso, SL_iso, SB_iso, lambda_iso)

et sans pertes, c'est tout simplement

RSB.set(eff,k,coeff,msto,cpsto,m_sable,Cp_sable,mpac,cpac)
alexandrecuer commented 3 years ago

Quand je fais un affichage sur plus de deux ans ( pour voir le comportement périodique des courbes), j'obtiens un truc désordonné:

Je dois faire d'autres réglages au niveau de l'affichage?

je dirais que tu es à moins de 2 ans non ? 2 ans = 8760 * 2 heures = 17520 heures

seviprince commented 3 years ago

Je vais tout arranger et mettre en ligne tout à l'heure avec les diagrammes de sankey également. Bonne soirée à vous

alexandrecuer commented 3 years ago

prends ton temps, on pourra voir celà demain, si tu vx on s'appelle via skype bonne nuit à toi

seviprince commented 3 years ago

D'accord. Je serai en ligne.

alexandrecuer commented 3 years ago

OK je suis prêt si tu veux EDIT : je vois que tu as mis le code en ligne...c'est OK, très bien ! je fais quelques modifs de documentation

alexandrecuer commented 3 years ago

pour passer ta procédure de concaténation de fichier météo en mode multi-annuel, il faut remplacer, dans couplage3.py, les commandes

meteo=np.concatenate((meteo,meteo))
meteo[npy:meteo.shape[0],0]=meteo[npy:meteo.shape[0],0]+npy

par :

year=3
meteo=np.concatenate((meteo,meteo,meteo))
for i in range(year):
    meteo[i*npy:(i+1)*npy,0]=meteo[i*npy:(i+1)*npy,0]+i*npy

ainsi, tu peux répliquer des météo identiques mais aussi concaténer des météo différentes....

alexandrecuer commented 3 years ago

Avec ces modifications, j'ai fait tourner sur 2 ans pour celà j'ai paramétré le cas d'usage 4 ainsi :

if usecase == 4:
    simStart =i_summerStart
    simEnd = i_summerStart+(year-1)*365*24
    RSB.agenda_dro[simStart:simEnd]=np.ones(simEnd-simStart)
    RSB.agenda_pac[simStart:simEnd]=np.ones(simEnd-simStart)

et je lance python couplage3.py False 4

image

en faisant

year=5
meteo=np.concatenate((meteo,meteo,meteo,meteo,meteo))

image

mais il faudrait effacer le besoin l'été, en gros reprogrammer la partie

"""
on efface les besoins de chauffage sur les étés
"""
besoin_chauffage[i_summerStart:i_summerEnd] = np.zeros(i_summerEnd-i_summerStart)

besoin_chauffage[i_summerStart+npy:i_summerEnd+npy]=np.zeros(i_summerEnd-i_summerStart)

avec une boucle....

seviprince commented 3 years ago

Bonjour, Concernant le problème sur les pertes détecté ce matin, c'est tout bon maintenant. J'ai refait les calculs et ça semble correct

alexandrecuer commented 3 years ago

les pbs détectés hier :

pour qu'on assure que les choses sont correctes, il faut que tu mettes le code dans la branche pertes...

alexandrecuer commented 3 years ago

J'ai réfléchi et il faut faire évoluer la classe sencity :

Côté bâtiment, il faudrait injecter ECSPower dans dromosense.tools voire peut-etre créer une classe buildingOne pour décrire un premier modèle de bâtiment....avec dedans des variables besoinHeat et besoinECS voire sunRad

@febron: Ce n'est pas urgent, ne le prends pas pour une commande...je le note ici uniquement pour le garder à l'esprit....l'essentiel est de faire évoluer intelligemment la fonction graphe qui n'est pas aboutie mais je vois bien les choses desormais

seviprince commented 3 years ago

Bonjour, Bien noté.