[cig-commits] r8352 - in short/3D/PyLith/trunk: . libsrc/bc libsrc/feassemble libsrc/topology modulesrc/topology pylith/faults pylith/topology unittests/libtests/topology unittests/libtests/topology/data unittests/pytests/topology unittests/pytests/topology/data

brad at geodynamics.org brad at geodynamics.org
Thu Nov 29 16:03:12 PST 2007


Author: brad
Date: 2007-11-29 16:03:10 -0800 (Thu, 29 Nov 2007)
New Revision: 8352

Modified:
   short/3D/PyLith/trunk/TODO
   short/3D/PyLith/trunk/libsrc/bc/AbsorbingDampers.cc
   short/3D/PyLith/trunk/libsrc/bc/Dirichlet.cc
   short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.cc
   short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.hh
   short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.cc
   short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.hh
   short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.cc
   short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.hh
   short/3D/PyLith/trunk/libsrc/topology/FieldsManager.cc
   short/3D/PyLith/trunk/libsrc/topology/FieldsManager.hh
   short/3D/PyLith/trunk/modulesrc/topology/topology.pyxe.src
   short/3D/PyLith/trunk/pylith/faults/FaultCohesiveKin.py
   short/3D/PyLith/trunk/pylith/topology/FieldsManager.py
   short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.cc
   short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.hh
   short/3D/PyLith/trunk/unittests/libtests/topology/data/tri3.mesh
   short/3D/PyLith/trunk/unittests/pytests/topology/TestFieldsManager.py
   short/3D/PyLith/trunk/unittests/pytests/topology/data/tri3.mesh
Log:
Added custom atlas routines to FieldsManager. Did a little work on logging too.

Modified: short/3D/PyLith/trunk/TODO
===================================================================
--- short/3D/PyLith/trunk/TODO	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/TODO	2007-11-30 00:03:10 UTC (rev 8352)
@@ -20,11 +20,16 @@
   1. EventLogging
    
      Check constraints/integrators.
+     Fault::adjustTopology()
+     High level events
+       MeshGenerator
+       Problem
   
   2. Optimization of restrict()/update()
+      UpdateState
+        Change disp to fields
+      Need to fix optimized ElasticityExplicit (something wrong)
 
-     Add tags management to FieldsManager
-
      a. Fault
      b. Absorbing BC
      c. Neumann BC

Modified: short/3D/PyLith/trunk/libsrc/bc/AbsorbingDampers.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/bc/AbsorbingDampers.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/bc/AbsorbingDampers.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -233,8 +233,8 @@
   const ALE::Obj<real_section_type>& coordinates = 
     mesh->getRealSection("coordinates");
   assert(!coordinates.isNull());
-  const ALE::Obj<real_section_type>& dispTpdt = fields->getHistoryItem(0);
-  const ALE::Obj<real_section_type>& dispTmdt = fields->getHistoryItem(2);
+  const ALE::Obj<real_section_type>& dispTpdt = fields->getFieldByHistory(0);
+  const ALE::Obj<real_section_type>& dispTmdt = fields->getFieldByHistory(2);
   assert(!dispTpdt.isNull());
   assert(!dispTmdt.isNull());
 
@@ -327,7 +327,7 @@
   const ALE::Obj<real_section_type>& coordinates = 
     mesh->getRealSection("coordinates");
   assert(!coordinates.isNull());
-  const ALE::Obj<real_section_type>& dispT = fields->getHistoryItem(1);
+  const ALE::Obj<real_section_type>& dispT = fields->getFieldByHistory(1);
   assert(!dispT.isNull());
 
   // Get parameters used in integration.

Modified: short/3D/PyLith/trunk/libsrc/bc/Dirichlet.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/bc/Dirichlet.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/bc/Dirichlet.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -196,11 +196,14 @@
   if (0 == numFixedDOF)
     return;
 
+
   const int numPoints = _points.size();
+  const int fiberDimension = 
+    (numPoints > 0) ? field->getFiberDimension(_points[0]) : 0;
+  double_array allValues(fiberDimension);
   for (int iPoint=0, i=0; iPoint < numPoints; ++iPoint) {
     const Mesh::point_type point = _points[iPoint];
-    const int fiberDimension = field->getFiberDimension(point);
-    double_array allValues(fiberDimension);
+    assert(fiberDimension == field->getFiberDimension(point));
     mesh->restrict(field, point, &allValues[0], fiberDimension);
     for (int iDOF=0; iDOF < numFixedDOF; ++iDOF)
       allValues[_fixedDOF[iDOF]] = _values[i++];

Modified: short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -28,7 +28,7 @@
 #include <assert.h> // USES assert()
 #include <stdexcept> // USES std::runtime_error
 
-#define FASTER
+//#define FASTER
 
 // ----------------------------------------------------------------------
 // Constructor
@@ -118,8 +118,9 @@
     assert(0);
 
   // Get cell information
+  const int materialId = _material->id();
   const ALE::Obj<ALE::Mesh::label_sequence>& cells = 
-    mesh->getLabelStratum("material-id", _material->id());
+    mesh->getLabelStratum("material-id", materialId);
   assert(!cells.isNull());
   const Mesh::label_sequence::iterator  cellsEnd = cells->end();
 
@@ -127,9 +128,9 @@
   const ALE::Obj<real_section_type>& coordinates = 
     mesh->getRealSection("coordinates");
   assert(!coordinates.isNull());
-  const ALE::Obj<real_section_type>& dispT = fields->getHistoryItem(1);
+  const ALE::Obj<real_section_type>& dispT = fields->getFieldByHistory(1);
   assert(!dispT.isNull());
-  const ALE::Obj<real_section_type>& dispTmdt = fields->getHistoryItem(2);
+  const ALE::Obj<real_section_type>& dispTmdt = fields->getFieldByHistory(2);
   assert(!dispTmdt.isNull());
 
   // Get parameters used in integration.
@@ -171,23 +172,17 @@
   } // for
 
 #ifdef FASTER
