Example #1
0
  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();
  }  
Example #2
0
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;

}
Example #3
0
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);

}