From 3619cea4bfe0c2a25c08520423bdd0b1eece4a0b Mon Sep 17 00:00:00 2001 From: Paul Dechamps <paul.dechamps@uliege.be> Date: Tue, 26 Mar 2024 23:41:37 +0100 Subject: [PATCH] (fix) Update adjoint Validating mesh w/ finite difference. Removed morpher from computation of fd --- blast/coupler.py | 1 + blast/interfaces/dart/DartAdjointInterface.py | 9 +- blast/src/DCoupledAdjoint.cpp | 7 +- blast/tests/dart/adjointVIImesh.py | 336 +++++++++++++++--- 4 files changed, 299 insertions(+), 54 deletions(-) diff --git a/blast/coupler.py b/blast/coupler.py index ba45552..64fb433 100644 --- a/blast/coupler.py +++ b/blast/coupler.py @@ -69,6 +69,7 @@ class Coupler: self.iSolverAPI.imposeBlwVel() self.tms['processing'].stop() + # TODO Change aeroCoeffs to dict aeroCoeffs = np.vstack((aeroCoeffs, [self.iSolverAPI.getCl(), self.vSolver.Cdt, self.vSolver.Cdf + self.iSolverAPI.getCd(), self.vSolver.Cdf])) # Check convergence status. diff --git a/blast/interfaces/dart/DartAdjointInterface.py b/blast/interfaces/dart/DartAdjointInterface.py index 527e4eb..e9e62d7 100644 --- a/blast/interfaces/dart/DartAdjointInterface.py +++ b/blast/interfaces/dart/DartAdjointInterface.py @@ -23,7 +23,7 @@ class DartAdjointInterface(): # for iRegv in range(2): # self.deltaStarExt[0][iRegv] = self.vSolver.extractDeltaStar(0, iRegv) - delta = 1e-5 + delta = 1e-6 saveBlw = np.zeros(nEs) for i in range(nEs): @@ -42,6 +42,7 @@ class DartAdjointInterface(): savex[iNo, jj] = self.iSolverAPI.iBnd[0].nodesCoord[iNo, jj] # Mach + print('Mach') for iNo in range(nNs): irow = self.iSolverAPI.blw[0].nodes[iNo].row self.iSolverAPI.solver.M[irow] += delta @@ -50,6 +51,7 @@ class DartAdjointInterface(): self.iSolverAPI.solver.M[irow] = saveMach[iNo] # Rho + print('Density') for iNo in range(nNs): irow = self.iSolverAPI.blw[0].nodes[iNo].row self.iSolverAPI.solver.rho[irow] += delta @@ -58,6 +60,7 @@ class DartAdjointInterface(): self.iSolverAPI.solver.rho[irow] = saverho[iNo] # # V + print('Velocity') for iNo in range(nNs): irow = self.iSolverAPI.blw[0].nodes[iNo].row for iDim in range(nDim): @@ -67,9 +70,9 @@ class DartAdjointInterface(): self.iSolverAPI.solver.U[irow][iDim] = savev[iNo*nDim + iDim] # # Mesh coordinates + print('Mesh') for iNo in range(nNs): - PAS BON CA. IL FAUT ALLER RECHERCHER LA BONNE ROW DANS nodesCoord (colonne 4 normalement). - irow = self.iSolverAPI.blw[0].nodes[iNo].row + irow = int(self.iSolverAPI.iBnd[0].nodesCoord[iNo,3]) for iDim in range(nDim): self.iSolverAPI.iBnd[0].nodesCoord[iNo, iDim] += delta blowing = self.__runViscous() diff --git a/blast/src/DCoupledAdjoint.cpp b/blast/src/DCoupledAdjoint.cpp index 64a530d..072c589 100644 --- a/blast/src/DCoupledAdjoint.cpp +++ b/blast/src/DCoupledAdjoint.cpp @@ -213,16 +213,12 @@ void CoupledAdjoint::run() Eigen::VectorXd rhsCl_x = dCl_x - dRphi_x.transpose() * lambdaClPhi - dRblw_x.transpose() * lambdaClBlw; alinsol->compute(dRx_x.transpose(), Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size()), lambdaCl_x_); - std::cout << "dRblw_x.transpose().norm() " << std::setprecision(15) << dRblw_x.transpose().norm() << std::endl; - std::cout << " lambdaClBlw.norm() " << std::setprecision(15) << lambdaClBlw.norm() << std::endl; - std::cout << "normClAoA " << std::setprecision(15) << tdCl_AoA << " Norm lambdaCl_x " << lambdaCl_x.norm() << std::endl; - throw; - for (auto n : isol->pbl->msh->nodes) { for (int m = 0; m < isol->pbl->nDim; m++) { tdCl_x[n->row](m) = lambdaCl_x[isol->pbl->nDim * (n->row) + m]; + // TODO: CHANGER POUR CD tdCd_x[n->row](m) = lambdaCl_x[isol->pbl->nDim * (n->row) + m]; } } @@ -337,7 +333,6 @@ void CoupledAdjoint::gradientwrtMesh(){ dCd_x = Eigen::Map<Eigen::VectorXd>(dCx_x[1].data(), dCx_x[1].size()); dRphi_x = iadjoint->getRu_X(); - std::cout << "AT input dRphi_x " << dRphi_x.rows() << " " << dRphi_x.cols() << " " << dRphi_x.norm() << std::endl; dRx_x = iadjoint->getRx_X(); } diff --git a/blast/tests/dart/adjointVIImesh.py b/blast/tests/dart/adjointVIImesh.py index ec40bb9..27fde99 100644 --- a/blast/tests/dart/adjointVIImesh.py +++ b/blast/tests/dart/adjointVIImesh.py @@ -56,7 +56,7 @@ def cfgInviscid(nthrds, verb): 'Verb' : verb, # verbosity # Model (geometry or mesh) 'File' : os.path.dirname(os.path.abspath(__file__)) + '/../../models/dart/n0012.geo', # Input file containing the model - 'Pars' : {'xLgt' : 50, 'yLgt' : 50, 'msF' : 20, 'msTe' : 0.01, 'msLe' : 0.0075}, # parameters for input file model + 'Pars' : {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.05, 'msLe' : 0.05}, # parameters for input file model 'Dim' : 2, # problem dimension 'Format' : 'gmsh', # save format (vtk or gmsh) # Markers @@ -66,7 +66,7 @@ def cfgInviscid(nthrds, verb): 'Wake' : 'wake', # LIST of names of physical group containing the wake 'WakeTip' : 'wakeTip', # LIST of names of physical group containing the edge of the wake 'Te' : 'te', # LIST of names of physical group containing the trailing edge - 'dbc' : True, + 'dbc' : False, 'Upstream' : 'upstream', # Freestream 'M_inf' : 0.2, # freestream Mach number @@ -93,10 +93,10 @@ def cfgBlast(verb): 'Minf' : 0.2, # Freestream Mach number (used for the computation of the time step only) 'CFL0' : 1, # Inital CFL number of the calculation 'Verb': verb, # Verbosity level of the solver - 'couplIter': 75, # Maximum number of iterations - 'couplTol' : 1e-4, # Tolerance of the VII methodology + 'couplIter': 150, # Maximum number of iterations + 'couplTol' : 1e-12, # Tolerance of the VII methodology 'iterPrint': 5, # int, number of iterations between outputs - 'resetInv' : True, # bool, flag to reset the inviscid calculation at every iteration. + 'resetInv' : False, # bool, flag to reset the inviscid calculation at every iteration. 'sections' : [0], 'xtrF' : [0.2, 0.2], # Forced transition location 'interpolator' : 'Matching', @@ -128,6 +128,8 @@ def main(): tms['pre'].stop() coupledAdjointSolver = blast.CoupledAdjoint(iSolverAPI.adjointSolver, vSolver) + import modules.dartflo.dart.default as floD + morpher = floD.morpher(iSolverAPI.argOut['msh'], iSolverAPI.argOut['pbl'].nDim, 'airfoil') from blast.interfaces.dart.DartAdjointInterface import DartAdjointInterface as DartAdjointinterface pyAdjoint = DartAdjointinterface(coupledAdjointSolver, iSolverAPI, vSolver) @@ -136,6 +138,8 @@ def main(): aeroCoeffs = coupler.run() tms['solver'].stop() + Clref = iSolverAPI.getCl() + tms['TotalAdjoint'].start() tms['dartAdjoint'].start() """for iReg in range(2): @@ -151,32 +155,108 @@ def main(): coupledAdjointSolver.run() tms['CoupledAdjoint'].stop() tms['TotalAdjoint'].stop() - print(coupledAdjointSolver.tdCl_AoA) - # Get matrix + # Get inviscid matrix + dCl_x_mat_DART = np.zeros((iSolverAPI.argOut['msh'].nodes.size(), 3)) + for n in iSolverAPI.argOut['bnd'].nodes: + for i in range(3): + dCl_x_mat_DART[n.row, i] = iSolverAPI.adjointSolver.dClMsh[n.row][i] + + # Get coupled matrix dCl_x_mat = np.zeros((iSolverAPI.argOut['msh'].nodes.size(), 3)) - for n in iSolverAPI.argOut['msh'].nodes: + for n in iSolverAPI.argOut['bnd'].nodes: for i in range(3): dCl_x_mat[n.row, i] = coupledAdjointSolver.tdCl_x[n.row][i] - - print(dCl_x_mat) - print(np.shape(dCl_x_mat)) - print(coupledAdjointSolver.tdCl_AoA, np.linalg.norm(dCl_x_mat)) - - # Get matrix - dCl_x_mat_DART = np.zeros((iSolverAPI.argOut['msh'].nodes.size(), 3)) - for n in iSolverAPI.argOut['msh'].nodes: - for i in range(3): - dCl_x_mat_DART[n.row, i] = iSolverAPI.adjointSolver.dClMsh[n.row][i] + ### Finite difference #### + print('Starting FD') + delta = 1e-6 + dCl_x_FD_coupled = np.zeros((iSolverAPI.argOut['msh'].nodes.size(),3)) + for n in iSolverAPI.argOut['bnd'].nodes: + idxV = np.where(iSolverAPI.iBnd[0].nodesCoord[:,3] == n.row)[0][0] + for idim in range(iSolverAPI.argOut['pbl'].nDim): + if iSolverAPI.iBnd[0].nodesCoord[idxV,idim] != n.pos[idim]: + print('WRONG NODE ', n.pos[i], n.row) + quit() + #morpher.savePos() + pos = n.pos[idim] + n.pos[idim] = pos + delta + iSolverAPI.iBnd[0].nodesCoord[idxV,idim] = pos + delta + #morpher.deform() # deforme le maillage et mets à jour les elements + + clPrev = 0 + iSolverAPI.reset() + for i in range(len(iSolverAPI.iBnd[0].elemsCoord[:,0])): + iSolverAPI.blw[0].setU(i, 0.) + iSolverAPI.imposeInvBC(0, adj=1) + for it in range(50): + iSolverAPI.run() + iSolverAPI.imposeInvBC(it, adj=0) + vSolver.run(it) + iSolverAPI.imposeBlwVel(adj=0) + clCurr = iSolverAPI.getCl() + if abs((clCurr - clPrev)/clCurr) < 1e-12: + print('1conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + break + clPrev = clCurr + if (it > 49): + print('Not converged') + quit() + Cl1 = iSolverAPI.getCl() + + n.pos[idim] = pos - delta + iSolverAPI.iBnd[0].nodesCoord[idxV,idim] = pos - delta + clPrev = 0 + iSolverAPI.reset() + for i in range(len(iSolverAPI.iBnd[0].elemsCoord[:,0])): + iSolverAPI.blw[0].setU(i, 0.) + iSolverAPI.imposeInvBC(0, adj=1) + for it in range(50): + iSolverAPI.run() + iSolverAPI.imposeInvBC(it, adj=0) + vSolver.run(it) + iSolverAPI.imposeBlwVel(adj=0) + clCurr = iSolverAPI.getCl() + if abs((clCurr - clPrev)/clCurr) < 1e-12: + print('2conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + break + clPrev = clCurr + if (it > 49): + print('Not converged') + quit() + Cl2 = iSolverAPI.getCl() + + n.pos[idim] = pos + iSolverAPI.iBnd[0].nodesCoord[idxV,idim] = pos + print(n.row, 'fd ', (Cl1 - Cl2)/(2*delta)) + dCl_x_FD_coupled[n.row, idim] = (Cl1 - Cl2)/(2*delta) + print(coupledAdjointSolver.tdCl_AoA) + for n in iSolverAPI.argOut['bnd'].nodes: + print('adj node', n.row, dCl_x_mat[n.row, :]) + for n in iSolverAPI.argOut['bnd'].nodes: + print('fd node', n.row, dCl_x_FD_coupled[n.row, :]) + for n in iSolverAPI.argOut['bnd'].nodes: + print('relDiff node', n.row, (dCl_x_FD_coupled[n.row, :] - dCl_x_mat[n.row, :]) / dCl_x_mat[n.row, :]) + print('norm dCl_x_mat', np.linalg.norm(dCl_x_mat)) + print('norm dCl_x_FD_coupled', np.linalg.norm(dCl_x_FD_coupled)) + print('norm dCl_x_adj_DART', np.linalg.norm(dCl_x_mat_DART)) + print('dCl_AoA', coupledAdjointSolver.tdCl_AoA) quit() + + # np.savetxt('dCl_x_FD_coupled.dat',dCl_x_FD_coupled) - ################# ONLY DART ################# + # print('COUPLED', dCl_x_mat - dCl_x_FD_coupled) + # print('DART', dCl_x_mat_DART - dCl_x_FD_dart) + # print(coupledAdjointSolver.tdCl_AoA) - args = parseargs() - icfg = cfgInviscid(args.k, args.verb) - vcfg = cfgBlast(args.verb) + # quit() + + # # # # ################# ONLY DART ################# + + # # args = parseargs() + # # icfg = cfgInviscid(args.k, args.verb) + # # vcfg = cfgBlast(args.verb) # define flow variables alpha = 2*np.pi/180 @@ -187,8 +267,8 @@ def main(): # mesh the geometry print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) tms['msh'].start() - pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1., 'msTe' : 0.01, 'msLe' : 0.01} - msh, gmshWriter = floD.mesh(dim, 'models/n0012.geo', pars, ['field', 'airfoil', 'downstream']) + pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 2., 'msTe' : 0.01, 'msLe' : 0.01} + msh, gmshWriter = floD.mesh(dim, 'models/rae2822.geo', pars, ['field', 'airfoil', 'downstream']) # create mesh deformation handler morpher = floD.morpher(msh, dim, 'airfoil') tms['msh'].stop() @@ -198,10 +278,9 @@ def main(): pbl, _, _, bnd, blw = floD.problem(msh, dim, alpha, 0., M_inf, c_ref, c_ref, 0.25, 0., 0., 'airfoil', vsc=True) tms['pre'].stop() - baseBlw = np.loadtxt('/home/paulzer/lab/blaster/blast/tests/dart/blwVelAF.dat') - for i in range(len(blw[0].nodes)-1): - blw[0].setU(int(baseBlw[i,0]), baseBlw[i,1]) - + # baseBlw = np.loadtxt('/home/paulzer/lab/blaster/blast/tests/dart/blwVelAF.dat') + # for i in range(len(blw[0].nodes)-1): + # blw[0].setU(int(baseBlw[i,0]), baseBlw[i,1]) # solve problem print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) @@ -219,25 +298,192 @@ def main(): adjoint.save(gmshWriter) tms['adjoint'].stop() - # compute norm of gradient wrt to mesh - dClX = 0 - dCdX = 0 - for n in msh.nodes: - dClX += np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]]).dot(np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]])) - dCdX += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]])) - dClX = np.sqrt(dClX) - dCdX = np.sqrt(dCdX) - - # recover gradient wrt to AoA from gradient wrt mesh - drot = np.array([[-np.sin(alpha), np.cos(alpha)], [-np.cos(alpha), -np.sin(alpha)]]) - dClAoA = 0 - dCdAoA = 0 + # Get matrix + dCl_x_mat_DART = np.zeros((msh.nodes.size(), 3)) + for n in bnd.nodes: + for i in range(3): + dCl_x_mat_DART[n.row, i] = adjoint.dClMsh[n.row][i] + print(dCl_x_mat_DART) + + dCl_x_FD = np.zeros((len(pbl.msh.nodes), 3)) + Clref = solver.Cl + delta = 1e-8 + + nodesPos = np.zeros((msh.nodes.size(), 3)) + + morpher.savePos() # garder en memoire la position initiale + for n in bnd.nodes: + for i in range(pbl.nDim): + pos = n.pos[i] # eviter les erreurs d'arrondi + nodesPos[n.row, i] = pos + n.pos[i] = pos + delta # deforme la surface + #morpher.deform() # deforme le maillage et mets à jour les elements + #solver.reset() + solver.run() + Cl1 = solver.Cl + n.pos[i] = pos - delta # deforme la surface + #morpher.deform() # deforme le maillage et mets à jour les elements + solver.run() + Cl2 = solver.Cl + dCl_x_FD[n.row, i] = (Cl1 - Cl2)/(2*delta) + n.pos[i] = pos for n in bnd.nodes: - dx = drot.dot(np.array([n.pos[0] - 0.25, n.pos[1]])) - dClAoA += np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]]).dot(dx) - dCdAoA += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(dx) + print((dCl_x_FD[n.row, :] - dCl_x_mat_DART[n.row, :]) / dCl_x_mat_DART[n.row, :]) + print('norm adj', np.linalg.norm(dCl_x_mat_DART)) + print('norm FD', np.linalg.norm(dCl_x_FD)) + + quit() + # print(nodesPos) + # idxNodeInterest = np.where(abs(nodesPos[:,0] - 8.19144e-2)<1e-4)[0] + # print('nodePos', nodesPos[idxNodeInterest,:]) + # print('adjoint',dCl_x_mat_DART[idxNodeInterest,:]) + # print('fd', dCl_x_FD[idxNodeInterest,:]) + # diffabs = dCl_x_FD - dCl_x_mat_DART + # print('diffabs', diffabs[idxNodeInterest,:]) + # diff = (dCl_x_FD - dCl_x_mat_DART)/dCl_x_mat_DART + # print('diffrel', diff[idxNodeInterest,:]) + + + # ################# ONLY DART AOA ################# + + # args = parseargs() + # icfg = cfgInviscid(args.k, args.verb) + # vcfg = cfgBlast(args.verb) + + # # define flow variables + # alpha = 2*np.pi/180 + # M_inf = 0.2 + # c_ref = 1 + # dim = 2 + + # # mesh the geometry + # print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) + # tms['msh'].start() + # pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 2., 'msTe' : 0.1, 'msLe' : 0.1} + # msh, gmshWriter = floD.mesh(dim, 'models/rae2822.geo', pars, ['field', 'airfoil', 'downstream']) + # # create mesh deformation handler + # morpher = floD.morpher(msh, dim, 'airfoil') + # tms['msh'].stop() + + # # set the problem and add fluid, initial/boundary conditions + # tms['pre'].start() + # pbl, _, _, bnd, blw = floD.problem(msh, dim, alpha, 0., M_inf, c_ref, c_ref, 0.25, 0., 0., 'airfoil', vsc=True) + # tms['pre'].stop() + + # # baseBlw = np.loadtxt('/home/paulzer/lab/blaster/blast/tests/dart/blwVelAF.dat') + # # for i in range(len(blw[0].nodes)-1): + # # blw[0].setU(int(baseBlw[i,0]), baseBlw[i,1]) + + # # solve problem + # print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) + # tms['solver'].start() + # solver = floD.newton(pbl) + # solver.run() + # solver.save(gmshWriter) + # tms['solver'].stop() + + # # solve adjoint problem + # print(ccolors.ANSI_BLUE + 'PyGradient...' + ccolors.ANSI_RESET) + # tms['adjoint'].start() + # adjoint = floD.adjoint(solver, morpher) + # adjoint.run() + # adjoint.save(gmshWriter) + # tms['adjoint'].stop() + + # # Get matrix + # dClAoaAdj = adjoint.dClAoa + # delta = 1e-6 + # clv = [] + # pbl.update(alpha + delta) + # solver.run() + # cl1 = solver.Cl + + # pbl.update(alpha - delta) + # solver.run() + # cl2 = solver.Cl + + # dClAoaFD = (cl1 - cl2) / (2*delta) + + # print('adj:', dClAoaAdj*np.pi/180) + # print('fd:', dClAoaFD*np.pi/180) + + ##### ONLY DART THROUGH API #### + + # args = parseargs() + # icfg = cfgInviscid(args.k, args.verb) + # vcfg = cfgBlast(args.verb) + + # coupler, iSolverAPI, vSolver = viscUtils.initBlast(icfg, vcfg) + + # # baseBlw = np.loadtxt('/home/paulzer/lab/blaster/blast/tests/dart/blwVelAF.dat') + # # for i in range(len(blw[0].nodes)-1): + # # blw[0].setU(int(baseBlw[i,0]), baseBlw[i,1]) + + # iSolverAPI.solver.run() + + # # solve adjoint problem + # print(ccolors.ANSI_BLUE + 'PyGradient...' + ccolors.ANSI_RESET) + # tms['adjoint'].start() + # iSolverAPI.adjointSolver.run() + # tms['adjoint'].stop() + + # # Get matrix + # dCl_x_mat_DART = np.zeros((iSolverAPI.argOut['msh'].nodes.size(), 3)) + # for n in iSolverAPI.argOut['bnd'].nodes: + # for i in range(3): + # dCl_x_mat_DART[n.row, i] = iSolverAPI.adjointSolver.dClMsh[n.row][i] + # print(dCl_x_mat_DART) + + # dCl_x_FD = np.zeros((len(iSolverAPI.argOut['pbl'].msh.nodes), 3)) + # Clref = iSolverAPI.solver.Cl + # delta = 1e-6 + + # nodesPos = np.zeros((iSolverAPI.argOut['pbl'].msh.nodes.size(), 3)) + + # for n in iSolverAPI.argOut['bnd'].nodes: + # for i in range(iSolverAPI.argOut['pbl'].nDim): + # iSolverAPI.argOut['mrf'].savePos() # garder en memoire la position initiale + # pos = n.pos[i] # eviter les erreurs d'arrondi + # nodesPos[n.row, i] = pos + # n.pos[i] = pos + delta # deforme la surface + # iSolverAPI.argOut['mrf'].deform() # deforme le maillage et mets à jour les elements + # iSolverAPI.solver.reset() + # iSolverAPI.solver.run() + # Cl1 = iSolverAPI.solver.Cl + # n.pos[i] = pos - delta # deforme la surface + # iSolverAPI.argOut['mrf'].deform() # deforme le maillage et mets à jour les elements + # iSolverAPI.solver.run() + # Cl2 = iSolverAPI.solver.Cl + # dCl_x_FD[n.row, i] = (Cl1 - Cl2)/(2*delta) + # n.pos[i] = pos + # print('pos', nodesPos) + # print('adjoint',dCl_x_mat_DART) + # print('fd', dCl_x_FD) + # diff = (dCl_x_FD - dCl_x_mat_DART)/dCl_x_mat_DART + # import math + # diff[np.isnan(diff)] = 0. + # print(diff[diff!=0]) + + + # compute norm of gradient wrt to mesh + # dClX = 0 + # dCdX = 0 + # for n in msh.nodes: + # dClX += np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]]).dot(np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]])) + # dCdX += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]])) + # dClX = np.sqrt(dClX) + # dCdX = np.sqrt(dCdX) + + # # recover gradient wrt to AoA from gradient wrt mesh + # drot = np.array([[-np.sin(alpha), np.cos(alpha)], [-np.cos(alpha), -np.sin(alpha)]]) + # dClAoA = 0 + # dCdAoA = 0 + # for n in bnd.nodes: + # dx = drot.dot(np.array([n.pos[0] - 0.25, n.pos[1]])) + # dClAoA += np.array([adjoint.dClMsh[n.row][0], adjoint.dClMsh[n.row][1]]).dot(dx) + # dCdAoA += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(dx) - print(dClAoA, adjoint.dClAoa) + # print(dClAoA, adjoint.dClAoa) quit() -- GitLab