-  if (_dispTags.find(_material->id()) == _dispTags.end()) {
-    _dispTags[_material->id()] = 
-      mesh->calculateCustomAtlas(dispT, cells);
-  } // if
-  const int dispTTag = _dispTags[_material->id()];
+  fields->createCustomAtlas("material-id", materialId);
+  const int dispTAtlasTag = 
+    fields->getFieldAtlasTagByHistory(1, materialId);
+  const int dispTmdtAtlasTag = 
+    fields->getFieldAtlasTagByHistory(2, materialId);
 
-  if (_dispTmdtTags.find(_material->id()) == _dispTmdtTags.end()) {
-    _dispTmdtTags[_material->id()] = 
-      dispTmdt->copyCustomAtlas(dispT, _dispTags[_material->id()]);
+  if (_residualAtlasTags.find(materialId) == _residualAtlasTags.end()) {
+    _residualAtlasTags[materialId] = 
+      residual->copyCustomAtlas(dispT, dispTAtlasTag);
   } // if
-  const int dispTmdtTag = _dispTmdtTags[_material->id()];
-
-  if (_residualTags.find(_material->id()) == _residualTags.end()) {
-    _residualTags[_material->id()] = 
-      residual->copyCustomAtlas(dispT, _dispTags[_material->id()]);
-  } // if
-  const int residualTag = _residualTags[_material->id()];
+  const int residualAtlasTag = _residualAtlasTags[materialId];
 #endif
 
   int c_index = 0;
@@ -204,9 +199,9 @@
     _resetCellVector();
 
 #ifdef FASTER
-    mesh->restrict(dispT, dispTTag, c_index, &dispTCell[0], 
+    mesh->restrict(dispT, dispTAtlasTag, c_index, &dispTCell[0], 
 		   cellVecSize);
-    mesh->restrict(dispTmdt, dispTmdtTag, c_index, &dispTmdtCell[0], 
+    mesh->restrict(dispTmdt, dispTmdtAtlasTag, c_index, &dispTmdtCell[0], 
 		   cellVecSize);
 #else
     mesh->restrict(dispT, *c_iter, &dispTCell[0], cellVecSize);
@@ -245,7 +240,7 @@
 
     // Assemble cell contribution into field
 #ifdef FASTER
-    mesh->updateAdd(residual, residualTag, c_index, _cellVector);
+    mesh->updateAdd(residual, residualAtlasTag, c_index, _cellVector);
 #else
     mesh->updateAdd(residual, *c_iter, _cellVector);
 #endif
@@ -277,7 +272,7 @@
   const ALE::Obj<real_section_type>& coordinates = 
     mesh->getRealSection("coordinates");
   assert(!coordinates.isNull());
-  const ALE::Obj<real_section_type>& dispT = fields->getHistoryItem(1);
+  const ALE::Obj<real_section_type>& dispT = fields->getFieldByHistory(1);
   assert(!dispT.isNull());
 
   // Get parameters used in integration.

Modified: short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.hh
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.hh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/ElasticityExplicit.hh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -139,9 +139,6 @@
 
   double _dtm1; ///< Time step for t-dt1 -> t
 
-  // Optimization
-  std::map<int, int> _dispTmdtTags; ///< Tags indexing dispTmdt field
-
 }; // ElasticityExplicit
 
 #endif // pylith_feassemble_elasticityexplicit_hh

Modified: short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -135,8 +135,9 @@
     assert(0);
 
   // Get cell information
+  const int materialId = _material->id();
   const ALE::Obj<ALE::Mesh::label_sequence>& cells = 
-    mesh->getLabelStratum("material-id", _material->id());
+    mesh->getLabelStratum("material-id", materialId);
   assert(!cells.isNull());
   const Mesh::label_sequence::iterator  cellsEnd = cells->end();
 
@@ -156,17 +157,14 @@
   const int spaceDim = _quadrature->spaceDim();
 
 #ifdef FASTER
-  if (_dispTags.find(_material->id()) == _dispTags.end()) {
-    _dispTags[_material->id()] = 
-      mesh->calculateCustomAtlas(dispTBctpdt, cells);
+  fields->createCustomAtlas("material-id", materialId);
+  const int dispAtlasTag = fields->getFieldAtlasTag("dispTBctpdt", materialId);
+
+  if (_residualAtlasTags.find(materialId) == _residualAtlasTags.end()) {
+    _residualAtlasTags[materialId] = 
+      residual->copyCustomAtlas(dispTBctpdt, dispAtlasTag);
   } // if
-  const int dispTBctpdtTag = _dispTags[_material->id()];
-  
-  if (_residualTags.find(_material->id()) == _residualTags.end()) {
-    _residualTags[_material->id()] = 
-      residual->copyCustomAtlas(dispTBctpdt, _dispTags[_material->id()]);
-  } // if
-  const int residualTag = _residualTags[_material->id()];
+  const int residualAtlasTag = _residualAtlasTags[materialId];
 #endif
   // Precompute the geometric and function space information
   _quadrature->precomputeGeometry(mesh, coordinates, cells);
@@ -206,7 +204,7 @@
     // Restrict input fields to cell
     PetscLogEventBegin(restrictEvent,0,0,0,0);
 #ifdef FASTER
-    mesh->restrict(dispTBctpdt, dispTBctpdtTag, c_index, &dispTBctpdtCell[0], 
+    mesh->restrict(dispTBctpdt, dispAtlasTag, c_index, &dispTBctpdtCell[0], 
 		   cellVecSize);
 #else
     mesh->restrict(dispTBctpdt, *c_iter, &dispTBctpdtCell[0], cellVecSize);
@@ -265,7 +263,7 @@
     // Assemble cell contribution into field
     PetscLogEventBegin(updateEvent,0,0,0,0);
 #ifdef FASTER
-    mesh->updateAdd(residual, residualTag, c_index, _cellVector);
+    mesh->updateAdd(residual, residualAtlasTag, c_index, _cellVector);
 #else
     mesh->updateAdd(residual, *c_iter, _cellVector);
 #endif
@@ -320,8 +318,9 @@
     assert(0);
 
   // Get cell information
+  const int materialId = _material->id();
   const ALE::Obj<ALE::Mesh::label_sequence>& cells = 
-    mesh->getLabelStratum("material-id", _material->id());
+    mesh->getLabelStratum("material-id", materialId);
   assert(!cells.isNull());
   const Mesh::label_sequence::iterator  cellsEnd = cells->end();
 
@@ -364,11 +363,8 @@
   } // for
 
 #ifdef FASTER
-  if (_dispTags.find(_material->id()) == _dispTags.end()) {
-    _dispTags[_material->id()] = 
-      mesh->calculateCustomAtlas(dispTBctpdt, cells);
-  } // if
-  const int dispTBctpdtTag = _dispTags[_material->id()];
+  fields->createCustomAtlas("material-id", materialId);
+  const int dispAtlasTag = fields->getFieldAtlasTag("dispTBctpdt", materialId);
 #endif
 
   // Loop over cells
@@ -387,7 +383,7 @@
 
     // Restrict input fields to cell
 #ifdef FASTER
-    mesh->restrict(dispTBctpdt, dispTBctpdtTag, c_index, &dispTBctpdtCell[0], 
+    mesh->restrict(dispTBctpdt, dispAtlasTag, c_index, &dispTBctpdtCell[0], 
 		   cellVecSize);
 #else
     mesh->restrict(dispTBctpdt, *c_iter, &dispTBctpdtCell[0], cellVecSize);

Modified: short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.hh
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.hh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/ElasticityImplicit.hh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -138,9 +138,6 @@
 
   double _dtm1; ///< Time step for t-dt1 -> t
 
-  // Optimization
-  std::map<int, int> _dispTBctpdtTags; ///< Tags indexing dispTBctpdt field.
-
 }; // ElasticityImplicit
 
 #endif // pylith_feassemble_elasticityimplicit_hh

Modified: short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -23,7 +23,7 @@
 #include <assert.h> // USES assert()
 #include <stdexcept> // USES std::runtime_error
 
-#define FASTER
+//#define FASTER
 
 // ----------------------------------------------------------------------
 // Constructor
@@ -122,8 +122,8 @@
   } // for
 
 #ifdef FASTER
-  assert(_dispTags.find(_material->id()) != _dispTags.end());
-  const int dispTag = _dispTags[_material->id()];
+  fields->createCustomAtlas("material-id", materialId);
+  const int dispAtlasTag = fields.getSolnFieldAtlasTag(materialId);
 #endif
   
   // Loop over cells
@@ -136,7 +136,7 @@
 
     // Restrict input fields to cell
 #ifdef FASTER
-    mesh->restrict(disp, dispTag, c_index, &dispCell[0], cellVecSize);
+    mesh->restrict(disp, dispAtlasTag, c_index, &dispCell[0], cellVecSize);
 #else
     mesh->restrict(disp, *c_iter, &dispCell[0], cellVecSize);
 #endif

Modified: short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.hh
===================================================================
--- short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.hh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/feassemble/IntegratorElasticity.hh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -182,8 +182,7 @@
   materials::ElasticMaterial* _material;
 
   // Optimization
-  std::map<int, int> _dispTags; ///< Tags indexing displacement field.
-  std::map<int, int> _residualTags; ///< Tags indexing residual field.
+  std::map<int, int> _residualAtlasTags; ///< Tags indexing residual field.
 
 }; // IntegratorElasticity
 

Modified: short/3D/PyLith/trunk/libsrc/topology/FieldsManager.cc
===================================================================
--- short/3D/PyLith/trunk/libsrc/topology/FieldsManager.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/topology/FieldsManager.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -61,7 +61,7 @@
     msg << "Could not find field '" << name << "'.";
     throw std::runtime_error(msg.str());
   } // if
