Ejemplo n.º 1
0
static void
_end_element(struct type_5_parser_context *ctx, const xmlChar *xn)
{
	error_if(NULL == ctx, error, "Param Error");
	error_if(NULL == xn, error, "Param Error");

	const char *name       = (const char *)xn;
	const char *characters = (const char *)trim(sbuf_ptr(ctx->buffer));

//	trace("name: %s (%d) chars: (%s)", name, ctx->in_valid_package, characters);

	if (0 == strcasecmp("LogicalChannelNumber", name) && ctx->in_valid_package) {
//		trace("LogicalChannelNumber: %s", characters);
		ctx->current_channel->order = (unsigned) atoi(characters);
		list_push(ctx->channels, ctx->current_channel);
		ctx->current_channel = _channel_order_alloc();
	}
	else if (0 == strcasecmp("PackageName", name)) {
		if (NULL != strcasestr(ctx->tvpackages, characters)) {
			ctx->in_valid_package = true;
//			trace("changing valid to true");
		} else {
			ctx->in_valid_package = false;
//			trace("changing valid to false");
		}
	}

error:
	sbuf_reset(ctx->buffer);
	return;
}
Ejemplo n.º 2
0
/// Adds a new view. Function has to be called just from the inside of view thread with a locked sync_view.
int add_view_in_thread(void* view_pars_ptr)
{
  error_if(need_safe_call(), "Calling add_view_in_thread from other thread.");
  ViewParams& view_params = *((ViewParams*)view_pars_ptr);

  //create GLUT window
  glutInitWindowPosition(view_params.x, view_params.y);
  glutInitWindowSize(view_params.width, view_params.height);
  int view_id = glutCreateWindow(view_params.title);
  glutSetWindowData(view_params.view);

  //initialize GLEW
  GLenum err = glewInit();
  error_if(err != GLEW_OK, "GLEW error: %s", glewGetErrorString(err));
  glew_initialized = true;

  //register callbacks
  glutDisplayFunc(on_display_stub);
  glutReshapeFunc(on_reshape_stub);
  glutMotionFunc(on_mouse_move_stub);
  glutPassiveMotionFunc(on_mouse_move_stub);
  glutMouseFunc(on_mouse_click_stub);
  glutKeyboardFunc(on_key_down_stub);
  glutSpecialFunc(on_special_key_stub);
  glutEntryFunc(on_entry_stub);
  glutCloseFunc(on_close_stub);

  //add to structures
  view_instances[view_id] = view_params.view;

  //call handlers
  view_params.view->on_create(view_id);

  return view_id;
}
Ejemplo n.º 3
0
static struct type_5_parser_context *
_ctx_alloc()
{
	struct type_5_parser_context *ctx;
	ctx = malloc(sizeof(struct type_5_parser_context));
	error_if(NULL == ctx, error, "malloc error: %s", strerror(errno));

	ctx->current_channel = _channel_order_alloc();
	error_if(NULL == ctx->current_channel, error, "malloc error: %s", strerror(errno));

	ctx->buffer = sbuf_new();
	error_if(NULL == ctx->buffer, error, "malloc error: %s", strerror(errno));

	ctx->channels = list_create();
	error_if(NULL == ctx->channels, error, "malloc error: %s", strerror(errno));

	ctx->in_valid_package = false;


	return ctx;

error:
	if (ctx) _ctx_free(ctx);
	return NULL;
}
Ejemplo n.º 4
0
/**
 * Validate epg document in bstring format against dtd
 */
