Design Methods¶
What is a design method?!¶
Design methods allow component designers to identify, from expert knowledge, the different ways users can design a component from functional requirements.
Declaring a design method in a system¶
Design methods are declared at System setup, using System.add_design_method. This class method takes the name of the design method as single argument; it will create a new entry in an internal dictionary of MathematicalProblem objects, mapped to their names.
Such objects bear unknowns and equations, declared with methods add_unkown and add_equation:
class MySystem(System):
def setup(self):
self.add_inward('x', 1.0)
self.add_outward('y', 0.0)
design = self.add_design_method('design_x') # create problem `design`, and store it with key 'design_x'
design.add_unknown('x').add_equation('y == 0') # define problem by declaring unknowns and equations
def compute(self):
self.y = self.x**2 - 3
In practice, design methods are mathematical problems that can be activated on demand.
Example¶
[1]:
from cosapp.base import System, Port
class XPort(Port):
def setup(self):
self.add_variable("x", 1.0)
class MultiplyWithDesignMethod(System):
def setup(self):
self.add_input(XPort, 'p_in', {'x': 1.})
self.add_output(XPort, 'p_out', {'x': 1.})
self.add_inward('K1', 5.)
# off-design constraints
self.add_inward('expected_output', 1.0)
self.add_unknown('p_in.x').add_equation('p_out.x == expected_output')
# design methods
self.add_inward('dx_design', 10.)
self.add_design_method('dx').add_unknown('K1').add_equation('p_out.x - p_in.x == dx_design')
def compute(self):
self.p_out.x = self.p_in.x * self.K1
Class MultiplyWithDesignMethod defines two types of mathematical problems, through add_unknown and add_equation:
Unknowns and equations declared directly on the system (that is
self.add_unknownandself.add_equationin system setup) are always enforced, for all instances of the class. They are referred to as the off-design problem of the class. Composite systems automatically collect the off-design problems of their sub-systems.Unknowns and equations declared within a design method define a design problem, which may or may not be activated.
Solving the off-design problem¶
[2]:
from cosapp.drivers import NonLinearSolver, RunSingleCase
m = MultiplyWithDesignMethod('m')
# Add solver
solver = m.add_driver(NonLinearSolver('solver', tol=1e-12))
m.K1 = 5
m.expected_output = 7.5
m.run_drivers()
print("Off-design problem:", solver.problem, sep="\n")
print(
"Off-design result:",
f"m.K1 = {m.K1}",
f"m.p_in.x = {m.p_in.x}",
f"m.p_out.x = {m.p_out.x}",
sep="\n ",
)
Off-design problem:
Unknowns
runner[p_in.x]
Equations
p_out.x == expected_output := 0.0
Off-design result:
m.K1 = 5
m.p_in.x = 1.5
m.p_out.x = 7.5
Activating a design method¶
Design methods are activated by extending an existing mathematical problem with the predefined design method. In the example below, a single-point design case is created using design method 'dx' of the system of interest.
[3]:
from cosapp.drivers import NonLinearSolver, RunSingleCase
m = MultiplyWithDesignMethod('m')
solver = m.add_driver(NonLinearSolver('solver', tol=1e-12))
# Add design point
case = solver.add_child(RunSingleCase('case'))
# Define case conditions
case.set_values({
'expected_output': 7.5,
'dx_design': 5.0,
})
case.design.extend(m.design_methods['dx']) # activate design method 'dx' of system `m`
m.run_drivers()
print("Design problem:", solver.problem, sep="\n")
print(
"Design result:",
f"m.K1 = {m.K1}",
f"m.p_in.x = {m.p_in.x}",
f"m.p_out.x = {m.p_out.x}",
sep="\n ",
)
Design problem:
Unknowns
inwards.K1
case[p_in.x]
Equations
p_out.x - p_in.x == dx_design := 0.0
p_out.x == expected_output := 0.0
Design result:
m.K1 = 3.0
m.p_in.x = 2.5
m.p_out.x = 7.5
Promoting sub-system design methods at parent level¶
Composite systems can take advantage of design methods defined for their sub-systems, and thus construct composite design methods.
class CompositeSystem(System):
def setup(self):
a = self.add_child(ComponentA('a'))
b = self.add_child(ComponentB('b'))
design = self.add_design_method('design')
design.extend(a.design_methods['design_this'])
design.extend(b.design_methods['design_that'])
Congrats! You are now ready to update your System into a design model with CoSApp!
[ ]: