// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void CalculateTriangleGroupCurvatures::operator()() const { int32_t err = 0; if (m_TriangleIds.size() == 0) { return; } // Instantiate a FindNRingNeighbors class to use during the loop FindNRingNeighbors::Pointer nRingNeighborAlg = FindNRingNeighbors::New(); int32_t* faceLabels = m_SurfaceMeshFaceLabels->getPointer(0); int32_t* fl = faceLabels + m_TriangleIds[0] * 2; int32_t feature0 = 0; int32_t feature1 = 0; if (fl[0] < fl[1]) { feature0 = fl[0]; feature1 = fl[1]; } else { feature0 = fl[1]; feature1 = fl[0]; } bool computeGaussian = (m_GaussianCurvature.get() != NULL); bool computeMean = (m_MeanCurvature.get() != NULL); bool computeDirection = (m_PrincipleDirection1.get() != NULL); std::vector<int64_t>::size_type tCount = m_TriangleIds.size(); // For each triangle in the group for(std::vector<int64_t>::size_type i = 0; i < tCount; ++i) { if (m_ParentFilter->getCancel() == true) { return; } int64_t triId = m_TriangleIds[i]; nRingNeighborAlg->setTriangleId(triId); nRingNeighborAlg->setRegionId0(feature0); nRingNeighborAlg->setRegionId1(feature1); nRingNeighborAlg->setRing(m_NRing); err = nRingNeighborAlg->generate(m_TrianglesPtr, faceLabels); Q_ASSERT(err >= 0); UniqueFaceIds_t triPatch = nRingNeighborAlg->getNRingTriangles(); Q_ASSERT(triPatch.size() > 1); DataArray<double>::Pointer patchCentroids = extractPatchData(triId, triPatch, m_SurfaceMeshTriangleCentroids->getPointer(0), QString("_INTERNAL_USE_ONLY_Patch_Centroids")); DataArray<double>::Pointer patchNormals = extractPatchData(triId, triPatch, m_SurfaceMeshFaceNormals->getPointer(0), QString("_INTERNAL_USE_ONLY_Patch_Normals")); // Translate the patch to the 0,0,0 origin double sub[3] = {patchCentroids->getComponent(0, 0), patchCentroids->getComponent(0, 1), patchCentroids->getComponent(0, 2)}; subtractVector3d(patchCentroids, sub); double np[3] = {patchNormals->getComponent(0, 0), patchNormals->getComponent(0, 1), patchNormals->getComponent(0, 2) }; double seedCentroid[3] = {patchCentroids->getComponent(0, 0), patchCentroids->getComponent(0, 1), patchCentroids->getComponent(0, 2) }; double firstCentroid[3] = {patchCentroids->getComponent(1, 0), patchCentroids->getComponent(1, 1), patchCentroids->getComponent(1, 2) }; double temp[3] = {firstCentroid[0] - seedCentroid[0], firstCentroid[1] - seedCentroid[1], firstCentroid[2] - seedCentroid[2]}; double vp[3] = {0.0, 0.0, 0.0}; // Cross Product of np and temp MatrixMath::Normalize3x1(np); MatrixMath::CrossProduct(np, temp, vp); MatrixMath::Normalize3x1(vp); // get the third orthogonal vector double up[3] = {0.0, 0.0, 0.0}; MatrixMath::CrossProduct(vp, np, up); // this constitutes a rotation matrix to a local coordinate system double rot[3][3] = {{up[0], up[1], up[2]}, {vp[0], vp[1], vp[2]}, {np[0], np[1], np[2]} }; double out[3] = { 0.0, 0.0, 0.0 }; // Transform all centroids and normals to new coordinate system for (size_t m = 0; m < patchCentroids->getNumberOfTuples(); ++m) { ::memcpy(out, patchCentroids->getPointer(m * 3), 3 * sizeof(double)); MatrixMath::Multiply3x3with3x1(rot, patchCentroids->getPointer(m * 3), out); ::memcpy(patchCentroids->getPointer(m * 3), out, 3 * sizeof(double)); ::memcpy(out, patchNormals->getPointer(m * 3), 3 * sizeof(double)); MatrixMath::Multiply3x3with3x1(rot, patchNormals->getPointer(m * 3), out); ::memcpy(patchNormals->getPointer(m * 3), out, 3 * sizeof(double)); // We rotate the normals now but we dont use them yet. If we start using part 3 of Goldfeathers paper then we // will need the normals. } { // Solve the Least Squares fit static const uint32_t NO_NORMALS = 3; static const uint32_t USE_NORMALS = 7; uint32_t cols = NO_NORMALS; if (m_UseNormalsForCurveFitting == true) { cols = USE_NORMALS; } size_t rows = patchCentroids->getNumberOfTuples(); Eigen::MatrixXd A(rows, cols); Eigen::VectorXd b(rows); double x = 0.0, y = 0.0, z = 0.0; for (size_t m = 0; m < rows; ++m) { x = patchCentroids->getComponent(m, 0); y = patchCentroids->getComponent(m, 1); z = patchCentroids->getComponent(m, 2); A(m) = 0.5 * x * x; // 1/2 x^2 A(m + rows) = x * y; // x*y A(m + rows * 2) = 0.5 * y * y; // 1/2 y^2 if (m_UseNormalsForCurveFitting == true) { A(m + rows * 3) = x * x * x; A(m + rows * 4) = x * x * y; A(m + rows * 5) = x * y * y; A(m + rows * 6) = y * y * y; } b[m] = z; // The Z Values } Eigen::Matrix2d M; if (false == m_UseNormalsForCurveFitting) { typedef Eigen::Matrix<double, NO_NORMALS, 1> Vector3d; Vector3d sln1 = A.colPivHouseholderQr().solve(b); // Now that we have the A, B, C constants we can solve the Eigen value/vector problem // to get the principal curvatures and pricipal directions. M << sln1(0), sln1(1), sln1(1), sln1(2); } else { typedef Eigen::Matrix<double, USE_NORMALS, 1> Vector7d; Vector7d sln1 = A.colPivHouseholderQr().solve(b); // Now that we have the A, B, C, D, E, F & G constants we can solve the Eigen value/vector problem // to get the principal curvatures and pricipal directions. M << sln1(0), sln1(1), sln1(1), sln1(2); } Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eig(M); Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d>::RealVectorType eValues = eig.eigenvalues(); Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d>::MatrixType eVectors = eig.eigenvectors(); // Kappa1 >= Kappa2 double kappa1 = eValues(0) * -1;// Kappa 1 double kappa2 = eValues(1) * -1; //kappa 2 Q_ASSERT(kappa1 >= kappa2); m_PrincipleCurvature1->setValue(triId, kappa1); m_PrincipleCurvature2->setValue(triId, kappa2); if (computeGaussian == true) { m_GaussianCurvature->setValue(triId, kappa1 * kappa2); } if (computeMean == true) { m_MeanCurvature->setValue(triId, (kappa1 + kappa2) / 2.0); } if (computeDirection == true) { Eigen::Matrix3d e_rot_T; e_rot_T.row(0) = Eigen::Vector3d(up[0], vp[0], np[0]); e_rot_T.row(1) = Eigen::Vector3d(up[1], vp[1], np[1]); e_rot_T.row(2) = Eigen::Vector3d(up[2], vp[2], np[2]); // Rotate our principal directions back into the original coordinate system Eigen::Vector3d dir1 ( eVectors.col(0)(0), eVectors.col(0)(1), 0.0 ); dir1 = e_rot_T * dir1; ::memcpy(m_PrincipleDirection1->getPointer(triId * 3), dir1.data(), 3 * sizeof(double) ); Eigen::Vector3d dir2 ( eVectors.col(1)(0), eVectors.col(1)(1), 0.0 ); dir2 = e_rot_T * dir2; ::memcpy(m_PrincipleDirection2->getPointer(triId * 3), dir2.data(), 3 * sizeof(double) ); } } } // End Loop over this triangle }
int main(int argc, char **args) { int res = ERR_SUCCESS; #ifdef WITH_PETSC PetscInitialize(&argc, &args, (char *) PETSC_NULL, PETSC_NULL); #endif set_verbose(false); if (argc < 2) error("Not enough parameters"); H1ShapesetLobattoHex shapeset; printf("* Loading mesh '%s'\n", args[1]); Mesh mesh; Mesh3DReader mesh_loader; if (!mesh_loader.load(args[1], &mesh)) error("Loading mesh file '%s'\n", args[1]); printf("* Setup space #1\n"); H1Space space1(&mesh, &shapeset); space1.set_bc_types(bc_types); order3_t o1(2, 2, 2); printf(" - Setting uniform order to (%d, %d, %d)\n", o1.x, o1.y, o1.z); space1.set_uniform_order(o1); printf("* Setup space #2\n"); H1Space space2(&mesh, &shapeset); space2.set_bc_types(bc_types); order3_t o2(4, 4, 4); printf(" - Setting uniform order to (%d, %d, %d)\n", o2.x, o2.y, o2.z); space2.set_uniform_order(o2); int ndofs = 0; ndofs += space1.assign_dofs(); ndofs += space2.assign_dofs(ndofs); printf(" - Number of DOFs: %d\n", ndofs); printf("* Calculating a solution\n"); #if defined WITH_UMFPACK UMFPackMatrix mat; UMFPackVector rhs; UMFPackLinearSolver solver(&mat, &rhs); #elif defined WITH_PARDISO PardisoMatrix mat; PardisoVector rhs; PardisoLinearSolver solver(&mat, &rhs); #elif defined WITH_PETSC PetscMatrix mat; PetscVector rhs; PetscLinearSolver solver(&mat, &rhs); #elif defined WITH_MUMPS MumpsMatrix mat; MumpsVector rhs; MumpsSolver solver(&mat, &rhs); #endif WeakForm wf(2); wf.add_matrix_form(0, 0, bilinear_form_1<double, scalar>, bilinear_form_1<ord_t, ord_t>, SYM); wf.add_vector_form(0, linear_form_1<double, scalar>, linear_form_1<ord_t, ord_t>); wf.add_matrix_form(1, 1, bilinear_form_2<double, scalar>, bilinear_form_2<ord_t, ord_t>, SYM); wf.add_vector_form(1, linear_form_2<double, scalar>, linear_form_2<ord_t, ord_t>); LinearProblem lp(&wf, Tuple<Space *>(&space1, &space2)); // assemble stiffness matrix Timer assemble_timer("Assembling stiffness matrix"); assemble_timer.start(); lp.assemble(&mat, &rhs); assemble_timer.stop(); // solve the stiffness matrix Timer solve_timer("Solving stiffness matrix"); solve_timer.start(); bool solved = solver.solve(); solve_timer.stop(); // output the measured values printf("%s: %s (%lf secs)\n", assemble_timer.get_name(), assemble_timer.get_human_time(), assemble_timer.get_seconds()); printf("%s: %s (%lf secs)\n", solve_timer.get_name(), solve_timer.get_human_time(), solve_timer.get_seconds()); if (solved) { // solution 1 Solution sln1(&mesh); sln1.set_coeff_vector(&space1, solver.get_solution()); ExactSolution esln1(&mesh, exact_sln_fn_1); // norm double h1_sln_norm1 = h1_norm(&sln1); double h1_err_norm1 = h1_error(&sln1, &esln1); printf(" - H1 solution norm: % le\n", h1_sln_norm1); printf(" - H1 error norm: % le\n", h1_err_norm1); double l2_sln_norm1 = l2_norm(&sln1); double l2_err_norm1 = l2_error(&sln1, &esln1); printf(" - L2 solution norm: % le\n", l2_sln_norm1); printf(" - L2 error norm: % le\n", l2_err_norm1); if (h1_err_norm1 > EPS || l2_err_norm1 > EPS) { // calculated solution is not enough precise res = ERR_FAILURE; } // solution 2 Solution sln2(&mesh); sln2.set_coeff_vector(&space2, solver.get_solution()); ExactSolution esln2(&mesh, exact_sln_fn_2); // norm double h1_sln_norm2 = h1_norm(&sln2); double h1_err_norm2 = h1_error(&sln2, &esln2); printf(" - H1 solution norm: % le\n", h1_sln_norm2); printf(" - H1 error norm: % le\n", h1_err_norm2); double l2_sln_norm2 = l2_norm(&sln2); double l2_err_norm2 = l2_error(&sln2, &esln2); printf(" - L2 solution norm: % le\n", l2_sln_norm2); printf(" - L2 error norm: % le\n", l2_err_norm2); if (h1_err_norm2 > EPS || l2_err_norm2 > EPS) { // calculated solution is not enough precise res = ERR_FAILURE; } #ifdef OUTPUT_DIR // output const char *of_name = OUTPUT_DIR "/solution.pos"; FILE *ofile = fopen(of_name, "w"); if (ofile != NULL) { GmshOutputEngine output(ofile); output.out(&sln1, "Uh_1"); output.out(&esln1, "U1"); output.out(&sln2, "Uh_2"); output.out(&esln2, "U2"); fclose(ofile); } else { warning("Can not open '%s' for writing.", of_name); } #endif } #ifdef WITH_PETSC mat.free(); rhs.free(); PetscFinalize(); #endif TRACE_END; return res; }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 2) error("Not enough parameters."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]); // Initialize the space 1. Ord3 o1(2, 2, 2); H1Space space1(&mesh, bc_types, NULL, o1); // Initialize the space 2. Ord3 o2(4, 4, 4); H1Space space2(&mesh, bc_types, NULL, o2); WeakForm wf(2); wf.add_matrix_form(0, 0, bilinear_form_1_1<double, scalar>, bilinear_form_1_1<Ord, Ord>, HERMES_SYM); wf.add_matrix_form(0, 1, bilinear_form_1_2<double, scalar>, bilinear_form_1_2<Ord, Ord>, HERMES_SYM); wf.add_vector_form(0, linear_form_1<double, scalar>, linear_form_1<Ord, Ord>); wf.add_matrix_form(1, 1, bilinear_form_2_2<double, scalar>, bilinear_form_2_2<Ord, Ord>, HERMES_SYM); wf.add_vector_form(1, linear_form_2<double, scalar>, linear_form_2<Ord, Ord>); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, Tuple<Space *>(&space1, &space2), is_linear); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the linear problem. info("Assembling (ndof: %d).", Space::get_num_dofs(Tuple<Space *>(&space1, &space2))); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving."); Solution sln1(&mesh); Solution sln2(&mesh); if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), Tuple<Space *>(&space1, &space2), Tuple<Solution *>(&sln1, &sln2)); else error ("Matrix solver failed.\n"); ExactSolution ex_sln1(&mesh, exact_sln_fn_1); ExactSolution ex_sln2(&mesh, exact_sln_fn_2); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(Tuple<Space *>(&space1, &space2), Tuple<ProjNormType>(HERMES_H1_NORM, HERMES_H1_NORM)); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(Tuple<Solution *>(&sln1, &sln2), Tuple<Solution *>(&ex_sln1, &ex_sln2), solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; delete adaptivity; // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char **args) { int res = ERR_SUCCESS; #ifdef WITH_PETSC PetscInitialize(&argc, &args, (char *) PETSC_NULL, PETSC_NULL); #endif if (argc < 2) error("Not enough parameters."); printf("* Loading mesh '%s'\n", args[1]); Mesh mesh1; H3DReader mesh_loader; if (!mesh_loader.load(args[1], &mesh1)) error("Loading mesh file '%s'\n", args[1]); #if defined RHS2 Ord3 order(P_INIT_X, P_INIT_Y, P_INIT_Z); printf(" - Setting uniform order to (%d, %d, %d)\n", order.x, order.y, order.z); // Create an H1 space with default shapeset. printf("* Setting the space up\n"); H1Space space(&mesh1, bc_types, essential_bc_values, order); int ndofs = space.assign_dofs(); printf(" - Number of DOFs: %d\n", ndofs); printf("* Calculating a solution\n"); // duplicate the mesh Mesh mesh2; mesh2.copy(mesh1); // do some changes mesh2.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); mesh2.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); Solution fsln(&mesh2); fsln.set_const(-6.0); #else // duplicate the mesh Mesh mesh2; mesh2.copy(mesh1); Mesh mesh3; mesh3.copy(mesh1); // change meshes mesh1.refine_all_elements(H3D_REFT_HEX_X); mesh2.refine_all_elements(H3D_REFT_HEX_Y); mesh3.refine_all_elements(H3D_REFT_HEX_Z); printf("* Setup spaces\n"); Ord3 o1(2, 2, 2); printf(" - Setting uniform order to (%d, %d, %d)\n", o1.x, o1.y, o1.z); H1Space space1(&mesh1, bc_types_1, essential_bc_values_1, o1); Ord3 o2(2, 2, 2); printf(" - Setting uniform order to (%d, %d, %d)\n", o2.x, o2.y, o2.z); H1Space space2(&mesh2, bc_types_2, essential_bc_values_2, o2); Ord3 o3(1, 1, 1); printf(" - Setting uniform order to (%d, %d, %d)\n", o3.x, o3.y, o3.z); H1Space space3(&mesh3, bc_types_3, essential_bc_values_3, o3); int ndofs = 0; ndofs += space1.assign_dofs(); ndofs += space2.assign_dofs(ndofs); ndofs += space3.assign_dofs(ndofs); printf(" - Number of DOFs: %d\n", ndofs); #endif #if defined WITH_UMFPACK MatrixSolverType matrix_solver = SOLVER_UMFPACK; #elif defined WITH_PETSC MatrixSolverType matrix_solver = SOLVER_PETSC; #elif defined WITH_MUMPS MatrixSolverType matrix_solver = SOLVER_MUMPS; #endif #ifdef RHS2 WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY_INT, &fsln); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); #elif defined SYS3 WeakForm wf(3); wf.add_matrix_form(0, 0, biform_1_1<double, scalar>, biform_1_1<Ord, Ord>, HERMES_SYM); wf.add_matrix_form(0, 1, biform_1_2<double, scalar>, biform_1_2<Ord, Ord>, HERMES_NONSYM); wf.add_vector_form(0, liform_1<double, scalar>, liform_1<Ord, Ord>); wf.add_matrix_form(1, 1, biform_2_2<double, scalar>, biform_2_2<Ord, Ord>, HERMES_SYM); wf.add_matrix_form(1, 2, biform_2_3<double, scalar>, biform_2_3<Ord, Ord>, HERMES_NONSYM); wf.add_vector_form(1, liform_2<double, scalar>, liform_2<Ord, Ord>); wf.add_matrix_form(2, 2, biform_3_3<double, scalar>, biform_3_3<Ord, Ord>, HERMES_SYM); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, Hermes::vector<Space *>(&space1, &space2, &space3), is_linear); #endif // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble stiffness matrix and load vector. dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving the linear problem."); bool solved = solver->solve(); // Time measurement. cpu_time.tick(); // Print timing information. info("Solution and mesh with polynomial orders saved. Total running time: %g s", cpu_time.accumulated()); // Time measurement. TimePeriod sln_time; sln_time.tick(); if (solved) { #ifdef RHS2 // Solve the linear system. If successful, obtain the solution. info("Solving the linear problem."); Solution sln(&mesh1); Solution::vector_to_solution(solver->get_solution(), &space, &sln); // Set exact solution. ExactSolution ex_sln(&mesh1, exact_solution); // Norm. double h1_sln_norm = h1_norm(&sln); double h1_err_norm = h1_error(&sln, &ex_sln); printf(" - H1 solution norm: % le\n", h1_sln_norm); printf(" - H1 error norm: % le\n", h1_err_norm); double l2_sln_norm = l2_norm(&sln); double l2_err_norm = l2_error(&sln, &ex_sln); printf(" - L2 solution norm: % le\n", l2_sln_norm); printf(" - L2 error norm: % le\n", l2_err_norm); if (h1_err_norm > EPS || l2_err_norm > EPS) { // Calculated solution is not enough precise. res = ERR_FAILURE; } #elif defined SYS3 // Solution 1. Solution sln1(&mesh1); Solution sln2(&mesh2); Solution sln3(&mesh3); Solution::vector_to_solution(solver->get_solution(), &space1, &sln1); Solution::vector_to_solution(solver->get_solution(), &space2, &sln2); Solution::vector_to_solution(solver->get_solution(), &space3, &sln3); ExactSolution esln1(&mesh1, exact_sln_fn_1); ExactSolution esln2(&mesh2, exact_sln_fn_2); ExactSolution esln3(&mesh3, exact_sln_fn_3); // Norm. double h1_err_norm1 = h1_error(&sln1, &esln1); double h1_err_norm2 = h1_error(&sln2, &esln2); double h1_err_norm3 = h1_error(&sln3, &esln3); double l2_err_norm1 = l2_error(&sln1, &esln1); double l2_err_norm2 = l2_error(&sln2, &esln2); double l2_err_norm3 = l2_error(&sln3, &esln3); printf(" - H1 error norm: % le\n", h1_err_norm1); printf(" - L2 error norm: % le\n", l2_err_norm1); if (h1_err_norm1 > EPS || l2_err_norm1 > EPS) { // Calculated solution is not enough precise. res = ERR_FAILURE; } printf(" - H1 error norm: % le\n", h1_err_norm2); printf(" - L2 error norm: % le\n", l2_err_norm2); if (h1_err_norm2 > EPS || l2_err_norm2 > EPS) { // Calculated solution is not enough precise. res = ERR_FAILURE; } printf(" - H1 error norm: % le\n", h1_err_norm3); printf(" - L2 error norm: % le\n", l2_err_norm3); if (h1_err_norm3 > EPS || l2_err_norm3 > EPS) { // Calculated solution is not enough precise. res = ERR_FAILURE; } #endif #ifdef RHS2 out_fn_vtk(&sln, "solution"); #elif defined SYS3 out_fn_vtk(&sln1, "sln1"); out_fn_vtk(&sln2, "sln2"); out_fn_vtk(&sln3, "sln3"); #endif } else res = ERR_FAILURE; // Print timing information. info("Solution and mesh with polynomial orders saved. Total running time: %g s", sln_time.accumulated()); // Clean up. delete matrix; delete rhs; delete solver; return res; }