-  return _real[name];
+  return iter->second;
 } // getReal
 
 // ----------------------------------------------------------------------
@@ -244,11 +244,116 @@
 // ----------------------------------------------------------------------
 // Get field in history by position.
 const ALE::Obj<pylith::real_section_type>&
-pylith::topology::FieldsManager::getHistoryItem(const int index)
-{ // getHistoryItem
+pylith::topology::FieldsManager::getFieldByHistory(const int index)
+{ // getFieldByHistory
   assert(index < _history.size());
   return getReal(_history[index].c_str());
-} // getHistoryItem
+} // getFieldByHistory
 
+// ----------------------------------------------------------------------
+// Create custom atlases for fields.
+void
+pylith::topology::FieldsManager::createCustomAtlas(const char* label,
+						   const int id)
+{ // createCustomAtlas
+  typedef std::map<int,int> map_tag_type;
 
+  assert(!_mesh.isNull());
+
+  const map_real_type::iterator f_begin = _real.begin();
+  const map_real_type::iterator f_end = _real.end();
+
+  if (f_begin == f_end) // If we don't have any fields, just return
+    return;
+  
+  // Get cells with label 'label' set to 'id'
+  const ALE::Obj<Mesh::label_sequence>& cells = 
+    _mesh->getLabelStratum(label, id);
+
+  // Create custom atlas in first field
+  const ALE::Obj<real_section_type>& field0 = f_begin->second;
+  assert(!field0.isNull());
+  int field0Tag = 0;
+  bool alreadySet = true;
+
+  const std::string& field0Name = f_begin->first;
+  map_tags_type::iterator t_iter = _tags.find(field0Name);
+  if (t_iter == _tags.end()) { // Need to create tags for field 'name'
+    map_tag_type fieldTags;
+    alreadySet = false;
+    fieldTags[id] = _mesh->calculateCustomAtlas(field0, cells);
+    field0Tag = fieldTags[id];
+    _tags[field0Name] = fieldTags;
+  } else { // Use tags already created
+    map_tag_type& fieldTags = t_iter->second;
+    if (fieldTags.find(id) == fieldTags.end()) { // Need to set tags for id
+      alreadySet = false;
+      fieldTags[id] = _mesh->calculateCustomAtlas(field0, cells);
+      field0Tag = fieldTags[id];
+    } // if
+  } // if/else
+  map_real_type::iterator f_iter=f_begin;
+  if (!alreadySet)
+    // Copy custom atlas in first field to other fields
+    for (++f_iter; f_iter != f_end; ++f_iter) {
+      assert(!f_iter->second.isNull());
+      const std::string& fieldName = f_iter->first;
+      t_iter = _tags.find(fieldName);
+      if (t_iter == _tags.end()) { // Need to create tags for field 'name'
+	map_tag_type fieldTags;
+	fieldTags[id] = f_iter->second->copyCustomAtlas(field0, field0Tag);
+	_tags[fieldName] = fieldTags;
+      } else { // Use tags already created
+	map_tag_type& fieldTags = t_iter->second;
+	if (fieldTags.find(id) == fieldTags.end()) // Need to set tags for id
+	  fieldTags[id] = f_iter->second->copyCustomAtlas(field0, field0Tag);
+      } // if/else
+    } // for
+} // createCustomAtlas
+
+// ----------------------------------------------------------------------
+// Get tag for field associated with label id.
+int
+pylith::topology::FieldsManager::getFieldAtlasTag(const char* name,
+						  const int id)
+{ // getFieldAtlasTag
+  map_tags_type::const_iterator t_iter = _tags.find(name);
+  if (t_iter == _tags.end()) {
+    std::ostringstream msg;
+    msg << "Could not find tags for field '" << name << "'.";
+    throw std::runtime_error(msg.str());
+  } // if
+  std::map<int,int>::const_iterator tag = t_iter->second.find(id);
+  if (tag == t_iter->second.end()) {
+    std::ostringstream msg;
+    msg << "Could not find tag for label '" << id
+	<< "' for field '" << name << "'.";
+    throw std::runtime_error(msg.str());
+  } // if
+
+  return tag->second;
+} // getFieldAtlasTag
+
+// ----------------------------------------------------------------------
+// Get tag for field in history by position.
+int
+pylith::topology::FieldsManager::getFieldAtlasTagByHistory(const int index,
+							   const int id)
+{ // getFieldAtlasTagByHistory
+  assert(index < _history.size());
+  return getFieldAtlasTag(_history[index].c_str(), id);
+} // getFieldAtlasTagByHistory
+
+// ----------------------------------------------------------------------
+// Get solution field atlas tag.
+int
+pylith::topology::FieldsManager::getSolutionAtlasTag(const int id)
+{ // getSolutionAtlasTag
+  if (_solutionName == "")
+    throw std::runtime_error("Cannot retrieve solution atlas tag. "
+			     "Name of solution field has not been specified.");
+  return getFieldAtlasTag(_solutionName.c_str(), id);
+} // getSolutionAtlasTag
+
+
 // End of file 

