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
File: ex2.cpp Project: FeMTTU/femus
int main (int argc, char** args) {

  // init Petsc-MPI communicator
  FemusInit mpinit (argc, args, MPI_COMM_WORLD);

  // define multilevel mesh
  MultiLevelMesh mlMsh;
  // read coarse level mesh and generate finers level meshes
  double scalingFactor = 1.;
  //mlMsh.ReadCoarseMesh("./input/cube_hex.neu","seventh",scalingFactor);
  //mlMsh.ReadCoarseMesh("./input/square_quad.neu", "seventh", scalingFactor);
  mlMsh.ReadCoarseMesh ("./input/quadAMR.neu", "seventh", scalingFactor);
  /* "seventh" is the order of accuracy that is used in the gauss integration scheme
     probably in the furure it is not going to be an argument of this function   */
  unsigned dim = mlMsh.GetDimension();

//   unsigned numberOfUniformLevels = 3;
//   unsigned numberOfSelectiveLevels = 0;
//   mlMsh.RefineMesh(numberOfUniformLevels , numberOfUniformLevels + numberOfSelectiveLevels, NULL);

  unsigned numberOfUniformLevels = 4;
  unsigned numberOfSelectiveLevels = 3;
  mlMsh.RefineMesh (numberOfUniformLevels + numberOfSelectiveLevels, numberOfUniformLevels , SetRefinementFlag);

  // erase all the coarse mesh levels
  //mlMsh.EraseCoarseLevels(numberOfUniformLevels - 3);

  // print mesh info
  mlMsh.PrintInfo();

  MultiLevelSolution mlSol (&mlMsh);

  // add variables to mlSol


  mlSol.AddSolution ("U", LAGRANGE, SERENDIPITY);
  mlSol.AddSolution ("V", LAGRANGE, SECOND);


  mlSol.Initialize ("All");

  // attach the boundary condition function and generate boundary data
  mlSol.AttachSetBoundaryConditionFunction (SetBoundaryCondition);

  mlSol.GenerateBdc ("All");

  // define the multilevel problem attach the mlSol object to it
  MultiLevelProblem mlProb (&mlSol);

  // add system Poisson in mlProb as a Linear Implicit System
  NonLinearImplicitSystem& system = mlProb.add_system < NonLinearImplicitSystem > ("Poisson");

  // add solution "u" to system
  system.AddSolutionToSystemPDE ("U");
  system.AddSolutionToSystemPDE ("V");

  //system.SetLinearEquationSolverType(FEMuS_DEFAULT);
  system.SetLinearEquationSolverType (FEMuS_ASM); // Additive Swartz Method
  // attach the assembling function to system
  system.SetAssembleFunction (AssemblePoisson_AD);


  system.SetMaxNumberOfNonLinearIterations(10);
  system.SetMaxNumberOfLinearIterations(3);
  system.SetAbsoluteLinearConvergenceTolerance(1.e-12);
  system.SetNonLinearConvergenceTolerance(1.e-8);
  system.SetMgType(F_CYCLE); // Q1 What's F cycle

  system.SetNumberPreSmoothingStep (0);
  system.SetNumberPostSmoothingStep (2);
  // initilaize and solve the system
  system.init();

  system.SetSolverFineGrids (GMRES);
  system.SetPreconditionerFineGrids (ILU_PRECOND);
  system.SetTolerances (1.e-3, 1.e-20, 1.e+50, 5);

  system.SetNumberOfSchurVariables (1);
  system.SetElementBlockNumber (4);
  //system.SetDirichletBCsHandling(ELIMINATION);
  //system.solve();
  system.MGsolve();

  // print solutions
  std::vector < std::string > variablesToBePrinted;
  variablesToBePrinted.push_back ("All");

  VTKWriter vtkIO (&mlSol);
  vtkIO.Write (DEFAULT_OUTPUTDIR, "biquadratic", variablesToBePrinted);

  GMVWriter gmvIO (&mlSol);
  variablesToBePrinted.push_back ("all");
  gmvIO.SetDebugOutput (true);
  gmvIO.Write (DEFAULT_OUTPUTDIR, "biquadratic", variablesToBePrinted);


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

  // call the adept stack object
  adept::Stack& s = FemusInit::_adeptStack;

  //  extract pointers to the several objects that we are going to use
  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system<NonLinearImplicitSystem> ("NS");   // 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 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
  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"

  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 < vector < adept::adouble > >  solV(dim);    // local solution
  vector < adept::adouble >  solP; // local solution

  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)

  for (unsigned  k = 0; k < dim; k++) {
    solV[k].reserve(maxSize);
    aResV[k].reserve(maxSize);
    coordX[k].reserve(maxSize);
  }

  solP.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);

  double* phiP;
  double weight; // gauss point weight

  vector< int > KKDof; // local to global pdeSys dofs
  KKDof.reserve((dim + 1) *maxSize);

  vector< double > Res; // local redidual vector
  Res.reserve((dim + 1) *maxSize);

  vector < double > Jac;
  Jac.reserve((dim + 1) *maxSize * (dim + 1) *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->IS_Mts2Gmt_elem_offset[iproc]; iel < msh->IS_Mts2Gmt_elem_offset[iproc + 1]; iel++) {

    unsigned kel = msh->IS_Mts2Gmt_elem[iel]; // mapping between paralell dof and mesh dof
    short unsigned kelGeom = el->GetElementType(kel);    // element geometry type

    unsigned nDofsV = el->GetElementDofNumber(kel, solVType);    // number of solution element dofs
    unsigned nDofsP = el->GetElementDofNumber(kel, solPType);    // number of solution element dofs
    unsigned nDofsX = el->GetElementDofNumber(kel, coordXType);    // number of coordinate element dofs

    unsigned nDofsVP = dim * nDofsV + nDofsP;
    // resize local arrays
    KKDof.resize(nDofsVP);

    for (unsigned  k = 0; k < dim; k++) {
      solV[k].resize(nDofsV);
      coordX[k].resize(nDofsX);
    }

    solP.resize(nDofsP);

    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 < nDofsV; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, solVType);    // local to global solution node
      unsigned solVDof = msh->GetMetisDof(iNode, 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
        KKDof[i + k * nDofsV] = pdeSys->GetKKDof(solVIndex[k], solVPdeIndex[k], iNode);    // global to global mapping between solution node and pdeSys dof
      }
    }

    for (unsigned i = 0; i < nDofsP; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, solPType);    // local to global solution node
      unsigned solPDof = msh->GetMetisDof(iNode, 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
      KKDof[i + dim * nDofsV] = pdeSys->GetKKDof(solPIndex, solPPdeIndex, iNode);    // global to global mapping between solution node and pdeSys dof
    }

    // local storage of coordinates
    for (unsigned i = 0; i < nDofsX; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, coordXType);    // local to global coordinates node
      unsigned coordXDof  = msh->GetMetisDof(iNode, coordXType);    // global to global mapping between coordinates node and coordinate dof

      for (unsigned k = 0; k < dim; k++) {
        coordX[k][i] = (*msh->_coordinate->_Sol[k])(coordXDof);      // global extraction and local storage for the element coordinates
      }
    }

    if (level == levelMax || !el->GetRefinedElementIndex(kel)) {      // 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[kelGeom][solVType]->GetGaussPointNumber(); ig++) {
        // *** get gauss point weight, test function and test function partial derivatives ***
        msh->_finiteElement[kelGeom][solVType]->Jacobian(coordX, ig, weight, phiV, phiV_x, phiV_xx);
        phiP = msh->_finiteElement[kelGeom][solPType]->GetPhi(ig);

        vector < adept::adouble > solV_gss(dim, 0);
        vector < vector < adept::adouble > > gradSolV_gss(dim);

        for (unsigned  k = 0; k < dim; k++) {
          gradSolV_gss[k].resize(dim);
          std::fill(gradSolV_gss[k].begin(), gradSolV_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];
          }

          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];
            }
          }
        }

        adept::adouble solP_gss = 0;

        for (unsigned i = 0; i < nDofsP; i++) {
          solP_gss += phiP[i] * solP[i];
        }

        double nu = 1.;

        // *** phiV_i loop ***
        for (unsigned i = 0; i < nDofsV; i++) {
          vector < adept::adouble > NSV(dim, 0.);

          for (unsigned j = 0; j < dim; j++) {
            for (unsigned  k = 0; k < dim; k++) {
              NSV[k]   +=  nu * phiV_x[i * dim + j] * (gradSolV_gss[k][j] + gradSolV_gss[j][k]);
              NSV[k]   +=  phiV[i] * (solV_gss[j] * gradSolV_gss[k][j]);
            }
          }

          for (unsigned  k = 0; k < dim; k++) {
            NSV[k] += -solP_gss * phiV_x[i * dim + k];
          }

          for (unsigned  k = 0; k < dim; k++) {
            aResV[k][i] += - NSV[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
    } // 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 them in RES
    Res.resize(nDofsVP);    //resize

    for (int i = 0; i < nDofsV; i++) {
      for (unsigned  k = 0; k < dim; k++) {
        Res[ i +  k * nDofsV ] = -aResV[k][i].value();
      }
    }

    for (int i = 0; i < nDofsP; i++) {
      Res[ i + dim * nDofsV ] = -aResP[i].value();
    }

    RES->add_vector_blocked(Res, KKDof);

    //Extarct and store the Jacobian
    if (assembleMatrix) {
      Jac.resize(nDofsVP * nDofsVP);
      // define the dependent variables

      for (unsigned  k = 0; k < dim; k++) {
        s.dependent(&aResV[k][0], nDofsV);
      }

      s.dependent(&aResP[0], nDofsP);

      // define the independent variables
      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, KKDof, KKDof);

      s.clear_independents();
      s.clear_dependents();
    }
  } //end element loop for each process

  RES->close();

  if (assembleMatrix) KK->close();

  // ***************** END ASSEMBLY *******************
}
Example #4
0
File: ex4.cpp Project: FeMTTU/femus
void ETD(MultiLevelProblem& ml_prob)
{

  const unsigned& NLayers = NumberOfLayers;

  adept::Stack& s = FemusInit::_adeptStack;

  LinearImplicitSystem* mlPdeSys  = &ml_prob.get_system<LinearImplicitSystem> ("SW");   // pointer to the linear implicit system named "Poisson"

  unsigned level = ml_prob._ml_msh->GetNumberOfLevels() - 1u;

  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)
  NumericVector* EPS = pdeSys->_EPS; // 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)
  unsigned    nprocs = msh->n_processors(); // get the process_id (for parallel computation)


  //solution variable
  std::vector < unsigned > solIndexh(NLayers);
  std::vector < unsigned > solPdeIndexh(NLayers);

  std::vector < unsigned > solIndexv(NLayers);
  std::vector < unsigned > solPdeIndexv(NLayers);
  
  std::vector < unsigned > solIndexHT(NLayers);
  std::vector < unsigned > solPdeIndexHT(NLayers);
  
  
   std::vector < unsigned > solIndexT(NLayers);

  vector< int > l2GMap; // local to global mapping
  
  for(unsigned i = 0; i < NLayers; i++) {
    char name[10];
    sprintf(name, "h%d", i);
    solIndexh[i] = mlSol->GetIndex(name); // get the position of "hi" in the sol object
    solPdeIndexh[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "hi" in the pdeSys object

    sprintf(name, "v%d", i);
    solIndexv[i] = mlSol->GetIndex(name); // get the position of "vi" in the sol object
    solPdeIndexv[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "vi" in the pdeSys object
    
    sprintf(name, "HT%d", i);
    solIndexHT[i] = mlSol->GetIndex(name); // get the position of "Ti" in the sol object
    solPdeIndexHT[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "Ti" in the pdeSys object
    
    sprintf(name, "T%d", i);
    solIndexT[i] = mlSol->GetIndex(name); // get the position of "Ti" in the sol object
    
  }

  unsigned solTypeh = mlSol->GetSolutionType(solIndexh[0]);    // get the finite element type for "hi"
  unsigned solTypev = mlSol->GetSolutionType(solIndexv[0]);    // get the finite element type for "vi"
  unsigned solTypeHT = mlSol->GetSolutionType(solIndexHT[0]);    // get the finite element type for "Ti"
  
  vector < double > x;    // local coordinates
  vector< vector < adept::adouble > > solh(NLayers);    // local coordinates
  vector< vector < adept::adouble > > solv(NLayers);    // local coordinates
  vector< vector < adept::adouble > > solHT(NLayers);    // local coordinates
  vector< vector < double > > solT(NLayers);    // local coordinates
  
  vector< vector < bool > > bdch(NLayers);    // local coordinates
  vector< vector < bool > > bdcv(NLayers);    // local coordinates
  vector< vector < bool > > bdcHT(NLayers);    // local coordinates
  
  unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC)

  vector < vector< adept::adouble > > aResh(NLayers);
  vector < vector< adept::adouble > > aResv(NLayers);
  vector < vector< adept::adouble > > aResHT(NLayers);
  
  KK->zero();
  RES->zero();

  double maxWaveSpeed = 0.;
  
  double dx;
  
  for(unsigned k=0; k<NumberOfLayers; k++){
    for(unsigned i =  msh->_dofOffset[solTypeHT][iproc]; i <  msh->_dofOffset[solTypeHT][iproc + 1]; i++){
      double valueT = (*sol->_Sol[solIndexT[k]])(i);
      double valueH = (*sol->_Sol[solIndexh[k]])(i);
            
      double valueHT = valueT * valueH;
    
      sol->_Sol[solIndexHT[k]]->set(i, valueHT);
    }
    sol->_Sol[solIndexHT[k]]->close();
  }
    
  for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) {

    short unsigned ielGeom = msh->GetElementType(iel);
    unsigned nDofh  = msh->GetElementDofNumber(iel, solTypeh);    // number of solution element dofs
    unsigned nDofv  = msh->GetElementDofNumber(iel, solTypev);    // number of solution element dofs
    unsigned nDofHT = msh->GetElementDofNumber(iel, solTypeHT);     // number of coordinate element dofs
    unsigned nDofx = msh->GetElementDofNumber(iel, xType);        // number of coordinate element dofs

    unsigned nDofs = nDofh + nDofv + nDofHT;

    // resize local arrays
    l2GMap.resize(NLayers * (nDofs) );

    for(unsigned i = 0; i < NLayers; i++) {
      solh[i].resize(nDofh);
      solv[i].resize(nDofv);
      solHT[i].resize(nDofHT);
      solT[i].resize(nDofHT);
      bdch[i].resize(nDofh);
      bdcv[i].resize(nDofv);
      bdcHT[i].resize(nDofHT);
      aResh[i].resize(nDofh);    //resize
      std::fill(aResh[i].begin(), aResh[i].end(), 0);    //set aRes to zero
      aResv[i].resize(nDofv);    //resize
      std::fill(aResv[i].begin(), aResv[i].end(), 0);    //set aRes to zero
      aResHT[i].resize(nDofHT);    //resize
      std::fill(aResHT[i].begin(), aResHT[i].end(), 0);    //set aRes to zero
    }
    x.resize(nDofx);

    //local storage of global mapping and solution
    for(unsigned i = 0; i < nDofh; i++) {
      unsigned solDofh = msh->GetSolutionDof(i, iel, solTypeh);    // global to global mapping between solution node and solution dof
      for(unsigned j = 0; j < NLayers; j++) {
        solh[j][i] = (*sol->_Sol[solIndexh[j]])(solDofh);      // global extraction and local storage for the solution
        bdch[j][i] = ( (*sol->_Bdc[solIndexh[j]])(solDofh) < 1.5) ? true : false;
        l2GMap[ j * nDofs + i] = pdeSys->GetSystemDof(solIndexh[j], solPdeIndexh[j], i, iel);    // global to global mapping between solution node and pdeSys dof
      }
    }
    for(unsigned i = 0; i < nDofv; i++) {
      unsigned solDofv = msh->GetSolutionDof(i, iel, solTypev);    // global to global mapping between solution node and solution dof
      for(unsigned j = 0; j < NLayers; j++) {
        solv[j][i] = (*sol->_Sol[solIndexv[j]])(solDofv);      // global extraction and local storage for the solution
        bdcv[j][i] = ( (*sol->_Bdc[solIndexv[j]])(solDofv) < 1.5) ? true : false;
        l2GMap[ j * nDofs + nDofh + i] = pdeSys->GetSystemDof(solIndexv[j], solPdeIndexv[j], i, iel);    // global to global mapping between solution node and pdeSys dof
      }
    }
    for(unsigned i = 0; i < nDofHT; i++) {
      unsigned solDofHT = msh->GetSolutionDof(i, iel, solTypeHT);    // global to global mapping between solution node and solution dof
      unsigned solDofh = msh->GetSolutionDof(i, iel, solTypeh);
      for(unsigned j = 0; j < NLayers; j++) {
        solHT[j][i] = (*sol->_Sol[solIndexHT[j]])(solDofHT);   // global extraction and local storage for the solution
	solT[j][i] = (*sol->_Sol[solIndexT[j]])(solDofHT);   // global extraction and local storage for the solution
        bdcHT[j][i] = ( (*sol->_Bdc[solIndexHT[j]])(solDofHT) < 1.5) ? true : false;
        l2GMap[ j * nDofs + nDofh + nDofv + i] = pdeSys->GetSystemDof(solIndexHT[j], solPdeIndexHT[j], i, iel);    // global to global mapping between solution node and pdeSys dof
	//std::cout << solT[j][i] << " ";
      }
    }

    s.new_recording();
    
    for(unsigned i = 0; i < nDofx; i++) {
      unsigned xDof  = msh->GetSolutionDof(i, iel, xType);    // global to global mapping between coordinates node and coordinate dof
      x[i] = (*msh->_topology->_Sol[0])(xDof);      // global extraction and local storage for the element coordinates
    }
    

    double xmid = 0.5 * (x[0] + x[1]);
    //std::cout << xmid << std::endl;
    double zz = sqrt(aa * aa - xmid * xmid); // z coordinate of points on sphere
    double dd = aa * acos((zz * z_c) / (aa * aa)); // distance to center point on sphere [m]
    double hh = 1 - dd * dd / (bb * bb);
    double b = ( H_shelf + H_0 / 2 * (1 + tanh(hh / phi)) ); 
    
   
   
      
    
    double hTot = 0.;
    
    double beta = 0.2;
    
     std::vector < adept::adouble > P(NLayers);
    for(unsigned k = 0; k < NLayers; k++) {
      hTot += solh[k][0].value();
      adept::adouble rhok = rho1[k] - beta * solT[k][0];
      P[k] = - rhok * 9.81 * b; // bottom topography
      for( unsigned j = 0; j < NLayers; j++){
	 adept::adouble rhoj = (j <= k) ? (rho1[j] - beta * solT[j][0]) : rhok;
	 P[k] += rhoj * 9.81 * solh[j][0];
      }
      P[k] /= 1024;
    }
       
    std::vector < double > hALE(NLayers, 0.); 
      
    hALE[0] = hRest[0] + (hTot - b);
    for(unsigned k = 1; k < NLayers - 1; k++){
      hALE[k] = hRest[k];
    }
    hALE[NLayers - 1] = b - hRest[NLayers - 1];
       
    std::vector < double > w(NLayers+1, 0.);
    
     dx = x[1] - x[0];
     
    for(unsigned k = NLayers; k>1; k--){
      w[k-1] = w[k] -  solh[k-1][0].value() * (solv[k-1][1].value() - solv[k-1][0].value() )/dx- ( hALE[k-1] - solh[k-1][0].value()) / dt;
      //std::cout << hALE[k-1] << " " << w[k-1] << " ";
    }
    //std::cout<<std::endl;
    
    std::vector < adept::adouble > zMid(NLayers);
    for(unsigned k = 0; k < NLayers; k++) {
      zMid[k] = -b + solh[k][0]/2;
      for(unsigned i = k+1; i < NLayers; i++) {
        zMid[k] += solh[i][0];
      }
    }
    
    double celerity = sqrt( 9.81 * hTot);
    for(unsigned i = 0; i<NLayers; i++){
      double vmid = 0.5 * ( solv[i][0].value() + solv[i][1].value() );
      maxWaveSpeed = ( maxWaveSpeed > fabs(vmid) + fabs(celerity) )?  maxWaveSpeed : fabs(vmid) + fabs(celerity);
    }
       

    for(unsigned k = 0; k < NLayers; k++) {
      if(!bdch[k][0]) {
        for (unsigned j = 0; j < nDofv; j++) {
          double sign = ( j == 0) ? 1. : -1;
          aResh[k][0] += sign * solh[k][0] * solv[k][j] / dx; 
	}
	aResh[k][0] += w[k+1] - w[k];	    
      }
      adept::adouble vMid = 0.5 * (solv[k][0] + solv[k][1]);
      adept::adouble fv = 0.5 * vMid * vMid + P[k];
      for (unsigned i = 0; i < nDofv; i++) {
        if(!bdcv[k][i]) {
          double sign = ( i == 0) ? -1. : 1;
          aResv[k][i] += sign * fv / dx;
	  if ( k > 0 ){
	    aResv[k][i] -= 0.5 * ( w[k]   * 0.5 * ( solv[k-1][i] - solv[k][i] ) / (0.5 * ( solh[k-1][0] + solh[k][0] ) ) );
	  }
	  if (k < NLayers - 1) {
	    aResv[k][i] -= 0.5 * ( w[k+1] * 0.5 * ( solv[k][i] - solv[k+1][i] ) / (0.5 * ( solh[k][0] + solh[k+1][0] ) ) );
	  }
	  //aResv[k][i] += sign * 9.81  * rho1[k] / 1024. * zMid[k] / dx;
        }
      }
      if(!bdcHT[k][0]) {
        for (unsigned j = 0; j < nDofv; j++) {
          double sign = ( j == 0) ? 1. : -1;
          aResHT[k][0] += sign * solv[k][j] * solHT[k][0] / dx; 
	}
	if(k<NLayers-1){
	  aResHT[k][0] += w[k+1] * 0.5 * (solHT[k][0]/solh[k][0] + solHT[k+1][0]/solh[k+1][0]);
	  //aResHT[k][0] += w[k+1] * 0.5 * (solT[k][0] + solT[k+1][0]);
	}
	if( k > 0){
	  aResHT[k][0] -= w[k] * 0.5 * (solHT[k-1][0]/solh[k-1][0] + solHT[k][0]/solh[k][0] );
	  //aResHT[k][0] -= w[k] * 0.5 * (solT[k-1][0] + solT[k][0]);
	}
      }
    } 

    vector< double > Res(NLayers * nDofs); // local redidual vector

    unsigned counter = 0;
    for(unsigned k = 0; k < NLayers; k++) {
      for(int i = 0; i < nDofh; i++) {
        Res[counter] =  aResh[k][i].value();
        counter++;
      }
      for(int i = 0; i < nDofv; i++) {
        Res[counter] =  aResv[k][i].value();
        counter++;
      }
      for(int i = 0; i < nDofHT; i++) {
        Res[counter] =  aResHT[k][i].value();
        counter++;
      }
    }

    RES->add_vector_blocked(Res, l2GMap);


    for(unsigned k = 0; k < NLayers; k++) {
      // define the dependent variables
      s.dependent(&aResh[k][0], nDofh);
      s.dependent(&aResv[k][0], nDofv);
      s.dependent(&aResHT[k][0], nDofHT);

      // define the independent variables
      s.independent(&solh[k][0], nDofh);
      s.independent(&solv[k][0], nDofv);
      s.independent(&solHT[k][0], nDofHT);
    }

    // get the jacobian matrix (ordered by row major )
    vector < double > Jac(NLayers * nDofs * NLayers * nDofs);
    s.jacobian(&Jac[0], true);

    //store K in the global matrix KK
    KK->add_matrix_blocked(Jac, l2GMap, l2GMap);

    s.clear_independents();
    s.clear_dependents();

  }

  RES->close();
  KK->close();

//   PetscViewer    viewer;
//   PetscViewerDrawOpen(PETSC_COMM_WORLD,NULL,NULL,0,0,900,900,&viewer);
//   PetscObjectSetName((PetscObject)viewer,"FSI matrix");
//   PetscViewerPushFormat(viewer,PETSC_VIEWER_DRAW_LG);
//   MatView((static_cast<PetscMatrix*>(KK))->mat(),viewer);
//   double a;
//   std::cin>>a;
//
  
//  abort();
  MFN mfn;
  Mat A = (static_cast<PetscMatrix*>(KK))->mat();
  FN f, f1, f2, f3 , f4;
  
 
  
  std::cout << "dt = " << dt << " dx = "<< dx << " maxWaveSpeed = "<<maxWaveSpeed << std::endl;
  
  //dt = 100.;

  Vec v = (static_cast< PetscVector* >(RES))->vec();
  Vec y = (static_cast< PetscVector* >(EPS))->vec();

  MFNCreate( PETSC_COMM_WORLD, &mfn );

  MFNSetOperator( mfn, A );
  MFNGetFN( mfn, &f );


//   FNCreate(PETSC_COMM_WORLD, &f1);
//   FNCreate(PETSC_COMM_WORLD, &f2);
//   FNCreate(PETSC_COMM_WORLD, &f3);
//   FNCreate(PETSC_COMM_WORLD, &f4);
// 
//   FNSetType(f1, FNEXP);
// 
//   FNSetType(f2, FNRATIONAL);
//   double coeff1[1] = { -1};
//   FNRationalSetNumerator(f2, 1, coeff1);
//   FNRationalSetDenominator(f2, 0, PETSC_NULL);
// 
//   FNSetType( f3, FNCOMBINE );
// 
//   FNCombineSetChildren(f3, FN_COMBINE_ADD, f1, f2);
// 
//   FNSetType(f4, FNRATIONAL);
//   double coeff2[2] = {1., 0.};
//   FNRationalSetNumerator(f4, 2, coeff2);
//   FNRationalSetDenominator(f4, 0, PETSC_NULL);
// 
//   FNSetType( f, FNCOMBINE );
// 
//   FNCombineSetChildren(f, FN_COMBINE_DIVIDE, f3, f4);

  FNPhiSetIndex(f,1);
  FNSetType( f, FNPHI );
// FNView(f,PETSC_VIEWER_STDOUT_WORLD);

  FNSetScale( f, dt, dt);
  MFNSetFromOptions( mfn );

  MFNSolve( mfn, v, y);
  MFNDestroy( &mfn );

//   FNDestroy(&f1);
//   FNDestroy(&f2);
//   FNDestroy(&f3);
//   FNDestroy(&f4);


  sol->UpdateSol(mlPdeSys->GetSolPdeIndex(), EPS, pdeSys->KKoffset); 

  unsigned solIndexeta = mlSol->GetIndex("eta");
  unsigned solIndexb = mlSol->GetIndex("b");
  sol->_Sol[solIndexeta]->zero();
  for(unsigned k=0;k<NumberOfLayers;k++){
    sol->_Sol[solIndexeta]->add(*sol->_Sol[solIndexh[k]]);
  }
  sol->_Sol[solIndexeta]->add(-1,*sol->_Sol[solIndexb]);

  for(unsigned k=0; k<NumberOfLayers; k++){
    for(unsigned i =  msh->_dofOffset[solTypeHT][iproc]; i <  msh->_dofOffset[solTypeHT][iproc + 1]; i++){
      double valueHT = (*sol->_Sol[solIndexHT[k]])(i);
      double valueH = (*sol->_Sol[solIndexh[k]])(i);
            
      double valueT = valueHT/valueH;
    
      sol->_Sol[solIndexT[k]]->set(i, valueT);
    }
    
    sol->_Sol[solIndexT[k]]->close();
    
  }
  
  
}
Example #5
0
File: ex2.cpp Project: FeMTTU/femus
void AssemblePoisson_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
  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system<NonLinearImplicitSystem> ("Poisson");   // 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
  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 solUIndex;
  solUIndex = mlSol->GetIndex ("U");   // get the position of "U" in the ml_sol object = 0
  unsigned solUType = mlSol->GetSolutionType (solUIndex);   // get the finite element type for "T"

  unsigned solUPdeIndex;
  solUPdeIndex = mlPdeSys->GetSolPdeIndex ("U");   // get the position of "U" in the pdeSys object = 0

  vector < adept::adouble >  solU; // local solution
  vector< adept::adouble > aResU; // local redidual vector

  unsigned solVIndex;
  solVIndex = mlSol->GetIndex ("V");
  unsigned solVType = mlSol->GetSolutionType (solVIndex);

  unsigned solVPdeIndex;
  solVPdeIndex = mlPdeSys->GetSolPdeIndex ("V");

  vector < adept::adouble >  solV; // local solution
  vector< adept::adouble > aResV; // local redidual vector

  vector < vector < double > > crdX (dim);   // local coordinates
  unsigned crdXType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC)

  solU.reserve (maxSize);
  aResU.reserve (maxSize);

  solV.reserve (maxSize);
  aResV.reserve (maxSize);

  for (unsigned  k = 0; k < dim; k++) {
    crdX[k].reserve (maxSize);
  }

  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

  phi.reserve (maxSize);
  phi_x.reserve (maxSize * dim);
  phi_xx.reserve (maxSize * dim2);

  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);

  double weight; // gauss point weight

  vector< int > sysDof; // local to global pdeSys dofs
  sysDof.reserve (2 * maxSize);

  vector< double > Res; // local residual vector
  Res.reserve (2 * maxSize);

  vector < double > Jac;
  Jac.reserve (4 * maxSize * maxSize);

  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 = msh->GetElementType (iel);     // element geometry type

    unsigned nDofsU = msh->GetElementDofNumber (iel, solUType);     // number of solution element dofs
    unsigned nDofsV = msh->GetElementDofNumber (iel, solVType);
    unsigned nDofsX = msh->GetElementDofNumber (iel, crdXType);     // number of solution element dofs

    // resize local arrays
    sysDof.resize (nDofsU + nDofsV);
    solU.resize (nDofsU);
    solV.resize (nDofsV);

    for (unsigned  k = 0; k < dim; k++) {
      crdX[k].resize (nDofsX);
    }

    aResU.assign (nDofsU, 0);
    aResV.assign (nDofsV, 0);

    // local storage of global mapping and solution
    for (unsigned i = 0; i < nDofsU; i++) {
      unsigned solUDof = msh->GetSolutionDof (i, iel, solUType);   // local to global mapping of the solution U
      solU[i] = (*sol->_Sol[solUIndex]) (solUDof);     // value of the solution U in the dofs
      sysDof[i] = pdeSys->GetSystemDof (solUIndex, solUPdeIndex, i, iel);   // local to global mapping between solution U and system
    }

    for (unsigned i = 0; i < nDofsV; i++) {
      unsigned solVDof = msh->GetSolutionDof (i, iel, solVType);
      solV[i] = (*sol->_Sol[solVIndex]) (solVDof);
      sysDof[i + nDofsU] = pdeSys->GetSystemDof (solVIndex, solVPdeIndex, i, iel);
    }

    // local storage of coordinates
    for (unsigned i = 0; i < nDofsX; i++) {
      unsigned coordXDof  = msh->GetSolutionDof (i, iel, crdXType);  // local to global mapping of the coordinate X[dim]

      for (unsigned k = 0; k < dim; k++) {
        crdX[k][i] = (*msh->_topology->_Sol[k]) (coordXDof);     // value of the solution X[dim]
      }
    }

    s.new_recording();

    // *** Gauss point loop *** //
    for (unsigned ig = 0; ig < msh->_finiteElement[ielGeom][solUType]->GetGaussPointNumber(); ig++) {
      // *** get gauss point weight, test function and test function partial derivatives ***
      msh->_finiteElement[ielGeom][solUType]->Jacobian (crdX, ig, weight, phi, phi_x, phi_xx);
      msh->_finiteElement[ielGeom][solVType]->Jacobian (crdX, ig, weight, phiV, phiV_x, phiV_xx);

      adept::adouble solUig = 0; // solution U in the gauss point
      vector < adept::adouble > gradSolUig (dim, 0.); // gradient of solution U in the gauss point

      for (unsigned i = 0; i < nDofsU; i++) {
        solUig += phi[i] * solU[i];

        for (unsigned j = 0; j < dim; j++) {
          gradSolUig[j] += phi_x[i * dim + j] * solU[i];
        }
      }

      adept::adouble solVig = 0; // solution V in the gauss point
      vector < adept::adouble > gradSolVig (dim, 0.); // gradient of solution U in the gauss point

      for (unsigned i = 0; i < nDofsV; i++) {
        solVig += phiV[i] * solV[i];

        for (unsigned j = 0; j < dim; j++) {
          gradSolVig[j] += phiV_x[i * dim + j] * solV[i];
        }
      }

      double nu = 1.;

      // *** phiU_i loop ***
      for (unsigned i = 0; i < nDofsU; i++) {
        adept::adouble LaplaceU = 0.;

        for (unsigned j = 0; j < dim; j++) {
          LaplaceU -=  nu * phi_x[i * dim + j] * gradSolUig[j];
        }

        aResU[i] += (phi[i] - LaplaceU) * weight;

      } // end phiU_i loop

      for (unsigned i = 0; i < nDofsV; i++) {
        adept::adouble LaplaceV = 0.;

        for (unsigned j = 0; j < dim; j++) {
          LaplaceV -=  nu * phiV_x[i * dim + j] * gradSolVig[j];
        }

        aResV[i] += (phiV[i] * solUig - LaplaceV) * weight;

      } // end phiV_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 them in RES
    Res.resize (nDofsU + nDofsV);   //resize

    for (int i = 0; i < nDofsU; i++) {
      Res[i] = -aResU[i].value();
    }

    for (int i = 0; i < nDofsV; i++) {
      Res[i + nDofsU] = -aResV[i].value();
    }

    RES->add_vector_blocked (Res, sysDof);

    //Extarct and store the Jacobian

    Jac.resize ( (nDofsU + nDofsV) * (nDofsU + nDofsV));
    // define the dependent variables
    s.dependent (&aResU[0], nDofsU);
    s.dependent (&aResV[0], nDofsV);

    // define the independent variables
    s.independent (&solU[0], nDofsU);
    s.independent (&solV[0], nDofsV);
    // 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();

  KK->close();

  // ***************** END ASSEMBLY *******************
}
Example #6
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);

}
Example #7
0
int main (int argc, char** args) {

  // init Petsc-MPI communicator
  FemusInit mpinit (argc, args, MPI_COMM_WORLD);

  // define multilevel mesh
  MultiLevelMesh mlMsh;
  // read coarse level mesh and generate finers level meshes
  double scalingFactor = 1.;
  //mlMsh.ReadCoarseMesh("./input/cube_hex.neu","seventh",scalingFactor);
  //mlMsh.ReadCoarseMesh("./input/square_quad.neu", "seventh", scalingFactor);
  mlMsh.ReadCoarseMesh ("./input/quadAMR.neu", "seventh", scalingFactor);
  /* "seventh" is the order of accuracy that is used in the gauss integration scheme
     probably in the furure it is not going to be an argument of this function   */
  unsigned dim = mlMsh.GetDimension();

  unsigned maxNumberOfMeshes = 5;


  vector < vector < double > > l2Norm;
  l2Norm.resize (maxNumberOfMeshes);

  vector < vector < double > > semiNorm;
  semiNorm.resize (maxNumberOfMeshes);

//   unsigned numberOfUniformLevels = 3;
//   unsigned numberOfSelectiveLevels = 0;
//   mlMsh.RefineMesh(numberOfUniformLevels , numberOfUniformLevels + numberOfSelectiveLevels, NULL);

  for (unsigned i = 1; i < maxNumberOfMeshes; i++) {

    unsigned numberOfUniformLevels = i + 3;
    unsigned numberOfSelectiveLevels = 0;
    //mlMsh.RefineMesh (numberOfUniformLevels + numberOfSelectiveLevels, numberOfUniformLevels , SetRefinementFlag);
    mlMsh.RefineMesh (numberOfUniformLevels + numberOfSelectiveLevels, numberOfUniformLevels , NULL);
    // erase all the coarse mesh levels
    //mlMsh.EraseCoarseLevels(numberOfUniformLevels - 3);

    // print mesh info
    mlMsh.PrintInfo();

    FEOrder feOrder[3] = {FIRST, SERENDIPITY, SECOND};
    l2Norm[i].resize (3);
    semiNorm[i].resize (3);

    for (unsigned j = 0; j < 3; j++) {

      MultiLevelSolution mlSol (&mlMsh);

      // add variables to mlSol

      mlSol.AddSolution("Flag",  DISCONTINOUS_POLYNOMIAL, ZERO);

      mlSol.AddSolution ("U", LAGRANGE, feOrder[j]);

      mlSol.Initialize ("All");

      // attach the boundary condition function and generate boundary data
      mlSol.AttachSetBoundaryConditionFunction (SetBoundaryCondition);

      mlSol.GenerateBdc ("All");

      // define the multilevel problem attach the mlSol object to it
      MultiLevelProblem mlProb (&mlSol);

      // add system Poisson in mlProb as a Linear Implicit System
      NonLinearImplicitSystem& system = mlProb.add_system < NonLinearImplicitSystem > ("Poisson");

      // add solution "u" to system
      system.AddSolutionToSystemPDE ("U");

      //system.SetMgSmoother(GMRES_SMOOTHER);
      system.SetMgSmoother (ASM_SMOOTHER); // Additive Swartz Method
      // attach the assembling function to system
      system.SetAssembleFunction (AssemblePoisson_AD);

      system.SetMaxNumberOfNonLinearIterations (10);
      system.SetMaxNumberOfLinearIterations (3);
      system.SetAbsoluteLinearConvergenceTolerance (1.e-12);
      system.SetNonLinearConvergenceTolerance (1.e-8);
      system.SetMgType (F_CYCLE);

      system.SetNumberPreSmoothingStep (0);
      system.SetNumberPostSmoothingStep (2);
      // initilaize and solve the system
      system.init();

      system.SetSolverFineGrids (GMRES);
      system.SetPreconditionerFineGrids (ILU_PRECOND);
      system.SetTolerances (1.e-3, 1.e-20, 1.e+50, 5);

      system.SetNumberOfSchurVariables (1);
      system.SetElementBlockNumber (4);
      //system.SetDirichletBCsHandling(ELIMINATION);
      //system.solve();
      system.MGsolve();

      std::pair< double , double > norm = GetErrorNorm (&mlSol);
      l2Norm[i][j]  = norm.first;
      semiNorm[i][j] = norm.second;

      // print solutions
      std::vector < std::string > variablesToBePrinted;
      variablesToBePrinted.push_back ("All");
      VTKWriter vtkIO (&mlSol);
      vtkIO.SetDebugOutput (true);
      vtkIO.Write (DEFAULT_OUTPUTDIR, "biquadratic", variablesToBePrinted, i);

//       GMVWriter gmvIO (&mlSol);
//       variablesToBePrinted.push_back ("all");
//       gmvIO.SetDebugOutput (true);
//       gmvIO.Write (DEFAULT_OUTPUTDIR, "biquadratic", variablesToBePrinted, i);

    }

  }
  // print the seminorm of the error and the order of convergence between different levels
  std::cout << std::endl;
  std::cout << std::endl;
  std::cout << "l2 ERROR and ORDER OF CONVERGENCE:\n\n";
  std::cout << "LEVEL\tFIRST\t\t\tSERENDIPITY\t\tSECOND\n";

  for (unsigned i = 1; i < maxNumberOfMeshes; i++) {
    std::cout << i + 1 << "\t";
    std::cout.precision (14);

    for (unsigned j = 0; j < 3; j++) {
      std::cout << l2Norm[i][j] << "\t";
    }

    std::cout << std::endl;



  }

  std::cout << std::endl;
  std::cout << std::endl;
  std::cout << "SEMINORM ERROR and ORDER OF CONVERGENCE:\n\n";
  std::cout << "LEVEL\tFIRST\t\t\tSERENDIPITY\t\tSECOND\n";

  for (unsigned i = 1; i < maxNumberOfMeshes; i++) {
    std::cout << i + 1 << "\t";
    std::cout.precision (14);

    for (unsigned j = 0; j < 3; j++) {
      std::cout << semiNorm[i][j] << "\t";
    }

    std::cout << std::endl;



  }

  return 0;
}
Example #8
0
File: ex2.cpp Project: FeMTTU/femus
void GetL2Norm ( MultiLevelProblem& ml_prob, MultiLevelProblem& ml_prob2 )
{

    LinearImplicitSystem* mlPdeSys  = &ml_prob.get_system<LinearImplicitSystem> ( "NonLocal" );
    const unsigned level = mlPdeSys->GetLevelToAssemble();
    Mesh*                    msh = ml_prob._ml_msh->GetLevel ( level );
    elem*                     el = msh->el;
    MultiLevelSolution*    mlSol = ml_prob._ml_sol;
    Solution*                sol = ml_prob._ml_sol->GetSolutionLevel ( level );
    
        LinearImplicitSystem* mlPdeSys2  = &ml_prob2.get_system<LinearImplicitSystem> ( "Local" );
    MultiLevelSolution*    mlSol2 = ml_prob2._ml_sol;
    Solution*                sol2 = ml_prob2._ml_sol->GetSolutionLevel ( level );

    const unsigned  dim = msh->GetDimension();

    unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC)

    double error_solExact_norm2 = 0.;

    double error_solExact_local_norm2 = 0.;

    double error_solLocal_norm2 = 0.;

    double solNonlocal_norm2 = 0.;

    double solLocal_norm2 = 0.;

    double sol_exact_norm2 = 0.;

    unsigned soluIndex;
    soluIndex = mlSol->GetIndex ( "u" );
    unsigned soluType = mlSol->GetSolutionType ( soluIndex );

    unsigned soluIndexLocal;
    soluIndexLocal = mlSol2->GetIndex ( "u_local" );

    unsigned    iproc = msh->processor_id();
    unsigned    nprocs = msh->n_processors();

    for ( int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++ ) {

        short unsigned ielGeom = msh->GetElementType ( iel );
        unsigned nDofu  = msh->GetElementDofNumber ( iel, soluType );
        unsigned nDofx = msh->GetElementDofNumber ( iel, xType );

        vector < vector < double > > x1 ( dim );

        for ( int i = 0; i < dim; i++ ) {
            x1[i].resize ( nDofx );
        }

        vector < double >  soluNonLoc ( nDofu );
        vector < double >  soluLoc ( nDofu );

        for ( unsigned i = 0; i < nDofu; i++ ) {
            unsigned solDof = msh->GetSolutionDof ( i, iel, soluType );
            soluNonLoc[i] = ( *sol->_Sol[soluIndex] ) ( solDof );
            soluLoc[i] = ( *sol2->_Sol[soluIndexLocal] ) ( solDof );
        }

        for ( unsigned i = 0; i < nDofx; i++ ) {
            unsigned xDof  = msh->GetSolutionDof ( i, iel, xType );

            for ( unsigned jdim = 0; jdim < dim; jdim++ ) {
                x1[jdim][i] = ( *msh->_topology->_Sol[jdim] ) ( xDof );
            }
        }

        vector <double> phi;  // local test function
        vector <double> phi_x; // local test function first order partial derivatives
        double weight; // gauss point weight

        // *** Gauss point loop ***
        for ( unsigned ig = 0; ig < msh->_finiteElement[ielGeom][soluType]->GetGaussPointNumber(); ig++ ) {
            // *** get gauss point weight, test function and test function partial derivatives ***
            msh->_finiteElement[ielGeom][soluType]->Jacobian ( x1, ig, weight, phi, phi_x );
            double soluNonLoc_gss = 0.;
            double soluLoc_gss = 0.;
            double exactSol_gss_x = 0.;
            double exactSol_gss_y = 0.;


            for ( unsigned i = 0; i < nDofu; i++ ) {
                soluNonLoc_gss += phi[i] * soluNonLoc[i];
                soluLoc_gss += phi[i] * soluLoc[i];
                exactSol_gss_x += phi[i] * x1[0][i]; // this is x at the Gauss point
//                 exactSol_gss_y += phi[i] * x1[1][i]; // this is y at the Gauss point
            }

            exactSol_gss_x = exactSol_gss_x * exactSol_gss_x * exactSol_gss_x * exactSol_gss_x + 0.1 * exactSol_gss_x * exactSol_gss_x; // this is x^4 + delta * x^2

//             exactSol_gss_x = exactSol_gss_x * exactSol_gss_x; // this is x^2

//             exactSol_gss_x = exactSol_gss_x * exactSol_gss_x * exactSol_gss_x; // this is x^3
//             exactSol_gss_y = exactSol_gss_y * exactSol_gss_y * exactSol_gss_y; // this is y^3

//             exactSol_gss_x = exactSol_gss_x * exactSol_gss_x * exactSol_gss_x * exactSol_gss_x; // this is x^4

//             exactSol_gss_x = 2 * exactSol_gss_x  + exactSol_gss_x * exactSol_gss_x * exactSol_gss_x * exactSol_gss_x * exactSol_gss_x ; // this is 2x + x^5

            error_solExact_norm2 += ( soluNonLoc_gss - exactSol_gss_x ) * ( soluNonLoc_gss - exactSol_gss_x ) * weight;

            //             error_solExact_norm2 += (soluNonLoc_gss -  (exactSol_gss_x + exactSol_gss_y)) * (soluNonLoc_gss -  (exactSol_gss_x + exactSol_gss_y)) * weight; //error L2 norm of x^3 + y^3

            error_solExact_local_norm2 += ( soluLoc_gss - exactSol_gss_x ) * ( soluLoc_gss - exactSol_gss_x ) * weight;

            error_solLocal_norm2 += ( soluNonLoc_gss - soluLoc_gss ) * ( soluNonLoc_gss - soluLoc_gss ) * weight;

            solNonlocal_norm2 += soluNonLoc_gss * soluNonLoc_gss * weight;

            solLocal_norm2 += soluLoc_gss * soluLoc_gss * weight;

//             sol_exact_norm2 += (exactSol_gss_x + exactSol_gss_y) * (exactSol_gss_x + exactSol_gss_y) * weight; //L2 norm of x^3 + y^3

            sol_exact_norm2 += exactSol_gss_x * exactSol_gss_x * weight;
        }
    }

    double norm2 = 0.;
    MPI_Allreduce ( &error_solExact_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    double norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of ERROR: Nonlocal - exact = " << norm << std::endl;

    norm2 = 0.;
    MPI_Allreduce ( &error_solExact_local_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of ERROR: Local - exact = " << norm << std::endl;

    norm2 = 0.;
    MPI_Allreduce ( &error_solLocal_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of ERROR: Nonlocal - local = " << norm << std::endl;

    norm2 = 0.;
    MPI_Allreduce ( &solNonlocal_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of NONLOCAL soln = " << norm << std::endl;

    norm2 = 0.;
    MPI_Allreduce ( &solLocal_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of LOCAL soln = " << norm << std::endl;

    norm2 = 0.;
    MPI_Allreduce ( &sol_exact_norm2, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "L2 norm of EXACT soln = " << norm << std::endl;


    double littleL2norm = 0.;
    std::vector<double> littleLInfinitynorm ( nprocs, 0. );

    for ( unsigned i =  msh->_dofOffset[soluType][iproc]; i <  msh->_dofOffset[soluType][iproc + 1]; i++ ) {

        double nonLocalNodalValue = ( *sol->_Sol[soluIndex] ) ( i );
        double LocalNodalValue = ( *sol2->_Sol[soluIndexLocal] ) ( i );

        double difference = fabs ( nonLocalNodalValue - LocalNodalValue );

        if ( difference > littleLInfinitynorm[iproc] ) littleLInfinitynorm[iproc] = difference;

        littleL2norm += difference * difference;

    }

    norm2 = 0.;
    MPI_Allreduce ( &littleL2norm, &norm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
    norm = sqrt ( norm2 );
    std::cout.precision ( 14 );
    std::cout << "l2 norm of ERROR: Nonlocal - local = " << norm << std::endl;

    for ( int kproc = 0; kproc < nprocs; kproc++ ) {
        MPI_Bcast ( &littleLInfinitynorm[iproc], 1, MPI_DOUBLE, kproc, MPI_COMM_WORLD );
    }

    double littleLInfinityNorm = littleLInfinitynorm[0];

    for ( unsigned kproc = 0; kproc < nprocs; kproc++ ) {
        if ( littleLInfinitynorm[kproc] > littleLInfinityNorm ) littleLInfinityNorm = littleLInfinitynorm[kproc];
    }

    std::cout.precision ( 14 );
    std::cout << "linfinity norm of ERROR: Nonlocal - local = " << littleLInfinityNorm << std::endl;


}
Example #9
0
File: ex2.cpp Project: FeMTTU/femus
int main ( int argc, char** argv )
{

    // init Petsc-MPI communicator
    FemusInit mpinit ( argc, argv, MPI_COMM_WORLD );

    MultiLevelMesh mlMsh;
    double scalingFactor = 1.;
    unsigned numberOfSelectiveLevels = 0;
//     mlMsh.ReadCoarseMesh ( "../input/nonlocal_boundary_test.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/interface.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest1.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest2.neu", "second", scalingFactor );
//         mlMsh.ReadCoarseMesh ( "../input/maxTest3.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest4.neu", "eighth", scalingFactor );
    mlMsh.ReadCoarseMesh ( "../input/maxTest5.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest6.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest7.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest8.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest9.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest10.neu", "eighth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/maxTest2Continuous.neu", "second", scalingFactor );
    //mlMsh.ReadCoarseMesh ( "../input/martaTest0.neu", "second", scalingFactor );
//      mlMsh.ReadCoarseMesh ( "../input/martaTest1.neu", "second", scalingFactor );
//    mlMsh.ReadCoarseMesh ( "../input/martaTest2.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/martaTest3.neu", "second", scalingFactor );
//        mlMsh.ReadCoarseMesh ( "../input/martaTest4.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/martaTest5.neu", "fifth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/martaTest7.neu", "fifth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/martaTest8.neu", "fifth", scalingFactor );
//            mlMsh.ReadCoarseMesh ( "../input/martaTest9.neu", "fifth", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/martaTest4Coarser.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/trial1.neu", "second", scalingFactor );
//     mlMsh.ReadCoarseMesh ( "../input/trial2.neu", "second", scalingFactor );
    mlMsh.RefineMesh ( numberOfUniformLevels + numberOfSelectiveLevels, numberOfUniformLevels , NULL );

    mlMsh.EraseCoarseLevels ( numberOfUniformLevels - 1 );
//     numberOfUniformLevels = 1;

    unsigned dim = mlMsh.GetDimension();

    MultiLevelSolution mlSol ( &mlMsh );

    // add variables to mlSol
    mlSol.AddSolution ( "u", LAGRANGE, FIRST, 2 );

    mlSol.AddSolution ( "u_local", LAGRANGE, FIRST, 2 );

    mlSol.AddSolution ( "u_exact", LAGRANGE, FIRST, 2 );

    mlSol.Initialize ( "All" );

    mlSol.Initialize ( "u_exact", InitalValueU );

    mlSol.AttachSetBoundaryConditionFunction ( SetBoundaryCondition );

    // ******* Set boundary conditions *******
    mlSol.GenerateBdc ( "All" );


    //BEGIN assemble and solve nonlocal problem
    MultiLevelProblem ml_prob ( &mlSol );

    // ******* Add FEM system to the MultiLevel problem *******
    LinearImplicitSystem& system = ml_prob.add_system < LinearImplicitSystem > ( "NonLocal" );
    system.AddSolutionToSystemPDE ( "u" );

    // ******* System FEM Assembly *******
    system.SetAssembleFunction ( AssembleNonLocalSys );
    system.SetMaxNumberOfLinearIterations ( 1 );
    // ******* set MG-Solver *******
    system.SetMgType ( V_CYCLE );

    system.SetAbsoluteLinearConvergenceTolerance ( 1.e-50 );
    //   system.SetNonLinearConvergenceTolerance(1.e-9);
//   system.SetMaxNumberOfNonLinearIterations(20);

    system.SetNumberPreSmoothingStep ( 1 );
    system.SetNumberPostSmoothingStep ( 1 );

    // ******* Set Preconditioner *******
    system.SetLinearEquationSolverType ( FEMuS_DEFAULT );

    system.SetSparsityPatternMinimumSize ( 500u ); //TODO tune

    system.init();

    // ******* Set Smoother *******
    system.SetSolverFineGrids ( GMRES );

    system.SetPreconditionerFineGrids ( ILU_PRECOND );

    system.SetTolerances ( 1.e-20, 1.e-20, 1.e+50, 100 );

// ******* Solution *******

    system.MGsolve();

    //END assemble and solve nonlocal problem

    //BEGIN assemble and solve local problem
    MultiLevelProblem ml_prob2 ( &mlSol );

    // ******* Add FEM system to the MultiLevel problem *******
    LinearImplicitSystem& system2 = ml_prob2.add_system < LinearImplicitSystem > ( "Local" );
    system2.AddSolutionToSystemPDE ( "u_local" );

    // ******* System FEM Assembly *******
    system2.SetAssembleFunction ( AssembleLocalSys );
    system2.SetMaxNumberOfLinearIterations ( 1 );
    // ******* set MG-Solver *******
    system2.SetMgType ( V_CYCLE );

    system2.SetAbsoluteLinearConvergenceTolerance ( 1.e-50 );

    system2.SetNumberPreSmoothingStep ( 1 );
    system2.SetNumberPostSmoothingStep ( 1 );

    // ******* Set Preconditioner *******
    system2.SetLinearEquationSolverType ( FEMuS_DEFAULT );

    system2.init();

    // ******* Set Smoother *******
    system2.SetSolverFineGrids ( GMRES );

    system2.SetPreconditionerFineGrids ( ILU_PRECOND );

    system2.SetTolerances ( 1.e-20, 1.e-20, 1.e+50, 100 );

// ******* Solution *******

    system2.MGsolve();

    //END assemble and solve local problem


    //BEGIN compute errors
    GetL2Norm ( ml_prob, ml_prob2 );
    //END compute errors

    // ******* Print solution *******
    mlSol.SetWriter ( VTK );
    std::vector<std::string> print_vars;
    print_vars.push_back ( "All" );
    mlSol.GetWriter()->SetDebugOutput ( true );
    mlSol.GetWriter()->Write ( DEFAULT_OUTPUTDIR, "biquadratic", print_vars, 0 );

    return 0;

} //end main
Example #10
0
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();

    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);


    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 = msh->GetElementType(iel);
        unsigned nDofs  = msh->GetElementDofNumber(iel, solHType);    // number of solution element dofs
        unsigned nDofs2 = msh->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
            }
        }


        // 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

        //--------------------------------------------------------------------------------------------------------
        // 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);


        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();

    KK->close();

    // ***************** END ASSEMBLY *******************
}
Example #11
0
/**
 * This function assemble the stiffnes matrix KK and the residual vector Res
 * Using automatic differentiation for Newton iterative scheme
 *                  J(u0) w =  - F(u0)  ,
 *                  with u = u0 + w
 *                  - F = f(x) - J u = Res
 *                  J = \grad_u F
 *
 * thus
 *                  J w = f(x) - J u0
 **/
void AssemblePoissonProblem_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

  LinearImplicitSystem* mlPdeSys  = &ml_prob.get_system<LinearImplicitSystem> ("Poisson");   // 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
  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)
  const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim)));          // conservative: based on line3, quad9, hex27

  unsigned    iproc = msh->processor_id(); // get the process_id (for parallel computation)

  //solution variable
  unsigned soluIndex;
  soluIndex = mlSol->GetIndex("u");    // get the position of "u" in the ml_sol object
  unsigned soluType = mlSol->GetSolutionType(soluIndex);    // get the finite element type for "u"

  unsigned soluPdeIndex;
  soluPdeIndex = mlPdeSys->GetSolPdeIndex("u");    // get the position of "u" in the pdeSys object

  vector < adept::adouble >  solu; // local solution
  solu.reserve(maxSize);

  vector < vector < double > > x(dim);    // local coordinates
  unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC)

  for (unsigned i = 0; i < dim; i++) {
    x[i].reserve(maxSize);
  }

  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

  phi.reserve(maxSize);
  phi_x.reserve(maxSize * dim);
  phi_xx.reserve(maxSize * dim2);

  vector< adept::adouble > aRes; // local redidual vector
  aRes.reserve(maxSize);

  vector< int > l2GMap; // local to global mapping
  l2GMap.reserve(maxSize);
  vector< double > Res; // local redidual vector
  Res.reserve(maxSize);
  vector < double > Jac;
  Jac.reserve(maxSize * maxSize);

  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 = msh->GetElementType(iel);
    unsigned nDofu  = msh->GetElementDofNumber(iel, soluType);    // number of solution element dofs
    unsigned nDofx = msh->GetElementDofNumber(iel, xType);    // number of coordinate element dofs

    // resize local arrays
    l2GMap.resize(nDofu);
    solu.resize(nDofu);

    for (int i = 0; i < dim; i++) {
      x[i].resize(nDofx);
    }

    aRes.resize(nDofu);    //resize
    std::fill(aRes.begin(), aRes.end(), 0);    //set aRes to zero

    // local storage of global mapping and solution
    for (unsigned i = 0; i < nDofu; i++) {
      unsigned solDof = msh->GetSolutionDof(i, iel, soluType);    // global to global mapping between solution node and solution dof
      solu[i] = (*sol->_Sol[soluIndex])(solDof);      // global extraction and local storage for the solution
      l2GMap[i] = pdeSys->GetSystemDof(soluIndex, soluPdeIndex, i, iel);    // global to global mapping between solution node and pdeSys dof
    }

    // local storage of coordinates
    for (unsigned i = 0; i < nDofx; i++) {
      unsigned xDof  = msh->GetSolutionDof(i, iel, xType);    // global to global mapping between coordinates node and coordinate dof

      for (unsigned jdim = 0; jdim < dim; jdim++) {
        x[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof);      // global extraction and local storage for the element coordinates
      }
    }


    // 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][soluType]->GetGaussPointNumber(); ig++) {
      // *** get gauss point weight, test function and test function partial derivatives ***
      msh->_finiteElement[ielGeom][soluType]->Jacobian(x, ig, weight, phi, phi_x, phi_xx);

      // evaluate the solution, the solution derivatives and the coordinates in the gauss point
      adept::adouble solu_gss = 0;
      vector < adept::adouble > gradSolu_gss(dim, 0.);
      vector < double > x_gss(dim, 0.);

      for (unsigned i = 0; i < nDofu; i++) {
        solu_gss += phi[i] * solu[i];

        for (unsigned jdim = 0; jdim < dim; jdim++) {
          gradSolu_gss[jdim] += phi_x[i * dim + jdim] * solu[i];
          x_gss[jdim] += x[jdim][i] * phi[i];
        }
      }

      // *** phi_i loop ***
      for (unsigned i = 0; i < nDofu; i++) {

        adept::adouble laplace = 0.;

        for (unsigned jdim = 0; jdim < dim; jdim++) {
          laplace   +=  phi_x[i * dim + jdim] * gradSolu_gss[jdim];
        }

        double srcTerm = - GetExactSolutionLaplace(x_gss);
        aRes[i] += (srcTerm * phi[i] - laplace) * weight;

      } // end phi_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
    Res.resize(nDofu);    //resize

    for (int i = 0; i < nDofu; i++) {
      Res[i] = - aRes[i].value();
    }

    RES->add_vector_blocked(Res, l2GMap);



    // define the dependent variables
    s.dependent(&aRes[0], nDofu);

    // define the independent variables
    s.independent(&solu[0], nDofu);

    // get the jacobian matrix (ordered by row major )
    Jac.resize(nDofu * nDofu);    //resize
    s.jacobian(&Jac[0], true);

    //store K in the global matrix KK
    KK->add_matrix_blocked(Jac, l2GMap, l2GMap);

    s.clear_independents();
    s.clear_dependents();

  } //end element loop for each process

  RES->close();

  KK->close();

  // ***************** END ASSEMBLY *******************
}
Example #12
0
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 *******************
}
Example #13
0
void AssembleBilaplaceProblem_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;
   
  NonLinearImplicitSystem* mlPdeSys 	= &ml_prob.get_system<NonLinearImplicitSystem>("Poisson"); // pointer to the linear implicit system named "Poisson" 
  
  const unsigned level = mlPdeSys->GetLevelToAssemble();
  const unsigned levelMax = mlPdeSys->GetLevelMax();
  const bool assembleMatrix = mlPdeSys->GetAssembleMatrix();  
  //  extract pointers to the several objects that we are going to use 
  
  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 soluIndex;
  soluIndex = mlSol->GetIndex("u"); // get the position of "u" in the ml_sol object
  unsigned soluType = mlSol->GetSolutionType(soluIndex); // get the finite element type for "u"  
    
  unsigned soluPdeIndex;
  soluPdeIndex = mlPdeSys->GetSolPdeIndex("u"); // get the position of "u" in the pdeSys object
    
  vector < adept::adouble >  solu; // local solution
  
  unsigned solvIndex;
  solvIndex = mlSol->GetIndex("v"); // get the position of "v" in the ml_sol object
  unsigned solvType = mlSol->GetSolutionType(solvIndex); // get the finite element type for "v"  
    
  unsigned solvPdeIndex;
  solvPdeIndex = mlPdeSys->GetSolPdeIndex("v"); // get the position of "v" in the pdeSys object
    
  vector < adept::adouble >  solv; // 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 > KKDof; // 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 > aResu; // local redidual vector
  vector< adept::adouble > aResv; // 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
  solu.reserve(maxSize);
  solv.reserve(maxSize);
  for(unsigned i = 0; i < dim; i++)
    x[i].reserve(maxSize);
  KKDof.reserve(2*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(2*maxSize);
  aResu.reserve(maxSize);
  aResv.reserve(maxSize);
   
  vector < double > Jac; // local Jacobian matrix (ordered by column, adept)
  Jac.reserve(4*maxSize*maxSize);
  vector< double > Jact; // local Jacobian matrix (ordered by raw, PETSC)
  Jact.reserve(4*maxSize*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->IS_Mts2Gmt_elem_offset[iproc]; iel < msh->IS_Mts2Gmt_elem_offset[iproc+1]; iel++) {
    
    unsigned kel = msh->IS_Mts2Gmt_elem[iel]; // mapping between paralell dof and mesh dof 
    short unsigned kelGeom = el->GetElementType( kel ); // element geometry type
    unsigned nDofs  = el->GetElementDofNumber( kel, soluType); // number of solution element dofs
    unsigned nDofs2 = el->GetElementDofNumber( kel, xType); // number of coordinate element dofs
    
    // resize local arrays
    KKDof.resize(2*nDofs);
    solu.resize(nDofs);
    solv.resize(nDofs);
    for(int i=0; i<dim; i++) {
      x[i].resize(nDofs2);
    }
    Res.resize(2*nDofs); //resize
    aResu.resize(nDofs); //resize
    aResv.resize(nDofs); //resize
    
    std::fill(aResu.begin(), aResu.end(), 0); //set aRes to zero
    std::fill(aResv.begin(), aResv.end(), 0); //set aRes to zero
    
    if(assembleMatrix) { //resize
      Jact.resize(4*nDofs*nDofs); 
      Jac.resize(4*nDofs*nDofs);
    }
         
    // local storage of global mapping and solution
    for( unsigned i=0; i<nDofs; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, soluType);  // local to global solution node   
      unsigned solDof = msh->GetMetisDof(iNode, soluType); // global to global mapping between solution node and solution dof
      solu[i] = (*sol->_Sol[soluIndex])(solDof); // global extraction and local storage for the solution
      solv[i] = (*sol->_Sol[solvIndex])(solDof); // global extraction and local storage for the solution
      KKDof[i]       = pdeSys->GetKKDof(soluIndex, soluPdeIndex, iNode); // global to global mapping between solution node and pdeSys dof
      KKDof[nDofs+i] = pdeSys->GetKKDof(solvIndex, solvPdeIndex, iNode); // global to global mapping between solution node and pdeSys dof
    }
        
     // local storage of coordinates 
    for( unsigned i=0; i<nDofs2; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, xType);  // local to global coordinates node     
      unsigned xDof  = msh->GetMetisDof(iNode, xType); // global to global mapping between coordinates node and coordinate dof
      for(unsigned jdim=0; jdim<dim; jdim++) {
	x[jdim][i] = (*msh->_coordinate->_Sol[jdim])(xDof); // global extraction and local storage for the element coordinates
      }
    }    
        
    if( level == levelMax || !el->GetRefinedElementIndex(kel)) { // 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[kelGeom][soluType]->GetGaussPointNumber(); ig++) {
	// *** get gauss point weight, test function and test function partial derivatives ***
	msh->_finiteElement[kelGeom][soluType]->Jacobian(x,ig,weight,phi,phi_x,phi_xx);
	
	// evaluate the solution, the solution derivatives and the coordinates in the gauss point
	adept::adouble soluGauss = 0;
	vector < adept::adouble > soluGauss_x(dim,0.);
	
	adept::adouble solvGauss = 0;
	vector < adept::adouble > solvGauss_x(dim,0.);

	vector < double > xGauss(dim,0.);
	
	for(unsigned i=0; i<nDofs; i++) {
	  soluGauss+=phi[i]*solu[i];
	  solvGauss+=phi[i]*solv[i];
	  for(unsigned jdim=0; jdim<dim; jdim++) {
	    soluGauss_x[jdim] += phi_x[i*dim+jdim]*solu[i];
	    solvGauss_x[jdim] += phi_x[i*dim+jdim]*solv[i];
	    xGauss[jdim] += x[jdim][i]*phi[i]; 
	  }
	}
        
        double c=.1;
        double Id[2][2]={{1.,0.},{0.,1.}};
	adept::adouble A2 = 1.;
	vector < vector < adept::adouble> > B(dim);
	for(unsigned jdim=0; jdim<dim; jdim++){
	  B[jdim].resize(dim);
	  A2 += soluGauss_x[jdim]*soluGauss_x[jdim]; 
	}
	adept::adouble A = sqrt(A2);
		
	for(unsigned jdim=0; jdim<dim; jdim++){
	  for(unsigned kdim=0; kdim<dim; kdim++){
	     B[jdim][kdim]= Id[jdim][kdim] - (soluGauss_x[jdim] * soluGauss_x[kdim]) / A2;
	  }
	}
		
        // *** phi_i loop ***
	for(unsigned i=0; i<nDofs; i++) {
	 			 
	  adept::adouble nonLinearLaplaceU = 0.;
	  adept::adouble nonLinearLaplaceV = 0.;
	  
	  for(unsigned jdim=0; jdim<dim; jdim++) {
	    
	    nonLinearLaplaceU +=  - 1. / A  * soluGauss_x[jdim] * phi_x[i*dim+jdim]; 
	    
	    nonLinearLaplaceV +=    1. / A * ( - ( B[jdim][0] * solvGauss_x[0] + B[jdim][1] * solvGauss_x[1] ) * phi_x[i*dim+jdim]
					       + ( solvGauss*solvGauss/A2 + c ) * soluGauss_x[jdim] * phi_x[i*dim+jdim] );
	    
	  }
	  	  
	  aResu[i]+= ( 2.*solvGauss/A * phi[i] - nonLinearLaplaceU ) * weight;
	  aResv[i]+= nonLinearLaplaceV * 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++) {
      Res[i]       = aResu[i].value();
      Res[nDofs+i] = aResv[i].value();
    }
    RES->add_vector_blocked(Res,KKDof);
    
    if(assembleMatrix) {
      
      // define the dependent variables
      s.dependent(&aResu[0], nDofs);
      s.dependent(&aResv[0], nDofs);
      
      // define the independent variables
      s.independent(&solu[0], nDofs);   
      s.independent(&solv[0], nDofs);   
      // get the jacobian matrix (ordered by column)
      s.jacobian(&Jac[0]);	
     
      // get the jacobian matrix (ordered by raw, i.e. Jact=Jac^t)
      for (int inode=0;inode<2*nDofs;inode++){
	for (int jnode=0;jnode<2*nDofs;jnode++){
	   Jact[inode*2*nDofs+jnode]=-Jac[jnode*2*nDofs+inode];
	}
      } 
      //store Jact in the global matrix KK
      KK->add_matrix_blocked(Jact,KKDof,KKDof);
      
      s.clear_independents();
      s.clear_dependents();
    }
  } //end element loop for each process

  RES->close();
  if( assembleMatrix ) KK->close();
  // ***************** END ASSEMBLY *******************
}
Example #14
0
void AssembleNonlinearProblem(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
  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system< NonLinearImplicitSystem > ("Poisson");   // pointer to the linear implicit system named "Poisson"

  const unsigned level = mlPdeSys->GetLevelToAssemble();
  const unsigned levelMax = mlPdeSys->GetLevelMax();
  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 soluIndex;
  soluIndex = mlSol->GetIndex("u");    // get the position of "u" in the ml_sol object
  unsigned soluType = mlSol->GetSolutionType(soluIndex);    // get the finite element type for "u"

  unsigned soluPdeIndex;
  soluPdeIndex = mlPdeSys->GetSolPdeIndex("u");    // get the position of "u" in the pdeSys object

  vector < double >  solu; // 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 > KKDof; // 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< double > J; // local Jacobian matrix

  // reserve memory for the local standar vectors
  const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim)));          // conservative: based on line3, quad9, hex27
  solu.reserve(maxSize);

  for (unsigned i = 0; i < dim; i++)
    x[i].reserve(maxSize);

  KKDof.reserve(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(maxSize);
  J.reserve(maxSize * 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->IS_Mts2Gmt_elem_offset[iproc]; iel < msh->IS_Mts2Gmt_elem_offset[iproc + 1]; iel++) {

    unsigned kel = msh->IS_Mts2Gmt_elem[iel]; // mapping between paralell dof and mesh dof
    short unsigned kelGeom = el->GetElementType(kel);    // element geometry type
    unsigned nDofs  = el->GetElementDofNumber(kel, soluType);    // number of solution element dofs
    unsigned nDofs2 = el->GetElementDofNumber(kel, xType);    // number of coordinate element dofs

    // resize local arrays
    KKDof.resize(nDofs);
    solu.resize(nDofs);

    for (int i = 0; i < dim; i++) {
      x[i].resize(nDofs2);
    }

    Res.resize(nDofs);    //resize
    std::fill(Res.begin(), Res.end(), 0);    //set Res to zero

    if (assembleMatrix) {
      J.resize(nDofs * nDofs);    //resize
      std::fill(J.begin(), J.end(), 0);    //set K to zero
    }

    // local storage of global mapping and solution
    for (unsigned i = 0; i < nDofs; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, soluType);    // local to global solution node
      unsigned solDof = msh->GetMetisDof(iNode, soluType);    // global to global mapping between solution node and solution dof
      solu[i] = (*sol->_Sol[soluIndex])(solDof);      // global extraction and local storage for the solution
      KKDof[i] = pdeSys->GetKKDof(soluIndex, soluPdeIndex, iNode);    // global to global mapping between solution node and pdeSys dof
    }

    // local storage of coordinates
    for (unsigned i = 0; i < nDofs2; i++) {
      unsigned iNode = el->GetMeshDof(kel, i, xType);    // local to global coordinates node
      unsigned xDof  = msh->GetMetisDof(iNode, xType);    // global to global mapping between coordinates node and coordinate dof

      for (unsigned jdim = 0; jdim < dim; jdim++) {
        x[jdim][i] = (*msh->_coordinate->_Sol[jdim])(xDof);      // global extraction and local storage for the element coordinates
      }
    }

    if (level == levelMax || !el->GetRefinedElementIndex(kel)) {      // do not care about this if now (it is used for the AMR)
      // *** Gauss point loop ***
      for (unsigned ig = 0; ig < msh->_finiteElement[kelGeom][soluType]->GetGaussPointNumber(); ig++) {
        // *** get gauss point weight, test function and test function partial derivatives ***
        msh->_finiteElement[kelGeom][soluType]->Jacobian(x, ig, weight, phi, phi_x, phi_xx);

        // evaluate the solution, the solution derivatives and the coordinates in the gauss point
        double soluGauss = 0;
        vector < double > soluGauss_x(dim, 0.);
        vector < double > xGauss(dim, 0.);

        for (unsigned i = 0; i < nDofs; i++) {
          soluGauss += phi[i] * solu[i];

          for (unsigned jdim = 0; jdim < dim; jdim++) {
            soluGauss_x[jdim] += phi_x[i * dim + jdim] * solu[i];
            xGauss[jdim] += x[jdim][i] * phi[i];
          }
        }

        // *** phi_i loop ***
        for (unsigned i = 0; i < nDofs; i++) {

          double nonLinearTerm = 0.;
          double mLaplace = 0.;

          for (unsigned jdim = 0; jdim < dim; jdim++) {
            mLaplace   +=  phi_x[i * dim + jdim] * soluGauss_x[jdim];
            nonLinearTerm += soluGauss * soluGauss_x[jdim] * phi[i];
          }

          double exactSolValue = GetExactSolutionValue(xGauss);
          vector < double > exactSolGrad(dim);
          GetExactSolutionGradient(xGauss , exactSolGrad);
          double exactSolLaplace = GetExactSolutionLaplace(xGauss);


          double f = (- exactSolLaplace + exactSolValue * (exactSolGrad[0] + exactSolGrad[1])) * phi[i] ;
          Res[i] += (f - (mLaplace + nonLinearTerm)) * weight;

          if (assembleMatrix) {
            // *** phi_j loop ***
            for (unsigned j = 0; j < nDofs; j++) {
              mLaplace = 0.;
              nonLinearTerm = 0.;

              for (unsigned kdim = 0; kdim < dim; kdim++) {
                mLaplace += (phi_x[i * dim + kdim] * phi_x[j * dim + kdim]);
                nonLinearTerm +=   phi[i] * (phi[j] * soluGauss_x[kdim] + soluGauss * phi_x[j * dim + kdim]);
              }

              J[i * nDofs + j] += (mLaplace + nonLinearTerm) * weight;
            } // end phi_j loop
          } // endif assemble_matrix
        } // 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

    RES->add_vector_blocked(Res, KKDof);

    if (assembleMatrix) KK->add_matrix_blocked(J, KKDof, KKDof);
  } //end element loop for each process

  RES->close();

  if (assembleMatrix) KK->close();

  // ***************** END ASSEMBLY *******************
}
Example #15
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 #16
0
void AssembleBoussinesqAppoximation(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
  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system<NonLinearImplicitSystem> ("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

  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 < double >  solT; // local solution
  vector < vector < double > >  solV(dim);    // local solution
  vector < double >  solP; // local solution

  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);

  for(unsigned  k = 0; k < dim; k++) {
    solV[k].reserve(maxSize);
    coordX[k].reserve(maxSize);
  }

  solP.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

  //BEGIN element loop
  for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) {

    //BEGIN local dof number extraction
    unsigned nDofsT = msh->GetElementDofNumber(iel, solTType);  //temperature
    unsigned nDofsV = msh->GetElementDofNumber(iel, solVType);  //velocity
    unsigned nDofsP = msh->GetElementDofNumber(iel, solPType);  //pressure
    unsigned nDofsX = msh->GetElementDofNumber(iel, coordXType); // coordinates
    unsigned nDofsTVP = nDofsT + dim * nDofsV + nDofsP; // all solutions
    //END local dof number extraction

    //BEGIN memory allocation
    Res.resize(nDofsTVP);
    std::fill(Res.begin(), Res.end(), 0);
    Jac.resize(nDofsTVP * nDofsTVP);
    std::fill(Jac.begin(), Jac.end(), 0);
    sysDof.resize(nDofsTVP);

    solT.resize(nDofsV);

    for(unsigned  k = 0; k < dim; k++) {
      solV[k].resize(nDofsV);
      coordX[k].resize(nDofsX);
    }

    solP.resize(nDofsP);
    //END memory allocation

    //BEGIN global to local extraction
    for(unsigned i = 0; i < nDofsT; i++) { //temperature
      unsigned solTDof = msh->GetSolutionDof(i, iel, solTType);  //local to global solution dof
      solT[i] = (*sol->_Sol[solTIndex])(solTDof);  //global to local solution value
      sysDof[i] = pdeSys->GetSystemDof(solTIndex, solTPdeIndex, i, iel);  //local to global system dof
    }

    for(unsigned i = 0; i < nDofsV; i++) { //velocity
      unsigned solVDof = msh->GetSolutionDof(i, iel, solVType);  //local to global solution dof

      for(unsigned  k = 0; k < dim; k++) {
        solV[k][i] = (*sol->_Sol[solVIndex[k]])(solVDof);  //global to local solution value
        sysDof[i + nDofsT + k * nDofsV] = pdeSys->GetSystemDof(solVIndex[k], solVPdeIndex[k], i, iel);  //local to global system dof
      }
    }

    for(unsigned i = 0; i < nDofsP; i++) { //pressure
      unsigned solPDof = msh->GetSolutionDof(i, iel, solPType);  //local to global solution dof
      solP[i] = (*sol->_Sol[solPIndex])(solPDof);  //global to local solution value
      sysDof[i + nDofsT + dim * nDofsV] = pdeSys->GetSystemDof(solPIndex, solPPdeIndex, i, iel);  //local to global system dof
    }

    for(unsigned i = 0; i < nDofsX; i++) { //coordinates
      unsigned coordXDof  = msh->GetSolutionDof(i, iel, coordXType);  //local to global coordinate dof

      for(unsigned k = 0; k < dim; k++) {
        coordX[k][i] = (*msh->_topology->_Sol[k])(coordXDof);  //global to local coordinate value
      }
    }

    //END global to local extraction

    //BEGIN Gauss point loop
    short unsigned ielGeom = msh->GetElementType(iel);

    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
      double solT_gss = 0;
      vector < double > gradSolT_gss(dim, 0.);

      for(unsigned i = 0; i < nDofsT; i++) {
        solT_gss += phiT[i] * solT[i];

        for(unsigned j = 0; j < dim; j++) {
          gradSolT_gss[j] += phiT_x[i * dim + j] * solT[i];
        }
      }

      vector < double > solV_gss(dim, 0);
      vector < vector < double > > gradSolV_gss(dim);

      for(unsigned  k = 0; k < dim; k++) {
        gradSolV_gss[k].resize(dim);
        std::fill(gradSolV_gss[k].begin(), gradSolV_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];
        }

        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];
          }
        }
      }

      double solP_gss = 0;

      for(unsigned i = 0; i < nDofsP; i++) {
        solP_gss += phiP[i] * solP[i];
      }


      double alpha = 1.;
      double beta = 1.;//40000.;


      double Pr = Prandtl;
      double Ra = Rayleigh;

      //BEGIN phiT_i loop: Energy balance
      for(unsigned i = 0; i < nDofsT; i++) {
        unsigned irow = i;

        for(unsigned k = 0; k < dim; k++) {
          Res[irow] +=  -alpha / sqrt(Ra * Pr) * phiT_x[i * dim + k] * gradSolT_gss[k] * weight;
          Res[irow] +=  -phiT[i] * solV_gss[k] * gradSolT_gss[k] * weight;

          if(assembleMatrix) {
            unsigned irowMat = irow * nDofsTVP;

            for(unsigned j = 0; j < nDofsT; j++) {
              Jac[ irowMat + j ] +=  alpha / sqrt(Ra * Pr) * phiT_x[i * dim + k] * phiT_x[j * dim + k] * weight;
              Jac[ irowMat + j ] +=  phiT[i] * solV_gss[k] * phiT_x[j * dim + k] * weight;
            }

            for(unsigned j = 0; j < nDofsV; j++) {
              unsigned jcol = nDofsT + k * nDofsV + j;
              Jac[ irowMat + jcol ] += phiT[i] * phiV[j] * gradSolT_gss[k] * weight;
            }
          }

        }
      }

      //END phiT_i loop

      //BEGIN phiV_i loop: Momentum balance
      for(unsigned i = 0; i < nDofsV; i++) {

        for(unsigned k = 0; k < dim; k++) {
          unsigned irow = nDofsT + k * nDofsV + i;

          for(unsigned l = 0; l < dim; l++) {
            Res[irow] +=  -sqrt(Pr / Ra) * phiV_x[i * dim + l] * (gradSolV_gss[k][l] + gradSolV_gss[l][k]) * weight;
            Res[irow] +=  -phiV[i] * solV_gss[l] * gradSolV_gss[k][l] * weight;
          }

          Res[irow] += solP_gss * phiV_x[i * dim + k] * weight;

          if(k == 1) {
            Res[irow] += beta * solT_gss * phiV[i] * weight;
          }

          if(assembleMatrix) {
            unsigned irowMat = nDofsTVP * irow;

            for(unsigned l = 0; l < dim; l++) {
              for(unsigned j = 0; j < nDofsV; j++) {
                unsigned jcol1 = (nDofsT + k * nDofsV + j);
                unsigned jcol2 = (nDofsT + l * nDofsV + j);
                Jac[ irowMat + jcol1] += sqrt(Pr / Ra) * phiV_x[i * dim + l] * phiV_x[j * dim + l] * weight;
                Jac[ irowMat + jcol2] += sqrt(Pr / Ra) * phiV_x[i * dim + l] * phiV_x[j * dim + k] * weight;
                Jac[ irowMat + jcol1] += phiV[i] * solV_gss[l] * phiV_x[j * dim + l] * weight;
                Jac[ irowMat + jcol2] += phiV[i] * phiV[j] * gradSolV_gss[k][l] * weight;
              }
            }

            for(unsigned j = 0; j < nDofsP; j++) {
              unsigned jcol = (nDofsT + dim * nDofsV) + j;
              Jac[ irowMat + jcol] += - phiV_x[i * dim + k] * phiP[j] * weight;
            }

            if(k == 1) {
              for(unsigned j = 0; j < nDofsT; j++) {
                Jac[ irowMat + j ] += -beta * phiV[i] * phiT[j] * weight;
              }
            }
          }

        }
      }

      //END phiV_i loop

      //BEGIN phiP_i loop: mass balance
      for(unsigned i = 0; i < nDofsP; i++) {
        unsigned irow = nDofsT + dim * nDofsV + i;

        for(int k = 0; k < dim; k++) {
          Res[irow] += (gradSolV_gss[k][k]) * phiP[i]  * weight;

          if(assembleMatrix) {
            unsigned irowMat = nDofsTVP * irow;

            for(unsigned j = 0; j < nDofsV; j++) {
              unsigned jcol = (nDofsT + k * nDofsV + j);
              Jac[ irowMat + jcol ] += - phiP[i] * phiV_x[j * dim + k] * weight;
            }
          }

        }
      }

      //END phiP_i loop

    }

    //END Gauss point loop

    //BEGIN local to global Matrix/Vector assembly
    RES->add_vector_blocked(Res, sysDof);

    if(assembleMatrix) {
      KK->add_matrix_blocked(Jac, sysDof, sysDof);
    }

    //END local to global Matrix/Vector assembly

  }

  //END element loop

  RES->close();

  if(assembleMatrix) {
    KK->close();
  }

  // ***************** END ASSEMBLY *******************
}
Example #17
0
File: ex4.cpp Project: coyigg/femus
void AssembleBilaplaceProblem_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

  // call the adept stack object
  adept::Stack& s = FemusInit::_adeptStack;

  //  extract pointers to the several objects that we are going to use

  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system<NonLinearImplicitSystem> ("Poisson");   // 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
  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 soluIndex;
  soluIndex = mlSol->GetIndex("u");    // get the position of "u" in the ml_sol object
  unsigned soluType = mlSol->GetSolutionType(soluIndex);    // get the finite element type for "u"

  unsigned soluPdeIndex;
  soluPdeIndex = mlPdeSys->GetSolPdeIndex("u");    // get the position of "u" in the pdeSys object

  vector < adept::adouble >  solu; // local solution

  unsigned solvIndex;
  solvIndex = mlSol->GetIndex("v");    // get the position of "v" in the ml_sol object
  unsigned solvType = mlSol->GetSolutionType(solvIndex);    // get the finite element type for "v"

  unsigned solvPdeIndex;
  solvPdeIndex = mlPdeSys->GetSolPdeIndex("v");    // get the position of "v" in the pdeSys object

  vector < adept::adouble >  solv; // 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 > aResu; // local redidual vector
  vector< adept::adouble > aResv; // 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
  solu.reserve(maxSize);
  solv.reserve(maxSize);

  for (unsigned i = 0; i < dim; i++)
    x[i].reserve(maxSize);

  sysDof.reserve(2 * 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(2 * maxSize);
  aResu.reserve(maxSize);
  aResv.reserve(maxSize);

  vector < double > Jac; // local Jacobian matrix (ordered by column, adept)
  Jac.reserve(4 * maxSize * maxSize);


  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 = msh->GetElementType(iel); 
    unsigned nDofs  = msh->GetElementDofNumber(iel, soluType);    // number of solution element dofs
    unsigned nDofs2 = msh->GetElementDofNumber(iel, xType);    // number of coordinate element dofs
    
    // resize local arrays
    sysDof.resize(2 * nDofs);
    solu.resize(nDofs);
    solv.resize(nDofs);

    for (int i = 0; i < dim; i++) {
      x[i].resize(nDofs2);
    }

    aResu.assign(nDofs, 0.);    //resize
    aResv.assign(nDofs, 0.);    //resize

    // local storage of global mapping and solution
    for (unsigned i = 0; i < nDofs; i++) {
      unsigned solDof = msh->GetSolutionDof(i, iel, soluType);    // global to global mapping between solution node and solution dof
      solu[i]          = (*sol->_Sol[soluIndex])(solDof);      // global extraction and local storage for the solution
      solv[i]          = (*sol->_Sol[solvIndex])(solDof);      // global extraction and local storage for the solution
      sysDof[i]         = pdeSys->GetSystemDof(soluIndex, soluPdeIndex, i, iel);    // global to global mapping between solution node and pdeSys dof
      sysDof[nDofs + i] = pdeSys->GetSystemDof(solvIndex, solvPdeIndex, 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 jdim = 0; jdim < dim; jdim++) {
        x[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof);  // global extraction and local storage for the element coordinates
      }
    }

    // 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][soluType]->GetGaussPointNumber(); ig++) {
      // *** get gauss point weight, test function and test function partial derivatives ***
      msh->_finiteElement[ielGeom][soluType]->Jacobian(x, ig, weight, phi, phi_x, phi_xx);

      // evaluate the solution, the solution derivatives and the coordinates in the gauss point
      adept::adouble soluGauss = 0;
      vector < adept::adouble > soluGauss_x(dim, 0.);

      adept::adouble solvGauss = 0;
      vector < adept::adouble > solvGauss_x(dim, 0.);

      vector < double > xGauss(dim, 0.);

      for (unsigned i = 0; i < nDofs; i++) {
        soluGauss += phi[i] * solu[i];
        solvGauss += phi[i] * solv[i];

        for (unsigned jdim = 0; jdim < dim; jdim++) {
          soluGauss_x[jdim] += phi_x[i * dim + jdim] * solu[i];
          solvGauss_x[jdim] += phi_x[i * dim + jdim] * solv[i];
          xGauss[jdim] += x[jdim][i] * phi[i];
        }
      }

      // *** phi_i loop ***
      for (unsigned i = 0; i < nDofs; i++) {

        adept::adouble Laplace_u = 0.;
        adept::adouble Laplace_v = 0.;

        for (unsigned jdim = 0; jdim < dim; jdim++) {
          Laplace_u   +=  - phi_x[i * dim + jdim] * soluGauss_x[jdim];
          Laplace_v   +=  - phi_x[i * dim + jdim] * solvGauss_x[jdim];
        }

        double exactSolValue = GetExactSolutionValue(xGauss);

        double pi = acos(-1.);
        aResv[i] += (solvGauss * phi[i] -  Laplace_u) * weight;
        aResu[i] += (4.*pi * pi * pi * pi * exactSolValue * phi[i] -  Laplace_v) * weight;
      } // end phi_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
    Res.resize(2 * nDofs);

    for (int i = 0; i < nDofs; i++) {
      Res[i]         = -aResu[i].value();
      Res[nDofs + i] = -aResv[i].value();
    }

    RES->add_vector_blocked(Res, sysDof);

    Jac.resize( 4 * nDofs * nDofs );

    // define the dependent variables
    s.dependent(&aResu[0], nDofs);
    s.dependent(&aResv[0], nDofs);

    // define the independent variables
    s.independent(&solu[0], nDofs);
    s.independent(&solv[0], nDofs);

    // get the jacobian matrix (ordered by column)
    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();
  KK->close();

  // ***************** END ASSEMBLY *******************
}
Example #18
0
std::pair <vector<double>, vector <double> > GetVaribleValues(MultiLevelProblem& ml_prob, const unsigned &elem, const std::vector<double>&xi) {

  NonLinearImplicitSystem* mlPdeSys   = &ml_prob.get_system<NonLinearImplicitSystem> ("NS");   // pointer to the linear implicit system named "Poisson"
  const unsigned level = mlPdeSys->GetLevelToAssemble();

  Mesh* msh = ml_prob._ml_msh->GetLevel(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
  const unsigned  dim = msh->GetDimension(); // get the domain dimension of the problem
  
  //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 < double >  solT; // local solution
  
  vector <unsigned> solVIndex(dim);
  solVIndex[0] = mlSol->GetIndex("U");
  solVIndex[1] = mlSol->GetIndex("V");
  if (dim==3) solVIndex[2] = mlSol->GetIndex("W");
  unsigned solVType = mlSol->GetSolutionType(solVIndex[0]);
  vector < vector <double> > solV(dim);
  
  unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation)
  MyVector <double> solTXi(1, 0.);
  solTXi.stack();
  MyVector <double> solUXi(1, 0.);
  solUXi.stack();
  MyVector <double> solVXi(1, 0.);
  solVXi.stack();
  /*
  if (dim==3) {
  	MyVector <double> solWXi(1, 0.);
    solWXi.stack();
  }
  */
  //BEGIN local dof number extraction
  if(elem >= msh->_elementOffset[iproc] && elem  < msh->_elementOffset[iproc + 1]) {
	unsigned nDofsT = msh->GetElementDofNumber(elem, solTType);  //temperature
  	solT.reserve(nDofsT);
  
    unsigned nDofsV = msh->GetElementDofNumber(elem, solVType); //velocity
    for(unsigned  k = 0; k < dim; k++) solV[k].reserve(nDofsV);

  	//BEGIN global to local extraction
  	for(unsigned i = 0; i < nDofsT; i++) { //temperature
      unsigned solTDof = msh->GetSolutionDof(i, elem, solTType);  //local to global solution dof
      solT[i] = (*sol->_Sol[solTIndex])(solTDof);  //global to local solution value
  	}

    for(unsigned i = 0; i < nDofsV; i++){ //velocity
      unsigned solVDof = msh->GetSolutionDof(i, elem, solVType);
      for(unsigned  k = 0; k < dim; k++) {
      solV[k][i] = (*sol->_Sol[solVIndex[k]])(solVDof); // global extraction and local storage for the solution
     }
   }
  
   short unsigned ielGeom = msh->GetElementType(elem);
   for(unsigned i = 0; i < nDofsT; i++) {
      basis *base = msh->_finiteElement[ielGeom][solTType]->GetBasis();
      double phiT = base->eval_phi(base->GetIND(i), &xi[0]);
      solTXi[iproc] += phiT * solT[i];
   }
   
   for(unsigned i = 0; i < nDofsV; i++) {
    basis *base = msh->_finiteElement[ielGeom][solVType]->GetBasis();
    double phiV = base->eval_phi(base->GetIND(i), &xi[0]);
    solUXi[iproc] += phiV * solV[0][i];
    solVXi[iproc] += phiV * solV[1][i];
 //   if(dim==3) solWXi[iproc] += phiV * solV[2][i];
   }
  }
  
  std::pair <vector <double>, vector <double> > out_value;
  unsigned mproc = msh->IsdomBisectionSearch(elem , 3);
  solUXi.broadcast(mproc);
  solVXi.broadcast(mproc);
  solTXi.broadcast(mproc);
  
  vector <double> solV_pt(dim);
  solV_pt[0]= solUXi[mproc];
  solV_pt[1]= solVXi[mproc];
  out_value.first = solV_pt;
  
  vector <double> solPT_pt(2);
  solPT_pt[0]= 0.;
  solPT_pt[1]=solTXi[mproc];
  out_value.second = solPT_pt;
  
  solUXi.clearBroadcast();
  solVXi.clearBroadcast();
  solTXi.clearBroadcast();
  return out_value;
}