Coverage for backend/idaes_service/solver/custom/integration_block.py: 74%
27 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1#################################################################################
2# The Institute for the Design of Advanced Energy Systems Integrated Platform
3# Framework (IDAES IP) was produced under the DOE Institute for the
4# Design of Advanced Energy Systems (IDAES).
5#
6# Copyright (c) 2018-2024 by the software owners: The Regents of the
7# University of California, through Lawrence Berkeley National Laboratory,
8# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon
9# University, West Virginia University Research Corporation, et al.
10# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md
11# for full copyright and license information.
12#################################################################################
13"""
14Base class for unit models
15"""
17from pyomo.environ import check_optimal_termination
18from pyomo.common.config import ConfigValue
19from pyomo.network import Port
21from idaes.core.base.process_base import (
22 declare_process_block_class,
23 ProcessBlockData,
24 useDefault,
25)
26from idaes.core.base.property_base import StateBlock
27from idaes.core.base.control_volume_base import (
28 ControlVolumeBlockData,
29 FlowDirection,
30 MaterialBalanceType,
31)
32from idaes.core.util.exceptions import (
33 BurntToast,
34 ConfigurationError,
35 BalanceTypeNotSupportedError,
36 InitializationError,
37)
38from idaes.core.util.tables import create_stream_table_dataframe
39import idaes.logger as idaeslog
40from idaes.core.solvers import get_solver
41from idaes.core.util.config import DefaultBool
42from idaes.core.initialization import SingleControlVolumeUnitInitializer
43from pyomo.environ import Var, units, Expression
44from pyomo.dae import Integral
47# Set up logger
48_log = idaeslog.getLogger(__name__)
51@declare_process_block_class("IntegrationBlock")
52class IntegrationBlockData(ProcessBlockData):
53 """
54 This block has no inlets or outlets, but one value that you can get the integral for.
55 """
57 # Create Class ConfigBlock
58 CONFIG = ProcessBlockData.CONFIG()
59 CONFIG.declare(
60 "dynamic",
61 ConfigValue(
62 default=useDefault,
63 domain=DefaultBool,
64 description="Dynamic model flag",
65 doc="""Indicates whether this model will be dynamic or not,
66**default** = useDefault.
67**Valid values:** {
68**useDefault** - get flag from parent (default = False),
69**True** - set as a dynamic model,
70**False** - set as a steady-state model.}""",
71 ),
72 )
74 def build(self):
75 """
77 """
78 super(IntegrationBlockData, self).build()
80 self.variable = Var(
81 self.flowsheet().time
82 )
84 #self.time = self.flowsheet().time
88 def _integral(m):
89 time_steps = sorted(self.flowsheet().time)
90 value = m.variable
91 return sum([
92 # Trapezium rule
93 # average the value at the current and next time step, then multiply by the time difference
94 0.5 * (value[time_steps[i]] + value[time_steps[i+1]]) * (time_steps[i+1] - time_steps[i])
95 for i in range(len(time_steps)-1)
96 ])
98 self.integral = Expression(
99 rule=_integral
100 )
103 # if self.config.dynamic:
104 # # create a variable to hold the normal value, and one to hold the integral value
105 # else: