Пример #1
0
static int bfam_ts_adams_inter_rhs(const char *key, void *val, void *arg)
{
  bfam_ts_adams_allprefix_t *data = (bfam_ts_adams_allprefix_t *)arg;
  bfam_subdomain_t *sub = (bfam_subdomain_t *)val;
  char prefix[BFAM_BUFSIZ];
  snprintf(prefix, BFAM_BUFSIZ, "%s%d_", BFAM_ADAMS_PREFIX,
           data->ts->currentStage % data->ts->nStages);
  BFAM_LDEBUG("Adams inter: using prefix %s", prefix);
  data->ts->inter_rhs(sub, prefix, prefix, "", data->ts->t);
  return 1;
}
Пример #2
0
static inline int
bfam_ts_adams_do_update(bfam_subdomain_t* sub, const bfam_long_real_t* A,
    const bfam_ts_adams_t* ts, const bfam_long_real_t dt, const int nStages)
{
  BFAM_LDEBUG("BFAM_TS_ADAMS_DO_UPDATE");

  /* Loop through the stages to scale rates and add in */
  /*
   * nStages is the computing number of stages whereas ts->nStages is the
   * storage number of stages
   */
  for(int k = 0; k < nStages;k++)
  {
    char prefix[BFAM_BUFSIZ];
    snprintf(prefix,BFAM_BUFSIZ,"%s%d_",BFAM_ADAMS_PREFIX,
        (ts->currentStage+ts->nStages-k)%ts->nStages);
    BFAM_LDEBUG("Adams step: stage %d of %d using prefix %s",k,nStages,prefix);
    ts->add_rates(sub, "", "", prefix, dt*A[k]);
  }
  return 1;
}
Пример #3
0
void bfam_ts_adams_free(bfam_ts_adams_t *ts)
{
  BFAM_LDEBUG("ADAMS FREE");
  if (ts->lsrk != NULL)
  {
    bfam_ts_lsrk_free(ts->lsrk);
    bfam_free(ts->lsrk);
  }
  ts->lsrk = NULL;
  bfam_communicator_free(ts->comm);
  bfam_free(ts->comm);
  ts->comm = NULL;
  bfam_dictionary_clear(&ts->elems);
  /*
  bfam_free_aligned(ts->A);
  ts->A = NULL;
  */
  ts->nStages = 0;
  ts->t = NAN;
  bfam_ts_free(&ts->base);
}
Пример #4
0
void bfam_ts_adams_init(
    bfam_ts_adams_t *ts, bfam_domain_t *dom, bfam_ts_adams_method_t method,
    bfam_domain_match_t subdom_match, const char **subdom_tags,
    bfam_domain_match_t comm_match, const char **comm_tags, MPI_Comm mpicomm,
    int mpitag, void *comm_data,
    void (*aux_rates)(bfam_subdomain_t *thisSubdomain, const char *prefix),
    void (*scale_rates)(bfam_subdomain_t *thisSubdomain,
                        const char *rate_prefix, const bfam_long_real_t a),
    void (*intra_rhs)(bfam_subdomain_t *thisSubdomain, const char *rate_prefix,
                      const char *minus_rate_prefix, const char *field_prefix,
                      const bfam_long_real_t t),
    void (*inter_rhs)(bfam_subdomain_t *thisSubdomain, const char *rate_prefix,
                      const char *minus_rate_prefix, const char *field_prefix,
                      const bfam_long_real_t t),
    void (*add_rates)(bfam_subdomain_t *thisSubdomain,
                      const char *field_prefix_lhs,
                      const char *field_prefix_rhs, const char *rate_prefix,
                      const bfam_long_real_t a),
    const int RK_init)
{
  BFAM_LDEBUG("ADAMS INIT");

  /*
   * set up some preliminaries
   */
  bfam_ts_init(&ts->base, dom);
  bfam_dictionary_init(&ts->elems);
  ts->t = BFAM_LONG_REAL(0.0);
  ts->base.step = &bfam_ts_adams_step;

  /*
   * store the function calls
   */
  ts->scale_rates = scale_rates;
  ts->intra_rhs = intra_rhs;
  ts->inter_rhs = inter_rhs;
  ts->add_rates = add_rates;

  ts->currentStage = 0;
  ts->numSteps = 0;

  ts->lsrk = NULL;

  switch (method)
  {
  default:
    BFAM_WARNING("Invalid Adams scheme, using ADAMS_3");
  case BFAM_TS_ADAMS_3:
    ts->nStages = 3;
    /*
    ts->A = bfam_malloc_aligned(ts->nStages*sizeof(bfam_long_real_t));

    ts->A[0] = BFAM_LONG_REAL(23.0)/
               BFAM_LONG_REAL(12.0);
    ts->A[1] = BFAM_LONG_REAL(-4.0)/
               BFAM_LONG_REAL( 3.0);
    ts->A[2] = BFAM_LONG_REAL( 5.0)/
               BFAM_LONG_REAL(12.0);
    */

    /* if necessary initialize the RK scheme */
    if (RK_init)
    {
      ts->lsrk = bfam_ts_lsrk_new_extended(
          dom, BFAM_TS_LSRK_KC54, subdom_match, subdom_tags, comm_match,
          comm_tags, mpicomm, mpitag, comm_data, aux_rates, scale_rates,
          intra_rhs, inter_rhs, add_rates, 0);
    }

    break;
  case BFAM_TS_ADAMS_1:
    ts->nStages = 1;
    /*
    ts->A = bfam_malloc_aligned(ts->nStages*sizeof(bfam_long_real_t));

    ts->A[0] = BFAM_LONG_REAL(1.0);
    */

    /* if necessary initialize the RK scheme */
    if (RK_init)
    {
      ts->lsrk = bfam_ts_lsrk_new_extended(
          dom, BFAM_TS_LSRK_FE, subdom_match, subdom_tags, comm_match,
          comm_tags, mpicomm, mpitag, comm_data, aux_rates, scale_rates,
          intra_rhs, inter_rhs, add_rates, 0);
    }

    break;
  case BFAM_TS_ADAMS_2:
    ts->nStages = 2;
    /*
    ts->A = bfam_malloc_aligned(ts->nStages*sizeof(bfam_long_real_t));

    ts->A[0] = BFAM_LONG_REAL( 3.0)/
               BFAM_LONG_REAL( 2.0);
    ts->A[1] = BFAM_LONG_REAL(-1.0)/
               BFAM_LONG_REAL( 2.0);
    */

    /* if necessary initialize the RK scheme */
    if (RK_init)
    {
      ts->lsrk = bfam_ts_lsrk_new_extended(
          dom, BFAM_TS_LSRK_HEUN, subdom_match, subdom_tags, comm_match,
          comm_tags, mpicomm, mpitag, comm_data, aux_rates, scale_rates,
          intra_rhs, inter_rhs, add_rates, 0);
    }

    break;
  case BFAM_TS_ADAMS_4:
    ts->nStages = 4;
    /*
    ts->A = bfam_malloc_aligned(ts->nStages*sizeof(bfam_long_real_t));

    ts->A[0] = BFAM_LONG_REAL( 55.0)/
               BFAM_LONG_REAL( 24.0);
    ts->A[1] = BFAM_LONG_REAL(-59.0)/
               BFAM_LONG_REAL( 24.0);
    ts->A[2] = BFAM_LONG_REAL( 37.0)/
               BFAM_LONG_REAL( 24.0);
    ts->A[3] = BFAM_LONG_REAL(  3.0)/
               BFAM_LONG_REAL(  8.0);
    */

    /* if necessary initialize the RK scheme */
    if (RK_init)
    {
      ts->lsrk = bfam_ts_lsrk_new_extended(
          dom, BFAM_TS_LSRK_KC54, subdom_match, subdom_tags, comm_match,
          comm_tags, mpicomm, mpitag, comm_data, aux_rates, scale_rates,
          intra_rhs, inter_rhs, add_rates, 0);
    }

    break;
  }

  /*
   * get the subdomains and create rates we will need
   */
  bfam_subdomain_t *subs[dom->numSubdomains + 1];
  bfam_locidx_t numSubs = 0;
  bfam_domain_get_subdomains(dom, subdom_match, subdom_tags, dom->numSubdomains,
                             subs, &numSubs);
  for (int s = 0; s < numSubs; s++)
  {
    int rval = bfam_dictionary_insert_ptr(&ts->elems, subs[s]->name, subs[s]);
    BFAM_ABORT_IF_NOT(rval != 1, "Issue adding subdomain %s", subs[s]->name);

    for (int n = 0; n < ts->nStages; n++)
    {
      char aux_rates_name[BFAM_BUFSIZ];
      snprintf(aux_rates_name, BFAM_BUFSIZ, "%s%d_", BFAM_ADAMS_PREFIX, n);
      aux_rates(subs[s], aux_rates_name);
    }
  }

  /*
   * Set up the communicator we will use
   */
  ts->comm = bfam_communicator_new(dom, comm_match, comm_tags, mpicomm, mpitag,
                                   comm_data);
}
Пример #5
0
void bfam_ts_adams_step(bfam_ts_t *a_ts, bfam_long_real_t dt)
{
  /* cast to the proper type */
  bfam_ts_adams_t *ts = (bfam_ts_adams_t *)a_ts;

  bfam_ts_adams_allprefix_t data;
  data.ts = ts;
  data.dt = dt;

  /*
   * start the communication
   */
  bfam_communicator_start(ts->comm);

  /*
   * do the intra work
   */
  bfam_dictionary_allprefixed_ptr(&ts->elems, "", &bfam_ts_adams_intra_rhs,
                                  &data);

  /*
   * finish the communication
   */
  bfam_communicator_finish(ts->comm);

  /*
   * do the inter work
   */
  bfam_dictionary_allprefixed_ptr(&ts->elems, "", &bfam_ts_adams_inter_rhs,
                                  &data);

  if (ts->lsrk)
  {
    /*
     * If we are using RK, we want to tell the RK scheme to use the next rate
     * for storage (not the current rate which is valid
     */
    ts->lsrk->t = ts->t;
    char rate_prefix[BFAM_BUFSIZ];
    snprintf(rate_prefix, BFAM_BUFSIZ, "%s%d_", BFAM_ADAMS_PREFIX,
             (ts->currentStage + 1) % ts->nStages);
    BFAM_LDEBUG("Adams step: RK rate rate_prefix %s", rate_prefix);
    BFAM_ASSERT(ts->lsrk->step_extended);
    ts->lsrk->step_extended((bfam_ts_t *)ts->lsrk, dt, rate_prefix, "", "");
    if (ts->numSteps + 2 >= ts->nStages)
    {
      bfam_ts_lsrk_free(ts->lsrk);
      bfam_free(ts->lsrk);
      ts->lsrk = NULL;
    }
  }
  else
    /* q_{n+1}  := q_{n} + dt \sum_{k=0}^{m} a_{k} dq_{n-k} */
    bfam_dictionary_allprefixed_ptr(&ts->elems, "", &bfam_ts_adams_update,
                                    &data);

  /* shift the stage counter */
  ts->currentStage = (ts->currentStage + 1) % ts->nStages;
  ts->numSteps++;

  /* update the stage time */
  ts->t += dt;
}