Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ensysmod/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .endpoints import users, authentication, energy_sources, datasets, energy_commodities, energy_sinks, \
energy_storages, energy_transmissions, energy_conversions, regions, ts_capacity_max, ts_operation_rate_fix, \
ts_operation_rate_max, energy_models
ts_operation_rate_max, ts_capacity_fix, energy_models

api_router = APIRouter()
api_router.include_router(authentication.router, prefix="/auth", tags=["Authentication"])
Expand All @@ -17,6 +17,7 @@
api_router.include_router(energy_transmissions.router, prefix="/transmissions", tags=["Energy Transmissions"])
api_router.include_router(energy_models.router, prefix="/models", tags=["Energy Models"])

api_router.include_router(ts_capacity_fix.router, prefix="/fix-capacities", tags=["TS Capacities Fix"])
api_router.include_router(ts_capacity_max.router, prefix="/max-capacities", tags=["TS Capacities Max"])
api_router.include_router(ts_operation_rate_fix.router, prefix="/fix-operation-rates", tags=["TS Operation Rates Fix"])
api_router.include_router(ts_operation_rate_max.router, prefix="/max-operation-rates", tags=["TS Operation Rates Max"])
2 changes: 2 additions & 0 deletions ensysmod/api/endpoints/energy_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ def create_conversion(request: schemas.EnergyConversionCreate,
detail=f"EnergyCommodity {request.commodity_unit} "
f"in dataset {request.ref_dataset} not found!")

# TODO Check commodities for conversion factors

return crud.energy_conversion.create(db=db, obj_in=request)
105 changes: 105 additions & 0 deletions ensysmod/api/endpoints/ts_capacity_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from typing import List, Optional

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from ensysmod import schemas, model, crud
from ensysmod.api import deps
from ensysmod.schemas import CapacityFix

router = APIRouter()


@router.get("/", response_model=List[schemas.CapacityFix])
def all_fix_capacities(db: Session = Depends(deps.get_db),
current: model.User = Depends(deps.get_current_user),
skip: int = 0,
limit: int = 100) -> List[schemas.CapacityFix]:
"""
Retrieve all fix capacities.
"""
return crud.capacity_fix.get_multi(db, skip=skip, limit=limit)


@router.get("/{ts_id}", response_model=schemas.CapacityFix)
def get_capacity_fix(ts_id: int,
db: Session = Depends(deps.get_db),
current: model.User = Depends(deps.get_current_user)):
"""
Retrieve a fix capacity.
"""
# TODO Check if user has permission for dataset and CapacityFix
return crud.capacity_fix.get(db, ts_id)


@router.post("/", response_model=schemas.CapacityFix)
def create_capacity_fix(request: schemas.CapacityFixCreate,
db: Session = Depends(deps.get_db),
current: model.User = Depends(deps.get_current_user)):
"""
Create a new fix capacity.
"""
component = crud.energy_component.get_by_dataset_and_name(db=db, dataset_id=request.ref_dataset,
name=request.component)
if component is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Component {request.component} not found in dataset {request.ref_dataset}!")

# TODO Check if user has permission for dataset

region = crud.region.get_by_dataset_and_name(db=db, dataset_id=request.ref_dataset, name=request.region)
if region is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Region {request.region} not found in dataset {request.ref_dataset}!")

ts = crud.capacity_fix.get_by_component_and_region(db=db, component_id=component.id, region_id=region.id)
if ts is not None:
raise HTTPException(status_code=status.HTTP_409_CONFLICT,
detail=f"CapacityFix for component {component.name} (id {component.id}) and "
f"region {region.name} (id {region.id}) already exists with id {ts.id}!")

ts_in_base: Optional[List[CapacityFix]] = crud.capacity_fix.get_by_component(db=db,
component_id=component.id)
if ts_in_base is not None:
# get maximum length fix_capacities in ts_in_base
max_length = 0
for ts_in in ts_in_base:
if ts_in.fix_capacities is not None:
max_length = max(max_length, len(ts_in.fix_capacities))

