void SetLambda(MultiLevelSolution &mlSol, const unsigned &level, const FEOrder &order, Operator operatorType){ unsigned SolType; if (order<FIRST || order> SECOND){ std::cout<<"Wong Solution Order"<<std::endl; exit(0); } else if ( order == FIRST ) SolType=0; else if ( order == SERENDIPITY ) SolType=1; else if ( order == SECOND) SolType=2; clock_t GetLambdaTime=0; clock_t start_time, end_time; start_time=clock(); adept::Stack & adeptStack = FemusInit::_adeptStack; Solution *mysolution = mlSol.GetSolutionLevel(level); Mesh *mymsh = mlSol._ml_msh->GetLevel(level); elem *myel = mymsh->el; unsigned indLmbd=mlSol.GetIndex("lmbd"); const unsigned geoDim = mymsh->GetDimension(); const unsigned nablaGoeDim = (3*(geoDim-1)+!(geoDim-1)); const unsigned max_size = static_cast< unsigned > (ceil(pow(3,geoDim))); bool diffusion, elasticity; if( operatorType == DIFFUSION ){ diffusion = true; elasticity = false; } if( operatorType == ELASTICITY ){ diffusion = false; elasticity = true; } else{ cout<<"wrong operator name in SetLambda\n" <<"valid options are diffusion or elasicity\n"; abort(); } unsigned varDim=geoDim*elasticity+diffusion; // local objects vector<vector<adept::adouble> > GradSolVAR(varDim); vector<vector<adept::adouble> > NablaSolVAR(varDim); for(int ivar=0;ivar<varDim;ivar++){ GradSolVAR[ivar].resize(geoDim); NablaSolVAR[ivar].resize(nablaGoeDim); } vector <double > phi; vector <adept::adouble> gradphi; vector <adept::adouble> nablaphi; adept::adouble Weight; phi.reserve(max_size); gradphi.reserve(max_size*geoDim); nablaphi.reserve(max_size*nablaGoeDim); vector <vector < adept::adouble> > vx(geoDim); for(int ivar=0;ivar<geoDim;ivar++){ vx[ivar].reserve(max_size); } unsigned SolTypeVx=2.; vector< vector< adept::adouble > > Soli(varDim); vector< vector< adept::adouble > > aRhs(varDim); vector< vector< adept::adouble > > aLhs(varDim); for(int ivar=0;ivar<varDim;ivar++){ Soli[ivar].reserve(max_size); aRhs[ivar].reserve(max_size); aLhs[ivar].reserve(max_size); } vector < double > K; K.reserve((max_size*varDim)*(max_size*varDim)); vector < double > M; M.reserve((max_size*varDim)*(max_size*varDim)); // mesh and procs unsigned nel = mymsh->GetNumberOfElements(); unsigned iproc = mymsh->processor_id(); // *** element loop *** for(int iel=mymsh->IS_Mts2Gmt_elem_offset[iproc]; iel < mymsh->IS_Mts2Gmt_elem_offset[iproc+1]; iel++) { unsigned kel = mymsh->IS_Mts2Gmt_elem[iel]; short unsigned kelt = myel->GetElementType(kel); unsigned nve = myel->GetElementDofNumber(kel,SolType)-1; unsigned nveVx = myel->GetElementDofNumber(kel,SolTypeVx); // -------------- resize -------------- for(int ivar=0; ivar<varDim; ivar++) { Soli[ivar].resize(nve); aRhs[ivar].resize(nve); aLhs[ivar].resize(nve); } M.resize((varDim*nve)*(varDim*nve)); K.resize((varDim*nve)*(varDim*nve)); // ------------------------------------ // ------------ get coordinates ------- for(int i=0;i<geoDim;i++){ vx[i].resize(nveVx); } for (unsigned i=0;i<nveVx;i++) { unsigned inode=myel->GetMeshDof(kel,i,SolTypeVx); unsigned inodeVx_Metis=mymsh->GetMetisDof(inode,SolTypeVx); for(int j=0; j<geoDim; j++) { //coordinates vx[j][i]= (*mymsh->_coordinate->_Sol[j])(inodeVx_Metis); } } // ------------------------------------ // ------------ init ------------------ for (unsigned i=0;i<nve;i++) { for(int ivar=0; ivar<varDim; ivar++) { Soli[ivar][i] = 1.; aRhs[ivar][i] = 0.; aLhs[ivar][i] = 0.; } } // ------------------------------------ adeptStack.new_recording(); double hk=1.; for (unsigned ig=0;ig < mymsh->_finiteElement[kelt][SolType]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives in the moving frame*** mymsh->_finiteElement[kelt][SolType]->Jacobian(vx,ig,Weight,phi,gradphi,nablaphi); if(ig==0){ double referenceElementScale[6]={8., 1./6., 1., 4., 1., 2.}; double GaussWeight = mymsh->_finiteElement[kelt][SolType]->GetGaussWeight(ig); double area=referenceElementScale[kelt]*Weight.value()/GaussWeight; hk = pow(area,1./geoDim); //cout<<hk<<endl; if(0 == SolType) break; } for(int ivar=0; ivar<varDim; ivar++){ for(int jvar=0; jvar<geoDim; jvar++) { GradSolVAR[ivar][jvar]=0.; } for(int jvar=0; jvar<nablaGoeDim; jvar++) { NablaSolVAR[ivar][jvar]=0.; } for (unsigned inode=0; inode<nve; inode++) { adept::adouble soli = Soli[ivar][inode]; for(int jvar=0; jvar<geoDim; jvar++) { GradSolVAR[ivar][jvar] += gradphi[inode*geoDim+jvar]*soli; } for(int jvar=0; jvar<nablaGoeDim; jvar++) { NablaSolVAR[ivar][jvar]+=nablaphi[inode*nablaGoeDim+jvar]*soli; } } } vector < adept::adouble > divGradSol(varDim,0.); for(unsigned ivar=0; ivar<varDim; ivar++) { for(unsigned jvar=0; jvar<geoDim; jvar++) { if(diffusion){ divGradSol[ivar] += NablaSolVAR[ivar][jvar]; } else if(elasticity){ unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = geoDim; // xy else if (2 == ivar + jvar ) kvar = geoDim+2; // xz else if (3 == ivar + jvar ) kvar = geoDim+1; // yz divGradSol[ivar] += 0.5*( NablaSolVAR[ivar][jvar] + NablaSolVAR[jvar][kvar]); } } } //BEGIN local assembly for (unsigned i=0; i<nve; i++){ for(unsigned ivar=0; ivar<varDim; ivar++) { for(unsigned jvar=0; jvar<geoDim; jvar++) { aRhs[ivar][i] += gradphi[i*geoDim+jvar]*(GradSolVAR[ivar][jvar]) * Weight; if(diffusion){ aLhs[ivar][i] += divGradSol[ivar] * nablaphi[i*nablaGoeDim+jvar] * Weight; //aRhs[ivar][i] += gradphi[i*geoDim+jvar]*(GradSolVAR[ivar][jvar]) * Weight; } else if(elasticity){ unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = geoDim; // xy else if (2 == ivar + jvar ) kvar = geoDim+2; // xz else if (3 == ivar + jvar ) kvar = geoDim+1; // yz aLhs[ivar][i] += divGradSol[ivar] * 0.5 * nablaphi[i*nablaGoeDim+jvar] * Weight; aLhs[jvar][i] += divGradSol[ivar] * 0.5 * nablaphi[i*nablaGoeDim+kvar] * Weight; //aRhs[ivar][i] += 0.5*gradphi[i*geoDim+jvar]*0.5*(GradSolVAR[ivar][jvar]+GradSolVAR[jvar][ivar]) * Weight; //aRhs[jvar][i] += 0.5*gradphi[i*geoDim+ivar]*0.5*(GradSolVAR[ivar][jvar]+GradSolVAR[jvar][ivar]) * Weight; } } } } //END local assembly } cout<<hk<<endl; double lambdak = 6./(hk*hk); //if SolType is linear if( SolType == 1 || SolType == 2){ // only if solType is quadratic or biquadratic for(int ivar=0; ivar<varDim; ivar++) { adeptStack.independent(&Soli[ivar][0], nve); } //Store RHS in M for(int ivar=0; ivar<varDim; ivar++) { adeptStack.dependent(&aRhs[ivar][0], nve); } adeptStack.jacobian(&M[0]); adeptStack.clear_dependents(); //Store LHS in K for(int ivar=0; ivar<varDim; ivar++) { adeptStack.dependent(&aLhs[ivar][0], nve); } adeptStack.jacobian(&K[0]); adeptStack.clear_dependents(); adeptStack.clear_independents(); unsigned matSize = nve*varDim; int remove[6][3]={{},{},{},{0,1,2},{0,2,2},{}}; unsigned indSize = matSize;// - remove[kelt][SolType]*elasticity; // for(int i=0;i<indSize;i++){ // for(int j=0;j<indSize;j++){ // cout<<K[matSize*i+j]<<" "; // } // cout<<endl; // } // cout<<endl; // for(int i=0;i<indSize;i++){ // for(int j=0;j<indSize;j++){ // cout<<M[matSize*i+j]<<" "; // } // cout<<endl; // } // LU = M factorization for (int k = 0 ; k < indSize-1 ; k++) { for ( int i = k+1 ; i < indSize ; i++) { M[i*matSize+k] /= M[k*matSize+k]; for ( int j= k+1 ; j < indSize ; j++) { M[i*matSize+j] -= M[i*matSize+k]*M[k*matSize+j] ; } } } // Power Method for the largest eigenvalue of K x = lambda LU x : // iteration step: // y = U^(-1) L^(-1) K x // lambda= phi(y)/phi(x) // y = y / l2norm(y) // x = y vector < double > x(matSize,1.); vector < double > y(matSize); double phik = x[0]+x[1]; lambdak=1.; double error=1.; while(error>1.0e-10 && counter <= 500){ double phikm1 = phik; double lambdakm1 = lambdak; // y = K x for(int i=0; i<indSize; i++){ y[i]=0.; for(int j=0; j<indSize; j++){ y[i] += K[ i*matSize + j ] * x[j]; } } // y = L^(-1) y for(int i=0; i<indSize; i++){ for(int j=0; j<i; j++){ y[i] -= M[i*matSize + j] * y[j]; } } // x <-- y = U^(-1) y double l2norm=0.; for(int i = indSize-1; i>=0; i--){ x[i] = y[i]; for(int j = i+1; j<indSize; j++){ x[i] -= M[ i*matSize + j] * x[j]; } x[i] /= M[i*matSize+i]; l2norm += x[i]*x[i]; } l2norm = sqrt(l2norm); phik = (x[0]+x[1]); lambdak= phik / phikm1; for(int i=0;i<indSize;i++){ x[i] /= l2norm; } phik /= l2norm; error = fabs( (lambdak-lambdakm1)/lambdak ); } } cout<<lambdak*hk*hk<<std::endl; mysolution->_Sol[indLmbd]->set(iel,sqrt(lambdak)); //abort(); } //end list of elements loop mysolution->_Sol[indLmbd]->close(); // ************************************* end_time=clock(); GetLambdaTime+=(end_time-start_time); std::cout<<"GetLambda Time = "<<GetLambdaTime/CLOCKS_PER_SEC <<std::endl; //abort(); }
void GetSolutionNorm(MultiLevelSolution& mlSol, const unsigned & group, std::vector <double> &data) { int iproc, nprocs; MPI_Comm_rank(MPI_COMM_WORLD, &iproc); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); NumericVector* p2; NumericVector* v2; NumericVector* vol; NumericVector* vol0; p2 = NumericVector::build().release(); v2 = NumericVector::build().release(); vol = NumericVector::build().release(); vol0 = NumericVector::build().release(); if(nprocs == 1) { p2->init(nprocs, 1, false, SERIAL); v2->init(nprocs, 1, false, SERIAL); vol->init(nprocs, 1, false, SERIAL); vol0->init(nprocs, 1, false, SERIAL); } else { p2->init(nprocs, 1, false, PARALLEL); v2->init(nprocs, 1, false, PARALLEL); vol->init(nprocs, 1, false, PARALLEL); vol0->init(nprocs, 1, false, PARALLEL); } p2->zero(); v2->zero(); vol->zero(); vol0->zero(); unsigned level = mlSol._mlMesh->GetNumberOfLevels() - 1; Solution* solution = mlSol.GetSolutionLevel(level); Mesh* msh = mlSol._mlMesh->GetLevel(level); const unsigned dim = msh->GetDimension(); const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim))); vector< double > solP; vector< vector < double> > solV(dim); vector< vector < double> > x0(dim); vector< vector < double> > x(dim); solP.reserve(max_size); for(unsigned d = 0; d < dim; d++) { solV[d].reserve(max_size); x0[d].reserve(max_size); x[d].reserve(max_size); } double weight; double weight0; vector <double> phiV; vector <double> gradphiV; vector <double> nablaphiV; double *phiP; phiV.reserve(max_size); gradphiV.reserve(max_size * dim); nablaphiV.reserve(max_size * (3 * (dim - 1) + !(dim - 1))); 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" vector < unsigned > solDIndex(dim); solDIndex[0] = mlSol.GetIndex("DX"); // get the position of "U" in the ml_sol object solDIndex[1] = mlSol.GetIndex("DY"); // get the position of "V" in the ml_sol object if(dim == 3) solDIndex[2] = mlSol.GetIndex("DZ"); // get the position of "V" in the ml_sol object unsigned solDType = mlSol.GetSolutionType(solDIndex[0]); unsigned solPIndex; solPIndex = mlSol.GetIndex("PS"); unsigned solPType = mlSol.GetSolutionType(solPIndex); for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { if(msh->GetElementGroup(iel) == group) { short unsigned ielt = msh->GetElementType(iel); unsigned ndofV = msh->GetElementDofNumber(iel, solVType); unsigned ndofP = msh->GetElementDofNumber(iel, solPType); unsigned ndofD = msh->GetElementDofNumber(iel, solDType); // resize phiV.resize(ndofV); gradphiV.resize(ndofV * dim); nablaphiV.resize(ndofV * (3 * (dim - 1) + !(dim - 1))); solP.resize(ndofP); for(int d = 0; d < dim; d++) { solV[d].resize(ndofV); x0[d].resize(ndofD); x[d].resize(ndofD); } // get local to global mappings for(unsigned i = 0; i < ndofD; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solDType); for(unsigned d = 0; d < dim; d++) { x0[d][i] = (*msh->_topology->_Sol[d])(idof); x[d][i] = (*msh->_topology->_Sol[d])(idof) + (*solution->_Sol[solDIndex[d]])(idof); } } for(unsigned i = 0; i < ndofV; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solVType); // global to global mapping between solution node and solution dof for(unsigned d = 0; d < dim; d++) { solV[d][i] = (*solution->_Sol[solVIndex[d]])(idof); // global extraction and local storage for the solution } } for(unsigned i = 0; i < ndofP; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solPType); solP[i] = (*solution->_Sol[solPIndex])(idof); } for(unsigned ig = 0; ig < mlSol._mlMesh->_finiteElement[ielt][solVType]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives *** msh->_finiteElement[ielt][solVType]->Jacobian(x0, ig, weight0, phiV, gradphiV, nablaphiV); msh->_finiteElement[ielt][solVType]->Jacobian(x, ig, weight, phiV, gradphiV, nablaphiV); phiP = msh->_finiteElement[ielt][solPType]->GetPhi(ig); vol0->add(iproc, weight0); vol->add(iproc, weight); std::vector < double> SolV2(dim, 0.); for(unsigned i = 0; i < ndofV; i++) { for(unsigned d = 0; d < dim; d++) { SolV2[d] += solV[d][i] * phiV[i]; } } double V2 = 0.; for(unsigned d = 0; d < dim; d++) { V2 += SolV2[d] * SolV2[d]; } v2->add(iproc, V2 * weight); double P2 = 0; for(unsigned i = 0; i < ndofP; i++) { P2 += solP[i] * phiP[i]; } P2 *= P2; p2->add(iproc, P2 * weight); } } } p2->close(); v2->close(); vol0->close(); vol->close(); double p2_l2 = p2->l1_norm(); double v2_l2 = v2->l1_norm(); double VOL0 = vol0->l1_norm(); double VOL = vol->l1_norm(); std::cout.precision(14); std::scientific; std::cout << " vol0 = " << VOL0 << std::endl; std::cout << " vol = " << VOL << std::endl; std::cout << " (vol-vol0)/vol0 = " << (VOL - VOL0) / VOL0 << std::endl; std::cout << " p_l2 norm / vol = " << sqrt(p2_l2 / VOL) << std::endl; std::cout << " v_l2 norm / vol = " << sqrt(v2_l2 / VOL) << std::endl; data[1] = (VOL - VOL0) / VOL0; data[2] = VOL; data[3] = sqrt(p2_l2 / VOL); data[4] = sqrt(v2_l2 / VOL); delete p2; delete v2; delete vol; }
double GetRelativeError(MultiLevelSolution& ml_sol, const bool& H1) { int iproc, nprocs; MPI_Comm_rank(MPI_COMM_WORLD, &iproc); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); NumericVector* error_vec; NumericVector* solution_vec; error_vec = NumericVector::build().release(); solution_vec = NumericVector::build().release(); if (nprocs == 1) { error_vec->init(nprocs, 1, false, SERIAL); solution_vec->init(nprocs, 1, false, SERIAL); } else { error_vec->init(nprocs, 1, false, PARALLEL); solution_vec->init(nprocs, 1, false, PARALLEL); } error_vec->zero(); solution_vec->zero(); unsigned gridn = ml_sol._mlMesh->GetNumberOfLevels(); for (int ilevel = gridn - 1; ilevel < gridn; ilevel++) { Solution* solution = ml_sol.GetSolutionLevel(ilevel); Mesh* msh = ml_sol._mlMesh->GetLevel(ilevel); unsigned iproc = msh->processor_id(); const unsigned dim = msh->GetDimension(); vector< vector < double> > coordinates(dim); vector< int > metis_node; vector <double> phi; vector <double> gradphi; vector <double> nablaphi; double weight; // reserve const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim))); metis_node.reserve(max_size); for (int i = 0; i < dim; i++) coordinates[i].reserve(max_size); phi.reserve(max_size); gradphi.reserve(max_size * dim); nablaphi.reserve(max_size * (3 * (dim - 1) + !(dim - 1))); unsigned SolIndex; SolIndex = ml_sol.GetIndex("Sol"); unsigned SolOrder = ml_sol.GetSolutionType(SolIndex); for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { if (ilevel == gridn - 1 || !msh->el->GetRefinedElementIndex(iel)) { short unsigned ielt = msh->el->GetElementType(iel); unsigned nve = msh->el->GetElementDofNumber(iel, SolOrder); // resize metis_node.resize(nve); phi.resize(nve); gradphi.resize(nve * dim); nablaphi.resize(nve * (3 * (dim - 1) + !(dim - 1))); for (int i = 0; i < dim; i++) { coordinates[i].resize(nve); } // get local to global mappings for (unsigned i = 0; i < nve; i++) { unsigned inode_coord_metis = msh->GetSolutionDof(i, iel, 2); metis_node[i] = msh->GetSolutionDof(i, iel, SolOrder); for (unsigned idim = 0; idim < dim; idim++) { coordinates[idim][i] = (*msh->_topology->_Sol[idim])(inode_coord_metis); } } for (unsigned ig = 0; ig < ml_sol._mlMesh->_finiteElement[ielt][SolOrder]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives *** ml_sol._mlMesh->_finiteElement[ielt][SolOrder]->Jacobian(coordinates, ig, weight, phi, gradphi, nablaphi); //current solution double SolT = 0; vector < double > gradSolT(dim, 0.); for (unsigned ivar = 0; ivar < dim; ivar++) { gradSolT[ivar] = 0; } double pi = acos(-1.); double x[4] = {0., 0., 0., 0.}; unsigned SolType = ml_sol.GetSolutionType("Sol"); for (unsigned i = 0; i < nve; i++) { double soli = (*solution->_Sol[SolIndex])(metis_node[i]); for (unsigned ivar = 0; ivar < dim; ivar++) { x[ivar] += coordinates[ivar][i] * phi[i]; } SolT += phi[i] * soli; for (unsigned ivar2 = 0; ivar2 < dim; ivar2++) { gradSolT[ivar2] += gradphi[i * dim + ivar2] * soli; } } double SolExact, dSolExactdx, dSolExactdy; #ifdef HAVE_FPARSER SolExact = fp_sol(x); dSolExactdx = fp_dsoldx(x); dSolExactdy = fp_dsoldy(x); #endif error_vec->add(iproc, ((SolT - SolExact) * (SolT - SolExact) + H1 * ((gradSolT[0] - dSolExactdx) * (gradSolT[0] - dSolExactdx) + (gradSolT[1] - dSolExactdy) * (gradSolT[1] - dSolExactdy)) )*weight); solution_vec->add(iproc, (SolExact * SolExact + H1 * (dSolExactdx * dSolExactdx + dSolExactdy * dSolExactdy))*weight); } } } } error_vec->close(); solution_vec->close(); double l2_error = error_vec->l1_norm(); double l2_solution = solution_vec->l1_norm(); delete error_vec; delete solution_vec; return sqrt(l2_error / l2_solution); }