Simple Explicit ExpressionsΒΆ
In this example, we define multiple expressions and register their
outputs.
Note that the outputs need not be registered in the order in which they
are defined, nor do they necessarily appear in the n2 diagram in the
order in which they are registered.
This is due to the fact that omtools
automatically rearranges
expressions so that the Component
objects do not have any
unnecessary feedbacks.
from openmdao.api import Problem
from openmdao.api import ScipyKrylov, NewtonSolver, NonlinearBlockGS
from omtools.api import Group, ImplicitComponent
import omtools.api as ot
import numpy as np
class ExampleBinaryOperations(Group):
def setup(self):
# declare inputs with default values
x1 = self.declare_input('x1', val=2)
x2 = self.declare_input('x2', val=3)
x3 = self.declare_input('x3', val=np.arange(7))
# Expressions with multiple binary operations
y1 = -2 * x1**2 + 4 * x2 + 3
self.register_output('y1', y1)
# Elementwise addition
y2 = x2 + x1
# Elementwise subtraction
y3 = x2 - x1
# Elementwise multitplication
y4 = x1 * x2
# Elementwise division
y5 = x1 / x2
y6 = x1 / 3
y7 = 2 / x2
# Elementwise Power
y8 = x2**2
y9 = x1**2
self.register_output('y2', y2)
self.register_output('y3', y3)
self.register_output('y4', y4)
self.register_output('y5', y5)
self.register_output('y6', y6)
self.register_output('y7', y7)
self.register_output('y8', y8)
self.register_output('y9', y9)
# Adding other expressions
self.register_output('y10', y1 + y7)
# Array with scalar power
y11 = x3**2
self.register_output('y11', y11)
# Array with array of powers
y12 = x3**(2 * np.ones(7))
self.register_output('y12', y12)
prob = Problem()
prob.model = ExampleBinaryOperations()
prob.setup(force_alloc_complex=True)
prob.run_model()
print('y1', prob['y1'].shape)
print(prob['y1'])
print('y2', prob['y2'].shape)
print(prob['y2'])
print('y3', prob['y3'].shape)
print(prob['y3'])
print('y4', prob['y4'].shape)
print(prob['y4'])
print('y5', prob['y5'].shape)
print(prob['y5'])
print('y6', prob['y6'].shape)
print(prob['y6'])
print('y7', prob['y7'].shape)
print(prob['y7'])
print('y8', prob['y8'].shape)
print(prob['y8'])
print('y9', prob['y9'].shape)
print(prob['y9'])
print('y10', prob['y10'].shape)
print(prob['y10'])
print('y11', prob['y11'].shape)
print(prob['y11'])
print('y12', prob['y12'].shape)
print(prob['y12'])
y1 (1,)
[7.]
y2 (1,)
[5.]
y3 (1,)
[1.]
y4 (1,)
[6.]
y5 (1,)
[0.66666667]
y6 (1,)
[0.66666667]
y7 (1,)
[0.66666667]
y8 (1,)
[9.]
y9 (1,)
[4.]
y10 (1,)
[7.66666667]
y11 (7,)
[ 0. 1. 4. 9. 16. 25. 36.]
y12 (7,)
[ 0. 1. 4. 9. 16. 25. 36.]
The Component
objects added to the model are guaranteed to be
connected such that there are no unnecessary feedbacks, regardless of
the order in which each output is defined or registered.
In this case, since there are no cycles, the n2 diagram is upper
triangular.