UNPKG

@open3cl/engine

Version:

Open Source 3CL-DPE engine

263 lines (232 loc) 10.1 kB
import enums from './enums.js'; import calc_mur from './3.2.1_mur.js'; import calc_pb from './3.2.2_plancher_bas.js'; import calc_ph from './3.2.3_plancher_haut.js'; import calc_bv from './3.3_baie_vitree.js'; import calc_porte from './3.3.1.4_porte.js'; import calc_pont_thermique from './3.4_pont_thermique.js'; import calc_ventilation from './4_ventilation.js'; function calc_Sdep(murs_list, porte_list, bv_list) { const Smurs_dep = murs_list.reduce((acc, mur) => { const type_adjacence = enums.type_adjacence[mur.donnee_entree.enum_type_adjacence_id]; if (mur.donnee_intermediaire.b === 0) return acc; if (type_adjacence.includes('local non déperditif')) return acc; else return acc + Number(mur.donnee_entree.surface_paroi_opaque); }, 0); const Sporte = porte_list.reduce((acc, porte) => { if (porte.donnee_intermediaire.b === 0) return acc; return acc + Number(porte.donnee_entree.surface_porte); }, 0); const Sbv = bv_list.reduce((acc, bv) => { if (bv.donnee_intermediaire.b === 0) return acc; return acc + Number(bv.donnee_entree.surface_totale_baie); }, 0); const Sdep = Smurs_dep + Sporte + Sbv; return Sdep; } export function Umur(o) { const de = o.donnee_entree; const di = o.donnee_intermediaire; return de.surface_paroi_opaque * di.umur * di.b; } export function Uph(o) { const de = o.donnee_entree; const di = o.donnee_intermediaire; return de.surface_paroi_opaque * di.uph * di.b; } export function Upb(o) { const de = o.donnee_entree; const di = o.donnee_intermediaire; return de.surface_paroi_opaque * di.upb_final * di.b; } export function Ubv(o) { const de = o.donnee_entree; const di = o.donnee_intermediaire; return de.surface_totale_baie * di.u_menuiserie * di.b; } export function Uporte(o) { const de = o.donnee_entree; const di = o.donnee_intermediaire; return de.surface_porte * di.uporte * di.b; } /** * Compare la liste des ponts thermiques déclarés et calculés * Retourne true si individuellement chacun des ponts thermiques est identique * @param calculatedPTs * @param declaredPTs * @returns {boolean} */ function verifyPontsThermiquesEquality(calculatedPTs, declaredPTs) { /** * Pour les ponts thermiques déclarés, le facteur deperdition_pont_thermique étant déjà pris en compte, seul k est considéré */ const uptForCalculatedPTs = calculatedPTs.map( (calculatedPT) => calculatedPT.donnee_intermediaire.k * (calculatedPT.donnee_entree.pourcentage_valeur_pont_thermique || 1) ); const uptForDeclaredPTs = declaredPTs.map((declaredPT) => declaredPT.donnee_intermediaire.k); return ( calculatedPTs.length === declaredPTs.length && !uptForCalculatedPTs.some((val, i) => { return ( val.toFixed(3) !== uptForDeclaredPTs[i].toFixed(3) && val.toFixed(3) !== ( uptForDeclaredPTs[i] * (calculatedPTs[i].donnee_entree.pourcentage_valeur_pont_thermique || 1) ).toFixed(3) ); }) ); } /** * Compare la liste des murs déclarés et calculés * Retourne true si individuellement chacun des murs est identique * @param calculatedMurs * @param declaredMurs * @returns {boolean} */ function verifyMursEquality(calculatedMurs, declaredMurs) { const uMurForCalculatedMurs = calculatedMurs.map( (calculatedMur) => calculatedMur.donnee_entree.surface_paroi_opaque * calculatedMur.donnee_intermediaire.umur * calculatedMur.donnee_intermediaire.b ); const uMurForDeclaredMurs = declaredMurs.map( (declaredMur) => declaredMur.donnee_entree.surface_paroi_opaque * declaredMur.donnee_intermediaire?.umur * declaredMur.donnee_intermediaire?.b ); return ( calculatedMurs.length === declaredMurs.length && !uMurForCalculatedMurs.some((val, i) => val.toFixed(3) !== uMurForDeclaredMurs[i].toFixed(3)) ); } /** * Calcul de la déperdition totale liée aux ponts thermiques * @param dpe {FullDpe} * @param calculatedPontsThermiques * @param declaredPontsThermiques * @return {number} */ function totalDeperditionPontThermique(dpe, calculatedPontsThermiques, declaredPontsThermiques) { const calculatedDeperditionPT = calculatedPontsThermiques.reduce( (acc, pt) => acc + Upt(pt) || 0, 0 ); if (!dpe.logement.sortie?.deperdition?.deperdition_pont_thermique) { return calculatedDeperditionPT; } // Total déclaré des déperditions des ponts thermiques const declaredDeperditionPT = dpe.logement.sortie.deperdition.deperdition_pont_thermique; /** * Comparaison des valeurs intermédiaires calculées et déclarées pour chacun des ponts thermiques * @type {boolean} */ const sameValues = verifyPontsThermiquesEquality( calculatedPontsThermiques, declaredPontsThermiques ); /** * Si individuellement les ponts thermiques déclarés et calculés sont identiques, la déperdition totale devrait l'être également * Pour certains DPE, il réside une différence que l'on prendra en compte pour la suite des calculs. */ if (sameValues && calculatedDeperditionPT.toFixed(5) !== declaredDeperditionPT.toFixed(5)) { console.error( `Les valeurs des ponts thermiques calculées et déclarées pour le DPE ${dpe.numero_dpe} sont les mêmes mais le total des déperditions pour les ponts thermiques ${declaredDeperditionPT} diffère du total calculé avec les mêmes valeurs ${declaredDeperditionPT}'. Le total déclaré est conservé.` ); return declaredDeperditionPT; } return calculatedDeperditionPT; } /** * Calcul de la déperdition totale liée aux murs * @param dpe {FullDpe} * @param calculatedMurs * @param declaredMurs * @return {number} */ function totalDeperditionMurs(dpe, calculatedMurs, declaredMurs) { // Total déclaré des déperditions des murs const declaredDeperditionMurs = dpe.logement.sortie?.deperdition?.deperdition_mur; /** * Comparaison des valeurs intermédiaires calculées et déclarées pour chacun des murs * @type {boolean} */ const sameValues = verifyMursEquality(calculatedMurs, declaredMurs); const calculatedDeperditionMur = calculatedMurs.reduce((acc, mur) => acc + Umur(mur) || 0, 0); /** * Si individuellement les murs déclarés et calculés sont identiques, la déperdition totale devrait l'être également * Pour certains DPE, il réside une différence que l'on prendra en compte pour la suite des calculs. */ if (sameValues && calculatedDeperditionMur.toFixed(5) !== declaredDeperditionMurs.toFixed(5)) { if (declaredDeperditionMurs.toFixed(5) > calculatedDeperditionMur.toFixed(5)) { console.error( `Les valeurs des murs calculées et déclarées pour le DPE ${dpe.numero_dpe} sont les mêmes mais le total déclaré des déperditions pour les murs '${declaredDeperditionMurs}' diffère et est supérieure au total calculé avec les mêmes valeurs '${calculatedDeperditionMur}'. Le total déclaré est conservé.` ); return declaredDeperditionMurs; } else { console.error( `Les valeurs des murs calculées et déclarées pour le DPE ${dpe.numero_dpe} sont les mêmes mais le total déclaré des déperditions pour les murs '${declaredDeperditionMurs}' diffère et est inférieure au total calculé avec les mêmes valeurs '${calculatedDeperditionMur}'. Le total calculé est conservé.` ); return calculatedDeperditionMur; } } return calculatedDeperditionMur; } export function Upt(pt) { const de = pt.donnee_entree; const di = pt.donnee_intermediaire; return de.l * di.k * (de.pourcentage_valeur_pont_thermique || 1); } export default function calc_deperdition(cg, zc, th, effetJoule, dpe, Sh) { const pc = cg.enum_periode_construction_id; const logement = dpe.logement; const enveloppe = logement.enveloppe; const mur_list = enveloppe.mur_collection.mur || []; const declaredMurs = structuredClone(mur_list); const pb_list = enveloppe.plancher_bas_collection.plancher_bas || []; const ph_list = enveloppe.plancher_haut_collection.plancher_haut || []; const porte_list = enveloppe.porte_collection.porte || []; const bv_list = enveloppe.baie_vitree_collection.baie_vitree || []; const pt_list = enveloppe.pont_thermique_collection.pont_thermique || []; const declaredPontsThermiques = structuredClone(pt_list); const vt_list = logement.ventilation_collection.ventilation || []; mur_list.forEach((mur) => calc_mur(mur, zc, pc, effetJoule)); pb_list.forEach((pb) => calc_pb(pb, zc, pc, effetJoule, pb_list)); ph_list.forEach((ph) => calc_ph(ph, zc, pc, effetJoule)); bv_list.forEach((bv) => calc_bv(bv, zc)); porte_list.forEach((porte) => calc_porte(porte, zc)); pt_list.forEach((pt) => calc_pont_thermique(pt, pc, logement)); const murs_list = mur_list.concat(ph_list); const Sdep = calc_Sdep(murs_list, porte_list, bv_list); vt_list.forEach((vt) => { calc_ventilation(vt, cg, th, Sdep, Sh, mur_list, ph_list, porte_list, bv_list); }); const d_mur = totalDeperditionMurs(dpe, mur_list, declaredMurs); const d_pb = pb_list.reduce((acc, pb) => acc + Upb(pb) || 0, 0); const d_ph = ph_list.reduce((acc, ph) => acc + Uph(ph) || 0, 0); const d_bv = bv_list.reduce((acc, bv) => acc + Ubv(bv) || 0, 0); const d_porte = porte_list.reduce((acc, porte) => acc + Uporte(porte) || 0, 0); const d_pt = totalDeperditionPontThermique(dpe, pt_list, declaredPontsThermiques); const hvent = vt_list.reduce((acc, vt) => acc + vt.donnee_intermediaire.hvent || 0, 0); const hperm = vt_list.reduce((acc, vt) => acc + vt.donnee_intermediaire.hperm || 0, 0); return { hvent, hperm, deperdition_renouvellement_air: hvent + hperm, deperdition_mur: d_mur, deperdition_plancher_bas: d_pb, deperdition_plancher_haut: d_ph, deperdition_baie_vitree: d_bv, deperdition_porte: d_porte, deperdition_pont_thermique: d_pt, deperdition_enveloppe: d_mur + d_pb + d_ph + d_bv + d_porte + d_pt + hvent + hperm }; }