Пример #1
0
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);
    }
  }
}
Пример #2
0
void RungeKutta::create_stage_wf(unsigned int size, double current_time, double time_step, Hermes::vector<Solution*> slns_time_prev) 
{
  // Clear the WeakForms.
  stage_wf_left.delete_all();
  stage_wf_right.delete_all();

  // First let's do the mass matrix (only one block ndof times ndof).
  for(unsigned int component_i = 0; component_i < size; component_i++) {
    if(dp->get_spaces()[component_i]->get_type() == HERMES_H1_SPACE || dp->get_spaces()[component_i]->get_type() == HERMES_L2_SPACE) {
      MatrixFormVolL2* proj_form = new MatrixFormVolL2(component_i, component_i);
      proj_form->areas.push_back(HERMES_ANY);
      proj_form->scaling_factor = 1.0;
      proj_form->u_ext_offset = 0;
      proj_form->adapt_eval = false;
      proj_form->adapt_order_increase = -1;
      proj_form->adapt_rel_error_tol = -1;
      stage_wf_left.add_matrix_form(proj_form);
    }
    if(dp->get_spaces()[component_i]->get_type() == HERMES_HDIV_SPACE || dp->get_spaces()[component_i]->get_type() == HERMES_HCURL_SPACE) {
      MatrixFormVolHCurl* proj_form = new MatrixFormVolHCurl(component_i, component_i);
      proj_form->areas.push_back(HERMES_ANY);
      proj_form->scaling_factor = 1.0;
      proj_form->u_ext_offset = 0;
      proj_form->adapt_eval = false;
      proj_form->adapt_order_increase = -1;
      proj_form->adapt_rel_error_tol = -1;
      stage_wf_left.add_matrix_form(proj_form);
    }
  }

  // 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.

  // Original weak formulation.
  WeakForm* wf = dp->get_weak_formulation();

  // Extracting volume and surface matrix and vector forms from the
  // original weak formulation.
  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++) {
    for (unsigned int i = 0; i < num_stages; i++) {
      for (unsigned int j = 0; j < num_stages; j++) {
        WeakForm::MatrixFormVol* mfv_ij = mfvol_base[m]->clone();

        mfv_ij->i = mfv_ij->i + i * dp->get_spaces().size();
        mfv_ij->j = mfv_ij->j + j * dp->get_spaces().size();

        mfv_ij->scaling_factor = -time_step * bt->get_A(i, j);

        mfv_ij->u_ext_offset = i * dp->get_spaces().size();

        // 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;

        for(unsigned int slns_time_prev_i = 0; slns_time_prev_i < slns_time_prev.size(); slns_time_prev_i++)
          mfv_ij->ext.push_back(slns_time_prev[slns_time_prev_i]);

        mfv_ij->set_current_stage_time(current_time + bt->get_C(i)*time_step);

        // 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++) {
    for (unsigned int i = 0; i < num_stages; i++) {
      for (unsigned int j = 0; j < num_stages; j++) {
        WeakForm::MatrixFormSurf* mfs_ij = mfsurf_base[m]->clone();

        mfs_ij->i = mfs_ij->i + i * dp->get_spaces().size();
        mfs_ij->j = mfs_ij->j + j * dp->get_spaces().size();

        mfs_ij->scaling_factor = -time_step * bt->get_A(i, j);

        mfs_ij->u_ext_offset = i * dp->get_spaces().size();

        // 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;

        for(unsigned int slns_time_prev_i = 0; slns_time_prev_i < slns_time_prev.size(); slns_time_prev_i++)
          mfs_ij->ext.push_back(slns_time_prev[slns_time_prev_i]);

        mfs_ij->set_current_stage_time(current_time + bt->get_C(i)*time_step);

        // 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++) {
    for (unsigned int i = 0; i < num_stages; i++) {
      WeakForm::VectorFormVol* vfv_i = vfvol_base[m]->clone();

      vfv_i->i = vfv_i->i + i * dp->get_spaces().size();

      vfv_i->scaling_factor = -1.0;
      vfv_i->u_ext_offset = i * dp->get_spaces().size();

      // 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;

      for(unsigned int slns_time_prev_i = 0; slns_time_prev_i < slns_time_prev.size(); slns_time_prev_i++)
        vfv_i->ext.push_back(slns_time_prev[slns_time_prev_i]);

      vfv_i->set_current_stage_time(current_time + bt->get_C(i)*time_step);

      // 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++) {
    for (unsigned int i = 0; i < num_stages; i++) {
      WeakForm::VectorFormSurf* vfs_i = vfsurf_base[m]->clone();

      vfs_i->i = vfs_i->i + i * dp->get_spaces().size();

      vfs_i->scaling_factor = -1.0;
      vfs_i->u_ext_offset = i * dp->get_spaces().size();

      // 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;

      for(unsigned int slns_time_prev_i = 0; slns_time_prev_i < slns_time_prev.size(); slns_time_prev_i++)
        vfs_i->ext.push_back(slns_time_prev[slns_time_prev_i]);

      vfs_i->set_current_stage_time(current_time + bt->get_C(i)*time_step);

      // Add the matrix form to the corresponding block of the
      // stage Jacobian matrix.
      stage_wf_right.add_vector_form_surf(vfs_i);
    }
  }
}
Пример #3
0
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);
    }
  }
}