Skip to content

Commit 18b20a5

Browse files
authored
Merge pull request #112 from fhac-ewi/feature/extending-metadata
Improved view Meta for grid optimization
2 parents 508f605 + 6695f71 commit 18b20a5

5 files changed

Lines changed: 230 additions & 32 deletions

File tree

src-frontend/src/App.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
IntermediateNode,
1111
MassenstromResponse,
1212
NodeElements,
13-
NodeType,
13+
NodeType, OptimizationMetadata,
1414
OutputNode,
1515
Pipe
1616
} from "./models";
@@ -26,23 +26,25 @@ import {NodeMenuSpawnerContainer} from "./NodeMenu/NodeMenuSpawnerContainer";
2626
import Notifications from "./Overlays/Notifications";
2727
import {OptimizationResults} from "./OptimizationResults";
2828
import {DetermineMassFlowRateButton} from "./NodeMenu/DetermineMassFlowRateButton";
29-
import {defaultMassenstrom} from "./defaultConfig";
3029
import Backdrop from "./Backdrop";
3130
import {KeyboardKey} from "./Components/ConfirmationButton";
3231
import {Map, Storage, Timeline} from "@material-ui/icons";
32+
import {
33+
defaultMassenstrom,
34+
defaultNodeElements,
35+
defaultOptimizationMetadata,
36+
defaultTemperatureKey
37+
} from "./utils/defaults";
3338

