diff --git a/pygeo/parameterization/DVGeo.py b/pygeo/parameterization/DVGeo.py index 31f7f61f..98ae6599 100644 --- a/pygeo/parameterization/DVGeo.py +++ b/pygeo/parameterization/DVGeo.py @@ -3721,8 +3721,12 @@ def _attachedPtJacobian(self, config): # We need to save the reference state so that we can always start # from the same place when calling _update_deriv - refFFDCoef = copy.copy(self.FFD.coef) - refCoef = copy.copy(self.coef) + if not self.isChild: + refFFDCoef = copy.copy(self.origFFDCoef.astype("D")) + refCoef = copy.copy(self.coef0.astype("D")) + else: + refFFDCoef = copy.copy(self.FFD.coef) + refCoef = copy.copy(self.coef) iDV = self.nDVG_count for key in self.DV_listGlobal: diff --git a/tests/reg_tests/commonUtils.py b/tests/reg_tests/commonUtils.py index adc1ad94..88f53451 100644 --- a/tests/reg_tests/commonUtils.py +++ b/tests/reg_tests/commonUtils.py @@ -127,11 +127,8 @@ def totalSensitivityFD(DVGeo, nPt, ptName, step=1e-1): nDV = len(baseVar) dIdxFD[key] = np.zeros([nPt, nDV]) for i in range(nDV): - # print('perturbing',key) xDV[key][i] = baseVar[i] + step - # print('setting design vars') DVGeo.setDesignVars(xDV) - # print('calling top level update') newPoints = DVGeo.update(ptName) deriv = (newPoints - refPoints) / step @@ -264,3 +261,21 @@ def chord(val, geo): for i in range(1, nRefAxPts): geo.scale_x[axis_key].coef[i] = val[i - fix_root_sect] + + +def span(val, geo): + axis_key = list(geo.axis.keys())[0] + C = geo.extractCoef(axis_key) + for i in range(1, C.shape[0]): + C[i, 2] *= val + + geo.restoreCoef(C, axis_key) + + +def spanX(val, geo): + axis_key = list(geo.axis.keys())[0] + C = geo.extractCoef(axis_key) + for i in range(1, C.shape[0]): + C[i, 0] *= val + + geo.restoreCoef(C, axis_key) diff --git a/tests/reg_tests/test_DVGeometry.py b/tests/reg_tests/test_DVGeometry.py index 29b04541..4177aaed 100644 --- a/tests/reg_tests/test_DVGeometry.py +++ b/tests/reg_tests/test_DVGeometry.py @@ -988,6 +988,66 @@ def test_ffdSplineOrder(self, train=False, refDeriv=False): commonUtils.testSensitivities(DVGeo, refDeriv, handler, pointset=3) + def test_spanDV(self, train=False): + """ + Test span DV + If the design FFD coef are not reset between updating the points and the derivative routines this will fail. + """ + DVGeo = DVGeometry(os.path.join(self.base_path, "../../input_files/2x1x8_rectangle.xyz")) + + DVGeo.addRefAxis("RefAx", xFraction=0.5, alignIndex="k", rotType=0, rot0ang=-90) + DVGeo.addGlobalDV(dvName="span", value=0.5, func=commonUtils.span, lower=0.1, upper=10, scale=1) + + points = np.zeros([2, 3]) + points[0, :] = [0.25, 0.4, 4] + points[1, :] = [-0.8, 0.2, 7] + ptName = "testPoints" + DVGeo.addPointSet(points, ptName) + + nPt = points.size + dIdx_FD = commonUtils.totalSensitivityFD(DVGeo, nPt, ptName) + + dIdPt = np.zeros([nPt, 2, 3]) + dIdPt[0, 0, 0] = 1.0 + dIdPt[1, 0, 1] = 1.0 + dIdPt[2, 0, 2] = 1.0 + dIdPt[3, 1, 0] = 1.0 + dIdPt[4, 1, 1] = 1.0 + dIdPt[5, 1, 2] = 1.0 + dIdx = DVGeo.totalSensitivity(dIdPt, ptName) + + np.testing.assert_allclose(dIdx["span"], dIdx_FD["span"], atol=1e-15) + + def test_spanDV_child(self, train=False): + """ + Test span DV with child + """ + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) + + # add design variables + DVGeoChild.addGlobalDV(dvName="span", value=0.5, func=commonUtils.spanX, lower=0.1, upper=10, scale=1) + DVGeo.addChild(DVGeoChild) + + points = np.zeros([2, 3]) + points[0, :] = [0.25, 0, 0] + points[1, :] = [-0.25, 0, 0] + ptName = "testPoints" + DVGeo.addPointSet(points, ptName) + + nPt = points.size + dIdx_FD = commonUtils.totalSensitivityFD(DVGeo, nPt, ptName) + + dIdPt = np.zeros([nPt, 2, 3]) + dIdPt[0, 0, 0] = 1.0 + dIdPt[1, 0, 1] = 1.0 + dIdPt[2, 0, 2] = 1.0 + dIdPt[3, 1, 0] = 1.0 + dIdPt[4, 1, 1] = 1.0 + dIdPt[5, 1, 2] = 1.0 + dIdx = DVGeo.totalSensitivity(dIdPt, ptName) + + np.testing.assert_allclose(dIdx["span"], dIdx_FD["span"], atol=1e-15) + if __name__ == "__main__": unittest.main()