Skip to content

Commit

Permalink
feat: include the windows in the heat loss rate (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReidyT authored Nov 22, 2024
1 parent b1ebce1 commit f6270d8
Show file tree
Hide file tree
Showing 16 changed files with 592 additions and 150 deletions.
25 changes: 24 additions & 1 deletion src/config/simulation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Material } from '@/types/material';
import { TimeUnit } from '@/types/time';
import { NonEmptyArray } from '@/types/utils';

export const SIMULATION_FRAME_MS = 150;
export const SIMULATION_SLIDING_WINDOW = { window: 2, unit: TimeUnit.Days };
Expand All @@ -9,8 +11,29 @@ export const SIMULATION_CSV_FILE = {

export const SIMULATION_INDOOR_TEMPERATURE_CELCIUS = 22;
export const SIMULATION_PRICE_KWH = 0.22;
export const SIMULATION_DEFAULT_MATERIAL = {
export const AEROGEL_MATERIAL: Material = {
price: 0,
thermalConductivity: 0.021,
thickness: 0.25,
};
export const SINGLE_WINDOW_PANE_MATERIAL: Material = {
price: 0,
thermalConductivity: 0.8,
thickness: 0.005,
};
export const DOUBLE_WINDOW_PANE_MATERIAL: NonEmptyArray<Material> = [
SINGLE_WINDOW_PANE_MATERIAL,
// Air
{
price: 0,
thermalConductivity: 0.024,
thickness: 0.005,
},
SINGLE_WINDOW_PANE_MATERIAL,
];

export const SIMULATION_DEFAULT_WALL_MATERIALS: NonEmptyArray<Material> = [
AEROGEL_MATERIAL,
];
export const SIMULATION_DEFAULT_WINDOW_MATERIALS: NonEmptyArray<Material> =
DOUBLE_WINDOW_PANE_MATERIAL;
114 changes: 114 additions & 0 deletions src/context/HouseComponentsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import {
ReactNode,
createContext,
useCallback,
useContext,
useMemo,
useState,
} from 'react';

import {
SIMULATION_DEFAULT_WALL_MATERIALS,
SIMULATION_DEFAULT_WINDOW_MATERIALS,
} from '@/config/simulation';
import { HouseComponents } from '@/models/HouseComponents';
import { HouseComponentType, Size } from '@/types/houseComponent';
import { Material } from '@/types/material';
import { NonEmptyArray } from '@/types/utils';
import { undefinedContextErrorFactory } from '@/utils/context';

export type RegisterComponentParams = {
componentId: string;
parentId?: string;
size: Size;
componentType: HouseComponentType;
};

type HouseComponentsContextType = {
houseComponents: HouseComponents;
registerComponent: (params: RegisterComponentParams) => void;
};

const HouseComponentsContext = createContext<HouseComponentsContextType | null>(
null,
);

type Props = {
children: ReactNode;
};

export const HouseComponentsProvider = ({ children }: Props): ReactNode => {
// TODO: will be updated by users
// An house component can be composed with multiple materials
// For example, a double-glazed window is made up of two panes of glass and air.
const componentMaterials: Map<
HouseComponentType,
NonEmptyArray<Material>
> = useMemo(
() =>
new Map([
// TODO: load form a CSV
[HouseComponentType.Wall, SIMULATION_DEFAULT_WALL_MATERIALS],
[HouseComponentType.Window, SIMULATION_DEFAULT_WINDOW_MATERIALS],
]),
[],
);
const [houseComponents, setHouseComponents] = useState<HouseComponents>(() =>
HouseComponents.create(),
);

const registerComponent = useCallback(
({
componentId,
parentId,
size,
componentType,
}: RegisterComponentParams): void => {
const materials = componentMaterials.get(componentType);

if (!materials?.length) {
throw new Error(
`No material was found for the component ${componentType}`,
);
}

setHouseComponents((curr) =>
curr.cloneWith({
componentId,
parentId,
component: {
size,
materials,
componentType,
actualArea: size.height * size.width,
},
}),
);
},
[componentMaterials],
);

const contextValue = useMemo(
() => ({
houseComponents,
registerComponent,
}),
[houseComponents, registerComponent],
);

return (
<HouseComponentsContext.Provider value={contextValue}>
{children}
</HouseComponentsContext.Provider>
);
};

export const useHouseComponents = (): HouseComponentsContextType => {
const context = useContext(HouseComponentsContext);

if (!context) {
throw undefinedContextErrorFactory('HouseComponents');
}

return context;
};
27 changes: 4 additions & 23 deletions src/context/SimulationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,13 @@ import {
} from 'react';

import {
SIMULATION_DEFAULT_MATERIAL,
SIMULATION_INDOOR_TEMPERATURE_CELCIUS,
SIMULATION_PRICE_KWH,
} from '@/config/simulation';
import { useHeatLoss } from '@/hooks/useHeatLoss';
import {
RegisterComponentParams,
useHouseComponents,
} from '@/hooks/useHouseComponents';
import { useSimulationProgression } from '@/hooks/useSimulationProgression';
import { FormattedHeatLoss } from '@/types/heatLoss';
import {
HeatLossPerComponent,
HouseComponentType,
} from '@/types/houseComponent';
import { Material } from '@/types/material';
import { HeatLossPerComponent } from '@/types/houseComponent';
import { SimulationProgression, SimulationStatus } from '@/types/simulation';
import { SlidingWindow } from '@/types/temperatures';
import { FormattedTime, TimeUnit, TimeUnitType } from '@/types/time';
Expand All @@ -39,6 +30,7 @@ import {
TemperatureIterator,
initSlidingWindow,
} from '../models/TemperatureIterator';
import { useHouseComponents } from './HouseComponentsContext';

type SimulationContextType = {
status: SimulationStatus;
Expand All @@ -50,9 +42,7 @@ type SimulationContextType = {
progression: SimulationProgression;
period: SlidingWindow['period'];
duration: FormattedTime;
materials: Map<HouseComponentType, Material>;
startSimulation: () => void;
registerComponent: (params: RegisterComponentParams) => void;
};

const SimulationContext = createContext<SimulationContextType | null>(null);
Expand Down Expand Up @@ -88,15 +78,10 @@ export const SimulationProvider = ({

// TODO: These parameters will be changed by the user
const indoorTemperature = SIMULATION_INDOOR_TEMPERATURE_CELCIUS;
const materials: Map<HouseComponentType, Material> = useMemo(
() => new Map([[HouseComponentType.Wall, SIMULATION_DEFAULT_MATERIAL]]),
[],
);

const pricekWh = SIMULATION_PRICE_KWH;

const { houseComponents, registerComponent } = useHouseComponents({
materials,
});
const { houseComponents } = useHouseComponents();

const { heatLosses, totalHeatLoss } = useHeatLoss({
houseComponents,
Expand Down Expand Up @@ -158,7 +143,6 @@ export const SimulationProvider = ({
period: currentWindow.period,
progression,
duration: simulationDuration,
materials,
status: simulationStatus,
heatLosses,
totalHeatLoss: formatHeatLossRate(totalHeatLoss),
Expand All @@ -168,17 +152,14 @@ export const SimulationProvider = ({
totalHeatLoss / powerConversionFactors.KiloWatt,
}),
startSimulation,
registerComponent,
}),
[
currentWindow.mean,
currentWindow.period,
heatLosses,
indoorTemperature,
materials,
pricekWh,
progression,
registerComponent,
simulationDuration,
simulationStatus,
startSimulation,
Expand Down
14 changes: 7 additions & 7 deletions src/hooks/useHeatLoss.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react';

import { HeatLossPerComponent, HouseComponents } from '@/types/houseComponent';
import { HouseComponents } from '@/models/HouseComponents';
import { HeatLossPerComponent } from '@/types/houseComponent';
import { TimeUnitType } from '@/types/time';
import {
calculateHeatLossConstantFactor,
Expand Down Expand Up @@ -32,13 +33,12 @@ export const useHeatLoss = ({
// Compute the constant factors per house's components
const heatLossConstantFactors = useMemo(
() =>
Array.from(houseComponents.entries()).reduce<HeatLossPerComponent>(
(acc, [id, c]) => ({
houseComponents.getAll().reduce<HeatLossPerComponent>(
(acc, c) => ({
...acc,
[id]: calculateHeatLossConstantFactor({
area: c.area,
thermalConductivity: c.material.thermalConductivity,
materialThickness: c.material.thickness,
[c.id]: calculateHeatLossConstantFactor({
area: c.actualArea,
materials: c.materials,
}),
}),
{},
Expand Down
57 changes: 0 additions & 57 deletions src/hooks/useHouseComponents.tsx

This file was deleted.

Loading

0 comments on commit f6270d8

Please sign in to comment.