Skip to content

Commit

Permalink
Merge pull request #3229 from eytanadler/ks_min
Browse files Browse the repository at this point in the history
Added `minimum` option to `KSComp`
  • Loading branch information
swryan committed Jun 4, 2024
2 parents 253921b + f860d2a commit c06242d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 4 deletions.
19 changes: 16 additions & 3 deletions openmdao/components/ks_comp.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,13 @@ def initialize(self):
self.options.declare('width', types=int, default=1, desc='Width of constraint vector.')
self.options.declare('vec_size', types=int, default=1,
desc='The number of rows to independently aggregate.')
self.options.declare('minimum', types=bool, default=False,
desc='Return the minimum instead of the maximum by multiplying both '
'the inputs and output by -1. It is not recommended to use both '
'this option and the lower_flag option (it will return the '
'negative of the aggregated max.)')
self.options.declare('lower_flag', types=bool, default=False,
desc="Set to True to reverse sign of input constraints.")
desc='Set to True to reverse sign of input constraints.')
self.options.declare('rho', 50.0, desc="Constraint Aggregation Factor.")
self.options.declare('upper', 0.0, desc="Upper bound for constraint, default is zero.")
self.options.declare('add_constraint', types=bool, default=False,
Expand Down Expand Up @@ -229,8 +234,15 @@ def compute(self, inputs, outputs):
con_val = inputs['g'] - opt['upper']
if opt['lower_flag']:
con_val = -con_val
if opt['minimum']:
con_val = -con_val

ks_val = KSfunction.compute(con_val, opt['rho'])

outputs['KS'] = KSfunction.compute(con_val, opt['rho'])
if opt['minimum']:
ks_val = -ks_val

outputs['KS'] = ks_val

def compute_partials(self, inputs, partials):
"""
Expand All @@ -244,11 +256,12 @@ def compute_partials(self, inputs, partials):
Sub-jac components written to partials[output_name, input_name].
"""
opt = self.options
width = opt['width']

con_val = inputs['g'] - opt['upper']
if opt['lower_flag']:
con_val = -con_val
if opt['minimum']:
con_val = -con_val

derivs = KSfunction.derivatives(con_val, opt['rho'])[0]

Expand Down
63 changes: 62 additions & 1 deletion openmdao/components/tests/test_ks_comp.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import openmdao.api as om
from openmdao.test_suite.components.simple_comps import DoubleArrayComp
from openmdao.test_suite.test_examples.beam_optimization.multipoint_beam_stress import MultipointBeamGroup
from openmdao.utils.assert_utils import assert_near_equal
from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials
from openmdao.utils.testing_utils import force_check_partials


Expand Down Expand Up @@ -320,6 +320,67 @@ def test_units(self):

assert_near_equal(prob.get_val('ks.KS', indices=0), np.amax(prob.get_val('x')), tolerance=1e-8)

def test_minimum(self):

n = 10

model = om.Group()

model.add_subsystem('ks', om.KSComp(width=n, minimum=True), promotes_inputs=[('g', 'x')])
model.set_input_defaults('x', range(n))

prob = om.Problem(model=model)
prob.setup()
prob.run_model()

assert_near_equal(prob.get_val('ks.KS', indices=0), np.amin(prob.get_val('x')), tolerance=1e-8)

def test_minimum_partials(self):

n = 10

model = om.Group()

model.add_subsystem('ks', om.KSComp(width=n, minimum=True), promotes_inputs=[('g', 'x')])
model.set_input_defaults('x', range(n))

prob = om.Problem(model=model)
prob.setup(force_alloc_complex=True)
prob.run_model()

partials = force_check_partials(prob, includes=['ks'], out_stream=None, method="cs", step=1e-200)
assert_check_partials(partials)

def test_minimum_and_lower_flag(self):

n = 10

model = om.Group()

model.add_subsystem('ks', om.KSComp(width=n, minimum=True, lower_flag=True), promotes_inputs=[('g', 'x')])
model.set_input_defaults('x', range(n))

prob = om.Problem(model=model)
prob.setup()
prob.run_model()

assert_near_equal(prob.get_val('ks.KS', indices=0), -np.amax(prob.get_val('x')), tolerance=1e-8)

def test_minimum_and_lower_flag_partials(self):

n = 10

model = om.Group()

model.add_subsystem('ks', om.KSComp(width=n, minimum=True, lower_flag=True), promotes_inputs=[('g', 'x')])
model.set_input_defaults('x', range(n))

prob = om.Problem(model=model)
prob.setup(force_alloc_complex=True)
prob.run_model()

partials = force_check_partials(prob, includes=['ks'], out_stream=None, method="cs", step=1e-200)
assert_check_partials(partials)

if __name__ == "__main__":
unittest.main()

0 comments on commit c06242d

Please sign in to comment.