void create_stage_wf(double current_time, double time_step, ButcherTable* bt, DiscreteProblem* dp, WeakForm* stage_wf_left, WeakForm* stage_wf_right) { // First let's do the mass matrix (only one block ndof times ndof). WeakForm::MatrixFormVol mfv_00; mfv_00.i = 0; mfv_00.j = 0; mfv_00.sym = HERMES_SYM; mfv_00.area = HERMES_ANY; mfv_00.fn = l2_form<double, scalar>; mfv_00.ord = l2_form<Ord, Ord>; mfv_00.ext = Hermes::vector<MeshFunction*> (); mfv_00.scaling_factor = 1.0; mfv_00.u_ext_offset = 0; stage_wf_left->add_matrix_form(&mfv_00); // In the rest we will take the stationary jacobian and residual forms // (right-hand side) and use them to create a block Jacobian matrix of // size (num_stages*ndof times num_stages*ndof) and a block residual // vector of length num_stages*ndof. // Number of stages. int num_stages = bt->get_size(); // Original weak formulation. WeakForm* wf = dp->get_weak_formulation(); // Extract mesh from (the first space of) the original discrete problem. Mesh* mesh = dp->get_space(0)->get_mesh(); // Create constant Solutions to represent the stage times, // stage_time = current_time + c_i*time_step. // (Temporary workaround. these should be passed as numbers.) Solution** stage_time_sol = new Solution*[num_stages]; for (int i = 0; i < num_stages; i++) { stage_time_sol[i] = new Solution(mesh); stage_time_sol[i]->set_const(mesh, current_time + bt->get_C(i)*time_step); } // Extracting volume and surface matrix and vector forms from the // original weak formulation. if (wf->get_neq() != 1) error("wf->neq != 1 not implemented yet."); Hermes::vector<WeakForm::MatrixFormVol> mfvol_base = wf->get_mfvol(); Hermes::vector<WeakForm::MatrixFormSurf> mfsurf_base = wf->get_mfsurf(); Hermes::vector<WeakForm::VectorFormVol> vfvol_base = wf->get_vfvol(); Hermes::vector<WeakForm::VectorFormSurf> vfsurf_base = wf->get_vfsurf(); // Duplicate matrix volume forms, scale them according // to the Butcher's table, enhance them with additional // external solutions, and anter them as blocks to the // new stage Jacobian. for (unsigned int m = 0; m < mfvol_base.size(); m++) { WeakForm::MatrixFormVol mfv_base = mfvol_base[m]; for (int i = 0; i < num_stages; i++) { for (int j = 0; j < num_stages; j++) { WeakForm::MatrixFormVol mfv_ij; mfv_ij.i = i; mfv_ij.j = j; mfv_ij.sym = mfv_base.sym; mfv_ij.area = mfv_base.area; mfv_ij.fn = mfv_base.fn; mfv_ij.ord = mfv_base.ord; std::copy(mfv_base.ext.begin(), mfv_base.ext.end(), mfv_ij.ext.begin()); mfv_ij.scaling_factor = -time_step * bt->get_A(i, j); // Set offset for u_ext[] external solutions. mfv_ij.u_ext_offset = i; // Add stage_time_sol[i] as an external function to the form. mfv_ij.ext.push_back(stage_time_sol[i]); // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_matrix_form(&mfv_ij); } } } // Duplicate matrix surface forms, enhance them with // additional external solutions, and anter them as // blocks of the stage Jacobian. for (unsigned int m = 0; m < mfsurf_base.size(); m++) { WeakForm::MatrixFormSurf mfs_base = mfsurf_base[m]; for (int i = 0; i < num_stages; i++) { for (int j = 0; j < num_stages; j++) { WeakForm::MatrixFormSurf mfs_ij; mfs_ij.i = i; mfs_ij.j = j; mfs_ij.area = mfs_base.area; mfs_ij.fn = mfs_base.fn; mfs_ij.ord = mfs_base.ord; std::copy(mfs_base.ext.begin(), mfs_base.ext.end(), mfs_ij.ext.begin()); mfs_ij.scaling_factor = -time_step * bt->get_A(i, j); // Set offset for u_ext[] external solutions. mfs_ij.u_ext_offset = i; // Add stage_time_sol[i] as an external function to the form. mfs_ij.ext.push_back(stage_time_sol[i]); // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_matrix_form_surf(&mfs_ij); } } } // Duplicate vector volume forms, enhance them with // additional external solutions, and anter them as // blocks of the stage residual. for (unsigned int m = 0; m < vfvol_base.size(); m++) { WeakForm::VectorFormVol vfv_base = vfvol_base[m]; for (int i = 0; i < num_stages; i++) { WeakForm::VectorFormVol vfv_i; vfv_i.i = i; vfv_i.area = vfv_base.area; vfv_i.fn = vfv_base.fn; vfv_i.ord = vfv_base.ord; std::copy(vfv_base.ext.begin(), vfv_base.ext.end(), vfv_i.ext.begin()); vfv_i.scaling_factor = -1.0; // Set offset for u_ext[] external solutions. vfv_i.u_ext_offset = i; // Add stage_time_sol[i] as an external function to the form. vfv_i.ext.push_back(stage_time_sol[i]); // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_vector_form(&vfv_i); } } // Duplicate vector surface forms, enhance them with // additional external solutions, and anter them as // blocks of the stage residual. for (unsigned int m = 0; m < vfsurf_base.size(); m++) { WeakForm::VectorFormSurf vfs_base = vfsurf_base[m]; for (int i = 0; i < num_stages; i++) { WeakForm::VectorFormSurf vfs_i; vfs_i.i = i; vfs_i.area = vfs_base.area; vfs_i.fn = vfs_base.fn; vfs_i.ord = vfs_base.ord; std::copy(vfs_base.ext.begin(), vfs_base.ext.end(), vfs_i.ext.begin()); vfs_i.scaling_factor = -1.0; // Set offset for u_ext[] external solutions. vfs_i.u_ext_offset = i; // Add stage_time_sol[i] as an external function to the form. vfs_i.ext.push_back(stage_time_sol[i]); // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_vector_form_surf(&vfs_i); } } }
void create_stage_wf(double current_time, double time_step, ButcherTable* bt, DiscreteProblem* dp, WeakForm* stage_wf_left, WeakForm* stage_wf_right, Solution** stage_time_sol) { // First let's do the mass matrix (only one block ndof times ndof). WeakForm::MatrixFormVol mfv_00; mfv_00.i = 0; mfv_00.j = 0; mfv_00.sym = HERMES_SYM; mfv_00.area = HERMES_ANY; mfv_00.fn = l2_form<double, scalar>; mfv_00.ord = l2_form<Ord, Ord>; mfv_00.ext = Hermes::vector<MeshFunction*> (); mfv_00.scaling_factor = 1.0; mfv_00.u_ext_offset = 0; mfv_00.adapt_eval = false; mfv_00.adapt_order_increase = -1; mfv_00.adapt_rel_error_tol = -1; stage_wf_left->add_matrix_form_internal(&mfv_00); // In the rest we will take the stationary jacobian and residual forms // (right-hand side) and use them to create a block Jacobian matrix of // size (num_stages*ndof times num_stages*ndof) and a block residual // vector of length num_stages*ndof. // Number of stages. int num_stages = bt->get_size(); // Original weak formulation. WeakForm* wf = dp->get_weak_formulation(); // Extract mesh from (the first space of) the original discrete problem. Mesh* mesh = dp->get_space(0)->get_mesh(); // Create constant Solutions to represent the stage times, // stage_time = current_time + c_i*time_step. // WARNING - THIS IS A TEMPORARY HACK. THE STAGE TIME SHOULD BE ENTERED // AS A NUMBER, NOT IN THIS WAY. IT WILL BE ADDED AFTER EXISTING EXTERNAL // SOLUTIONS IN ExtData. for (int i = 0; i < num_stages; i++) { stage_time_sol[i] = new Solution(mesh); stage_time_sol[i]->set_const(mesh, current_time + bt->get_C(i)*time_step); } // Extracting volume and surface matrix and vector forms from the // original weak formulation. if (wf->get_neq() != 1) error("wf->neq != 1 not implemented yet."); Hermes::vector<WeakForm::MatrixFormVol> mfvol_base = wf->get_mfvol(); Hermes::vector<WeakForm::MatrixFormSurf> mfsurf_base = wf->get_mfsurf(); Hermes::vector<WeakForm::VectorFormVol> vfvol_base = wf->get_vfvol(); Hermes::vector<WeakForm::VectorFormSurf> vfsurf_base = wf->get_vfsurf(); // Duplicate matrix volume forms, scale them according // to the Butcher's table, enhance them with additional // external solutions, and anter them as blocks to the // new stage Jacobian. for (unsigned int m = 0; m < mfvol_base.size(); m++) { WeakForm::MatrixFormVol mfv_base = mfvol_base[m]; for (int i = 0; i < num_stages; i++) { for (int j = 0; j < num_stages; j++) { WeakForm::MatrixFormVol mfv_ij; mfv_ij.i = i; mfv_ij.j = j; mfv_ij.sym = mfv_base.sym; mfv_ij.area = mfv_base.area; mfv_ij.fn = mfv_base.fn; mfv_ij.ord = mfv_base.ord; mfv_ij.scaling_factor = -time_step * bt->get_A(i, j); // Duplicate external solutions. // THIS WAS WRONG, ONE CANNOT COPY INTO AN EMPTY STD::VECTOR: // std::copy(mfv_base.ext.begin(), mfv_base.ext.end(), mfv_ij.ext.begin()); for (unsigned int f_idx = 0; f_idx < mfv_base.ext.size(); f_idx++) mfv_ij.ext.push_back(mfv_base.ext[f_idx]); // Add stage_time_sol[i] as an external function to the form. mfv_ij.ext.push_back(stage_time_sol[i]); // Set offset for u_ext[] external solutions. mfv_ij.u_ext_offset = i; // This form will not be integrated adaptively. mfv_ij.adapt_eval = false; mfv_ij.adapt_order_increase = -1; mfv_ij.adapt_rel_error_tol = -1; // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_matrix_form_internal(&mfv_ij); } } } // Duplicate matrix surface forms, enhance them with // additional external solutions, and anter them as // blocks of the stage Jacobian. for (unsigned int m = 0; m < mfsurf_base.size(); m++) { WeakForm::MatrixFormSurf mfs_base = mfsurf_base[m]; for (int i = 0; i < num_stages; i++) { for (int j = 0; j < num_stages; j++) { WeakForm::MatrixFormSurf mfs_ij; mfs_ij.i = i; mfs_ij.j = j; mfs_ij.area = mfs_base.area; mfs_ij.fn = mfs_base.fn; mfs_ij.ord = mfs_base.ord; mfs_ij.scaling_factor = -time_step * bt->get_A(i, j); // Duplicate external solutions. // THIS WAS WRONG, ONE CANNOT COPY INTO AN EMPTY STD::VECTOR: // std::copy(mfs_base.ext.begin(), mfs_base.ext.end(), mfs_ij.ext.begin()); for (unsigned int f_idx = 0; f_idx < mfs_base.ext.size(); f_idx++) mfs_ij.ext.push_back(mfs_base.ext[f_idx]); // Add stage_time_sol[i] as an external function to the form. mfs_ij.ext.push_back(stage_time_sol[i]); // Set offset for u_ext[] external solutions. mfs_ij.u_ext_offset = i; // This form will not be integrated adaptively. mfs_ij.adapt_eval = false; mfs_ij.adapt_order_increase = -1; mfs_ij.adapt_rel_error_tol = -1; // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_matrix_form_surf_internal(&mfs_ij); } } } // Duplicate vector volume forms, enhance them with // additional external solutions, and anter them as // blocks of the stage residual. for (unsigned int m = 0; m < vfvol_base.size(); m++) { WeakForm::VectorFormVol vfv_base = vfvol_base[m]; for (int i = 0; i < num_stages; i++) { WeakForm::VectorFormVol vfv_i; vfv_i.i = i; vfv_i.area = vfv_base.area; vfv_i.fn = vfv_base.fn; vfv_i.ord = vfv_base.ord; vfv_i.scaling_factor = -1.0; // Duplicate external solutions. // THIS WAS WRONG, ONE CANNOT COPY INTO AN EMPTY STD::VECTOR: // std::copy(vfv_base.ext.begin(), vfv_base.ext.end(), vfv_ij.ext.begin()); for (unsigned int f_idx = 0; f_idx < vfv_base.ext.size(); f_idx++) vfv_i.ext.push_back(vfv_base.ext[f_idx]); // Add stage_time_sol[i] as an external function to the form. vfv_i.ext.push_back(stage_time_sol[i]); // Set offset for u_ext[] external solutions. vfv_i.u_ext_offset = i; // This form will not be integrated adaptively. vfv_i.adapt_eval = false; vfv_i.adapt_order_increase = -1; vfv_i.adapt_rel_error_tol = -1; // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_vector_form_internal(&vfv_i); } } // Duplicate vector surface forms, enhance them with // additional external solutions, and anter them as // blocks of the stage residual. for (unsigned int m = 0; m < vfsurf_base.size(); m++) { WeakForm::VectorFormSurf vfs_base = vfsurf_base[m]; for (int i = 0; i < num_stages; i++) { WeakForm::VectorFormSurf vfs_i; vfs_i.i = i; vfs_i.area = vfs_base.area; vfs_i.fn = vfs_base.fn; vfs_i.ord = vfs_base.ord; vfs_i.scaling_factor = -1.0; // Duplicate external solutions. // THIS WAS WRONG, ONE CANNOT COPY INTO AN EMPTY STD::VECTOR: // std::copy(vfv_base.ext.begin(), vfv_base.ext.end(), vfv_ij.ext.begin()); for (unsigned int f_idx = 0; f_idx < vfs_base.ext.size(); f_idx++) vfs_i.ext.push_back(vfs_base.ext[f_idx]); // Add stage_time_sol[i] as an external function to the form. vfs_i.ext.push_back(stage_time_sol[i]); // Set offset for u_ext[] external solutions. vfs_i.u_ext_offset = i; // This form will not be integrated adaptively. vfs_i.adapt_eval = false; vfs_i.adapt_order_increase = -1; vfs_i.adapt_rel_error_tol = -1; // Add the matrix form to the corresponding block of the // stage Jacobian matrix. stage_wf_right->add_vector_form_surf_internal(&vfs_i); } } }