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