//---------------------------------------------------------------------------- fei::SharedPtr<fei::LinearSystem> fei::LinearSystem::Factory::createLinearSystem(fei::SharedPtr<fei::MatrixGraph>& matrixGraph) { fei::SharedPtr<fei::LinearSystem> linsys(new snl_fei::LinearSystem_General(matrixGraph)); return(linsys); }
int main(int argc, char* argv[]) { // load the mesh file Mesh mesh; mesh.load("domain.mesh"); // a-priori mesh refinements mesh.refine_all_elements(); mesh.refine_towards_boundary(5, 4, false); mesh.refine_towards_boundary(1, 4); mesh.refine_towards_boundary(3, 4); // initialize the shapeset and the cache H1ShapesetBeuchler shapeset; PrecalcShapeset pss(&shapeset); // spaces for velocities and pressure H1Space xvel(&mesh, &shapeset); H1Space yvel(&mesh, &shapeset); H1Space press(&mesh, &shapeset); // initialize boundary conditions xvel.set_bc_types(xvel_bc_type); xvel.set_bc_values(xvel_bc_value); yvel.set_bc_types(yvel_bc_type); press.set_bc_types(press_bc_type); // set velocity and pressure polynomial degrees xvel.set_uniform_order(P_INIT_VEL); yvel.set_uniform_order(P_INIT_VEL); press.set_uniform_order(P_INIT_PRESSURE); // assign degrees of freedom int ndofs = 0; ndofs += xvel.assign_dofs(ndofs); ndofs += yvel.assign_dofs(ndofs); ndofs += press.assign_dofs(ndofs); // velocities from the previous time step and for the Newton's iteration Solution xprev, yprev, xiter, yiter, piter; xprev.set_zero(&mesh); yprev.set_zero(&mesh); xiter.set_zero(&mesh); yiter.set_zero(&mesh); piter.set_zero(&mesh); // set up weak formulation WeakForm wf(3); if (NEWTON_ON) { wf.add_biform(0, 0, callback(bilinear_form_sym_0_0_1_1), SYM); wf.add_biform(0, 0, callback(newton_bilinear_form_unsym_0_0), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(0, 1, callback(newton_bilinear_form_unsym_0_1), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(0, 2, callback(bilinear_form_unsym_0_2), ANTISYM); wf.add_biform(1, 0, callback(newton_bilinear_form_unsym_1_0), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(1, 1, callback(bilinear_form_sym_0_0_1_1), SYM); wf.add_biform(1, 1, callback(newton_bilinear_form_unsym_1_1), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(1, 2, callback(bilinear_form_unsym_1_2), ANTISYM); wf.add_liform(0, callback(newton_F_0), ANY, 5, &xprev, &yprev, &xiter, &yiter, &piter); wf.add_liform(1, callback(newton_F_1), ANY, 5, &xprev, &yprev, &xiter, &yiter, &piter); wf.add_liform(2, callback(newton_F_2), ANY, 2, &xiter, &yiter); } else { wf.add_biform(0, 0, callback(bilinear_form_sym_0_0_1_1), SYM); wf.add_biform(0, 0, callback(simple_bilinear_form_unsym_0_0_1_1), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(1, 1, callback(bilinear_form_sym_0_0_1_1), SYM); wf.add_biform(1, 1, callback(simple_bilinear_form_unsym_0_0_1_1), UNSYM, ANY, 2, &xprev, &yprev); wf.add_biform(0, 2, callback(bilinear_form_unsym_0_2), ANTISYM); wf.add_biform(1, 2, callback(bilinear_form_unsym_1_2), ANTISYM); wf.add_liform(0, callback(simple_linear_form), ANY, 1, &xprev); wf.add_liform(1, callback(simple_linear_form), ANY, 1, &yprev); } // visualization VectorView vview("velocity [m/s]", 0, 0, 1500, 470); ScalarView pview("pressure [Pa]", 0, 530, 1500, 470); vview.set_min_max_range(0, 1.6); vview.fix_scale_width(80); //pview.set_min_max_range(-0.9, 1.0); pview.fix_scale_width(80); pview.show_mesh(true); // matrix solver UmfpackSolver umfpack; // linear system LinSystem linsys(&wf, &umfpack); // nonlinear system NonlinSystem nonsys(&wf, &umfpack); if (NEWTON_ON) { // set up the nonlinear system nonsys.set_spaces(3, &xvel, &yvel, &press); nonsys.set_pss(1, &pss); } else { // set up the linear system linsys.set_spaces(3, &xvel, &yvel, &press); linsys.set_pss(1, &pss); } // main loop char title[100]; int num_time_steps = FINAL_TIME / TAU; for (int i = 1; i <= num_time_steps; i++) { TIME += TAU; info("\n---- Time step %d, time = %g -----------------------------------", i, TIME); // this is needed to update the time-dependent boundary conditions ndofs = 0; ndofs += xvel.assign_dofs(ndofs); ndofs += yvel.assign_dofs(ndofs); ndofs += press.assign_dofs(ndofs); if (NEWTON_ON) { Solution xsln, ysln, psln; int it = 1; double res_l2_norm; do { info("\n---- Time step %d, Newton iter %d ---------------------------------\n", i, it++); // assemble and solve nonsys.assemble(); nonsys.solve(3, &xsln, &ysln, &psln); res_l2_norm = nonsys.get_residuum_l2_norm(); info("Residuum L2 norm: %g\n", res_l2_norm); // want to see Newtons iterations //sprintf(title, "Time level %d, Newton iteration %d", i, it-1); //vview.set_title(title); //vview.show(&xsln, &ysln, EPS_LOW); //pview.show(&psln); //pview.wait_for_keypress(); xiter = xsln; yiter = ysln; piter = psln; } while (res_l2_norm > NEWTON_TOL); // visualization at the end of the time step sprintf(title, "Velocity, time %g", TIME); vview.set_title(title); vview.show(&xprev, &yprev, EPS_LOW); sprintf(title, "Pressure, time %g", TIME); pview.set_title(title); pview.show(&piter); // copying result of the Newton's iteration into xprev, yprev xprev.copy(&xiter); yprev.copy(&yiter); } else { // assemble and solve Solution xsln, ysln, psln; linsys.assemble(); linsys.solve(3, &xsln, &ysln, &psln); // visualization sprintf(title, "Velocity, time %g", TIME); vview.set_title(title); vview.show(&xsln, &ysln, EPS_LOW); sprintf(title, "Pressure, time %g", TIME); pview.set_title(title); pview.show(&psln); //pview.wait_for_keypress(); xprev = xsln; yprev = ysln; } // uncomment one of the following lines to generate a series of video frames //vview.save_numbered_screenshot("velocity%03d.bmp", i, true); //pview.save_numbered_screenshot("pressure%03d.bmp", i, true); // the frames can then be converted to a video file with the command // mencoder "mf://velocity*.bmp" -mf fps=20 -o velocity.avi -ovc lavc -lavcopts vcodec=mpeg4 } // wait for keyboard or mouse input View::wait("Waiting for keyboard or mouse input."); return 0; }