Source code for basd.designer.parameter_set

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2010 - 2024, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""parameter_set provides the ParameterSet class which saves the parameter sets used
in the optimization for 3d battery system layout
"""

from dataclasses import dataclass

import numpy as np

from ..requirements import Requirements
from .basic_sets import BasicParameterSet, Overhead, SlaveUtilization
from .overhead_functions import OverheadFunctions


[docs] @dataclass(kw_only=True) class ParameterSet(BasicParameterSet): # pylint: disable=too-many-instance-attributes """Defines the parameter set for the battery system layout :param overhead: specifies the overhead functions which should be used """ overhead: OverheadFunctions requirements: Requirements
[docs] def get_maximum_module_voltage(self) -> float: """returns the minimum module voltage :return: minimum module voltage """ return self.cell.electrics.voltage.maximum * self.module.y * self.module.x
[docs] def get_height(self, bjb: bool = False) -> tuple[float, Overhead]: """returns the height of a battery system related to the parameter set :raises ValueError: stops if overhead is not set :return: return pack height and overhead dictionary """ cell_block_height = self.cell.mechanics.height cell_block_height_overhead = self.overhead.cell_block_height( self, cell_block_height ) cell_block_height += cell_block_height_overhead module_height = cell_block_height module_height_overhead = self.overhead.module_height(self, module_height) module_height += module_height_overhead string_height = module_height * self.string.z string_height_overhead = self.overhead.string_height(self, string_height) string_height += string_height_overhead pack_height = string_height * self.pack.z # if bjb should be placed in this direction if bjb: pack_height_overhead = self.overhead.pack_height(self, pack_height) else: # consider minimal value for this direction as overhead pack_height_overhead = ( (self.overhead.min_height - pack_height) if pack_height < self.overhead.min_height else 0 ) pack_height += pack_height_overhead overhead = Overhead( ( cell_block_height_overhead, np.round(100 * cell_block_height_overhead / cell_block_height), ), ( module_height_overhead, np.round(100 * module_height_overhead / module_height), ), ( string_height_overhead, np.round(100 * string_height_overhead / string_height), ), (pack_height_overhead, np.round(100 * pack_height_overhead / pack_height)), ) return pack_height, overhead
[docs] def get_length(self, bjb: bool = False) -> tuple[float, Overhead]: """returns the length of a battery system related to the parameter set :raises ValueError: stops if overhead is not set :return: return pack length and overhead dictionary """ if self.cell_rotation == 1: # 1 = 90° cell rotation cell_length = self.cell.mechanics.width else: cell_length = self.cell.mechanics.length cell_block_length = cell_length * self.cell_block.y cell_block_length_overhead = self.overhead.cell_block_length( self, cell_block_length ) cell_block_length += cell_block_length_overhead module_length = cell_block_length * self.module.y module_length_overhead = self.overhead.module_length(self, module_length) module_length += module_length_overhead string_length = module_length * self.string.y string_length_overhead = self.overhead.string_length(self, string_length) string_length += string_length_overhead pack_length = string_length * self.pack.y # if bjb should be placed in this direction if bjb: pack_length_overhead = self.overhead.pack_length(self, pack_length) else: # consider minimal value for this direction as overhead pack_length_overhead = ( (self.overhead.min_length - pack_length) if pack_length < self.overhead.min_length else 0 ) pack_length += pack_length_overhead overhead = Overhead( ( cell_block_length_overhead, np.round(100 * cell_block_length_overhead / cell_block_length), ), ( module_length_overhead, np.round(100 * module_length_overhead / module_length), ), ( string_length_overhead, np.round(100 * string_length_overhead / string_length), ), (pack_length_overhead, np.round(100 * pack_length_overhead / pack_length)), ) return pack_length, overhead
[docs] def get_width(self, bjb: bool = False) -> tuple[float, Overhead]: """returns the width of a battery system related to the parameter set :raises ValueError: stops if overhead is not set :return: return pack width and overhead dictionary """ if self.cell_rotation == 1: # 1 = 90° cell rotation cell_width = self.cell.mechanics.length else: cell_width = self.cell.mechanics.width cell_block_width = cell_width * self.cell_block.x cell_block_width_overhead = self.overhead.cell_block_width( self, cell_block_width ) cell_block_width += cell_block_width_overhead module_width = cell_block_width * self.module.x module_width_overhead = self.overhead.module_width(self, module_width) module_width += module_width_overhead string_width = module_width * self.string.x string_width_overhead = self.overhead.string_width(self, string_width) string_width += string_width_overhead pack_width = string_width * self.pack.x # if bjb should be placed in this direction if bjb: pack_width_overhead = self.overhead.pack_width(self, pack_width) else: # consider minimal value for this direction as overhead pack_width_overhead = ( (self.overhead.min_width - self.overhead.min_width) if pack_width < self.overhead.min_width else 0 ) pack_width += pack_width_overhead overhead = Overhead( ( cell_block_width_overhead, np.round(100 * cell_block_width_overhead / cell_block_width), ), ( module_width_overhead, np.round(100 * module_width_overhead / module_width), ), ( string_width_overhead, np.round(100 * string_width_overhead / string_width), ), (pack_width_overhead, np.round(100 * pack_width_overhead / pack_width)), ) return pack_width, overhead
[docs] def get_weight(self) -> tuple[float, Overhead]: """returns the weight of a battery system related to the parameter set :raises ValueError: stops if overhead is not set :return: return pack width and overhead dictionary """ cell_block_weight = ( self.cell.mechanics.weight * self.cell_block.y * self.cell_block.x ) cell_block_weight_overhead = self.overhead.cell_block_gravimetric( self, cell_block_weight ) cell_block_weight += cell_block_weight_overhead module_weight = cell_block_weight * self.module.y * self.module.x module_weight_overhead = self.overhead.module_gravimetric(self, module_weight) module_weight += module_weight_overhead string_weight = module_weight * self.string.y * self.string.x * self.string.z string_weight_overhead = self.overhead.string_gravimetric(self, string_weight) string_weight += string_weight_overhead pack_weight = string_weight * self.pack.y * self.pack.x * self.pack.z pack_weight_overhead = self.overhead.pack_gravimetric(self, pack_weight) pack_weight += pack_weight_overhead overhead = Overhead( ( cell_block_weight_overhead, np.round(100 * cell_block_weight_overhead / cell_block_weight), ), ( module_weight_overhead, np.round(100 * module_weight_overhead / module_weight), ), ( string_weight_overhead, np.round(100 * string_weight_overhead / string_weight), ), (pack_weight_overhead, np.round(100 * pack_weight_overhead / pack_weight)), ) return pack_weight, overhead
[docs] def get_slave_utilization(self, pins_per_slave: int) -> tuple[int, int]: """get_slave_utilization determines the min. and max. utilization of the slaves :param pins_per_slave: max. number of pins available on the slave :return: min. and max. utilization of the slave """ number_of_cell_blocks = self.module.x * self.module.y number_of_slaves = int(np.ceil(number_of_cell_blocks / pins_per_slave)) # For example with 22 number of cell blocks and 12 pins per slave, # the workload of 3 slaves would be 7+7+8, which would give a # different number for the min/max workload per slave. min_work_load = np.floor(number_of_cell_blocks / number_of_slaves) max_work_load = np.ceil(number_of_cell_blocks / number_of_slaves) utilization = SlaveUtilization(min_work_load, max_work_load, number_of_slaves) return utilization