Source code for stemp_abw.models

import random
from uuid import uuid4

from django.db import models
from django.db.models import Sum
from django.contrib.gis.db import models as geomodels
from django.contrib.postgres.fields import JSONField
from django.utils import timezone
from stemp_abw.app_settings import labels


# class MapLayers(models.Model):
#     model_label = models.CharField(max_length=20)
#     caption = models.CharField(max_length=50)
#     description = models.CharField(max_length=100)

#############################
# Layer models (status quo) #
#############################

[docs]class LayerModel(models.Model):
[docs] class Meta: abstract = True
@property def name(self): raise NotImplementedError def __str__(self): return '{name} Objekt ({pk_name}={pk})'.format( name=labels()['layers'][self.name]['title'], pk_name=self._meta.pk.name, pk=self.pk)
[docs]class RpAbwBound(LayerModel): name = 'rpabw' geom = geomodels.MultiLineStringField(srid=4326, null=True)
[docs]class RegMun(LayerModel): name = 'reg_mun' ags = models.IntegerField(primary_key=True) geom = geomodels.MultiPolygonField(srid=3035) geom_centroid = geomodels.PointField(srid=3035, null=True) gen = models.CharField(max_length=254)
[docs]class RegMunPop(RegMun): """This is a proxy model for RegMun which got same relations to the DB table but changes the model name. This is needed to load the appropriate DetailView when clicking on a map feature (serialized property in the data view). - See Also: https://github.com/rl-institut/WAM_APP_stemp_abw/issues/2 - All other model classes which heir from RegMun work like this. """ name = 'reg_mun_pop' class Meta: proxy = True @property def pop(self): return self.mundata.pop_2017 @property def pop_region(self): return MunData.objects.aggregate(Sum('pop_2017'))['pop_2017__sum']
[docs]class RegMunPopDensity(RegMunPop): name = 'reg_mun_pop_density' class Meta: proxy = True @property def pop_density(self): return round(self.mundata.pop_2017 / self.mundata.area) @property def area_region(self): return MunData.objects.aggregate(Sum('area'))['area__sum'] @property def pop_density_region(self): return round(self.pop_region / self.area_region)
[docs]class RegMunGenEnergyRe(RegMun): name = 'reg_mun_gen_energy_re' class Meta: proxy = True @property def gen_energy_re(self): return round((self.mundata.gen_el_energy_wind + self.mundata.gen_el_energy_pv_roof + self.mundata.gen_el_energy_pv_ground + self.mundata.gen_el_energy_hydro + self.mundata.gen_el_energy_bio) / 1e3) @property def gen_energy_re_region(self): result = MunData.objects.aggregate(Sum('gen_el_energy_wind'))['gen_el_energy_wind__sum'] + \ MunData.objects.aggregate(Sum('gen_el_energy_pv_roof'))['gen_el_energy_pv_roof__sum'] + \ MunData.objects.aggregate(Sum('gen_el_energy_pv_ground'))['gen_el_energy_pv_ground__sum'] + \ MunData.objects.aggregate(Sum('gen_el_energy_hydro'))['gen_el_energy_hydro__sum'] + \ MunData.objects.aggregate(Sum('gen_el_energy_bio'))['gen_el_energy_bio__sum'] return round(result / 1e3)
[docs]class RegMunDemElEnergy(RegMun): name = 'reg_mun_dem_el_energy' class Meta: proxy = True @property def dem_el_energy(self): return round((self.mundata.dem_el_energy_hh + self.mundata.dem_el_energy_rca + self.mundata.dem_el_energy_ind) / 1e3) @property def dem_el_energy_region(self): result = MunData.objects.aggregate(Sum('dem_el_energy_hh'))['dem_el_energy_hh__sum'] + \ MunData.objects.aggregate(Sum('dem_el_energy_rca'))['dem_el_energy_rca__sum'] + \ MunData.objects.aggregate(Sum('dem_el_energy_ind'))['dem_el_energy_ind__sum'] return round(result / 1e3)
[docs]class RegMunEnergyReElDemShare(RegMunGenEnergyRe, RegMunDemElEnergy): name = 'reg_mun_energy_re_el_dem_share' class Meta: proxy = True @property def energy_re_el_dem_share(self): return round(self.gen_energy_re / self.dem_el_energy * 100) @property def energy_re_el_dem_share_region(self): return round(self.gen_energy_re_region / self.dem_el_energy_region * 100)
[docs]class RegMunGenEnergyRePerCapita(RegMunGenEnergyRe, RegMunPop): name = 'reg_mun_gen_energy_re_per_capita' class Meta: proxy = True @property def gen_energy_re_per_capita(self): return round(self.gen_energy_re * 1e3 / self.mundata.pop_2017, 1) @property def gen_energy_re_per_capita_region(self): return round(self.gen_energy_re_region * 1e3 / self.pop_region, 1)
[docs]class RegMunGenEnergyReDensity(RegMunGenEnergyRe, RegMunPopDensity): name = 'reg_mun_gen_energy_re_density' class Meta: proxy = True @property def gen_energy_re_density(self): return round(self.gen_energy_re * 1e3 / self.mundata.area, 1) @property def gen_energy_re_density_region(self): return round(self.gen_energy_re_region * 1e3 / self.area_region, 1)
[docs]class RegMunGenCapRe(RegMun): name = 'reg_mun_gen_cap_re' class Meta: proxy = True @property def gen_cap_re(self): return round(self.mundata.gen_capacity_wind + self.mundata.gen_capacity_pv_roof_large + self.mundata.gen_capacity_pv_ground + self.mundata.gen_capacity_hydro + self.mundata.gen_capacity_bio) @property def gen_cap_re_region(self): result = MunData.objects.aggregate(Sum('gen_capacity_wind'))['gen_capacity_wind__sum'] + \ MunData.objects.aggregate(Sum('gen_capacity_pv_roof_large'))['gen_capacity_pv_roof_large__sum'] + \ MunData.objects.aggregate(Sum('gen_capacity_pv_ground'))['gen_capacity_pv_ground__sum'] + \ MunData.objects.aggregate(Sum('gen_capacity_hydro'))['gen_capacity_hydro__sum'] + \ MunData.objects.aggregate(Sum('gen_capacity_bio'))['gen_capacity_bio__sum'] return round(result)
[docs]class RegMunGenCapReDensity(RegMunGenCapRe, RegMunPopDensity): name = 'reg_mun_gen_cap_re_density' class Meta: proxy = True @property def gen_cap_re_density(self): return round(self.gen_cap_re / self.mundata.area, 2) @property def gen_cap_re_density_region(self): return round(self.gen_cap_re_region / self.area_region, 2)
[docs]class RegMunGenCountWindDensity(RegMunPopDensity): name = 'reg_mun_gen_count_wind_density' class Meta: proxy = True @property def gen_count_wind_density(self): return round(self.mundata.gen_count_wind / self.mundata.area, 2) @property def gen_count_wind_density_region(self): result = MunData.objects.aggregate(Sum('gen_count_wind'))['gen_count_wind__sum'] return round(result / self.area_region, 2)
[docs]class RegMunDemElEnergyPerCapita(RegMunDemElEnergy, RegMunPop): name = 'reg_mun_dem_el_energy_per_capita' class Meta: proxy = True @property def dem_el_energy_per_capita(self): return round(self.dem_el_energy * 1e6 / self.mundata.pop_2017) @property def dem_el_energy_per_capita_region(self): return round(self.dem_el_energy_region * 1e6 / self.pop_region)
[docs]class RegMunDemThEnergy(RegMun): name = 'reg_mun_dem_th_energy' class Meta: proxy = True @property def dem_th_energy(self): return round((self.mundata.dem_th_energy_hh + self.mundata.dem_th_energy_rca) / 1e3) @property def dem_th_energy_region(self): result = MunData.objects.aggregate(Sum('dem_th_energy_hh'))['dem_th_energy_hh__sum'] + \ MunData.objects.aggregate(Sum('dem_th_energy_rca'))['dem_th_energy_rca__sum'] return round(result / 1e3)
[docs]class RegMunDemThEnergyPerCapita(RegMunDemThEnergy, RegMunPopDensity): name = 'reg_mun_dem_th_energy_per_capita' class Meta: proxy = True @property def dem_th_energy_per_capita(self): return round(self.dem_th_energy * 1e6 / self.mundata.pop_2017) @property def dem_th_energy_per_capita_region(self): return round(self.dem_th_energy_region * 1e6 / self.pop_region)
# TODO: Add docstrings for models below
[docs]class RegWaterProtArea(LayerModel): name = 'reg_water_prot_area' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) schutzzone = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) amtsblatt = models.CharField(max_length=254, null=True)
[docs]class RegBirdProtArea(LayerModel): name = 'reg_bird_prot_area' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegBirdProtAreaB200(LayerModel): name = 'reg_bird_prot_area_b200' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegNatureProtArea(LayerModel): name = 'reg_nature_prot_area' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) schutzzone = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegLandscProtAreaParts(LayerModel): name = 'reg_landsc_prot_area_parts' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True)
[docs]class RegResidArea(LayerModel): name = 'reg_resid_area' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegResidAreaB500(LayerModel): name = 'reg_resid_area_b500' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegPrioAreaFloodProt(LayerModel): name = 'reg_prio_area_flood_prot' geom = geomodels.MultiPolygonField(srid=3035, null=True) bemerkunge = models.CharField(max_length=254, null=True) bezeich_2 = models.CharField(max_length=254, null=True) bezeich_3 = models.CharField(max_length=254, null=True)
[docs]class RegSurfaceWater(LayerModel): """Surface water Oberflächengewässer (Fließgewässer 1. Ordnung, stehende Gewässer > 1 ha). """ name = 'reg_surface_water' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegPrioAreaCult(LayerModel): name = 'reg_prio_area_cult' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegForest(LayerModel): name = 'reg_forest' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegFFHProtArea(LayerModel): name = 'reg_ffh_prot_area' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegResidAreaB1000(LayerModel): name = 'reg_resid_area_b1000' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegPrioAreaWEC(LayerModel): name = 'reg_prio_area_wec' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True) bezeich_3 = models.CharField(max_length=254, null=True)
[docs]class GenWEC(LayerModel): name = 'gen_wec' geom = geomodels.MultiPointField(srid=3035, null=True)
[docs]class GenPVGround(LayerModel): name = 'gen_pv_ground' geom = geomodels.MultiPointField(srid=3035, null=True)
[docs]class RegDeadZoneHard(LayerModel): name = 'reg_dead_zone_hard' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegDeadZoneSoft(LayerModel): name = 'reg_dead_zone_soft' geom = geomodels.MultiPolygonField(srid=3035, null=True)
# TODO: New layers below -> insert data into DB!
[docs]class RegFFHProtAreaB(LayerModel): name = 'reg_ffh_prot_area_b' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegLandscProtArea(LayerModel): name = 'reg_landsc_prot_area' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegNaturePark(LayerModel): name = 'reg_nature_park' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegBioReserve(LayerModel): name = 'reg_bio_reserve' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) schutzzone = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegRetentAreaEcosys(LayerModel): name = 'reg_retent_area_ecosys' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegPrioAreaNature(LayerModel): name = 'reg_prio_area_nature' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegNatureMonum(LayerModel): name = 'reg_nature_monum' geom = geomodels.MultiPolygonField(srid=3035, null=True) gebietsnam = models.CharField(max_length=254, null=True) gebietsnum = models.CharField(max_length=254, null=True) rechtsgrun = models.CharField(max_length=254, null=True) erfassungs = models.CharField(max_length=254, null=True) info_konta = models.CharField(max_length=254, null=True)
[docs]class RegPrioAreaWater(LayerModel): name = 'reg_prio_area_water' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegPrioAreaAgri(LayerModel): name = 'reg_prio_area_agri' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegRetentAreaAgri(LayerModel): name = 'reg_retent_area_agri' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegPrioAreaRes(LayerModel): name = 'reg_prio_area_res' geom = geomodels.MultiPolygonField(srid=3035, null=True) bezeich_2 = models.CharField(max_length=254, null=True)
[docs]class RegInfrasRailway(LayerModel): name = 'reg_infras_railway' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegInfrasRoad(LayerModel): name = 'reg_infras_road' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegInfrasHvgrid(LayerModel): name = 'reg_infras_hvgrid' geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class RegInfrasAviation(LayerModel): name = 'reg_infras_aviation' geom = geomodels.MultiPolygonField(srid=3035, null=True)
########################## # Layer models (results) # ##########################
[docs]class ResultLayerModel(RegMun): """This model is a dummy proxy model for displaying layer results Notes ----- It bases the municipalities' model :class:`stemp_abw.models.RegMun` which is required (geom, names) for all result layers. The result data column cannot be defined using property decorator as the results are stored in :class:`stemp_abw.results.results.Results` which is connected to a session and not accessible from models. Instead, the result column is dynamically added in the serial view :class:`stemp_abw.views.serial_views.GeoJSONResultLayerData`. """ name = None class Meta: proxy = True
[docs] @classmethod def name_init(cls, name): """Class method to set model name property which is needed to match the layer configuration (config/layers_results.cfg) and control (associated layer switch in GUI). Parameters ---------- name : :obj:`str` Model name as used in config/layers_results.cfg """ cls.name = name return cls
# TODO: Alter extended classes to result classes
[docs]class RegMunEnergyReElDemShareResult(RegMun): name = 'reg_mun_energy_re_el_dem_share_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunGenEnergyReResult(RegMun): name = 'reg_mun_gen_energy_re_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunGenEnergyReDensityResult(RegMun): name = 'reg_mun_gen_energy_re_density_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunGenCapReResult(RegMun): name = 'reg_mun_gen_cap_re_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunGenCapReDensityResult(RegMun): name = 'reg_mun_gen_cap_re_density_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunGenCountWindDensityResult(RegMun): name = 'reg_mun_gen_count_wind_density_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunDemElEnergyResult(RegMun): name = 'reg_mun_dem_el_energy_result' class Meta: proxy = True
# TODO: Alter extended class to result class
[docs]class RegMunDemElEnergyPerCapitaResult(RegMun): name = 'reg_mun_dem_el_energy_per_capita_result' class Meta: proxy = True
################################ # Layer models (results DELTA) # ################################ # TODO: This is a test delta layer
[docs]class RegMunEnergyReElDemShareDeltaResult(RegMun): name = 'reg_mun_energy_re_el_dem_share_result_delta' class Meta: proxy = True @property def energy_re_el_dem_share_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunGenEnergyReDeltaResult(RegMun): name = 'reg_mun_gen_energy_re_result_delta' class Meta: proxy = True @property def gen_energy_re_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunGenEnergyReDensityDeltaResult(RegMun): name = 'reg_mun_gen_energy_re_density_result_delta' class Meta: proxy = True @property def gen_energy_re_density_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunGenCapReDeltaResult(RegMun): name = 'reg_mun_gen_cap_re_result_delta' class Meta: proxy = True @property def gen_cap_re_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunGenCapReDensityDeltaResult(RegMun): name = 'reg_mun_gen_cap_re_density_result_delta' class Meta: proxy = True @property def gen_cap_re_density_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunGenCountWindDensityDeltaResult(RegMun): name = 'reg_mun_gen_count_wind_density_result_delta' class Meta: proxy = True @property def gen_count_wind_density_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunDemElEnergyDeltaResult(RegMun): name = 'reg_mun_dem_el_energy_result_delta' class Meta: proxy = True @property def dem_el_energy_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
# TODO: This is a test delta layer
[docs]class RegMunDemElEnergyPerCapitaDeltaResult(RegMun): name = 'reg_mun_dem_el_energy_per_capita_result_delta' class Meta: proxy = True @property def dem_el_energy_per_capita_result_delta(self): return str(random.randrange(-100, 100, 1)) + '%'
############### # Data models # ############### # The following tables contain initial data only, data that result from # adjustments in the tool are not saved to these tables.
[docs]class MunData(models.Model): """Statistical data of municipalities (status quo) Attributes ---------- ags : Municipality key (Amtlicher Gemeindeschlüssel), refers to :class:`stemp_abw.models.RegMun` area : Total area in km^2 pop_2011 : Population (2011) according to Zensus pop_2017 : Population (2017) according to GV-ISys pop_2030 : Population (2030) forecast according to MLV Sachsen-Anhalt pop_2050 : Population (2050), linearly extrapolated using 2017 and 2030 total_living_space : Total living space (Wohnfläche) in m^2 gen_count_wind : Count of wind turbines gen_count_pv_roof_small : Count of small (<=30 kVA) roof-mounted PV systems gen_count_pv_roof_large : Count of large (>30 kVA, <=300 kVA) roof-mounted PV systems gen_count_pv_ground : Count of ground-mounted PV systems (>300 kVA) gen_count_hydro : Count of run-of-river systems gen_count_bio : Count of biogas/biomass systems gen_count_conventional_large : Count of large (>=10 MW) conventional plants in MW gen_count_conventional_small : Count of small (<10 MW) conventional plants in MW. Simplified assumption: 1 plant per municipality gen_count_sewage_landfill_gas : Count of sewage/landfill gas systems gen_count_storage : Count of storages gen_capacity_wind : Total nominal power of wind turbines in MVA gen_capacity_pv_roof_small : Total nominal power of small roof-mounted PV systems in MW gen_capacity_pv_roof_large : Total nominal power of large roof-mounted PV systems in MW gen_capacity_pv_ground : Total nominal power of ground-mounted PV systems in MW gen_capacity_hydro : Total nominal power of run-of-river systems in MW gen_capacity_bio : Total nominal power of biogas/biomass systems in MW gen_capacity_conventional_large : Total nominal power of large (>=10 MW) conventional plants in MW gen_capacity_conventional_small : Total nominal power of small (<10 MW) conventional plants in MW gen_capacity_sewage_landfill_gas : Total nominal power of sewage/landfill gas systems in MW gen_capacity_storage : Total storage capacity of storages in MWh gen_el_energy_wind : Annual el. energy fed in by wind turbines in MWh gen_el_energy_pv_roof : Annual el. energy fed in by roof-mounted PV systems in MWh gen_el_energy_pv_ground: Annual el. energy fed in by ground-mounted PV systems in MWh gen_el_energy_hydro : Annual el. energy fed in by run-of-river systems in MWh gen_el_energy_bio : Annual el. energy fed in by biomass/biogas systems incl. sewage and landfill gas in MWh gen_el_energy_conventional : Annual el. energy fed in by conventional power plants in MWh (large >=10 MW and small <10 MW). dem_el_peak_load_hh : El. peak demand of households in MW dem_el_peak_load_rca : El. peak demand of retail, commercial and agricultural sector (GHD) in MW dem_el_peak_load_ind : El. peak demand of industry in MW dem_el_energy_hh : Annual el. energy consumed by households in MWh dem_el_energy_rca : Annual el. energy consumed by retail, commercial and agricultural sector (GHD) in MWh dem_el_energy_ind : Annual el. energy consumed by industry in MWh dem_th_peak_load_hh : Heat peak demand of households in MW dem_th_peak_load_rca : Heat peak demand of retail, commercial and agricultural sector (GHD) in MW dem_th_peak_load_ind : Heat peak demand of industry in MW dem_th_energy_hh : Annual heat consumed by households in MWh dem_th_energy_hh_efh : Annual heat consumed by single-family households (Einfamilienhäuser) in MWh dem_th_energy_hh_mfh : Annual heat consumed by multi-family households (Mehrfamilienhäuser) in MWh dem_th_energy_hh_efh_spec : Annual heat consumed by single-family households (Einfamilienhäuser), area-specific in kWh/m^2 dem_th_energy_hh_mfh_spec : Annual heat consumed by multi-family households (Mehrfamilienhäuser), area-specific in kWh/m^2 dem_th_energy_rca : Annual heat consumed by retail, commercial and agricultural sector (GHD) in MWh dem_th_energy_ind : Annual heat consumed by industry in MWh dem_th_energy_hh_per_capita : Annual heat demand of households per capita in MWh dem_th_energy_total_per_capita : Annual heat demand of households, retail, commercial and agricultural sector per capita in MWh reg_prio_area_wec_area : Area sum of priority areas (parts) in ha reg_prio_area_wec_count : Count of priority area (parts) """ ags = models.OneToOneField(RegMun, primary_key=True, on_delete=models.DO_NOTHING) area = models.FloatField(null=True) pop_2011 = models.IntegerField(null=True) pop_2017 = models.IntegerField(null=True) pop_2030 = models.IntegerField(null=True) pop_2050 = models.IntegerField(null=True) total_living_space = models.FloatField(null=True) gen_count_wind = models.FloatField(null=True) gen_count_pv_roof_small = models.FloatField(null=True) gen_count_pv_roof_large = models.FloatField(null=True) gen_count_pv_ground = models.FloatField(null=True) gen_count_hydro = models.FloatField(null=True) gen_count_bio = models.FloatField(null=True) gen_count_conventional_large = models.FloatField(null=True) gen_count_conventional_small = models.FloatField(null=True) gen_count_sewage_landfill_gas = models.FloatField(null=True) gen_count_storage = models.FloatField(null=True) gen_capacity_wind = models.FloatField(null=True) gen_capacity_pv_roof_small = models.FloatField(null=True) gen_capacity_pv_roof_large = models.FloatField(null=True) gen_capacity_pv_ground = models.FloatField(null=True) gen_capacity_hydro = models.FloatField(null=True) gen_capacity_bio = models.FloatField(null=True) gen_capacity_conventional_large = models.FloatField(null=True) gen_capacity_conventional_small = models.FloatField(null=True) gen_capacity_sewage_landfill_gas = models.FloatField(null=True) gen_capacity_storage = models.FloatField(null=True) gen_el_energy_wind = models.FloatField(null=True) gen_el_energy_pv_roof = models.FloatField(null=True) gen_el_energy_pv_ground = models.FloatField(null=True) gen_el_energy_hydro = models.FloatField(null=True) gen_el_energy_bio = models.FloatField(null=True) gen_el_energy_conventional = models.FloatField(null=True) dem_el_peak_load_hh = models.FloatField(null=True) dem_el_peak_load_rca = models.FloatField(null=True) dem_el_peak_load_ind = models.FloatField(null=True) dem_el_energy_hh = models.FloatField(null=True) dem_el_energy_rca = models.FloatField(null=True) dem_el_energy_ind = models.FloatField(null=True) dem_th_peak_load_hh = models.FloatField(null=True) dem_th_peak_load_rca = models.FloatField(null=True) dem_th_peak_load_ind = models.FloatField(null=True) dem_th_energy_hh = models.FloatField(null=True) dem_th_energy_hh_efh = models.FloatField(null=True) dem_th_energy_hh_mfh = models.FloatField(null=True) dem_th_energy_hh_efh_spec = models.FloatField(null=True) dem_th_energy_hh_mfh_spec = models.FloatField(null=True) dem_th_energy_rca = models.FloatField(null=True) dem_th_energy_ind = models.FloatField(null=True) dem_th_energy_hh_per_capita = models.FloatField(null=True) dem_th_energy_total_per_capita = models.FloatField(null=True) reg_prio_area_wec_area = models.FloatField(null=True) reg_prio_area_wec_count = models.IntegerField(null=True)
[docs]class FeedinTs(models.Model): """Feedin timeseries (hourly, partly normalized - see columns) Attributes ---------- id : DB id timestamp : timestamp ags : Municipality key (Amtlicher Gemeindeschlüssel), refers to :class:`stemp_abw.models.RegMun` pv_ground : Photovoltaics (ground-mounted systems) normalized (relative values) pv_roof : Photovoltaics (roof-mounted systems) normalized (relative values) hydro : Run-of-river plants normalized (relative values) wind_sq : Wind turbines (status quo) normalized (relative values) wind_fs : Wind turbines (future scenarios) normalized (relative values) bio : Biogas/biomass plants (incl. landfill and sewage) normalized (relative values) conventional : Conventional plants (>=10 MW: power-led, <10 MW: heat-led) NOT normalized (absolute values) Notes ----- Timeseries are stored per timestep and ags -> one dataset is uniquely identified by timestamp and municipality's ags. """ id = models.BigAutoField(primary_key=True) timestamp = models.DateTimeField(db_index=True) ags = models.ForeignKey(RegMun, on_delete=models.DO_NOTHING) pv_ground = models.FloatField(blank=True, null=True) pv_roof = models.FloatField(blank=True, null=True) hydro = models.FloatField(blank=True, null=True) wind_sq = models.FloatField(blank=True, null=True) wind_fs = models.FloatField(blank=True, null=True) bio = models.FloatField(blank=True, null=True) conventional = models.FloatField(blank=True, null=True)
[docs]class Powerplant(models.Model): """Power plants (status quo) Attributes ---------- id : DB id ags : Municipality key (Amtlicher Gemeindeschlüssel), refers to :class:`stemp_abw.models.RegMun` capacity : Nominal power in MW chp : Indicates if plant is of type CHP (combined heat and power) com_month : Month of commissioning com_year : Year of commissioning comment : Comment decom_month : Month of decommissioning decom_year : Year of decommissioning efficiency : Efficiency energy_source_level_1 : Indicates if renewable or conventional energy_source_level_2 : Indicates energy source energy_source_level_3 : More specific energy source geometry : Geometry SRID: EPSG:4326 (WGS84) technology : Technology thermal_capacity : Nominal thermal nominal power, if applicable coastdat2 : No. of coastdat2 weather cell (reegis) capacity_in : Capacity of inflow federal_state : Abbreviation of federal state name (2 letters according to ISO 3166-2:DE) Notes ----- Most of the attributes correspond to the OPSD dataset, some were added by reegis. """ id = models.BigIntegerField(primary_key=True) ags = models.ForeignKey(RegMun, on_delete=models.DO_NOTHING) capacity = models.FloatField(blank=True, null=True) chp = models.TextField(blank=True, null=True) com_month = models.FloatField(blank=True, null=True) com_year = models.FloatField(blank=True, null=True) comment = models.TextField(blank=True, null=True) decom_month = models.BigIntegerField(blank=True, null=True) decom_year = models.BigIntegerField(blank=True, null=True) efficiency = models.FloatField(blank=True, null=True) energy_source_level_1 = models.TextField(blank=True, null=True) energy_source_level_2 = models.TextField(blank=True, null=True) energy_source_level_3 = models.TextField(blank=True, null=True) geometry = geomodels.PointField(blank=True, null=True) state = models.TextField(blank=True, null=True) technology = models.TextField(blank=True, null=True) thermal_capacity = models.FloatField(blank=True, null=True) coastdat2 = models.FloatField(blank=True, null=True) capacity_in = models.FloatField(blank=True, null=True) federal_state = models.TextField(blank=True, null=True)
[docs]class DemandTs(models.Model): """Demand timeseries (hourly, partly normalized - see columns) Attributes ---------- id : DB id timestamp : timestamp ags : Municipality key (Amtlicher Gemeindeschlüssel), refers to :class:`stemp_abw.models.RegMun` el_hh : El. demand of households el_rca : El. demand of retail, commercial and agricultural sector (GHD) el_ind : El. demand of industry th_hh_efh : Heat demand of households in single-family houses (Einfamilienhäuser), absolute, in MW th_hh_mfh : Heat demand of households in multi-family houses (Mehrfamilienhäuser), absolute, in MW th_hh_efh_spec : Heat demand of households in single-family houses (Einfamilienhäuser), area-specific in kWh/m^2 th_hh_mfh_spec : Heat demand of households in multi-family houses (Mehrfamilienhäuser), area-specific in kWh/m^2 th_rca : Heat demand of retail, commercial and agricultural sector (GHD) in MW th_ind : Heat demand of industry in MW Notes ----- Timeseries are stored per timestep and ags -> one dataset is uniquely identified by timestamp and municipality's ags. """ id = models.BigAutoField(primary_key=True) timestamp = models.DateTimeField(db_index=True) ags = models.ForeignKey(RegMun, on_delete=models.DO_NOTHING) el_hh = models.FloatField(blank=True, null=True) el_rca = models.FloatField(blank=True, null=True) el_ind = models.FloatField(blank=True, null=True) th_hh_efh = models.FloatField(blank=True, null=True) th_hh_mfh = models.FloatField(blank=True, null=True) th_hh_efh_spec = models.FloatField(blank=True, null=True) th_hh_mfh_spec = models.FloatField(blank=True, null=True) th_rca = models.FloatField(blank=True, null=True) th_ind = models.FloatField(blank=True, null=True)
# class Emission(models.Model): # """Emissions of technologies in kg/MWh""" # technology = models.CharField(max_length=254, null=True) # emissions_fix = models.FloatField() # emissions_variable = models.FloatField() # # class Costs(models.Model): # """Costs of technologies in €/MWh""" # technology = models.CharField(max_length=254, null=True) # costs_fix = models.FloatField() # costs_variable = models.FloatField()
[docs]class RepoweringScenario(models.Model): """Repowering scenario TODO: Add doctring """ id = models.BigAutoField(primary_key=True) name_de = models.CharField(max_length=50) desc_de = models.CharField(max_length=255, null=True) name_en = models.CharField(max_length=50) desc_en = models.CharField(max_length=255, null=True) data = JSONField(default=None, null=True)
[docs]class REPotentialAreas(models.Model): """Potential areas for renewable plants Attributes ---------- id : DB id area_params : TODO: Define format App settings for usable areas (area panel) mun_data : TODO: Define format Available potentials (per technology) TO BE SPECIFIED geom : Geometry SRID: EPSG:3035 (ETRS89/LAEA) """ name = 're_pot_areas' id = models.BigAutoField(primary_key=True) area_params = JSONField(default=None, null=True) mun_data = JSONField(default=None, null=True) geom = geomodels.MultiPolygonField(srid=3035, null=True)
[docs]class SimulationResults(models.Model): """Results of a scenario simulation Attributes ---------- id : DB id data : json Result data, format as defined <HERE> """ id = models.BigAutoField(primary_key=True) data = JSONField() def __str__(self): return self.data
[docs]class ScenarioData(models.Model): """Scenario data Attributes ---------- id : DB id data : json TODO: Define format Scenario data, format as defined <HERE> data_uuid : UUID for scenario data to quickly compare settings to avoid blowing up postgreSQL """ id = models.BigAutoField(primary_key=True) data = JSONField() data_uuid = models.UUIDField(default=uuid4, editable=False, unique=True, null=False) def __str__(self): return self.data
[docs]class Scenario(models.Model): """Scenario (energy system configuration) Attributes ---------- id : DB id created : DateTime Timestamp of creation name : String Name of scenario is_user_scenario : Bool True, if scenario was created by a user (default) data : Reference to ScenarioData results : Reference to SimulationResults re_potential_areas : Reference to REPotentialAreas repowering_scenario : Reference to RepoweringScenario """ id = models.BigAutoField(primary_key=True) created = models.DateTimeField(default=timezone.now) name = models.CharField(max_length=50, unique=True) description = models.CharField(max_length=255, null=True) is_user_scenario = models.BooleanField(default=True) data = models.ForeignKey(ScenarioData, on_delete=models.DO_NOTHING) results = models.ForeignKey(SimulationResults, on_delete=models.DO_NOTHING, null=True, default=None) re_potential_areas = models.ForeignKey(REPotentialAreas, on_delete=models.DO_NOTHING) repowering_scenario = models.ForeignKey(RepoweringScenario, on_delete=models.DO_NOTHING) def __str__(self): return f'{self.name}'