Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Child FFD constraint tests and fixes #103

Merged
merged 14 commits into from
Oct 5, 2021
30 changes: 26 additions & 4 deletions pygeo/constraints/DVCon.py
Original file line number Diff line number Diff line change
Expand Up @@ -1944,7 +1944,17 @@ def addLeTeConstraints(
)

def addLinearConstraintsShape(
self, indSetA, indSetB, factorA, factorB, lower=0, upper=0, name=None, config=None, DVGeoName="default"
self,
indSetA,
indSetB,
factorA,
factorB,
lower=0,
upper=0,
name=None,
config=None,
DVGeoName="default",
childIdx=None,
):
"""
Add a complete generic set of linear constraints for the shape
Expand Down Expand Up @@ -2007,6 +2017,11 @@ def addLinearConstraintsShape(

self._checkDVGeo(DVGeoName)

if childIdx is not None:
DVGeo = self.DVGeometries[DVGeoName].children[childIdx]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a bit of code reading, but I see how this makes sense. We have a single DVcon object which "receives" the parent DVGeo, and we were previously applying the constraint to this object instead of the children (when present) as expected. This means that we now need to add one of these for each child ffd, right? Can you add a short description of what is going on and how to extract the childIdx index from DVGeo?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, without childIdx the constraint is applied on the parent. You only need to add this constraint to each FFD that needs it. childIdx is defined by the order in which you add the child FFD to the parent (the first is 0, second is 1, etc.). I will update the docstrings to include this description.

To be clear though, I took this approach directly from addLeTeConstraints which already worked with child FFDs.

else:
DVGeo = self.DVGeometries[DVGeoName]

if len(indSetA) != len(indSetB):
raise Error("The length of the supplied indices are not " "the same length")

Expand Down Expand Up @@ -2044,7 +2059,7 @@ def addLinearConstraintsShape(

# Finally add the linear constraint object
self.linearCon[conName] = LinearConstraint(
conName, indSetA, indSetB, factorA, factorB, lower, upper, self.DVGeometries[DVGeoName], config=config
conName, indSetA, indSetB, factorA, factorB, lower, upper, DVGeo, config=config
)

def addGearPostConstraint(
Expand Down Expand Up @@ -2751,7 +2766,9 @@ def addCurvatureConstraint(
addToPyOpt,
)

def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, stop=-1, config=None, DVGeoName="default"):
def addMonotonicConstraints(
self, key, slope=1.0, name=None, start=0, stop=-1, config=None, DVGeoName="default", childIdx=None
):
"""
Parameters
----------
Expand Down Expand Up @@ -2783,6 +2800,11 @@ def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, stop=-1, c
"""
self._checkDVGeo(DVGeoName)

if childIdx is not None:
DVGeo = self.DVGeometries[DVGeoName].children[childIdx]
else:
DVGeo = self.DVGeometries[DVGeoName]

if name is None:
conName = "%s_monotonic_constraint_%d" % (self.name, len(self.linearCon))
else:
Expand All @@ -2797,7 +2819,7 @@ def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, stop=-1, c
options=options,
lower=0,
upper=None,
DVGeo=self.DVGeometries[DVGeoName],
DVGeo=DVGeo,
config=config,
)

Expand Down
23 changes: 18 additions & 5 deletions tests/reg_tests/test_DVConstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,12 @@ def test_4(self, train=False, refDeriv=False):

DVGeo, DVCon = self.generate_dvgeo_dvcon_c172()

DVCon.addLeTeConstraints(0, "iLow")
DVCon.addLeTeConstraints(0, "iHigh")
if self.child:
DVCon.addLeTeConstraints(0, "iLow", childIdx=0)
DVCon.addLeTeConstraints(0, "iHigh", childIdx=0)
else:
DVCon.addLeTeConstraints(0, "iLow")
DVCon.addLeTeConstraints(0, "iHigh")

funcs, funcsSens = generic_test_base(DVGeo, DVCon, handler)
# LeTe constraints should be all zero at the start
Expand Down Expand Up @@ -639,7 +643,12 @@ def test_10(self, train=False, refDeriv=False):
for i in range(lIndex.shape[0]):
indSetA.append(lIndex[i, 0, 0])
indSetB.append(lIndex[i, 0, 1])
DVCon.addLinearConstraintsShape(indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0)
if self.child:
DVCon.addLinearConstraintsShape(
indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0, childIdx=0
)
else:
DVCon.addLinearConstraintsShape(indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0)
funcs, funcsSens = generic_test_base(DVGeo, DVCon, handler)
funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler)
funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler)
Expand Down Expand Up @@ -766,8 +775,12 @@ def test_14(self, train=False, refDeriv=False):

DVGeo, DVCon = self.generate_dvgeo_dvcon_c172()

DVCon.addMonotonicConstraints("twist")
DVCon.addMonotonicConstraints("twist", start=1, stop=2)
if self.child:
DVCon.addMonotonicConstraints("twist", childIdx=0)
DVCon.addMonotonicConstraints("twist", start=1, stop=2, childIdx=0)
else:
DVCon.addMonotonicConstraints("twist")
DVCon.addMonotonicConstraints("twist", start=1, stop=2)

funcs, funcsSens = generic_test_base(DVGeo, DVCon, handler)
handler.assert_allclose(
Expand Down