3439
function App() {
3540

3641
const [renderUpload, setRenderUpload] = useState<boolean>(false);
3742
const [tabVal, setTabVal] = useState("2")
3843
const [massenstrom, setMassenstrom] = useState<MassenstromResponse>(defaultMassenstrom)
39-
const [nodeElements, setNodeElements] = useState<NodeElements>({
40-
inputNodes: [],
41-
intermediateNodes: [],
42-
outputNodes: []
43-
});
44+
const [nodeElements, setNodeElements] = useState<NodeElements>(defaultNodeElements);
4445
const [pipes, setPipes] = useState<Elements<Pipe>>([])
45-
const [temperatureKey, setTemperatureKey] = useState<string>("")
46+
const [temperatureKey, setTemperatureKey] = useState<string>(defaultTemperatureKey)
47+
const [optimizationMetadata, setOptimizationMetadata] = useState<OptimizationMetadata>(defaultOptimizationMetadata)
4648

4749
const handleKeyDown = (e: KeyboardEvent) => {
4850

@@ -134,7 +136,8 @@ function App() {
134136
</div>
135137
</TabPanel>
136138
<TabPanel value="2">
137-
<MetaDataContainer temperatureKey={temperatureKey} setTemperatureKey={setTemperatureKey}/>
139+
<MetaDataContainer temperatureKey={temperatureKey} setTemperatureKey={setTemperatureKey}
140+
optimizationMetadata={optimizationMetadata} setOptimizationMetadata={setOptimizationMetadata}/>
138141
</TabPanel>
139142
<TabPanel value={"3"}>
140143
<Suspense fallback={<Backdrop open={true}/>}>

src-frontend/src/MetaData/MetaDataContainer.tsx

Lines changed: 175 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,76 @@
1-
import React, {Dispatch, SetStateAction, useState} from "react";
1+
import React, {Dispatch, SetStateAction} from "react";
22
import {Button, Grid, InputLabel, TextField, Typography} from "@material-ui/core";
33
import {TemperatureDropdown} from "./TemperatureDropdown";
4+
import {OptimizationMetadata} from "../models";
45

56
interface Properties {
67
temperatureKey: string,
78
setTemperatureKey: Dispatch<SetStateAction<string>>
9+
optimizationMetadata: OptimizationMetadata,
10+
setOptimizationMetadata: (om: OptimizationMetadata) => void
811
}
912

10-
export const MetaDataContainer = ({temperatureKey, setTemperatureKey}: Properties) => {
13+
export const MetaDataContainer = ({temperatureKey, setTemperatureKey, optimizationMetadata, setOptimizationMetadata}: Properties) => {
1114

15+
const {
16+
gridInvestCostTemplate,
17+
gridOperatingCostTemplate,
18+
pumpInvestCostTemplate,
19+
heatGenerationCost,
20+
lifespanOfResources,
21+
wacc,
22+
electricityCost,
23+
electricalEfficiency,
24+
hydraulicEfficiency,
25+
insulationThickness
26+
} = optimizationMetadata;
1227

13-
const [insulationThickness, setInsulationThickness] = useState(0);
14-
const [pressureDropPerOutput, setPressureDropPerOutput] = useState(0)
28+
const SPACING = 3
1529

30+
const dispatchChange = (val: string, prop: string) => {
31+
const opt = {...optimizationMetadata};
32+
let valToInsert: (string|number) = val;
33+
if (isNumberProp(prop)) {
34+
if(!Number.isNaN(val) && val !== "") {
35+
valToInsert = getAsNumber(val);
36+
// @ts-ignore
37+
opt[prop] = valToInsert;
38+
setOptimizationMetadata(opt)
39+
}
40+
} else {
41+
// @ts-ignore
42+
opt[prop] = valToInsert;
43+
setOptimizationMetadata(opt)
44+
}
45+
}
1646

47+
const isNumberProp = (prop: string) => {
48+
const numberProps = [
49+
"heatGenerationCost",
50+
"lifespanOfResources",
51+
"wacc",
52+
"electricityCost",
53+
"electricalEfficiency",
54+
"hydraulicEfficiency",
55+
"insulationThickness"]
56+
return numberProps.includes(prop)
57+
}
58+
59+
const getAsNumber = (val: string): number => {
60+
return Number.parseFloat(val);
61+
}
1762

1863
return <Grid
1964
container
2065
direction="row"
2166
justify="center"
2267
alignItems="center"
68+
spacing={SPACING}
2369
>
2470
<Grid container
25-
direction="row" item xs={7} spacing={3}>
71+
direction="row"
72+
alignContent="center"
73+
justify="center" item xs={7} spacing={SPACING}>
2674
<Grid item xs={12}>
2775
<Typography className={"header-form"} color="textSecondary" gutterBottom>
2876
Hier kannst du gegebenenfalls die Meta Daten anpassen
@@ -31,30 +79,142 @@ export const MetaDataContainer = ({temperatureKey, setTemperatureKey}: Propertie
3179
</Grid>
3280

3381
<Grid container
34-
direction="row" item xs={7} spacing={3}>
82+
direction="row" item xs={7} spacing={SPACING}>
83+
<Grid item xs={6}
84+
alignContent="center"
85+
justify="center">
86+
<InputLabel>Isolationsdicke</InputLabel>
87+
</Grid>
3588
<Grid item xs={6}>
36-
<InputLabel>Druckverlust pro Output</InputLabel>
37-
{/*<TextField id="outlined-basic" label="Isolationsdicke" type="number" variant="outlined" placeholder="127.30"/>*/}
89+
<TextField id="outlined-basic" type="number" variant="outlined" placeholder="127.30"
90+
value={insulationThickness}
91+
onChange={(e) => dispatchChange(e.target.value, "insulationThickness")}/>
92+
3893
</Grid>
94+
</Grid>
95+
96+
<Grid container
97+
direction="row" item xs={7} spacing={SPACING}>
3998
<Grid item xs={6}>
40-
<TextField id="outlined-basic" variant="outlined" type="number"
41-
placeholder="127.30"/>
99+
<InputLabel>Netzinvestitionskosten Template (f(Durchmesser) = [€/m])</InputLabel>
100+
</Grid>
101+
<Grid item xs={6}>
102+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="3*d"
103+
value={gridInvestCostTemplate}
104+
onChange={(e) => dispatchChange(e.target.value, "gridInvestCostTemplate")}/>
105+
42106
</Grid>
43107
</Grid>
44108

45109
<Grid container
46-
direction="row" item xs={7} spacing={3}>
110+
direction="row" item xs={7} spacing={SPACING}>
47111
<Grid item xs={6}>
48-
<InputLabel>Isolationsdicke</InputLabel>
112+
<InputLabel>Netzoperationskosten Template (f(Netzinvestitionskosten) = [€/a])</InputLabel>
113+
</Grid>
114+
<Grid item xs={6}>
115+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="3*cost"
116+
value={gridOperatingCostTemplate}
117+
onChange={(e) => dispatchChange(e.target.value, "gridOperatingCostTemplate")}/>
118+
119+
</Grid>
120+
</Grid>
121+
122+
<Grid container
123+
direction="row" item xs={7} spacing={SPACING}>
124+
<Grid item xs={6}>
125+
<InputLabel>Pumpeninvestitionskosten Template (f(Leistung) = [€/kW])</InputLabel>
126+
</Grid>
127+
<Grid item xs={6}>
128+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="3*d"
129+
value={pumpInvestCostTemplate}
130+
onChange={(e) => dispatchChange(e.target.value, "pumpInvestCostTemplate")}/>
131+
132+
</Grid>
133+
</Grid>
134+
135+
<Grid container
136+
direction="row" item xs={7} spacing={SPACING}>
137+
<Grid item xs={6}>
138+
<InputLabel>Heizkosten [€/kWh])</InputLabel>
139+
</Grid>
140+
<Grid item xs={6}>
141+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="0.12"
142+
value={heatGenerationCost}
143+
onChange={(e) => dispatchChange(e.target.value, "heatGenerationCost")}/>
144+
145+
</Grid>
146+
</Grid>
147+
148+
<Grid container
149+
direction="row" item xs={7} spacing={SPACING}>
150+
<Grid item xs={6}>
151+
<InputLabel>Lebensspanne der Ressourcen [a]</InputLabel>
152+
</Grid>
153+
<Grid item xs={6}>
154+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="25"
155+
value={lifespanOfResources}
156+
onChange={(e) => dispatchChange(e.target.value, "lifespanOfResources")}/>
157+
158+
</Grid>
159+
</Grid>
160+
161+
<Grid container
162+
direction="row" item xs={7} spacing={SPACING}>
163+
<Grid item xs={6}>
164+
<InputLabel>Weighted Average Cost of Capital [%]</InputLabel>
165+
</Grid>
166+
<Grid item xs={6}>
167+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="15"
168+
value={wacc}
169+
onChange={(e) => dispatchChange(e.target.value, "wacc")}/>
170+
171+
</Grid>
172+
</Grid>
173+
174+
<Grid container
175+
direction="row" item xs={7} spacing={SPACING}>
176+
<h3>Pumpen</h3>
177+
</Grid>
178+
179+
<Grid container
180+
direction="row" item xs={7} spacing={SPACING}>
181+
<Grid item xs={6}>
182+
<InputLabel>Elektrizitätskosten Pumpstation [ct/kWh]</InputLabel>
183+
</Grid>
184+
<Grid item xs={6}>
185+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="15"
186+
value={electricityCost}
187+
onChange={(e) => dispatchChange(e.target.value, "electricityCost")}/>
188+
189+
</Grid>
190+
</Grid>
191+
<Grid container
192+
direction="row" item xs={7} spacing={SPACING}>
193+
<Grid item xs={6}>
194+
<InputLabel>Elektrische Effizienz (Pumpe)</InputLabel>
195+
</Grid>
196+
<Grid item xs={6}>
197+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="15"
198+
value={electricalEfficiency}
199+
onChange={(e) => dispatchChange(e.target.value, "electricalEfficiency")}/>
200+
201+
</Grid>
202+
</Grid>
203+
<Grid container
204+
direction="row" item xs={7} spacing={SPACING}>
205+
<Grid item xs={6}>
206+
<InputLabel>Hydraulische Effizienz (Pumpe)</InputLabel>
49207
</Grid>
50208
<Grid item xs={6}>
51-
<TextField id="outlined-basic" type="number" variant="outlined" placeholder="127.30"/>
209+
<TextField id="outlined-basic" type="text" variant="outlined" placeholder="15"
210+
value={hydraulicEfficiency}
211+
onChange={(e) => dispatchChange(e.target.value, "hydraulicEfficiency")}/>
52212

53213
</Grid>
54214
</Grid>
55215

56216
<Grid container
57-
direction="row" item xs={7} spacing={3}>
217+
direction="row" item xs={7} spacing={SPACING}>
58218
<Grid item xs={6}>
59219
<InputLabel>Temperaturreihe</InputLabel>
60220
</Grid>
@@ -63,7 +223,7 @@ export const MetaDataContainer = ({temperatureKey, setTemperatureKey}: Propertie
63223
</Grid>
64224
</Grid>
65225

66-
<Grid container direction="row" item xs={7} spacing={1}>
226+
<Grid container direction="row" item xs={7} spacing={SPACING}>
67227
<Grid item xs={12}>
68228
<Button variant="contained" onClick={() => {
69229
}}>

src-frontend/src/defaultConfig.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src-frontend/src/models.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ export interface MassenstromResponse {
5252
massenstrom: number[]
5353
}
5454

55+
export interface OptimizationMetadata {
56+
insulationThickness: number,
57+
gridInvestCostTemplate: String, // f(Durchmesser) = y [€/m]
58+
gridOperatingCostTemplate: String, // f(gridInvestCost) = y [€/year]
59+
pumpInvestCostTemplate: String, // f(Leistung) = y [€/kW]
60+
heatGenerationCost: number, // €/kWh [for calculating heat loss]
61+
lifespanOfResources: number, // Jahre
62+
wacc: number, // Weighted Average Cost of Capital in %
63+
electricityCost: number, // ct/kWh [for pump station]
64+
electricalEfficiency: number, // for pump
65+
hydraulicEfficiency: number, // for pump
66+
}
67+
5568

5669
export const instanceOfHotWaterGrid = (object: any): object is HotWaterGrid => {
5770
if (!object) {

src-frontend/src/utils/defaults.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {MassenstromResponse, NodeElements, OptimizationMetadata} from "../models";
2+
3+
export const defaultOptimizationMetadata: OptimizationMetadata = {
4+
insulationThickness: 0.0,
5+
gridInvestCostTemplate: "", // f(Durchmesser) = y [€/m]
6+
gridOperatingCostTemplate: "", // f(gridInvestCost) = y [€/year]
7+
pumpInvestCostTemplate: "", // f(Leistung) = y [€/kW]
8+
heatGenerationCost: 0.0, // €/kWh [for calculating heat loss]
9+
lifespanOfResources: 0.0, // Jahre
10+
wacc: 0.0, // Weighted Average Cost of Capital in %
11+
electricityCost: 0.0, // ct/kWh [for pump station]
12+
electricalEfficiency: 0.0, // for pump
13+
hydraulicEfficiency: 0.0, // for pump
14+
}
15+
16+
export const defaultMassenstrom: MassenstromResponse = {
17+
temperatures: [],
18+
flowInTemperatures: [],
19+
flowOutTemperatures: [],
20+
energyHeatDemand: [],
21+
massenstrom: []
22+
}
23+
24+
export const defaultNodeElements: NodeElements = {
25+
inputNodes: [],
26+
intermediateNodes: [],
27+
outputNodes: []
28+
}
29+
30+
export const defaultTemperatureKey: string = ""

0 commit comments

Comments
 (0)