Ejemplo n.º 1
0
int SkewSymmetricScatter(Vec *x,PetscScalar *cacheScalar ,PetscInt *cacheInt, PetscInt n2,PetscInt Istart,PetscInt localsizex , VecScatter *ctx){

PetscInt i,k; 
IS       isbc;
Vec      bcvec;

VecCreateSeqWithArray(MPI_COMM_SELF,localsizex*4,cacheScalar,&bcvec);

k = 0; 
for(i=0;i<localsizex;i++){*(cacheInt+k)= n2*(n2*2-Istart)-1-i*n2;k++;} 
for(i=0;i<localsizex;i++){*(cacheInt+k)= n2*(n2*2-Istart)-2-i*n2;k++;}
for(i=0;i<localsizex;i++){*(cacheInt+k)= n2*(n2*2-Istart)-n2+1-i*n2;k++;}
for(i=0;i<localsizex;i++){*(cacheInt+k)= n2*(n2*2-Istart)-n2-i*n2;k++;}

ISCreateGeneralWithArray(MPI_COMM_WORLD,4*localsizex,cacheInt,&isbc);
VecScatterCreate(*x,isbc,bcvec,PETSC_NULL,ctx);
ISDestroy(isbc);

return 0;
}
Ejemplo n.º 2
0
int main(int argc,char **args)
{
  PetscInt       rank,size,npt;  
  PetscErrorCode ierr;
  Vec            x,y0,tempvec, *vinda,*vindb,*vindc;
  PetscInt       i,j,k,l,n,p,m,m2,pmax,puse,Istart,Iend,localsize,niter;

  PetscScalar    dx,dy,dx2,dy2;  
  PetscScalar    *Mixnorm;
  PetscInt       iter,*iterind,*nind;
  FILE           *fidoutput;   
  char           fname[50];
  PetscViewer    socketviewer; 
  PetscInt       withMatlab;
  PetscTruth     Matlabflag;


  PetscLogDouble v1,v2,elapsed_time;


  PetscInitialize(&argc,&args,(char *)0,help);
  MPI_Comm_size(PETSC_COMM_WORLD,&size);
  MPI_Comm_rank(PETSC_COMM_WORLD,&rank);

  ierr = PetscPrintf(PETSC_COMM_WORLD,"\nPETSC: Petsc Initializes successfully! \n");
  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: comm_size is %d \n", size);
 
  ierr = PetscOptionsGetInt(PETSC_NULL,"-withMatlab",&withMatlab,&Matlabflag);CHKERRQ(ierr);  
  if (Matlabflag == PETSC_FALSE){withMatlab = 0;}else{withMatlab = 1;}


  if(withMatlab==1){
  // Rank 0 connects to socket, use default socket
  PetscViewerSocketOpen(PETSC_COMM_WORLD,0,PETSC_DEFAULT,&socketviewer);  
  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: socket opened! \n");CHKERRQ(ierr); 

  // Receive n from Matlab
  IntReceive(socketviewer, &nind);
  n = *nind;
  //  Receive iter from Matlab
  IntReceive(socketviewer, &iterind);
  iter = *iterind;
 
  }else{
  ierr = PetscOptionsGetInt(PETSC_NULL,"-ngrid",&n,PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscOptionsGetInt(PETSC_NULL,"-niter",&iter,PETSC_NULL);CHKERRQ(ierr);
  }

  
 
/////////////////////////////////////////////////////////////////////////////////////




  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: number of grid is %d \n", n);
  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: number of iteration is %d \n", iter);



  Mixnorm    = malloc(iter*sizeof(PetscScalar));
  dx         = 1.0/n;
  dy         = 1.0/n;
  dx2        = dx/2-dx/1e6;
  dy2        = dy/2-dy/1e6;
  npt        = 5;
  pmax       = 4e6;
  puse       = pmax;

  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: estimated buffer size (per processer) %f Mbytes \n", pmax*1.0/1e6*8*16 );
  ierr = PetscPrintf(PETSC_COMM_WORLD,"PETSC: estimated variable size %f Mbytes\n", 1.0*n*n/1e6*8*2);

/////////////////////////////////////////////////////////////////////////////////////
  
  ierr  = VecCreateMPI(PETSC_COMM_WORLD,PETSC_DECIDE ,n,&tempvec);CHKERRQ(ierr);
  ierr  = VecGetOwnershipRange(tempvec,&Istart,&Iend);CHKERRQ(ierr); 
  localsize = Iend-Istart;
  ierr = VecDestroy(tempvec);CHKERRQ(ierr);
/////////////////////////////////////////////////////////////////////////////////////
// Create initial vector
    Vec         x0;
    PetscScalar *x0array;
    x0array = malloc((localsize)*n*sizeof(PetscScalar));
    k = 0;
    for(i=Istart;i<Iend;i++){
        for(j=0;j<n;j++){
            *(x0array+k) = cos(2*M_PI*(dx/2+i*dx));
            //*(x0array+k) = cos(2*M_PI*(dy/2+j*dy));       
            k++;

        }
    }

  

    ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n*localsize,PETSC_DECIDE,x0array,&x0);CHKERRQ(ierr);
    ierr = VecDuplicate(x0,&x);CHKERRQ(ierr); 
    ierr = VecCreateSeq(PETSC_COMM_SELF,pmax*npt,&y0);CHKERRQ(ierr);
     
    ierr =  VecNorm(x0,NORM_2,Mixnorm); CHKERRQ(ierr);  
    PetscPrintf(PETSC_COMM_WORLD,"PETSC: initial norm= %f \n",*(Mixnorm+0)/n ); 

///////////////////////////////////////////////////////////////////////////
// Map Center Points
  PetscInt     *NzindJ,*idx,*idy,*idp;
  PetscScalar  *CenterX,*CenterY,*VecVal,*pty;
  PetscScalar  *ShiftX,*ShiftY,CX,CY, *yarray;
  IS           isx,isy;
  VecScatter   ctx;

  CenterX      = malloc(npt*sizeof(PetscScalar));
  CenterY      = malloc(npt*sizeof(PetscScalar));
  ShiftX       = malloc(npt*sizeof(PetscScalar));
  ShiftY       = malloc(npt*sizeof(PetscScalar));
  VecVal       = malloc(npt*sizeof(PetscScalar));
  yarray       = malloc(pmax*sizeof(PetscScalar)); 

  NzindJ       = malloc(pmax*npt*sizeof(PetscInt));
  idx          = malloc(pmax*npt*sizeof(PetscInt));
  idy          = malloc(pmax*npt*sizeof(PetscInt)); 
  idp          = malloc(pmax*sizeof(PetscInt)); 
 

  *(ShiftX+0) = 0;
  *(ShiftY+0) = 0;
  *(ShiftX+1) = -dx2;
  *(ShiftY+1) = -dy2;
  *(ShiftX+2) =  dx2;
  *(ShiftY+2) = -dy2;
  *(ShiftX+3) = -dx2;
  *(ShiftY+3) =  dy2;
  *(ShiftX+4) =  dy2;
  *(ShiftY+4) =  dx2;


  //*(ShiftX+5) = 0;
  //*(ShiftY+5) = -dy2;
  //*(ShiftX+6) = -dx2;
  //*(ShiftY+6) = 0;
  //*(ShiftX+7) =  dx2;
  //*(ShiftY+7) = 0;
  //*(ShiftX+8) = 0;
  //*(ShiftY+9) =  dy2;

  for(i=0;i<npt*pmax;i++){ *(idy+i)=i; }
  ISCreateGeneralWithArray(PETSC_COMM_SELF,npt*pmax,idy,&isy);
  vinda = &x0;
  vindb = &x;


   sprintf(fname, "mixnorm_%d_%d",n,iter);
   ierr =PetscPrintf(PETSC_COMM_WORLD,"\n iter     norm      time      unit time\n");CHKERRQ(ierr);
   ierr =PetscFOpen(PETSC_COMM_WORLD,fname,"w",&fidoutput);CHKERRQ(ierr);


for(niter=0;niter<iter;niter++){
   
 ierr = PetscGetTime(&v1);CHKERRQ(ierr);
 l = 0; p = 0;

 if (n*localsize-l<=pmax){puse = n*localsize-l;}else{puse=pmax;}     
     for(i=Istart;i<Iend;i++){
         for(j=0;j<n;j++){
              CX = dx2+i*dx;
              CY = dy2+j*dy;              
              for(k=0;k<npt;k++){ 
                   *(CenterX+k) = CX + *(ShiftX+k);
                   *(CenterY+k) = CY + *(ShiftY+k);    
                   InverseStandardMap((CenterX+k),(CenterY+k));
                   *(NzindJ+p*npt +k) =  floor(*(CenterX+k)*n)*n +  floor(*(CenterY+k)*n);      
              }          
              *(idp+p) = Istart*n+ l;
      
             if(p>=puse-1){ 
          
                 ierr =  ISCreateGeneralWithArray(PETSC_COMM_WORLD,npt*puse,NzindJ,&isx);CHKERRQ(ierr);
                 for(m=0;m<npt*puse;m++){ *(idy+m)=m; }
                 ierr =  ISCreateGeneralWithArray(PETSC_COMM_SELF,npt*puse,idy,&isy);CHKERRQ(ierr);
                 ierr =  VecScatterCreate(*vinda,isx,y0,isy,&ctx);CHKERRQ(ierr);
                 ierr =  VecScatterBegin(*vinda,y0,INSERT_VALUES,SCATTER_FORWARD,ctx);CHKERRQ(ierr);
                 ierr =  VecScatterEnd(*vinda,y0,INSERT_VALUES,SCATTER_FORWARD,ctx);CHKERRQ(ierr);
                 ierr =  VecScatterDestroy(ctx);
                 ierr =  VecGetArray(y0,&pty);CHKERRQ(ierr);
              
                 for(m=0;m<puse;m++){
                     for(m2=0;m2<npt;m2++){
                        *(yarray+m) = *(yarray+m)+*(pty+m*npt+m2);
                     }  
                     *(yarray+m) = *(yarray+m)/npt;
                 } 
                 VecRestoreArray(y0,&pty);
                 VecSetValues(*vindb,puse,idp,yarray,INSERT_VALUES);       

 

                 for(m=0;m<pmax;m++){*(yarray+m) = 0; } 
                 p = 0;

                 if (n*localsize-l<=pmax){puse = n*localsize-l-1;}else{puse=pmax;}            
             }else{p++;}

             l++;
         
        }
    }


   VecAssemblyBegin(*vindb);
   VecAssemblyEnd(*vindb);

   vindc = vindb;
   vindb = vinda;
   vinda = vindc;   


   //ierr =  VecCopy(x,x0);CHKERRQ(ierr);
   ierr =  VecNorm(*vinda,NORM_2,Mixnorm+niter); CHKERRQ(ierr); 
   *(Mixnorm+niter) = *(Mixnorm+niter)/n; 

        
   ierr = PetscGetTime(&v2);CHKERRQ(ierr);
   elapsed_time = v2 - v1; 
   PetscPrintf(PETSC_COMM_WORLD,"     %d   %f   %f  %f \n",niter,*(Mixnorm+niter),elapsed_time,elapsed_time/n/n*1e6 );
   PetscFPrintf(PETSC_COMM_WORLD,fidoutput,"    %d   %f   %f  %f\n"
                ,niter,*(Mixnorm+niter),elapsed_time,elapsed_time/n/n*1e6 );
}



 PetscFClose(PETSC_COMM_WORLD,fidoutput);

///////////////////////////////////////////////////////////////////////////

    if(withMatlab==1){
     VecView(x0,socketviewer);
     PetscScalarView(iter,Mixnorm,socketviewer);
    }
 
  free(CenterX);
  free(CenterY);
  free(ShiftX);
  free(ShiftY);
  

  free(x0array);
  free(idx);
  free(idy);
  free(idp);
  free(yarray);

 

  free(NzindJ);

  free(Mixnorm);

 
   ierr = VecDestroy(x0);CHKERRQ(ierr);
   ierr = VecDestroy(x);CHKERRQ(ierr);
   ierr = VecDestroy(y0);CHKERRQ(ierr);
 
  PetscPrintf(PETSC_COMM_WORLD,"Done!");
  
//////////////////////////////////////////////////////////////////////////////////////
  ierr = PetscFinalize();CHKERRQ(ierr);
  return 0;
}
Ejemplo n.º 3
0
/*
A new Strategy can handle large size problem (more than 4G variables)

*/
int BackwardAverageRL(Vec *x, Vec *y, PetscInt *cacheInt, PetscScalar *cacheScalar, PetscInt n, PetscInt npt, PetscInt pmax, PetscInt Istart, PetscInt Iend,PetscScalar c){

 PetscInt       rank,size;
 PetscErrorCode ierr;
 PetscInt       i, j, k=0, pi, pj, n2,n4 ,m, puse, pgrid,lx;  
 PetscInt       localsizex,localsizey, rowcount=0;
 PetscInt       k1,k2,pgrid1,pgrid2;
 PetscInt       *idy,*idp, *NzindJ;
 PetscScalar    dx,dy,dx2,dy2,CX,CY;

 PetscScalar    *pty, *pty0; 
 IS             isx1,isx2,isy1,isy2;
 VecScatter     ctx1,ctx2;
 Vec            y0;
 Vec            x1,x2;
 PetscScalar    *ptx1,*ptx2;
 PetscInt       size1,size2,col1,col2;
 

 MPI_Comm_size(PETSC_COMM_WORLD,&size);
 MPI_Comm_rank(PETSC_COMM_WORLD,&rank);

 n2     = (PetscInt)(n*0.5);
 n4     = (PetscInt)(n*0.25);
 dx     = 1.0/n;
 dy     = 1.0/n;
 dx2    = dx/2-dx/1e6;
 dy2    = dy/2-dy/1e6;


  NzindJ = cacheInt;    //pmax
  idp    = cacheInt;    //pmax
  idy    = cacheInt   + pmax; 

  pty0   = cacheScalar   ; //pmax

  
  localsizex    = Iend-Istart;
  localsizey    = (PetscInt)(pmax*1.0/(localsizex+1))-2;
  if(localsizey>n2){localsizey =n2;}
 
  
  ierr =  VecGetArray(*x,&ptx1);CHKERRQ(ierr);
  ptx2 = ptx1;

  if(rank< size*0.5){lx =  localsizex*n2;}else{lx =0;}
  VecCreateMPIWithArray(PETSC_COMM_WORLD,lx,PETSC_DETERMINE,ptx1,&x1);
  if(rank< size*0.5){lx =  0;}else{lx =  localsizex*n2; }
  VecCreateMPIWithArray(PETSC_COMM_WORLD,lx,PETSC_DETERMINE,ptx2,&x2);

  VecGetSize(x1,&size1);
  VecGetSize(x2,&size2);
  col1 = (PetscInt)(size1*1.0/n2);
  col2 = (PetscInt)(size2*1.0/n2);

  ierr =  VecGetArray(*y,&pty);CHKERRQ(ierr);
  ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,(localsizex+1)*(localsizey+1),pty0,&y0);


