// Description: if an entry with "id" tag and timestep exists in the cache,
//  returns the entry, otherwise returns a reference to an empty DERIV that
//  is stored in the cache and stores the associated "id" and timestep.
//  The entry is locked and given a new last_access_time_ to show that it has
//  been used recently.
//  The entry must be released by release_item() when we are finished working
//  with it.
LataDeriv<LataObject> & LataFilterCache::get_item_(const Nom & id, entier tstep)
{
  entier i;
  const entier n = data_.size();
  for (i = 0; i < n; i++) {
    const DataCacheItem & item = data_[i];
    if (item.id_ == id && item.tstep_ == tstep)
      break;
  }
  if (i == n) {
    // Look for an empty slot:
    for (i = 0; i < n; i++)
      if (data_[i].id_ == "??")
        break;
    // No empty slot: create a new slot:
    if (i == n)
      data_.add();
    DataCacheItem & item = data_[i];
    item.id_ = id;
    item.tstep_ = tstep;
    item.lock_ = 0;
    Journal(cache_info_level) << "LataFilterCache<C>::get " << id << " (new cache entry " << i << ")." << endl;
  } else {
    Journal(cache_info_level) << "LataFilterCache<C>::get " << id << " (existing cache entry " << i << ")." << endl;
  }
  // Mark item and lock it:
  DataCacheItem & item = data_[i];
  item.last_access_time_ = cache_data_access_count_++;
  item.lock_++;
  return item.item_;
}
// Description: tells that if needed the item can be deleted from cache
//  (there is no reference to it anymore outside of the cache).
//  We update the memory size of this item here.
void LataFilterCache::release_item(const Nom & id)
{
  Journal(cache_info_level) << "LataFilterCache::release_item " << id << endl;
  const entier n = data_.size();
  entier i;
  for (i = 0; i < n; i++) {
    const DataCacheItem & item = data_[i];
    if (item.id_ == id)
      break;
  }
  if (i == n) {
    Journal() << "LataFilterCache::release_item internal error: unknown item " << id << endl;
    throw;
  }
  if (data_[i].lock_ <= 0) {
    Journal() << "LataFilterCache::release_item internal error: item is already unlocked" << id << endl;
    throw;
  }
  data_[i].last_access_time_ = cache_data_access_count_++;
  data_[i].lock_--;
  if (data_[i].item_.non_nul())
    data_[i].memory_size_ = data_[i].item_.valeur().compute_memory_size();
  else
    data_[i].memory_size_ = 0;
}
void DomainIJK::fill_field_from_lataDB(const LataDB & lataDB,
                                       const Field_Id & id, 
                                       LataDeriv<LataField_base> & field) const
{
  const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_);
  LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_);

  entier ij = 0, offset = 0, sz = 0;
  switch(loc) {
  case LataField_base::ELEM: 
    // Product of number of elements in directions I and J
    ij = coord_[0].size_array() - 1;
    if (coord_.size() > 2)
      ij *= coord_[1].size_array() - 1;
    // Select a range of elements in direction K
    offset = ij * part_begin_;
    sz = ij * (part_end_ - part_begin_);
    break;
  case LataField_base::SOM:
  case LataField_base::FACES:
    // Product of number of nodes in directions I and J
    ij = coord_[0].size_array();
    if (coord_.size() > 2)
      ij *= coord_[1].size_array();
    offset = ij * part_begin_;
    sz = ij * (part_end_ + 1 - part_begin_);
    break;
  default:
    Journal() << "Error in DomainIJK::fill_field_from_lataDB: unknown localisation" << endl;
    throw;
  }
  
  const LataDBDataType & type = lata_field.datatype_;
  switch(type.type_) {
  case LataDBDataType::REAL32: {
    FloatTab & data = field.instancie(Field<FloatTab> ).data_;
    lataDB.read_data(lata_field, data, offset, sz);
    break;
  }
  case LataDBDataType::REAL64: {
    DoubleTab & data = field.instancie(Field<DoubleTab> ).data_; 
    lataDB.read_data(lata_field, data, offset, sz);
    break;
  }
  case LataDBDataType::INT32:
  case LataDBDataType::INT64: {
    IntTab & data = field.instancie(Field<IntTab> ).data_; 
    lataDB.read_data(lata_field, data, offset, sz);
    break;
  }
  default:
    Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl;
    throw;
  }
  field.valeur().id_ = id;
  field.valeur().component_names_ = lata_field.component_names_;
  field.valeur().localisation_ = loc;
  field.valeur().nature_ = lata_field.nature_;
}
void build_field_(OperatorRegularize & op,
                  const DomainUnstructured & src_domain,
                  const DomainIJK          & dest_domain,
                  const Field<TabType> & src,
                  Field<TabType> & dest)
{
  Journal(verb_level) << "OperatorRegularize field " << src.id_.uname_ << endl;
  if (!op.geom_init_) {
    // Must fill the renum_.... arrays first !
    LataDeriv<Domain> dest;
    op.build_geometry(src_domain, dest);
  }
  dest.component_names_ = src.component_names_;
  dest.localisation_ = src.localisation_;
  dest.nature_ = src.nature_;
  const entier sz = src.data_.dimension(0);
  const entier nb_compo = src.data_.dimension(1);
  entier i;
  switch(src.localisation_) {
  case LataField_base::ELEM:
    dest.data_.resize(dest_domain.nb_elements(), nb_compo);
    for (i = 0; i < sz; i++) {
      const entier new_i = op.renum_elements_[i];
      for (entier j = 0; j < nb_compo; j++)
        dest.data_(new_i, j) = src.data_(i, j);
    }
    break;
  case LataField_base::SOM:
    dest.data_.resize(dest_domain.nb_nodes(), nb_compo);
    for (i = 0; i < sz; i++) {
      const entier new_i = op.renum_nodes_[i];
      for (entier j = 0; j < nb_compo; j++)
        dest.data_(new_i, j) = src.data_(i, j);
    }
    break;
  case LataField_base::FACES:
    {
      if (nb_compo != 1) {
        Journal() << "Error in OperatorRegularize: field at faces has nb_compo != 1" << endl;
        throw;
      }
      dest.nature_ = LataDBField::VECTOR;
      const entier nb_dim = dest_domain.dimension();
      dest.data_.resize(dest_domain.nb_faces(), nb_dim);
      // Field is interpreted as normal component to the face
      for (i = 0; i < sz; i++) {
        const entier code = op.renum_faces_[i];
        // decodage numero et direction de la face:
        const entier new_i = code >> 2;
        const entier direction = (code & 3);
        dest.data_(new_i, direction) = src.data_(i, 0);
      }
    }
    break;
  default:
    Journal() << "Error in OperatorRegularize::build_field_: unknown localisation" << endl;
    throw;
  }
}
entier LataOptions::parse_option(const Nom & s)
{
  if (s.debute_par("verbosity=")) {
    entier level = read_int_opt(s);
    set_Journal_level(level);
  } else if (s.debute_par("regularize=")) {
    regularize = true;
    regularize_tolerance = read_float_opt(s);
  } else if (s.debute_par("regularize_polyedre=")) {
    regularize_polyedre = read_int_opt(s);
  } else if (s.debute_par("extend_domain=")) {
    extend_domain = read_int_opt(s);
  } else if (s == "invalidate") {
    invalidate = true;
  } else if (s.debute_par("reconnect=")) {
    reconnect = true;
    reconnect_tolerance = read_float_opt(s);   
  } else if (s.debute_par("reconnect_tolerance=")) {
    reconnect_tolerance = read_float_opt(s);   
  } else if (s == "dualmesh") {
    dual_mesh = true;
  } else if (s == "nodualmesh") {
    dual_mesh = false;
  } else if (s == "ncmesh") {
    nc_mesh = true;
  } else if (s == "facesmesh") {
    faces_mesh = true;
  } else if (s == "nofacesmesh") {
    faces_mesh = false;
  } else if (s == "boundarymesh") {
    boundary_mesh = true;
  } else if (s.debute_par("clipbox=")) {
    Noms list = extract_list(((const char*)s)+8);
    if (list.size() != 6) {
      Journal() << "Error : clipbox parameters expects 6 values" << endl;
      throw;
    }
    for (entier i = 0; i < 3; i++) {
      clipbox_min[i] = read_float_opt(list[i]);
      clipbox_max[i] = read_float_opt(list[i+3]);
    }
  } else if (s == "load_virtual_elements") {
    load_virtual_elements = true;
  } else if (s == "user_fields") {
    user_fields_ = true;
    Journal() << "Option: User_fields ON" << endl;
  } else if (s.debute_par("ijk_mesh_nb_parts")) {
    ijk_mesh_nb_parts_ = read_int_opt(s);
  } else if (s == "export_fields_at_faces") {
    export_fields_at_faces_ = 1;
  } else if (s.debute_par("ijk_virt_layer=")) {
    ijk_virt_layer = read_int_opt(s);
  } else
    return user_fields_options_.parse_option(s);;
  return 1;
}
// Description: Find duplicate coordinates in the "coord" array.
//  nodes_renumber will have dimension src_coord.dimension(0)
//  nodes_renumber[i] = i if the node imust be conserved,
//  nodes_renumber[i] = j if the node i is identical to node j. We always have j<i
//  eps = tolerance in each direction to consider that two nodes are identical
//  nb_nodes_untouched : do not search duplicate nodes in the "nb_nodes_untouched"
//   first nodes. The remaining nodes are still compared to all nodes.
void Reconnect::search_duplicate_nodes(const FloatTab & src_coord,
                                       ArrOfInt & nodes_renumber,
                                       double eps,
                                       entier nb_nodes_untouched)
{
  // Create a temporary DoubleTab (coords are normally float)
  const entier nb_nodes = src_coord.dimension(0);
  const entier dim = src_coord.dimension(1);
  entier i;
  // Build an octree with all coordinates
  Journal(verb_level+1) << " Building octree" << endl;
  DoubleTab coords;
  coords.resize(nb_nodes, dim);
  for (i = 0; i < nb_nodes; i++) 
    for (entier j = 0; j < dim; j++)
      coords(i,j) = src_coord(i,j);
  Octree_Double octree;
  octree.build_nodes(coords, 0 /* no virtual nodes */);
  
  Journal(verb_level+1) << " Searching duplicate nodes" << endl;
  nodes_renumber.resize_array(nb_nodes);
  for (i = 0; i < nb_nodes; i++)
    nodes_renumber[i] = i;
  // For each node, are there several nodes within epsilon ?
  ArrOfInt node_list;
  node_list.set_smart_resize(1);
  entier count = 0; // Number of nodes renumbered
  for (i = 0; i < nb_nodes; i++) {
    if (nodes_renumber[i] != i)
      continue; // node already suppressed

    const double x = coords(i, 0);
    const double y = (dim>1) ? coords(i, 1) : 0.;
    const double z = (dim>2) ? coords(i, 2) : 0.;
    octree.search_elements_box(x-eps, y-eps, z-eps,
                               x+eps, y+eps, z+eps,
                               node_list);
    Octree_Double::search_nodes_close_to(x, y, z,
                                         coords, node_list,
                                         eps);
    const entier n = node_list.size_array();
    if (n > 1) {
      for (entier j = 0; j < n; j++) {
        // Change only nodes with rank > i
        const entier node = node_list[j];
        if (node > j) {
          nodes_renumber[node] = i;
          count++;
        }
      }
    }
  }
  Journal(verb_level+1) << " " << count << " duplicate nodes will be removed" << endl;
}
// Reads the requested field to "field" structure.
// id.block_ is not used, the data block read is the same as the domain.
void DomainUnstructured::fill_field_from_lataDB(const LataDB & lataDB,
                                                const Field_Id & id, 
                                                LataDeriv<LataField_base> & field) const
{
  const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_);
  LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_);
  const entier decal = lata_block_offset(loc);

  const ArrOfInt & virt_items = get_virt_items(loc);
  const entier virt_size = virt_items.size_array();
  const entier size = nb_items(loc) - virt_size;

  const LataDBDataType & type = lata_field.datatype_;
  switch(type.type_) {
  case LataDBDataType::REAL32: {
    FloatTab & data = field.instancie(Field<FloatTab> ).data_;
    lataDB.read_data(lata_field, data, decal, size);
    if (virt_size > 0) {
      FloatTab tmp;
      lataDB.read_data(lata_field, tmp, virt_items);
      const entier debut = data.size_array();
      data.resize(data.dimension(0)+virt_size, data.dimension(1));
      data.inject_array(tmp, virt_size, debut);
    }
    break;
  }
  case LataDBDataType::REAL64: {
    DoubleTab & data = field.instancie(Field<DoubleTab> ).data_; 
    lataDB.read_data(lata_field, data, decal, size);
    if (virt_size > 0) {
      DoubleTab tmp;
      lataDB.read_data(lata_field, tmp, virt_items);
      const entier debut = data.size_array();
      data.resize(data.dimension(0)+virt_size, data.dimension(1));
      data.inject_array(tmp, virt_size, debut);
    }
    break;
  }
  case LataDBDataType::INT32:
  case LataDBDataType::INT64: {
    IntTab & data = field.instancie(Field<IntTab> ).data_; 
    lataDB.read_data(lata_field, data, decal, size);
    if (virt_size > 0) {
      IntTab tmp;
      lataDB.read_data(lata_field, tmp, virt_items);
      const entier debut = data.size_array();
      data.resize(data.dimension(0)+virt_size, data.dimension(1));
      data.inject_array(tmp, virt_size, debut);
    }
    break;
  }
  default:
    Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl;
    throw;
  }
  field.valeur().id_ = id;
  field.valeur().component_names_ = lata_field.component_names_;
  field.valeur().localisation_ = loc;
  field.valeur().nature_ = lata_field.nature_;
}
void Domain::fill_field_from_lataDB(const LataDB & lataDB,
                                    const Field_Id & id, 
                                    LataDeriv<LataField_base> & field) const
{
  Journal() << "Error : fill_field_from_lataDB not coded for this domain type" << endl;
  throw;
}
void LataFilter::release_geometry(const Domain & dom)
{
  Journal(filter_info_level) << "LataFilter::release_geometry " 
                             << dom.id_.name_ << " time=" << dom.id_.timestep_ 
                             << " bloc=" << dom.id_.block_ << endl;
  release_cached_domain(dom.id_);
}
void LataFilter::release_field(const LataField_base & field)
{
  Journal(filter_info_level) << "LataFilter::release_field " 
                             << field.id_.uname_ << " time=" << field.id_.timestep_ 
                             << " bloc=" << field.id_.block_ << endl;
  release_cached_field(field.id_);
}
// Description: returns the offset in the lata block on disk of the first
//  item for this Domain.id_.block_ (parallel computation).
//  (this value must be set with set_lata_block_offset)
entier Domain::lata_block_offset(const LataField_base::Elem_som loc) const
{
  entier n = -1;
  switch (loc) {
  case LataField_base::SOM: n = decal_nodes_lata_; break;
  case LataField_base::ELEM: n = decal_elements_lata_; break;
  case LataField_base::FACES: n = decal_faces_lata_; break;
  default:
    Journal() << "Invalid localisation " << (int) loc << " in Domain::lata_block_offset" << endl;
    throw;
  }
  if (n < 0) {
    Journal() << "Error: lata_block_offset not set for localisation " << (int) loc << endl;
    throw;
  }
  return n;
}
// Description: fill "data" for the requested "geometry/field". "geometry"  and "field" must be names
//  returned by get_exportable_geometry_names() and get_exportable_field_names()
const LataFieldMetaData & LataFilter::get_field_metadata(const Field_UName & uname) const
{
  for (entier i = 0; i < fields_metadata_.size(); i++)
    if (fields_metadata_[i].uname_ == uname)
      return fields_metadata_[i];
  
  Journal() << "Error in LataFilter::get_field_metadata: unknown field " << uname << endl;
  throw;
  return fields_metadata_[0];
}
// Description: fill "data" for the requested "geometry". "geometry" must be a name
//  returned by get_exportable_geometry_names()
const LataGeometryMetaData & LataFilter::get_geometry_metadata(const char * geometry) const
{
  Motcle geom(geometry);
  for (entier i = 0; i < geoms_metadata_.size(); i++)
    if (geom == geoms_metadata_[i].internal_name_)
      return geoms_metadata_[i];

  Journal() << "Error in LataFilter::get_geometry_metadata: unknown geometry " << geometry << endl;
  throw;
  return geoms_metadata_[0];
}
// Description: set the lata_block_offset (see lata_block_offset)
void Domain::set_lata_block_offset(const LataField_base::Elem_som loc, entier n)
{
  switch (loc) {
  case LataField_base::SOM: decal_nodes_lata_ = n; break;
  case LataField_base::ELEM: decal_elements_lata_ = n; break;
  case LataField_base::FACES: decal_faces_lata_ = n; break;
  default:
    Journal() << "Invalid localisation " << (int) loc << " in Domain::set_lata_block_offset" << endl;
    throw;
  }
}
// Description: updates the elements_ and faces_ arrays of the domain so that
//  all nodes having the same coordinates are replaced by one unique node
//  in these arrays. See search_duplicate_nodes for nb_nodes_untouched description.
void Reconnect::reconnect_geometry(DomainUnstructured & geom, double tolerance, entier nb_nodes_untouched)
{
  Journal(verb_level) << "Reconnect domain " << geom.id_.name_ << endl;

  ArrOfInt nodes_renumber;
  search_duplicate_nodes(geom.nodes_, nodes_renumber, tolerance, nb_nodes_untouched);

  apply_renumbering(nodes_renumber, geom.elements_);
  
  if (geom.faces_ok()) 
    apply_renumbering(nodes_renumber, geom.faces_);
}
// Description: returns the number of items of the given type
entier Domain::nb_items(const LataField_base::Elem_som loc) const
{
  entier n = -1;
  switch (loc) {
  case LataField_base::SOM: n = nb_nodes(); break;
  case LataField_base::ELEM: n = nb_elements(); break;
  case LataField_base::FACES: n = nb_faces(); break;
  default:
    Journal() << "Invalid localisation " << (int) loc << " in Domain::nb_items" << endl;
    throw;
  }
  return n;
}
double LataOptions::read_float_opt(const Nom & s)
{
  const char *ptr = strstr(s, "=");
  if (!ptr) 
    ptr = s;
  errno = 0;
  char *errorptr = 0;
  double x = strtod(ptr+1, &errorptr);
  if (errno || *errorptr != 0) {
    Journal() << "LataOptions error reading float parameter: " << s << endl;
    throw;
  }
  return x;
}
entier LataOptions::read_int_opt(const Nom & s)
{
  const char *ptr = strstr(s, "=");
  if (!ptr) 
    ptr = s;
  errno = 0;
  char *errorptr = 0;
  entier x = strtol(ptr+1, &errorptr, 0 /* base 10 par defaut */);
  if (errno || *errorptr != 0) {
    Journal() << "LataOptions error reading int parameter: " << s << endl;
    throw;
  }
  return x;
}
// Description: returns the requested field, computing it if it is not
//  already in the cache. You MUST call release_field() on the returned field
//  when you don't need it any more...
//  See also class Field_Id
const LataField_base & LataFilter::get_field(const Field_Id & id)
{
  Journal(filter_info_level) << "LataFilter::get_field " 
                             << id.uname_ << " time=" << id.timestep_ 
                             << " bloc=" << id.block_ << endl;

  data_cache_.cleanup_cache(id.timestep_);

  const LataFieldMetaData & field_metadata = get_field_metadata(id.uname_);

  LataDeriv<LataField_base> & field_ptr = get_cached_field(id);
  if (!field_ptr.non_nul()) {
    if (field_metadata.source_ == "latadb") {
      // Request for a native field : load it from lataDB
      const Domain & dom = get_geometry(id);
      dom.fill_field_from_lataDB(lataDB(), id, field_ptr);
      release_geometry(dom);
    } else if (field_metadata.source_.debute_par("OPERATOR")) {
      const Field_Id src_id(field_metadata.source_field_,
                            id.timestep_,
                            id.block_);
      const Domain & src_domain = get_geometry(src_id);
      const LataField_base & src_field = get_field(src_id);
      const Domain & dest_domain = get_geometry(id);
      Operator & op = get_set_operator(dest_domain.id_);
      op.build_field(src_domain, src_field, dest_domain, field_ptr);
      field_ptr.valeur().id_ = Field_Id(field_metadata.uname_, src_field.id_.timestep_, src_field.id_.block_);
      release_field(src_field);
      release_geometry(src_domain);
      release_geometry(dest_domain);
      release_cached_operator(dest_domain.id_);
    } else if (field_metadata.source_ == "user_fields") {
      Field<FloatTab> & f = field_ptr.instancie(Field<FloatTab> );
      f = user_fields_.valeur().get_field(id);
      // Force field id to correct value:
      f.id_ = id;
      f.component_names_ = field_metadata.component_names_;
      f.nature_ = field_metadata.is_vector_ ? LataDBField::VECTOR : LataDBField::SCALAR;
      f.localisation_ = field_metadata.localisation_;
    }
  }

  return field_ptr.valeur();
}
// Description: removes from the cache the oldest items until the total
//  memory used by the cache is below max_mem_size (in bytes), and
//  if tstep_to_keep > 0, also removes all timesteps except 0 and tstep_to_keep
void LataFilterCache::cleanup_cache(entier tstep_to_keep)
{
  if (clear_cache_on_tstep_change_ && tstep_to_keep > 0) {
    Journal(cache_info_level) << "LataFilterCache::clear_cache_tsteps except 0 and " << tstep_to_keep << endl;
    const entier n = data_.size();
    for (entier i = 0; i < n; i++) {
      DataCacheItem & item = data_[i];
      if (item.id_ != "??") {
        if (item.tstep_ == 0 || item.tstep_ == tstep_to_keep) {
          Journal(cache_info_level+1) << " item " << item.id_ << " timestep " << item.tstep_ << " kept" << endl;
        } else if (item.lock_) {
          Journal(cache_info_level+1) << " item " << item.id_ << " locked" << endl;
        } else {
          Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl;
          item.item_.reset();
          item.id_ = "??";
          item.tstep_ = -1;
        }
      }
    }
  }
  if (cache_memory_limit_ >= 0) {
    Journal(cache_info_level) << "LataFilterCache::clear_cache_memory " << cache_memory_limit_ << endl;
    do {
      const entier n = data_.size();
      // Scan cached data, looking for the oldest item and summing up memory
      BigEntier total_memsize = 0;
      entier oldest = -1;
      BigEntier oldest_time = cache_data_access_count_;
      for (entier i = 0; i < n; i++) {
        const DataCacheItem & item = data_[i];
        if (item.id_ != "??") {
          total_memsize += item.memory_size_;
          if (!item.lock_ && item.last_access_time_ < oldest_time) {
            oldest_time = item.last_access_time_;
            oldest = i;
          }
        }
      }
      if (oldest < 0 || total_memsize < cache_memory_limit_) 
        break;
      
      DataCacheItem & item = data_[oldest];
      Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl;
      item.item_.reset();
      item.id_ = "??";
      item.tstep_ = -1;
    } while(1);
  }
}
Domain::Element Domain::element_type_from_string(const Motcle & type_elem)
{
  Element type;
  if (type_elem == "HEXAEDRE")
    type=hexa;
  else if (type_elem == "HEXAEDRE_AXI")
    type=hexa;
  else if (type_elem == "HEXAEDRE_VEF")
    type=hexa;
  else if (type_elem == "QUADRANGLE")
    type=quadri;
  else if (type_elem == "QUADRANGLE_3D")
    type=quadri;
  else if (type_elem == "RECTANGLE")
    type=quadri;
  else if (type_elem == "RECTANGLE_2D_AXI")
    type=quadri;
  else if (type_elem == "RECTANGLE_AXI")
    type=quadri;
  else if (type_elem == "SEGMENT")
    type=line;
  else if (type_elem == "SEGMENT_2D")
    type=line;
  else if (type_elem == "TETRAEDRE")
    type=tetra;
  else if (type_elem == "TRIANGLE")
    type=triangle;
  else if (type_elem == "TRIANGLE_3D")
    type=triangle;
  else if (type_elem == "POINT")
    type=point;
  else if (type_elem == "PRISM6")
    type=prism6;
  else if (type_elem.debute_par("POLYEDRE"))
    type=polyedre;
  else {
    Journal() << "Error in elem_type_from_string: unknown element type " << type_elem << endl;
    throw;
  }
  return type;
}
示例#22
0
    void testFetch ()
    {
        beginTestCase ("fetch");

        Livecache <> c (m_clock, Journal());

        add (1, 1, c);
        add (2, 1, c);
        add (3, 1, c);
        add (4, 1, c);
        add (4, 2, c);
        add (4, 3, c);
        add (5, 1, c);
        add (6, 1, c);
        add (6, 2, c);
        add (7, 1, c);

        // VFALCO TODO!!!

        pass();
    }