Modified: short/3D/PyLith/trunk/libsrc/topology/FieldsManager.hh
===================================================================
--- short/3D/PyLith/trunk/libsrc/topology/FieldsManager.hh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/libsrc/topology/FieldsManager.hh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -124,8 +124,41 @@
    * @param index Index in history [0=most recent, 1=previous, etc]
    * @returns Field in history.
    */
-  const ALE::Obj<real_section_type>& getHistoryItem(const int index);
+  const ALE::Obj<real_section_type>& getFieldByHistory(const int index);
 
+  /** Create custom atlases for fields.
+   *
+   * @param label Name of label.
+   * @param id Id associated with label.
+   * @returns Tag for custom atlask.
+   */
+  void createCustomAtlas(const char* label,
+			 const int id);
+  
+  /** Get atlas tag for field associated with label id.
+   *
+   * @param name Name of field.
+   * @param id Id associated with label.
+   * @returns Tag for custom atlask.
+   */
+  int getFieldAtlasTag(const char* name,
+		       const int id);
+  
+  /** Get tag for field in history by position.
+   *
+   * @param index Index in history [0=most recent, 1=previous, etc]
+   * @param id Id associated with label.
+   */
+  int getFieldAtlasTagByHistory(const int index,
+				const int id);
+
+  /** Get solution field atlas tag.
+   *
+   * @param id Id associated with label.
+   * @returns Tag for custom atlask.
+   */
+  int getSolutionAtlasTag(const int id);
+
 // NOT IMPLEMENTED //////////////////////////////////////////////////////
 private :
 
@@ -139,6 +172,7 @@
 private :
 
   typedef std::map< std::string, ALE::Obj<real_section_type> > map_real_type;
+  typedef std::map< std::string, std::map<int,int> > map_tags_type;
 
 // PRIVATE MEMBERS //////////////////////////////////////////////////////
 private :