while(rowcount<n2){

     if (n2-rowcount<=localsizey){localsizey =n2-rowcount;}      
     puse = localsizex*localsizey;
     pgrid = (localsizex+1)*(localsizey+1);
     k= 0;
     k1=0;
     k2=0; 
     for(i=Istart;i<Iend+1;i++){
        for(j=rowcount;j<rowcount+localsizey+1;j++){
           
             CX = (PetscScalar)(i*dx);
             CY = (PetscScalar)(j*dy); 
             InverseStandardMap(&CX,&CY,c); 
             pi = (PetscInt)floor(CX*n);
             pj = (PetscInt)floor(CY*n);   
             if(pj>=n2) {SkewSymmetricPoint(&pi, &pj, n);}

             if(pi<col1){
                  *(NzindJ+k1) =  (PetscInt)(n2*pi +  pj);
                  *(idy+k1)   =  k;
                   k1++;
              }else{
                  *(NzindJ+pgrid-k2-1) =  (PetscInt)(n2*(pi-col1)+pj);
                  *(idy+pgrid-k2-1)   =  k;
                   k2++;
              } 
             k++;    
          }
      }

      pgrid1 = k1;
      pgrid2 = k2;


    ierr =  ISCreateGeneralWithArray(PETSC_COMM_SELF,pgrid1,NzindJ,&isx1);CHKERRQ(ierr);
    ierr =  ISCreateGeneralWithArray(PETSC_COMM_SELF,pgrid2,NzindJ+pgrid1,&isx2);CHKERRQ(ierr);  
 
    ierr =  ISCreateGeneralWithArray(PETSC_COMM_SELF,pgrid1,idy,&isy1);CHKERRQ(ierr);
    ierr =  ISCreateGeneralWithArray(PETSC_COMM_SELF,pgrid2,idy+pgrid1,&isy2);CHKERRQ(ierr);

  
    ierr =  VecDestroy(y0);CHKERRQ(ierr);
    ierr =  VecCreateSeqWithArray(PETSC_COMM_SELF,pgrid,pty0,&y0);CHKERRQ(ierr);



    ierr =  VecScatterCreate(x1,isx1,y0,isy1,&ctx1);CHKERRQ(ierr);
    ierr =  VecScatterCreate(x2,isx2,y0,isy2,&ctx2);CHKERRQ(ierr);

    ierr =  VecScatterBegin(x1,y0,INSERT_VALUES,SCATTER_FORWARD,ctx1);CHKERRQ(ierr);
    ierr =  VecScatterEnd(x1,y0,INSERT_VALUES,SCATTER_FORWARD,ctx1);CHKERRQ(ierr);
    ierr =  VecScatterBegin(x2,y0,INSERT_VALUES,SCATTER_FORWARD,ctx2);CHKERRQ(ierr);
    ierr =  VecScatterEnd(x2,y0,INSERT_VALUES,SCATTER_FORWARD,ctx2);CHKERRQ(ierr);

    ierr =  VecScatterDestroy(ctx1);
    ierr =  VecScatterDestroy(ctx2);
    ierr =  VecGetArray(y0,&pty0);CHKERRQ(ierr);

      m = 0;
      for(i=0;i<localsizex;i++){
           for(j=0;j<localsizey;j++){
              *(pty+i*n2+j+rowcount) = (*(pty0+i*(localsizey+1)+j)+
                                        *(pty0+i*(localsizey+1)+j+1)+
                                        *(pty0+(i+1)*(localsizey+1)+j)+
                                        *(pty0+(i+1)*(localsizey+1)+j+1))/4;         
               m++; 
           }
      }

     VecRestoreArray(y0,&pty0);
     VecRestoreArray(*y,&pty);
     rowcount = rowcount + localsizey;
}



     VecDestroy(x1);
     VecDestroy(x2);