int
epg_validate(const char *xml)
{
    if (!xml)
        return -1;

    int rc;

    xmlValidCtxtPtr ctx = xmlNewValidCtxt();
    error_if(ctx == NULL, error, "Error creating validation context");

    xmlDocPtr doc = xmlParseMemory((char *)xml, strlen(xml));
    error_if(doc == NULL, error, "Error creating Parser");

    /* Validate against in memory dtd */
    xmlParserInputBufferPtr buf = xmlParserInputBufferCreateMem(
        xmltv_dtd, strlen(xmltv_dtd), XML_CHAR_ENCODING_NONE);
    xmlDtdPtr dtd = xmlIOParseDTD(NULL, buf, XML_CHAR_ENCODING_NONE);
    xmlFreeParserInputBuffer(buf);
/*
    xmlDtdPtr dtd = xmlParseDTD(NULL, BAD_CAST epg_dtd_file);
*/
    rc = xmlValidateDtd(ctx, doc, dtd);
    trace("Resultado de validación: %d", rc);

    xmlCleanupParser();

    return rc;

 error:
    xmlCleanupParser();
    return -1;

}
Ejemplo n.º 5
0
    Adapt<Scalar>::Adapt(Hermes::vector<Space<Scalar>*> spaces,
      Hermes::vector<ProjNormType> proj_norms) :
    spaces(spaces),
      num_act_elems(-1),
      have_errors(false),
      have_coarse_solutions(false),
      have_reference_solutions(false)
    {
      // sanity check
      if (proj_norms.size() > 0 && spaces.size() != proj_norms.size())
        error("Mismatched numbers of spaces and projection types in Adapt<Scalar>::Adapt().");

      this->num = spaces.size();

      // sanity checks
      error_if(this->num <= 0, "Too few components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS);
      error_if(this->num > H2D_MAX_COMPONENTS, "Too many components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS);

      // reset values
      memset(errors, 0, sizeof(errors));
      memset(sln, 0, sizeof(sln));
      memset(rsln, 0, sizeof(rsln));

      // if norms were not set by the user, set them to defaults
      // according to spaces
      if (proj_norms.size() == 0) 
      {
        for (int i = 0; i < this->num; i++) 
        {
          switch (spaces[i]->get_type()) 
          {
          case HERMES_H1_SPACE: proj_norms.push_back(HERMES_H1_NORM); break;
          case HERMES_HCURL_SPACE: proj_norms.push_back(HERMES_HCURL_NORM); break;
          case HERMES_HDIV_SPACE: proj_norms.push_back(HERMES_HDIV_NORM); break;
          case HERMES_L2_SPACE: proj_norms.push_back(HERMES_L2_NORM); break;
          default: error("Unknown space type in Adapt<Scalar>::Adapt().");
          }
        }
      }

      // assign norm weak forms  according to norms selection
      for (int i = 0; i < this->num; i++)
        for (int j = 0; j < this->num; j++)
        {
          error_form[i][j] = NULL;
          norm_form[i][j] = NULL;
        }

      for (int i = 0; i < this->num; i++)
      {
        error_form[i][i] = new MatrixFormVolError(proj_norms[i]);
        norm_form[i][i] = error_form[i][i];
      }
    }
Ejemplo n.º 6
0
void
epg_add_programme(struct epg *epg, struct epg_programme *programme)
{
    error_if(epg == NULL, error, "Param Error");
    error_if(programme == NULL, error, "Param Error");

    list_push(epg->programmes, (void *)programme);

 error:
    return;
}
Ejemplo n.º 7
0
void
epg_add_channel(struct epg *epg, struct epg_channel *channel)
{
    error_if(epg == NULL, error, "Param Error");
    error_if(channel == NULL, error, "Param Error");

    list_push(epg->channels, (void *)channel);

 error:
    return;
}
Ejemplo n.º 8
0
static void
_actors_to_xml(xmlNodePtr root, list_s *actors)
{
    error_if(root == NULL, error, "Param Error");
    error_if(actors == NULL, error, "Param Error");
    char *s = NULL;
    list_foreach(actors, first, next, cur) {
        s = (char *) cur->value;
//		trace("Adding actor: %s", s)
        xmlNewChild(root, NULL, BAD_CAST "actor", BAD_CAST s);
    }
Ejemplo n.º 9
0
/** Programmes **/
struct epg_programme *
epg_programme_alloc()
{
    struct epg_programme *prog = (struct epg_programme *) malloc(sizeof(struct epg_programme));
    error_if(prog == NULL, error, "Error Allocating Memory");

    prog->channel      = NULL;
    prog->title        = NULL;
    prog->desc         = NULL;
    prog->director     = NULL;
    prog->country      = NULL;
    prog->episode_num  = NULL;
    prog->aspect       = NULL;
    prog->rating_value = NULL;
    prog->rating_icon  = NULL;
    prog->star_rating  = NULL;

    prog->actors = list_create();

    return prog;

 error:
    if (prog)
        epg_programme_free(prog);
    return NULL;
}
Ejemplo n.º 10
0
void
epg_programme_list_free(list_s *programmes)
{
    error_if(programmes == NULL, error, "Param Error");
    list_foreach(programmes, first, next, cur) {
        epg_programme_free((struct epg_programme *) cur->value);
    }
Ejemplo n.º 11
0
char *
epg_to_xmltv(const struct epg *epg)
{
    xmlDocPtr  doc  = NULL;
    xmlDtdPtr  dtd  = NULL;
    xmlNodePtr root = NULL;
    xmlChar   *s    = NULL;

    error_if(epg == NULL, error, "Param Error");

    LIBXML_TEST_VERSION;

    doc = xmlNewDoc((const xmlChar *)"1.0");
    error_if(doc == NULL, error, "Error Creating xmlDoc");

    root = xmlNewDocNode(doc, NULL, BAD_CAST "tv", NULL);
    error_if(root == NULL, error, "Error creating root node");

    dtd = xmlCreateIntSubset(doc, BAD_CAST "tv", NULL, BAD_CAST "epg.dtd");
    error_if(dtd == NULL, error, "Error adding DTD to xmlDoc");

    xmlDocSetRootElement(doc, root);
    xmlNewProp(root,
           BAD_CAST "generator-info-name",
           BAD_CAST "tvz_epg - https://github.com/virgiliosanz/movistar_sv");

    trace("%s", "Adding programmes");
    _programmes_to_xml(root, epg->programmes);

    trace("%s", "Adding channels");
    _channels_to_xml(root, epg->channels);

    trace("calling xmlDocDumpMemory chan: %zu prog: %zu",
        list_count(epg->channels), list_count(epg->programmes));

    int size;
    xmlDocDumpMemoryEnc(doc, &s, &size, "UTF-8");
    xmlCleanupParser();

    return (char *)s;

 error:
    xmlCleanupParser();
    if (s) free(s);

    return NULL;
}
Ejemplo n.º 12
0
void
epg_channel_list_free(list_s *channels)
{
    error_if(channels == NULL, error, "Param error");

    list_foreach(channels, first, next, cur) {
        epg_channel_free((struct epg_channel *) cur->value);
    }
Ejemplo n.º 13
0
void KellyTypeAdapt::add_error_estimator_surf(KellyTypeAdapt::ErrorEstimatorForm* form)
{
  error_if (form->i < 0 || form->i >= this->num,
            "Invalid component number (%d), max. supported components: %d", form->i, H2D_MAX_COMPONENTS);

  form->adapt = this;
  this->error_estimators_surf.push_back(form);
}
Ejemplo n.º 14
0
/** epg **/
struct epg *
epg_alloc()
{
    struct epg *epg = (struct epg *) malloc(sizeof(struct epg));
    error_if(epg == NULL, error, "Error Allocating Memory");

    epg->channels = list_create();
    error_if(epg->channels == NULL, error, "Cannot create list");

    epg->programmes = list_create();
    error_if(epg->programmes == NULL, error, "Cannot create list");

    return epg;

 error:
    if (epg)
        epg_free(epg);
    return NULL;
}
Ejemplo n.º 15
0
void
_channels_to_xml(xmlNodePtr root, list_s *channels)
{
    error_if(root == NULL, error, "Param Error");
    error_if(NULL == channels, error, "Param Error");
    error_if(0 >= channels->count, error, "Channel list empty");

    xmlNodePtr node;
    struct epg_channel *chan;
    list_foreach(channels, first, next, cur) {
        chan = (struct epg_channel *) cur->value;

        node = xmlNewChild(root, NULL, BAD_CAST "channel", NULL);
        xmlNewProp(node, BAD_CAST "id", BAD_CAST chan->id);

        node = xmlNewChild(node,
                           NULL,
                           BAD_CAST "display-name",
                           BAD_CAST chan->display_name);
        xmlNewProp(node, BAD_CAST "lang", BAD_CAST "es");
    }
Ejemplo n.º 16
0
static void
_start_element(
	struct type_5_parser_context *ctx,
	const xmlChar                *xn,
	const xmlChar               **_attrs)
{
	error_if(NULL == ctx, error, "Param Error");
	error_if(NULL == xn, error, "Param Error");

	const char *name   = (const char *)xn;
	const char **attrs = (const char **)_attrs;

	if (0 ==  strcasecmp("TextualID", name)) {
//		trace("TextualID: %s (valid: %d)", attrs[1], ctx->in_valid_package);
		if (ctx->in_valid_package) {
			ctx->current_channel->id = strdup(attrs[1]);
		}
	}

error:
	return;

}
Ejemplo n.º 17
0
      void H1ProjBasedSelector<Scalar>::precalc_shapes(const double3* gip_points, const int num_gip_points, const Trf* trfs, const int num_noni_trfs, const Hermes::vector<typename OptimumSelector<Scalar>::ShapeInx>& shapes, const int max_shape_inx, typename ProjBasedSelector<Scalar>::TrfShape& svals)
      {
        //for all transformations
        bool done = false;
        int inx_trf = 0;
        while (!done && inx_trf < H2D_TRF_NUM)
        {
          //prepare data for processing
          const Trf& trf = trfs[inx_trf];
          Hermes::vector<typename ProjBasedSelector<Scalar>::TrfShapeExp>& trf_svals = svals[inx_trf];

          //allocate
          trf_svals.resize(max_shape_inx + 1);

          //for all shapes
          const int num_shapes = (int)shapes.size();
          for(int i = 0; i < num_shapes; i++)
          {
            int inx_shape = shapes[i].inx;
            typename ProjBasedSelector<Scalar>::TrfShapeExp& shape_exp = trf_svals[inx_shape];

            //allocate
            shape_exp.allocate(H2D_H1FE_NUM, num_gip_points);

            //for all GIP points
            for(int k = 0; k < num_gip_points; k++)
            {
              //transform coordinates
              double ref_x = gip_points[k][H2D_GIP2D_X] * trf.m[0] + trf.t[0];
              double ref_y = gip_points[k][H2D_GIP2D_Y] * trf.m[1] + trf.t[1];

              //for all expansions: retrieve values
              shape_exp[H2D_H1FE_VALUE][k] = this->shapeset->get_fn_value(inx_shape, ref_x, ref_y, 0);
              shape_exp[H2D_H1FE_DX][k] = this->shapeset->get_dx_value(inx_shape, ref_x, ref_y, 0);
              shape_exp[H2D_H1FE_DY][k] = this->shapeset->get_dy_value(inx_shape, ref_x, ref_y, 0);
            }
          }

          //move to the next transformation
          if (inx_trf == H2D_TRF_IDENTITY)
            done = true;
          else
          {
            inx_trf++;
            if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
              inx_trf = H2D_TRF_IDENTITY;
          }
        }
        error_if(!done, "All transformation processed but identity transformation not found."); //identity transformation has to be the last transformation
      }
Ejemplo n.º 18
0
/// Forces a redisplay of a view. Function has to be called just from the inside of view thread.
static int refresh_view_in_thread(void* view_id_ptr) {
  error_if(need_safe_call(), "Calling refresh_view_in_thread from other thread.");
  int view_id = *((int*)view_id_ptr);
  std::map<int, View*>::iterator found_view = view_instances.find(view_id);
  assert_msg(found_view != view_instances.end(), "Refreshing a view that is not registered");

  //redisplay
  if (found_view != view_instances.end()) {
    glutSetWindow(view_id);
    glutPostRedisplay();
  }

  return 0;
}
Ejemplo n.º 19
0
static struct mtv_channel_order *
_channel_order_alloc()
{
	struct mtv_channel_order *mco;
	mco = malloc(sizeof(struct mtv_channel_order));
	error_if(NULL == mco, error, "malloc error: %s", strerror(errno));

	mco->id = NULL;

	return mco;

error:
	if (mco) free(mco);
	return NULL;
}
Ejemplo n.º 20
0
char *
epg_to_m3u(const list_s *channels, enum epg_m3u_format format)
{
    sbuf_s *buffer = sbuf_new();
    error_if(buffer == NULL, error, "Error Allocating sbuf_s");

    error_if(channels == NULL, error, "Params Error");
    trace("There are %zu channels", list_count(channels));

    list_apply_with_state_cb func =
        (format == epg_m3u_format_simpletv) ?
        _gen_m3u_simpletv : _gen_m3u_tvheadend;

    list_walk_with_state((list_s *)channels, func, (void *)buffer);

    char *s = sbuf_detach(buffer);
    sbuf_delete(buffer);
    return s;

error:
    if (buffer)
        sbuf_delete(buffer);
    return NULL;
}
Ejemplo n.º 21
0
/// Sets a title of a view. Function has to be called just from the inside of view thread with a locked sync_view.
static int set_view_title_in_thread(void* title_pars_ptr)
{
  error_if(need_safe_call(), "Calling set_view_title_in_thread from other thread.");
  TitleParams& title_params = *((TitleParams*)title_pars_ptr);
  std::map<int, View*>::iterator found_view = view_instances.find(title_params.view_id);
  if (found_view == view_instances.end()) {
    debug_log("Settings title of a view that is not registered.");
    return -1;
  }

  //create GLUT window
  glutSetWindow(title_params.view_id);
  glutSetWindowTitle(title_params.title);

  return 0;
}
Ejemplo n.º 22
0
void RefMap::calc_inv_ref_map(int order)
{
  assert(quad_2d != NULL);
  int i, j, np = quad_2d->get_num_points(order);

  // construct jacobi matrices of the direct reference map for all integration points

  AUTOLA_OR(double2x2, m, np);
  memset(m, 0, m.size);
  ref_map_pss.force_transform(sub_idx, ctm);
  for (i = 0; i < nc; i++)
  {
    double *dx, *dy;
    ref_map_pss.set_active_shape(indices[i]);
    ref_map_pss.set_quad_order(order);
    ref_map_pss.get_dx_dy_values(dx, dy);
    for (j = 0; j < np; j++)
    {
      m[j][0][0] += coeffs[i][0] * dx[j];
      m[j][0][1] += coeffs[i][0] * dy[j];
      m[j][1][0] += coeffs[i][1] * dx[j];
      m[j][1][1] += coeffs[i][1] * dy[j];
    }
  }

  // calculate the jacobian and inverted matrix
  double trj = get_transform_jacobian();
  double2x2* irm = cur_node->inv_ref_map[order] = new double2x2[np];
  double* jac = cur_node->jacobian[order] = new double[np];
  for (i = 0; i < np; i++)
  {
    jac[i] = (m[i][0][0] * m[i][1][1] - m[i][0][1] * m[i][1][0]);
    double ij = 1.0 / jac[i];
    error_if(!finite(ij), "1/jac[%d] is infinity when calculating inv. ref. map for order %d (jac=%g)", i, order);
    assert_msg(ij == ij, "1/jac[%d] is NaN when calculating inv. ref. map for order %d (jac=%g)", i, order);

    // invert and transpose the matrix
    irm[i][0][0] =  m[i][1][1] * ij;
    irm[i][0][1] = -m[i][1][0] * ij;
    irm[i][1][0] = -m[i][0][1] * ij;
    irm[i][1][1] =  m[i][0][0] * ij;

    jac[i] *= trj;
  }
}
Ejemplo n.º 23
0
/// Removes a new view. Function has to be called just from the inside of view thread with a locked sync_view.
int remove_view_in_thread(void* remove_params_ptr)
{
  error_if(need_safe_call(), "Calling remove_view_in_thread from other thread.");
  RemoveParams& params = *(RemoveParams*)remove_params_ptr;
  std::map<int, View*>::iterator found_view = view_instances.find(params.view_id);
  if (found_view == view_instances.end()) {
    debug_log("Removing of a view that is not registered");
    return -1;
  }

  //destroy window if requested (it will not be requested when remove is called as a reaction to on_close)
  if (params.destroy_glut_window)
  {
    //remove window from GLUT
    glutSetWindow(params.view_id);
    glutSetWindowData(NULL); //prevent stubs from being executed if there is still some message waiting for the window

    //call on-close event
    found_view->second->on_close();

    //finish removal of window from GLUT
    glutDestroyWindow(params.view_id);
  }

  //remove from structures
  view_instances.erase(found_view);

  //thread cleanup
  if (view_instances.size() == 0)
  {
    view_thread->should_quit = true;
    view_thread = NULL;

    //signal all events
    view_sync.signal_close();
    view_sync.signal_keypress();
    view_sync.signal_drawing_finished();
  }

  return 0;
}
Ejemplo n.º 24
0
/** Channels **/
struct epg_channel *
epg_channel_alloc()
{
    struct epg_channel *chan = (struct epg_channel *) malloc(sizeof(struct epg_channel));
    error_if(chan == NULL, error, "Error Allocating Memory");

    chan->id           = NULL;
    chan->display_name = NULL;
    chan->short_name   = NULL;
    chan->url          = NULL;
    chan->icon         = NULL;
    chan->ip           = NULL;
    chan->port         = 0;
    chan->tags         = NULL;
    chan->order        = 0;

    return chan;

 error:
    if (chan)
        epg_channel_free(chan);
    return NULL;
}
Ejemplo n.º 25
0
  void L2ProjBasedSelector::precalc_ortho_shapes(const double3* gip_points, const int num_gip_points, const Trf* trfs, const int num_noni_trfs, const std::vector<ShapeInx>& shapes, const int max_shape_inx, TrfShape& svals) {
    //calculate values
    precalc_shapes(gip_points, num_gip_points, trfs, num_noni_trfs, shapes, max_shape_inx, svals);

    //calculate orthonormal basis
    const int num_shapes = (int)shapes.size();
    for(int i = 0; i < num_shapes; i++) {
      const int inx_shape_i = shapes[i].inx;

      //orthogonalize
      for(int j = 0; j < i; j++) {
        const int inx_shape_j = shapes[j].inx;

        //calculate product of non-transformed functions
        double product = 0.0;
        for(int k = 0; k < num_gip_points; k++) {
          double sum = 0.0;
          sum += svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_L2FE_VALUE][k] * svals[H2D_TRF_IDENTITY][inx_shape_j][H2D_L2FE_VALUE][k];
          product += gip_points[k][H2D_GIP2D_W] * sum;
        }

        //for all transformations
        int inx_trf = 0;
        bool done = false;
        while (!done && inx_trf < H2D_TRF_NUM) {
          //for all integration points
          for(int k = 0; k < num_gip_points; k++) {
            svals[inx_trf][inx_shape_i][H2D_L2FE_VALUE][k] -= product * svals[inx_trf][inx_shape_j][H2D_L2FE_VALUE][k];
          }

          //move to the next transformation
          if (inx_trf == H2D_TRF_IDENTITY)
            done = true;
          else {
            inx_trf++;
            if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
              inx_trf = H2D_TRF_IDENTITY;
          }
        }
        error_if(!done, "All transformation processed but identity transformation not found."); //identity transformation has to be the last transformation
      }

      //normalize
      //calculate norm
      double norm_squared = 0.0;
      for(int k = 0; k < num_gip_points; k++) {
        double sum = 0.0;
        sum += sqr(svals[H2D_TRF_IDENTITY][inx_shape_i][H2D_L2FE_VALUE][k]);
        norm_squared += gip_points[k][H2D_GIP2D_W] * sum;
      }
      double norm = sqrt(norm_squared);
      assert_msg(finite(1/norm), "Norm (%g) is almost zero.", norm);

      //for all transformations: normalize
      int inx_trf = 0;
      bool done = false;
      while (!done && inx_trf < H2D_TRF_NUM) {
        //for all integration points
        for(int k = 0; k < num_gip_points; k++) {
          svals[inx_trf][inx_shape_i][H2D_L2FE_VALUE][k] /= norm;
        }

        //move to the next transformation
        if (inx_trf == H2D_TRF_IDENTITY)
          done = true;
        else {
          inx_trf++;
          if (inx_trf >= num_noni_trfs) //if all transformations were processed, move to the identity transformation
            inx_trf = H2D_TRF_IDENTITY;
        }
      }
      error_if(!done, "All transformation processed but identity transformation not found."); //identity transformation has to be the last transformation
    }
  }
Ejemplo n.º 26
0
    bool Adapt<Scalar>::adapt(Hermes::vector<RefinementSelectors::Selector<Scalar> *> refinement_selectors, double thr, int strat,
      int regularize, double to_be_processed)
    {
      error_if(!have_errors, "element errors have to be calculated first, call Adapt<Scalar>::calc_err_est().");
      error_if(refinement_selectors == Hermes::vector<RefinementSelectors::Selector<Scalar> *>(), "selector not provided");
      if (spaces.size() != refinement_selectors.size()) error("Wrong number of refinement selectors.");
      Hermes::TimePeriod cpu_time;

      //get meshes
      int max_id = -1;
      Mesh* meshes[H2D_MAX_COMPONENTS];
      for (int j = 0; j < this->num; j++) 
      {
        meshes[j] = this->spaces[j]->get_mesh();
        if (rsln[j] != NULL) 
        {
          rsln[j]->set_quad_2d(&g_quad_2d_std);
          rsln[j]->enable_transform(false);
        }
        if (meshes[j]->get_max_element_id() > max_id)
          max_id = meshes[j]->get_max_element_id();
      }

      //reset element refinement info
      int** idx = new int*[max_id];
      for(int i = 0; i < max_id; i++)
        idx[i] = new int[num];

      for(int j = 0; j < max_id; j++)
        for(int l = 0; l < this->num; l++)
          idx[j][l] = -1; // element not refined

      double err0_squared = 1000.0;
      double processed_error_squared = 0.0;

      std::vector<ElementToRefine> elem_inx_to_proc; //list of indices of elements that are going to be processed
      elem_inx_to_proc.reserve(num_act_elems);

      //adaptivity loop
      double error_squared_threshod = -1; //an error threshold that breaks the adaptivity loop in a case of strategy 1
      int num_exam_elem = 0; //a number of examined elements
      int num_ignored_elem = 0; //a number of ignored elements
      int num_not_changed = 0; //a number of element that were not changed
      int num_priority_elem = 0; //a number of elements that were processed using priority queue

      bool first_regular_element = true; //true if first regular element was not processed yet
      int inx_regular_element = 0;
      while (inx_regular_element < num_act_elems || !priority_queue.empty())
      {
        int id, comp, inx_element;

        //get element identification
        if (priority_queue.empty()) 
        {
          id = regular_queue[inx_regular_element].id;
          comp = regular_queue[inx_regular_element].comp;
          inx_element = inx_regular_element;
          inx_regular_element++;
        }
        else 
        {
          id = priority_queue.front().id;
          comp = priority_queue.front().comp;
          inx_element = -1;
          priority_queue.pop();
          num_priority_elem++;
        }
        num_exam_elem++;

        //get info linked with the element
        double err_squared = errors[comp][id];
        Mesh* mesh = meshes[comp];
        Element* e = mesh->get_element(id);

        if (!should_ignore_element(inx_element, mesh, e)) 
        {
          //check if adaptivity loop should end
          if (inx_element >= 0) 
          {
            //prepare error threshold for strategy 1
            if (first_regular_element) 
            {
              error_squared_threshod = thr * err_squared;
              first_regular_element = false;
            }

            // first refinement strategy:
            // refine elements until prescribed amount of error is processed
            // if more elements have similar error refine all to keep the mesh symmetric
            if ((strat == 0) && (processed_error_squared > sqrt(thr) * errors_squared_sum)
              && fabs((err_squared - err0_squared)/err0_squared) > 1e-3) break;

            // second refinement strategy:
            // refine all elements whose error is bigger than some portion of maximal error
            if ((strat == 1) && (err_squared < error_squared_threshod)) break;

            if ((strat == 2) && (err_squared < thr)) break;

            if ((strat == 3) &&
              ( (err_squared < error_squared_threshod) ||
              ( processed_error_squared > 1.5 * to_be_processed )) ) break;
          }

          // get refinement suggestion
          ElementToRefine elem_ref(id, comp);
          int current = this->spaces[comp]->get_element_order(id);
          // rsln[comp] may be unset if refinement_selectors[comp] == HOnlySelector or POnlySelector
          bool refined = refinement_selectors[comp]->select_refinement(e, current, rsln[comp], elem_ref);

          //add to a list of elements that are going to be refined
          if (can_refine_element(mesh, e, refined, elem_ref) ) 
          {
            idx[id][comp] = (int)elem_inx_to_proc.size();
            elem_inx_to_proc.push_back(elem_ref);
            err0_squared = err_squared;
            processed_error_squared += err_squared;
          }
          else 
          {
            debug_log("Element (id:%d, comp:%d) not changed", e->id, comp);
            num_not_changed++;
          }
        }
        else 
        {
          num_ignored_elem++;
        }
      }

      verbose("Examined elements: %d", num_exam_elem);
      verbose(" Elements taken from priority queue: %d", num_priority_elem);
      verbose(" Ignored elements: %d", num_ignored_elem);
      verbose(" Not changed elements: %d", num_not_changed);
      verbose(" Elements to process: %d", elem_inx_to_proc.size());
      bool done = false;
      if (num_exam_elem == 0)
        done = true;
      else if (elem_inx_to_proc.empty())
      {
        warn("None of the elements selected for refinement could be refined. Adaptivity step not successful, returning 'true'.");
        done = true;
      }

      //fix refinement if multimesh is used
      fix_shared_mesh_refinements(meshes, elem_inx_to_proc, idx, refinement_selectors);

      //apply refinements
      apply_refinements(elem_inx_to_proc);

      // in singlemesh case, impose same orders across meshes
      homogenize_shared_mesh_orders(meshes);

      // mesh regularization
      if (regularize >= 0)
      {
        if (regularize == 0)
        {
          regularize = 1;
          warn("Total mesh regularization is not supported in adaptivity. 1-irregular mesh is used instead.");
        }
        for (int i = 0; i < this->num; i++)
        {
          int* parents;
          parents = meshes[i]->regularize(regularize);
          this->spaces[i]->distribute_orders(meshes[i], parents);
          ::free(parents);
        }
      }

      for (int j = 0; j < this->num; j++)
        if (rsln[j] != NULL)
          rsln[j]->enable_transform(true);

      verbose("Refined elements: %d", elem_inx_to_proc.size());
      report_time("Refined elements in: %g s", cpu_time.tick().last());

      //store for the user to retrieve
      last_refinements.swap(elem_inx_to_proc);

      have_errors = false;
      if (strat == 2 && done == true)
        have_errors = true; // space without changes

      // since space changed, assign dofs:
      Space<Scalar>::assign_dofs(this->spaces);

      return done;
    }
Ejemplo n.º 27
0
 double Adapt<Scalar>::get_element_error_squared(int component, int id) const
 { 
   error_if(!have_errors, "Element errors have to be calculated first, call calc_err_est()."); 
   return errors[component][id]; 
 };
Ejemplo n.º 28
0
double KellyTypeAdapt::calc_err_internal(Hermes::vector<Solution *> slns,
                                         Hermes::vector<double>* component_errors,
                                         unsigned int error_flags)
{    
  int n = slns.size();
  error_if (n != this->num,
            "Wrong number of solutions.");

  TimePeriod tmr;

  for (int i = 0; i < n; i++)
  {
    this->sln[i] = slns[i];
    sln[i]->set_quad_2d(&g_quad_2d_std);
  }

  have_coarse_solutions = true;
  
  WeakForm::Stage stage;

  num_act_elems = 0;
  for (int i = 0; i < num; i++)
  {
    stage.meshes.push_back(sln[i]->get_mesh());
    stage.fns.push_back(sln[i]);

    num_act_elems += stage.meshes[i]->get_num_active_elements();
    int max = stage.meshes[i]->get_max_element_id();

    if (errors[i] != NULL) delete [] errors[i];
    errors[i] = new double[max];
    memset(errors[i], 0.0, sizeof(double) * max);
  }
/*
  for (unsigned int i = 0; i < error_estimators_vol.size(); i++)
    trset.insert(error_estimators_vol[i].ext.begin(), error_estimators_vol[i].ext.end());
  for (unsigned int i = 0; i < error_estimators_surf.size(); i++)
    trset.insert(error_estimators_surf[i].ext.begin(), error_estimators_surf[i].ext.end());
*/

  double total_norm = 0.0;

  bool calc_norm = false;
  if ((error_flags & HERMES_ELEMENT_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL ||
      (error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL) calc_norm = true;

  double *norms = NULL;
  if (calc_norm)
  {
    norms = new double[num];
    memset(norms, 0.0, num * sizeof(double));
  }

  double *errors_components = new double[num];
  memset(errors_components, 0.0, num * sizeof(double));
  this->errors_squared_sum = 0.0;
  double total_error = 0.0;

  bool bnd[4];          // FIXME: magic number - maximal possible number of element surfaces
  SurfPos surf_pos[4];
  Element **ee;
  Traverse trav;

  // Reset the e->visited status of each element of each mesh (most likely it will be set to true from
  // the latest assembling procedure).
  if (ignore_visited_segments)
  {
    for (int i = 0; i < num; i++)
    {
      Element* e;
      for_all_active_elements(e, stage.meshes[i])
        e->visited = false;
    }
  }
  
  //WARNING: AD HOC debugging parameter.
  bool multimesh = false;

  // Begin the multimesh traversal.
  trav.begin(num, &(stage.meshes.front()), &(stage.fns.front()));
  while ((ee = trav.get_next_state(bnd, surf_pos)) != NULL)
  {   
    // Go through all solution components.
    for (int i = 0; i < num; i++)
    {
      if (ee[i] == NULL)
        continue;
      
      // Set maximum integration order for use in integrals, see limit_order()
      update_limit_table(ee[i]->get_mode());

      RefMap *rm = sln[i]->get_refmap();

      double err = 0.0;

      // Go through all volumetric error estimators.
      for (unsigned int iest = 0; iest < error_estimators_vol.size(); iest++)
      {
        // Skip current error estimator if it is assigned to a different component or geometric area
        // different from that of the current active element.
        if (error_estimators_vol[iest]->i != i)
          continue;
        /*
        if (error_estimators_vol[iest].area != ee[i]->marker)
          continue;
          */
        else if (error_estimators_vol[iest]->area != HERMES_ANY)
          continue;

        err += eval_volumetric_estimator(error_estimators_vol[iest], rm);
      }

      // Go through all surface error estimators (includes both interface and boundary est's).
      for (unsigned int iest = 0; iest < error_estimators_surf.size(); iest++)
      {
        if (error_estimators_surf[iest]->i != i)
          continue;

        for (int isurf = 0; isurf < ee[i]->get_num_surf(); isurf++)
        {
            /*
          if (error_estimators_surf[iest].area > 0 &&
              error_estimators_surf[iest].area != surf_pos[isurf].marker) continue;
          */
          if (bnd[isurf])   // Boundary
          {
            if (error_estimators_surf[iest]->area == H2D_DG_INNER_EDGE) continue;
            
            /*
            if (boundary_markers_conversion.get_internal_marker(error_estimators_surf[iest].area) < 0 &&
                error_estimators_surf[iest].area != HERMES_ANY) continue;
            */    
            
            err += eval_boundary_estimator(error_estimators_surf[iest], rm, surf_pos);
          }
          else              // Interface
          {
            if (error_estimators_surf[iest]->area != H2D_DG_INNER_EDGE) continue;

            /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
            
            // 5 is for bits per page in the array.
            LightArray<NeighborSearch*> neighbor_searches(5);
            unsigned int num_neighbors = 0;
            DiscreteProblem::NeighborNode* root;
            int ns_index;
            
            dp.min_dg_mesh_seq = 0;
            for(int j = 0; j < num; j++)
              if(stage.meshes[j]->get_seq() < dp.min_dg_mesh_seq || j == 0)
                dp.min_dg_mesh_seq = stage.meshes[j]->get_seq();
            
            ns_index = stage.meshes[i]->get_seq() - dp.min_dg_mesh_seq; // = 0 for single mesh
            
            // Determine the minimum mesh seq in this stage.
            if (multimesh) 
            {              
              // Initialize the NeighborSearches.
              dp.init_neighbors(neighbor_searches, stage, isurf);
              
              // Create a multimesh tree;
              root = new DiscreteProblem::NeighborNode(NULL, 0);
              dp.build_multimesh_tree(root, neighbor_searches);
              
              // Update all NeighborSearches according to the multimesh tree.
              // After this, all NeighborSearches in neighbor_searches should have the same count 
              // of neighbors and proper set of transformations
              // for the central and the neighbor element(s) alike.
              // Also check that every NeighborSearch has the same number of neighbor elements.
              for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                if(neighbor_searches.present(j)) {
                  NeighborSearch* ns = neighbor_searches.get(j);
                  dp.update_neighbor_search(ns, root);
                  if(num_neighbors == 0)
                    num_neighbors = ns->n_neighbors;
                  if(ns->n_neighbors != num_neighbors)
                    error("Num_neighbors of different NeighborSearches not matching in KellyTypeAdapt::calc_err_internal.");
                }
            }
            else
            {
              NeighborSearch *ns = new NeighborSearch(ee[i], stage.meshes[i]);
              ns->original_central_el_transform = stage.fns[i]->get_transform();
              ns->set_active_edge(isurf);
              ns->clear_initial_sub_idx();
              num_neighbors = ns->n_neighbors;
              neighbor_searches.add(ns, ns_index);
            }

            // Go through all segments of the currently processed interface (segmentation is caused
            // by hanging nodes on the other side of the interface).
            for (unsigned int neighbor = 0; neighbor < num_neighbors; neighbor++)
            {              
              if (ignore_visited_segments) {
                bool processed = true;
                for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                  if(neighbor_searches.present(j))
                    if(!neighbor_searches.get(j)->neighbors.at(neighbor)->visited) {
                      processed = false;
                      break;
                    }
                if (processed) continue;
              }
              
              // Set the active segment in all NeighborSearches
              for(unsigned int j = 0; j < neighbor_searches.get_size(); j++)
                if(neighbor_searches.present(j)) {
                  neighbor_searches.get(j)->active_segment = neighbor;
                  neighbor_searches.get(j)->neighb_el = neighbor_searches.get(j)->neighbors[neighbor];
                  neighbor_searches.get(j)->neighbor_edge = neighbor_searches.get(j)->neighbor_edges[neighbor];
                }
                
              // Push all the necessary transformations to all functions of this stage.
              // The important thing is that the transformations to the current subelement are already there.
              // Also store the current neighbor element and neighbor edge in neighb_el, neighbor_edge.
              if (multimesh) 
              {
                for(unsigned int fns_i = 0; fns_i < stage.fns.size(); fns_i++)
                  for(unsigned int trf_i = 0; trf_i < neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->central_n_trans[neighbor]; trf_i++)
                    stage.fns[fns_i]->push_transform(neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->central_transformations[neighbor][trf_i]);
              }
              else
              {            
                // Push the transformations only to the solution on the current mesh
                for(unsigned int trf_i = 0; trf_i < neighbor_searches.get(ns_index)->central_n_trans[neighbor]; trf_i++)
                  stage.fns[i]->push_transform(neighbor_searches.get(ns_index)->central_transformations[neighbor][trf_i]);
              }
              /* END COPY FROM DISCRETE_PROBLEM.CPP */
              rm->force_transform(this->sln[i]->get_transform(), this->sln[i]->get_ctm());
              
              // The estimate is multiplied by 0.5 in order to distribute the error equally onto
              // the two neighboring elements.
              double central_err = 0.5 * eval_interface_estimator(error_estimators_surf[iest],
                                                                  rm, surf_pos, neighbor_searches, 
                                                                  ns_index);
              double neighb_err = central_err;

              // Scale the error estimate by the scaling function dependent on the element diameter
              // (use the central element's diameter).
              if (use_aposteriori_interface_scaling && interface_scaling_fns[i])
                central_err *= interface_scaling_fns[i](ee[i]->get_diameter());

              // In the case this edge will be ignored when calculating the error for the element on
              // the other side, add the now computed error to that element as well.
              if (ignore_visited_segments)
              {
                Element *neighb = neighbor_searches.get(i)->neighb_el;

                // Scale the error estimate by the scaling function dependent on the element diameter
                // (use the diameter of the element on the other side).
                if (use_aposteriori_interface_scaling && interface_scaling_fns[i])
                  neighb_err *= interface_scaling_fns[i](neighb->get_diameter());

                errors_components[i] += central_err + neighb_err;
                total_error += central_err + neighb_err;
                errors[i][ee[i]->id] += central_err;
                errors[i][neighb->id] += neighb_err;
              }
              else
                err += central_err;
              
              /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
              
              // Clear the transformations from the RefMaps and all functions.
              if (multimesh)
                for(unsigned int fns_i = 0; fns_i < stage.fns.size(); fns_i++)
                  stage.fns[fns_i]->set_transform(neighbor_searches.get(stage.meshes[fns_i]->get_seq() - dp.min_dg_mesh_seq)->original_central_el_transform);
              else
                stage.fns[i]->set_transform(neighbor_searches.get(ns_index)->original_central_el_transform);

              rm->set_transform(neighbor_searches.get(ns_index)->original_central_el_transform);

              
              /* END COPY FROM DISCRETE_PROBLEM.CPP */
            }
            
            /* BEGIN COPY FROM DISCRETE_PROBLEM.CPP */
            
            if (multimesh)
              // Delete the multimesh tree;
              delete root;
            
            // Delete the neighbor_searches array.
            for(unsigned int j = 0; j < neighbor_searches.get_size(); j++) 
              if(neighbor_searches.present(j))
                delete neighbor_searches.get(j);
              
            /* END COPY FROM DISCRETE_PROBLEM.CPP */
            
          }
        }
      }

      if (calc_norm)
      {
        double nrm = eval_solution_norm(error_form[i][i], rm, sln[i]);
        norms[i] += nrm;
        total_norm += nrm;
      }

      errors_components[i] += err;
      total_error += err;
      errors[i][ee[i]->id] += err;

      ee[i]->visited = true;
    }
  }
  trav.finish();

  // Store the calculation for each solution component separately.
  if(component_errors != NULL)
  {
    component_errors->clear();
    for (int i = 0; i < num; i++)
    {
      if((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_ABS)
        component_errors->push_back(sqrt(errors_components[i]));
      else if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL)
        component_errors->push_back(sqrt(errors_components[i]/norms[i]));
      else
      {
        error("Unknown total error type (0x%x).", error_flags & HERMES_TOTAL_ERROR_MASK);
        return -1.0;
      }
    }
  }

  tmr.tick();
  error_time = tmr.accumulated();

  // Make the error relative if needed.
  if ((error_flags & HERMES_ELEMENT_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL)
  {
    for (int i = 0; i < num; i++)
    {
      Element* e;
      for_all_active_elements(e, stage.meshes[i])
        errors[i][e->id] /= norms[i];
    }
  }

  this->errors_squared_sum = total_error;

  // Element error mask is used here, because this variable is used in the adapt()
  // function, where the processed error (sum of errors of processed element errors)
  // is matched to this variable.
  if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_ELEMENT_ERROR_REL)
    errors_squared_sum /= total_norm;

  // Prepare an ordered list of elements according to an error.
  fill_regular_queue(&(stage.meshes.front()));
  have_errors = true;

  if (calc_norm)
    delete [] norms;
  delete [] errors_components;

  // Return error value.
  if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_ABS)
    return sqrt(total_error);
  else if ((error_flags & HERMES_TOTAL_ERROR_MASK) == HERMES_TOTAL_ERROR_REL)
    return sqrt(total_error / total_norm);
  else
  {
    error("Unknown total error type (0x%x).", error_flags & HERMES_TOTAL_ERROR_MASK);
    return -1.0;
  }
}
Ejemplo n.º 29
0
int main(int argc, char* argv[])
{
  int ret = ERROR_FAILURE;

  if (argc < 2)
  {
    printf("please input as this format: <mesh type> <meshfile> [meshfiledump] \n");
    return ERROR_FAILURE;
  }

  char *mtype = argv[1];
  char *file_name = argv[2];
  char *file_name_dump = NULL;
  if (argc > 2)
    file_name_dump = argv[3];

  // load the mesh file
  Mesh mesh;
  MeshLoader *mloader = NULL;
  if (strcmp(mtype, "exII") == 0) mloader = new ExodusIIReader();
  else if (strcmp(mtype, "h2d") == 0) mloader = new H2DReader();
  else if (strcmp(mtype, "h2d-str") == 0) {
    // load the file into a string
    FILE *file = fopen(file_name , "rb");
    error_if(file == NULL, "unable to open file '%s'", file_name);

    // obtain file size:
    fseek(file, 0, SEEK_END);
    long size = ftell(file);
    rewind(file);

    // allocate memory to contain the whole file:
    char *buffer = (char *) malloc (sizeof(char) * size);
    error_if(buffer == NULL, "memory error");

    // copy the file into the buffer:
    size_t result = fread(buffer, 1, size, file);
    error_if(result != size, "reading error");

    fclose(file);

    //
    H2DReader *hloader = new H2DReader();
    hloader->load_str(buffer, &mesh);
    ret = dump_compare(mesh, file_name_dump);
    delete hloader;
    free(buffer);
    return ret;
  }
  else if (strcmp(mtype, "h2d-old") == 0) {
    H2DReader *hloader = new H2DReader();
    hloader->load_old(file_name, &mesh);
    ret = dump_compare(mesh, file_name_dump);
    delete hloader;
    return ret;
  }
  else {
    error("unknown mesh loader type");
  }

  if (mloader->load(file_name, &mesh))
  {
    ret = dump_compare(mesh, file_name_dump);
  }
  else
  {
    error("failed");
    ret = ERROR_FAILURE;
  }

  delete mloader;

  return ret;
}
Ejemplo n.º 30
0
void
_programmes_to_xml(xmlNodePtr root, list_s *programmes)
{
    error_if(NULL == root, error, "Param Error");
    error_if(NULL == programmes, error, "Param Error");
    error_if(0 >= programmes->count, error, "Programs list empty");

    xmlNodePtr node;
    xmlNodePtr subnode;
    char start[EPG_START_FMT_SIZE];
    char progdate[EPG_DATE_FMT_SIZE];
    struct epg_programme *prog;
    size_t n_programmes = 0;

    list_foreach(programmes, first, next, cur) {
        prog = (struct epg_programme *) cur->value;

//		epg_debug_programme(prog);

        if (!prog->title || !prog->channel) {
            warn("No channel (%s) or title (%s)!!",
                prog->channel, prog->title);
            continue;
        }

//		trace("Adding channel (%s): %s", prog->title, prog->channel);
        node = xmlNewChild(root, NULL, BAD_CAST "programme", NULL);
        xmlNewProp(node, BAD_CAST "channel", BAD_CAST prog->channel);

        strftime(start, EPG_START_FMT_SIZE, EPG_START_FMT, &prog->start);
//		trace("Adding start time: %s", start);
        xmlNewProp(node, BAD_CAST "start", BAD_CAST start);

//		trace("Adding title: %s", prog->title);
        subnode = xmlNewChild(node, NULL,
                          BAD_CAST "title",
                      BAD_CAST prog->title);
        xmlNewProp(subnode, BAD_CAST "lang", BAD_CAST "es");

        if (prog->desc) {
//			trace("Adding desc: '%s'", prog->desc);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "desc",
                          BAD_CAST prog->desc);
            xmlNewProp(subnode, BAD_CAST "lang", BAD_CAST "es");
        }


        subnode = xmlNewChild(node, NULL, BAD_CAST "credits", NULL);
        if (prog->director) {
//			trace("Adding director: %s", prog->director);
            xmlNewChild(subnode,
                        NULL,
                        BAD_CAST "director",
                    BAD_CAST prog->director);
        }
//		trace("Addind %d actors", prog->actors->count);
        if (prog->actors->count > 0) {
            _actors_to_xml(subnode, prog->actors);
        }

        strftime(progdate,
            EPG_DATE_FMT_SIZE, EPG_DATE_FMT, &prog->date);
//		trace("Adding progdate: %s", progdate);
        subnode = xmlNewChild(node,
            NULL, BAD_CAST "date", BAD_CAST progdate);

        if (prog->country) {
//			trace("Adding country: %s", prog->country);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "country",
                              BAD_CAST prog->country);
        }

        if (prog->episode_num) {
//			trace("Adding episode num: %s", prog->episode_num);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "episode-num",
                          BAD_CAST prog->episode_num);
            xmlNewProp(subnode,
                       BAD_CAST "system",
                       BAD_CAST "epg_ns");
        }

        if (prog->aspect) {
//			trace("Adding aspect: %s", prog->aspect);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "video",
                                  NULL);
            xmlNewChild(subnode,
                        NULL,
                        BAD_CAST "aspect",
                    BAD_CAST prog->aspect);
        }

        if (prog->rating_value) {
//			trace("Adding rating_value: %s", prog->rating_value);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "rating",
                                  NULL);
            xmlNewProp(subnode,
                       BAD_CAST "system",
                       BAD_CAST "MPAA");
            xmlNewChild(subnode,
                        NULL,
                        BAD_CAST "value",
                    BAD_CAST prog->rating_value);
        }

        if (prog->rating_icon) {
//			trace("Adding rating_icon: %s", prog->rating_icon);
            subnode = xmlNewChild(subnode,
                                  NULL,
                                  BAD_CAST "icon",
                                  NULL);
            xmlNewProp(subnode,
                       BAD_CAST "src",
                       BAD_CAST prog->rating_icon);
        }

        if (prog->star_rating) {
//			trace("Adding star_rating: %s", prog->star_rating);
            subnode = xmlNewChild(node,
                                  NULL,
                                  BAD_CAST "star-rating",
                                  NULL);
            xmlNewChild(subnode,
                        NULL,
                        BAD_CAST "value",
                    BAD_CAST prog->star_rating);
        }
        n_programmes++;

    }