protected void setDirichlet(
     SparseBlockMatrix BM, SparseBlockVector BV, int matIndex, double value) {
   int row = matIndex;
   int col = matIndex;
   BM.set(row, col, 1.0);
   BV.set(row, value);
   for (int r = 1; r <= BM.getRowDim(); r++) {
     if (r != row) {
       BV.add(r, -BM.get(r, col) * value);
       BM.set(r, col, 0.0);
     }
   }
   for (int c = 1; c <= BM.getColDim(); c++) {
     if (c != col) {
       BM.set(row, c, 0.0);
     }
   }
 }
  public void gaussNewtonIterate() {
    // 初值
    NodeList nodes = mesh.getNodeList();
    // 初始q=q0
    Vector q0 = new SparseVectorHashMap(nodes.size());
    Vector q00 = new SparseVectorHashMap(nodes.size());
    for (int i = 1; i <= nodes.size(); i++) {
      Node node = nodes.at(i);
      if (node.getNodeType() == NodeType.Dirichlet)
        q0.set(i, this.coef_q.value(Variable.createFrom(coef_q, node, 0)));
      else {
        // q0.set(i,this.coef_q.value(Variable.createFrom(coef_q, node, 0))+1.0+Math.random()*0.9);
        // q0.set(i,1.0+Math.random()*0.9);

        double x = node.coord(1);
        double y = node.coord(2);

        if (Math.sqrt((x) * (x) + (y) * (y)) < 0.5) {
          q0.set(i, 3.0);

          // =1的圆位置偏移
          // if(Math.sqrt((x-0.3)*(x-0.3)+(y)*(y))<0.5) {
          //	q0.set(i,1.0);
        } else {
          q0.set(i, 8.0);
        }
      }
      q00.set(
          i, this.coef_q.value(Variable.createFrom(coef_q, node, 0)) + 1.0 + Math.random() * 0.9);
    }
    plotVector(mesh, q0, "q0.dat");
    plotVector(mesh, q00, "q00.dat");

    // 初始u=u0, lambda=lambda0,从q00计算而来
    Vector u0 = this.solveStateEquation(q0); // q00
    plotVector(mesh, u0, "u0.dat");
    Vector lambda0 = this.solveAdjointEquation(u0, q0); // q00
    plotVector(mesh, lambda0, "lambda0.dat");

    // 强制u0=0,lambda0=0
    // q0 = new SparseVectorHashMap(nodes.size(),1.0);
    // u0 = new SparseVectorHashMap(nodes.size(),0.0);
    // lambda0 = new SparseVectorHashMap(nodes.size(),0.0);

    SparseBlockVector f = new SparseBlockVector(3);
    // 迭代求解
    for (int iter = 0; iter < 50; iter++) {
      iterNum = iter;

      SparseBlockMatrix BM = this.getSearchDirectionMatrix(u0, q0);

      f.setBlock(1, this.getResLu(u0, lambda0, q0).scale(-1.0));
      f.setBlock(2, this.getResLlmd(u0, q0).scale(-1.0)); // bugfix lambda0->q0
      f.setBlock(3, this.getResLq(u0, lambda0, q0).scale(-1.0));

      // 设置边界条件并求解
      // 需要交换矩阵BM的第1, 2列,然后设置边界条件,这样使得矩阵A, A'可逆
      // BlockMatrix newBM = this.changeBlockColumn(BM, 1, 2);
      // this.imposeDirichletCondition(newBM, f, FC.c0);
      // SchurComplementLagrangianSolver solver =
      //	new SchurComplementLagrangianSolver(BM, f,mesh);
      // BlockVector x = solver.solve();

      this.imposeDirichletCondition(BM, f, FC.C0);
      SolverJBLAS sol = new SolverJBLAS();
      SparseBlockVector x = sol.solveDGESV(BM, f);

      plotVector(mesh, x.getBlock(1), String.format("delta_u%02d.dat", iter));
      plotVector(mesh, x.getBlock(2), String.format("delta_lambda%02d.dat", iter));
      plotVector(mesh, x.getBlock(3), String.format("delta_q%02d.dat", iter));

      // 待定,与beta选取有关
      // double stepLength = 0.01;
      // double stepLength = 0.3;
      // double stepLength = 0.00005;
      double stepLength = 0.0001;

      u0.add(stepLength, x.getBlock(1));
      lambda0.add(stepLength, x.getBlock(2));
      q0.add(stepLength, x.getBlock(3));

      plotVector(mesh, u0, String.format("rlt_u%02d.dat", iter));
      plotVector(mesh, lambda0, String.format("rlt_lambda%02d.dat", iter));
      plotVector(mesh, q0, String.format("rlt_q%02d.dat", iter));
    }
  }