return 0;
}
Ejemplo n.º 4
0
int main(int argc, char * argv[])
{
  typedef MPI::HGeometryForest<DIM,DOW> forest_t;
  typedef MPI::BirdView<forest_t> ir_mesh_t;
  typedef FEMSpace<double,DIM,DOW> fe_space_t;  
  typedef MPI::DOF::GlobalIndex<forest_t, fe_space_t> global_index_t;

  PetscInitialize(&argc, &argv, (char *)NULL, help);

  forest_t forest(PETSC_COMM_WORLD);
  forest.readMesh(argv[1]);
  ir_mesh_t ir_mesh(forest);

  int round = 0;
  if (argc >= 3) round = atoi(argv[2]);

  ir_mesh.globalRefine(round);
  ir_mesh.semiregularize();
  ir_mesh.regularize(false);

  setenv("AFEPACK_TEMPLATE_PATH", "/usr/local/AFEPack/template/triangle", 1);

  TemplateGeometry<DIM> tri;
  tri.readData("triangle.tmp_geo");
  CoordTransform<DIM,DIM> tri_ct;
  tri_ct.readData("triangle.crd_trs");
  TemplateDOF<DIM> tri_td(tri);
  tri_td.readData("triangle.1.tmp_dof");
  BasisFunctionAdmin<double,DIM,DIM> tri_bf(tri_td);
  tri_bf.readData("triangle.1.bas_fun");

  std::vector<TemplateElement<double,DIM,DIM> > tmp_ele(1);
  tmp_ele[0].reinit(tri, tri_td, tri_ct, tri_bf);

  RegularMesh<DIM,DOW>& mesh = ir_mesh.regularMesh();
  fe_space_t fem_space(mesh, tmp_ele);
  u_int n_ele = mesh.n_geometry(DIM);
  fem_space.element().resize(n_ele);
  for (int i = 0;i < n_ele;i ++) {
    fem_space.element(i).reinit(fem_space, i, 0);
  }
  fem_space.buildElement();
  fem_space.buildDof();
  fem_space.buildDofBoundaryMark();

  std::cout << "Building global indices ... " << std::flush;
  global_index_t global_index(forest, fem_space);
  global_index.build();
  std::cout << "OK!" << std::endl;

  std::cout << "Building the linear system ... " << std::flush;
  Mat A;
  Vec x, b;
  MatCreateMPIAIJ(PETSC_COMM_WORLD, 
                  global_index.n_primary_dof(), global_index.n_primary_dof(),
                  PETSC_DECIDE, PETSC_DECIDE,
                  0, PETSC_NULL, 0, PETSC_NULL, &A);
  VecCreateMPI(PETSC_COMM_WORLD, global_index.n_primary_dof(), PETSC_DECIDE, &b);
  fe_space_t::ElementIterator
    the_ele = fem_space.beginElement(),
    end_ele = fem_space.endElement();
  for (;the_ele != end_ele;++ the_ele) {
    double vol = the_ele->templateElement().volume();
    const QuadratureInfo<DIM>& qi = the_ele->findQuadratureInfo(5);
    std::vector<Point<DIM> > q_pnt = the_ele->local_to_global(qi.quadraturePoint());
    int n_q_pnt = qi.n_quadraturePoint();
    std::vector<double> jac = the_ele->local_to_global_jacobian(qi.quadraturePoint());
    std::vector<std::vector<double> > bas_val = the_ele->basis_function_value(q_pnt);
    std::vector<std::vector<std::vector<double> > > bas_grad = the_ele->basis_function_gradient(q_pnt);

    const std::vector<int>& ele_dof = the_ele->dof();
    u_int n_ele_dof = ele_dof.size();
    FullMatrix<double> ele_mat(n_ele_dof, n_ele_dof);
    Vector<double> ele_rhs(n_ele_dof);
    for (u_int l = 0;l < n_q_pnt;++ l) {
      double JxW = vol*jac[l]*qi.weight(l);
      double f_val = _f_(q_pnt[l]);
      for (u_int i = 0;i < n_ele_dof;++ i) {
        for (u_int j = 0;j < n_ele_dof;++ j) {
          ele_mat(i, j) += JxW*(bas_val[i][l]*bas_val[j][l] +
                                innerProduct(bas_grad[i][l], bas_grad[j][l]));
        }
        ele_rhs(i) += JxW*f_val*bas_val[i][l];
      }
    }
    /**
     * 此处将单元矩阵和单元载荷先计算好,然后向全局的矩阵和载荷向量上
     * 集中,可以提高效率。
     */

    std::vector<int> indices(n_ele_dof);
    for (u_int i = 0;i < n_ele_dof;++ i) {
      indices[i] = global_index(ele_dof[i]);
    }
    MatSetValues(A, n_ele_dof, &indices[0], n_ele_dof, &indices[0], &ele_mat(0,0), ADD_VALUES);
    VecSetValues(b, n_ele_dof, &indices[0], &ele_rhs(0), ADD_VALUES);
  }
  MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
  MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
  VecAssemblyBegin(b);
  VecAssemblyEnd(b);
  std::cout << "OK!" << std::endl;

  /// 加上狄氏边值条件
  std::cout << "Applying the Dirichlet boundary condition ... " << std::flush;
  u_int n_bnd_dof = 0; /// 首先清点边界上自由度的个数
  for (u_int i = 0;i < fem_space.n_dof();++ i) {
    if (fem_space.dofBoundaryMark(i) > 0) {
      /// 如果不是在主几何体上就不做
      if (! global_index.is_dof_on_primary_geometry(i)) continue;

      n_bnd_dof += 1;
    }
  }

  /// 准备空间存储边界上全局标号、自变量和右端项
  std::vector<int> bnd_idx(n_bnd_dof);
  std::vector<double> rhs_entry(n_bnd_dof);

  /// 对自由度做循环
  for (u_int i = 0, j = 0;i < fem_space.n_dof();++ i) {
    if (fem_space.dofBoundaryMark(i) > 0) { /// 边界上的自由度?
      /// 如果不是在主几何体上就不做
      if (! global_index.is_dof_on_primary_geometry(i)) continue;

      bnd_idx[j] = global_index(i); /// 行的全局标号
      /// 计算并记下自变量和右端项,假设自由度值为插值量
      double u_b_val = _u_b_(fem_space.dofInfo(i).interp_point);
      rhs_entry[j] = u_b_val;

      j += 1;
    }
  }
  /// 将矩阵修改为对角元 1.0,其它元素为零的状态
  /// MatSetOption(A, MAT_KEEP_ZEROED_ROWS);
  MatZeroRows(A, n_bnd_dof, &bnd_idx[0], 1.0); 

  /// 修改右端项为相应点的边值
  Vec rhs_bnd;
  VecCreateSeqWithArray(PETSC_COMM_SELF, n_bnd_dof, &rhs_entry[0], &rhs_bnd);
  IS is_bnd;
  ISCreateGeneralWithArray(PETSC_COMM_WORLD, n_bnd_dof, &bnd_idx[0], &is_bnd);
  VecScatter bnd_scatter;
  VecScatterCreate(rhs_bnd, PETSC_NULL, b, is_bnd, &bnd_scatter);
  VecScatterBegin(bnd_scatter, rhs_bnd, b, INSERT_VALUES, SCATTER_FORWARD);
  VecScatterEnd(bnd_scatter, rhs_bnd, b, INSERT_VALUES, SCATTER_FORWARD);
  VecDestroy(rhs_bnd);
  ISDestroy(is_bnd);
  VecScatterDestroy(bnd_scatter);
  std::cout << "OK!" << std::endl;

  VecDuplicate(b, &x);

  KSP solver;
  KSPCreate(PETSC_COMM_WORLD, &solver);
  KSPSetOperators(solver, A, A, SAME_NONZERO_PATTERN);
  KSPSetType(solver, KSPGMRES);
  KSPSetFromOptions(solver);
  KSPSolve(solver, b, x);

  if (forest.rank() == 0) {
    KSPConvergedReason reason;
    KSPGetConvergedReason(solver,&reason);
    if (reason == KSP_DIVERGED_INDEFINITE_PC) {
      printf("\nDivergence because of indefinite preconditioner;\n");
      printf("Run the executable again but with -pc_ilu_shift option.\n");
    } else if (reason<0) {
      printf("\nOther kind of divergence: this should not happen.\n");
    } else {
      PetscInt its;
      KSPGetIterationNumber(solver,&its);
      printf("\nConvergence in %d iterations.\n",(int)its);
    }
    printf("\n");
  }

  MatDestroy(A);
  VecDestroy(b);
  KSPDestroy(solver);

  FEMFunction<double,DIM> u_h(fem_space);
  Vec X;
  VecCreateSeqWithArray(PETSC_COMM_SELF, global_index.n_local_dof(), &u_h(0), &X);

  std::vector<int> primary_idx(global_index.n_primary_dof());
  global_index.build_primary_index(&primary_idx[0]);
  IS is;
  ISCreateGeneralWithArray(PETSC_COMM_WORLD, global_index.n_local_dof(),
                           &global_index(0), &is);
  VecScatter scatter;
  VecScatterCreate(x, is, X, PETSC_NULL, &scatter);
  VecScatterBegin(scatter, x, X, INSERT_VALUES, SCATTER_FORWARD);
  VecScatterEnd(scatter, x, X, INSERT_VALUES, SCATTER_FORWARD);

  VecDestroy(x);
  VecDestroy(X);
  VecScatterDestroy(scatter);
  ISDestroy(is);

  char filename[1024];
  sprintf(filename, "u_h%d.dx", forest.rank());
  u_h.writeOpenDXData(filename);

  PetscFinalize();

  return 0;
}