diff --git a/blast/interfaces/DSolversInterface.py b/blast/interfaces/DSolversInterface.py index 8ce769401e43e382e873dbf70704ce457c363d07..bf1cd1a4d5ede687cbb146be8df51fdd3c967911 100644 --- a/blast/interfaces/DSolversInterface.py +++ b/blast/interfaces/DSolversInterface.py @@ -72,7 +72,7 @@ class SolversInterface: reg.getYUpper(), reg.getZUpper()) self.vSolver.setGlobMesh(iSec, 1, - abs(reg.getXLower()), + reg.getXLower(), reg.getYLower(), reg.getZLower()) # External variables @@ -90,7 +90,30 @@ class SolversInterface: struture but name was', reg.name) ## Inviscid variables for reg in self.vBnd[iSec]: + # External variables reg.updatePrev() + if 'vAirfoil' in reg.name: + self.xxExt[iSec][0] = np.zeros(reg.stagPoint+1) + self.deltaStarExt[iSec][0] = np.zeros(reg.stagPoint+1) + #self.vtOld[iSec][0] = np.zeros(reg.stagPoint+1) + self.xxExt[iSec][1] = np.zeros(reg.nPoints + - reg.stagPoint) + self.deltaStarExt[iSec][1] = np.zeros(reg.nPoints + - reg.stagPoint) + #self.vtOld[iSec][1] = np.zeros(reg.nPoints + # - reg.stagPoint) + elif 'vWake' in reg.name: + iReg = 2 + self.vSolver.setGlobMesh(iSec, iReg, + reg.nodesCoord[:,0], + reg.nodesCoord[:,1], + reg.nodesCoord[:,2]) + # External variables + self.xxExt[iSec][2] = np.zeros(reg.nPoints) + self.deltaStarExt[iSec][2] = np.zeros(reg.nPoints) + #self.vtOld[iSec][2] = np.zeros(reg.nPoints) + else: + raise RuntimeError('Wrong region') if 'vWake' in reg.name: iReg = 2 self.vSolver.setVelocities(iSec, iReg, diff --git a/blast/interfaces/dart/DartAdjointInterface.py b/blast/interfaces/dart/DartAdjointInterface.py index e9e62d749b6ed0ab810215c8a7be822421c15f00..2bea93d2c80e7ebdf499029f7d1d45f473923c30 100644 --- a/blast/interfaces/dart/DartAdjointInterface.py +++ b/blast/interfaces/dart/DartAdjointInterface.py @@ -29,55 +29,76 @@ class DartAdjointInterface(): for i in range(nEs): saveBlw[i] = self.iSolverAPI.blw[0].getU(i) - saveMach = np.zeros(nNs) - saverho = np.zeros(nNs) - savev = np.zeros(nDim*nNs) - savex = np.zeros((nNs, nDim)) - for iNo in range(nNs): - irow = self.iSolverAPI.blw[0].nodes[iNo].row - saveMach[iNo] = self.iSolverAPI.solver.M[irow] - saverho[iNo] = self.iSolverAPI.solver.rho[irow] - for jj in range(nDim): - savev[iNo*nDim + jj] = self.iSolverAPI.solver.U[irow][jj] - 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 - blowing = self.__runViscous() - dRblw_M[:,iNo] = (blowing-saveBlw)/delta - self.iSolverAPI.solver.M[irow] = saveMach[iNo] + for i, n in enumerate(self.iSolverAPI.blw[0].nodes): + # vidx = np.where(self.iSolverAPI.iBnd[0].nodesCoord[:,3] == n.row)[0][0] + # if self.iSolverAPI.iBnd[0].nodesCoord[vidx,0] != n.pos[0] or self.iSolverAPI.iBnd[0].nodesCoord[vidx,1] != n.pos[1]: + # print('WRONG NODE MACH') + # quit() + savemach = self.iSolverAPI.solver.M[n.row] + self.iSolverAPI.solver.M[n.row] = savemach + delta + blowing1 = self.__runViscous() + + self.iSolverAPI.solver.M[n.row] = savemach - delta + blowing2 = self.__runViscous() + self.iSolverAPI.solver.M[n.row] = savemach + dRblw_M[:,i] = -(blowing1 - blowing2)/(2*delta) # Rho print('Density') - for iNo in range(nNs): - irow = self.iSolverAPI.blw[0].nodes[iNo].row - self.iSolverAPI.solver.rho[irow] += delta - blowing = self.__runViscous() - dRblw_rho[:,iNo] = (blowing-saveBlw)/delta - self.iSolverAPI.solver.rho[irow] = saverho[iNo] + for i, n in enumerate(self.iSolverAPI.blw[0].nodes): + # vidx = np.where(self.iSolverAPI.iBnd[0].nodesCoord[:,3] == n.row)[0][0] + # if self.iSolverAPI.iBnd[0].nodesCoord[vidx,0] != n.pos[0] or self.iSolverAPI.iBnd[0].nodesCoord[vidx,1] != n.pos[1]: + # print('WRONG NODE DENSITY') + # quit() + saverho = self.iSolverAPI.solver.rho[n.row] + self.iSolverAPI.solver.rho[n.row] = saverho + delta + blowing1 = self.__runViscous() + + self.iSolverAPI.solver.rho[n.row] = saverho - delta + blowing2 = self.__runViscous() + self.iSolverAPI.solver.rho[n.row] = saverho + dRblw_rho[:,i] = -(blowing1 - blowing2)/(2*delta) # # V print('Velocity') - for iNo in range(nNs): - irow = self.iSolverAPI.blw[0].nodes[iNo].row - for iDim in range(nDim): - self.iSolverAPI.solver.U[irow][iDim] += delta - blowing = self.__runViscous() - dRblw_v[:,iNo*nDim + iDim] = (blowing-saveBlw)/delta - self.iSolverAPI.solver.U[irow][iDim] = savev[iNo*nDim + iDim] + for i, n in enumerate(self.iSolverAPI.blw[0].nodes): + #vidx = np.where(self.iSolverAPI.iBnd[0].nodesCoord[:,3] == n.row)[0][0] + for jj in range(nDim): + # if self.iSolverAPI.iBnd[0].nodesCoord[vidx,jj] != n.pos[jj]: + # print('WRONG NODE VELOCITY') + # quit() + savev = self.iSolverAPI.solver.U[n.row][jj] + self.iSolverAPI.solver.U[n.row][jj] = savev + delta + blowing1 = self.__runViscous() + + self.iSolverAPI.solver.U[n.row][jj] = savev - delta + blowing2 = self.__runViscous() + self.iSolverAPI.solver.U[n.row][jj] = savev + dRblw_v[:,i*nDim + jj] = -(blowing1 - blowing2)/(2*delta) # # Mesh coordinates print('Mesh') - for iNo in range(nNs): - 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() - dRblw_x[:, irow*nDim+iDim] = (blowing-saveBlw)/delta - self.iSolverAPI.iBnd[0].nodesCoord[iNo, iDim] = savex[iNo, iDim] + for i, n in enumerate(self.iSolverAPI.blw[0].nodes): + vidx = np.where(self.iSolverAPI.iBnd[0].nodesCoord[:,3] == n.row)[0][0] + for jj in range(nDim): + if self.iSolverAPI.iBnd[0].nodesCoord[vidx,jj] != n.pos[jj]: + print('WRONG NODE MESH') + quit() + savemesh = n.pos[jj] + self.iSolverAPI.iBnd[0].nodesCoord[vidx, jj] = savemesh + delta + blowing1 = self.__runViscous() + + self.iSolverAPI.iBnd[0].nodesCoord[vidx, jj] = savemesh - delta + blowing2 = self.__runViscous() + self.iSolverAPI.iBnd[0].nodesCoord[vidx, jj] = savemesh + dRblw_x[:, n.row*nDim+jj] = -(blowing1 - blowing2)/(2*delta) + + # print('dRblw_M',dRblw_M[dRblw_M!=0]) + # print('dRblw_rho', dRblw_rho[dRblw_rho!=0]) + # print('dRblw_v', dRblw_v[dRblw_v!=0]) + # print('dRblw_x', dRblw_x[dRblw_x!=0]) self.coupledAdjointSolver.setdRblw_M(dRblw_M) self.coupledAdjointSolver.setdRblw_rho(dRblw_rho) diff --git a/blast/interfaces/dart/DartInterface.py b/blast/interfaces/dart/DartInterface.py index e2cc4f7a5af8197f31e1ee881fd269647cd35009..68656e12751e8d4c9b43d7fdf40f72e95b8b8559 100644 --- a/blast/interfaces/dart/DartInterface.py +++ b/blast/interfaces/dart/DartInterface.py @@ -152,6 +152,9 @@ class DartInterface(SolversInterface): if self.cfg['nDim'] == 2: self.iBnd[n].connectBlowingVel() for i, blw in enumerate(self.iBnd[n].blowingVel): + if n == 1 and blw != 0: + print('blw not 0 in wake') + quit() self.blw[n].setU(i, blw) def setMesh(self): diff --git a/blast/src/DBoundaryLayer.cpp b/blast/src/DBoundaryLayer.cpp index dae9606aef41cdda02a72105fe6fbe2159c2025b..ed33ed251c9c7cc72a86947e447f04df2e6e96e6 100644 --- a/blast/src/DBoundaryLayer.cpp +++ b/blast/src/DBoundaryLayer.cpp @@ -46,21 +46,21 @@ void BoundaryLayer::setMesh(std::vector<double> x, mesh->setGlob(x, y, z); // Resize and reset all variables if needed. - if (mesh->getDiffnElm() != 0) - { - u.resize(nVar * nMarkers, 0.); - Ret.resize(nMarkers, 0.); - cd.resize(nMarkers, 0.); - cf.resize(nMarkers, 0.); - Hstar.resize(nMarkers, 0.); - Hstar2.resize(nMarkers, 0.); - Hk.resize(nMarkers, 0.); - ctEq.resize(nMarkers, 0.); - us.resize(nMarkers, 0.); - deltaStar.resize(nMarkers, 0.); - delta.resize(nMarkers, 0.); - regime.resize(nMarkers, 0); - } + // if (mesh->getDiffnElm() != 0) + // { + u.resize(nVar * nMarkers, 0.); + Ret.resize(nMarkers, 0.); + cd.resize(nMarkers, 0.); + cf.resize(nMarkers, 0.); + Hstar.resize(nMarkers, 0.); + Hstar2.resize(nMarkers, 0.); + Hk.resize(nMarkers, 0.); + ctEq.resize(nMarkers, 0.); + us.resize(nMarkers, 0.); + deltaStar.resize(nMarkers, 0.); + delta.resize(nMarkers, 0.); + regime.resize(nMarkers, 0); + // } } /** diff --git a/blast/src/DCoupledAdjoint.cpp b/blast/src/DCoupledAdjoint.cpp index 072c5893c5a7b348ff4c550e6607e2ecc4829422..793d5207304e58025e7678dc4b6631c98c5399c7 100644 --- a/blast/src/DCoupledAdjoint.cpp +++ b/blast/src/DCoupledAdjoint.cpp @@ -126,6 +126,22 @@ void CoupledAdjoint::buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMat // Create a list of triplets for the larger matrix std::vector<Eigen::Triplet<double>> triplets; + // Sanity check + for (size_t irow = 0; irow < matrices.size(); ++irow) + { + if (irow > 0) + if (matrices[irow].size() != matrices[irow-1].size()){ + std::cout << "WRONG ROW SIZE " << std::endl; + throw; + } + for (size_t icol = 0; icol < matrices[irow].size(); ++icol) + if (icol > 0) + if (matrices[irow][icol]->rows() != matrices[irow][icol-1]->rows()){ + std::cout << "WRONG COL SIZE " << std::endl; + throw; + } + } + // Iterate over the rows and columns of the vector int rowOffset = 0; for (const auto& row : matrices) { @@ -162,8 +178,8 @@ void CoupledAdjoint::run() std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> matrices = { {&dRphi_phi, &dRM_phi, &dRv_phi, &dRrho_phi, &dRblw_phi}, {&dRphi_M, &dRM_M, &dRv_M, &dRrho_M, &dRblw_M}, - {&dRphi_rho, &dRM_rho, &dRv_rho, &dRrho_rho, &dRblw_rho}, {&dRphi_v, &dRM_v, &dRv_v, &dRrho_v, &dRblw_v}, + {&dRphi_rho, &dRM_rho, &dRv_rho, &dRrho_rho, &dRblw_rho}, {&dRphi_blw, &dRM_blw, &dRv_blw, &dRrho_blw, &dRblw_blw} }; @@ -187,20 +203,31 @@ void CoupledAdjoint::run() Eigen::VectorXd lambdaClPhi = lambdaCl.segment(0, isol->pbl->msh->nodes.size()); Eigen::VectorXd lambdaClBlw = lambdaCl.segment(lambdaCl.size() - isol->pbl->bBCs[0]->uE.size(), isol->pbl->bBCs[0]->uE.size()); + // std::vector<std::vector<double>> dCf_U = iadjoint->computeGradientCoefficientsFlow(); // {dCl, dCd}/dU + // std::vector<double> lamClFlodum= iadjoint->solveFlow(dCf_U[0]); + // Eigen::VectorXd lamClFlodum2 = Eigen::Map<Eigen::VectorXd> (lamClFlodum.data(), lamClFlodum.size()); + // Eigen::VectorXd diff = lambdaClPhi - lamClFlodum2; + // for (auto i=0; i<diff.size(); ++i) + // std::cout << "dart " << lamClFlodum2[i] << ", vii " << lambdaClPhi[i] << ", diff " << diff[i] << std::endl; + // throw; + + // std::vector<std::vector<double>> dCf_U = iadjoint->computeGradientCoefficientsFlow(); // {dCl, dCd}/dU + // std::vector<double> lamClFlodum= iadjoint->solveFlow(dCf_U[0]); // lambdaClU = dRu/dU^-T * dCl/dU + // lambdaClPhi = Eigen::Map<Eigen::VectorXd>(lamClFlodum.data(), lamClFlodum.size()); tdCl_AoA = dCl_AoA - dRphi_AoA.transpose()*lambdaClPhi; // Total gradient // CD - std::vector<double> rhsCd(A_adjoint.cols(), 0.0); - for (auto i = 0; i<dCd_phi.size(); ++i) - rhsCd[i] = dCd_phi[i]; - 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()); - alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCd_.data(), rhsCd_.size()), lambdaCd_); - Eigen::VectorXd lambdaCdPhi = lambdaCd.block(0, 0, isol->pbl->msh->nodes.size(), 1); + // std::vector<double> rhsCd(A_adjoint.cols(), 0.0); + // for (auto i = 0; i<dCd_phi.size(); ++i) + // rhsCd[i] = dCd_phi[i]; + // 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()); + // alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCd_.data(), rhsCd_.size()), lambdaCd_); + // Eigen::VectorXd lambdaCdPhi = lambdaCd.block(0, 0, isol->pbl->msh->nodes.size(), 1); - tdCd_AoA = dCd_AoA - dRphi_AoA.transpose()*lambdaCdPhi; // Total gradient + // tdCd_AoA = dCd_AoA - dRphi_AoA.transpose()*lambdaCdPhi; // Total gradient //***** Gradient wrt mesh coordinates *****// //*****************************************// @@ -210,7 +237,14 @@ void CoupledAdjoint::run() Eigen::VectorXd lambdaCl_x = Eigen::VectorXd::Zero(isol->pbl->nDim * isol->pbl->msh->nodes.size()); Eigen::Map<Eigen::VectorXd> lambdaCl_x_(lambdaCl_x.data(), lambdaCl_x.size()); + // std::vector<std::vector<double>> dCf_U = iadjoint->computeGradientCoefficientsFlow(); // {dCl, dCd}/dU + // std::vector<double> lambdaClPhidum = iadjoint->solveFlow(dCf_U[0]); // lambdaClU = dRu/dU^-T * dCl/dU + // lambdaClPhi.resize(lambdaClPhidum.size()); + // for (auto ii = 0; ii < lambdaClPhi.size(); ii++) + // lambdaClPhi[ii] = lambdaClPhidum[ii]; + Eigen::VectorXd rhsCl_x = dCl_x - dRphi_x.transpose() * lambdaClPhi - dRblw_x.transpose() * lambdaClBlw; + dRx_x.setIdentity(); alinsol->compute(dRx_x.transpose(), Eigen::Map<Eigen::VectorXd>(rhsCl_x.data(), rhsCl_x.size()), lambdaCl_x_); for (auto n : isol->pbl->msh->nodes) @@ -222,6 +256,54 @@ void CoupledAdjoint::run() tdCd_x[n->row](m) = lambdaCl_x[isol->pbl->nDim * (n->row) + m]; } } + + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_phi = Eigen::Sparsetrix<double, Eigen::RowMajor> (isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->msh->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_M = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->bBCs[0]->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_rho = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->bBCs[0]->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_v = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->nDim * isol->pbl->bBCs[0]->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRx_blw = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->bBCs[0]->uE.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRM_x = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->bBCs[0]->nodes.size(), isol->pbl->nDim * isol->pbl->msh->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRv_x = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->bBCs[0]->nodes.size(), isol->pbl->nDim * isol->pbl->msh->nodes.size()); + // Eigen::SparseMatrix<double, Eigen::RowMajor> dRrho_x = Eigen::SparseMatrix<double, Eigen::RowMajor> (isol->pbl->bBCs[0]->nodes.size(), isol->pbl->nDim * isol->pbl->msh->nodes.size()); + // dRx_phi = dRx_phi.transpose(); + // dRx_M = dRx_M.transpose(); + // dRx_rho = dRx_rho.transpose(); + // dRx_v = dRx_v.transpose(); + // dRx_blw = dRx_blw.transpose(); + // dRx_x = dRx_x.transpose(); + // dRphi_x = dRphi_x.transpose(); + // dRM_x = dRM_x.transpose(); + // dRv_x = dRv_x.transpose(); + // dRrho_x = dRrho_x.transpose(); + // dRblw_x = dRblw_x.transpose(); + // std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> matricesTest = { + // {&dRphi_phi, &dRM_phi, &dRv_phi, &dRrho_phi, &dRblw_phi, &dRx_phi}, + // {&dRphi_M, &dRM_M, &dRv_M, &dRrho_M, &dRblw_M, &dRx_M}, + // {&dRphi_rho, &dRM_rho, &dRv_rho, &dRrho_rho, &dRblw_rho, &dRx_rho}, + // {&dRphi_v, &dRM_v, &dRv_v, &dRrho_v, &dRblw_v, &dRx_v}, + // {&dRphi_blw, &dRM_blw, &dRv_blw, &dRrho_blw, &dRblw_blw, &dRx_blw}, + // {&dRphi_x, &dRM_x, &dRv_x, &dRrho_x, &dRblw_x, &dRx_x} + // }; + + // rows = 0; cols = 0; + // for (const auto& row : matricesTest) rows += row[0]->rows(); // All matrices in a row have the same number of rows + // for (const auto& mat1 : matricesTest[0]) cols += mat1->cols(); // All matrices in a column have the same number of columns + // Eigen::SparseMatrix<double, Eigen::RowMajor> A_adjoint_test(rows, cols); + // buildAdjointMatrix(matricesTest, A_adjoint_test); + // std::cout << "MATRIX BUILT " << std::endl; + + // std::vector<double> rhsCl_test(A_adjoint_test.cols(), 0.0); + // for (auto i = 0; i<dCl_phi.size(); ++i) + // rhsCl_test[i] = dCl_phi[i]; + // for (auto ii = rhsCl_test.size() - isol->pbl->nDim * isol->pbl->msh->nodes.size(); ii < rhsCl_test.size(); ++ii) + // rhsCl_test[ii] = dCl_x[ii]; + // Eigen::VectorXd rhsCl_test_ = Eigen::Map<const Eigen::VectorXd>(rhsCl_test.data(), rhsCl_test.size()); + + // Eigen::VectorXd lambdaCl_test(A_adjoint_test.cols()); // Solution vector for lambdasCl + // Eigen::Map<Eigen::VectorXd> lambdaCl_test_(lambdaCl_test.data(), lambdaCl_test.size()); + // alinsol->compute(A_adjoint_test, Eigen::Map<Eigen::VectorXd>(rhsCl_test_.data(), rhsCl_test_.size()), lambdaCl_test_); + // Eigen::VectorXd lambdaCl_x = lambdaCl_test.segment(lambdaCl_test.size() - isol->pbl->nDim * isol->pbl->msh->nodes.size(), isol->pbl->nDim * isol->pbl->msh->nodes.size()); + } void CoupledAdjoint::gradientswrtInviscidFlow() @@ -232,8 +314,8 @@ void CoupledAdjoint::gradientswrtInviscidFlow() //**** dRM_phi, dRrho_phi, dRv_phi ****// auto pbl = isol->pbl; // Finite difference - std::vector<double> Phi_save = isol->phi; // Differential of the independant variable (phi) - double deltaPhi = 1e-8; // perturbation + std::vector<double> Phi_save = isol->phi; // Differential of the independent variable (phi) + double deltaPhi = 1e-6; // perturbation std::vector<Eigen::Triplet<double>> tripletsdM; std::vector<Eigen::Triplet<double>> tripletsdrho; @@ -243,7 +325,7 @@ void CoupledAdjoint::gradientswrtInviscidFlow() Phi_save[n->row] = isol->phi[n->row] + deltaPhi; // Recompute the quantities on surface nodes. - size_t jj = 0; + int jj = 0; for (auto srfNode : pbl->bBCs[0]->nodes){ double dM = 0.; double drho = 0.; @@ -261,10 +343,11 @@ void CoupledAdjoint::gradientswrtInviscidFlow() dv /= static_cast<double>(pbl->fluid->neMap[srfNode].size()); // Form triplets - tripletsdM.push_back(Eigen::Triplet<double>(jj, n->row, (dM - isol->M[srfNode->row])/deltaPhi)); - tripletsdrho.push_back(Eigen::Triplet<double>(jj, n->row, (drho - isol->rho[srfNode->row])/deltaPhi)); - for (size_t i = 0; i < pbl->nDim; ++i) - tripletsdv.push_back(Eigen::Triplet<double>(jj*pbl->nDim + i, n->row, (dv(i) - isol->U[srfNode->row](i))/deltaPhi)); + tripletsdM.push_back(Eigen::Triplet<double>(jj, n->row, -(dM - isol->M[srfNode->row])/deltaPhi)); + tripletsdrho.push_back(Eigen::Triplet<double>(jj, n->row, -(drho - isol->rho[srfNode->row])/deltaPhi)); + for (int i = 0; i < pbl->nDim; ++i) + tripletsdv.push_back(Eigen::Triplet<double>(jj*pbl->nDim + i, n->row, -(dv(i) - isol->U[srfNode->row](i))/deltaPhi)); + jj++; } // Reset phi @@ -337,7 +420,7 @@ void CoupledAdjoint::gradientwrtMesh(){ } void CoupledAdjoint::setdRblw_M(std::vector<std::vector<double>> _dRblw_dM){ - dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dM.size(), _dRblw_dM[0].size()); + //dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dM.size(), _dRblw_dM[0].size()); // Convert std::vector<double> to Eigen::Triplets std::vector<Eigen::Triplet<double>> triplets; for (size_t i = 0; i < _dRblw_dM.size(); i++){ @@ -350,7 +433,7 @@ void CoupledAdjoint::setdRblw_M(std::vector<std::vector<double>> _dRblw_dM){ dRblw_M.prune(0.); } void CoupledAdjoint::setdRblw_v(std::vector<std::vector<double>> _dRblw_dv){ - dRblw_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dv.size(), _dRblw_dv[0].size()); + //dRblw_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dv.size(), _dRblw_dv[0].size()); // Convert std::vector<double> to Eigen::Triplets std::vector<Eigen::Triplet<double>> triplets; for (size_t i = 0; i < _dRblw_dv.size(); i++){ @@ -363,7 +446,7 @@ void CoupledAdjoint::setdRblw_v(std::vector<std::vector<double>> _dRblw_dv){ dRblw_v.prune(0.); } void CoupledAdjoint::setdRblw_rho(std::vector<std::vector<double>> _dRblw_drho){ - dRblw_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_drho.size(), _dRblw_drho[0].size()); + //dRblw_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_drho.size(), _dRblw_drho[0].size()); // Convert std::vector<double> to Eigen::Triplets std::vector<Eigen::Triplet<double>> triplets; for (size_t i = 0; i < _dRblw_drho.size(); i++){ @@ -376,7 +459,7 @@ void CoupledAdjoint::setdRblw_rho(std::vector<std::vector<double>> _dRblw_drho){ dRblw_rho.prune(0.); } void CoupledAdjoint::setdRblw_x(std::vector<std::vector<double>> _dRblw_dx){ - dRblw_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dx.size(), _dRblw_dx[0].size()); + //dRblw_x = Eigen::SparseMatrix<double, Eigen::RowMajor>(_dRblw_dx.size(), _dRblw_dx[0].size()); // Convert std::vector<double> to Eigen::Triplets std::vector<Eigen::Triplet<double>> triplets; for (size_t i = 0; i < _dRblw_dx.size(); i++){ @@ -546,7 +629,13 @@ void CoupledAdjoint::transposeMatrices(){ // std::cout << "dRblw_M " << dRblw_M.rows() << " " << dRblw_M.cols() << std::endl; // std::cout << "dRblw_rho " << dRblw_rho.rows() << " " << dRblw_rho.cols() << std::endl; // std::cout << "dRblw_v " << dRblw_v.rows() << " " << dRblw_v.cols() << std::endl; - // std::cout << "dRblw_blw " << dRblw_blw.rows() << " " << dRblw_blw.cols() << std::endl; + // std::cout << "dRphi_x " << dRphi_x.rows() << " " << dRphi_x.cols() << std::endl; + // std::cout << "dRM_x " << dRM_x.rows() << " " << dRM_x.cols() << std::endl; + // std::cout << "dRv_x " << dRv_x.rows() << " " << dRv_x.cols() << std::endl; + // std::cout << "dRrho_x " << dRrho_x.rows() << " " << dRrho_x.cols() << std::endl; + // std::cout << "dRblw_x " << dRblw_x.rows() << " " << dRblw_x.cols() << std::endl; + // std::cout << "dRphi_x " << dRphi_x.rows() << " " << dRphi_x.cols() << std::endl; + // std::cout << "dRx_x " << dRx_x.rows() << " " << dRx_x.cols() << std::endl; } void CoupledAdjoint::writeMatrixToFile(const Eigen::MatrixXd& matrix, const std::string& filename) { diff --git a/blast/src/DDriver.cpp b/blast/src/DDriver.cpp index 9ae18616fde6d7071861850b7cf83caea47b385b..a551acb9b12e88ef2d0719a58736e186f5994d32 100644 --- a/blast/src/DDriver.cpp +++ b/blast/src/DDriver.cpp @@ -121,7 +121,7 @@ int Driver::run(unsigned int const couplIter) tms["0-CheckIn"].stop(); // Loop over the regions (upper, lower and wake). - for (size_t iRegion = 0; iRegion < sections[iSec].size(); ++iRegion) + for (size_t iRegion = 0; iRegion < 2; ++iRegion) { convergenceStatus[iSec][iRegion].resize(0); @@ -132,6 +132,11 @@ int Driver::run(unsigned int const couplIter) if (verbose > 1) std::cout << sections[iSec][iRegion]->name << " "; + std::vector<double> xxExtCurr(sections[iSec][iRegion]->mesh->getnMarkers(), 0.); + for (size_t iPoint = 0; iPoint < xxExtCurr.size(); ++iPoint) + xxExtCurr[iPoint] = sections[iSec][iRegion]->mesh->getLoc(iPoint); + sections[iSec][iRegion]->mesh->setExt(xxExtCurr); + // Check if safe mode is required. if (couplIter == 0 || sections[iSec][iRegion]->mesh->getDiffnElm() != 0 || stagPtMvmt[iSec] == true || solverExitCode != 0) { @@ -243,7 +248,7 @@ int Driver::run(unsigned int const couplIter) if (verbose > 1) std::cout << std::endl; } - + sections[0][2]->computeBlwVel(); for (size_t i = 0; i < sections.size(); ++i) computeSectionalDrag(sections[i], i); computeTotalDrag(); diff --git a/blast/tests/dart/adjointVII.py b/blast/tests/dart/adjointVII.py index 065e06a797465019027b8a4d9614f60fb1a00a7f..9f2cbdbab4e4d12f1f984874c1a1dbd9554b186a 100644 --- a/blast/tests/dart/adjointVII.py +++ b/blast/tests/dart/adjointVII.py @@ -93,8 +93,8 @@ 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': 200, # 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. 'sections' : [0], diff --git a/blast/tests/dart/adjointVIImesh.py b/blast/tests/dart/adjointVIImesh.py index 27fde997fee5d04d44e9c2c551f5162111f78a0e..5617a2fd02e42349052ec4c48a88a78e3fae953b 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' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.05, 'msLe' : 0.05}, # parameters for input file model + 'Pars' : {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.1, 'msLe' : 0.1}, # parameters for input file model 'Dim' : 2, # problem dimension 'Format' : 'gmsh', # save format (vtk or gmsh) # Markers @@ -136,6 +136,7 @@ def main(): print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) tms['solver'].start() aeroCoeffs = coupler.run() + iSolverAPI.run() tms['solver'].stop() Clref = iSolverAPI.getCl() @@ -168,9 +169,37 @@ def main(): for i in range(3): dCl_x_mat[n.row, i] = coupledAdjointSolver.tdCl_x[n.row][i] + ### DART ### + delta = 1e-6 + dCl_x_FD_DART = np.zeros((len(iSolverAPI.argOut['pbl'].msh.nodes), 3)) + for n in iSolverAPI.argOut['bnd'].nodes: + for i in range(iSolverAPI.argOut['pbl'].nDim): + #print('BEFORE', iSolverAPI.solver.U[n.row][i]) + pos = n.pos[i] # eviter les erreurs d'arrondi + n.pos[i] = pos + delta # deforme la surface + #morpher.deform() # deforme le maillage et mets à jour les elements + #solver.reset() + iSolverAPI.reset() + iSolverAPI.run() + Cl1 = iSolverAPI.getCl() + #print('+', iSolverAPI.solver.U[n.row][i]) + + n.pos[i] = pos - delta # deforme la surface + #morpher.deform() # deforme le maillage et mets à jour les elements + iSolverAPI.reset() + iSolverAPI.run() + Cl2 = iSolverAPI.getCl() + #print('-', iSolverAPI.solver.U[n.row]) + dCl_x_FD_DART[n.row, i] = (Cl1 - Cl2)/(2*delta) + n.pos[i] = pos + #quit() + # for n in iSolverAPI.argOut['bnd'].nodes: + # print((dCl_x_FD_DART[n.row, :] - dCl_x_mat_DART[n.row, :]) / dCl_x_mat_DART[n.row, :]) + # quit() + ### Finite difference #### print('Starting FD') - delta = 1e-6 + delta = 1e-8 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] @@ -186,21 +215,24 @@ def main(): 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() + # for i in range(len(iSolverAPI.iBnd[0].elemsCoord[:,0])): + # iSolverAPI.blw[0].setU(i, 0.) + # iSolverAPI.imposeInvBC(0, adj=1) + iSolverAPI.imposeInvBC(0, adj=0) + for it in range(100): + eci = iSolverAPI.run() iSolverAPI.imposeInvBC(it, adj=0) - vSolver.run(it) + ec = vSolver.run(it) + if ec != 0: + raise RuntimeError('Not converged in 1') iSolverAPI.imposeBlwVel(adj=0) clCurr = iSolverAPI.getCl() - if abs((clCurr - clPrev)/clCurr) < 1e-12: - print('1conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + if abs((clCurr - clPrev)/clCurr) < 1e-13: + #print('1conv', n.row, it, abs((clCurr - clPrev)/clCurr)) break clPrev = clCurr - if (it > 49): - print('Not converged') + if (it >= 90): + print('Not converged', it) quit() Cl1 = iSolverAPI.getCl() @@ -208,42 +240,160 @@ def main(): 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): + # for i in range(len(iSolverAPI.iBnd[0].elemsCoord[:,0])): + # iSolverAPI.blw[0].setU(i, 0.) + # iSolverAPI.imposeInvBC(0, adj=1) + iSolverAPI.imposeInvBC(0, adj=0) + for it in range(100): iSolverAPI.run() iSolverAPI.imposeInvBC(it, adj=0) - vSolver.run(it) + ec = vSolver.run(it) + if ec != 0: + raise RuntimeError('Not converged in 2') iSolverAPI.imposeBlwVel(adj=0) clCurr = iSolverAPI.getCl() - if abs((clCurr - clPrev)/clCurr) < 1e-12: - print('2conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + if abs((clCurr - clPrev)/clCurr) < 1e-13: + #print('2conv', n.row, it, abs((clCurr - clPrev)/clCurr)) break clPrev = clCurr - if (it > 49): - print('Not converged') + if (it >= 90): + print('Not converged', it) quit() Cl2 = iSolverAPI.getCl() n.pos[idim] = pos iSolverAPI.iBnd[0].nodesCoord[idxV,idim] = pos - print(n.row, 'fd ', (Cl1 - Cl2)/(2*delta)) + #print(n.row, 'fd ', (Cl1 - Cl2)/(2*delta)) dCl_x_FD_coupled[n.row, idim] = (Cl1 - Cl2)/(2*delta) + #absDiff = (dCl_x_FD_coupled[n.row, :] - dCl_x_mat[n.row, :]) + #print(f"row {n.row:<5} pos: [{n.pos[0]:<5.3}, {n.pos[1]:<5.3}, {n.pos[2]:<5.3}] Cl1 {Cl1:<5.7} Cl2 {Cl2:<5.7} absDiff {absDiff}") + + ### FD AoA ### + delta = 0.000001*np.pi/180 + iSolverAPI.reset() + iSolverAPI.argOut['pbl'].update(alpha+delta) + iSolverAPI.imposeInvBC(0, adj=0) + for it in range(100): + eci = iSolverAPI.run() + iSolverAPI.imposeInvBC(it, adj=0) + ec = vSolver.run(it) + if ec != 0: + raise RuntimeError('Not converged in 1') + iSolverAPI.imposeBlwVel(adj=0) + clCurr = iSolverAPI.getCl() + if abs((clCurr - clPrev)/clCurr) < 1e-13: + print('1conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + break + clPrev = clCurr + if (it >= 90): + print('Not converged') + quit() + Cl1 = iSolverAPI.getCl() + print('1', it, Cl1) + iSolverAPI.reset() + iSolverAPI.argOut['pbl'].update(alpha-delta) + for it in range(100): + eci = iSolverAPI.run() + iSolverAPI.imposeInvBC(it, adj=0) + ec = vSolver.run(it) + if ec != 0: + raise RuntimeError('Not converged in 1') + iSolverAPI.imposeBlwVel(adj=0) + clCurr = iSolverAPI.getCl() + if abs((clCurr - clPrev)/clCurr) < 1e-13: + print('1conv', n.row, it, abs((clCurr - clPrev)/clCurr)) + break + clPrev = clCurr + if (it > 90): + print('Not converged') + quit() + Cl2 = iSolverAPI.getCl() + print('2', it, Cl2) + dCl_aoa_coupled_FD = (Cl1 - Cl2)/(2*delta) + + ### FD AoA DART ### + + ### DART ### + delta = 1e-6 * np.pi/180 + #solver.reset() + iSolverAPI.argOut['pbl'].update(alpha + delta) + iSolverAPI.reset() + iSolverAPI.run() + Cl1 = iSolverAPI.getCl() + #print('+', iSolverAPI.solver.U[n.row][i]) + + iSolverAPI.argOut['pbl'].update(alpha - delta) + #morpher.deform() # deforme le maillage et mets à jour les elements + iSolverAPI.reset() + iSolverAPI.run() + Cl2 = iSolverAPI.getCl() - print(coupledAdjointSolver.tdCl_AoA) + iSolverAPI.argOut['pbl'].update(alpha) + + dCl_AoA_FD_DART = (Cl1 - Cl2) / (2*delta) + print(iSolverAPI.adjointSolver.dClAoa, dCl_AoA_FD_DART, (iSolverAPI.adjointSolver.dClAoa - dCl_AoA_FD_DART)/iSolverAPI.adjointSolver.dClAoa) + + # 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_FROMMESH_FD = 0 + #dCdAoA = 0 + for n in iSolverAPI.argOut['bnd'].nodes: + dx = drot.dot(np.array([n.pos[0] - 0.25, n.pos[1]])) + dClAoA_FROMMESH_FD += np.array([dCl_x_FD_coupled[n.row,0], dCl_x_FD_coupled[n.row,1]]).dot(dx) + #dCdAoA += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(dx) + + # 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_FROMMESH_ADJ = 0 + #dCdAoA = 0 for n in iSolverAPI.argOut['bnd'].nodes: - print('adj node', n.row, dCl_x_mat[n.row, :]) + dx = drot.dot(np.array([n.pos[0] - 0.25, n.pos[1]])) + dClAoA_FROMMESH_ADJ += np.array([dCl_x_mat[n.row,0], dCl_x_mat[n.row,1]]).dot(dx) + #dCdAoA += np.array([adjoint.dCdMsh[n.row][0], adjoint.dCdMsh[n.row][1]]).dot(dx) + print(dClAoA_FROMMESH_ADJ) + + print('from fd', dClAoA_FROMMESH_FD) + print('from adj', dClAoA_FROMMESH_ADJ) + + + + + #quit() + # 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('absDiff node', n.row, (dCl_x_FD_coupled[n.row, :] - dCl_x_mat[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) + mat = np.zeros((iSolverAPI.argOut['bnd'].nodes.size(), 6)) + ii = 0 for n in iSolverAPI.argOut['bnd'].nodes: - print('fd node', n.row, dCl_x_FD_coupled[n.row, :]) + mat[ii, :] = [n.row, n.pos[0], dCl_x_mat[n.row,0], dCl_x_FD_coupled[n.row, 0], dCl_x_mat_DART[n.row,0], dCl_x_FD_DART[n.row, 0]] + ii +=1 + mat = mat[mat[:,0].argsort()] + print('x') + for row in mat: + print(' '.join('{:>15.10f}'.format(val) for val in row)) + ii = 0 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) + mat[ii, :] = [n.row, n.pos[1], dCl_x_mat[n.row,1], dCl_x_FD_coupled[n.row, 1], dCl_x_mat_DART[n.row,1], dCl_x_FD_DART[n.row, 1]] + ii +=1 + #print('nodes {:8.8f} x {:8.8f} AdjCoupl {:8.8f} FDCoupl {:8.8f} AdjDart {:8.8f} FDDart {:8.8f}'.format(n.row, n.pos[0], dCl_x_mat[n.row,0], dCl_x_FD_coupled[n.row, 0], dCl_x_mat_DART[n.row,0], dCl_x_FD_DART[n.row, 0])) + mat = mat[mat[:,0].argsort()] + print('y') + for row in mat: + print(' '.join('{:>15.10f}'.format(val) for val in row)) + print('dClaoa_AdjCoupl', coupledAdjointSolver.tdCl_AoA, 'dClaoa_FDCoupl', dCl_aoa_coupled_FD, 'dClaoa_AdjDart', iSolverAPI.adjointSolver.dClAoa, 'dClaoa_FDDart', dCl_AoA_FD_DART) + print('err viscous', (coupledAdjointSolver.tdCl_AoA - dCl_aoa_coupled_FD)/coupledAdjointSolver.tdCl_AoA) + print('err inviscid', (iSolverAPI.adjointSolver.dClAoa - dCl_AoA_FD_DART)/iSolverAPI.adjointSolver.dClAoa) quit() - # np.savetxt('dCl_x_FD_coupled.dat',dCl_x_FD_coupled) # print('COUPLED', dCl_x_mat - dCl_x_FD_coupled) @@ -267,8 +417,8 @@ def main(): # mesh the geometry print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) tms['msh'].start() - 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']) + pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1., 'msTe' : 0.05, 'msLe' : 0.05} + msh, gmshWriter = floD.mesh(dim, 'models/n0012.geo', pars, ['field', 'airfoil', 'downstream']) # create mesh deformation handler morpher = floD.morpher(msh, dim, 'airfoil') tms['msh'].stop()