void AssembleBoussinesqAppoximation_AD(MultiLevelProblem& ml_prob) { // ml_prob is the global object from/to where get/set all the data // level is the level of the PDE system to be assembled // levelMax is the Maximum level of the MultiLevelProblem // assembleMatrix is a flag that tells if only the residual or also the matrix should be assembled // extract pointers to the several objects that we are going to use TransientNonlinearImplicitSystem* mlPdeSys = &ml_prob.get_system<TransientNonlinearImplicitSystem> ("NS"); // pointer to the linear implicit system named "Poisson" const unsigned level = mlPdeSys->GetLevelToAssemble(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object bool assembleMatrix = mlPdeSys->GetAssembleMatrix(); // call the adept stack object adept::Stack& s = FemusInit::_adeptStack; if(assembleMatrix) s.continue_recording(); else s.pause_recording(); SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned dim2 = (3 * (dim - 1) + !(dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) // reserve memory for the local standar vectors const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 //solution variable unsigned solTIndex; solTIndex = mlSol->GetIndex("T"); // get the position of "T" in the ml_sol object unsigned solTType = mlSol->GetSolutionType(solTIndex); // get the finite element type for "T" vector < unsigned > solVIndex(dim); solVIndex[0] = mlSol->GetIndex("U"); // get the position of "U" in the ml_sol object solVIndex[1] = mlSol->GetIndex("V"); // get the position of "V" in the ml_sol object if(dim == 3) solVIndex[2] = mlSol->GetIndex("W"); // get the position of "V" in the ml_sol object unsigned solVType = mlSol->GetSolutionType(solVIndex[0]); // get the finite element type for "u" unsigned solPIndex; solPIndex = mlSol->GetIndex("P"); // get the position of "P" in the ml_sol object unsigned solPType = mlSol->GetSolutionType(solPIndex); // get the finite element type for "u" unsigned solTPdeIndex; solTPdeIndex = mlPdeSys->GetSolPdeIndex("T"); // get the position of "T" in the pdeSys object // std::cout << solTIndex <<" "<<solTPdeIndex<<std::endl; vector < unsigned > solVPdeIndex(dim); solVPdeIndex[0] = mlPdeSys->GetSolPdeIndex("U"); // get the position of "U" in the pdeSys object solVPdeIndex[1] = mlPdeSys->GetSolPdeIndex("V"); // get the position of "V" in the pdeSys object if(dim == 3) solVPdeIndex[2] = mlPdeSys->GetSolPdeIndex("W"); unsigned solPPdeIndex; solPPdeIndex = mlPdeSys->GetSolPdeIndex("P"); // get the position of "P" in the pdeSys object vector < adept::adouble > solT; // local solution vector < vector < adept::adouble > > solV(dim); // local solution vector < adept::adouble > solP; // local solution vector < double > solTold; // local solution vector < vector < double > > solVold(dim); // local solution vector < double > solPold; // local solution vector< adept::adouble > aResT; // local redidual vector vector< vector < adept::adouble > > aResV(dim); // local redidual vector vector< adept::adouble > aResP; // local redidual vector vector < vector < double > > coordX(dim); // local coordinates unsigned coordXType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) solT.reserve(maxSize); solTold.reserve(maxSize); aResT.reserve(maxSize); for(unsigned k = 0; k < dim; k++) { solV[k].reserve(maxSize); solVold[k].reserve(maxSize); aResV[k].reserve(maxSize); coordX[k].reserve(maxSize); } solP.reserve(maxSize); solPold.reserve(maxSize); aResP.reserve(maxSize); vector <double> phiV; // local test function vector <double> phiV_x; // local test function first order partial derivatives vector <double> phiV_xx; // local test function second order partial derivatives phiV.reserve(maxSize); phiV_x.reserve(maxSize * dim); phiV_xx.reserve(maxSize * dim2); vector <double> phiT; // local test function vector <double> phiT_x; // local test function first order partial derivatives vector <double> phiT_xx; // local test function second order partial derivatives phiT.reserve(maxSize); phiT_x.reserve(maxSize * dim); phiT_xx.reserve(maxSize * dim2); double* phiP; double weight; // gauss point weight vector< int > sysDof; // local to global pdeSys dofs sysDof.reserve((dim + 2) *maxSize); vector< double > Res; // local redidual vector Res.reserve((dim + 2) *maxSize); vector < double > Jac; Jac.reserve((dim + 2) *maxSize * (dim + 2) *maxSize); if(assembleMatrix) KK->zero(); // Set to zero all the entries of the Global Matrix // element loop: each process loops only on the elements that owns for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { // element geometry type short unsigned ielGeom = msh->GetElementType(iel); unsigned nDofsT = msh->GetElementDofNumber(iel, solTType); // number of solution element dofs unsigned nDofsV = msh->GetElementDofNumber(iel, solVType); // number of solution element dofs unsigned nDofsP = msh->GetElementDofNumber(iel, solPType); // number of solution element dofs unsigned nDofsX = msh->GetElementDofNumber(iel, coordXType); // number of coordinate element dofs unsigned nDofsTVP = nDofsT + dim * nDofsV + nDofsP; // resize local arrays sysDof.resize(nDofsTVP); solT.resize(nDofsV); solTold.resize(nDofsV); for(unsigned k = 0; k < dim; k++) { solV[k].resize(nDofsV); solVold[k].resize(nDofsV); coordX[k].resize(nDofsX); } solP.resize(nDofsP); solPold.resize(nDofsP); aResT.resize(nDofsV); //resize std::fill(aResT.begin(), aResT.end(), 0); //set aRes to zero for(unsigned k = 0; k < dim; k++) { aResV[k].resize(nDofsV); //resize std::fill(aResV[k].begin(), aResV[k].end(), 0); //set aRes to zero } aResP.resize(nDofsP); //resize std::fill(aResP.begin(), aResP.end(), 0); //set aRes to zero // local storage of global mapping and solution for(unsigned i = 0; i < nDofsT; i++) { unsigned solTDof = msh->GetSolutionDof(i, iel, solTType); // global to global mapping between solution node and solution dof solT[i] = (*sol->_Sol[solTIndex])(solTDof); // global extraction and local storage for the solution solTold[i] = (*sol->_SolOld[solTIndex])(solTDof); // global extraction and local storage for the solution sysDof[i] = pdeSys->GetSystemDof(solTIndex, solTPdeIndex, i, iel); // global to global mapping between solution node and pdeSys dofs } // local storage of global mapping and solution for(unsigned i = 0; i < nDofsV; i++) { unsigned solVDof = msh->GetSolutionDof(i, iel, solVType); // global to global mapping between solution node and solution dof for(unsigned k = 0; k < dim; k++) { solV[k][i] = (*sol->_Sol[solVIndex[k]])(solVDof); // global extraction and local storage for the solution solVold[k][i] = (*sol->_SolOld[solVIndex[k]])(solVDof); // global extraction and local storage for the solution sysDof[i + nDofsT + k * nDofsV] = pdeSys->GetSystemDof(solVIndex[k], solVPdeIndex[k], i, iel); // global to global mapping between solution node and pdeSys dof } } for(unsigned i = 0; i < nDofsP; i++) { unsigned solPDof = msh->GetSolutionDof(i, iel, solPType); // global to global mapping between solution node and solution dof solP[i] = (*sol->_Sol[solPIndex])(solPDof); // global extraction and local storage for the solution solPold[i] = (*sol->_SolOld[solPIndex])(solPDof); // global extraction and local storage for the solution sysDof[i + nDofsT + dim * nDofsV] = pdeSys->GetSystemDof(solPIndex, solPPdeIndex, i, iel); // global to global mapping between solution node and pdeSys dof } // local storage of coordinates for(unsigned i = 0; i < nDofsX; i++) { unsigned coordXDof = msh->GetSolutionDof(i, iel, coordXType); // global to global mapping between coordinates node and coordinate dof for(unsigned k = 0; k < dim; k++) { coordX[k][i] = (*msh->_topology->_Sol[k])(coordXDof); // global extraction and local storage for the element coordinates } } // start a new recording of all the operations involving adept::adouble variables if(assembleMatrix) s.new_recording(); // *** Gauss point loop *** for(unsigned ig = 0; ig < msh->_finiteElement[ielGeom][solVType]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** msh->_finiteElement[ielGeom][solTType]->Jacobian(coordX, ig, weight, phiT, phiT_x, phiT_xx); msh->_finiteElement[ielGeom][solVType]->Jacobian(coordX, ig, weight, phiV, phiV_x, phiV_xx); phiP = msh->_finiteElement[ielGeom][solPType]->GetPhi(ig); // evaluate the solution, the solution derivatives and the coordinates in the gauss point adept::adouble solT_gss = 0; double solTold_gss = 0; vector < adept::adouble > gradSolT_gss(dim, 0.); vector < double > gradSolTold_gss(dim, 0.); for(unsigned i = 0; i < nDofsT; i++) { solT_gss += phiT[i] * solT[i]; solTold_gss += phiT[i] * solTold[i]; for(unsigned j = 0; j < dim; j++) { gradSolT_gss[j] += phiT_x[i * dim + j] * solT[i]; gradSolTold_gss[j] += phiT_x[i * dim + j] * solTold[i]; } } vector < adept::adouble > solV_gss(dim, 0); vector < double > solVold_gss(dim, 0); vector < vector < adept::adouble > > gradSolV_gss(dim); vector < vector < double > > gradSolVold_gss(dim); for(unsigned k = 0; k < dim; k++) { gradSolV_gss[k].resize(dim); gradSolVold_gss[k].resize(dim); std::fill(gradSolV_gss[k].begin(), gradSolV_gss[k].end(), 0); std::fill(gradSolVold_gss[k].begin(), gradSolVold_gss[k].end(), 0); } for(unsigned i = 0; i < nDofsV; i++) { for(unsigned k = 0; k < dim; k++) { solV_gss[k] += phiV[i] * solV[k][i]; solVold_gss[k] += phiV[i] * solVold[k][i]; } for(unsigned j = 0; j < dim; j++) { for(unsigned k = 0; k < dim; k++) { gradSolV_gss[k][j] += phiV_x[i * dim + j] * solV[k][i]; gradSolVold_gss[k][j] += phiV_x[i * dim + j] * solVold[k][i]; } } } adept::adouble solP_gss = 0; double solPold_gss = 0; for(unsigned i = 0; i < nDofsP; i++) { solP_gss += phiP[i] * solP[i]; solPold_gss += phiP[i] * solPold[i]; } double alpha = 1.; double beta = 1.;//40000.; double Pr = 0.71; double Ra = 340000; double dt = mlPdeSys -> GetIntervalTime(); // *** phiT_i loop *** for(unsigned i = 0; i < nDofsT; i++) { adept::adouble Temp = 0.; adept::adouble TempOld = 0.; for(unsigned j = 0; j < dim; j++) { Temp += 1. / sqrt(Ra * Pr) * alpha * phiT_x[i * dim + j] * gradSolT_gss[j]; Temp += phiT[i] * (solV_gss[j] * gradSolT_gss[j]); TempOld += 1. / sqrt(Ra * Pr) * alpha * phiT_x[i * dim + j] * gradSolTold_gss[j]; TempOld += phiT[i] * (solVold_gss[j] * gradSolTold_gss[j]); } aResT[i] += (- (solT_gss - solTold_gss) * phiT[i] / dt - 0.5 * (Temp + TempOld)) * weight; } // end phiT_i loop // *** phiV_i loop *** for(unsigned i = 0; i < nDofsV; i++) { vector < adept::adouble > NSV(dim, 0.); vector < double > NSVold(dim, 0.); for(unsigned j = 0; j < dim; j++) { for(unsigned k = 0; k < dim; k++) { NSV[k] += sqrt(Pr / Ra) * phiV_x[i * dim + j] * (gradSolV_gss[k][j] + gradSolV_gss[j][k]); NSV[k] += phiV[i] * (solV_gss[j] * gradSolV_gss[k][j]); NSVold[k] += sqrt(Pr / Ra) * phiV_x[i * dim + j] * (gradSolVold_gss[k][j] + gradSolVold_gss[j][k]); NSVold[k] += phiV[i] * (solVold_gss[j] * gradSolVold_gss[k][j]); } } for(unsigned k = 0; k < dim; k++) { NSV[k] += -solP_gss * phiV_x[i * dim + k]; NSVold[k] += -solPold_gss * phiV_x[i * dim + k]; } NSV[1] += -beta * solT_gss * phiV[i]; NSVold[1] += -beta * solTold_gss * phiV[i]; for(unsigned k = 0; k < dim; k++) { aResV[k][i] += (- (solV_gss[k] - solVold_gss[k]) * phiV[i] / dt - 0.5 * (NSV[k] + NSVold[k])) * weight; } } // end phiV_i loop // *** phiP_i loop *** for(unsigned i = 0; i < nDofsP; i++) { for(int k = 0; k < dim; k++) { aResP[i] += - (gradSolV_gss[k][k]) * phiP[i] * weight; } } // end phiP_i loop } // end gauss point loop //-------------------------------------------------------------------------------------------------------- // Add the local Matrix/Vector into the global Matrix/Vector //copy the value of the adept::adoube aRes in double Res and store them in RES Res.resize(nDofsTVP); //resize for(int i = 0; i < nDofsT; i++) { Res[i] = -aResT[i].value(); } for(int i = 0; i < nDofsV; i++) { for(unsigned k = 0; k < dim; k++) { Res[ i + nDofsT + k * nDofsV ] = -aResV[k][i].value(); } } for(int i = 0; i < nDofsP; i++) { Res[ i + nDofsT + dim * nDofsV ] = -aResP[i].value(); } RES->add_vector_blocked(Res, sysDof); //Extarct and store the Jacobian if(assembleMatrix) { Jac.resize(nDofsTVP * nDofsTVP); // define the dependent variables s.dependent(&aResT[0], nDofsT); for(unsigned k = 0; k < dim; k++) { s.dependent(&aResV[k][0], nDofsV); } s.dependent(&aResP[0], nDofsP); // define the independent variables s.independent(&solT[0], nDofsT); for(unsigned k = 0; k < dim; k++) { s.independent(&solV[k][0], nDofsV); } s.independent(&solP[0], nDofsP); // get the and store jacobian matrix (row-major) s.jacobian(&Jac[0] , true); KK->add_matrix_blocked(Jac, sysDof, sysDof); s.clear_independents(); s.clear_dependents(); } } //end element loop for each process RES->close(); if(assembleMatrix) { KK->close(); } // ***************** END ASSEMBLY ******************* }
void AssembleWillmoreFlow_AD(MultiLevelProblem& ml_prob) { // ml_prob is the global object from/to where get/set all the data // level is the level of the PDE system to be assembled // levelMax is the Maximum level of the MultiLevelProblem // assembleMatrix is a flag that tells if only the residual or also the matrix should be assembled // call the adept stack object adept::Stack& s = FemusInit::_adeptStack; // extract pointers to the several objects that we are going to use TransientNonlinearImplicitSystem* mlPdeSys = &ml_prob.get_system<TransientNonlinearImplicitSystem> ("Willmore"); // pointer to the linear implicit system named "Poisson" const unsigned level = mlPdeSys->GetLevelToAssemble(); const unsigned levelMax = mlPdeSys->GetLevelMax(); const bool assembleMatrix = mlPdeSys->GetAssembleMatrix(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) //solution variable unsigned solRIndex[3]; solRIndex[0] = mlSol->GetIndex("X"); // get the position of "X" in the ml_sol object solRIndex[1] = mlSol->GetIndex("Y"); // get the position of "Y" in the ml_sol object solRIndex[2] = mlSol->GetIndex("Z"); // get the position of "Z" in the ml_sol object unsigned solRType[3]; solRType[0]= mlSol->GetSolutionType(solRIndex[0]); // get the finite element type for "R" solRType[1]= mlSol->GetSolutionType(solRIndex[1]); // get the finite element type for "R" solRType[2]= mlSol->GetSolutionType(solRIndex[2]); // get the finite element type for "R" unsigned solRPdeIndex[3]; solRPdeIndex[0] = mlPdeSys->GetSolPdeIndex("X"); // get the position of "X" in the pdeSys object solRPdeIndex[1] = mlPdeSys->GetSolPdeIndex("Y"); // get the position of "Y" in the pdeSys object solRPdeIndex[2] = mlPdeSys->GetSolPdeIndex("Z"); // get the position of "Z" in the pdeSys object vector < adept::adouble > solR[3]; // local solution vector < double > solR_old[3]; unsigned solHIndex; solHIndex = mlSol->GetIndex("H"); // get the position of "H" in the ml_sol object unsigned solHType = mlSol->GetSolutionType(solHIndex); // get the finite element type for "H" unsigned solHPdeIndex; solHPdeIndex = mlPdeSys->GetSolPdeIndex("H"); // get the position of "H" in the pdeSys object vector < adept::adouble > solH; // local solution vector < vector < double > > x(dim); // local coordinates unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) vector< int > sysDof; // local to global pdeSys dofs vector <double> phi; // local test function vector <double> phi_x; // local test function first order partial derivatives vector <double> phi_xx; // local test function second order partial derivatives double weight; // gauss point weight vector< double > Res; // local redidual vector vector< adept::adouble > aResR[3]; // local redidual vector vector< adept::adouble > aResH; // local redidual vector // reserve memory for the local standar vectors const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 for(int i=0;i<3;i++){ solR[i].reserve(maxSize); solR_old[i].reserve(maxSize); } solH.reserve(maxSize); for (unsigned i = 0; i < dim; i++) x[i].reserve(maxSize); sysDof.reserve(4 * maxSize); phi.reserve(maxSize); phi_x.reserve(maxSize * dim); unsigned dim2 = (3 * (dim - 1) + !(dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) phi_xx.reserve(maxSize * dim2); Res.reserve(4 * maxSize); for(int i=0;i<3;i++){ aResR[i].reserve(maxSize); } aResH.reserve(maxSize); vector < double > Jac; // local Jacobian matrix (ordered by column, adept) Jac.reserve(4 * maxSize * 4 * maxSize); if (assembleMatrix) KK->zero(); // Set to zero all the entries of the Global Matrix // element loop: each process loops only on the elements that owns for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { short unsigned ielGeom = el->GetElementType(iel); // element geometry type unsigned nDofs = el->GetElementDofNumber(iel, solHType); // number of solution element dofs unsigned nDofs2 = el->GetElementDofNumber(iel, xType); // number of coordinate element dofs // resize local arrays sysDof.resize(4 * nDofs); for(int i = 0; i < 3; i++){ solR[i].resize(nDofs); solR_old[i].resize(nDofs); } solH.resize(nDofs); for (int i = 0; i < dim; i++) { x[i].resize(nDofs2); } Res.resize(4 * nDofs); //resize for(int i = 0; i < 3; i++){ aResR[i].resize(nDofs); //resize } aResH.resize(nDofs); //resize for(int i = 0; i < 3; i++){ std::fill(aResR[i].begin(), aResR[i].end(), 0); //set aRes to zero } std::fill(aResH.begin(), aResH.end(), 0); //set aRes to zero // local storage of global mapping and solution for (unsigned i = 0; i < nDofs; i++) { unsigned solDof = msh->GetSolutionDof(i, iel, solHType); // global to global mapping between solution node and solution dof for(int k = 0; k < 3; k++){ solR[k][i] = (*sol->_Sol[solRIndex[k]])(solDof); // global extraction and local storage for the solution solR_old[k][i] = (*sol->_SolOld[solRIndex[k]])(solDof); // global extraction and local storage for the solution } solH[i] = (*sol->_Sol[solHIndex])(solDof); // global extraction and local storage for the solution for(int k = 0; k < 3; k++){ sysDof[k*nDofs + i] = pdeSys->GetSystemDof(solRIndex[k], solRPdeIndex[k], i, iel); // global to global mapping between solution node and pdeSys dof } sysDof[3*nDofs + i] = pdeSys->GetSystemDof(solHIndex, solHPdeIndex, i, iel); // global to global mapping between solution node and pdeSys dof } // local storage of coordinates for (unsigned i = 0; i < nDofs2; i++) { unsigned xDof = msh->GetSolutionDof(i, iel, xType); // global to global mapping between coordinates node and coordinate dof for (unsigned idim = 0; idim < dim; idim++) { x[idim][i] = (*msh->_topology->_Sol[idim])(xDof); // global extraction and local storage for the element coordinates } } if (level == levelMax || !el->GetRefinedElementIndex(iel)) { // do not care about this if now (it is used for the AMR) // start a new recording of all the operations involving adept::adouble variables s.new_recording(); // *** Gauss point loop *** for (unsigned ig = 0; ig < msh->_finiteElement[ielGeom][solHType]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** msh->_finiteElement[ielGeom][solHType]->Jacobian(x, ig, weight, phi, phi_x, phi_xx); // evaluate the solution, the solution derivatives and the coordinates in the gauss point adept::adouble solRGauss[3]; double solRGaussOld[3]; adept::adouble solRGauss_x[3][2]; adept::adouble solRGauss_xx[3][2][2]; adept::adouble sol_x[2]; sol_x[0]=sol_x[1]=0.; for(int k=0; k<3; k++){ solRGauss[k]=0.; solRGaussOld[k]=0.; for(int i=0; i<dim; i++){ solRGauss_x[k][i]=0.; for(int j=0; j<dim; j++){ solRGauss_xx[k][i][j]=0.; } } } adept::adouble solHGauss = 0; adept::adouble solHGauss_x[2]={0.,0.}; for (unsigned i = 0; i < nDofs; i++) { for(int k = 0; k < 3; k++){ solRGauss[k] += phi[i] * solR[k][i]; solRGaussOld[k] += phi[i] * solR_old[k][i]; } solHGauss += phi[i] * solH[i]; for (unsigned u = 0; u < dim; u++) { sol_x[u] += phi[i] * x[u][i]; } for (unsigned u = 0; u < dim; u++) { // gradient for(int k=0; k < 3; k++){ solRGauss_x[k][u] += phi_x[i * dim + u] * solR[k][i]; } solHGauss_x[u] += phi_x[i * dim + u] * solH[i]; } for( unsigned u = 0; u < dim; u++ ) { // hessian for( unsigned v = 0; v < dim; v++ ) { unsigned uvindex = 0; //_uu if( u != v ) uvindex = 2; //_uv or _vu else if( u == 1 ) uvindex = 1; //_vv for(int k = 0; k < 3; k++){ solRGauss_xx[k][u][v] += phi_xx[i * dim2 + uvindex] * solR[k][i]; } } } } adept::adouble g[2][2]; g[0][0] = g[0][1] = g[1][0] = g[1][1] = 0.; for(int k = 0; k < 3; k++){ for(int u = 0; u < dim; u++){ for(int v = 0; v < dim; v++){ g[u][v] += solRGauss_x[k][u] * solRGauss_x[k][v]; } } } adept::adouble detg = g[0][0]*g[1][1]-g[0][1]*g[1][0]; adept::adouble A = sqrt(detg); adept::adouble gI[2][2]; gI[0][0] = g[1][1]/detg; gI[0][1] = -g[0][1]/detg; gI[1][0] = -g[1][0]/detg; gI[1][1] = g[0][0]/detg; adept::adouble N[3]; N[0] = ( solRGauss_x[1][0] * solRGauss_x[2][1] - solRGauss_x[1][1] * solRGauss_x[2][0] ) / A; N[1] = ( solRGauss_x[2][0] * solRGauss_x[0][1] - solRGauss_x[2][1] * solRGauss_x[0][0] ) / A; N[2] = ( solRGauss_x[0][0] * solRGauss_x[1][1] - solRGauss_x[0][1] * solRGauss_x[1][0] ) / A; adept::adouble h[2][2]; h[0][0]=h[0][1]=h[1][0]=h[1][1]=0.; for(int k=0; k<3; k++){ for(int u=0; u<dim; u++){ for(int v=0; v<dim; v++){ h[u][v] += solRGauss_xx[k][u][v] * N[k]; } } } //adept::adouble K = cos(sol_x[0])/(a+cos(sol_x[0]));//(h[0][0]*h[1][1]-h[0][1]*h[1][0])/detg; adept::adouble K = (h[0][0]*h[1][1]-h[0][1]*h[1][0])/detg; adept::adouble H_exact = 0.5*(1. + cos(sol_x[0])/(a+cos(sol_x[0]))); // *** phi_i loop *** for (unsigned i = 0; i < nDofs; i++) { for(int k=0; k<3; k++){ for(int u=0; u<dim; u++){ adept::adouble AgIgradRgradPhi=0; for(int v=0; v<dim; v++){ AgIgradRgradPhi += A * gI[u][v].value() * solRGauss_x[k][v]; } aResR[k][i] += AgIgradRgradPhi * phi_x[i * dim + u] * weight; } aResR[k][i] += 2.* A * solHGauss.value() * N[k] * phi[i] * weight; } for(int u=0; u<dim; u++){ adept::adouble AgIgradHgradPhi=0; for(int v=0; v<dim; v++){ AgIgradHgradPhi += A * gI[u][v].value() * solHGauss_x[v]; } aResH[i] -= AgIgradHgradPhi * phi_x[i * dim + u] * weight; } aResH[i] += A * ( -0*(solRGauss[0]-solRGaussOld[0])*N[0].value() -0*(solRGauss[1]-solRGaussOld[1])*N[1].value() -0*(solRGauss[2]-solRGaussOld[2])*N[2].value() + 2. * solHGauss * ( solHGauss * solHGauss - K.value() ) )* phi[i] * weight; } // end phi_i loop } // end gauss point loop } // endif single element not refined or fine grid loop //-------------------------------------------------------------------------------------------------------- // Add the local Matrix/Vector into the global Matrix/Vector //copy the value of the adept::adoube aRes in double Res and store for (int i = 0; i < nDofs; i++) { for( int k=0;k<3;k++){ Res[ k * nDofs + i] = -aResR[k][i].value(); } Res[ 3 * nDofs + i] = -aResH[i].value(); } RES->add_vector_blocked(Res, sysDof); if (assembleMatrix) { Jac.resize((4 * nDofs) *(4 * nDofs)); // define the dependent variables for( int k=0;k<3;k++){ s.dependent(&aResR[k][0], nDofs); } s.dependent(&aResH[0], nDofs); // define the independent variables for( int k=0;k<3;k++){ s.independent(&solR[k][0], nDofs); } s.independent(&solH[0], nDofs); // get the jacobian matrix (ordered by row) s.jacobian(&Jac[0], true); KK->add_matrix_blocked(Jac, sysDof, sysDof); s.clear_independents(); s.clear_dependents(); } } //end element loop for each process RES->close(); if (assembleMatrix) KK->close(); // ***************** END ASSEMBLY ******************* }