diff --git a/dynamics/Dynamic.py b/dynamics/Dynamic.py index 3dfe74865f35eff044fefddd50c5df05a5b16280..af6662d5840abc90e7e06d86fd9d368ba3d56c06 100644 --- a/dynamics/Dynamic.py +++ b/dynamics/Dynamic.py @@ -26,6 +26,7 @@ import pandas as pd import pyomo.environ as pyo class GlobalDynamic: + # d_steps: length of each time step in seconds def __init__(self, d_steps): self.d_steps = d_steps self.root_dynamic = TrivialDynamic(self.d_steps, self) @@ -145,15 +146,29 @@ class Dynamic: # returns the length of the time step at the given position # position is relative to this dynamic + def step_length_p(self, position): + pass + + # returns the length of the time step at the given position in hours + # position is relative to this dynamic def step_size_p(self, position): pass # returns the length of the time step at the given index # index is relative to the root dynamic + def step_length(self, index): + pass + + # returns the length of the time step at the given index in hours + # index is relative to the root dynamic def step_size(self, index): pass # returns the length af all time steps in this dynamic + def step_lengths(self): + pass + + # returns the length af all time steps in this dynamic in hours def step_sizes(self): pass @@ -282,7 +297,7 @@ class Dynamic: # a dynamic defined by the length of each time step class TrivialDynamic(Dynamic): - # d_step: the length all time_steps + # d_steps: length of each time step in seconds def __init__(self, d_steps, global_dynamic): self.d_steps = d_steps self.global_dynamic = global_dynamic @@ -317,15 +332,24 @@ class TrivialDynamic(Dynamic): def position_of(self, index): return index - def step_size_p(self, position): + def step_length_p(self, position): return self.d_steps[position] - def step_size(self, index): + def step_size_p(self, position): + return self.d_steps[position] / 3600 + + def step_length(self, index): return self.d_steps[index] - def step_sizes(self): + def step_size(self, index): + return self.d_steps[index] / 3600 + + def step_lengths(self): return self.d_steps + def step_sizes(self): + return [d_step / 3600 for d_step in self.d_steps] + def sub_dynamic_p(self, positions): return self.global_dynamic.sub_dynamic(self, positions) @@ -386,18 +410,31 @@ class BackedDynamic(Dynamic): raise IndexError('The dynamic does not have a position for this index!') return self.indices.index(index) + def step_length_p(self, position): + if position < 0 or len(self.indices) - 1 <= position: + raise IndexError("The dynamic does not have a time step at this position!") + return sum(self.reference.step_length(index) for index in self.reference.indices_within(self.indices[position], self.indices[position + 1])) + def step_size_p(self, position): if position < 0 or len(self.indices) - 1 <= position: raise IndexError("The dynamic does not have a time step at this position!") - return sum(self.reference.step_size(index) for index in self.reference.indices_within(self.indices[position], self.indices[position + 1])) + return sum(self.reference.step_length(index) for index in self.reference.indices_within(self.indices[position], self.indices[position + 1])) / 3600 + + def step_length(self, index): + if index not in self.indices[:-1]: + raise IndexError("The dynamic does not have a time step at this index!") + return self.step_length_p(self.indices.index(index)) def step_size(self, index): if index not in self.indices[:-1]: raise IndexError("The dynamic does not have a time step at this index!") - return self.step_size_p(self.indices.index(index)) + return self.step_length_p(self.indices.index(index)) / 3600 + + def step_lengths(self): + return [self.step_length_p(position) for position in range(self.number_of_steps())] def step_sizes(self): - return [self.step_size_p(position) for position in range(self.number_of_steps())] + return [self.step_length_p(position) / 3600 for position in range(self.number_of_steps())] def sub_dynamic_p(self, positions): if any(position < 0 or len(self.indices) <= position for position in positions): @@ -475,17 +512,31 @@ class PartialDynamic(Dynamic): raise IndexError('The dynamic does not have a position for this index!') return reference_position - self.start + def step_length_p(self, position): + if position < 0 or self.end - self.start <= position: + raise IndexError("The dynamic does not have a time step at this position!") + return self.reference.step_length_p(self.start + position) + def step_size_p(self, position): if position < 0 or self.end - self.start <= position: raise IndexError("The dynamic does not have a time step at this position!") return self.reference.step_size_p(self.start + position) + def step_length(self, index): + reference_position = self.reference.position_of(index) + if reference_position < self.start or self.end <= reference_position: + raise IndexError('The dynamic does not have a time step at this index!') + return self.step_length_p(reference_position - self.start) + def step_size(self, index): reference_position = self.reference.position_of(index) if reference_position < self.start or self.end <= reference_position: raise IndexError('The dynamic does not have a time step at this index!') return self.step_size_p(reference_position - self.start) + def step_lengths(self): + return [self.reference.step_length_p(position) for position in range(self.start, self.end)] + def step_sizes(self): return [self.reference.step_size_p(position) for position in range(self.start, self.end)] @@ -548,7 +599,7 @@ def compute_assignment_to_backed(dynamic, target_dynamic): else: acc = [] for source_index in source_indices: - acc.append((source_index, dynamic.step_size(source_index) / target_dynamic.step_size_p(target_position))) + acc.append((source_index, dynamic.step_length(source_index) / target_dynamic.step_length_p(target_position))) assignment.add_expression(acc, target_index) assignment.compile() return assignment @@ -578,17 +629,17 @@ def compute_assignment_common_reference(dynamic, target_dynamic): length = 0 while root_p_start not in dynamic.indices[:-1]: # because root is a TrivialDynamic, root_p_start is equivalent to root_i_start root_p_start -= 1 - length += root.step_size_p(root_p_start) + length += root.step_length_p(root_p_start) source_position = dynamic.indices.index(root_p_start) # because root is a TrivialDynamic, positions and indices are equivalent target_position = 0 - remaining_length = dynamic.step_size_p(source_position) - length + remaining_length = dynamic.step_length_p(source_position) - length else: # Here source_i_start > target_i_start becuase the case of source_i_start == target_i_start is handled in the else branch of target_i_srat not in dynamic.indices root = dynamic.root() root_p_start = source_i_start # because root is a TrivialDynamic, positions and indices are equivalent length = 0 source_position = 0 while root_p_start not in target_dynamic.indices: - length += root.step_size_p(root_p_start) + length += root.step_length_p(root_p_start) root_p_start += 1 if root_p_start in dynamic.indices[:-1]: length = 0 @@ -597,13 +648,13 @@ def compute_assignment_common_reference(dynamic, target_dynamic): assignment.compile() # here, we discover that the entire source_dynamic does not cover one time_step of the target_dynamic return assignment target_position = target_dynamic.position_of(root_p_start) # because root is a TrivialDynamic, positions and indices are equivalent - remaining_length = dynamic.step_size_p(source_position) - length + remaining_length = dynamic.step_length_p(source_position) - length else: source_position = dynamic.indices.index(target_i_start) target_position = 0 - remaining_length = dynamic.step_size(target_i_start) + remaining_length = dynamic.step_length(target_i_start) while target_position < len(target_dynamic.indices) - 1: - remaining_target_length = target_dynamic.step_size_p(target_position) + remaining_target_length = target_dynamic.step_length_p(target_position) acc = [] while remaining_target_length > 0: if remaining_length == 0: @@ -611,7 +662,7 @@ def compute_assignment_common_reference(dynamic, target_dynamic): if source_position >= len(dynamic.indices) - 1: assignment.compile() return assignment - remaining_length = dynamic.step_size_p(source_position) + remaining_length = dynamic.step_length_p(source_position) if remaining_target_length <= remaining_length: acc.append((dynamic.indices[source_position], remaining_target_length)) remaining_length -= remaining_target_length @@ -621,7 +672,7 @@ def compute_assignment_common_reference(dynamic, target_dynamic): remaining_target_length -= remaining_length remaining_length -= remaining_length for i, (index, factor) in enumerate(acc): - acc[i] = (index, factor / target_dynamic.step_size_p(target_position)) + acc[i] = (index, factor / target_dynamic.step_length_p(target_position)) assignment.add_expression(acc, target_dynamic.index_of(target_position)) target_position += 1 assignment.compile()