@@ -155,6 +189,9 @@
   /// History manager for a subset of the fields
   std::vector<std::string> _history;
 
+  /// Tags for each real field.
+  map_tags_type _tags;
+
 }; // FieldsManager
 
 #endif // pylith_topology_fieldsmanager_hh

Modified: short/3D/PyLith/trunk/modulesrc/topology/topology.pyxe.src
===================================================================
--- short/3D/PyLith/trunk/modulesrc/topology/topology.pyxe.src	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/modulesrc/topology/topology.pyxe.src	2007-11-30 00:03:10 UTC (rev 8352)
@@ -863,17 +863,17 @@
     return
 
 
-  def getHistoryItem(self, index):
+  def getFieldByHistory(self, index):
     """
     Get field in history by position.
     """
-    # create shim for getHistoryItem
-    #embed{ void* FieldsManager_getHistoryItem(void* objVptr, int index)
+    # create shim for getFieldByHistory
+    #embed{ void* FieldsManager_getFieldByHistory(void* objVptr, int index)
     void* result = 0;
     try {
       assert(0 != objVptr);
       const ALE::Obj<pylith::real_section_type>& field =
-        ((pylith::topology::FieldsManager*) objVptr)->getHistoryItem(index);
+        ((pylith::topology::FieldsManager*) objVptr)->getFieldByHistory(index);
       result = (void*) &field;
     } catch (const std::exception& err) {
       PyErr_SetString(PyExc_RuntimeError,
@@ -888,10 +888,34 @@
     return result;
     #}embed
     cdef void* ptr
-    ptr = FieldsManager_getHistoryItem(self.thisptr, index)
+    ptr = FieldsManager_getFieldByHistory(self.thisptr, index)
     return PyCObject_FromVoidPtr(ptr, NULL)
 
 
+  def createCustomAtlas(self, label, id):
+    """
+    Create custom atlases for fields.
+    """
+    # create shim for createCustomAtlas
+    #embed{ void FieldsManager_createCustomAtlas(void* objVptr, char* label, int id)
+    try {
+      assert(0 != objVptr);
+      ((pylith::topology::FieldsManager*) objVptr)->createCustomAtlas(label, id);
+    } catch (const std::exception& err) {
+      PyErr_SetString(PyExc_RuntimeError,
+                      const_cast<char*>(err.what()));
+    } catch (const ALE::Exception& err) {
+      PyErr_SetString(PyExc_RuntimeError,
+                      const_cast<char*>(err.msg().c_str()));
+    } catch (...) {
+      PyErr_SetString(PyExc_RuntimeError,
+                      "Caught unknown C++ exception.");
+    } // try/catch
+    #}embed
+    FieldsManager_createCustomAtlas(self.thisptr, label, id)
+    return
+
+
   def _createHandle(self):
     """
     Wrap pointer to C++ object in PyCObject.

Modified: short/3D/PyLith/trunk/pylith/faults/FaultCohesiveKin.py
===================================================================
--- short/3D/PyLith/trunk/pylith/faults/FaultCohesiveKin.py	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/pylith/faults/FaultCohesiveKin.py	2007-11-30 00:03:10 UTC (rev 8352)
@@ -62,7 +62,7 @@
     """
     FaultCohesive.__init__(self, name)
     Integrator.__init__(self)
-    self._loggingPrefix = "FaCK "
+    self._loggingPrefix = "CoKi "
     return
 
 
@@ -92,9 +92,14 @@
     """
     Initialize cohesive elements.
     """
+    logEvent = "%sinit" % self._loggingPrefix
+
     self._info.log("Initializing fault '%s'." % self.label)
+
+    self._logger.eventBegin(logEvent)
     self.eqsrc.initialize()
     FaultCohesive.initialize(self)
+    self._logger.eventEnd(logEvent)
     return
 
 
@@ -119,6 +124,18 @@
     return
     
   
+  def _setupLogging(self):
+    """
+    Setup event logging.
+    """
+    Integrator._setupLogging(self)
+
+    events = ["init"]
+    for event in events:
+      self._logger.registerEvent("%s%s" % (self._loggingPrefix, event))
+    return
+  
+
 # FACTORIES ////////////////////////////////////////////////////////////
 
 def fault():

Modified: short/3D/PyLith/trunk/pylith/topology/FieldsManager.py
===================================================================
--- short/3D/PyLith/trunk/pylith/topology/FieldsManager.py	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/pylith/topology/FieldsManager.py	2007-11-30 00:03:10 UTC (rev 8352)
@@ -124,12 +124,20 @@
     return
 
 
-  def getHistoryItem(self, index):
+  def getFieldByHistory(self, index):
     """
     Get field in history by position.
     """
     assert(None != self.cppHandle)
-    return self.cppHandle.getHistoryItem(index)
+    return self.cppHandle.getFieldByHistory(index)
 
 
+  def createCustomAtlas(self, label, id):
+    """
+    Calculate custom atlas for fields in FieldsManager.
+    """
+    assert(None != self.cppHandle)
+    return self.cppHandle.createCustomAtlas(label, id)
+
+
 # End of file 

Modified: short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.cc
===================================================================
--- short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.cc	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.cc	2007-11-30 00:03:10 UTC (rev 8352)
@@ -103,7 +103,7 @@
   const ALE::Obj<real_section_type>& fieldA = manager.getReal(labelA);
   CPPUNIT_ASSERT(!fieldA.isNull());
   const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
-  mesh->allocate(fieldA);
+  fieldA->allocateStorage();
   for (Mesh::label_sequence::iterator v_iter = vertices->begin();
        v_iter != vertices->end();
        ++v_iter)
@@ -115,7 +115,7 @@
   const ALE::Obj<real_section_type>& fieldB = manager.getReal(labelB);
   CPPUNIT_ASSERT(!fieldB.isNull());
   const ALE::Obj<Mesh::label_sequence>& cells = mesh->heightStratum(0);
-  mesh->allocate(fieldB);
+  fieldB->allocateStorage();
   for (Mesh::label_sequence::iterator c_iter = cells->begin();
        c_iter != cells->end();
        ++c_iter)
@@ -167,7 +167,7 @@
   const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
   fieldA->setFiberDimension(vertices, fiberDim);
   fieldA->setConstraintDimension(fixedPt, 1);
-  mesh->allocate(fieldA);
+  fieldA->allocateStorage();
   fieldA->setConstraintDof(fixedPt, &fixedDim);
 
   const char* labelB = "field B";
@@ -216,7 +216,7 @@
   const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
   fieldA->setFiberDimension(vertices, fiberDim);
   fieldA->setConstraintDimension(fixedPt, 1);
-  mesh->allocate(fieldA);
+  fieldA->allocateStorage();
   fieldA->setConstraintDof(fixedPt, &fixedDim);
 
   const char* labelB = "field B";
@@ -355,10 +355,10 @@
 } // testShiftHistory
 
 // ----------------------------------------------------------------------
-// Test getHistoryItem().
+// Test getFieldByHistory().
 void
-pylith::topology::TestFieldsManager::testGetHistoryItem(void)
-{ // testGetHistoryItem
+pylith::topology::TestFieldsManager::testGetFieldByHistory(void)
+{ // testGetFieldByHistory
   ALE::Obj<Mesh> mesh;
   _initialize(&mesh);
   FieldsManager manager(mesh);
@@ -378,17 +378,219 @@
   fieldA->setFiberDimension(vertices, fiberDimA);
   fieldB->setFiberDimension(vertices, fiberDimB);
 
-  const ALE::Obj<real_section_type>& testA = manager.getHistoryItem(0);
+  const ALE::Obj<real_section_type>& testA = manager.getFieldByHistory(0);
   CPPUNIT_ASSERT_EQUAL(fiberDimA, 
 		       testA->getFiberDimension(*(vertices->begin())));
 
-  const ALE::Obj<real_section_type>& testB = manager.getHistoryItem(1);
+  const ALE::Obj<real_section_type>& testB = manager.getFieldByHistory(1);
   CPPUNIT_ASSERT_EQUAL(fiberDimB, 
 		       testB->getFiberDimension(*(vertices->begin())));
-} // testGetHistoryItem
+} // testGetFieldByHistory
 
 // ----------------------------------------------------------------------
+// Test createCustomAtlas().
 void
+pylith::topology::TestFieldsManager::testCreateCustomAtlas(void)
+{ // testCreateCustomAtlas
+  ALE::Obj<Mesh> mesh;
+  _initialize(&mesh);
+  FieldsManager manager(mesh);
+
+  const char* fieldNames[] = { "field A", "field B" };
+  const int numFields = 2;
+  const int fiberDimA = 2;
+  const int fiberDimB = 3;
+
+  const int materialIds[] = { 4, 3 };
+  const int numMaterials = 2;
+
+  for (int iField=0; iField < numFields; ++iField)
+    manager.addReal(fieldNames[iField]);
+
+  const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
+
+  const ALE::Obj<real_section_type>& fieldA = manager.getReal(fieldNames[0]);
+  fieldA->setFiberDimension(vertices, fiberDimA);
+  fieldA->allocateStorage();
+
+  const ALE::Obj<real_section_type>& fieldB = manager.getReal(fieldNames[1]);
+  fieldB->setFiberDimension(vertices, fiberDimB);
+  fieldB->allocateStorage();
+
+  for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial)
+    manager.createCustomAtlas("material-id", materialIds[iMaterial]);
+
+  for (int iField=0; iField < numFields; ++iField) {
+    FieldsManager::map_tags_type::iterator t_iter =
+      manager._tags.find(fieldNames[iField]);
+    CPPUNIT_ASSERT(t_iter != manager._tags.end());
+    const std::map<int,int>& tags = t_iter->second;
+    for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial) {
+      std::map<int,int>::const_iterator tag = 
+	tags.find(materialIds[iMaterial]);
+      CPPUNIT_ASSERT(tag != tags.end());
+      CPPUNIT_ASSERT_EQUAL(materialIds[iMaterial], tag->first);
+    } // for
+  } // for
+} // testCreateCustomAtlas
+
+// ----------------------------------------------------------------------
+// Test getFieldAtlasTag().
+void
+pylith::topology::TestFieldsManager::testGetFieldAtlasTag(void)
+{ // testGetFieldAtlasTag
+  ALE::Obj<Mesh> mesh;
+  _initialize(&mesh);
+  FieldsManager manager(mesh);
+
+  const char* fieldNames[] = { "field A", "field B" };
+  const int numFields = 2;
+  const int fiberDimA = 2;
+  const int fiberDimB = 3;
+
+  const int materialIds[] = { 4, 3 };
+  const int numMaterials = 2;
+
+  for (int iField=0; iField < numFields; ++iField)
+    manager.addReal(fieldNames[iField]);
+
+  const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
+
+  const ALE::Obj<real_section_type>& fieldA = manager.getReal(fieldNames[0]);
+  fieldA->setFiberDimension(vertices, fiberDimA);
+  fieldA->allocateStorage();
+
+  const ALE::Obj<real_section_type>& fieldB = manager.getReal(fieldNames[1]);
+  fieldB->setFiberDimension(vertices, fiberDimB);
+  fieldB->allocateStorage();
+
+  for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial)
+    manager.createCustomAtlas("material-id", materialIds[iMaterial]);
+
+  for (int iField=0; iField < numFields; ++iField) {
+    FieldsManager::map_tags_type::iterator t_iter =
+      manager._tags.find(fieldNames[iField]);
+    CPPUNIT_ASSERT(t_iter != manager._tags.end());
+    const std::map<int,int>& tags = t_iter->second;
+    for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial) {
+      std::map<int,int>::const_iterator tag = 
+	tags.find(materialIds[iMaterial]);
+      CPPUNIT_ASSERT(tag != tags.end());
+      CPPUNIT_ASSERT_EQUAL(materialIds[iMaterial], tag->first);
+      const int tagValueE = tag->second;
+      const int tagValue = 
+	manager.getFieldAtlasTag(fieldNames[iField], materialIds[iMaterial]);
+      CPPUNIT_ASSERT_EQUAL(tagValueE, tagValue);
+    } // for
+  } // for
+} // testGetFieldAtlasTag
+
+// ----------------------------------------------------------------------
+// Test getFieldAtlasTagByHistory().
+void
+pylith::topology::TestFieldsManager::testGetFieldAtlasTagByHistory(void)
+{ // testGetFieldAtlasTagByHistory
+  ALE::Obj<Mesh> mesh;
+  _initialize(&mesh);
+  FieldsManager manager(mesh);
+
+  const char* fieldNames[] = { "field A", "field B" };
+  const int numFields = 2;
+  const int fiberDimA = 2;
+  const int fiberDimB = 3;
+
+  const int materialIds[] = { 4, 3 };
+  const int numMaterials = 2;
+
+  for (int iField=0; iField < numFields; ++iField)
+    manager.addReal(fieldNames[iField]);
+  manager.createHistory(fieldNames, numFields);
+
+  const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
+
+  const ALE::Obj<real_section_type>& fieldA = manager.getReal(fieldNames[0]);
+  fieldA->setFiberDimension(vertices, fiberDimA);
+  fieldA->allocateStorage();
+
+  const ALE::Obj<real_section_type>& fieldB = manager.getReal(fieldNames[1]);
+  fieldB->setFiberDimension(vertices, fiberDimB);
+  fieldB->allocateStorage();
+
+  for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial)
+    manager.createCustomAtlas("material-id", materialIds[iMaterial]);
+
+  for (int iField=0; iField < numFields; ++iField) {
+    FieldsManager::map_tags_type::iterator t_iter =
+      manager._tags.find(fieldNames[iField]);
+    CPPUNIT_ASSERT(t_iter != manager._tags.end());
+    const std::map<int,int>& tags = t_iter->second;
+    for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial) {
+      std::map<int,int>::const_iterator tag = 
+	tags.find(materialIds[iMaterial]);
+      CPPUNIT_ASSERT(tag != tags.end());
+      CPPUNIT_ASSERT_EQUAL(materialIds[iMaterial], tag->first);
+      const int tagValueE = tag->second;
+      const int tagValue = 
+	manager.getFieldAtlasTagByHistory(iField, materialIds[iMaterial]);
+      CPPUNIT_ASSERT_EQUAL(tagValueE, tagValue);
+    } // for
+  } // for
+} // testGetFieldAtlasTagByHistory
+
+// ----------------------------------------------------------------------
+// Test getSolutionAtlasTag().
+void
+pylith::topology::TestFieldsManager::testGetSolutionAtlasTag(void)
+{ // testGetFieldAtlasTag
+  ALE::Obj<Mesh> mesh;
+  _initialize(&mesh);
+  FieldsManager manager(mesh);
+
+  const char* fieldNames[] = { "field A", "field B" };
+  const int numFields = 2;
+  const int fiberDimA = 2;
+  const int fiberDimB = 3;
+  const char* solnName = "field B";
+
+  const int materialIds[] = { 4, 3 };
+  const int numMaterials = 2;
+
+  for (int iField=0; iField < numFields; ++iField)
+    manager.addReal(fieldNames[iField]);
+  manager.solutionField(solnName);
+
+  const ALE::Obj<Mesh::label_sequence>& vertices = mesh->depthStratum(0);
+
+  const ALE::Obj<real_section_type>& fieldA = manager.getReal(fieldNames[0]);
+  fieldA->setFiberDimension(vertices, fiberDimA);
+  fieldA->allocateStorage();
+
+  const ALE::Obj<real_section_type>& fieldB = manager.getReal(fieldNames[1]);
+  fieldB->setFiberDimension(vertices, fiberDimB);
+  fieldB->allocateStorage();
+
+  for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial)
+    manager.createCustomAtlas("material-id", materialIds[iMaterial]);
+
+
+  FieldsManager::map_tags_type::iterator t_iter =
+    manager._tags.find(solnName);
+  CPPUNIT_ASSERT(t_iter != manager._tags.end());
+  const std::map<int,int>& tags = t_iter->second;
+  for (int iMaterial=0; iMaterial < numMaterials; ++iMaterial) {
+    std::map<int,int>::const_iterator tag = 
+      tags.find(materialIds[iMaterial]);
+    CPPUNIT_ASSERT(tag != tags.end());
+    CPPUNIT_ASSERT_EQUAL(materialIds[iMaterial], tag->first);
+    const int tagValueE = tag->second;
+    const int tagValue = 
+      manager.getSolutionAtlasTag(materialIds[iMaterial]);
+    CPPUNIT_ASSERT_EQUAL(tagValueE, tagValue);
+  } // for
+} // testGetSolutionAtlasTag
+
+// ----------------------------------------------------------------------
+void
 pylith::topology::TestFieldsManager::_initialize(ALE::Obj<Mesh>* mesh) const
 { // _initialize
   CPPUNIT_ASSERT(0 != mesh);

Modified: short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.hh
===================================================================
--- short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.hh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/unittests/libtests/topology/TestFieldsManager.hh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -40,6 +40,7 @@
 
   // CPPUNIT TEST SUITE /////////////////////////////////////////////////
   CPPUNIT_TEST_SUITE( TestFieldsManager );
+
   CPPUNIT_TEST( testConstructor );
   CPPUNIT_TEST( testAddReal );
   CPPUNIT_TEST( testGetReal );
@@ -52,7 +53,12 @@
   CPPUNIT_TEST( testGetSolution );
   CPPUNIT_TEST( testCreateHistory );
   CPPUNIT_TEST( testShiftHistory );
-  CPPUNIT_TEST( testGetHistoryItem );
+  CPPUNIT_TEST( testGetFieldByHistory );
+  CPPUNIT_TEST( testCreateCustomAtlas );
+  CPPUNIT_TEST( testGetFieldAtlasTag );
+  CPPUNIT_TEST( testGetFieldAtlasTagByHistory );
+  CPPUNIT_TEST( testGetSolutionAtlasTag );
+
   CPPUNIT_TEST_SUITE_END();
 
   // PUBLIC METHODS /////////////////////////////////////////////////////
@@ -94,9 +100,21 @@
   /// Test shiftHistory().
   void testShiftHistory(void);
 
-  /// Test getHistoryItem().
-  void testGetHistoryItem(void);
+  /// Test getFieldByHistory().
+  void testGetFieldByHistory(void);
 
+  /// Test createCustomAtlas().
+  void testCreateCustomAtlas(void);
+
+  /// Test getFieldAtlasTag().
+  void testGetFieldAtlasTag(void);
+
+  /// Test getFieldAtlasTagByHistory().
+  void testGetFieldAtlasTagByHistory(void);
+
+  /// Test getSolutionAtlasTag().
+  void testGetSolutionAtlasTag(void);
+
   // PRIVATE METHODS ////////////////////////////////////////////////////
 private :
 

Modified: short/3D/PyLith/trunk/unittests/libtests/topology/data/tri3.mesh
===================================================================
--- short/3D/PyLith/trunk/unittests/libtests/topology/data/tri3.mesh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/unittests/libtests/topology/data/tri3.mesh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -19,8 +19,8 @@
              1       1  3  2
     }
     material-ids = {
-             0   0
-             1   0
+             0   3
+             1   4
     }
   }
   group = {

Modified: short/3D/PyLith/trunk/unittests/pytests/topology/TestFieldsManager.py
===================================================================
--- short/3D/PyLith/trunk/unittests/pytests/topology/TestFieldsManager.py	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/unittests/pytests/topology/TestFieldsManager.py	2007-11-30 00:03:10 UTC (rev 8352)
@@ -228,7 +228,7 @@
     """
     Test createHistory().
 
-    WARNING: This is not a rigorous test of setConstraintSizes() because we
+    WARNING: This is not a rigorous test of createHitory() because we
     don't verify the results.
     """
     mesh = self._initialize()
@@ -251,7 +251,7 @@
     """
     Test createHistory().
 
-    WARNING: This is not a rigorous test of setConstraintSizes() because we
+    WARNING: This is not a rigorous test of shitHistory() because we
     don't verify the results.
     """
     mesh = self._initialize()
@@ -270,11 +270,11 @@
     return
 
 
-  def test_getHistoryItem(self):
+  def test_getFieldByHistory(self):
     """
     Test createHistory().
 
-    WARNING: This is not a rigorous test of setConstraintSizes() because we
+    WARNING: This is not a rigorous test of getFieldByHistory() because we
     don't verify the results.
     """
     mesh = self._initialize()
@@ -287,13 +287,45 @@
 
     manager.createHistory(fields)
     for i in [0, 2, 1]:
-      field = manager.getHistoryItem(i)
+      field = manager.getFieldByHistory(i)
 
     # We should really add something here to check to make sure things
     # actually initialized correctly.
     return
 
 
+  def test_createCustomAtlas(self):
+    """
+    Test createCustomAtlas().
+
+    WARNING: This is not a rigorous test of createCustomAtlas() because we
+    don't verify the results.
+    """
+    mesh = self._initialize()
+    from pylith.topology.FieldsManager import FieldsManager
+    manager = FieldsManager(mesh)
+    
+    fields = ["field A", "field B", "field C"]
+    for field in fields:
+      manager.addReal(field)
+      
+    manager.setFiberDimension("field A", 3, "vertices")
+    manager.allocate("field A")
+
+    manager.setFiberDimension("field B", 4, "vertices")
+    manager.allocate("field B")
+
+    manager.setFiberDimension("field C", 5, "vertices")
+    manager.allocate("field C")
+
+    manager.createCustomAtlas("material-id", 4)
+    manager.createCustomAtlas("material-id", 3)
+
+    # We should really add something here to check to make sure things
+    # actually initialized correctly.
+    return
+
+
   # PRIVATE METHODS ////////////////////////////////////////////////////
 
   def _initialize(self):

Modified: short/3D/PyLith/trunk/unittests/pytests/topology/data/tri3.mesh
===================================================================
--- short/3D/PyLith/trunk/unittests/pytests/topology/data/tri3.mesh	2007-11-29 01:40:04 UTC (rev 8351)
+++ short/3D/PyLith/trunk/unittests/pytests/topology/data/tri3.mesh	2007-11-30 00:03:10 UTC (rev 8352)
@@ -19,8 +19,8 @@
              1       1  3  2
     }
     material-ids = {
-             0   0
-             1   0
+             0   3
+             1   4
     }
   }
   group = {



More information about the cig-commits mailing list