int main (int argc, char* argv[]) { // Load the mesh. Mesh basemesh; ExodusIIReader mesh_loader; if (!mesh_loader.load("coarse_mesh_full.e", &basemesh)) error("Loading mesh file '%s' failed.\n", "coarse_mesh_full.e"); Mesh C_mesh, phi_mesh; C_mesh.copy(basemesh); phi_mesh.copy(basemesh); H1Space C_space(&C_mesh, bc_types_C, essential_bc_values_C, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); H1Space phi_space(MULTIMESH ? &phi_mesh : &C_mesh, bc_types_phi, essential_bc_values_phi, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); Solution C_prev_time(&C_mesh); C_prev_time.set_const(C0); Solution phi_prev_time(MULTIMESH ? &phi_mesh : &C_mesh); phi_prev_time.set_const(0.0); WeakForm wf(2); // Add the bilinear and linear forms. if (TIME_DISCR == 1) { // Implicit Euler. wf.add_matrix_form(0, 0, callback(J_euler_DFcDYc), HERMES_NONSYM); wf.add_matrix_form(0, 1, callback(J_euler_DFcDYphi), HERMES_NONSYM); wf.add_matrix_form(1, 0, callback(J_euler_DFphiDYc), HERMES_NONSYM); wf.add_matrix_form(1, 1, callback(J_euler_DFphiDYphi), HERMES_NONSYM); wf.add_vector_form(0, callback(Fc_euler), HERMES_ANY_INT, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); wf.add_vector_form(1, callback(Fphi_euler), HERMES_ANY, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); } else { wf.add_matrix_form(0, 0, callback(J_cranic_DFcDYc), HERMES_NONSYM); wf.add_matrix_form(0, 1, callback(J_cranic_DFcDYphi), HERMES_NONSYM); wf.add_matrix_form(1, 0, callback(J_cranic_DFphiDYc), HERMES_NONSYM); wf.add_matrix_form(1, 1, callback(J_cranic_DFphiDYphi), HERMES_NONSYM); wf.add_vector_form(0, callback(Fc_cranic), HERMES_ANY, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); wf.add_vector_form(1, callback(Fphi_cranic), HERMES_ANY); } int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&C_space, &phi_space)); Solution C_sln(C_space.get_mesh()); Solution phi_sln(phi_space.get_mesh()); info("Projecting initial condition to obtain initial vector for the Newton's method."); scalar* coeff_vec_coarse = new scalar[ndof]; OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<MeshFunction *>(&C_prev_time, &phi_prev_time), coeff_vec_coarse, matrix_solver); bool is_linear = false; DiscreteProblem dp_coarse(&wf, Hermes::vector<Space *>(&C_space, &phi_space), is_linear); //Solution::vector_to_solutions(coeff_vec_coarse, dp_coarse.get_spaces(), Hermes::vector<Solution *>(&C_sln, &phi_sln), NULL); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); info("Solving on coarse mesh:"); bool verbose = true; if (!solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); info("Solved!"); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solutions(coeff_vec_coarse, Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<Solution *>(&C_sln, &phi_sln)); out_fn_vtk(&C_sln,"C_init_sln"); out_fn_vtk(&phi_sln,"phi_init_sln"); //out_fn_vtk(&sln, "sln", ts); Solution *C_ref_sln, *phi_ref_sln; PidTimestepController pid(T_FINAL, false, INIT_TAU); TAU = pid.timestep; info("Starting time iteration with the step %g", *TAU); do { pid.begin_step(); if (pid.get_timestep_number() > 1 && pid.get_timestep_number() % UNREF_FREQ == 0) { info("Global mesh derefinement."); C_mesh.copy(basemesh); if (MULTIMESH) { phi_mesh.copy(basemesh); } C_space.set_uniform_order(Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); phi_space.set_uniform_order(Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); } bool done = false; int as = 1; double err_est; do { info("Time step %d, adaptivity step %d:", pid.get_timestep_number(), as); // Construct globally refined reference mesh // and setup reference space. int order_increase = 1; Hermes::vector<Space *>* ref_spaces = construct_refined_spaces(Hermes::vector<Space *>(&C_space, &phi_space), order_increase); scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (as == 1 && pid.get_timestep_number() == 1) { info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&C_sln, &phi_sln), coeff_vec, matrix_solver); } else { info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(C_ref_sln, phi_ref_sln), coeff_vec, matrix_solver); } if (as > 1) { // Now deallocate the previous mesh info("Deallocating the previous mesh"); //delete C_ref_sln->get_mesh(); //delete phi_ref_sln->get_mesh(); //delete C_ref_sln; //delete phi_ref_sln; } /*TODO TEMP */ if (pid.get_timestep_number() > 1) { delete C_ref_sln; delete phi_ref_sln; } info("Solving on fine mesh:"); if (!solve_newton(coeff_vec, dp, solver, matrix, rhs, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Store the result in ref_sln. C_ref_sln = new Solution(ref_spaces->at(0)->get_mesh()); phi_ref_sln = new Solution(ref_spaces->at(1)->get_mesh()); Solution::vector_to_solutions(coeff_vec, *ref_spaces, Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln)); // Projecting reference solution onto the coarse mesh info("Projecting fine mesh solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln), Hermes::vector<Solution *>(&C_sln, &phi_sln), matrix_solver); info("Calculating error estimate."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<ProjNormType> (HERMES_H1_NORM, HERMES_H1_NORM)); Hermes::vector<double> err_est_rel; bool solutions_for_adapt = true; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&C_sln, &phi_sln), Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln), solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS, &err_est_rel) * 100; // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d", C_space.get_num_dofs(), (*ref_spaces)[0]->get_num_dofs()); info("err_est_rel[0]: %g%%", err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d", phi_space.get_num_dofs(), (*ref_spaces)[1]->get_num_dofs()); info("err_est_rel[1]: %g%%", err_est_rel[1]*100); // Report results. info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel: %g%%", Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space)), Space::get_num_dofs(*ref_spaces), err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); adaptivity->adapt(THRESHOLD); info("Adapted..."); if (Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } //as++; delete solver; delete matrix; delete rhs; delete ref_spaces; delete dp; delete[] coeff_vec; done = true; } while (!done); out_fn_vtk(C_ref_sln,"C_sln", pid.get_timestep_number()); out_fn_vtk(phi_ref_sln,"phi_sln", pid.get_timestep_number()); pid.end_step(Hermes::vector<Solution*> (C_ref_sln, phi_ref_sln), Hermes::vector<Solution*> (&C_prev_time, &phi_prev_time)); // Copy last reference solution into sln_prev_time. C_prev_time.copy(C_ref_sln); phi_prev_time.copy(phi_ref_sln); } while (pid.has_next()); //View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<std::complex<double> > bc(Hermes::vector<std::string>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT), std::complex<double>(0.0, 0.0)); EssentialBCs<std::complex<double> > bcs(&bc); // Create an H1 space. H1Space<std::complex<double> >* phi_space = new H1Space<std::complex<double> >(&mesh, &bcs, P_INIT); H1Space<std::complex<double> >* psi_space = new H1Space<std::complex<double> >(&mesh, &bcs, P_INIT); int ndof = Space<std::complex<double> >::get_num_dofs(Hermes::vector<Space<std::complex<double> > *>(phi_space, psi_space)); info("ndof = %d.", ndof); // Initialize previous time level solutions. ConstantSolution<std::complex<double> > phi_prev_time(&mesh, init_cond_phi); ConstantSolution<std::complex<double> > psi_prev_time(&mesh, init_cond_psi); // Initialize the weak formulation. WeakForm<std::complex<double> > wf(2); wf.add_matrix_form(0, 0, callback(biform_euler_0_0)); wf.add_matrix_form(0, 1, callback(biform_euler_0_1)); wf.add_matrix_form(1, 0, callback(biform_euler_1_0)); wf.add_matrix_form(1, 1, callback(biform_euler_1_1)); wf.add_vector_form(0, callback(liform_euler_0), HERMES_ANY, &phi_prev_time); wf.add_vector_form(1, callback(liform_euler_1), HERMES_ANY, &psi_prev_time); // Initialize views. ScalarView view("Psi", new WinGeom(0, 0, 600, 500)); view.fix_scale_width(80); // Time stepping loop: int nstep = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= nstep; ts++) { info("Time step %d:", ts); info("Solving linear system."); // Initialize the FE problem. bool is_linear = true; DiscreteProblem<std::complex<double> > dp(&wf, Hermes::vector<Space<double>* *>(phi_space, psi_space), is_linear); SparseMatrix<std::complex<double> >* matrix = create_matrix<std::complex<double> >(matrix_solver_type); Vector<std::complex<double> >* rhs = create_vector<std::complex<double> >(matrix_solver_type); LinearSolver<std::complex<double> >* solver = create_linear_solver<std::complex<double> >(matrix_solver_type, matrix, rhs); // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution<std::complex<double> >::vector_to_solutions(solver->get_sln_vector(), Hermes::vector<Space<std::complex<double> >*>(phi_space, psi_space), Hermes::vector<Solution<std::complex<double> > *>(&phi_prev_time, &psi_prev_time)); else error ("Matrix solver failed.\n"); // Show the new time level solution. char title[100]; sprintf(title, "Time step %d", ts); view.set_title(title); view.show(&psi_prev_time); } // Wait for all views to be closed. View::wait(); return 0; }