Operator & LataFilter::get_set_operator(const Domain_Id & id)
{
  LataDeriv<Operator> & op_ptr  = get_cached_operator(id);
  if (!op_ptr.non_nul()) {
    // Operator not in the cache ? Build it:
    if (id.name_.finit_par("_IJK")) {
      OperatorRegularize & op = op_ptr.instancie(OperatorRegularize);
      op.set_tolerance(opt_.regularize_tolerance);
      op.set_extend_layer(opt_.extend_domain);
    } else if (id.name_.finit_par("_dual")) {
      op_ptr.instancie(OperatorDualMesh);
    } else if (id.name_.finit_par("_Boundary")) {
      op_ptr.instancie(OperatorBoundary);
    } else if (id.name_.finit_par("_centerfaces")) {
      op_ptr.instancie(OperatorFacesMesh);
    } else {
      Journal() << "Internal error in LataFilter::get_operator: forgot to implement operator choice for " << id.name_ << endl;
      throw;
    }
  }
  return op_ptr.valeur();
}
示例#24
0
Bibliographic FieldBuilder::buildField(const KeyValuePair& kvp)
{
	String key = kvp.getKey();
	Bibliographic field = Bibliographic(kvp);

	if (key == "author") {
		field = (Author)field;
		return field; 
	}

	else if (key == "doi") {
		field = Doi();
	}

	else if (key == "issn") {
		field = Issn();
	}

	else if (key == "journal") {
		field = Journal();
	}

	else if (key == "month") {
		field = Month();
	}

	else if (key == "number") {
		field = Number();
	}

	else if (key == "pages") {
		field = Pages();
	}

	else if (key == "title") {
		field = Title();
	}

	else if (key == "url") {
		field = Url();
	}

	else if (key == "urldate") {
		field = UrlDate();
	}

	else if (key == "volume") {
		field = Volume();
	}

	else if (key == "year") {
		field = Year();
	}

	else {
		field = Bibliographic();
		field.setKey(kvp.getKey());
	}
	field.setValue(kvp.getValue());
	return field;
}
void build_geometry_(OperatorRegularize & op,
                     const DomainUnstructured & src, LataDeriv<Domain> & dest_domain)
{
  Journal(verb_level) << "OperatorRegularize domain " << src.id_.name_ << endl;
  if (src.elt_type_ != Domain::quadri && src.elt_type_ != Domain::hexa) {
    Journal() << "Error in OperatorRegularize::build_geometry: cannot operate on unstructured mesh with this element type" << endl;
    throw;
  }

  DomainIJK & dest = dest_domain.instancie(DomainIJK);
  dest.elt_type_ = src.elt_type_;
  const entier nsom = src.nodes_.dimension(0);
  const entier dim = src.nodes_.dimension(1);
  ArrOfInt nb_som_dir(dim);
  {
    double product_n = 1.;
    for (entier i_dim = 0; i_dim < dim; i_dim++) {
      ArrOfFloat & coord = dest.coord_.add(ArrOfFloat());
      coord.resize_array(nsom);
      entier i;
      for (i = 0; i < nsom; i++)
        coord[i] = src.nodes_(i, i_dim);
      coord.ordonne_array();
      retirer_doublons(coord, op.tolerance_);
      product_n *= coord.size_array();
      // Add extended domain layer:
      if (coord.size_array() > 1) {
        const entier n = coord.size_array();
        const entier l = op.extend_layer_;
        coord.resize_array(n + l * 2);
        double x0 = coord[n-1];
        double delta = coord[n-2] - x0;
        for (i = 1; i <= l; i++)
          coord[n + l + i] = x0 + delta * i;
        for (i = l-1; i >= 0; i--)
          coord[i + l] = coord[i];
        x0 = coord[l];
        delta = coord[l+1] - x0;
        for (i = 1; i <= l; i++)
          coord[l - i] = x0 - delta * i;
      }
      nb_som_dir[i_dim] = coord.size_array();
    }
    // Verifying that unique has deleted many points...
    // If well organised, nsom=nx*ny*nz
    // If chaos, nsom=(nx+ny+nz)/3
    // We want to verify that we are nearer to organisation than to chaos !
    if (product_n > (double) nsom * (double) nsom - 1.) {
      Journal() << "Positions do not seam regular !" << endl;
      throw;
    }
  }
  int i;
  op.renum_nodes_.resize_array(nsom);
  int nb_som_ijk = 1;
  for (i = 0; i < dim; i++) 
    nb_som_ijk *= nb_som_dir[i];
  IntTab ijk_indexes;
  ijk_indexes.resize(nsom, dim);
  for (i = 0; i < nsom; i++) {
    entier ijk_index = 0;
    for (int j = dim-1; j >= 0; j--) {
      const double x = src.nodes_(i,j);
      int index = search_in_ordered_vect(x, dest.coord_[j]);
      if (index < 0) {
        Journal() << "Error: coordinate (" << i << "," << j << ") = " << x << " not found in regularize" << endl
                  << "Try reducing regularize tolerance value (option regularize=epsilon)" << endl;
        throw;
      }
      ijk_indexes(i, j) = index;
      ijk_index += index;
      if (j)
        ijk_index *= nb_som_dir[j-1];
    }
    op.renum_nodes_[i] = ijk_index;
  }
  const int max_index = max_array(nb_som_dir);
  int nb_elems_ijk = 1;
  for (i = 0; i < dim; i++)
    nb_elems_ijk *= nb_som_dir[i] - 1;
  dest.invalid_connections_.resize_array(nb_elems_ijk);
  dest.invalid_connections_ = 1; // Everything invalid by default
  const int nelem = src.elements_.dimension(0);
  const int nb_som_elem = src.elements_.dimension(1);
  op.renum_elements_.resize_array(nelem);
  // Pour chaque element, indice dans le maillage ijk du plus sommet le plus proche de l'origine
  // (pour les faces...)
  ArrOfInt idx_elem_som;
  idx_elem_som.resize_array(nelem);
  int min_index[3];
  for (i = 0; i < nelem; i++) {
    min_index[0] = min_index[1] = min_index[2] = max_index;
    for (int j = 0; j < nb_som_elem; j++) {
      int node = src.elements_(i,j);
      for (int k = 0; k < loop_max(dim, 3); k++) {
        int idx = ijk_indexes(node, k);
        min_index[k] = (idx < min_index[k]) ? idx : min_index[k];
        break_loop(k,dim);
      }
    }
    entier idx = 0;
    entier idx_som = 0;
    if (dim == 1) {
      idx = min_index[0];
      idx_som = idx;
    } else if (dim == 2) {
      idx = min_index[1] * (nb_som_dir[0]-1) + min_index[0];
      idx_som = min_index[1] * nb_som_dir[0] + min_index[0];
    } else if (dim == 3) {
      idx = (min_index[2] * (nb_som_dir[1]-1) + min_index[1]) * (nb_som_dir[0]-1) + min_index[0];
      idx_som = (min_index[2] * nb_som_dir[1] + min_index[1]) * nb_som_dir[0] + min_index[0];
    } else
      throw;
    op.renum_elements_[i] = idx;
    dest.invalid_connections_.clearbit(idx);
    idx_elem_som[i] = idx_som;
  }
  
  if (src.faces_ok()) {
    const int nfaces = src.faces_.dimension(0);
    op.renum_faces_.resize_array(nfaces);
    op.renum_faces_ = -1;
    const int nb_elem_face = src.elem_faces_.dimension(1);
    ArrOfInt delta_dir(dim);
    delta_dir[0] = 1;
    for (i = 1; i < dim; i++)
      delta_dir[i] = delta_dir[i-1] * nb_som_dir[i-1];
    for (i = 0; i < nelem; i++) {
      // Les faces haut, gauche et arriere du cube a l'origine portent le numero 0
      // Voir DomaineIJK pour la convention sur la numerotation des faces
      for (entier j = 0; j < nb_elem_face; j++) {
        const entier i_face = src.elem_faces_(i, j);
        entier dir = j % dim;
        entier index = idx_elem_som[i];
        if (j>=dim) 
          index += delta_dir[dir];
        // Encodage du numero de la face et de la direction
        index = (index << 2) + dir;
        if (op.renum_faces_[i_face] < 0) {
          op.renum_faces_[i_face] = index;
        } else if (op.renum_faces_[i_face] != index) {
          Journal() << "Error in OperatorRegularize: faces renumbering failed" << endl;
          throw;
        }
      }
    }
  }
  op.geom_init_ = 1;
}
// Process the content of the source LataDB structure and builds the metadata for
//  all geometries and fields that the filter can export (depending on options,
//  for example, provide dual mesh geometry and fields only if dualmesh option is on).
void LataFilter::get_all_metadata(LataVector<LataGeometryMetaData> & geoms_data, LataVector<LataFieldMetaData> & fields_data)
{
  geoms_data.reset();
  fields_data.reset();
  entier current_tstep = 1;
  // If no real timestep, just check timestep 0
  if (lataDB().nb_timesteps() < 2)
    current_tstep = 0;
  Noms lata_geoms_names = lataDB().geometry_names(current_tstep, LataDB::FIRST_AND_CURRENT);
  const entier nb_geoms = lata_geoms_names.size();
  for (entier i_geom = 0; i_geom < nb_geoms; i_geom++) {
    // Name of the current geometry (from lataDB)
    const Nom & lata_geom_name = lata_geoms_names[i_geom];
    const LataDBGeometry & lata_geom = lataDB().get_geometry(current_tstep, lata_geom_name, LataDB::FIRST_AND_CURRENT);
    // Query properties from LataDB:
    // Is it a dynamic mesh ?
    const entier dynamic = lata_geom.timestep_ > 0;
    // Element type ?
    Domain::Element element_type = Domain::element_type_from_string(lata_geom.elem_type_);
    // It is regularizable ?
    entier regularizable = (element_type == Domain::quadri || element_type == Domain::hexa)
      && (lata_geom.elem_type_ != "HEXAEDRE_AXI") && (lata_geom.elem_type_ != "RECTANGLE_AXI");
    Journal(filter_info_level) << " metadata: geometry " << lata_geom_name << " element type says regularizable=" << regularizable << endl;
    // Query for dimension
    const entier domain_already_ijk = lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_I", LataDB::FIRST_AND_CURRENT);

    // Do we have faces ?
    const entier have_faces = 
      domain_already_ijk ||
      (lataDB().field_exists(current_tstep, lata_geom_name, "FACES", LataDB::FIRST_AND_CURRENT)
       && lataDB().field_exists(current_tstep, lata_geom_name, "ELEM_FACES", LataDB::FIRST_AND_CURRENT));

    entier dim = 1;
    // Query for number of blocks in the lata file:
    entier nblocks = 1;
    if (domain_already_ijk) {
      if (lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_K", LataDB::FIRST_AND_CURRENT))
        dim = 3;
      else
        dim = 2;
      nblocks = opt_.ijk_mesh_nb_parts_;
      Nom nom_sommets;
      if (dim == 2)
        nom_sommets = "SOMMETS_IJK_J";
      else
        nom_sommets = "SOMMETS_IJK_K";
      const LataDBField & coord = lataDB().get_field(current_tstep, lata_geom_name, nom_sommets, "", LataDB::FIRST_AND_CURRENT);
      // Nombre d'elements dans la direction du decoupage parallele:
      const entier nelem = coord.size_ - 1;
      // Si les tranches sont trop petites diminuer le nombre de blocs
      if (nblocks > (nelem + 3) / 4)
        nblocks = (nelem + 3) / 4;
    } else {
      dim = lataDB().get_field(current_tstep, lata_geom_name, "SOMMETS", "*", LataDB::FIRST_AND_CURRENT).nb_comp_;
      if (lataDB().field_exists(current_tstep, lata_geom_name, "JOINTS_SOMMETS", LataDB::FIRST_AND_CURRENT))
        nblocks = lataDB().get_field(current_tstep, lata_geom_name, "JOINTS_SOMMETS", "*", LataDB::FIRST_AND_CURRENT).size_;
    }

    // Initialize data common to all domains:
    LataGeometryMetaData data;
    data.dynamic_ = dynamic;
    data.dimension_ = dim;
    data.element_type_ = element_type;
    // If we reconnect all subdomains, always load all of them:
    if (!opt_.reconnect)
      data.nblocks_ = nblocks;
    else
      data.nblocks_ = 1;

    data.internal_name_ = lata_geom_name;
    data.displayed_name_ = lata_geom_name;
    data.source_ = "latadb";
    Journal(filter_info_level) << " metadata: adding geometry " << lata_geom_name << " displayed name=" << lata_geom_name << endl;
    geoms_data.add(data);
    // Add fields at som and elem:
    add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                "from_elem,from_som,from_faces", dim, fields_data,
                                "latadb",
                                "??");
    if (regularizable && ((opt_.regularize_tolerance < 0) || (!opt_.regularize))) {
      regularizable = 0;
      Journal(filter_info_level) << " regularize option not set: don't build ijk domain" << endl;
    }
    if (regularizable && domain_already_ijk) {
      regularizable = 0;
      Journal(filter_info_level) << " domain is already IJK: do not regularize" << endl;
    }

    // opt_.regularize == 2 means: provide ijk only if faces are present
    if (regularizable && opt_.regularize == 2) {
      if (!have_faces) {
        Journal(filter_info_level) << " regularize option==2 and no faces => do not regularize" << endl;
        regularizable = 0;
      }
    }
    if (regularizable) {
      data.internal_name_ = lata_geom_name;
      data.internal_name_ += "_IJK";
      data.displayed_name_ = lata_geom_name;
      data.source_ = "operator_ijk";
      data.source_domain_ = lata_geom_name;
      geoms_data.add(data);
      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
      // Add fields at som and elem:
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  "from_elem,from_som,from_faces", dim, fields_data,
                                  "operator_ijk",
                                  data.source_domain_);
    }

    // Provide dual mesh
    if (opt_.dual_mesh && have_faces) {
      data.internal_name_ = lata_geom_name;
      
      // If it's quadri or hexa, we need the regular mesh
      data.source_domain_ = data.internal_name_;
      if (regularizable) {
        data.internal_name_ += "_IJK";
        data.source_domain_ += "_IJK";
      }
      data.internal_name_ += "_dual";
      data.displayed_name_ += "_dual";

      data.source_ = "operator_dual";
      geoms_data.add(data);
      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
      // Add fields at faces, localisation will be at elements,
      //  forced to vector type if vdf:
      Nom options("from_faces,to_elem");
      if (regularizable)
        options += ",to_vector";
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  options, dim, fields_data,
                                  "operator_dual",
                                  data.source_domain_);      
    }

    // Provide nc mesh if possible
    if (opt_.nc_mesh && have_faces && !regularizable /* doesn't work for vdf */) {
      data.internal_name_ = lata_geom_name;
      data.internal_name_ += "_nc";
      data.displayed_name_ = data.internal_name_;
      data.source_ = "operator_nc";
      data.source_domain_ = lata_geom_name;
      geoms_data.add(data);
      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
      // Add fields at faces, localisation will be at nodes
      Nom options("from_faces,to_som");
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  options, dim, fields_data,
                                  "operator_nc",
                                  data.source_domain_);
    }
    // Provide faces mesh if possible
    if (opt_.faces_mesh && have_faces && !regularizable /* doesn't work for vdf */ &&  !(domain_already_ijk) ) {
   
      data.internal_name_ = lata_geom_name;
      data.internal_name_ += "_centerfaces";
      data.displayed_name_ = data.internal_name_;
      data.source_ = "operator_faces";
      data.source_domain_ = lata_geom_name;
      if (data.element_type_ == Domain::triangle)
        data.element_type_=Domain::line;
      else if ( data.element_type_ == Domain::tetra)
        data.element_type_=Domain::triangle;

      geoms_data.add(data);
      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
      // Add fields at faces, localisation will be at nodes
      Nom options("from_faces,to_elem");
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  options, dim, fields_data,
                                  "operator_faces",
                                  data.source_domain_);
    }
    // Provide boundary mesh
    if (opt_.boundary_mesh && (element_type == Domain::hexa || element_type == Domain::tetra)) {
      data.internal_name_ = lata_geom_name;
      data.internal_name_ += "_Boundary";
      data.displayed_name_ = data.internal_name_;
      data.source_ = "operator_boundary";
      data.source_domain_ = lata_geom_name;
      geoms_data.add(data);
      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
      Nom options("from_elem,from_som");
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  options, dim, fields_data,
                                  "operator_boundary",
                                  data.source_domain_);
      options = "from_faces,to_elem";
      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
                                  options, dim, fields_data,
                                  "operator_boundary",
                                  data.source_domain_);
    }
  }

  if (user_fields_.non_nul())
    user_fields_.valeur().new_fields_metadata(*this, fields_data);
}
示例#27
0
bool CUserPageBuilder::Build(CWholePage* pWholePage)
{
	// introducing the players - these will point to the XML objects required
	// to construct a user page
	CPageUI			Interface(m_InputContext);
	CUser*			pViewer = NULL;
	CUser			Owner(m_InputContext);
	CGuideEntry		Masthead(m_InputContext);
	CForum			PageForum(m_InputContext);
	CForum			Journal(m_InputContext);
	CPostList		RecentPosts(m_InputContext);
	CArticleList	RecentArticles(m_InputContext);
	CArticleList	RecentApprovals(m_InputContext);
	CCommentsList	RecentComments(m_InputContext);
	CArticleSubscriptionList	SubscribedUsersArticles(m_InputContext);
	
	CTDVString	sSecretKey;
	int			iSecretKey = 0;
	int			iUserID = 0;		// the user ID in the URL
	bool		bRegistering = false;
	bool		bSuccess = true;	// our success flag

	// get the user ID from the URL => zero if not present
	// TODO: something appropriate if no ID provided	
	iUserID = m_InputContext.GetParamInt("UserID");
	// now get the secret key if there is one
	// we may need to process it so get it as a string
	if (m_InputContext.GetParamString("Key", sSecretKey))
	{
		// if the secret key start with "3D" we must strip this off
		// - it is caused by a mime encoding problem, 3D is the ascii hex for =
		if (sSecretKey.Find("3D") == 0)
		{
			sSecretKey =  sSecretKey.Mid(2);
		}
		iSecretKey = atoi(sSecretKey);
		if (iSecretKey > 0)
		{
			// if there is a secret key then it is a registration attempt
			bRegistering = true;
		}
	}
	// now give appropriate page depending on whether this is a registration or not
	if (bRegistering)
	{
//		CStoredProcedure* pSP = m_InputContext.CreateStoredProcedureObject();
		CTDVString sPageContent = "";
		CTDVString sPageSubject = "";
//		CTDVString sCookie;

		// check we got our SP okay
//		if (pSP == NULL)
//		{
//			bSuccess = false;
//		}
		// if so then call the activate user method, which should return us a nice
		// warm cookie if all goes well
//		if (bSuccess)
//		{
//			bSuccess = pSP->ActivateUser(iUserID, iSecretKey, &sCookie);
			// make sure cookie is not empty
//			if (sCookie.IsEmpty())
//			{
//				bSuccess = false;
//			}
//		}
		// if okay then build page with the cookie in and a message to the user
		if (bSuccess)
		{
			// we have a cookie and we are prepared to use it
			// TODO: what about the MEMORY tag?
			// TODO: put this in stylesheet? Deal with delayed refresh?
//			CTDVString sCookieXML = "<SETCOOKIE><COOKIE>" + sCookie + "</COOKIE></SETCOOKIE>";

//			sPageSubject = "Registration in process ...";
//			sPageContent << "<GUIDE><BODY>";
//			sPageContent << "<P>Thank you for registering as an official Researcher for The Hitch Hiker's ";
//			sPageContent << "Guide to the Galaxy: we do hope you enjoy contributing to the Guide.</P>";
//			sPageContent << "<P>Please wait while you are transferred to <LINK BIO=\"U" << iUserID << "\">";
//			sPageContent << "your Personal Home Page</LINK> ... or click the link if nothing happens.</P>";
//			sPageContent << "</BODY></GUIDE>";
//			pWholePage = CreateSimplePage(sPageSubject, sPageContent);
//			if (pWholePage == NULL)
//			{
//				bSuccess = false;
//			}

			if (bSuccess)
			{
				bSuccess = InitPage(pWholePage, "USERPAGE",false);
			}
			// put the cookie xml inside the H2G2 tag
//			bSuccess = pWholePage->AddInside("H2G2", sCookieXML);

//			CTDVString sUserXML = "";
//			sUserXML << "<REGISTERING-USER>";
//			sUserXML << "<USER>";
//			sUserXML << "<USERNAME></USERNAME>";
//			sUserXML << "<USERID>" << iUserID << "</USERID>";
//			sUserXML << "</USER>";
//			sUserXML << "</REGISTERING-USER>";
//			bSuccess = pWholePage->AddInside("H2G2", sUserXML);
//			bSuccess = bSuccess && pWholePage->SetPageType("REGISTER-CONFIRMATION");

		CTDVString sRedirect;
		sRedirect << "ShowTerms" << iUserID;
		sRedirect << "?key=" << sSecretKey;
		pWholePage->Redirect(sRedirect);
		}
		else
		{
			sPageSubject = "Sorry ...";
			sPageContent << "<GUIDE><BODY>";
			sPageContent << "<P>The URL you've given is wrong. Please re-check your email, or <LINK HREF=\"/Register\">click here to re-enter your email address</LINK>.</P>";
			sPageContent << "</BODY></GUIDE>";
			bSuccess = CreateSimplePage(pWholePage, sPageSubject, sPageContent);
		}
		// make sure we delete the SP if any
//		delete pSP;
//		pSP = NULL;
	}
	else
	{
		// get or create all the appropriate xml objects
		pViewer		= m_InputContext.GetCurrentUser();
		bool bGotMasthead = false; 
		bool bGotPageForum = false; 
		bool bGotJournal = false; 
		bool bGotRecentPosts = false; 
		bool bGotRecentArticles = false; 
		bool bGotRecentApprovals = false; 
		bool bGotRecentComments = false; 
		bool bGotSubscribedToUsersRecentArticles = false; 

		bool bGotOwner		= CreatePageOwner(iUserID, Owner);

		CreatePageTemplate(pWholePage);
		if (m_InputContext.IncludeUsersGuideEntryInPersonalSpace() || (m_InputContext.GetParamInt("i_uge") == 1) ||
			m_InputContext.IncludeUsersGuideEntryForumInPersonalSpace() || (m_InputContext.GetParamInt("i_ugef") == 1))
		{
			bGotMasthead = CreatePageArticle(iUserID, Owner, Masthead);

			if (m_InputContext.IncludeUsersGuideEntryForumInPersonalSpace() || (m_InputContext.GetParamInt("i_ugef") == 1))
			{
				// GuideEntry forum can not be returned if GuideEntry is not being returned.
				bGotPageForum = CreatePageForum(pViewer, Masthead, PageForum);
			}
		}

		bool bGotInterface = CreateUserInterface(pViewer, Owner, Masthead, Interface);
		
		// Only display other information if the page has a valid masthead
		if (bGotMasthead)
		{
			if (m_InputContext.IncludeJournalInPersonalSpace() || (m_InputContext.GetParamInt("i_j") == 1))
			{
				bGotJournal = CreateJournal(Owner, pViewer, Journal);
			}

			if (m_InputContext.IncludeRecentPostsInPersonalSpace() || (m_InputContext.GetParamInt("i_rp") == 1))
			{
				bGotRecentPosts = CreateRecentPosts(Owner, pViewer, RecentPosts);
			}

			if (m_InputContext.IncludeRecentCommentsInPersonalSpace() || (m_InputContext.GetParamInt("i_rc") == 1))
			{
				bGotRecentComments = CreateRecentComments(Owner, pViewer, RecentComments);
			}

			if (m_InputContext.IncludeRecentGuideEntriesInPersonalSpace() || (m_InputContext.GetParamInt("i_rge") == 1))
			{
				bGotRecentArticles = CreateRecentArticles(Owner, RecentArticles);
				bGotRecentApprovals = CreateRecentApprovedArticles(Owner, RecentApprovals);
			}

			if (m_InputContext.IncludeUploadsInPersonalSpace() || (m_InputContext.GetParamInt("i_u") == 1))
			{
				CTDVString sUploadsXML;
				CUpload Upload(m_InputContext);
				Upload.GetUploadsForUser(iUserID,sUploadsXML);
				pWholePage->AddInside("H2G2",sUploadsXML);
			}

			if (m_InputContext.IncludeRecentArticlesOfSubscribedToUsersInPersonalSpace() || (m_InputContext.GetParamInt("i_rasu") == 1))
			{
				bGotSubscribedToUsersRecentArticles = CreateSubscribedToUsersRecentArticles(Owner, m_InputContext.GetSiteID(), SubscribedUsersArticles); 
			}
		}

		// See if the user wants to swap to this site and change their masthead and journal (if it exists)
/*
	This feature is now redundant. There's no concept of a homesite.
		if (m_InputContext.ParamExists("homesite"))
		{
			if (pViewer == NULL)
			{
				// error: Not registered - ignore request
			}
			else if (!bGotOwner)
			{
				// error - no actual owner, ignore request
			}
			else if (pViewer->GetIsEditor())
			{
				int iCurrentSiteID = m_InputContext.GetSiteID();
				int iThisSite = iCurrentSiteID;
				if (bGotMasthead)
				{
					iCurrentSiteID = Masthead.GetSiteID();
				}
				if ( iThisSite != iCurrentSiteID && m_InputContext.CanUserMoveToSite(iCurrentSiteID, iThisSite))
				{
					CStoredProcedure SP;
					m_InputContext.InitialiseStoredProcedureObject(&SP);
					if (bGotMasthead)
					{
						SP.MoveArticleToSite(Masthead.GetH2G2ID(), m_InputContext.GetSiteID());
						//delete pMasthead;
						Masthead.Destroy();
						bGotMasthead = CreatePageArticle(iUserID, Owner, Masthead);
					}
					int iJournal;
					Owner.GetJournal(&iJournal);
					if (iJournal > 0)
					{
						SP.MoveForumToSite(iJournal, m_InputContext.GetSiteID());
					}

					int iPrivateForum;
					if (Owner.GetPrivateForum(&iPrivateForum))
					{
						SP.MoveForumToSite(iPrivateForum, m_InputContext.GetSiteID());
					}
					pWholePage->AddInside("H2G2", "<SITEMOVED RESULT='success'/>");
				}
			}
		}
*/
		// check that all the *required* objects have been created successfully
		// note that pViewer can be NULL if an unregistered viewer
		// pOwner can be NULL if we are serving a default page because this user ID
		// does not exist
		// bGotJournal can be false if the user doesn't exist, or has no journal
		// bGotRecentPosts can be false if the user doesn't exist
		// pRecentArticles can be NULL if the user doesn't exist
		// pRecentApprovals can be NULL if the user doesn't exist
		// bGotPageForum can be false if there is no masthead, or if it has no forum yet
		// pMasthead could be NULL if the user has not created one yet
		if (pWholePage->IsEmpty() || bGotInterface == false)
		{
			bSuccess = false;
		}
		// now add all the various subcomponents into the whole page xml
		// add owner of page
		if (bSuccess)
		{
			// if we have a page owner then put their details in, otherwise make
			// up a pretend user from the ID we were given
			if (bGotOwner)
			{
				bSuccess = pWholePage->AddInside("PAGE-OWNER", &Owner);
			}
			else
			{
				CTDVString sPretendUserXML = "";
				sPretendUserXML << "<USER><USERID>" << iUserID << "</USERID>";
				sPretendUserXML << "<USERNAME>Researcher " << iUserID << "</USERNAME></USER>";
				bSuccess = pWholePage->AddInside("PAGE-OWNER", sPretendUserXML);
			}
		}
		// there should always be an interface but check anyway
		if (bSuccess && bGotInterface)
		{
			bSuccess = pWholePage->AddInside("H2G2", &Interface);
		}
		if (bSuccess && m_InputContext.ParamExists("clip"))
		{
			CTDVString sSubject;
			if (bGotOwner)
			{
				Owner.GetUsername(sSubject);
			}
			else
			{
				sSubject << "U" << iUserID;
			}

			bool bPrivate = m_InputContext.GetParamInt("private") > 0;
			CLink Link(m_InputContext);
			if ( Link.ClipPageToUserPage("userpage", iUserID, sSubject, NULL, pViewer, bPrivate) )
				pWholePage->AddInside("H2G2", &Link);
		}
		// if masthead NULL stylesheet should do the default response
		if (bSuccess && bGotMasthead && (m_InputContext.IncludeUsersGuideEntryInPersonalSpace() || (m_InputContext.GetParamInt("i_uge") == 1)))
		{
			bSuccess = pWholePage->AddInside("H2G2", &Masthead);
		}
		// add page forum if there is one => this is the forum associated with
		// the guide enty that is the masthead for this user
		if (bSuccess && bGotPageForum && (m_InputContext.IncludeUsersGuideEntryForumInPersonalSpace() || (m_InputContext.GetParamInt("i_ugef") == 1)))
		{
			bSuccess = pWholePage->AddInside("H2G2", &PageForum);
		}
		// add journal if it exists
		if (bSuccess && bGotJournal)
		{
			bSuccess = pWholePage->AddInside("JOURNAL", &Journal);
		}
		// add recent posts if they exist, this may add an empty
		// POST-LIST tag if the user exists but has never posted
		if (bSuccess && bGotRecentPosts)
		{
			bSuccess = pWholePage->AddInside("RECENT-POSTS", &RecentPosts);
		}
		// add recent articles if they exist, this may add an empty
		// ARTICLES-LIST tag if the user exists but has never written a guide entry
		if (bSuccess && bGotRecentArticles)
		{
			bSuccess = pWholePage->AddInside("RECENT-ENTRIES", &RecentArticles);
			// add the user XML for the owner too
			if (bGotOwner)
			{
				bSuccess = bSuccess && pWholePage->AddInside("RECENT-ENTRIES", &Owner);
			}
		}
		// add recent articles if they exist, this may add an empty
		// ARTICLES-LIST tag if the user exists but has never had an entry approved
		if (bSuccess && bGotRecentApprovals)
		{
			bSuccess = pWholePage->AddInside("RECENT-APPROVALS", &RecentApprovals);
			// add the user XML for the owner too
			if (bGotOwner)
			{
				bSuccess = bSuccess && pWholePage->AddInside("RECENT-APPROVALS", &Owner);
			}
		}
		// add recent comments if they exist, this may add an empty
		// COMMENTS-LIST tag if the user exists but has never posted
		if (bSuccess && bGotRecentComments)
		{
			bSuccess = pWholePage->AddInside("RECENT-COMMENTS", &RecentComments);
		}

		if (bSuccess && bGotSubscribedToUsersRecentArticles)
		{
			bSuccess = pWholePage->AddInside("RECENT-SUBSCRIBEDARTICLES", &SubscribedUsersArticles);
		}

		CTDVString sSiteXML;
		m_InputContext.GetSiteListAsXML(&sSiteXML);
		bSuccess = bSuccess && pWholePage->AddInside("H2G2", sSiteXML);

		if (bGotMasthead && (m_InputContext.IncludeWatchInfoInPersonalSpace() || (m_InputContext.GetParamInt("i_wi") == 1)))
		{
			CWatchList WatchList(m_InputContext);
			bSuccess = bSuccess && WatchList.Initialise(iUserID);
			bSuccess = bSuccess && pWholePage->AddInside("H2G2",&WatchList);
			int iSiteID = m_InputContext.GetSiteID();
			bSuccess = bSuccess && WatchList.WatchingUsers(iUserID, iSiteID);
			bSuccess = bSuccess && pWholePage->AddInside("H2G2",&WatchList);
		}

		CWhosOnlineObject Online(m_InputContext);
		bSuccess = bSuccess && Online.Initialise(NULL, 1, true);
		bSuccess = bSuccess && pWholePage->AddInside("H2G2", &Online);

		if (bGotMasthead && (m_InputContext.IncludeClubsInPersonalSpace() || (m_InputContext.GetParamInt("i_c") == 1)))
		{
			if (pViewer != NULL && pViewer->GetUserID() == iUserID) 
			{
				CClub Club(m_InputContext);
				Club.GetUserActionList(iUserID, 0, 20);
				pWholePage->AddInside("H2G2", &Club);
			}

			// Now add all the clubs the user belongs to
			CCurrentClubs Clubs(m_InputContext);
			if (bSuccess && Clubs.CreateList(iUserID,true))
			{
				bSuccess = pWholePage->AddInside("H2G2",&Clubs);
			}
		}
		
		if (bGotMasthead && bSuccess && (m_InputContext.IncludePrivateForumsInPersonalSpace() || (m_InputContext.GetParamInt("i_pf") == 1)))
		{
			pWholePage->AddInside("H2G2", "<PRIVATEFORUM/>");
			CForum Forum(m_InputContext);
			int iPrivateForum = 0;
			if (bGotOwner)
			{
				Owner.GetPrivateForum(&iPrivateForum);
			}
			Forum.GetThreadList(pViewer, iPrivateForum, 10,0);
			pWholePage->AddInside("PRIVATEFORUM", &Forum);

			// Now check to see if the user has alerts set for their private forum
			if (bGotOwner)
			{
				CEmailAlertList Alert(m_InputContext);
				Alert.GetUserEMailAlertSubscriptionForForumAndThreads(iUserID,iPrivateForum);
				pWholePage->AddInside("PRIVATEFORUM", &Alert);
			}
		}

		if (bGotMasthead && bSuccess && (m_InputContext.IncludeLinksInPersonalSpace() || (m_InputContext.GetParamInt("i_l") == 1)))
		{
			CTDVString sLinkGroup;
			m_InputContext.GetParamString("linkgroup", sLinkGroup);
			if (bGotOwner && pViewer != NULL && Owner.GetUserID() == pViewer->GetUserID()) 
			{
				ManageClippedLinks(pWholePage);
			}
			if (bGotOwner)
			{
				CLink Link(m_InputContext);
				bool bShowPrivate = (pViewer != NULL && Owner.GetUserID() == pViewer->GetUserID());
				Link.GetUserLinks(Owner.GetUserID(), sLinkGroup, bShowPrivate);
				pWholePage->AddInside("H2G2", &Link);
				Link.GetUserLinkGroups(Owner.GetUserID());
				pWholePage->AddInside("H2G2", &Link);
			}
		}

		if (bGotMasthead && m_InputContext.IncludeTaggedNodesInPersonalSpace() || (m_InputContext.GetParamInt("i_tn") == 1))
		{
			//Get the Users Crumtrail - all the nodes + ancestors the user is tagged to .
			CCategory CCat(m_InputContext);
			if ( bSuccess && CCat.GetUserCrumbTrail(Owner.GetUserID()) )
			{
				bSuccess = pWholePage->AddInside("H2G2",&CCat);
			}
		}

		if (bSuccess && bGotMasthead)
		{
			CTDVString sPostCodeXML;
			CTDVString sNoticeXML;
			if (m_InputContext.IncludeNoticeboardInPersonalSpace() || (m_InputContext.GetParamInt("i_n") == 1) ||
				m_InputContext.IncludePostcoderInPersonalSpace() || (m_InputContext.GetParamInt("i_p") == 1))
			{
				if (pViewer != NULL)
				{
					// Insert the notice board information!
					CTDVString sPostCodeToFind;
					if(pViewer->GetPostcode(sPostCodeToFind))
					{
						int iSiteID = m_InputContext.GetSiteID();
						CNotice Notice(m_InputContext);
						if (!Notice.GetLocalNoticeBoardForPostCode(sPostCodeToFind,iSiteID,sNoticeXML,sPostCodeXML))
						{
							sNoticeXML << "<NOTICEBOARD><ERROR>FailedToFindLocalNoticeBoard</ERROR></NOTICEBOARD>";
						}
					}
					else
					{
						//if the user has not entered a postcode then flag an Notice Board error
						sNoticeXML << "<NOTICEBOARD><ERROR>UserNotEnteredPostCode</ERROR></NOTICEBOARD>";
					}
				}
				else
				{
					sNoticeXML << "<NOTICEBOARD><ERROR>UserNotLoggedIn</ERROR></NOTICEBOARD>";
				}

				if (m_InputContext.IncludeNoticeboardInPersonalSpace() || (m_InputContext.GetParamInt("i_n") == 1))
				{
					bSuccess = pWholePage->AddInside("H2G2",sNoticeXML);
				}
			}

			if (m_InputContext.IncludePostcoderInPersonalSpace() || (m_InputContext.GetParamInt("i_p") == 1))
			{
				// Insert the postcoder if it's not empty
				if (bSuccess && !sPostCodeXML.IsEmpty())
				{
					bSuccess = bSuccess && pWholePage->AddInside("H2G2",sPostCodeXML);
				}
			}
		}

		if (m_InputContext.IncludeSiteOptionsInPersonalSpace() || (m_InputContext.GetParamInt("i_so") == 1))
		{
			// Return SiteOption SystemMessageOn if set. 
			if (bSuccess && m_InputContext.IsSystemMessagesOn(m_InputContext.GetSiteID()))
			{
				CTDVString sSiteOptionSystemMessageXML = "<SITEOPTION><NAME>UseSystemMessages</NAME><VALUE>1</VALUE></SITEOPTION>"; 

				bSuccess = bSuccess && pWholePage->AddInside("H2G2",sSiteOptionSystemMessageXML);
			}
		}
		
/*
		Mark Howitt 11/8/05 - Removing the civic data from the user page as it is nolonger used by any sites.
							  The only place civic data is used now is on the postcoder page.

		//include civic data
		if (bSuccess)
		{
			if ( m_InputContext.GetSiteID( ) == 16 )
			{
				CTDVString sActualPostCode;				
				bool bFoundLocalInfo = false;
				// First check to see if there is a postcode in the URL
				if (m_InputContext.ParamExists("postcode"))
				{
					// Get the postcode and use this to display the noticeboard
					if (m_InputContext.GetParamString("postcode", sActualPostCode))
					{
						//dont do any validations
						bFoundLocalInfo = true;				
					}
				}

				//next if no postcode variable is included in URL
				//or if the specified postcode value is invalid 
				//or if the specified postcode value has no entries on the db				
				if (!bFoundLocalInfo)
				{
					// No postcode given, try to get the viewing users postcode if we have one.
					if (pViewer)
					{
						if (pViewer->GetPostcode(sActualPostCode))
						{
							if ( sActualPostCode.IsEmpty( ) == false)
							{
								//dont do any validations
								bFoundLocalInfo = true;
							}
						}							
					}
					else
					{
						//try session cookie, if any 
						CTDVString sPostCodeToFind;
						CPostcoder postcoder(m_InputContext);
						CTDVString sActualPostCode = postcoder.GetPostcodeFromCookie();
						if ( !sActualPostCode.IsEmpty() )
						{
							//dont do any validations
							bFoundLocalInfo = true;
						}
					}
				}

				if ( bFoundLocalInfo )
				{
					if (!sActualPostCode.IsEmpty())
					{
						bool bHitPostcode = false;
						CPostcoder cPostcoder(m_InputContext);
						cPostcoder.MakePlaceRequest(sActualPostCode, bHitPostcode);
						if (bHitPostcode)
						{
							CTDVString sXML = "<CIVICDATA POSTCODE='";
							sXML << sActualPostCode << "'/>";
							pWholePage->AddInside("H2G2", sXML);
							bSuccess = pWholePage->AddInside("CIVICDATA",&cPostcoder);
						}
					}
				}
			}
		}
*/
	}

	return bSuccess;
}
// Description: this method must return the total memory consumption
//  of the object (used to compute the size of the data cache)
BigEntier LataObject::compute_memory_size() const
{
  Journal() << "Error in LataObject::compute_memory_size(): function not implemented" << endl;
  throw;
}
void set_Journal_level(entier level)
{
  journal_level = level;
  Journal() << "Changed lata journal level: " << journal_level << endl;
}
// Description: 
//  Returns a reference to the requested geometry.
//  If the geometry is not found at the requested timestep, it
//  is seached in the first timestep.
//  If the geometry does not exist in the cache, all needed data is loaded
//   and the geometry is allocated and built in the internal cache.
//  The reference is valid until the user calls release_geometry()
//  The user MUST call release_geometry() to allow the data to be
//   removed from the data cache.
const Domain & LataFilter::get_geometry(const Domain_Id & id)
{
  Journal(filter_info_level) << "LataFilter::get_geometry " 
                             << id.name_ << " time=" << id.timestep_ 
                             << " bloc=" << id.block_ << endl;
  data_cache_.cleanup_cache(id.timestep_);

  Domain_Id requested_id(id);
  // Get the real timestep where this domain is stored:
  const LataGeometryMetaData & geom_metadata = get_geometry_metadata(id.name_);
  if (geom_metadata.dynamic_) 
    requested_id.timestep_ = id.timestep_;
  else
    requested_id.timestep_ = 0;

  LataDeriv<Domain> & dom_ptr = get_cached_domain(requested_id);
  if (!dom_ptr.non_nul()) {
    if (geom_metadata.source_ == "latadb") {
      // Request for a native domain : load it from lataDB
      // If reconnect and loading all subdomains, go ! Don't store the operator in cache since it's
      //  not required to process fields.
      
      // Is it a structured or unstructured mesh ?
      if (lataDB().field_exists(requested_id.timestep_, requested_id.name_, "SOMMETS")) 
        {
          DomainUnstructured & dom = dom_ptr.instancie(DomainUnstructured);
      
          if (opt_.reconnect) {
            // Bloc demande, peut etre le bloc 0 ou le bloc -1:
            const entier req_block = requested_id.block_;
            if (requested_id.block_ > 0) {
              Cerr << "Error: requesting block " << requested_id.block_ << " with reconnect option" << endl;
//              exit(-1);
            }
            requested_id.block_ = -1; // load all blocks
            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, 0);
            Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance);
            dom.id_.block_ = req_block;
          } else {
            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, opt_.load_virtual_elements ? 1 : 0);
            if (opt_.load_virtual_elements && dom.nb_virt_items(LataField_base::ELEM) > 0) {
              Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance,
                                            dom.nb_nodes() - dom.nb_virt_items(LataField_base::SOM));
            }
          }
        }
      else
        {
          // Structured ijk:
          DomainIJK & dom = dom_ptr.instancie(DomainIJK);
          if (opt_.reconnect || requested_id.block_ < 0) {
            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* parallel splitting */, 
                                        0 /* no virtual elements */);
          } else {
            const entier nparts = opt_.ijk_mesh_nb_parts_;
            const entier virtual_size = opt_.load_virtual_elements ? opt_.ijk_virt_layer : 0;
            dom.fill_domain_from_lataDB(lataDB(), requested_id, nparts /* parallel splitting */, 
                                        virtual_size /* with virtual elements */);
          }
        }
    } else if (geom_metadata.source_.debute_par("OPERATOR")) {
      const Domain & src_domain = get_geometry(Domain_Id(geom_metadata.source_domain_, 
                                                         requested_id.timestep_,
                                                         requested_id.block_));
      Operator & op = get_set_operator(requested_id);
      op.build_geometry(src_domain, dom_ptr);
      dom_ptr.valeur().id_ = requested_id;
      release_cached_operator(requested_id);
      release_geometry(src_domain);
    } else {
      Journal() << "Unknown source in geometry metadata " << geom_metadata.source_ << endl;
      throw;
    }
  }

  return dom_ptr.valeur();
}