Пример #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 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);
    }
  }
}