public Vector getRealU() { // 4.Weak form WeakFormLaplace2D weakForm = new WeakFormLaplace2D(); plotFunction(mesh, coef_q, "qReal.dat"); weakForm.setParam(coef_q, 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!"); // 6.Solve linear system Solver solver = new Solver(); Vector u = solver.solveCG(stiff, load); System.out.println("u="); for (int i = 1; i <= u.getDim(); i++) System.out.println(String.format("%.3f", u.get(i))); plotVector(mesh, u, "uReal.dat"); return u; }
public static void plotFunction(Mesh mesh, Function fun, String fileName) { NodeList list = mesh.getNodeList(); int nNode = list.size(); Variable var = new Variable(); Vector v = new SparseVectorHashMap(nNode); for (int i = 1; i <= nNode; i++) { Node node = list.at(i); var.setIndex(node.globalIndex); var.set("x", node.coord(1)); var.set("y", node.coord(2)); v.set(i, fun.value(var)); } plotVector(mesh, v, fileName); }
public static void connectSells(Mesh mesh, Vector v) { NodeList nodes = mesh.getNodeList(); for (int i = 1; i <= nodes.size(); i++) { Node node = nodes.at(i); if (node instanceof NodeRefined) { NodeRefined nRefined = (NodeRefined) node; if (nRefined.isHangingNode()) { v.set( node.globalIndex, v.get(nRefined.constrainNodes.at(1).globalIndex) * 0.5 + v.get(nRefined.constrainNodes.at(2).globalIndex) * 0.5); } } } }
/** * 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; }
public void run() { // 1.Read in a triangle mesh from an input file with // format ASCII UCD generated by Gridgen MeshReader reader = new MeshReader("triangle.grd"); Mesh mesh = reader.read2DMesh(); // Compute geometry relationship of nodes and elements mesh.computeNodeBelongsToElements(); // 2.Mark border types HashMap<NodeType, Function> mapNTF = new HashMap<NodeType, Function>(); mapNTF.put(NodeType.Dirichlet, null); mesh.markBorderNode(mapNTF); // 3.Use element library to assign degrees of // freedom (DOF) to element ElementList eList = mesh.getElementList(); FELinearTriangle feLT = new FELinearTriangle(); for (int i = 1; i <= eList.size(); i++) feLT.assignTo(eList.at(i)); // 4.Weak form WeakFormLaplace2D weakForm = new WeakFormLaplace2D(); // Right hand side(RHS): f = -2*(x^2+y^2)+36 weakForm.setF(X.M(X).A(Y.M(Y)).M(-2.0).A(36.0)); // 5.Assembly process AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm); assembler.assemble(); Matrix stiff = assembler.getStiffnessMatrix(); Vector load = assembler.getLoadVector(); // Boundary condition assembler.imposeDirichletCondition(C0); // 6.Solve linear system SolverJBLAS solver = new SolverJBLAS(); Vector u = solver.solveDGESV(stiff, load); System.out.println("u="); for (int i = 1; i <= u.getDim(); i++) System.out.println(String.format("%.3f", u.get(i))); // 7.Output results to an Techplot format file MeshWriter writer = new MeshWriter(mesh); writer.writeTechplot("./tutorial/Laplace2D.dat", u); this.mesh = mesh; this.u = u; }
/** * 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 static void adaptiveTestTriangle() { MeshReader reader = new MeshReader("patch_triangle.grd"); Mesh mesh = reader.read2DMesh(); mesh.computeNodeBelongsToElements(); mesh.computeNeighborNodes(); mesh.computeGlobalEdge(); mesh.computeNeighborElements(); HashMap<NodeType, Function> mapNTF = new HashMap<NodeType, Function>(); mapNTF.put(NodeType.Dirichlet, null); mesh.markBorderNode(mapNTF); ElementList eList = mesh.getElementList(); ElementList eToRefine = new ElementList(); // 直接指定需要加密的单元编号 eToRefine.add(eList.at(6)); eToRefine.add(eList.at(16)); eToRefine.add(eList.at(3)); eToRefine.add(eList.at(4)); Refiner.refineOnce(mesh, eToRefine); mesh.markBorderNode(mapNTF); // //二次加密 // eToRefine.clear(); // //单元编号的问题该如何处理? // eToRefine.add(eList.at(17)); // //第一步:新增加的结点赋予全局编号,加入mesh对象 // Refiner.refineOnce(mesh, eToRefine); // mesh.markBorderNode(mapNTF); SFLinearLocal2D[] shapeFun = new SFLinearLocal2D[3]; for (int i = 0; i < 3; i++) shapeFun[i] = new SFLinearLocal2D(i + 1); SFLinearLocal2D[] shapeFun2 = new SFLinearLocal2D[3]; for (int i = 0; i < 3; i++) { shapeFun2[i] = new SFLinearLocal2D(i + 1, 0.5); } // Asign degree of freedom to element for (int i = 1; i <= mesh.getElementList().size(); i++) { Element e = mesh.getElementList().at(i); int nDofLocalIndexCounter = 0; for (int j = 1; j <= e.nodes.size(); j++) { // Asign shape function to DOF if (e.nodes.at(j) instanceof NodeRefined) { NodeRefined nRefined = (NodeRefined) e.nodes.at(j); if (nRefined.isHangingNode()) { DOF dof = new DOF( ++nDofLocalIndexCounter, nRefined.constrainNodes.at(1).globalIndex, shapeFun2[j - 1]); e.addNodeDOF(j, dof); DOF dof2 = new DOF( ++nDofLocalIndexCounter, nRefined.constrainNodes.at(2).globalIndex, shapeFun2[j - 1]); e.addNodeDOF(j, dof2); } else { DOF dof = new DOF(++nDofLocalIndexCounter, e.nodes.at(j).globalIndex, shapeFun[j - 1]); e.addNodeDOF(j, dof); } } else { DOF dof = new DOF(++nDofLocalIndexCounter, e.nodes.at(j).globalIndex, shapeFun[j - 1]); e.addNodeDOF(j, dof); } } } // User defined weak form of PDE (including bounder conditions) WeakFormLaplace2D weakForm = new WeakFormLaplace2D(); // -\Delta{u} = f // u(x,y)=0, (x,y)\in\partial{\Omega} // \Omega = [0,10]*[0,10] // u=[(x-5)^2-25]*[(y-5)^2-25] // f=-2*( (x-5)^2 + (y-5)^2 ) + 100 Function fxm5 = new FAxpb("x", 1.0, -5.0); Function fym5 = new FAxpb("y", 1.0, -5.0); weakForm.setF( FC.c(-2.0) .M(FMath.pow(fxm5, new FC(2.0))) .A(FC.c(-2.0).M(FMath.pow(fym5, new FC(2.0)))) .A(FC.c(100.0))); AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm); System.out.println("Begin Assemble..."); assembler.assemble(); Matrix stiff = assembler.getStiffnessMatrix(); Vector load = assembler.getLoadVector(); assembler.imposeDirichletCondition(new FC(0.0)); System.out.println("Assemble done!"); SolverJBLAS solver = new SolverJBLAS(); Vector u = solver.solveDGESV(stiff, load); // hanging node赋值 for (int i = 1; i <= mesh.getElementList().size(); i++) { Element e = mesh.getElementList().at(i); for (int j = 1; j <= e.nodes.size(); j++) { if (e.nodes.at(j) instanceof NodeRefined) { NodeRefined nRefined = (NodeRefined) e.nodes.at(j); if (nRefined.isHangingNode()) { double hnValue = (u.get(nRefined.constrainNodes.at(1).globalIndex) + u.get(nRefined.constrainNodes.at(2).globalIndex)) / 2.0; u.set(nRefined.globalIndex, hnValue); } } } } System.out.println("u="); for (int i = 1; i <= u.getDim(); i++) System.out.println(String.format("%.3f", u.get(i))); MeshWriter writer = new MeshWriter(mesh); writer.writeTechplot("patch_triangle.dat", u); }
public static void beforeRefinement() { // MeshReader reader = new MeshReader("patch_rectangle.grd"); MeshReader reader = new MeshReader("patch_rectangle2.grd"); // MeshReader reader = new MeshReader("patch_rectangle_refine.grd"); Mesh mesh = reader.read2DMesh(); mesh.computeNodeBelongsToElements(); mesh.computeNeighborNodes(); mesh.computeGlobalEdge(); mesh.computeNeighborElements(); HashMap<NodeType, Function> mapNTF = new HashMap<NodeType, Function>(); mapNTF.put(NodeType.Dirichlet, null); mesh.markBorderNode(mapNTF); SFBilinearLocal2D[] shapeFun = new SFBilinearLocal2D[4]; for (int i = 0; i < 4; i++) shapeFun[i] = new SFBilinearLocal2D(i + 1); // Asign degree of freedom to element for (int i = 1; i <= mesh.getElementList().size(); i++) { Element e = mesh.getElementList().at(i); int nDofLocalIndexCounter = 0; for (int j = 1; j <= e.nodes.size(); j++) { // Asign shape function to DOF DOF dof = new DOF(++nDofLocalIndexCounter, e.nodes.at(j).globalIndex, shapeFun[j - 1]); e.addNodeDOF(j, dof); } } // User defined weak form of PDE (including bounder conditions) WeakFormLaplace2D weakForm = new WeakFormLaplace2D(); // -\Delta{u} = f // u(x,y)=0, (x,y)\in\partial{\Omega} // \Omega = [0,10]*[0,10] // u=[(x-5)^2-25]*[(y-5)^2-25] // f=-2*( (x-5)^2 + (y-5)^2 ) + 100 Function fxm5 = new FAxpb("x", 1.0, -5.0); Function fym5 = new FAxpb("y", 1.0, -5.0); weakForm.setF( FC.c(-2.0) .M(FMath.pow(fxm5, new FC(2.0))) .A(FC.c(-2.0).M(FMath.pow(fym5, new FC(2.0)))) .A(FC.c(100.0))); AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm); System.out.println("Begin Assemble..."); assembler.assemble(); Matrix stiff = assembler.getStiffnessMatrix(); Vector load = assembler.getLoadVector(); assembler.imposeDirichletCondition(new FC(0.0)); System.out.println("Assemble done!"); stiff.print(); SolverJBLAS solver = new SolverJBLAS(); Vector u = solver.solveDGESV(stiff, load); System.out.println("u="); for (int i = 1; i <= u.getDim(); i++) System.out.println(String.format("%.3f", u.get(i))); MeshWriter writer = new MeshWriter(mesh); writer.writeTechplot("patch_rectangle_before_refine.dat", u); writer.writeTechplot("patch_rectangle_before_refine_load.dat", load); }
public static void adaptiveTestRectangle() { // MeshReader reader = new MeshReader("patch_rectangle.grd"); MeshReader reader = new MeshReader("patch_rectangle2.grd"); // MeshReader reader = new MeshReader("patch_rectangle_refine.grd"); Mesh mesh = reader.read2DMesh(); HashMap<NodeType, Function> mapNTF = new HashMap<NodeType, Function>(); // 验证边界结点加密后是自由的,而不是hanging node // mapNTF.put(NodeType.Robin, new AbstractFunction("x","y"){ // @Override // public double value(Variable v) { // if(Math.abs(v.get("x"))<0.01) // return 1.0; // else // return -1.0; // } // }); mapNTF.put(NodeType.Dirichlet, null); mesh.computeNodeBelongsToElements(); mesh.computeNeighborNodes(); mesh.markBorderNode(mapNTF); mesh.computeGlobalEdge(); mesh.computeNeighborElements(); ElementList eList = mesh.getElementList(); ElementList eToRefine = new ElementList(); eToRefine.add(eList.at(6)); eToRefine.add(eList.at(7)); eToRefine.add(eList.at(10)); eToRefine.add(eList.at(11)); Refiner.refineOnce(mesh, eToRefine); mesh.markBorderNode(mapNTF); mesh.printMeshInfo(); Tools.plotFunction(mesh, "", "patch_rectangle_test1.dat", FC.C0); // 二次加密 eToRefine.clear(); // 单元编号的问题该如何处理? eToRefine.add(eList.at(17)); eToRefine.add(eList.at(18)); // 第一步:新增加的结点赋予全局编号,加入mesh对象 Refiner.refineOnce(mesh, eToRefine); mesh.markBorderNode(mapNTF); mesh.printMeshInfo(); Tools.plotFunction(mesh, "", "patch_rectangle_test2.dat", FC.C0); SFBilinearLocal2D[] shapeFun = new SFBilinearLocal2D[4]; for (int i = 0; i < 4; i++) shapeFun[i] = new SFBilinearLocal2D(i + 1); SFBilinearLocal2D[] shapeFun2 = new SFBilinearLocal2D[4]; for (int i = 0; i < 4; i++) { shapeFun2[i] = new SFBilinearLocal2D(i + 1, 0.5); } // Asign degree of freedom to element for (int i = 1; i <= mesh.getElementList().size(); i++) { Element e = mesh.getElementList().at(i); int nDofLocalIndexCounter = 0; for (int j = 1; j <= e.nodes.size(); j++) { // Asign shape function to DOF if (e.nodes.at(j) instanceof NodeRefined) { NodeRefined nRefined = (NodeRefined) e.nodes.at(j); if (nRefined.isHangingNode()) { DOF dof = new DOF( ++nDofLocalIndexCounter, nRefined.constrainNodes.at(1).globalIndex, shapeFun2[j - 1]); e.addNodeDOF(j, dof); DOF dof2 = new DOF( ++nDofLocalIndexCounter, nRefined.constrainNodes.at(2).globalIndex, shapeFun2[j - 1]); e.addNodeDOF(j, dof2); } else { DOF dof = new DOF(++nDofLocalIndexCounter, e.nodes.at(j).globalIndex, shapeFun[j - 1]); e.addNodeDOF(j, dof); } } else { DOF dof = new DOF(++nDofLocalIndexCounter, e.nodes.at(j).globalIndex, shapeFun[j - 1]); e.addNodeDOF(j, dof); } } } // User defined weak form of PDE (including bounder conditions) WeakFormLaplace2D weakForm = new WeakFormLaplace2D(); // -\Delta{u} = f // u(x,y)=0, (x,y)\in\partial{\Omega} // \Omega = [0,10]*[0,10] // u=[(x-5)^2-25]*[(y-5)^2-25] // f=-2*( (x-5)^2 + (y-5)^2 ) + 100 Function fxm5 = new FAxpb("x", 1.0, -5.0); Function fym5 = new FAxpb("y", 1.0, -5.0); weakForm.setF( FC.c(-2.0) .M(FMath.pow(fxm5, new FC(2.0))) .A(FC.c(-2.0).M(FMath.pow(fym5, new FC(2.0)))) .A(FC.c(100.0))); AssemblerScalar assembler = new AssemblerScalar(mesh, weakForm); System.out.println("Begin Assemble..."); assembler.assemble(); Matrix stiff = assembler.getStiffnessMatrix(); Vector load = assembler.getLoadVector(); assembler.imposeDirichletCondition(new FC(0.0)); System.out.println("Assemble done!"); stiff.print(); load.print(); SolverJBLAS solver = new SolverJBLAS(); Vector u = solver.solveDGESV(stiff, load); // //hanging node赋值 // for(int i=1;i<=mesh.getElementList().size();i++) { // Element e = mesh.getElementList().at(i); // for(int j=1;j<=e.nodes.size();j++) { // if(e.nodes.at(j) instanceof NodeRefined) { // NodeRefined nRefined = (NodeRefined)e.nodes.at(j); // if(nRefined.isHangingNode()) { // double hnValue = // (u.get(nRefined.constrainNodes.at(1).globalIndex)+ // u.get(nRefined.constrainNodes.at(2).globalIndex))/2.0; // // u.set(nRefined.globalIndex, hnValue); // } // } // } // } System.out.println("u="); for (int i = 1; i <= u.getDim(); i++) System.out.println(String.format("%.3f", u.get(i))); MeshWriter writer = new MeshWriter(mesh); writer.writeTechplot("patch_rectangle.dat", u); Vector res = new SparseVectorHashMap(u.getDim()); stiff.mult(u, res); res.add(-1.0, load); writer.writeTechplot("patch_rectangle_res.dat", res); writer.writeTechplot("patch_rectangle_load.dat", load); connectSells(mesh, load); writer.writeTechplot("patch_rectangle_load_connectSells.dat", load); }
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)); } }