diff --git a/blast/_src/blastw.i b/blast/_src/blastw.i index ac1b2e6f06c50db252a032d5fb94066256f1c9c8..732a11389ee2d5951cab29ddcbf9f1dd430450f6 100644 --- a/blast/_src/blastw.i +++ b/blast/_src/blastw.i @@ -58,3 +58,5 @@ threads="1" %shared_ptr(blast::CoupledAdjoint); %include "DCoupledAdjoint.h" +%immutable blast::CoupledAdjoint::tdCl_AoA; +%immutable blast::CoupledAdjoint::tdCd_AoA; diff --git a/blast/interfaces/dart/DartAdjointInterface.py b/blast/interfaces/dart/DartAdjointInterface.py new file mode 100644 index 0000000000000000000000000000000000000000..cb3d6326a8c1eac7099d70dd4dcf0c3f5bd55580 --- /dev/null +++ b/blast/interfaces/dart/DartAdjointInterface.py @@ -0,0 +1,83 @@ +import numpy as np + +class DartAdjointInterface(): + def __init__(self, _coupledAdjointSolver, _iSolverAPI, _vSolver): + self.coupledAdjointSolver = _coupledAdjointSolver + self.iSolverAPI = _iSolverAPI + self.vSolver = _vSolver + + def computeDerivatives(self): + + nRun = 0 + + # Store blowing velocity + saveBlw = self.__getBlowingVelocity() + + saveMach, saveRho, saveV = self.__getInviscidState() + + dRblw_dM = np.zeros((len(saveBlw), 0)) + deltaMach = 1e-4 + + # Finite difference + for i in range(len(saveMach)): + self.iSolverAPI.iBnd[0].M[i] = saveMach[i] + deltaMach + self.iSolverAPI.setViscousSolver(1) + self.vSolver.run(1) + nRun+=1 + self.iSolverAPI.imposeBlwVel() + newBlowing = self.__getBlowingVelocity() + dRblw_dM = np.column_stack((dRblw_dM, (newBlowing - saveBlw) / deltaMach)) + self.iSolverAPI.iBnd[0].M[i] = saveMach[i] + + dRblw_dRho = np.zeros((len(saveBlw), 0)) + deltaRho = 1e-8 + + # Finite difference + for i in range(len(saveRho)): + self.iSolverAPI.iBnd[0].Rho[i] = saveRho[i] + deltaRho + self.iSolverAPI.setViscousSolver(1) + self.vSolver.run(1) + nRun+=1 + self.iSolverAPI.imposeBlwVel() + newBlowing = self.__getBlowingVelocity() + dRblw_dRho = np.column_stack((dRblw_dRho, (newBlowing - saveBlw) / deltaRho)) + self.iSolverAPI.iBnd[0].Rho[i] = saveRho[i] + + dRblw_dv = np.zeros((len(saveBlw), 0)) + deltaV = 1e-4 + + # Finite difference + for j in range(self.iSolverAPI.solver.pbl.nDim): + for i in range(len(saveV[:,0])): + self.iSolverAPI.iBnd[0].V[i,j] = saveV[i,j] + deltaV + self.iSolverAPI.setViscousSolver(1) + self.vSolver.run(1) + nRun+=1 + self.iSolverAPI.imposeBlwVel() + newBlowing = self.__getBlowingVelocity() + dRblw_dv = np.column_stack((dRblw_dv, (newBlowing - saveBlw) / deltaV)) + self.iSolverAPI.iBnd[0].V[i,j] = saveV[i,j] + + print('Total runs for finite difference', nRun) + self.coupledAdjointSolver.setdRblw_M(dRblw_dM) + self.coupledAdjointSolver.setdRblw_v(dRblw_dv) + self.coupledAdjointSolver.setdRblw_rho(dRblw_dRho) + + def __getBlowingVelocity(self): + blowingVelocity = np.zeros(0) + for k in range(len(self.iSolverAPI.blw[0].tag.elems)): + blowingVelocity = np.append(blowingVelocity, self.iSolverAPI.blw[0].getU(k)) + return blowingVelocity + + def __getInviscidState(self): + V = np.zeros((len(self.iSolverAPI.iBnd[0].nodesCoord[:,3]), 3)) + M = np.zeros(len(self.iSolverAPI.iBnd[0].nodesCoord[:,3])) + Rho = np.zeros(len(self.iSolverAPI.iBnd[0].nodesCoord[:,3])) + for n in range(2): + for iRow, row in enumerate(self.iSolverAPI.iBnd[n].nodesCoord[:,3]): + row=int(row) + for iDim in range(3): + V[iRow,iDim] = self.iSolverAPI.solver.U[row][iDim] + M[iRow] = self.iSolverAPI.solver.M[row] + Rho[iRow] = self.iSolverAPI.solver.rho[row] + return M, Rho, V diff --git a/blast/src/CMakeLists.txt b/blast/src/CMakeLists.txt index 394f4cb3d9eff38db98e44d6e2e9a46937771d32..f6964d91e7e637cc47dd9d5b4e95ac94c631374b 100644 --- a/blast/src/CMakeLists.txt +++ b/blast/src/CMakeLists.txt @@ -18,9 +18,13 @@ FILE(GLOB SRCS *.h *.cpp *.inl *.hpp) ADD_LIBRARY(blast SHARED ${SRCS}) MACRO_DebugPostfix(blast) -TARGET_INCLUDE_DIRECTORIES(blast PUBLIC ${PROJECT_SOURCE_DIR}/blast/src) +TARGET_INCLUDE_DIRECTORIES(blast PUBLIC ${PROJECT_SOURCE_DIR}/blast/src + ${PROJECT_SOURCE_DIR}/modules/dartflo/ext/amfe/tbox/src + ${PROJECT_SOURCE_DIR}/modules/dartflo/ext/amfe/fwk/src + ${PROJECT_SOURCE_DIR}/modules/dartflo/dart/src + ${PYTHON_INCLUDE_PATH}) -TARGET_LINK_LIBRARIES(blast tbox) +TARGET_LINK_LIBRARIES(blast dart tbox fwk) INSTALL(TARGETS blast DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/blast/src/DCoupledAdjoint.cpp b/blast/src/DCoupledAdjoint.cpp index 34db14b9fee840127b9bedda2bcff6e0c9b49423..2b54e0b4c7cabc7135bc988bfbcc3d29bc8af1c2 100644 --- a/blast/src/DCoupledAdjoint.cpp +++ b/blast/src/DCoupledAdjoint.cpp @@ -15,12 +15,12 @@ */ #include "DCoupledAdjoint.h" -#include "../../modules/dartflo/dart/src/wAdjoint.h" -#include "../../modules/dartflo/dart/src/wNewton.h" -#include "../../modules/dartflo/dart/src/wSolver.h" -#include "../../modules/dartflo/dart/src/wProblem.h" -#include "../../modules/dartflo/dart/src/wBlowing.h" -#include "../../modules/dartflo/dart/src/wFluid.h" +#include "wAdjoint.h" +#include "wNewton.h" +#include "wSolver.h" +#include "wProblem.h" +#include "wBlowing.h" +#include "wFluid.h" #include "wMshData.h" #include "wNode.h" @@ -45,136 +45,132 @@ CoupledAdjoint::CoupledAdjoint(std::shared_ptr<dart::Adjoint> _iadjoint, std::sh } else alinsol = isol->linsol; - + sizeBlowing = iadjoint->getSizeBlowing(); - - dCldAoA = 0.0; - dCddAoA = 0.0; + + auto nDim = isol->pbl->nDim; // Number of dimensions of the problem + auto nNs = isol->pbl->bBCs[0]->nodes.size(); // Number of surface nodes + auto nNd = isol->pbl->msh->nodes.size(); // Number of domain nodes + auto nEs = isol->pbl->bBCs[0]->uE.size(); // Number of elements on the surface + + 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); + dRv_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNd); + dRblw_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNd); + + dRphi_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); + dRM_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRrho_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRv_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNs); + dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); + + dRphi_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nNs); + dRM_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRrho_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nNs); + dRv_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nNs); + dRblw_rho = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nNs); + + dRphi_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nDim*nNs); + dRM_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNs); + dRrho_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nDim*nNs); + dRv_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nDim*nNs); + dRblw_v = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nDim*nNs); + + dRphi_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNd, nEs); + dRM_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); + dRrho_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nNs, nEs); + dRv_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nDim*nNs, nEs); + dRblw_blw = Eigen::SparseMatrix<double, Eigen::RowMajor>(nEs, nEs); + + dCl_phi = Eigen::VectorXd::Zero(nNd); + dCd_phi = Eigen::VectorXd::Zero(nNd); + + dCl_AoA = 0.0; + dCd_AoA = 0.0; } void CoupledAdjoint::buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> &matrices, Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint) { - // Determine the sizes of the smaller matrices - int rows = matrixAdjoint.rows(); - int cols = matrixAdjoint.cols(); - // Create a list of triplets for the larger matrix std::vector<Eigen::Triplet<double>> triplets; // Iterate over the rows and columns of the vector - int rowOffset = 0; - for (const auto& row : matrices) { - int colOffset = 0; - for (const auto& matrix : row) { - // Add the triplets of the matrix to the list of triplets for the larger matrix - for (int k = 0; k < matrix->outerSize(); ++k) { - for (Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator it(*matrix, k); it; ++it) { - triplets.push_back(Eigen::Triplet<double>(it.row() + rowOffset, it.col() + colOffset, it.value())); - } +int rowOffset = 0; +for (const auto& row : matrices) { + int colOffset = 0; + for (const auto& matrix : row) { + // Add the triplets of the matrix to the list of triplets for the larger matrix + for (int k = 0; k < matrix->outerSize(); ++k) { + for (Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator it(*matrix, k); it; ++it) { + triplets.push_back(Eigen::Triplet<double>(it.row() + rowOffset, it.col() + colOffset, it.value())); } - colOffset += matrix->cols(); } - rowOffset += row[0]->rows(); + colOffset += matrix->cols(); } - + rowOffset += row[0]->rows(); +} // Create a new matrix from the deque of triplets matrixAdjoint.setFromTriplets(triplets.begin(), triplets.end()); + matrixAdjoint.prune(0.); + matrixAdjoint.makeCompressed(); } void CoupledAdjoint::run() -{ - Eigen::SparseMatrix<double, Eigen::RowMajor> A = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> B = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> C = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> D = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> E = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> F = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> G = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> H = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - Eigen::SparseMatrix<double, Eigen::RowMajor> I = Eigen::SparseMatrix<double, Eigen::RowMajor>(3,3); - - std::deque<Eigen::Triplet<double>> T; - T.push_back(Eigen::Triplet<double>(0, 0, 1.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 2.0)); - A.setFromTriplets(T.begin(), T.end()); - //std::cout << "A\n" <<A << std::endl; - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 3.0)); - T.push_back(Eigen::Triplet<double>(0, 1, 2.0)); - B.setFromTriplets(T.begin(), T.end()); - //std::cout << "B\n" <<B << std::endl; - /*T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 0.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 0.0)); - C.setFromTriplets(T.begin(), T.end());*/ - std::cout << "C\n" << C << std::endl; - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 2.0)); - T.push_back(Eigen::Triplet<double>(2, 1, 1.0)); - D.setFromTriplets(T.begin(), T.end()); - //std::cout << "D\n" << D << std::endl; - - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 2.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 1.0)); - E.setFromTriplets(T.begin(), T.end()); - //std::cout << "E\n" << E << std::endl; - - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 2.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 1.0)); - F.setFromTriplets(T.begin(), T.end()); - //std::cout << "F\n" << F << std::endl; - - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 2.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 4.0)); - G.setFromTriplets(T.begin(), T.end()); - //std::cout << "G\n" << G << std::endl; - - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 2.0)); - T.push_back(Eigen::Triplet<double>(1, 1, 1.0)); - H.setFromTriplets(T.begin(), T.end()); - //std::cout << "H\n" << H << std::endl; - - T.clear(); - T.push_back(Eigen::Triplet<double>(0, 0, 5.0)); - T.push_back(Eigen::Triplet<double>(1, 2, 1.0)); - I.setFromTriplets(T.begin(), T.end()); - //std::cout << "I\n" << I << std::endl; - - std::cout << "gradientswrtInviscidFlow\n"; - dRM_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->bBCs[0]->nodes.size(), isol->pbl->msh->nodes.size()); - dRrho_phi = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->bBCs[0]->nodes.size(), isol->pbl->msh->nodes.size()); +{ gradientswrtInviscidFlow(); - std::cout << " coucou " << std::endl; - std::cout << "dRM_phi\n" << dRM_phi.norm() << std::endl; - std::cout << "dRrho_phi\n" << dRrho_phi.norm() << std::endl; + gradientswrtBlowingVelocity(); + transposeMatrices(); + gradientwrtAoA(); + + // Adjoint matrix // Store pointers to the matrices in a 2D vector std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> matrices = { - {&A, &B, &C, &D, &E}, - {&D, &E, &F, &I, &G}, - {&G, &H, &I, &A, &B}, - {&B, &E, &F, &I, &G}, - {&B, &A, &I, &C, &B} + {&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_blw, &dRM_blw, &dRv_blw, &dRrho_blw, &dRblw_blw} }; - // Create a larger sparse matrix and set it from the list of triplets int rows = 0; int cols = 0; - for (const auto& row : matrices) { - rows += row[0]->rows(); // All matrices in a row have the same number of rows - cols = std::max(cols, static_cast<int>(row.size() * row[0]->cols())); // All matrices in a column have the same number of columns - } + for (const auto& row : matrices) rows += row[0]->rows(); // All matrices in a row have the same number of rows + 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); - std::cout << "largeMatrix\n" << A_adjoint << std::endl; + /******** CL ********/ + // Build right hand side for Cl + std::vector<double> rhsCl(A_adjoint.cols(), 0.0); + std::copy(dCl_phi.data(), dCl_phi.data() + dCl_phi.size(), rhsCl.begin()); + + // Solution vector for lambdasCl + Eigen::VectorXd lambdasCl(A_adjoint.cols()); + Eigen::Map<Eigen::VectorXd> lambdasCl_(lambdasCl.data(), lambdasCl.size()); // Solve coupled system - // alinsol->compute(AdjointMatrix.transpose(), Eigen::Map<Eigen::VectorXd>(dU_.data(), dU_.size()), lambdas); + alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCl.data(), rhsCl.size()), lambdasCl_); + Eigen::VectorXd lambdaClPhi = lambdasCl.block(0, 0, isol->pbl->msh->nodes.size(), 1); + + // Compute total derivative dCl_dAoA + tdCl_AoA = dCl_AoA - dRphi_AoA.transpose()*lambdaClPhi; + + /******** CD ********/ + // Build right hand side for Cd + std::vector<double> rhsCd(A_adjoint.cols(), 0.0); + std::copy(dCd_phi.data(), dCd_phi.data() + dCd_phi.size(), rhsCd.begin()); + + // Solution vector for lambdasCd + Eigen::VectorXd lambdasCd(A_adjoint.cols()); + Eigen::Map<Eigen::VectorXd> lambdasCd_(lambdasCd.data(), lambdasCd.size()); + + // Solve coupled system + alinsol->compute(A_adjoint, Eigen::Map<Eigen::VectorXd>(rhsCd.data(), rhsCd.size()), lambdasCd_); + Eigen::VectorXd lambdaCdPhi = lambdasCd.block(0, 0, isol->pbl->msh->nodes.size(), 1); + + // Compute total derivative dCl_dAoA + tdCd_AoA = dCd_AoA - dRphi_AoA.transpose()*lambdaCdPhi; } void CoupledAdjoint::gradientswrtInviscidFlow() @@ -182,96 +178,180 @@ void CoupledAdjoint::gradientswrtInviscidFlow() //**** dRphi_phi ****// dRphi_phi = iadjoint->getRu_U(); - //**** dRM_phi, dRrho_phi, dRv_phi ****// - auto pbl = isol->pbl; - //dRM_dPhi = iadjoint->getRM_U(); - // Finite difference - double deltaPhi = 1e-4; // perturbation - std::vector<double> Phi_save = isol->phi; // Differential of the independant variable (phi) - std::vector<double> dM = std::vector<double>(pbl->bBCs[0]->nodes.size(), 0.0); // Differential of the Mach number - std::vector<double> drho = std::vector<double>(pbl->bBCs[0]->nodes.size(), 0.0); // Differential of the density - - std::vector<Eigen::Triplet<double>> tripletsdM; - std::vector<Eigen::Triplet<double>> tripletsdrho; - - for (auto n : pbl->msh->nodes){ - Phi_save[n->row] = isol->phi[n->row] + deltaPhi; - - std::fill(dM.begin(), dM.end(), 0.0); - std::fill(drho.begin(), drho.end(), 0.0); - - // Recompute Mach number on surface nodes. - size_t jj = 0; - for (auto srfNode : pbl->bBCs[0]->nodes){ - // Average of the Mach on the elements adjacent to the considered node. - for (auto e : pbl->fluid->neMap[srfNode]){ - dM[jj] += pbl->fluid->mach->eval(*e, Phi_save, 0); - drho[jj] += pbl->fluid->rho->eval(*e, Phi_save, 0); - } - dM[jj] /= pbl->fluid->neMap[srfNode].size(); - drho[jj] /= pbl->fluid->neMap[srfNode].size(); - // Form triplets - tripletsdM.push_back(Eigen::Triplet<double>(jj, n->row, (dM[jj] - isol->M[srfNode->row])/deltaPhi)); - tripletsdrho.push_back(Eigen::Triplet<double>(jj, n->row, (drho[jj] - isol->rho[srfNode->row])/deltaPhi)); - jj++; - } - // Reset phi - Phi_save[n->row] = isol->phi[n->row]; - } - - // Fill matrices with gradients - dRM_phi.setFromTriplets(tripletsdM.begin(), tripletsdM.end()); - dRrho_phi.setFromTriplets(tripletsdrho.begin(), tripletsdrho.end()); - // Remove zeros - dRM_phi.prune(0.); - dRrho_phi.prune(0.); - - // // Objective functionss - // dCl_dPhi = - // dCd_dPhi = + // //**** dRM_phi, dRrho_phi, dRv_phi ****// + // auto pbl = isol->pbl; + // //dRM_dPhi = iadjoint->getRM_U(); + // // Finite difference + // double deltaPhi = 1e-4; // perturbation + // std::vector<double> Phi_save = isol->phi; // Differential of the independant variable (phi) + // std::vector<double> dM = std::vector<double>(pbl->bBCs[0]->nodes.size(), 0.0); // Differential of the Mach number + // std::vector<double> dv = std::vector<double>(pbl->nDim*pbl->bBCs[0]->nodes.size(), 0.0); // Differential of the Mach number + // std::vector<double> drho = std::vector<double>(pbl->bBCs[0]->nodes.size(), 0.0); // Differential of the density + + // std::vector<Eigen::Triplet<double>> tripletsdM; + // std::vector<Eigen::Triplet<double>> tripletsdrho; + // std::vector<Eigen::Triplet<double>> tripletsdv; + + // for (auto n : pbl->msh->nodes){ + // Phi_save[n->row] = isol->phi[n->row] + deltaPhi; + + // std::fill(dM.begin(), dM.end(), 0.0); + // std::fill(drho.begin(), drho.end(), 0.0); + + // // Recompute Mach number on surface nodes. + // size_t jj = 0; + // for (auto srfNode : pbl->bBCs[0]->nodes){ + // // Average of the Mach on the elements adjacent to the considered node. + // for (auto e : pbl->fluid->neMap[srfNode]){ + // dM[jj] += pbl->fluid->mach->eval(*e, Phi_save, 0); + // drho[jj] += pbl->fluid->rho->eval(*e, Phi_save, 0); + // Eigen::VectorXd grad = e->computeGradient(Phi_save, 0); + // for (size_t i = 0; i < grad.size(); ++i) + // dv[jj*pbl->nDim + i] += grad(i); + // } + // dM[jj] /= pbl->fluid->neMap[srfNode].size(); + // drho[jj] /= pbl->fluid->neMap[srfNode].size(); + // for (size_t i = 0; i < pbl->nDim; ++i){ + // dv[jj*pbl->nDim + i] /= pbl->fluid->neMap[srfNode].size(); + // tripletsdv.push_back(Eigen::Triplet<double>(jj*pbl->nDim + i, n->row, dv[jj*pbl->nDim + i] - isol->U[srfNode->row][i]/deltaPhi)); + // } + // // Form triplets + // tripletsdM.push_back(Eigen::Triplet<double>(jj, n->row, (dM[jj] - isol->M[srfNode->row])/deltaPhi)); + // tripletsdrho.push_back(Eigen::Triplet<double>(jj, n->row, (drho[jj] - isol->rho[srfNode->row])/deltaPhi)); + // jj++; + // } + // // Reset phi + // Phi_save[n->row] = isol->phi[n->row]; + // } + + // // Fill matrices with gradients + // dRM_phi.setFromTriplets(tripletsdM.begin(), tripletsdM.end()); + // dRrho_phi.setFromTriplets(tripletsdrho.begin(), tripletsdrho.end()); + // dRv_phi.setFromTriplets(tripletsdv.begin(), tripletsdv.end()); + // // Remove zeros + // dRM_phi.prune(0.); + // dRrho_phi.prune(0.); + // dRv_phi.prune(0.); + + // Objective functionss + std::vector<std::vector<double>> dCx_phi = iadjoint->computeGradientCoefficientsFlow(); + dCl_phi = Eigen::VectorXd::Map(dCx_phi[0].data(), dCx_phi[0].size()); + dCd_phi = Eigen::VectorXd::Map(dCx_phi[1].data(), dCx_phi[1].size()); } void CoupledAdjoint::gradientswrtMachNumber(){ - // dRphi_dM = 0 - // dRM_dM = - // dRrho_dM = 0 - // dRv_dM = 0 - // dRblw_dM = - - // // Objective functions - // dCl_dM = - // dCd_dM = + // dRphi_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->msh->nodes.size(), isol->pbl->bBCs[0]->nodes.size()); + // dRrho_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->bBCs[0]->nodes.size(), isol->pbl->bBCs[0]->nodes.size()); + // dRv_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->nDim*isol->pbl->bBCs[0]->nodes.size(), isol->pbl->bBCs[0]->nodes.size()); + // dRblw_M = Eigen::SparseMatrix<double, Eigen::RowMajor>(isol->pbl->bBCs[0]->uE.size(), isol->pbl->bBCs[0]->nodes.size()); } void CoupledAdjoint::gradientswrtDensity(){ // dRphi_dRho = 0 // dRM_dRho = 0 - // dRrho_dRho = + // dRrho_dRho = // dRv_dRho = 0 // dRblw_dRho = - // dCl_dRho = - // dCd_dRho = + // dCl_dRho = + // dCd_dRho = } void CoupledAdjoint::gradientswrtVelocity(){ // dRphi_dV = 0 // dRM_dV = 0 // dRrho_dV = 0 - // dRv_dV = - // dRblw_dV = + // dRv_dV = + // dRblw_dV = - // dCl_dV = - // dCd_dV = + // dCl_dV = + // dCd_dV = } void CoupledAdjoint::gradientswrtBlowingVelocity(){ - // dRphi_dBlw = - // dRM_dBlw = 0 - // dRrho_dBlw = 0 - // dRv_dBlw = 0 - // dRblw_dBlw = - - // dCl_dBlw = - // dCd_dBlw = -} \ No newline at end of file + //dRphi_blw = iadjoint->getRu_Blw(); + + // All others are zero. +} + +void CoupledAdjoint::gradientwrtAoA(){ + std::vector<double> dCx_AoA = iadjoint->computeGradientCoefficientsAoa(); + dCl_AoA = dCx_AoA[0]; dCd_AoA = dCx_AoA[1]; + + dRphi_AoA = iadjoint->getRu_A(); + + // All others are zero. +} + +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()); + // Convert std::vector<double> to Eigen::Triplets + std::vector<Eigen::Triplet<double>> triplets; + for (size_t i = 0; i < _dRblw_dM.size(); i++){ + for (size_t j = 0; j < _dRblw_dM[i].size(); j++){ + triplets.push_back(Eigen::Triplet<double>(i, j, _dRblw_dM[i][j])); + } + } + // Set matrix + dRblw_M.setFromTriplets(triplets.begin(), triplets.end()); + 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()); + // Convert std::vector<double> to Eigen::Triplets + std::vector<Eigen::Triplet<double>> triplets; + for (size_t i = 0; i < _dRblw_dv.size(); i++){ + for (size_t j = 0; j < _dRblw_dv[i].size(); j++){ + triplets.push_back(Eigen::Triplet<double>(i, j, _dRblw_dv[i][j])); + } + } + // Set matrix + dRblw_v.setFromTriplets(triplets.begin(), triplets.end()); + 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()); + // Convert std::vector<double> to Eigen::Triplets + std::vector<Eigen::Triplet<double>> triplets; + for (size_t i = 0; i < _dRblw_drho.size(); i++){ + for (size_t j = 0; j < _dRblw_drho[i].size(); j++){ + triplets.push_back(Eigen::Triplet<double>(i, j, _dRblw_drho[i][j])); + } + } + // Set matrix + dRblw_rho.setFromTriplets(triplets.begin(), triplets.end()); + dRblw_rho.prune(0.); +} + +void CoupledAdjoint::transposeMatrices(){ + // Transpose all matrices + dRphi_phi = dRphi_phi.transpose(); + dRphi_M = dRphi_M.transpose(); + dRphi_rho = dRphi_rho.transpose(); + dRphi_v = dRphi_v.transpose(); + dRphi_blw = dRphi_blw.transpose(); + + dRM_phi = dRM_phi.transpose(); + dRM_M = dRM_M.transpose(); + dRM_rho = dRM_rho.transpose(); + dRM_v = dRM_v.transpose(); + dRM_blw = dRM_blw.transpose(); + + dRrho_phi = dRrho_phi.transpose(); + dRrho_M = dRrho_M.transpose(); + dRrho_rho = dRrho_rho.transpose(); + dRrho_v = dRrho_v.transpose(); + dRrho_blw = dRrho_blw.transpose(); + + dRv_phi = dRv_phi.transpose(); + dRv_M = dRv_M.transpose(); + dRv_rho = dRv_rho.transpose(); + dRv_v = dRv_v.transpose(); + dRv_blw = dRv_blw.transpose(); + + dRblw_phi = dRblw_phi.transpose(); + dRblw_M = dRblw_M.transpose(); + dRblw_rho = dRblw_rho.transpose(); + dRblw_v = dRblw_v.transpose(); + dRblw_blw = dRblw_blw.transpose(); +} diff --git a/blast/src/DCoupledAdjoint.h b/blast/src/DCoupledAdjoint.h index 73aa0b5051c869fcc616faaa4d049fcec8d864b8..93973c7f917b84e4564d3c35e8348a15f2dc9fa5 100644 --- a/blast/src/DCoupledAdjoint.h +++ b/blast/src/DCoupledAdjoint.h @@ -19,7 +19,7 @@ #include "blast.h" #include "wObject.h" -#include "../../modules/dartflo/dart/src/wAdjoint.h" +#include "dart.h" #include <Eigen/Sparse> #include <iostream> @@ -39,9 +39,12 @@ public: std::shared_ptr<dart::Newton> isol; ///< Inviscid Newton solver std::shared_ptr<blast::Driver> vsol; ///< Viscous solver std::shared_ptr<tbox::LinearSolver> alinsol; ///< linear solver (adjoint aero) - double dCldAoA; - double dCddAoA; + 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 tdCl_AoA; ///< Total derivative of the lift coefficient with respect to the angle of attack + double tdCd_AoA; ///< Total erivative of the drag coefficient with respect to the angle of attack private: size_t sizeBlowing; @@ -75,12 +78,20 @@ private: Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_rho; ///< Derivative of the blowing velocity residual with respect to the density Eigen::SparseMatrix<double, Eigen::RowMajor> dRblw_blw; ///< Derivative of the blowing velocity residual with respect to the blowing velocity + Eigen::VectorXd dRphi_AoA; ///< Derivative of the inviscid flow residual with respect to the angle of attack + 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 + public: CoupledAdjoint(std::shared_ptr<dart::Adjoint> iAdjoint, std::shared_ptr<blast::Driver> vSolver); - virtual ~CoupledAdjoint () {std::cout << "~CoupledAdjoint()\n";}; + virtual ~CoupledAdjoint () {std::cout << "~blast::CoupledAdjoint()\n";}; void run(); + void setdRblw_M(std::vector<std::vector<double>> dRblw_dM); + void setdRblw_v(std::vector<std::vector<double>> dRblw_dv); + void setdRblw_rho(std::vector<std::vector<double>> dRblw_drho); + private: void buildAdjointMatrix(std::vector<std::vector<Eigen::SparseMatrix<double, Eigen::RowMajor>*>> &matrices, Eigen::SparseMatrix<double, Eigen::RowMajor> &matrixAdjoint); @@ -89,6 +100,10 @@ private: void gradientswrtDensity(); void gradientswrtVelocity(); void gradientswrtBlowingVelocity(); + + void gradientwrtAoA(); + + void transposeMatrices(); }; } // namespace blast #endif // DDARTADJOINT diff --git a/blast/src/DDriver.cpp b/blast/src/DDriver.cpp index a1fcba0bbb46a638a8ea896cfa1f40ab71460ec5..b937b4fd30652b43034c123f2f1d28b5b9f424b5 100644 --- a/blast/src/DDriver.cpp +++ b/blast/src/DDriver.cpp @@ -162,7 +162,7 @@ int Driver::run(unsigned int const couplIter) { tSolver->setCFL0(CFL0); tSolver->setitFrozenJac(5); - tSolver->setinitSln(false); + tSolver->setinitSln(true); // Keyword annoncing iteration safety level. if (verbose > 1) diff --git a/blast/tests/dart/adjointVII.py b/blast/tests/dart/adjointVII.py index 6b2f8bb87562f1d329f2383fa82d552b4b53d8c8..a689678825c4e2bbdd146eadce4a15d579812eb5 100644 --- a/blast/tests/dart/adjointVII.py +++ b/blast/tests/dart/adjointVII.py @@ -105,7 +105,18 @@ def cfgBlast(verb): 'nDim' : 2 } +import dart.utils as floU +import dart.default as floD +import tbox.utils as tboxU +import fwk +from fwk.testing import * +from fwk.coloring import ccolors +import numpy as np + def main(): + + alpha = 2*np.pi/180 + # Timer. tms = fwk.Timers() tms['total'].start() @@ -118,15 +129,120 @@ def main(): coupler, iSolverAPI, vSolver = viscUtils.initBlast(icfg, vcfg) tms['pre'].stop() - adjointSolver = blast.CoupledAdjoint(iSolverAPI.adjointSolver, vSolver) + coupledAdjointSolver = blast.CoupledAdjoint(iSolverAPI.adjointSolver, vSolver) + from blast.interfaces.dart.DartAdjointInterface import DartAdjointInterface as DartAdjointinterface + pyAdjoint = DartAdjointinterface(coupledAdjointSolver, iSolverAPI, vSolver) print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) tms['solver'].start() aeroCoeffs = coupler.run() + tms['solver'].stop() #iSolverAPI.run() - adjointSolver.run() - print("sucess", adjointSolver) + tms['FDDerivatives'].start() + #pyAdjoint.computeDerivatives() + tms['FDDerivatives'].stop() + tms['CoupledAdjoint'].start() + iSolverAPI.adjointSolver.run() + tms['CoupledAdjoint'].stop() + dCl_dAlpha_DartAdjoint = iSolverAPI.adjointSolver.dClAoa + dCd_dAlpha_DartAdjoint = iSolverAPI.adjointSolver.dCdAoa + coupledAdjointSolver.run() + print("sucess", coupledAdjointSolver) + + dalpha = 1e-4 + aoaV = [alpha-dalpha, alpha+dalpha] + clV = [] + cdV = [] + for aoa in aoaV: + coupler, iSolverAPI, vSolver = viscUtils.initBlast(icfg, vcfg) + iSolverAPI.argOut['pbl'].update(aoa) + coupler.run() + clV.append(iSolverAPI.getCl()) + cdV.append(iSolverAPI.getCd()) + dCl_dalpha_FD_coupled = (clV[-1] - clV[0]) / (2*dalpha) + dCd_dalpha_FD_coupled = (cdV[-1] - cdV[0]) / (2*dalpha) + + dalpha = 1e-4 + aoaV = [alpha-dalpha, alpha+dalpha] + clV = [] + cdV = [] + for aoa in aoaV: + coupler, iSolverAPI, vSolver = viscUtils.initBlast(icfg, vcfg) + iSolverAPI.argOut['pbl'].update(aoa) + iSolverAPI.run() + clV.append(iSolverAPI.getCl()) + cdV.append(iSolverAPI.getCd()) + dCl_dalpha_FD_dart = (clV[-1] - clV[0]) / (2*dalpha) + dCd_dalpha_FD_dart = (cdV[-1] - cdV[0]) / (2*dalpha) + + print(' ------------------- RESULTS -------------------') + print('CL') + print('dCl_dalpha_adjointDart', dCl_dAlpha_DartAdjoint) + print('dCl_dalpha_FD', dCl_dalpha_FD_dart) + print('dCl_dalpha_FD', dCl_dalpha_FD_coupled) + print('dCl_dalpha_coupledAdjoint', coupledAdjointSolver.tdCl_AoA) + + print('CD') + print('dCd_dalpha_adjointDart', dCd_dAlpha_DartAdjoint) + print('dCd_dalpha_FD', dCd_dalpha_FD_dart) + print('dCd_dalpha_FD', dCd_dalpha_FD_coupled) + print('dCd_dalpha_coupledAdjoint', coupledAdjointSolver.tdCd_AoA) + + print(tms) + + quit() + + # ONLY DART + + # define flow variables + 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' : 1., 'msTe' : 0.0075, 'msLe' : 0.0075} + 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() + + # set the problem and add fluid, initial/boundary conditions + tms['pre'].start() + pbl, _, _, bnd, _ = floD.problem(msh, dim, alpha, 0., M_inf, c_ref, c_ref, 0.25, 0., 0., 'airfoil',vsc=True, dbc=True) + tms['pre'].stop() + + # 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() + + dalpha = 1e-2 + aoaV = [alpha-dalpha, alpha+dalpha] + clV = [] + for aoa in aoaV: + pbl.update(aoa) + solver.reset() + solver.run() + clV.append(solver.Cl) + print(clV) + dCl_dalpha_FD = (clV[-1] - clV[0]) / (2*dalpha) + print('dCl_dalpha_FD', dCl_dalpha_FD) + print('dCl_dalpha_adjointDart', adjoint.dClAoa) quit()