diff --git a/blast/interfaces/DAdjointInterface.py b/blast/interfaces/DAdjointInterface.py deleted file mode 100644 index 7eee2fe9576c1630f05d6fa85b04df1833a7edd6..0000000000000000000000000000000000000000 --- a/blast/interfaces/DAdjointInterface.py +++ /dev/null @@ -1,566 +0,0 @@ -import numpy as np -from matplotlib import pyplot as plt - -class AdjointInterface(): - def __init__(self, _coupledAdjointSolver, _iSolverAPI, _vSolver): - self.coupledAdjointSolver = _coupledAdjointSolver - self.isol = _iSolverAPI - self.vsol = _vSolver - - def build(self): - nDim = self.isol.solver.pbl.nDim - nNd = self.isol.solver.pbl.msh.nodes.size() - - nNs_v = 0 - for isec in self.isol.sec[0]: - nNs_v += isec.nNodes - nEs_v = 0 - for isec in self.isol.sec[0]: - nEs_v += isec.nElms - - dRdStar_dStar = np.zeros((nNs_v, nNs_v)) - dRdStar_M = np.zeros((nNs_v, nNs_v)) - dRdStar_rho = np.zeros((nNs_v, nNs_v)) - dRdStar_v = np.zeros((nNs_v, nNs_v*nDim)) - dRdStar_x = np.zeros((nNs_v, nNd*nDim)) - - dRblw_rho = np.zeros((nEs_v, nNs_v)) - dRblw_v = np.zeros((nEs_v, nNs_v*nDim)) - dRblw_dStar = np.zeros((nEs_v, nNs_v)) - dRblw_x = np.zeros((nEs_v, nNd*nDim)) - - delta = 1e-6 - delta_x = 1e-8 - - # Compute dVt/dV - dVt_v = np.zeros((nNs_v, nNs_v*nDim)) - v = np.zeros((nNs_v, nDim)) - for d in range(nDim): - v[:self.isol.sec[0][0].nNodes, d] = self.isol.vBnd[0][0].getVelocity("upper", d) - v[self.isol.sec[0][0].nNodes:self.isol.sec[0][0].nNodes+self.isol.sec[0][1].nNodes, d] = self.isol.vBnd[0][0].getVelocity("lower", d) - v[self.isol.sec[0][0].nNodes+self.isol.sec[0][1].nNodes:, d] = self.isol.vBnd[0][1].getVelocity("wake", d) - - i = 0 - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - for d in range(nDim): - dVt_v[i, i*nDim+d] = 1/np.sqrt(v[i, 0]**2 + v[i, 1]**2)*v[i, d] - i += 1 - - """# Finite difference - i = 0 - offset = 0 - dVt_v_fd = np.zeros((nNs_v, nNs_v*nDim)) - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - for d in range(nDim): - save = v[i, d] - v[i, d] = save + delta - vt1 = np.sqrt(v[:,0]**2 + v[:,1]**2) - v[i, d] = save - delta - vt2 = np.sqrt(v[:,0]**2 + v[:,1]**2) - dVt_v_fd[:, i*nDim+d] = (vt1 - vt2)/(2*delta) - v[i, d] = save - i += 1""" - - # dRdStar_M - i = 0 - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - mach_lo = isec.Me[j] - isec.Me[j] = mach_lo + delta - deltaStar1 = self.__runViscous() - isec.Me[j] = mach_lo - delta - deltaStar2 = self.__runViscous() - isec.Me[j] = mach_lo - dRdStar_M[:, i] = -(deltaStar1 - deltaStar2)/(2.*delta) - i += 1 - - # dRdStar_dStar - dRdStar_dStar_test = np.zeros((nNs_v, nNs_v)) - i = 0 - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - dStar_lo = isec.deltaStarExt[j] - isec.deltaStarExt[j] = dStar_lo + delta - deltaStar1 = self.__runViscous() - isec.deltaStarExt[j] = dStar_lo - delta - deltaStar2 = self.__runViscous() - isec.deltaStarExt[j] = dStar_lo - dRdStar_dStar_test[:, i] = (deltaStar1 - deltaStar2)/(2.*delta) - i += 1 - - # Set dRdStar_dStar to identity - dRdStar_dStar = np.eye(nNs_v) - dRdStar_dStar_test - - # dRdStar_vt - dRdStar_vt = np.zeros((nNs_v, nNs_v)) - i = 0 - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - save = isec.vt[j] - isec.vt[j] = save + delta - #isec.vtExt[j] = save + delta - deltaStar1 = self.__runViscous() - isec.vt[j] = save - delta - #isec.vtExt[j] = save - delta - deltaStar2 = self.__runViscous() - isec.vt[j] = save - #isec.vtExt[j] = save - dRdStar_vt[:, i] = -(deltaStar1 - deltaStar2)/(2.*delta) - i += 1 - - dRdStar_v = dRdStar_vt @ dVt_v - - """# dRdStar_v fd - i = 0 - offset = 0 - dRdStar_v_fd = np.zeros((nNs_v, nNs_v*nDim)) - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - for d in range(nDim): - save = v[i, d] - v[i, d] = save + delta - # Recompute vt - vt = np.sqrt(v[:, 0]**2 + v[:, 1]**2) - # Change vt in c++ object - # Resplit vt in the sections - for nodesSec in range(isec.nNodes): - #print('nodesSec', nodesSec, 'isec.vt', isec.vt[nodesSec], 'vt', vt[offset + nodesSec]) - isec.vt[nodesSec] = vt[offset + nodesSec] - deltaStar1 = self.__runViscous() - v[i, d] = save - delta - # Recompute vt - vt = np.sqrt(v[:, 0]**2 + v[:, 1]**2) - # Change vt in c++ object - for nodesSec in range(isec.nNodes): - isec.vt[nodesSec] = vt[offset + nodesSec] - deltaStar2 = self.__runViscous() - v[i, d] = save - dRdStar_v_fd[:, i*nDim+d] = -(deltaStar1 - deltaStar2)/(2*delta) - i += 1 - offset += isec.nNodes - print('diff', dRdStar_v - dRdStar_v_fd) - print('max diff dRdstar_v', np.max(np.abs(dRdStar_v - dRdStar_v_fd))) - quit()""" - - # dRdStar_x - print('dRdStar_x') - for isec in self.isol.sec[0]: - if isec.name == 'upper' or isec.name == 'lower': - iReg = 0 - elif isec.name == 'wake': - iReg = 1 - for j in range(isec.nNodes): - rowj = self.isol.blw[iReg].nodes[isec.rows[j]].row - save = isec.x[j] - - isec.x[j] = save + delta_x - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - - deltaStar1 = self.__runViscous() - - isec.x[j] = save - delta_x - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - - deltaStar2 = self.__runViscous() - - diff = (deltaStar1 - deltaStar2)/(2.*delta_x) - - isec.x[j] = save - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - - dRdStar_x[:, rowj*nDim+0] -= diff - - save = isec.y[j] - isec.y[j] = save + delta_x - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - - deltaStar1 = self.__runViscous() - - isec.y[j] = save - delta_x - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - - deltaStar2 = self.__runViscous() - - diff = (deltaStar1 - deltaStar2)/(2.*delta_x) - - isec.y[j] = save - isec.computeLocalCoordinates() - isec.xxExt = isec.loc - dRdStar_x[:, rowj*nDim+1] -= diff - - print('done') - """# Finite difference dRdStar_x_fd_2 - dRdStar_x_fd = np.zeros((nNs_v, nNd*nDim)) - saveNodes = np.zeros((len(self.isol.iobj['pbl'].msh.nodes), self.isol.getnDim())) - for n in self.isol.iobj['pbl'].msh.nodes: - for i in range(self.isol.getnDim()): - saveNodes[n.row, i] = n.pos[i] - for ib, b in enumerate(self.isol.blw): - for inod, n in enumerate(b.nodes): - # Find all the nodes in the viscous mesh corresponding to the current node. We also save the boundary index (0: airfoil, 1: wake) - vidx = [] - try: - vidx.append((np.where(self.isol.vBnd[0][0].nodesCoord[:,3] == n.row)[0][0], 0)) - except IndexError: - pass - try: - vidx.append((np.where(self.isol.vBnd[0][1].nodesCoord[:,3] == n.row)[0][0], 1)) - except IndexError: - pass - for idim in range(self.isol.getnDim()): - ddStar = [np.zeros(nNs_v), np.zeros(nNs_v)] - for isgn, sign in enumerate([-1, 1]): - # Modify all the nodes of the viscous mesh (contained in vidx) - for (ii, boundary) in vidx: - self.isol.vBnd[0][boundary].nodesCoord[ii, idim] = saveNodes[n.row, idim] + sign * delta - self.setvMesh(self.isol.vBnd, self.isol.sec[0]) - - ddStar[isgn] = self.__runViscous() - - # Reset mesh - for vb in self.isol.vBnd[0]: - for jj, jrow in enumerate(vb.nodesCoord[:,3]): - for d in range(self.isol.getnDim()): - vb.nodesCoord[jj, d] = saveNodes[int(jrow), d] - dRdStar_x_fd[:, n.row*self.isol.getnDim()+idim] = -(ddStar[1] - ddStar[0])/(2*delta) - np.savetxt('dRdStar_x_fd.txt', dRdStar_x_fd) - np.savetxt('dRdStar_x.txt', dRdStar_x) - print('max diff', np.max(np.abs(dRdStar_x - dRdStar_x_fd))) - quit()""" - - # dRblw_rho - offsetNodes = 0 - offsetElems = 0 - for isec in self.isol.sec[0]: - test = np.array(isec.evalGradwrtRho()) - dRblw_rho[offsetElems:offsetElems+isec.nElms, offsetNodes:offsetNodes+isec.nNodes] = -test - offsetNodes += isec.nNodes - offsetElems += isec.nElms - - """# Finite difference - start = time.time() - i = 0 - offset = 0 - dRblw_rho_fd = np.zeros((nEs_v, nNs_v)) - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - save = isec.rhoe[j] - isec.rhoe[j] = save + delta - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing1 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - isec.rhoe[j] = save - delta - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing2 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - isec.rhoe[j] = save - dRblw_rho_fd[:, i] = (blowing1 - blowing2)/(2*delta) - i += 1 - offset += isec.nNodes - end = time.time() - print('done dRblw_rho_fd in', end-start)""" - - # dRblw_vt - offsetNodes = 0 - offsetElems = 0 - dRblw_vt = np.zeros((nEs_v, nNs_v)) - for isec in self.isol.sec[0]: - test = np.array(isec.evalGradwrtVt()) - dRblw_vt[offsetElems:offsetElems+isec.nElms, offsetNodes:offsetNodes+isec.nNodes] = -test - offsetNodes += isec.nNodes - offsetElems += isec.nElms - - #print('dRblw_vt', dRblw_vt) - - # dRblw_v = dRblw_vt*dVt_v - dRblw_v = dRblw_vt @ dVt_v - - # Validate by finite difference - """i = 0 - offset = 0 - dRblw_v_fd = np.zeros((nEs_v, nNs_v*nDim)) - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - for d in range(nDim): - save = v[i, d] - v[i, d] = save + delta - # Recompute vt - vt = np.sqrt(v[:, 0]**2 + v[:, 1]**2) - # Change vt in c++ object - # Resplit vt in the sections - for nodesSec in range(isec.nNodes): - #print('nodesSec', nodesSec, 'isec.vt', isec.vt[nodesSec], 'vt', vt[offset + nodesSec]) - isec.vt[nodesSec] = vt[offset + nodesSec] - - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing1 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - v[i, d] = save - delta - # Recompute vt - vt = np.sqrt(v[:, 0]**2 + v[:, 1]**2) - # Change vt in c++ object - for nodesSec in range(isec.nNodes): - isec.vt[nodesSec] = vt[offset + nodesSec] - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing2 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - v[i, d] = save - dRblw_v_fd[:, i*nDim+d] = (blowing1 - blowing2)/(2*delta) - i += 1 - offset += isec.nNodes""" - - # dRblw_dStar - offsetNodes = 0 - offsetElems = 0 - for isec in self.isol.sec[0]: - test = np.array(isec.evalGradwrtDeltaStar()) - dRblw_dStar[offsetElems:offsetElems+isec.nElms, offsetNodes:offsetNodes+isec.nNodes] = -test - offsetNodes += isec.nNodes - offsetElems += isec.nElms - - """# Finite difference - dRblw_dStar_fd = np.zeros((nEs_v, nNs_v)) - i = 0 - for isec in self.isol.sec[0]: - for j in range(isec.nNodes): - save = isec.rhoe[j] - isec.deltaStar[j] = save + delta - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing1 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - isec.deltaStar[j] = save - delta - isec.computeBlowingVelocity() - blowing_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing2 = np.concatenate([blowing_part1, blowing_part2, blowing_part3]) - isec.deltaStar[j] = save - dRblw_dStar_fd[:, i] = -(blowing1 - blowing2)/(2*delta) - i += 1 - print('diff', dRblw_dStar - dRblw_dStar_fd) - print('max diff', np.max(np.abs(dRblw_dStar - dRblw_dStar_fd))) - quit()""" - - - """print('Max error dRblw_v', np.max(np.abs(dRblw_v - dRblw_v_fd))) - print('Max error dRblw_rho', np.max(np.abs(dRblw_rho - dRblw_rho_fd))) - print('Max error dRblw_dStar', np.max(np.abs(dRblw_dStar - dRblw_dStar_fd)))""" - - # dRblw_x - offsetElems = 0 - dRblw_x = np.zeros((nEs_v, nNd*nDim)) - for isec in self.isol.sec[0]: - if isec.name == 'upper' or isec.name == 'lower': - iReg = 0 - elif isec.name == 'wake': - iReg = 1 - test_x = -np.array(isec.evalGradwrtX()) - test_y = -np.array(isec.evalGradwrtY()) - for j in range(isec.nNodes): - rowj = self.isol.blw[iReg].nodes[isec.rows[j]].row - dRblw_x[offsetElems:offsetElems+isec.nElms, rowj*nDim+0] = test_x[:, j] - dRblw_x[offsetElems:offsetElems+isec.nElms, rowj*nDim+1] = test_y[:, j] - offsetElems += isec.nElms - - - """# Finite difference dRblw_x_fd_2 - dRblw_x_fd = np.zeros((nEs_v, nNd*nDim)) - saveNodes = np.zeros((len(self.isol.iobj['pbl'].msh.nodes), self.isol.getnDim())) - for n in self.isol.iobj['pbl'].msh.nodes: - for i in range(self.isol.getnDim()): - saveNodes[n.row, i] = n.pos[i] - for ib, b in enumerate(self.isol.blw): - for inod, n in enumerate(b.nodes): - # Find all the nodes in the viscous mesh corresponding to the current node. We also save the boundary index (0: airfoil, 1: wake) - vidx = [] - try: - vidx.append((np.where(self.isol.vBnd[0][0].nodesCoord[:,3] == n.row)[0][0], 0)) - except IndexError: - pass - try: - vidx.append((np.where(self.isol.vBnd[0][1].nodesCoord[:,3] == n.row)[0][0], 1)) - except IndexError: - pass - for idim in range(self.isol.getnDim()): - dblw = [np.zeros(nEs_v), np.zeros(nEs_v)] - for isgn, sign in enumerate([-1, 1]): - # Modify all the nodes of the viscous mesh (contained in vidx) - for (ii, boundary) in vidx: - self.isol.vBnd[0][boundary].nodesCoord[ii, idim] = saveNodes[n.row, idim] + sign * delta - self.setvMesh(self.isol.vBnd, self.isol.sec[0]) - for reg in self.isol.sec[0]: - reg.computeBlowingVelocity() - - blowing1_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing1_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing1_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - dblw[isgn] = np.concatenate([blowing1_part1, blowing1_part2, blowing1_part3]) - - # Reset mesh - for vb in self.isol.vBnd[0]: - for jj, jrow in enumerate(vb.nodesCoord[:,3]): - for d in range(self.isol.getnDim()): - vb.nodesCoord[jj, d] = saveNodes[int(jrow), d] - dRblw_x_fd[:, n.row*self.isol.getnDim()+idim] = -(dblw[1] - dblw[0])/(2*delta) - # Write to file - np.savetxt('dRblw_x_fd.txt', dRblw_x_fd) - np.savetxt('dRblw_x.txt', dRblw_x) - print('max diff', np.max(np.abs(dRblw_x - dRblw_x_fd))) - quit()""" - - """# Finite difference dRblw_x_fd - offsetElems = 0 - dRblw_x_fd = np.zeros((nEs_v, nNd*nDim)) - for isec in self.isol.sec[0]: - if isec.name == 'upper' or isec.name == 'lower': - iReg = 0 - elif isec.name == 'wake': - iReg = 1 - for j in range(isec.nNodes): - rowj = self.isol.blw[iReg].nodes[isec.rows[j]].row - save = isec.x[j] - isec.x[j] = save + delta - isec.computeLocalCoordinates() - isec.computeBlowingVelocity() - - blowing1_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing1_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing1_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing1 = np.concatenate([blowing1_part1, blowing1_part2, blowing1_part3]) - - isec.x[j] = save - delta - isec.computeLocalCoordinates() - isec.computeBlowingVelocity() - - blowing2_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing2_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing2_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing2 = np.concatenate([blowing2_part1, blowing2_part2, blowing2_part3]) - bb = (blowing1 - blowing2)/(2*delta) - - isec.x[j] = save - dRblw_x_fd[offsetElems:offsetElems+isec.nElms, rowj*nDim+0] = -bb[offsetElems:offsetElems+isec.nElms] - - if rowj == 0: - print(isec.name, j, -(blowing1 - blowing2)/(2*delta)) - - save = isec.y[j] - isec.y[j] = save + delta - isec.computeLocalCoordinates() - isec.computeBlowingVelocity() - - blowing1_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing1_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing1_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing1 = np.concatenate([blowing1_part1, blowing1_part2, blowing1_part3]) - - isec.y[j] = save - delta - isec.computeLocalCoordinates() - isec.computeBlowingVelocity() - - blowing2_part1 = np.asarray(self.isol.sec[0][0].blowingVelocity) - blowing2_part2 = np.asarray(self.isol.sec[0][1].blowingVelocity) - blowing2_part3 = np.asarray(self.isol.sec[0][2].blowingVelocity) - blowing2 = np.concatenate([blowing2_part1, blowing2_part2, blowing2_part3]) - bb = (blowing1 - blowing2)/(2*delta) - - isec.y[j] = save - dRblw_x_fd[offsetElems:offsetElems+isec.nElms, rowj*nDim+1] = -bb[offsetElems:offsetElems+isec.nElms] - offsetElems += isec.nElms - for row in range(len(dRblw_x[:,0])): - print(dRblw_x[row,:] - dRblw_x_fd[row,:]) - print( - 'max diff', np.max(np.abs(dRblw_x - dRblw_x_fd))) - quit()""" - - print('Imposing matrix') - self.coupledAdjointSolver.setdRdStar_M(dRdStar_M) - print('dRdStar_M done') - self.coupledAdjointSolver.setdRdStar_v(dRdStar_v) - print('dRdStar_v done') - self.coupledAdjointSolver.setdRdStar_dStar(dRdStar_dStar) - print('dRdStar_dStar done') - self.coupledAdjointSolver.setdRdStar_x(dRdStar_x) - print('dRdStar_x done') - - - self.coupledAdjointSolver.setdRblw_rho(dRblw_rho) - print('dRblw_rho done') - self.coupledAdjointSolver.setdRblw_v(dRblw_v) - print('dRblw_v done') - self.coupledAdjointSolver.setdRblw_dStar(dRblw_dStar) - print('dRblw_dStar done') - self.coupledAdjointSolver.setdRblw_x(dRblw_x) - print('dRblw_x done') - - def __getDeltaStar(self): - deltaStar_part1 = np.asarray(self.isol.sec[0][0].deltaStar) - deltaStar_part2 = np.asarray(self.isol.sec[0][1].deltaStar) - deltaStar_part3 = np.asarray(self.isol.sec[0][2].deltaStar) - deltaStar = np.concatenate([deltaStar_part1, deltaStar_part2, deltaStar_part3]) - #deltaStar = np.concatenate([deltaStar_part1, deltaStar_part2]) - return deltaStar - - def setvMesh(self, vBnd, secs): - import tbox - # Compute section chord - xMin = np.min(vBnd[0][0].nodesCoord[:,0]) - xMax = np.max(vBnd[0][0].nodesCoord[:,0]) - chord = xMax - xMin - for reg in secs: - if reg.name == 'wake': - iReg = 1 - elif reg.name == 'lower' or reg.name == 'upper': - iReg = 0 - else: - raise RuntimeError('Invalid region', reg.name) - - nodeRows = tbox.std_vector_int() - for val in vBnd[0][iReg].getNodesRow(reg.name): - nodeRows.push_back(int(val)) - connectElems = tbox.std_vector_int() - for val in vBnd[0][iReg].getConnectList(reg.name): - connectElems.push_back(int(val)) - # x, y, z - xv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 0): - xv.push_back(val) - yv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 1): - yv.push_back(val) - zv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 2): - zv.push_back(val) - - # Set mesh - reg.setMesh(xv, - yv, - zv, - chord, - xMin, - nodeRows, - connectElems) - - def __runViscous(self): - ext = self.vsol.run() - if ext != 0: - raise ValueError('Viscous solver did not converge') - deltaStar = self.__getDeltaStar() - return deltaStar diff --git a/blast/src/DCoupledAdjoint.cpp b/blast/src/DCoupledAdjoint.cpp index e71203795e1e1969ead3c77129565d7cbe52116f..8ea9318add45b1a8ec63c746970f578903e819fb 100644 --- a/blast/src/DCoupledAdjoint.cpp +++ b/blast/src/DCoupledAdjoint.cpp @@ -72,11 +72,6 @@ void CoupledAdjoint::reset() for (auto bBC : isol->pbl->bBCs) nEs += bBC->uE.size(); // Number of blowing elements - std::cout << "nDim " << nDim << std::endl; - std::cout << "nNd " << nNd << std::endl; - std::cout << "nNs " << nNs << std::endl; - std::cout << "nEs " << nEs << std::endl; - dRphi_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNd); dRM_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); dRrho_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNd); @@ -130,8 +125,12 @@ void CoupledAdjoint::reset() dRphi_AoA = Eigen::VectorXd::Zero(nNd); // Objective functions + // Cl = f(phi) & Cd = Cdp + Cdf = f(phi, M, v) dCl_phi = Eigen::VectorXd::Zero(nNd); dCd_phi = Eigen::VectorXd::Zero(nNd); + dCd_M = Eigen::VectorXd::Zero(nNs); + dCd_v = Eigen::VectorXd::Zero(nDim*nNs); + dCd_dStar = Eigen::VectorXd::Zero(nNs); // Angle of attack dCl_AoA = 0.0; @@ -142,7 +141,8 @@ void CoupledAdjoint::reset() // Mesh dRx_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNd, nDim*nNd); dCl_x = Eigen::VectorXd::Zero(nDim*nNd); - dCd_x = Eigen::VectorXd::Zero(nDim*nNd); + dCdp_x = Eigen::VectorXd::Zero(nDim*nNd); + dCdf_x = Eigen::VectorXd::Zero(nDim*nNd); tdCl_x.resize(nNd, Eigen::Vector3d::Zero()); tdCd_x.resize(nNd, Eigen::Vector3d::Zero()); @@ -192,17 +192,35 @@ void CoupledAdjoint::buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMat void CoupledAdjoint::run() { + tms["0-adj_total"].start(); + tms["1-adj_inviscid"].start(); gradientswrtInviscidFlow(); + tms["1-adj_inviscid"].stop(); + tms["2-adj_mach"].start(); gradientswrtMachNumber(); + tms["2-adj_mach"].stop(); + tms["3-adj_density"].start(); gradientswrtDensity(); + tms["3-adj_density"].stop(); + tms["4-adj_velocity"].start(); gradientswrtVelocity(); + tms["4-adj_velocity"].stop(); + tms["5-adj_dStar"].start(); gradientswrtDeltaStar(); + tms["5-adj_dStar"].stop(); + tms["6-adj_blw"].start(); gradientswrtBlowingVelocity(); + tms["6-adj_blw"].stop(); + tms["7-adj_aoa"].start(); gradientwrtAoA(); + tms["7-adj_aoa"].stop(); + tms["8-adj_mesh"].start(); gradientwrtMesh(); + tms["8-adj_mesh"].stop(); transposeMatrices(); + tms["9-build"].start(); // Store pointers to the matrices in a 2D vector std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> matrices = { {&dRphi_phi, &dRM_phi, &dRrho_phi, &dRv_phi, &dRdStar_phi, &dRblw_phi}, @@ -218,6 +236,7 @@ void CoupledAdjoint::run() for (const auto& mat1 : matrices[0]) cols += mat1->cols(); // All matrices in a column have the same number of columns Eigen::SparseMatrix<double, Eigen::RowMajor> A_adjoint(rows, cols); buildAdjointMatrix(matrices, A_adjoint); + tms["9-build"].stop(); size_t phiIdx = 0; size_t machIdx = dRphi_phi.cols(); @@ -229,13 +248,15 @@ void CoupledAdjoint::run() //***** Gradient wrt angle of attack *****// //****************************************// // CL + tms["10-solveCxAoA"].start(); std::vector<double> rhsCl(A_adjoint.cols(), 0.0); - for (auto i = 0; i<dCl_phi.size(); ++i) + for (auto i = phiIdx; i<phiIdx+dCl_phi.size(); ++i) rhsCl[i] = dCl_phi[i]; // Only dCl_dphi is non-zero Eigen::VectorXd rhsCl_ = Eigen::Map<const Eigen::VectorXd>(rhsCl.data(), rhsCl.size()); Eigen::VectorXd lambdaCl(A_adjoint.cols()); // Solution vector for lambdasCl Eigen::Map<Eigen::VectorXd> lambdaCl_(lambdaCl.data(), lambdaCl.size()); + alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCl_.data(), rhsCl_.size()), lambdaCl_); // Total gradient @@ -243,17 +264,40 @@ void CoupledAdjoint::run() // CD std::vector<double> rhsCd(A_adjoint.cols(), 0.0); - for (auto i = 0; i<dCd_phi.size(); ++i) - rhsCd[i] = dCd_phi[i]; + int jj = 0; + for (auto i = phiIdx; i<phiIdx+dCd_phi.size(); ++i) + { + rhsCd[i] = dCd_phi[jj]; + jj++; + } + jj = 0; + for (auto i = machIdx; i<machIdx+dCd_M.size(); ++i) + { + rhsCd[i] = dCd_M[jj]; + jj++; + } + jj = 0; + for (auto i = vIdx; i<vIdx+dCd_v.size(); ++i) + { + rhsCd[i] = dCd_v[jj]; + jj++; + } + jj = 0; + for (auto i = dStarIdx; i<dStarIdx+dCd_dStar.size(); ++i) + { + rhsCd[i] = dCd_dStar[jj]; + jj++; + } Eigen::VectorXd rhsCd_ = Eigen::Map<const Eigen::VectorXd>(rhsCd.data(), rhsCd.size()); Eigen::VectorXd lambdaCd(A_adjoint.cols()); // Solution vector for lambdasCd Eigen::Map<Eigen::VectorXd> lambdaCd_(lambdaCd.data(), lambdaCd.size()); - // Solve linear system + alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCd_.data(), rhsCd_.size()), lambdaCd_); // Total gradient tdCd_AoA = dCd_AoA - dRphi_AoA.transpose()*lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Total gradient + tms["10-solveCxAoA"].stop(); //***** Gradient wrt mesh coordinates *****// //*****************************************// @@ -261,6 +305,7 @@ void CoupledAdjoint::run() // Solution lambdaCl_x of (from augmented Lagrangian, eqn d/dx ) // "dCk_x + dRphi_x * lambdaCk_phi + dRdStar_x * lambdaCk_x + dRblw_x * lambdaCk_blw + dRx_x * lambdaCk_x = 0" + tms["12-solveCxMesh"].start(); Eigen::VectorXd rhsCl_x = dCl_x; rhsCl_x -= dRphi_x.transpose() * lambdaCl.segment(phiIdx, dRphi_phi.cols()); // Potential contribution rhsCl_x -= dRM_x.transpose() * lambdaCl.segment(machIdx, dRM_M.cols()); // Mach number contribution @@ -273,7 +318,8 @@ void CoupledAdjoint::run() Eigen::Map<Eigen::VectorXd> lambdaCl_x_(lambdaCl_x.data(), lambdaCl_x.size()); alinsol->compute(dRx_x.transpose(), Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size()), lambdaCl_x_); - Eigen::VectorXd rhsCd_x = dCd_x; + Eigen::VectorXd rhsCd_x = dCdp_x; // Pressure drag coefficient contribution + rhsCd_x += dCdf_x; // Friction drag coefficient contribution rhsCd_x -= dRphi_x.transpose() * lambdaCd.segment(phiIdx, dRphi_phi.cols()); // Potential contribution rhsCd_x -= dRM_x.transpose() * lambdaCd.segment(machIdx, dRM_M.cols()); // Mach number contribution rhsCd_x -= dRrho_x.transpose() * lambdaCd.segment(rhoIdx, dRrho_rho.cols()); // Density contribution @@ -293,6 +339,8 @@ void CoupledAdjoint::run() tdCd_x[n->row](m) = lambdaCd_x[isol->pbl->nDim * (n->row) + m]; } } + tms["12-solveCxMesh"].stop(); + //std::cout << tms << std::endl; } /** @@ -363,6 +411,57 @@ void CoupledAdjoint::gradientswrtInviscidFlow() // Remove zeros dRM_phi.prune(0.); dRrho_phi.prune(0.); dRv_phi.prune(0.); + // // Analytical + // std::vector<Eigen::Triplet<double>> tripletsdM_an; + + // size_t jj = 0; + // int iReg = 0; + // for (auto sec : vsol->sections[0]) + // { + // if (sec->name == "wake") + // iReg = 1; + // else if (sec->name == "upper" || sec->name == "lower") + // iReg = 0; + // else + // throw std::runtime_error("gradientswrtInviscidFlow: Unknown section name"); + // for (size_t iNode = 0; iNode < sec->nNodes; ++iNode) + // { + // tbox::Node* srfNode = pbl->bBCs[iReg]->nodes[sec->rows[iNode]]; + // for (auto e: pbl->fluid->neMap[srfNode]) + // { + // // Get pre-computed values + // tbox::Cache &cache = e->getVCache(); + // tbox::Gauss &gauss = cache.getVGauss(); + // Eigen::VectorXd grad = Eigen::VectorXd::Zero(e->nodes.size()); + // for (size_t k = 0; k < gauss.getN(); ++k) + // { + // // Gauss point and determinant + // double wdj = gauss.getW(k) * e->getDetJ(k); + // // Shape functions and solution gradient + // Eigen::MatrixXd const &dSf = e->getJinv(k) * cache.getDsf(k); + // Eigen::VectorXd dPhi = e->computeGradient(isol->phi, k); + // grad += isol->pbl->fluid->mach->evalGrad(*e, isol->phi, k) * dSf.transpose() * dPhi; + // } + // for (size_t k = 0; k < e->nodes.size(); ++k) + // { + // tripletsdM_an.push_back(Eigen::Triplet<double>(jj, e->nodes[k]->row, -grad(k)/e->nodes.size())); + // } + // } + // ++jj; + // } + // } + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_phi_an(dRM_phi.rows(), dRM_phi.cols()); + // dRM_phi_an.setFromTriplets(tripletsdM_an.begin(), tripletsdM_an.end()); + // dRM_phi_an.prune(0.); + // writeMatrixToFile(dRM_phi_an, "dRM_phi_an.txt"); + // writeMatrixToFile(dRM_phi, "dRM_phi.txt"); + // writeMatrixToFile((dRM_phi_an - dRM_phi), "dif.txt"); + // std::cout << "written" << std::endl; + // std::cout << dRM_phi_an - dRM_phi << std::endl; + + // throw; + + //**** partials dCl_phi, dCd_phi ****// std::vector<std::vector<double>> dCx_phi = iadjoint->computeGradientCoefficientsFlow(); dCl_phi = Eigen::VectorXd::Map(dCx_phi[0].data(), dCx_phi[0].size()); @@ -385,6 +484,7 @@ void CoupledAdjoint::gradientswrtMachNumber() size_t i = 0; double saveM = 0.; std::vector<Eigen::VectorXd> ddStar(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); for (auto sec: vsol->sections[0]) for (size_t j = 0; j < sec->nNodes; ++j) { @@ -392,13 +492,17 @@ void CoupledAdjoint::gradientswrtMachNumber() sec->Me[j] = saveM + delta; ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; sec->Me[j] = saveM - delta; ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; sec->Me[j] = saveM; for (int k = 0; k < ddStar[0].size(); ++k) T.push_back(Eigen::Triplet<double>(k, i, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); + // Collect Cd gradients + dCd_M(i) = (dCdf[0] - dCdf[1])/(2.*delta); ++i; } dRdStar_M.setFromTriplets(T.begin(), T.end()); @@ -501,6 +605,8 @@ void CoupledAdjoint::gradientswrtVelocity() i = 0; double saveM = 0.; std::vector<Eigen::VectorXd> dvt(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); + Eigen::VectorXd dCd_vt = Eigen::VectorXd::Zero(dRM_M.cols()); for (auto sec: vsol->sections[0]) for (size_t j = 0; j < sec->nNodes; ++j) { @@ -508,13 +614,16 @@ void CoupledAdjoint::gradientswrtVelocity() sec->vt[j] = saveM + delta; dvt[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; sec->vt[j] = saveM - delta; dvt[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; sec->vt[j] = saveM; for (int k = 0; k < dvt[0].size(); ++k) T.push_back(Eigen::Triplet<double>(k, i, -(dvt[0][k] - dvt[1][k])/(2.*delta))); + dCd_vt(i) = (dCdf[0] - dCdf[1])/(2.*delta); ++i; } Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_vt(dRdStar_M.rows(), dRdStar_M.cols()); @@ -525,6 +634,8 @@ void CoupledAdjoint::gradientswrtVelocity() dRdStar_v = dRdStar_vt * dVt_v; dRdStar_v.prune(0.); + //**** dRCdf_v ****// + dCd_v = dCd_vt.transpose() * dVt_v; // [1xnNs] x [nNs x nNs*nDim] = [1 x nNs*nDim] //**** dRblw_vt (analytical) ****// std::deque<Eigen::Triplet<double>> T_blw; @@ -561,6 +672,7 @@ void CoupledAdjoint::gradientswrtDeltaStar() double delta = 1e-6; double saveDStar = 0.; std::vector<Eigen::VectorXd> ddstar(2, Eigen::VectorXd::Zero(dRdStar_dStar.cols())); + std::vector<double> dCdf(2, 0.); size_t i = 0; for (auto sec: vsol->sections[0]) for (size_t j = 0; j < sec->nNodes; ++j) @@ -569,13 +681,16 @@ void CoupledAdjoint::gradientswrtDeltaStar() sec->deltaStarExt[j] = saveDStar + delta; ddstar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; sec->deltaStarExt[j] = saveDStar - delta; ddstar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; sec->deltaStarExt[j] = saveDStar; for (int k = 0; k < ddstar[0].size(); ++k) T.push_back(Eigen::Triplet<double>(k, i, (ddstar[0][k] - ddstar[1][k])/(2.*delta))); + dCd_dStar(i) = (dCdf[0] - dCdf[1])/(2.*delta); ++i; } Eigen::SparseMatrix<double, Eigen::RowMajor> dRdStar_dStar_dum(dRdStar_dStar.rows(), dRdStar_dStar.cols()); @@ -663,13 +778,101 @@ void CoupledAdjoint::gradientwrtMesh(){ /**** dCk_dx ****/ std::vector<std::vector<double>> dCx_x = iadjoint->computeGradientCoefficientsMesh(); dCl_x = Eigen::Map<Eigen::VectorXd>(dCx_x[0].data(), dCx_x[0].size()); - dCd_x = Eigen::Map<Eigen::VectorXd>(dCx_x[1].data(), dCx_x[1].size()); + dCdp_x = Eigen::Map<Eigen::VectorXd>(dCx_x[1].data(), dCx_x[1].size()); /**** dRphi_x ****/ dRphi_x = iadjoint->getRu_X(); /**** dRx_x ****/ dRx_x = iadjoint->getRx_X(); + /**** dRdStar_x ****/ + std::deque<Eigen::Triplet<double>> T_dStar_x; + double delta = 1e-8; + size_t i = 0; + int iReg = 0; + double saveX = 0.; + std::vector<Eigen::VectorXd> ddStar(2, Eigen::VectorXd::Zero(dRdStar_M.cols())); + std::vector<double> dCdf(2, 0.); + for (auto sec: vsol->sections[0]) + { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + for (size_t j = 0; j < sec->nNodes; ++j) + { + int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; + // x + saveX = sec->x[j]; + + sec->x[j] = saveX + delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->x[j] = saveX - delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->x[j] = saveX; + + for (int k = 0; k < ddStar[0].size(); ++k) + T_dStar_x.push_back(Eigen::Triplet<double>(k, rowj*isol->pbl->nDim+0, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); + dCdf_x(rowj*isol->pbl->nDim+0) += (dCdf[0] - dCdf[1])/(2.*delta); + // y + saveX = sec->y[j]; + + sec->y[j] = saveX + delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[0] = this->runViscous(); + dCdf[0] = vsol->Cdf; + sec->y[j] = saveX - delta; + sec->computeLocalCoordinates(); + sec->xxExt = sec->loc; + ddStar[1] = this->runViscous(); + dCdf[1] = vsol->Cdf; + + sec->y[j] = saveX; + + for (int k = 0; k < ddStar[0].size(); ++k) + T_dStar_x.push_back(Eigen::Triplet<double>(k, rowj*isol->pbl->nDim+1, -(ddStar[0][k] - ddStar[1][k])/(2.*delta))); + dCdf_x(rowj*isol->pbl->nDim+1) += (dCdf[0] - dCdf[1])/(2.*delta); + ++i; + } + } + dRdStar_x.setFromTriplets(T_dStar_x.begin(), T_dStar_x.end()); + dRdStar_x.prune(0.); + + /**** dRblw_x ****/ + std::deque<Eigen::Triplet<double>> T_blw_x; + int offSetElms = 0; + for (const auto& sec: vsol->sections[0]) + { + if (sec->name == "wake") + iReg = 1; + else if (sec->name == "upper" || sec->name == "lower") + iReg = 0; + else + throw std::runtime_error("Unknown section name"); + std::vector<std::vector<double>> gradX = sec->evalGradwrtX(); + std::vector<std::vector<double>> gradY = sec->evalGradwrtY(); + for (size_t i = 0; i < gradX.size(); ++i) + for (size_t j = 0; j < gradX[i].size(); ++j) + { + int rowj = isol->pbl->bBCs[iReg]->nodes[sec->rows[j]]->row; + T_blw_x.push_back(Eigen::Triplet<double>(i + offSetElms, rowj*isol->pbl->nDim+0, -gradX[i][j])); + T_blw_x.push_back(Eigen::Triplet<double>(i + offSetElms, rowj*isol->pbl->nDim+1, -gradY[i][j])); + } + offSetElms += sec->nElms; + } + dRblw_x.setFromTriplets(T_blw_x.begin(), T_blw_x.end()); + dRblw_x.prune(0.); + /**** dRM_x, dRrho_x, dRv_x ****/ double delta_x = 1e-8; auto pbl = isol->pbl; @@ -831,8 +1034,6 @@ void CoupledAdjoint::setdRblw_x(std::vector<std::vector<double>> _dRblw_x){ Eigen::VectorXd CoupledAdjoint::runViscous() { int exitCode = vsol->run(); - if (exitCode != 0) - throw std::runtime_error("CoupledAdjoint::runViscous: Solver did not converge"); // Extract deltaStar std::vector<Eigen::VectorXd> dStar_p; diff --git a/blast/src/DCoupledAdjoint.h b/blast/src/DCoupledAdjoint.h index 09936987b47e07fdb33074654f432ce15536bd29..086a70d31cd853d8508bf4d59e111bd4d8dac390 100644 --- a/blast/src/DCoupledAdjoint.h +++ b/blast/src/DCoupledAdjoint.h @@ -20,6 +20,7 @@ #include "blast.h" #include "wObject.h" #include "dart.h" +#include "wTimers.h" #include <Eigen/Sparse> #include <iostream> @@ -99,16 +100,23 @@ private: // Objective functions Eigen::VectorXd dCl_phi; ///< Derivative of the lift coefficient with respect to the inviscid flow Eigen::VectorXd dCd_phi; ///< Derivative of the drag coefficient with respect to the inviscid flow + Eigen::VectorXd dCd_M; ///< Derivative of the drag coefficient with respect to the Mach number + Eigen::VectorXd dCd_rho; ///< Derivative of the drag coefficient with respect to the density + Eigen::VectorXd dCd_v; ///< Derivative of the drag coefficient with respect to the velocity + Eigen::VectorXd dCd_dStar; ///< Derivative of the drag coefficient with respect to delta* // Angle of attack Eigen::VectorXd dRphi_AoA; ///< Derivative of the inviscid flow residual with respect to the angle of attack double dCl_AoA; ///< Partial derivative of the lift coefficient with respect to the angle of attack - double dCd_AoA; ///< Partial erivative of the drag coefficient with respect to the angle of attack + double dCd_AoA; ///< Partial derivative of the total drag coefficient with respect to the angle of attack // Mesh Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_x; ///< Derivative of the mesh residual with respect to the mesh coordinates Eigen::VectorXd dCl_x; ///< Partial derivative of the lift coefficient with respect to the mesh coordinates - Eigen::VectorXd dCd_x; ///< Partial derivative of the drag coefficient with respect to the mesh coordinates + Eigen::VectorXd dCdp_x; ///< Partial derivative of the pressure drag coefficient with respect to the mesh coordinates + Eigen::VectorXd dCdf_x; ///< Partial derivative of the friction drag coefficient with respect to the mesh coordinates + + fwk::Timers tms; //< internal timers public: CoupledAdjoint(std::shared_ptr<dart::Adjoint> iAdjoint, std::shared_ptr<blast::Driver> vSolver); diff --git a/blast/tests/dart/adjointVII_2D.py b/blast/tests/dart/adjointVII_2D.py index 44401961d30404d840627b175d422ca6e2cf1c9a..ea6db8211ea1d332f2aaf6157edf445efe66570b 100644 --- a/blast/tests/dart/adjointVII_2D.py +++ b/blast/tests/dart/adjointVII_2D.py @@ -18,13 +18,11 @@ # @author Paul Dechamps # @date 2024 -# Test the blast adjoint implementation. +# Test the blaster adjoint implementation. # Imports. import blast.utils as viscUtils -from blast.interfaces.DAdjointInterface import AdjointInterface -import modules.dartflo.dart.default as floD import blast import numpy as np @@ -38,9 +36,6 @@ from fwk.testing import * from fwk.coloring import ccolors import numpy as np -import os -import sys - def cfgInviscid(nthrds, verb): import os.path # Parameters @@ -110,24 +105,18 @@ def main(): alpha = icfg['AoA']*np.pi/180 dalpha = 1e-6 * np.pi/180 daoa = [alpha - dalpha, alpha + dalpha] - dcl = [] - dcd = [] coupler, isol, vsol = viscUtils.initBlast(icfg, vcfg) morpher = isol.iobj['mrf'] # Adjoint objects cAdj = blast.CoupledAdjoint(isol.adjointSolver, vsol) - pyAdjoint = AdjointInterface(cAdj, isol, vsol) # Run coupled case print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) tms['forward'].start() aeroCoeffs = coupler.run() - tms['forward'].stop() - - # Print with precision of 1e-12 - print(f"{isol.solver.Cl:.12f}", f"{isol.solver.Cd:.12f}") + tms['forward'].stop() print(ccolors.ANSI_BLUE + 'PyDartAdjoint...' + ccolors.ANSI_RESET) tms['adj_dart'].start() @@ -135,9 +124,6 @@ def main(): tms['adj_dart'].stop() print(ccolors.ANSI_BLUE + 'PyBlasterAdjoint...' + ccolors.ANSI_RESET) - tms['adj_py'].start() - pyAdjoint.build() - tms['adj_py'].stop() tms['adj_blast'].start() cAdj.run() tms['adj_blast'].stop() @@ -161,9 +147,9 @@ def main(): coupler.reset() aeroCoeffs = coupler.run(write=False) dcl.append(isol.getCl()) - dcd.append(isol.getCd()) - dCl_AoA_FD = (dcl[-1] - dcl[-2])/(2*dalpha) - dCd_AoA_FD = (dcd[-1] - dcd[-2])/(2*dalpha) + dcd.append(isol.getCd()+vsol.Cdf) + dCl_AoA_FD = (dcl[-1] - dcl[-2])/(2.*dalpha) + dCd_AoA_FD = (dcd[-1] - dcd[-2])/(2.*dalpha) tms['fd_blaster_aoa'].stop() isol.setAoA(icfg['AoA']*np.pi/180) # Reset AoA after FD @@ -190,7 +176,6 @@ def main(): import time start_time = time.time() for inod, n in enumerate(isol.blw[0].nodes): - vidx = np.where(isol.vBnd[0][0].nodesCoord[:,3] == n.row)[0][0] # Safety check if isol.iobj['bnd'].nodes[inod].row != n.row: raise RuntimeError('Nodes do not match', n.row, isol.iobj['bnd'].nodes[inod].row) @@ -201,40 +186,35 @@ def main(): morpher.savePos() n.pos[idim] = saveNodes[n.row, idim] + sign * delta morpher.deform() - isol.vBnd[0][0].nodesCoord[vidx, idim] = saveNodes[n.row, idim] + sign * delta - setvMesh(isol.vBnd, isol.sec[0]) + isol.updateMesh() coupler.reset() # prevent print from contextlib import redirect_stdout with redirect_stdout(None): - aeroCoeffs = coupler.run(write=False) + coupler.run(write=False) cmp += 1 if cmp % 20 == 0: print('F-D opers', cmp, '/', isol.blw[0].nodes.size() * isol.getnDim() * 2, '(node '+str(n.row)+')', 'time', str(round(time.time() - start_time, 3))+'s') cl[isgn] = isol.getCl() - cd[isgn] = isol.getCd() + cd[isgn] = isol.getCd() + vsol.Cdf # Reset mesh for node in isol.iobj['sol'].pbl.msh.nodes: for d in range(isol.getnDim()): node.pos[d] = saveNodes[node.row, d] - for jj, jrow in enumerate(isol.vBnd[0][0].nodesCoord[:,3]): - for d in range(isol.getnDim()): - isol.vBnd[0][0].nodesCoord[jj, d] = saveNodes[int(jrow), d] - dCl_x_blaster_fd[inod, idim] = (cl[1] - cl[0]) / (2 * delta) - dCd_x_blaster_fd[inod, idim] = (cd[1] - cd[0]) / (2 * delta) + dCl_x_blaster_fd[inod, idim] = (cl[1] - cl[0]) / (2. * delta) + dCd_x_blaster_fd[inod, idim] = (cd[1] - cd[0]) / (2. * delta) tms['fd_blaster_msh'].stop() print('Statistics') print(tms) - print(ccolors.ANSI_BLUE + 'PyTesting' + ccolors.ANSI_RESET) tests = CTests() tests.add(CTest('dCl_dAoA', cAdj.tdCl_AoA, dCl_AoA_FD, 1e-5)) tests.add(CTest('dCd_dAoA', cAdj.tdCd_AoA, dCd_AoA_FD, 1e-4)) - tests.add(CTest('norm dCl_dx (adj - fd)', np.linalg.norm(dCl_x), np.linalg.norm(dCl_x_blaster_fd), 1e-4)) - tests.add(CTest('norm dCd_dx (adj - fd)', np.linalg.norm(dCd_x), np.linalg.norm(dCd_x_blaster_fd), 1e-3)) + tests.add(CTest('norm dCl_dx (adj - fd)', np.linalg.norm(dCl_x), np.linalg.norm(dCl_x_blaster_fd), 1e-6)) + tests.add(CTest('norm dCd_dx (adj - fd)', np.linalg.norm(dCd_x), np.linalg.norm(dCd_x_blaster_fd), 1e-4)) tests.add(CTest('dCl_dAoA (msh)', dCl_AoA_fromX, cAdj.tdCl_AoA, 1e-2)) # The value gets closer if the mesh if refined tests.add(CTest('dCd_dAoA (msh)', dCd_AoA_fromX, cAdj.tdCd_AoA, 1e-1)) # The value gets closer if the mesh if refined tests.run() @@ -242,48 +222,5 @@ def main(): # eof print('') -def setvMesh(vBnd, secs): - import tbox - # Compute section chord - xMin = np.min(vBnd[0][0].nodesCoord[:,0]) - xMax = np.max(vBnd[0][0].nodesCoord[:,0]) - chord = xMax - xMin - for reg in secs: - if reg.name == 'wake': - iReg = 1 - elif reg.name == 'lower' or reg.name == 'upper': - iReg = 0 - else: - raise RuntimeError('Invalid region', reg.name) - - nodeRows = tbox.std_vector_int() - for val in vBnd[0][iReg].getNodesRow(reg.name): - nodeRows.push_back(int(val)) - connectElems = tbox.std_vector_int() - for val in vBnd[0][iReg].getConnectList(reg.name): - connectElems.push_back(int(val)) - # x, y, z - xv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 0): - xv.push_back(val) - yv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 1): - yv.push_back(val) - zv = tbox.std_vector_double() - for val in vBnd[0][iReg].getNodesCoord(reg.name, 2): - zv.push_back(val) - - # Set mesh - reg.setMesh(xv, - yv, - zv, - chord, - xMin, - nodeRows, - connectElems) - - reg.xxExt = reg.loc - - if __name__ == '__main__': main() \ No newline at end of file