@open3cl/engine 1.8.68 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/11_ecs.js CHANGED
@@ -58,11 +58,12 @@ function tv_rendement_distribution_ecs(di, de, du, pvc) {
58
58
  * Calcul installation par installation pour les réseaux collectifs bouclés ou avec traçage.
59
59
  *
60
60
  * @param {object} de - donnee_entree de l'installation ECS
61
+ * @param {object} di - donnee_intermediaire de l'installation ECS (reçoit la longueur de bouclage lb)
61
62
  * @param {number} surfaceImmeuble - surface habitable totale de l'immeuble (m²)
62
63
  * @param {object} becsParMois - besoin ECS mensuel de l'immeuble {Janvier: X, Février: X, ...} [kWh]
63
64
  * @returns {number} conso_auxiliaire_distribution_ecs_installation [Wh]
64
65
  */
65
- function calc_auxiliaire_distribution_ecs_immeuble(de, surfaceImmeuble, becsParMois) {
66
+ function calc_auxiliaire_distribution_ecs_immeuble(de, di, surfaceImmeuble, becsParMois) {
66
67
  const type_installation = enums.type_installation[de.enum_type_installation_id];
67
68
 
68
69
  // Seulement pour les installations collectives
@@ -95,6 +96,7 @@ function calc_auxiliaire_distribution_ecs_immeuble(de, surfaceImmeuble, becsParM
95
96
  // Étape 3 : Calcul de Lb pour l'installation i
96
97
  // Lb = 1.2 × (1.1 × Sh_inst/nombre_niveaux + 4 × nombre_niveaux)
97
98
  const Lb = 1.2 * (1.1 * (Sh_inst / Niv_inst) + 4 * Niv_inst);
99
+ di.lb = Lb;
98
100
 
99
101
  // Étape 4 : DeltaPb = 0.2 × Lb + 10
100
102
  const DeltaPb = 0.2 * Lb + 10;
@@ -287,6 +289,7 @@ export default function calc_ecs(
287
289
  if (th === 'immeuble' && becsParMois && Object.keys(becsParMois).length > 0) {
288
290
  const conso_aux_wh = calc_auxiliaire_distribution_ecs_immeuble(
289
291
  de,
292
+ di,
290
293
  surfaceImmeuble,
291
294
  becsParMois
292
295
  );
package/11_ecs.spec.js CHANGED
@@ -734,4 +734,36 @@ describe('calc_ecs - auxiliaires de distribution ECS (immeuble)', () => {
734
734
 
735
735
  expect(sansNiveau).toBe(avecUnNiveau);
736
736
  });
737
+
738
+ /** Calcule l'ECS d'un immeuble et retourne la donnée intermédiaire de l'installation. */
739
+ function donneeIntermediaireImmeuble(deExtra) {
740
+ const ecs = makeEcs({ tv_rendement_distribution_ecs_id: '5', ...deExtra });
741
+ calc_ecs({}, ecs, 100, 200, 1, 'ca1', 'h1a', 'immeuble', false, 400, null, false, {
742
+ Janvier: 10000
743
+ });
744
+ return ecs.donnee_intermediaire;
745
+ }
746
+
747
+ test('réseau bouclé : longueur de bouclage lb exposée dans la donnée intermédiaire', () => {
748
+ const di = donneeIntermediaireImmeuble({
749
+ enum_type_installation_id: '2',
750
+ enum_bouclage_reseau_ecs_id: '2',
751
+ surface_habitable: 100,
752
+ nombre_niveau_installation_ecs: '2'
753
+ });
754
+
755
+ // Lb = 1,2 × (1,1 × 100 / 2 + 4 × 2) = 75,6 m
756
+ expect(di.lb).toBeCloseTo(75.6, 9);
757
+ });
758
+
759
+ test.each([
760
+ ['réseau avec traçage', { enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '3' }],
761
+ [
762
+ 'réseau collectif non bouclé',
763
+ { enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '1' }
764
+ ],
765
+ ['installation individuelle', { enum_type_installation_id: '1' }]
766
+ ])('%s : pas de longueur de bouclage lb', (_libelle, de) => {
767
+ expect(donneeIntermediaireImmeuble(de).lb).toBeUndefined();
768
+ });
737
769
  });
package/15_conso_aux.js CHANGED
@@ -283,6 +283,12 @@ function getPuissanceCirculateur(em_ch, de, di, du, surfaceHabitable, GV, Tbase)
283
283
  // Calcul de la longueur du réseau le plus défavorisé
284
284
  const Lem = 5 * Fcot * (nbNiveauChauffage + (surfaceInstallation / nbNiveauChauffage) ** 0.5);
285
285
 
286
+ // Exposition de la longueur du réseau (lb) dans les données intermédiaires des émetteurs desservis
287
+ em_ch.forEach((em) => {
288
+ em.donnee_intermediaire = em.donnee_intermediaire || {};
289
+ em.donnee_intermediaire.lb = Lem;
290
+ });
291
+
286
292
  // Pertes de charge du réseau (kPa)
287
293
  const deltaPemnom = 0.15 * Lem + deltaPem;
288
294
 
@@ -412,6 +418,7 @@ export function conso_aux_distribution_ecs(
412
418
  // Pour l'appartement, on utilise la surface à l'échelle de l'immeuble
413
419
  const Sh = (Sh_install / Sh_logement) * Sh_immeuble_ratio;
414
420
  const Lb = 4 * Math.pow(Sh / Niv_inst_ecs, 0.5) + 6 * (Niv_inst_ecs - 0.5);
421
+ di.lb = Lb;
415
422
 
416
423
  // Etape 4: DeltaPb (kPa) - perte de charge dans le bouclage
417
424
  const DeltaPb = 0.2 * Lb + 10;
@@ -389,6 +389,73 @@ describe('conso_aux_distribution_ch - auxiliaires de distribution', () => {
389
389
  );
390
390
  });
391
391
 
392
+ /**
393
+ * La longueur du réseau le plus défavorisé (Lem) est exposée sous le nom lb dans la donnée
394
+ * intermédiaire de chaque émetteur desservi par le circulateur.
395
+ * @see : Methode_de_calcul_3CL_DPE_2021-338.pdf - §15.2.1
396
+ */
397
+ test('longueur du réseau lb exposée dans la donnée intermédiaire des émetteurs', () => {
398
+ const em = [
399
+ {
400
+ donnee_entree: {
401
+ enum_type_emission_distribution_id: '10',
402
+ enum_temp_distribution_ch_id: '3'
403
+ },
404
+ donnee_intermediaire: { rendement_emission: 0.95 }
405
+ }
406
+ ];
407
+ conso_aux_distribution_ch(em, {}, {}, {}, 100, 1, 1, '0', 100000);
408
+ // Lem = 5 × Fcot × (Niv + (Sh / Niv)^0,5) = 5 × 0,802 × (1 + 10) = 44,11 m
409
+ expect(em[0].donnee_intermediaire.lb).toBeCloseTo(44.11, 9);
410
+ // les autres données intermédiaires de l'émetteur sont conservées
411
+ expect(em[0].donnee_intermediaire.rendement_emission).toBe(0.95);
412
+ });
413
+
414
+ test('lb : plancher chauffant sur 2 niveaux, donnée intermédiaire absente créée', () => {
415
+ const em = [
416
+ {
417
+ donnee_entree: {
418
+ enum_type_emission_distribution_id: '6',
419
+ enum_temp_distribution_ch_id: '3'
420
+ }
421
+ }
422
+ ];
423
+ conso_aux_distribution_ch(em, { nombre_niveau_installation_ch: 2 }, {}, {}, 200, 1, 1, '0', 1);
424
+ // Lem = 5 × 0,156 × (2 + (200 / 2)^0,5) = 9,36 m
425
+ expect(em[0].donnee_intermediaire.lb).toBeCloseTo(9.36, 9);
426
+ });
427
+
428
+ test('lb : seuls les émetteurs reliés au générateur reçoivent la longueur du réseau', () => {
429
+ const plancher = {
430
+ donnee_entree: {
431
+ enum_type_emission_distribution_id: '6',
432
+ enum_temp_distribution_ch_id: '3',
433
+ enum_lien_generateur_emetteur_id: '1'
434
+ }
435
+ };
436
+ const convecteur = {
437
+ donnee_entree: {
438
+ enum_type_emission_distribution_id: '1',
439
+ enum_temp_distribution_ch_id: '3',
440
+ enum_lien_generateur_emetteur_id: '2'
441
+ }
442
+ };
443
+ conso_aux_distribution_ch(
444
+ [plancher, convecteur],
445
+ { enum_lien_generateur_emetteur_id: '1' },
446
+ {},
447
+ {},
448
+ 100,
449
+ 1,
450
+ 1,
451
+ '0',
452
+ 100000
453
+ );
454
+ // Lem = 5 × 0,156 × (1 + 10) = 8,58 m
455
+ expect(plancher.donnee_intermediaire.lb).toBeCloseTo(8.58, 9);
456
+ expect(convecteur.donnee_intermediaire).toBeUndefined();
457
+ });
458
+
392
459
  test('aucun émetteur relié au générateur : tous les émetteurs sont conservés', () => {
393
460
  const em = (lien) => ({
394
461
  donnee_entree: {
@@ -776,6 +843,40 @@ describe("conso_aux_distribution_ecs - auxiliaires de distribution d'ECS", () =>
776
843
  expect(di.conso_auxiliaire_distribution_ecs).toBeCloseTo(2.4208575056559525, 9);
777
844
  });
778
845
 
846
+ test('réseau bouclé : longueur de bouclage lb exposée dans la donnée intermédiaire', () => {
847
+ const di = {};
848
+ conso_aux_distribution_ecs(
849
+ {},
850
+ {
851
+ enum_type_installation_id: '2',
852
+ enum_bouclage_reseau_ecs_id: '2',
853
+ surface_habitable: 50,
854
+ nombre_niveau_installation_ecs: 4
855
+ },
856
+ di,
857
+ 50,
858
+ 1600,
859
+ 1,
860
+ 1,
861
+ 30
862
+ );
863
+ // Sh = 1600 m² (échelle immeuble) : Lb = 4 × (1600 / 4)^0,5 + 6 × (4 − 0,5) = 80 + 21 = 101 m
864
+ expect(di.lb).toBeCloseTo(101, 9);
865
+ });
866
+
867
+ test.each([
868
+ [
869
+ 'installation individuelle',
870
+ { enum_type_installation_id: '1', enum_bouclage_reseau_ecs_id: '2' }
871
+ ],
872
+ ['réseau non bouclé', { enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '1' }],
873
+ ['réseau avec traçage', { enum_type_installation_id: '2', enum_bouclage_reseau_ecs_id: '3' }]
874
+ ])('%s : pas de longueur de bouclage lb', (_libelle, de) => {
875
+ const di = { besoin_ecs: 1000 };
876
+ conso_aux_distribution_ecs({}, de, di, 50, 2000, 1, 1, 30);
877
+ expect(di.lb).toBeUndefined();
878
+ });
879
+
779
880
  test('plus de niveaux desservis : bouclage plus court, donc consommation plus faible', () => {
780
881
  const scenario = (Niv) => {
781
882
  const di = {};
package/engine.js CHANGED
@@ -35,7 +35,7 @@ import DpeSanitizerService from './dpe-sanitizer.service.js';
35
35
  import { reconstituerRdimDpeGenereImmeuble } from './17.2_rdim_dpe_genere_immeuble.js';
36
36
  import { reconstituerRdimEcsIndividuelleUnique } from './11_rdim_ecs_individuelle_unique.js';
37
37
 
38
- const LIB_VERSION = '1.8.68';
38
+ const LIB_VERSION = '1.9.0';
39
39
 
40
40
  const dpeSanitizerService = new DpeSanitizerService();
41
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open3cl/engine",
3
- "version": "1.8.68",
3
+ "version": "1.9.0",
4
4
  "description": "Open Source 3CL-DPE engine",
5
5
  "main": "index.js",
6
6
  "directories": {