/**
   * Adjoint equation L_{u} := (q\nabla{\psi},\nabla{\lambda}) + (u-z,\psi)
   *
   * @return
   */
  public SparseVector getResLu(Vector u, Vector lambda, Vector q) {
    // 4.Weak form
    WeakFormLaplace2D weakForm = new WeakFormLaplace2D();
    Function fq = new Vector2Function(q);
    weakForm.setParam(fq, FC.C0, null, null);
    // Right hand side(RHS): f(x) = - (u - z)
    Function z_u = z.S(new Vector2Function(u));
    plotFunction(mesh, z_u, String.format("z_u%02d.dat", this.iterNum));
    weakForm.setF(z_u);

    // 5.Assembly process
    AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm);
    System.out.println("Begin Assemble...");
    assembler.assemble();
    SparseMatrix stiff = assembler.getStiffnessMatrix();
    SparseVector load = assembler.getLoadVector();
    // Boundary condition
    assembler.imposeDirichletCondition(FC.C0);
    System.out.println("Assemble done!");

    if (debug) {
      // 6.Solve linear system
      Solver solver = new Solver();
      Vector lmd_solve = solver.solveCGS(stiff, load);
      plotVector(mesh, lmd_solve, "lambda_solve.dat");
    }

    // Residual
    SparseVector res = new SparseVectorHashMap(lambda.getDim());
    stiff.mult(lambda, res);
    res.add(-1.0, load);
    plotVector(mesh, res, "Res_Lu.dat");

    return res;
  }
  /**
   * State equation L_{\lambda} := (q\nabla{u},\nabla{\phi})-(f,\phi)=0
   *
   * <p>获取状态方程的余量
   *
   * @return
   */
  public SparseVector getResLlmd(Vector u, Vector q) {
    // 4.Weak form
    WeakFormLaplace2D weakForm = new WeakFormLaplace2D();
    Function fq = new Vector2Function(q);
    weakForm.setParam(fq, FC.C0, null, null);
    // Right hand side(RHS): f(x) = -4.0
    weakForm.setF(FC.c(-4.0));

    // 5.Assembly process
    AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm);
    System.out.println("Begin Assemble...");
    assembler.assemble();
    SparseMatrix stiff = assembler.getStiffnessMatrix();
    SparseVector load = assembler.getLoadVector();
    // Boundary condition
    assembler.imposeDirichletCondition(diri);
    System.out.println("Assemble done!");

    if (debug) {
      // 6.Solve linear system
      Solver solver = new Solver();
      Vector u_solve = solver.solveCGS(stiff, load);
      plotVector(mesh, u_solve, "u_solve.dat");
    }

    // Residual
    SparseVector res = new SparseVectorHashMap(u.getDim());
    stiff.mult(u, res);
    res.add(-1.0, load);
    plotVector(mesh, res, "Res_Llambda.dat");

    return res;
  }
  /**
   * Parameter regularization L_{q} := \beta(q-\overline{q},\chi) + (\chi\nabla{u},\nabla{\lambda})
   *
   * @param u
   * @param lambda
   * @param q
   * @return
   */
  public SparseVector getResLq(Vector u, Vector lambda, Vector q) {
    // 4.Weak form
    WeakFormL22D weakForm = new WeakFormL22D();
    weakForm.setParam(FC.C0, FC.C1);
    // Right hand side(RHS): f(x) = -(1.0/\beta)\nabla{u}\cdot\nabla{v}
    Function fu = new Vector2Function(u, mesh, "x", "y");
    Function flmd = new Vector2Function(lambda, mesh, "x", "y");
    Function f = FMath.grad(fu).dot(FMath.grad(flmd));
    plotFunction(mesh, f, String.format("Grad(u)Grad(lmd)%02d.dat", this.iterNum));
    Function f2 = FC.c(-1.0 / beta).M(f).A(qBar);
    plotFunction(mesh, f2, String.format("LqRHS%02d.dat", this.iterNum));
    weakForm.setF(f2);

    // 5.Assembly process
    AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm);
    System.out.println("Begin Assemble...");
    assembler.assemble();
    SparseMatrix stiff = assembler.getStiffnessMatrix();
    SparseVector load = assembler.getLoadVector();
    // Boundary condition
    assembler.imposeDirichletCondition(FC.c(8.0));
    System.out.println("Assemble done!");

    if (debug) {
      // 6.Solve linear system
      Solver solver = new Solver();
      Vector q_solve = solver.solveCGS(stiff, load);
      plotVector(mesh, q_solve, "q_solve.dat");
    }

    // Residual
    SparseVector res = new SparseVectorHashMap(q.getDim());
    stiff.mult(q, res);
    res.add(-1.0, load);
    plotVector(mesh, res, "Res_Lq.dat");

    return res;
  }
  public SparseBlockMatrix getSearchDirectionMatrix(Vector uk, Vector qk) {
    SparseBlockMatrix BM = new SparseBlockMatrix(3, 3);
    SparseMatrix M = this.getM();
    SparseMatrix A = this.getA(qk);
    SparseMatrix AT = A.copy().trans();
    SparseMatrix C = this.getC(uk);
    SparseMatrix CT = C.copy().trans();
    SparseMatrix R = this.getBR();

    SparseMatrix BM13 = new SparseMatrixRowMajor(M.getRowDim(), R.getColDim());
    SparseMatrix BM22 = new SparseMatrixRowMajor(A.getRowDim(), A.getColDim());
    SparseMatrix BM31 = new SparseMatrixRowMajor(R.getRowDim(), M.getColDim());

    BM.setBlock(1, 1, M);
    BM.setBlock(1, 2, AT);
    BM.setBlock(1, 3, BM13);

    BM.setBlock(2, 1, A);
    BM.setBlock(2, 2, BM22);
    BM.setBlock(2, 3, C);

    BM.setBlock(3, 1, BM31);
    BM.setBlock(3, 2, CT);
    BM.setBlock(3, 3, R);

    return BM;
  }