if max_length > 0 and max_length != len(request.fix_capacities):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail=f"CapacityFix for component {component.name} (id {component.id}) has a length "
f"of {max_length}. Your new time series has {len(request.fix_capacities)} "
f"elements.")

return crud.capacity_fix.create(db=db, obj_in=request)


@router.put("/{ts_id}", response_model=schemas.CapacityFix)
def update_capacity_fix(ts_id: int,
request: schemas.CapacityFixUpdate,
db: Session = Depends(deps.get_db),
current: model.User = Depends(deps.get_current_user)):
"""
Update a fix capacity.
"""
# TODO Check if user has permission for CapacityFix
ts = crud.capacity_fix.get(db=db, id=ts_id)
if ts is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"CapacityFix {ts_id} not found!")
return crud.capacity_fix.update(db=db, db_obj=ts, obj_in=request)


@router.delete("/{ts_id}", response_model=schemas.CapacityFix)
def remove_capacity_fix(ts_id: int,
db: Session = Depends(deps.get_db),
current: model.User = Depends(deps.get_current_user)):
"""
Delete a fix capacity.
"""
ts = crud.capacity_fix.get(db=db, id=ts_id)
if ts is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"CapacityFix {ts_id} not found!")
# TODO Check if user has permission for dataset
return crud.capacity_fix.remove(db=db, id=ts_id)
7 changes: 5 additions & 2 deletions ensysmod/crud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
from .energy_commodity import energy_commodity
from .energy_component import energy_component
from .energy_conversion import energy_conversion
from .energy_conversion_factor import energy_conversion_factor
from .energy_model import energy_model
from .energy_sink import energy_sink
from .energy_source import energy_source
from .energy_storage import energy_storage
from .energy_transmission import energy_transmission
from .energy_transmission_distance import energy_transmission_distance
from .region import region
from .ts_capacity_fix import capacity_fix
from .ts_capacity_max import capacity_max
from .ts_operation_rate_max import operation_rate_max
from .ts_operation_rate_fix import operation_rate_fix
from .ts_operation_rate_max import operation_rate_max
from .user import user
from .energy_model import energy_model
1 change: 0 additions & 1 deletion ensysmod/crud/base_depends_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def create(self, db: Session, *, obj_in: Union[CreateSchemaType, ModelType, dict
component = crud.energy_component.create(db, obj_in=obj_in)
obj_in_dict = jsonable_encoder(obj_in)
obj_in_dict["ref_component"] = component.id
print(obj_in_dict)
return super().create(db, obj_in=obj_in_dict)

def remove(self, db: Session, *, id: Any) -> ModelType:
Expand Down
1 change: 0 additions & 1 deletion ensysmod/crud/base_depends_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def get_by_component_and_region(self, db: Session, *, component_id: int, region_
.first()

def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:

component = crud.energy_component.get_by_dataset_and_name(db, name=obj_in.component,
dataset_id=obj_in.ref_dataset)
region = crud.region.get_by_dataset_and_name(db, name=obj_in.region, dataset_id=obj_in.ref_dataset)
Expand Down
10 changes: 9 additions & 1 deletion ensysmod/crud/energy_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ def create(self, db: Session, *, obj_in: EnergyConversionCreate) -> EnergyConver
dataset_id=obj_in.ref_dataset)
obj_in_dict = obj_in.dict()
obj_in_dict['ref_commodity_unit'] = commodity.id
return super().create(db=db, obj_in=obj_in_dict)
db_obj = super().create(db=db, obj_in=obj_in_dict)

# save energy conversion factors
for factor_create in obj_in.conversion_factors:
factor_create.ref_dataset = obj_in.ref_dataset
factor_create.ref_component = db_obj.component.id
crud.energy_conversion_factor.create(db, obj_in=factor_create)

return db_obj


energy_conversion = CRUDEnergyConversion(EnergyConversion)
48 changes: 48 additions & 0 deletions ensysmod/crud/energy_conversion_factor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from sqlalchemy.orm import Session

from ensysmod import crud
from ensysmod.crud.base import CRUDBase
from ensysmod.model import EnergyConversionFactor
from ensysmod.schemas import EnergyConversionFactorCreate, EnergyConversionFactorUpdate


# noinspection PyMethodMayBeStatic,PyArgumentList
class CRUDEnergyConversionFactor(CRUDBase[EnergyConversionFactor,
EnergyConversionFactorCreate,
EnergyConversionFactorUpdate]):
"""
CRUD operations for EnergyConversionFactor
"""

def remove_by_component(self, db: Session, component_id: int):
"""
Removes all EnergyConversionFactor entries for a given component.

:param db: Database session
:param component_id: ID of the component
"""
db.query(EnergyConversionFactor).filter(EnergyConversionFactor.ref_component == component_id).delete()

def create(self, db: Session, obj_in: EnergyConversionFactorCreate):
"""
Creates a new EnergyConversionFactor entry.

:param db: Database session
:param obj_in: EnergyConversionFactor entry
:return: Created EnergyConversionFactor entry
"""
commodity = crud.energy_commodity.get_by_dataset_and_name(db, name=obj_in.commodity,
dataset_id=obj_in.ref_dataset)

db_obj = EnergyConversionFactor(
ref_component=obj_in.ref_component,
ref_commodity=commodity.id,
conversion_factor=obj_in.conversion_factor
)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj


energy_conversion_factor = CRUDEnergyConversionFactor(EnergyConversionFactor)
1 change: 0 additions & 1 deletion ensysmod/crud/energy_source.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from sqlalchemy.orm import Session

from ensysmod import crud
from ensysmod.crud.base import CRUDBase
from ensysmod.crud.base_depends_component import CRUDBaseDependsComponent
from ensysmod.model import EnergySource
from ensysmod.schemas import EnergySourceCreate, EnergySourceUpdate
Expand Down
9 changes: 8 additions & 1 deletion ensysmod/crud/energy_transmission.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ def create(self, db: Session, *, obj_in: EnergyTransmissionCreate) -> EnergyTran
dataset_id=obj_in.ref_dataset)
obj_in_dict = obj_in.dict()
obj_in_dict['ref_commodity'] = commodity.id
return super().create(db=db, obj_in=obj_in_dict)
db_obj = super().create(db=db, obj_in=obj_in_dict)

# also create distances
for distance_create in obj_in.distances:
distance_create.ref_component = db_obj.component.id
crud.energy_transmission_distance.create(db, obj_in=distance_create)

return db_obj


energy_transmission = CRUDEnergyTransmission(EnergyTransmission)
26 changes: 26 additions & 0 deletions ensysmod/crud/energy_transmission_distance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from sqlalchemy.orm import Session

from ensysmod.crud.base import CRUDBase
from ensysmod.model import EnergyTransmissionDistance
from ensysmod.schemas import EnergyTransmissionDistanceCreate, EnergyTransmissionDistanceUpdate


# noinspection PyMethodMayBeStatic,PyArgumentList
class CRUDEnergyTransmissionDistance(CRUDBase[EnergyTransmissionDistance,
EnergyTransmissionDistanceCreate,
EnergyTransmissionDistanceUpdate]):
"""
CRUD operations for EnergyTransmissionDistance
"""

def remove_by_component(self, db: Session, component_id: int):
"""
Removes all EnergyTransmissionDistance entries for a given component.

:param db: Database session
:param component_id: ID of the component
"""
db.query(EnergyTransmissionDistance).filter(EnergyTransmissionDistance.ref_component == component_id).delete()


energy_transmission_distance = CRUDEnergyTransmissionDistance(EnergyTransmissionDistance)
14 changes: 14 additions & 0 deletions ensysmod/crud/ts_capacity_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ensysmod.crud.base_depends_timeseries import CRUDBaseDependsTimeSeries
from ensysmod.model import CapacityFix
from ensysmod.schemas import CapacityFixCreate, CapacityFixUpdate


# noinspection PyMethodMayBeStatic,PyArgumentList
class CRUDCapacityFix(CRUDBaseDependsTimeSeries[CapacityFix, CapacityFixCreate, CapacityFixUpdate]):
"""
CRUD operations for CapacityFix
"""
pass


capacity_fix = CRUDCapacityFix(CapacityFix)
10 changes: 9 additions & 1 deletion ensysmod/database/ref_base_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ def ref_component(self):
def ref_region(self):
return Column(Integer, ForeignKey("region.id"), index=True, nullable=False)

@declared_attr
def ref_region_to(self):
return Column(Integer, ForeignKey("region.id"), nullable=True)

@declared_attr
def component(self):
return relationship("EnergyComponent")

@declared_attr
def region(self):
return relationship("Region")
return relationship("Region", foreign_keys=[self.ref_region])

@declared_attr
def region_to(self):
return relationship("Region", foreign_keys=[self.ref_region_to])
4 changes: 3 additions & 1 deletion ensysmod/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
from .energy_component import EnergyComponent, EnergyComponentType, CapacityVariableDomain
from .energy_conversion import EnergyConversion
from .energy_conversion_factor import EnergyConversionFactor
from .energy_model import EnergyModel
from .energy_sink import EnergySink
from .energy_source import EnergySource
from .energy_storage import EnergyStorage
from .energy_transmission import EnergyTransmission
from .energy_transmission_distance import EnergyTransmissionDistance
from .region import Region
from .ts_capacity_fix import CapacityFix
from .ts_capacity_max import CapacityMax
from .ts_operation_rate_fix import OperationRateFix
from .ts_operation_rate_max import OperationRateMax
from .user import User
from .energy_model import EnergyModel
2 changes: 2 additions & 0 deletions ensysmod/model/energy_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class EnergyComponent(Base):
interest_rate = Column(DECIMAL, nullable=False, default=0.08)
economic_lifetime = Column(Integer, nullable=False, default=10)

shared_potential_id = Column(String, nullable=True)

# constraint capacityVariableDomain

# table constraints
Expand Down
1 change: 1 addition & 0 deletions ensysmod/model/energy_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ class EnergyConversion(Base):
# Relationships
component = relationship("EnergyComponent")
commodity_unit = relationship("EnergyCommodity", back_populates="energy_conversions")
conversion_factors = relationship("EnergyConversionFactor", back_populates="conversion")
14 changes: 12 additions & 2 deletions ensysmod/model/energy_conversion_factor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from sqlalchemy import Column, Integer, ForeignKey, DECIMAL
from sqlalchemy import Column, Integer, ForeignKey, DECIMAL, UniqueConstraint
from sqlalchemy.orm import relationship

from ensysmod.database.base_class import Base

Expand All @@ -10,6 +11,15 @@ class EnergyConversionFactor(Base):
This class is used to store the energy conversion factors for a energy conversion component.
"""
id = Column(Integer, primary_key=True, index=True)
ref_component = Column(Integer, ForeignKey("energy_component.id"), index=True, nullable=False)
ref_component = Column(Integer, ForeignKey("energy_conversion.ref_component"), index=True, nullable=False)
ref_commodity = Column(Integer, ForeignKey("energy_commodity.id"), index=True, nullable=False)
conversion_factor = Column(DECIMAL, nullable=False)

# Relationships
conversion = relationship("EnergyConversion", back_populates="conversion_factors")
commodity = relationship("EnergyCommodity")

# table constraints
__table_args__ = (
UniqueConstraint("ref_component", "ref_commodity", name="_conversion_factors_component_commodity_uc"),
)
4 changes: 3 additions & 1 deletion ensysmod/model/energy_source.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy import Column, Integer, ForeignKey, DECIMAL
from sqlalchemy.orm import relationship

from ensysmod.database.base_class import Base
Expand All @@ -13,6 +13,8 @@ class EnergySource(Base):
ref_component = Column(Integer, ForeignKey("energy_component.id"), index=True, nullable=False, primary_key=True)
ref_commodity = Column(Integer, ForeignKey("energy_commodity.id"), index=True, nullable=False)

commodity_cost = Column(DECIMAL, nullable=True)

# Relationships
component = relationship("EnergyComponent")
commodity = relationship("EnergyCommodity", back_populates="energy_sources")
Loading