Code Duplication    Length = 71-72 lines in 2 locations

src/oemof/solph/constraints/storage_level.py 2 locations

@@ 250-321 (lines=72) @@
247
            ),
248
        )
249
250
    def _inputs_tsam():
251
        INPUTS = po.Set(initialize=input_levels.keys())
252
        setattr(model, f"{name}_INPUTS", INPUTS)
253
254
        inactive_input = po.Var(
255
            INPUTS,
256
            model.TIMEINDEX_TYPICAL_CLUSTER_OFFSET,
257
            domain=po.Binary,
258
            bounds=(0, 1),
259
        )
260
        setattr(model, f"{name}_active_input", inactive_input)
261
262
        constraint_name = f"{name}_input_active_constraint"
263
264
        def _input_active_rule(m):
265
            r"""
266
            .. math::
267
                \hat{y}_n \ge (E(t) - E_n) / E_{max}
268
            """
269
            for p, i, g in m.TIMEINDEX_CLUSTER:
270
                k = m.es.tsa_parameters[p]["order"][i]
271
                t = m.get_timestep_from_tsam_timestep(p, k, g)
272
                tk = m.get_timestep_from_tsam_timestep(p, k, g)
273
                for inp in input_levels:
274
                    getattr(m, constraint_name).add(
275
                        (inp, p, i, g),
276
                        (
277
                            m.GenericStorageBlock.intra_storage_delta[
278
                                storage_component, p, k, g + 1
279
                            ]
280
                            + m.GenericStorageBlock.inter_storage_content[
281
                                storage_component, i
282
                            ]
283
                            * (1 - storage_component.loss_rate[t])
284
                            ** (g * m.timeincrement[tk])
285
                        )
286
                        / storage_component.nominal_storage_capacity
287
                        - input_levels[inp]
288
                        <= inactive_input[inp, p, k, g],
289
                    )
290
291
        setattr(
292
            model,
293
            constraint_name,
294
            po.Constraint(
295
                INPUTS,
296
                model.TIMEINDEX_CLUSTER,
297
                noruleinit=True,
298
            ),
299
        )
300
        setattr(
301
            model,
302
            constraint_name + "build",
303
            po.BuildAction(rule=_input_active_rule),
304
        )
305
306
        # Define constraints on the input flows
307
        def _constraint_input_rule(m, i, p, k, g):
308
            t = m.get_timestep_from_tsam_timestep(p, k, g)
309
            return (
310
                m.flow[i, multiplexer_bus, p, t]
311
                / m.flows[i, multiplexer_bus].nominal_value
312
                <= 1 - inactive_input[i, p, k, g]
313
            )
314
315
        setattr(
316
            model,
317
            f"{name}_input_constraint",
318
            po.Constraint(
319
                INPUTS,
320
                model.TIMEINDEX_TYPICAL_CLUSTER,
321
                rule=_constraint_input_rule,
322
            ),
323
        )
324
@@ 108-178 (lines=71) @@
105
            ),
106
        )
107
108
    def _outputs_tsam():
109
        OUTPUTS = po.Set(initialize=output_levels.keys())
110
        setattr(model, f"{name}_OUTPUTS", OUTPUTS)
111
112
        active_output = po.Var(
113
            OUTPUTS,
114
            model.TIMEINDEX_TYPICAL_CLUSTER_OFFSET,
115
            domain=po.Binary,
116
            bounds=(0, 1),
117
        )
118
        setattr(model, f"{name}_active_output", active_output)
119
120
        constraint_name = f"{name}_output_active_constraint"
121
122
        def _output_active_rule(m):
123
            r"""
124
            .. math::
125
                y_n \le E(t) / E_n
126
            """
127
            for p, i, g in m.TIMEINDEX_CLUSTER:
128
                k = m.es.tsa_parameters[p]["order"][i]
129
                t = m.get_timestep_from_tsam_timestep(p, k, g)
130
                tk = m.get_timestep_from_tsam_timestep(p, k, g)
131
                for o in output_levels:
132
                    getattr(m, constraint_name).add(
133
                        (o, p, i, g),
134
                        (
135
                            m.GenericStorageBlock.intra_storage_delta[
136
                                storage_component, p, k, g + 1
137
                            ]
138
                            + m.GenericStorageBlock.inter_storage_content[
139
                                storage_component, i
140
                            ]
141
                            * (1 - storage_component.loss_rate[t])
142
                            ** (g * m.timeincrement[tk])
143
                        )
144
                        / storage_component.nominal_storage_capacity
145
                        >= active_output[o, p, k, g] * output_levels[o],
146
                    )
147
148
        setattr(
149
            model,
150
            constraint_name,
151
            po.Constraint(
152
                OUTPUTS,
153
                model.TIMEINDEX_CLUSTER,
154
                noruleinit=True,
155
            ),
156
        )
157
        setattr(
158
            model,
159
            constraint_name + "build",
160
            po.BuildAction(rule=_output_active_rule),
161
        )
162
163
        # Define constraints on the output flows
164
        def _constraint_output_rule(m, o, p, k, g):
165
            t = m.get_timestep_from_tsam_timestep(p, k, g)
166
            return (
167
                m.flow[multiplexer_bus, o, p, t]
168
                / m.flows[multiplexer_bus, o].nominal_value
169
                <= active_output[o, p, k, g]
170
            )
171
172
        setattr(
173
            model,
174
            f"{name}_output_constraint",
175
            po.Constraint(
176
                OUTPUTS,
177
                model.TIMEINDEX_TYPICAL_CLUSTER,
178
                rule=_constraint_output_rule,
179
            ),
180
        )
181