Example #1
0
template<class T> void Convert_To_Tetrahedralized_Volume( tetgenio& out, 
                                                          TETRAHEDRALIZED_VOLUME<T>& volume )
{
    ARRAY<VECTOR<T,3> > X;
    for( int i=0; i < out.numberofpoints; i++){
        VECTOR<T,3> p;
        p.x = out.pointlist[ i*out.mesh_dim + 0 ];
        p.y = out.pointlist[ i*out.mesh_dim + 1 ];
        p.z = out.pointlist[ i*out.mesh_dim + 2 ];
        X.Append(p);
        //LOG::cout << "V" << i+1 << " : " << p << std::endl;
    }

    ARRAY<VECTOR<int,4> > elements;
    for( int i=0; i < out.numberoftetrahedra; i++){
        VECTOR<int,4> e;
        e(1) = out.tetrahedronlist[ i*out.numberofcorners + 0 ];
        e(2) = out.tetrahedronlist[ i*out.numberofcorners + 1 ];
        e(3) = out.tetrahedronlist[ i*out.numberofcorners + 2 ];
        e(4) = out.tetrahedronlist[ i*out.numberofcorners + 3 ];
        elements.Append(e);
        //LOG::cout << "T" << i+1 << " : " << e << std::endl;
    }

    int m = X.m;
    int n = elements.m;

    volume.mesh.Initialize_Mesh(m,elements);
    volume.particles.array_collection->Resize(m);
    volume.particles.X=X;
}
Example #2
0
void LineSeg<D> :: GetRawData (ARRAY<double> & data) const
{
  data.Append(2);
  for(int i=0; i<D; i++)
    data.Append(p1[i]);
  for(int i=0; i<D; i++)
    data.Append(p2[i]);
}
Example #3
0
void SplineSeg3<D> :: GetRawData (ARRAY<double> & data) const
{
  data.Append(3);
  for(int i=0; i<D; i++)
    data.Append(p1[i]);
  for(int i=0; i<D; i++)
    data.Append(p2[i]);
  for(int i=0; i<D; i++)
    data.Append(p3[i]);
}
//#####################################################################
// Function Cubic_MN_Weights
//#####################################################################
template<class T,class T2> ARRAY<T> CUBIC_MN_INTERPOLATION<T,T2>::
Cubic_MN_Weights(const T alpha) const
{
    T alpha2=alpha*alpha;
    T alpha3=alpha2*alpha;
    ARRAY<T> weights;
    weights.Append(-alpha3/2.+alpha2-.5*alpha); //f_k-1
    weights.Append(alpha3/2.-5*alpha2/2.+1); //f_k
    weights.Append(-alpha3/2.+2*alpha2+alpha/2.); //f_k+1
    weights.Append(alpha3/2.-alpha2/2.);  //f_k+2
    for(int i=1;i<=weights.m;i++) weights(i)=max((T)0.,min((T)1.,weights(i)));
    return weights;
}
Example #5
0
// Template method that works for BaseArray, BlockArray, PointerArray or BaseList
template <class ARRAY, typename T> void GenericSample(ARRAY& test, const T& aValue, const T& bValue)
{
	const Int	ARRAY_TEST_SIZE = 1024;
	Int	i;

	// append ARRAY_TEST_SIZE elements (all initialized by the default constructor)
	for (i = 0; i < ARRAY_TEST_SIZE; i++)
		test.Append();

	// use an AutoIterator to iterate over the whole array and assign aValue to every element
	for (AutoIterator<ARRAY> it(test); it; ++it)
		*it = aValue;

	// insert an element with bValue at index 10
	test.Insert(10, bValue);
	
	// erase the element at index 11
	test.Erase(11);

	// just a quick check: we should still have the same number of elements
	if (test.GetCount() != ARRAY_TEST_SIZE)
		GeBoom();

	// using an Iterator: assign bValue to all elements from test[25] to test[49]
	typename ARRAY::Iterator end = test.Begin() + 50;
	for (typename ARRAY::Iterator it = test.Begin() + 25; it != end; it++)
		*it = bValue;
}
void RegisterUserFormats (ARRAY<const char*> & names)
{
    char *types[] =
    {
        "Neutral Format",
        "Surface Mesh Format" ,
        "DIFFPACK Format",
        "TecPlot Format",
        "Tochnog Format",
        "Abaqus Format",
        "Fluent Format",
        "Permas Format",
        "FEAP Format",
        "Elmer Format",
        "STL Format",
        "VRML Format",
        "Gmsh Format",
        "JCMwave Format",
        "TET Format",
        //      { "Chemnitz Format" },
        0
    };

    for (int i = 0; types[i]; i++)
        names.Append (types[i]);
}
Example #7
0
  void Add (int ind)
  {
    if (!flags.Test(ind))
      {
	set.Append (ind);
	flags.Set (ind);
      }
  }
Example #8
0
void Primitive :: GetTangentialSurfaceIndices (const Point<3> & p, 
					       ARRAY<int> & surfind, double eps) const
{
  for (int j = 0; j < GetNSurfaces(); j++)
    if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)
      if (!surfind.Contains (GetSurfaceId(j)))
	surfind.Append (GetSurfaceId(j));
}
Example #9
0
void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, const FlatArray<T> & in3,
		   ARRAY<T> & out)
{
  out.SetSize(0);
  for(int i=0; i<in1.Size(); i++)
    if(in2.Contains(in1[i]) && in3.Contains(in1[i]))
      out.Append(in1[i]);
}
Example #10
0
void SplineSeg3<D> :: LineIntersections (const double a, const double b, const double c,
					 ARRAY < Point<D> > & points, const double eps) const
{
  points.SetSize(0);

  double t;

  const double c1 = a*p1(0) - sqrt(2.)*a*p2(0) + a*p3(0) 
    + b*p1(1) - sqrt(2.)*b*p2(1) + b*p3(1) 
    + (2.-sqrt(2.))*c;
  const double c2 = -2.*a*p1(0) + sqrt(2.)*a*p2(0) -2.*b*p1(1) + sqrt(2.)*b*p2(1) + (sqrt(2.)-2.)*c;
  const double c3 = a*p1(0) + b*p1(1) + c;

  if(fabs(c1) < 1e-20)
    {
      if(fabs(c2) < 1e-20)
	return;

      t = -c3/c2;
      if((t > -eps) && (t < 1.+eps))
	points.Append(GetPoint(t));
      return;
    }

  const double discr = c2*c2-4.*c1*c3;

  if(discr < 0)
    return;

  if(fabs(discr/(c1*c1)) < 1e-14)
    {
      t = -0.5*c2/c1;
      if((t > -eps) && (t < 1.+eps))
	points.Append(GetPoint(t));
      return;
    }

  t = (-c2 + sqrt(discr))/(2.*c1);
  if((t > -eps) && (t < 1.+eps))
    points.Append(GetPoint(t));

  t = (-c2 - sqrt(discr))/(2.*c1);
  if((t > -eps) && (t < 1.+eps))
    points.Append(GetPoint(t));
}
//#####################################################################
// Function Compute_Level_Set_Helper
//#####################################################################
template<class T> void LEVELSET_MAKER_UNIFORM_2D<T>::
Compute_Level_Set_Helper(const TV_INT& index,T next,ARRAY<TV_INT>& next_todo,ARRAY<T,TV_INT>& phi)
{
    if(!phi.Valid_Index(index)) return;
    T& p=phi(index);
    if(p!=FLT_MAX) return;
    p=next;
    next_todo.Append(index);
}
//#####################################################################
// Function Simplices_On_Subsimplex
//#####################################################################
template<int d> template<int d2> void SIMPLEX_MESH<d>::
Simplices_On_Subsimplex(const VECTOR<int,d2>& subsimplex_nodes,ARRAY<int>& simplices_on_subsimplex) const
{
    assert(incident_elements);
    const ARRAY<int>& incident=(*incident_elements)(subsimplex_nodes[1]);
    VECTOR<int,d2-1> other_nodes=subsimplex_nodes.Remove_Index(1);
    for(int i=1;i<=incident.m;i++){
        int simplex=incident(i);
        if(Nodes_In_Simplex(other_nodes,simplex)) simplices_on_subsimplex.Append(simplex);}
}
//#####################################################################
// Function Get_Simplex_Bounding_Boxes
//#####################################################################
template<class T> void RIGID_COLLISION_GEOMETRY<VECTOR<T,3> >::
Get_Simplex_Bounding_Boxes(ARRAY<RANGE<TV> >& bounding_boxes,const bool with_body_motion,const T extra_thickness,const T body_thickness_factor) const
{
    if(!rigid_geometry.simplicial_object->triangle_list) rigid_geometry.simplicial_object->Update_Triangle_List();
    for(int t=1;t<=rigid_geometry.simplicial_object->mesh.elements.m;t++){
        RANGE<TV> box=rigid_geometry.World_Space_Simplex_Bounding_Box(t);
        if(with_body_motion) box.Enlarge_To_Include_Box(rigid_geometry.World_Space_Simplex_Bounding_Box(t,saved_states(1).x));
        box.Change_Size(extra_thickness+body_thickness_factor*collision_thickness);
        bounding_boxes.Append(box);}
}
Example #14
0
void CircleSeg<D> :: LineIntersections (const double a, const double b, const double c,
					ARRAY < Point<D> > & points, const double eps) const
{
  points.SetSize(0);

  double px=0,py=0;

  if(fabs(b) > 1e-20)
    py = -c/b;
  else
    px = -c/a;

  const double c1 = a*a + b*b;
  const double c2 = 2. * ( a*(py-pm(1)) - b*(px-pm(0)));
  const double c3 = pow(px-pm(0),2) + pow(py-pm(1),2) - pow(Radius(),2);
    
  const double discr = c2*c2 - 4*c1*c3;

  if(discr < 0)
    return;

  ARRAY<double> t;

  if(fabs(discr) < 1e-20)
    t.Append(-0.5*c2/c1);
  else
    {
      t.Append((-c2+sqrt(discr))/(2.*c1));
      t.Append((-c2-sqrt(discr))/(2.*c1));
    }

  for(int i=0; i<t.Size(); i++)
    {
      Point<D> p (px-t[i]*b,py+t[i]*a);

      double angle = atan2(p(1),p(0))+M_PI;

      if(angle > StartAngle()-eps && angle < EndAngle()+eps)
	points.Append(p);
    }
}
Example #15
0
void LineSeg<D> :: LineIntersections (const double a, const double b, const double c,
				      ARRAY < Point<D> > & points, const double eps) const
{
  points.SetSize(0);

  double denom = -a*p2(0)+a*p1(0)-b*p2(1)+b*p1(1);
  if(fabs(denom) < 1e-20)
    return;

  double t = (a*p1(0)+b*p1(1)+c)/denom;
  if((t > -eps) && (t <  1.+eps))
    points.Append(GetPoint(t));
}
//#####################################################################
// Function Command_Prompt_Response
//#####################################################################
template<class T,class RW> void OPENGL_COMPONENT_DEBUG_PARTICLES_2D<T,RW>::
Command_Prompt_Response()
{
    if(!OPENGL_WORLD::Singleton()->prompt_response.empty()){
        std::string command;
        std::istringstream sstream(OPENGL_WORLD::Singleton()->prompt_response);
        sstream>>command;
        if(command=="s"){
            ARRAY<int> indices;
            int index;
            while(sstream>>index) indices.Append(index);
            opengl_particles.Clear_Selection();
            opengl_particles.Select_Points(indices);}}
//#####################################################################
// Function Get_All_Face_Neighbors
//#####################################################################
template<class T> void QUADTREE_CELL<T>::
Get_All_Face_Neighbors(int face_index,ARRAY<QUADTREE_CELL<T>*>& face_neighbors,const QUADTREE_GRID<T>* grid) const
{
    int face_index_to_offset[][2]={{-1,0},{1,0},{0,-1},{0,1}}; // convertes from face index to x and y offsets for use in neighbor search
    QUADTREE_CELL<T>* neighbor=Get_Neighbor(face_index_to_offset[face_index][0],face_index_to_offset[face_index][1],grid,0,false);
    if(!neighbor) return;
    if(neighbor->Has_Children()){
        GET_ALL_FACE_NEIGHBORS_HELPER<T> helper;helper.face_neighbors=&face_neighbors;
        if(face_index==0){helper.cell_to_add=0;MAP_QUADTREE_MESH<T>::Map_Face_Process_Face(&helper,neighbor,this,X_AXIS,Get_All_Face_Neighbors_Helper);}
        else if(face_index==1){helper.cell_to_add=1;MAP_QUADTREE_MESH<T>::Map_Face_Process_Face(&helper,this,neighbor,X_AXIS,Get_All_Face_Neighbors_Helper);}
        else if(face_index==2){helper.cell_to_add=0;MAP_QUADTREE_MESH<T>::Map_Face_Process_Face(&helper,neighbor,this,Y_AXIS,Get_All_Face_Neighbors_Helper);}
        else{assert(face_index==3);helper.cell_to_add=1;
            MAP_QUADTREE_MESH<T>::Map_Face_Process_Face(&helper,this,neighbor,Y_AXIS,Get_All_Face_Neighbors_Helper);}}
    else face_neighbors.Append(neighbor);
}
Example #18
0
void Polyhedra :: GetPrimitiveData (const char *& classname, 
				    ARRAY<double> & coeffs) const
{
  classname = "Polyhedra";
  coeffs.SetSize(0);
  coeffs.Append (points.Size());
  coeffs.Append (faces.Size());
  coeffs.Append (planes.Size());

  /*
  int i, j;
  for (i = 1; i <= planes.Size(); i++)
    {
      planes.Elem(i)->Print (*testout);
    }
  for (i = 1; i <= faces.Size(); i++)
    {
      (*testout) << "face " << i << " has plane " << faces.Get(i).planenr << endl;
      for (j = 1; j <= 3; j++)
	(*testout) << points.Get(faces.Get(i).pnums[j-1]);
      (*testout) << endl;
    }
  */
}
Example #19
0
void LocalH :: GetOuterPoints (ARRAY<Point3d> & points)
{
  int i, nb = boxes.Size(); 

  for (i = 1; i <= nb; i++)
    {
      GradingBox * box = boxes.Get(i);
      if (!box->flags.isinner &&
	  !box->flags.cutboundary)
	{
	  Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]);
	  points.Append (c);
	}
    }
}
Example #20
0
void Polyhedra :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,
						   ARRAY<int> & surfind, double eps) const
{
  Vec<3> v1n = v1;
  v1n.Normalize();
  Vec<3> v2n = v2; //  - (v2 * v1n) * v1n;
  v2n.Normalize();


  for (int i = 0; i < faces.Size(); i++)
    {
      const Point<3> & p1 = points[faces[i].pnums[0]];
      
      Vec<3> v0 = p - p1;
      if (fabs (v0 * faces[i].nn) > eps) continue; // n->nn
      if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn
      if (fabs (v2n * faces[i].nn) > eps_base1) continue; // n->nn

      double lam01 = (faces[i].w1 * v0);
      double lam02 = (faces[i].w2 * v0);
      double lam03 = 1-lam01-lam02;
      double lam11 = (faces[i].w1 * v1);
      double lam12 = (faces[i].w2 * v1);
      double lam13 = -lam11-lam12;
      double lam21 = (faces[i].w1 * v2);
      double lam22 = (faces[i].w2 * v2);
      double lam23 = -lam21-lam22;

      bool ok1 = lam01 > eps_base1 ||
	lam01 > -eps_base1 && lam11 > eps_base1 ||
	lam01 > -eps_base1 && lam11 > -eps_base1 && lam21 > eps_base1;

      bool ok2 = lam02 > eps_base1 ||
	lam02 > -eps_base1 && lam12 > eps_base1 ||
	lam02 > -eps_base1 && lam12 > -eps_base1 && lam22 > eps_base1;
      
      bool ok3 = lam03 > eps_base1 ||
	lam03 > -eps_base1 && lam13 > eps_base1 ||
	lam03 > -eps_base1 && lam13 > -eps_base1 && lam23 > eps_base1;

      if (ok1 && ok2 && ok3)
	{
	  if (!surfind.Contains (GetSurfaceId(faces[i].planenr)))
	    surfind.Append (GetSurfaceId(faces[i].planenr));
	}
    }  
}
Example #21
0
void Primitive :: 
GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,
				 ARRAY<int> & surfind, double eps) const
{
  for (int j = 0; j < GetNSurfaces(); j++)
    {
      if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)
	{
	  Vec<3> grad;
	  GetSurface(j).CalcGradient (p, grad);
	  if (sqr (grad * v1) < 1e-6 * v1.Length2() * grad.Length2()  && 
	      sqr (grad * v2) < 1e-6 * v2.Length2() * grad.Length2() )   // new, 18032006 JS
	    {
	      if (!surfind.Contains (GetSurfaceId(j)))
		surfind.Append (GetSurfaceId(j));
	    }
	}
    }
}
Example #22
0
void Polyhedra :: GetTangentialSurfaceIndices (const Point<3> & p, 
					       ARRAY<int> & surfind, double eps) const
{
  for (int i = 0; i < faces.Size(); i++)
    {
      const Point<3> & p1 = points[faces[i].pnums[0]];
      
      Vec<3> v0 = p - p1;
      double lam3 = -(faces[i].nn * v0); // n->nn

      if (fabs (lam3) > eps) continue;

      double lam1 = (faces[i].w1 * v0);
      double lam2 = (faces[i].w2 * v0);

      if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1)
	if (!surfind.Contains (GetSurfaceId(i)))
	  surfind.Append (GetSurfaceId(i));
    }

}
Example #23
0
void LocalH :: GetInnerPoints (ARRAY<Point3d> & points)
{
  int i, nb = boxes.Size(); 

  for (i = 1; i <= nb; i++)
    {
      GradingBox * box = boxes.Get(i);
      /*
      if (box->flags.pinner)
	points.Append (box->randomip);
      */
      //      if (box->flags.pinner)
      if (box->flags.isinner)
	{
	  Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]);
	  points.Append (c);
	  /*
	  cout << "add point " << c << "; h = " << box->hopt
	       << "; max-min = " << (box->x2[0]-box->x1[0]) << endl;
	  */
	}
    }
}
Example #24
0
//#####################################################################
// Function Exchange_Boundary_Columns
//#####################################################################
template<class T_GRID> template<class T_ARRAYS_HORIZONTAL_COLUMN> void MPI_RLE_GRID<T_GRID>::
Exchange_Boundary_Columns(const int bandwidth,T_ARRAYS_HORIZONTAL_COLUMN& columns)
{
    int tag=Get_Unique_Tag();
    T_BOX_HORIZONTAL_INT sentinels=T_GRID::CELL_ITERATOR::Sentinels();
    // send
    ARRAY<MPI::Request> requests;
    ARRAY<T_BOX_HORIZONTAL_INT> send_regions;
    Find_Boundary_Regions(send_regions,sentinels,false,RANGE<VECTOR<int,1> >(0,bandwidth-1),true);
    ARRAY<ARRAY<char> > buffers(send_regions.m); // must stay alive until after Wait_All
    for(int n=1; n<=send_regions.m; n++)if(all_neighbor_ranks(n)!=MPI::PROC_NULL)
            requests.Append(ISend_Columns(columns,send_regions,n,tag,buffers(n)));
    // probe and receive
    ARRAY<T_BOX_HORIZONTAL_INT> recv_regions;
    Find_Boundary_Regions(recv_regions,sentinels,false,RANGE<VECTOR<int,1> >(-bandwidth,-1),true);
    for(int message=1; message<=requests.m; message++) {
        MPI::Status probe_status;
        comm->Probe(MPI::ANY_SOURCE,tag,probe_status);
        Recv_Columns(columns,recv_regions,tag,probe_status);
    }
    // wait for sends to complete
    MPI_UTILITIES::Wait_All(requests);
}
//#####################################################################
// Function Find_Or_Read_Structure
//#####################################################################
template<class TV> bool RIGID_GEOMETRY_COLLECTION<TV>::
Find_Or_Read_Structure(const STREAM_TYPE stream_type,ARRAY<int>& structure_ids,const std::string& filename,const T scaling_factor,const TV& center)
{
    int id;
    if(!FILE_UTILITIES::File_Exists(filename)) return false;
    std::string hashname=STRING_UTILITIES::string_sprintf("%s@%.6f",filename.c_str(),scaling_factor); // mangle hash name
    if(!always_create_structure&&structure_hash.Get(hashname,id)){ // already read in
        if(!structure_list.Is_Active(id)) PHYSBAM_FATAL_ERROR();} // // only works if the referenced geometry is still in memory
    else{ // read in for the first time
        STRUCTURE<TV>* structure=0;
        if(!stream_type.use_doubles)
            structure=Read_Write<STRUCTURE<TV>,float>::Create_From_File(filename);
#ifndef COMPILE_WITHOUT_DOUBLE_SUPPORT
        else
            structure=Read_Write<STRUCTURE<TV>,double>::Create_From_File(filename);
#endif
        if(scaling_factor!=1){
            Wrap_Structure_Helper(structure,center);
            structure->Rescale(scaling_factor);}
        id=structure_list.Add_Element(structure);
        if(!always_create_structure) structure_hash.Insert(hashname,id);}
    structure_ids.Append(id);
    return true;
}
Example #26
0
 void AddILimit(twoint l) {
     ilimit->Append(l);
 }
Example #27
0
 void AddOLimit(twoint l) {
     olimit->Append(l);
 }
Example #28
0
 //don't check, if already exists!
 void AddNewSegment(const STLBoundarySeg & seg) {
     boundary.Append(seg);
 };
Example #29
0
  void WriteTETFormat (const Mesh & mesh,
		       const string & filename)//, const string& problemType )
  {
    string problemType = "";
    if(!mesh.PureTetMesh())
      throw NgException("Can only export pure tet mesh in this format");

    cout << "starting .tet export to file " << filename << endl;


    ARRAY<int> point_ids,edge_ids,face_ids;
    ARRAY<int> elnum(mesh.GetNE());
    elnum = -1;

    
    ARRAY<int> userdata_int;
    ARRAY<double> userdata_double;
    ARRAY<int> ports;

    ARRAY<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D;

    int pos_int = 0;
    int pos_double = 0;
    
    bool haveuserdata = 
      (mesh.GetUserData("TETmesh:double",userdata_double) &&
       mesh.GetUserData("TETmesh:int",userdata_int) && 
       mesh.GetUserData("TETmesh:ports",ports) &&
       mesh.GetUserData("TETmesh:point_id",point_ids,PointIndex::BASE) &&
       mesh.GetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D) &&
       mesh.GetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D) &&
       mesh.GetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D) &&
       mesh.GetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D));


    int version,subversion;

    if(haveuserdata)
      {
	version = int(userdata_double[0]);
	subversion = int(10*(userdata_double[0] - version));
	pos_double++;
      }
    else
      {
	version = 2;
	subversion = 0;
      }

    
    if(version >= 2)
      {
	// test if ids are disjunct, if not version 2.0 not possible
	int maxbc(-1),mindomain(-1);
	
	for(ElementIndex i=0; i<mesh.GetNE(); i++)
	  if(i==0 || mesh[i].GetIndex() < mindomain)
	    mindomain = mesh[i].GetIndex();
	for(int i=1; i<=mesh.GetNFD(); i++)
	  if(i==1 || mesh.GetFaceDescriptor(i).BCProperty() > maxbc)
	    maxbc = mesh.GetFaceDescriptor(i).BCProperty();
	
	if(maxbc >= mindomain)
	  {
	    cout << "WARNING: writing version " << version << "." << subversion << " tetfile not possible, ";
	    version = 1; subversion = 1;
	    cout << "using version " << version << "." << subversion << endl;
	  }
      }



    int startsize = point_ids.Size();
    point_ids.SetSize(mesh.GetNP()+1);
    for(int i=startsize; i<point_ids.Size(); i++)
      point_ids[i] = -1;


    for(int i=0; i<PointIndex::BASE; i++)
      point_ids[i] = -1;


    INDEX_2_CLOSED_HASHTABLE<int> edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());;
    INDEX_3_CLOSED_HASHTABLE<int> facenumbers(4*mesh.GetNE()+mesh.GetNSE());

    ARRAY<INDEX_2> edge2node;
    ARRAY<INDEX_3> face2edge;
    ARRAY<INDEX_4> element2face;

    int numelems(0),numfaces(0),numedges(0),numnodes(0);

    for(SegmentIndex si = 0; si < mesh.GetNSeg(); si++)
      {
	const Segment & seg = mesh[si];
	INDEX_2 i2(seg.p1,seg.p2);
	i2.Sort();
	if(edgenumbers.Used(i2))
	  continue;

	numedges++;
	edgenumbers.Set(i2,numedges);
	edge2node.Append(i2);

	edge_ids.Append(seg.edgenr);

	if(point_ids[seg.p1] == -1)
	  point_ids[seg.p1] = (version >= 2) ? seg.edgenr : 0;
	if(point_ids[seg.p2] == -1)
	  point_ids[seg.p2] = (version >= 2) ? seg.edgenr : 0;
      }

    for(SurfaceElementIndex si = 0; si < mesh.GetNSE(); si++)
      {
	if(mesh[si].IsDeleted())
	  continue;

	const Element2d & elem = mesh[si];

	numfaces++;
	INDEX_3 i3(elem[0], elem[1], elem[2]);

	int min = i3[0];
	int minpos = 0;
	for(int j=1; j<3; j++)
	  if(i3[j] < min)
	    {
	      min = i3[j]; minpos = j;
	    }
	if(minpos == 1)
	  {
	    int aux = i3[0]; i3[0] = i3[1]; i3[1] = i3[2]; i3[2] = aux;
	  }
	else if(minpos == 2)
	  {
	    int aux = i3[0]; i3[0] = i3[2]; i3[2] = i3[1]; i3[1] = aux;
	  }
	facenumbers.Set(i3,numfaces);

	int bc = mesh.GetFaceDescriptor(elem.GetIndex()).BCProperty();
	face_ids.Append(bc);

	for(int j=0; j<3; j++)
	  if(point_ids[elem[j]] == -1)
	    point_ids[elem[j]] = (version >= 2) ? bc : 0;

	INDEX_2 i2a,i2b;
	INDEX_3 f_to_n;
	for(int j=0; j<3; j++)
	  {
	    i2a = INDEX_2(i3[j],i3[(j+1)%3]);
	    i2b[0] = i2a[1]; i2b[1] = i2a[0];
	    if(edgenumbers.Used(i2a))
	      f_to_n[j] = edgenumbers.Get(i2a);
	    else if(edgenumbers.Used(i2b))
	      f_to_n[j] = -edgenumbers.Get(i2b);
	    else
	      {
		numedges++;
		edgenumbers.Set(i2a,numedges);
		edge2node.Append(i2a);
		f_to_n[j] = numedges;
		if(version >= 2)
		  edge_ids.Append(bc);
		else
		  edge_ids.Append(0);
	      }
	  }
	face2edge.Append(f_to_n);
      }
    
    for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
      {
	const Element & el = mesh[ei];

	if(el.IsDeleted())
	  continue;

	numelems++;
	elnum[ei] = numelems;

	static int tetfaces[4][3] =
	  { { 0, 2, 1 },
	    { 0, 1, 3 },
	    { 1, 2, 3 },
	    { 2, 0, 3 } };
	
	for(int j=0; j<4; j++)
	  if(point_ids[el[j]] == -1)
	    point_ids[el[j]] = (version >= 2) ? el.GetIndex() : 0;

	INDEX_4 e_to_f;

	for(int i = 0; i < 4; i++)
	  {
	    INDEX_3 i3a(el[tetfaces[i][0]],el[tetfaces[i][1]],el[tetfaces[i][2]]);
	    
	    int min = i3a[0];
	    int minpos = 0;
	    for(int j=1; j<3; j++)
	      if(i3a[j] < min)
		{
		  min = i3a[j]; minpos = j;
		}
	    if(minpos == 1)
	      {
		int aux = i3a[0]; i3a[0] = i3a[1]; i3a[1] = i3a[2]; i3a[2] = aux;
	      }
	    else if(minpos == 2)
	      {
		int aux = i3a[0]; i3a[0] = i3a[2]; i3a[2] = i3a[1]; i3a[1] = aux;
	      }
	    INDEX_3 i3b(i3a[0],i3a[2],i3a[1]);
	    

	    if(facenumbers.Used(i3a))
	      e_to_f[i] = facenumbers.Get(i3a);
	    else if(facenumbers.Used(i3b))
	      e_to_f[i] = -facenumbers.Get(i3b);
	    else
	      {
		numfaces++;
		facenumbers.Set(i3a,numfaces);
		e_to_f[i] = numfaces;
		if(version >= 2)
		  face_ids.Append(el.GetIndex());
		else
		  face_ids.Append(0);

		INDEX_2 i2a,i2b;
		INDEX_3 f_to_n;
		for(int j=0; j<3; j++)
		  {
		    i2a = INDEX_2(i3a[j],i3a[(j+1)%3]);
		    i2b[0] = i2a[1]; i2b[1] = i2a[0];
		    if(edgenumbers.Used(i2a))
		      f_to_n[j] = edgenumbers.Get(i2a);
		    else if(edgenumbers.Used(i2b))
		      f_to_n[j] = -edgenumbers.Get(i2b);
		    else
		      {
			numedges++;
			edgenumbers.Set(i2a,numedges);
			edge2node.Append(i2a);
			f_to_n[j] = numedges;
			if(version >= 2)
			  edge_ids.Append(el.GetIndex());
			else
			  edge_ids.Append(0);
		      }
		  }
		face2edge.Append(f_to_n);	  
	      }
	  }
	element2face.Append(e_to_f);
      }




    ofstream outfile(filename.c_str());

    outfile.precision(16);

    int unitcode;
    double tolerance;
    double dS1,dS2, alphaDeg;
    double x3D,y3D,z3D;
    int modelverts(0), modeledges(0), modelfaces(0), modelcells(0);

    int numObj0D,numObj1D,numObj2D,numObj3D;
    int numports = ports.Size();

    ARRAY<int> nodenum(point_ids.Size()+1);

    nodenum = -1;
	    


    numnodes = 0;
    for(int i=0; i<point_ids.Size(); i++)
      {
	if(point_ids[i] != -1)
	  {
	    numnodes++;
	    nodenum[i] = numnodes;
	  }
      }


    if(haveuserdata)
      {
	unitcode = userdata_int[pos_int];
	pos_int++;

	tolerance = userdata_double[pos_double];
	pos_double++;

	dS1 = userdata_double[pos_double];
	pos_double++;
	dS2 = userdata_double[pos_double];
	pos_double++;
	alphaDeg = userdata_double[pos_double];
	pos_double++;

	x3D = userdata_double[pos_double];
	pos_double++;
	y3D = userdata_double[pos_double];
	pos_double++;
	z3D = userdata_double[pos_double];
	pos_double++;

	if(version == 2)
	  {
	    modelverts = userdata_int[pos_int];
	    pos_int++;
	    modeledges = userdata_int[pos_int];
	    pos_int++;
	    modelfaces = userdata_int[pos_int];
	    pos_int++;
	    modelcells = userdata_int[pos_int];
	    pos_int++;
	  }

	numObj3D = userdata_int[pos_int];
	pos_int++;
	numObj2D = userdata_int[pos_int];
	pos_int++;
	numObj1D = userdata_int[pos_int];
	pos_int++;
	numObj0D = userdata_int[pos_int];
	pos_int++;
      }
    else
      {
	unitcode = 3;

	tolerance = 1e-5;

	dS1 = dS2 = alphaDeg = 0;

	x3D = y3D = z3D = 0;

	modelverts = modeledges = modelfaces = modelcells = 0;
	
	numObj3D = numObj2D = numObj1D = numObj0D = 0;
      }

    string uidpid;
    if(version == 1)
      uidpid = "PID";
    else if (version == 2)
      uidpid = "UID";
    

    ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps;
    for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
      {
	if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)
	  {
	    idmaps.Append(new ARRAY<int,PointIndex::BASE>);
	    mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true);
	  }
      }

    ARRAY<int> id_num,id_type;
    ARRAY< ARRAY<int> *> id_groups;


	// sst 2008-03-12: Write problem class...
	{
		std::string block;
		block  = "// CST Tetrahedral ";
		block += !problemType.empty() ? problemType : "High Frequency";
		block += " Mesh, Version no.:\n";
		
		size_t size = block.size()-3;
		block += "// ";
		block.append( size, '^' );
		block += "\n";

		outfile
			<< block
			<< version << "." << subversion << "\n\n";
	}

	outfile 
	    << "// User Units Code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << unitcode << "\n\n"					\
	    << "// Geometric coord \"zero\" tolerance threshold:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << tolerance << "\n\n"				  \
	    << "// Periodic UnitCell dS1 , dS2 , alphaDeg:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << dS1 << " " << dS2 << " " << alphaDeg <<"\n\n"	\
	    << "// Periodic UnitCell origin in global coords (x3D,y3D,z3D):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << x3D << " " << y3D << " " << z3D << "\n" << endl;

    if(version == 2)
      {
	outfile << "// Model entity count: Vertices, Edges, Faces, Cells:\n" \
		<< "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
		<< modelverts << " " << modeledges << " " << modelfaces << " " << modelcells << endl << endl;
      }


    outfile << "// Topological mesh-entity counts (#elements,#faces,#edges,#nodes):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    outfile << numelems << " " 
	    << numfaces << " "
	    << numedges << " " 
	    << numnodes << endl << endl;

    outfile << "// NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<< uidpid <<":\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
       


    id_num.SetSize(mesh.GetNP()+1);
    id_type.SetSize(mesh.GetNP()+1);
    id_num = 0;
    id_type = 0;

    int n2,n4,n8;
    n2 = n4 = n8 = 0;

 
    for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
      {
	if(id_num[i] != 0)
	  continue;

	if(nodenum[i] == -1)
	  continue;

	ARRAY<int> group;
	group.Append(i);
	for(int j=0; j<idmaps.Size(); j++)
	  {
	    startsize = group.Size();
	    for(int k=0; k<startsize; k++)
	      {
		int id = (*idmaps[j])[group[k]];
		if(id != 0 && !group.Contains(id) && nodenum[id] != -1)
		  {
		    group.Append(id);
		    id_num[id] = j+1+id_num[group[k]];
		  }
	      }
	  }
	if(group.Size() > 1)
	  {
	    id_groups.Append(new ARRAY<int>(group));
	    if(group.Size() == 2)
	      {
		id_type[i] = 1;
		id_type[group[1]] = 2;
		n2++;
	      }
	    else if(group.Size() == 4)
	      {
		id_type[i] = 3;
		for(int j=1; j<group.Size(); j++)
		  id_type[group[j]] = 4;
		n4++;
	      }
	    else if(group.Size() == 8)
	      {
		id_type[i] = 5;
		for(int j=1; j<group.Size(); j++)
		  id_type[group[j]] = 6;
		n8++;
	      }
	    else
	      cerr << "ERROR: Identification group size = " << group.Size() << endl;
	  }
	
      }


    for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
      {
	if(nodenum[i] == -1)
	  continue;
	outfile << nodenum[i] << " "
		<< mesh[i](0) << " "
		<< mesh[i](1) << " "
		<< mesh[i](2) << " " << id_type[i] << " ";
	if(i-PointIndex::BASE < point_ids.Size())
	  outfile << point_ids[i];
	else
	  outfile << "0";
	outfile << "\n";
      }
    outfile << endl;

    outfile << "\n// Number of Periodic Master Nodes:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << n2 << "\n"			       \
	    << "\n" \
	    << "// MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<id_groups.Size(); i++)
      {
	if(id_groups[i]->Size() != 2)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << nodenum[(*id_groups[i])[j]] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  outfile << id_num[(*id_groups[i])[j]] << " ";
	outfile << "\n";

	delete id_groups[i];
	id_groups[i] = NULL;
      }
    outfile << endl;
	
	
    outfile << "// Number of Corner Periodic Master Nodes:\n"	      \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << n4 << "\n"				      \
	    << "\n" \
	    << "// MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";


    for(int i=0; i<id_groups.Size(); i++)
      {
	if(!id_groups[i] || id_groups[i]->Size() != 4)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << nodenum[(*id_groups[i])[j]] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  {
	    outfile << id_num[(*id_groups[i])[j]] << " ";
	  }
	outfile << "\n";

	delete id_groups[i];
	id_groups[i] = NULL;
      }
    outfile << endl;


    outfile << "// Number of Cubic Periodic Master Nodes:\n"	     \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << n8 << "\n"				     \
	    << "\n" \
	    << "// MasterNodeID, 7-SlaveNodeID's, TranslCodes:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<id_groups.Size(); i++)
      {
	if(!id_groups[i] || id_groups[i]->Size() != 8)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << nodenum[(*id_groups[i])[j]] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  outfile << id_num[(*id_groups[i])[j]] << " ";
	outfile << "\n";

	delete id_groups[i];
	id_groups[i] = NULL;
      }
    outfile << endl;

    


    outfile << "// EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<<uidpid<<":\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";

    
      
    ARRAY< ARRAY<int>* > vertex_to_edge(mesh.GetNP()+1);
    for(int i=0; i<=mesh.GetNP(); i++)
      vertex_to_edge[i] = new ARRAY<int>;

    ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps_edge(idmaps.Size());
    for(int i=0; i<idmaps_edge.Size(); i++)
      {
	idmaps_edge[i] = new ARRAY<int,PointIndex::BASE>(numedges);
	(*idmaps_edge[i]) = 0;
      }

    ARRAY<int> possible;
    for(int i=0; i<edge2node.Size(); i++)
      {
	const INDEX_2 & v = edge2node[i];
	for(int j=0; j<idmaps.Size(); j++)
	  {
	    INDEX_2 vid((*idmaps[j])[v[0]], (*idmaps[j])[v[1]]);
	    if(vid[0] != 0 && vid[0] != v[0] && vid[1] != 0 && vid[1] != v[1])
	      {
		Intersection(*vertex_to_edge[vid[0]],*vertex_to_edge[vid[1]],possible);
		if(possible.Size() == 1)
		  {
		    (*idmaps_edge[j])[possible[0]] = i+1;
		    (*idmaps_edge[j])[i+1] = possible[0];
		  }
		else if(possible.Size() > 0)
		  {
		    cerr << "ERROR: too many possible edge identifications" << endl;
		    (*testout) << "ERROR: too many possible edge identifications" << endl
			       << "*vertex_to_edge["<<vid[0]<<"] " << *vertex_to_edge[vid[0]] << endl
			       << "*vertex_to_edge["<<vid[1]<<"] " << *vertex_to_edge[vid[1]] << endl
			       << "possible " << possible << endl;
		  }
	      }
	  }
	vertex_to_edge[v[0]]->Append(i+1);
	vertex_to_edge[v[1]]->Append(i+1);
      }


    for(int i=0; i<vertex_to_edge.Size(); i++)
      delete vertex_to_edge[i];


    id_groups.SetSize(0);
    id_num.SetSize(numedges+1);
    id_num = 0;
    id_type.SetSize(numedges+1);
    id_type = 0;

    n2 = n4 = n8 = 0;

    for(int i=1; i<=edge2node.Size(); i++)
      {
	if(id_num[i] != 0)
	  continue;


	ARRAY<int> group;
	group.Append(i);
	for(int j=0; j<idmaps_edge.Size(); j++)
	  {
	    startsize = group.Size();
	    for(int k=0; k<startsize; k++)
	      {
		int id = (*idmaps_edge[j])[group[k]];
		if(id != 0 && !group.Contains(id))
		  {
		    group.Append(id);
		    id_num[id] = j+1+id_num[group[k]];
		  }
	      }
	  }
	if(group.Size() > 1)
	  {
	    id_num[i] = 1;
	    id_groups.Append(new ARRAY<int>(group));
	    if(group.Size() == 2)
	      {
		id_type[i] = 1;
		id_type[group[1]] = 2;
		n2++;
	      }
	    else if(group.Size() == 4)
	      {
		id_type[i] = 3;
		for(int j=1; j<group.Size(); j++)
		  id_type[group[j]] = 4;
		n4++;
	      }
	    else
	      {
		cerr << "ERROR: edge identification group size = " << group.Size() << endl;
		(*testout) << "edge group " << group << endl;
		for(int j=0; j<idmaps_edge.Size(); j++)
		  {
		    (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl;
		  }
	      }
	  }
      }



    for(int i=1; i<=edge2node.Size(); i++)
      {
	if(id_num[i] != 0)
	  continue;


	ARRAY<int> group;
	group.Append(i);
	for(int j=0; j<idmaps_edge.Size(); j++)
	  {
	    startsize = group.Size();
	    for(int k=0; k<startsize; k++)
	      {
		int id = (*idmaps_edge[j])[group[k]];
		if(id != 0 && !group.Contains(id))
		  {
		    group.Append(id);
		    id_num[id] = j+1+id_num[group[k]];
		  }
	      }
	  }
	if(group.Size() > 1)
	  {
	    id_num[i] = 1;
	    id_groups.Append(new ARRAY<int>(group));
	    if(group.Size() == 2)
	      {
		id_type[i] = 1;
		id_type[group[1]] = 2;
		n2++;
	      }
	    else if(group.Size() == 4)
	      {
		id_type[i] = 3;
		for(int j=1; j<group.Size(); j++)
		  id_type[group[j]] = 4;
		n4++;
	      }
	    else
	      {
		cerr << "ERROR: edge identification group size = " << group.Size() << endl;
		(*testout) << "edge group " << group << endl;
		for(int j=0; j<idmaps_edge.Size(); j++)
		  {
		    (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl;
		  }
	      }
	  }
	
      }

    
    for(int i=0; i<edge2node.Size(); i++)
      outfile << i+1 << " " << nodenum[edge2node[i][0]] << " " << nodenum[edge2node[i][1]] 
	      << " " << id_type[i+1] << " " << edge_ids[i] << "\n";

    outfile << endl;

    

    outfile << "// Number of Periodic Master Edges:\n"\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\
	    << n2 << "\n"			      \
	    << "\n"\
	    << "// MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<id_groups.Size(); i++)
      {
	if(id_groups[i]->Size() != 2)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << (*id_groups[i])[j] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  outfile << id_num[(*id_groups[i])[j]] << " ";
	outfile << "\n";

	delete id_groups[i];
	id_groups[i] = NULL;
      }
    outfile << endl;

    outfile << "// Number of Corner Periodic Master Edges:\n"		\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\
	    << n4 << "\n"				     \
	    << "\n"\
	    << "// MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<id_groups.Size(); i++)
      {
	if(!id_groups[i] || id_groups[i]->Size() != 4)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << (*id_groups[i])[j] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  outfile << id_num[(*id_groups[i])[j]] << " ";
	outfile << "\n";

	delete id_groups[i];
	id_groups[i] = NULL;
      }
    outfile << endl;


    outfile << "// FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), "<<uidpid<<":\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";

    
    
    ARRAY< ARRAY<int>* > edge_to_face(numedges+1);
    for(int i=0; i<edge_to_face.Size(); i++)
      edge_to_face[i] = new ARRAY<int>;

    
    for(int i=0; i<idmaps.Size(); i++)
      {
	idmaps[i]->SetSize(numfaces);
	(*idmaps[i]) = 0;
      }

    
    for(int i=0; i<face2edge.Size(); i++)
      {
	for(int j=0; j<idmaps_edge.Size(); j++)
	  {
	    int e1id,e2id,e3id;
	    e1id = (*idmaps_edge[j])[abs(face2edge[i][0])];
	    e2id = (*idmaps_edge[j])[abs(face2edge[i][1])];
	    e3id = (*idmaps_edge[j])[abs(face2edge[i][2])];
	    if(e1id != 0 && e1id != abs(face2edge[i][0]) &&
	       e2id != 0 && e2id != abs(face2edge[i][1]) &&
	       e3id != 0 && e3id != abs(face2edge[i][2]))
	      {
		Intersection(*edge_to_face[e1id],*edge_to_face[e2id],*edge_to_face[e3id],possible);
		if(possible.Size() == 1)
		  {
		    (*idmaps[j])[possible[0]] = i+1;
		    (*idmaps[j])[i+1] = possible[0];
		  }
		else if(possible.Size() > 0)
		  cerr << "ERROR: too many possible face identifications" << endl;
	      }
	  }

	edge_to_face[abs(face2edge[i][0])]->Append(i+1);
	edge_to_face[abs(face2edge[i][1])]->Append(i+1);
	edge_to_face[abs(face2edge[i][2])]->Append(i+1);
      }

    for(int i=0; i<edge_to_face.Size(); i++)
      delete edge_to_face[i];


    for(int i=0; i<idmaps_edge.Size(); i++)
      delete idmaps_edge[i];

    
    id_groups.SetSize(0);
    id_num.SetSize(numfaces+1);
    id_num = 0;

    n2 = n4 = n8 = 0;

    for(int i=1; i<=numfaces; i++)
      {
	if(id_num[i] != 0)
	  continue;

	ARRAY<int> group;
	group.Append(i);
	for(int j=0; j<idmaps.Size(); j++)
	  {
	    startsize = group.Size();
	    for(int k=0; k<startsize; k++)
	      {
		int id = (*idmaps[j])[group[k]];
		if(id != 0 && !group.Contains(id))
		  {
		    group.Append(id);
		    id_num[id] = j+1+id_num[group[k]];
		  }
	      }
	  }
	if(group.Size() > 1)
	  {
	    id_num[i] = -1;
	    id_groups.Append(new ARRAY<int>(group));
	    if(group.Size() == 2)
	      n2++;
	    else
	      cerr << "ERROR: face identification group size = " << group.Size() << endl;
	  }
	
      }


    for(int i=0; i<idmaps.Size(); i++)
      delete idmaps[i];




    for(int i=0; i<face2edge.Size(); i++)
      {	
	outfile << i+1 << " ";
	for(int j=0; j<3; j++)
	  outfile << face2edge[i][j] << " ";

	if(id_num[i+1] == 0)
	  outfile << 0;
	else if(id_num[i+1] == -1)
	  outfile << 1;
	else
	  outfile << 2;

	outfile << " " << face_ids[i] <<"\n";
      }
    outfile << endl;


    outfile << "// Number of Periodic Master Faces:\n"\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\
	    << n2 << "\n"			      \
	    << "\n"\
	    << "// MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2):\n"\
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<id_groups.Size(); i++)
      {
	if(id_groups[i]->Size() != 2)
	  continue;

	for(int j=0; j<id_groups[i]->Size(); j++)
	  outfile << (*id_groups[i])[j] << " ";
	for(int j=1; j<id_groups[i]->Size(); j++)
	  outfile << id_num[(*id_groups[i])[j]] << " ";
	outfile << "\n";

	delete id_groups[i];
      }
    outfile << endl;

    


    outfile << "// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, "<<uidpid<<":\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";

    for(ElementIndex i=0; i<mesh.GetNE(); i++)
      {
	if(elnum[i] >= 0)
	  {
	    outfile << elnum[i] << " ";
	    for(int j=0; j<4; j++)
	      outfile << element2face[elnum[i]-1][j] << " ";

	    outfile << mesh[i].GetIndex() << "\n";
	  }
      }
    outfile << endl;

    outfile << "// ElemID, NodeID0, NodeID1, NodeID2, NodeID3:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";

    
    for(ElementIndex i=0; i<mesh.GetNE(); i++)
      {
	if(elnum[i] >= 0)
	  outfile << elnum[i] << " "
		  << nodenum[mesh[i][1]] << " " << nodenum[mesh[i][0]] << " " << nodenum[mesh[i][2]] << " " << nodenum[mesh[i][3]] << "\n";
      }
    outfile << endl;
    

    

    outfile << "// Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D):\n"
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
	    << " "<< numObj3D << " " << numObj2D << " " << numObj1D << " " << numObj0D << "\n" \
	    << "\n" \
	    << "// Number of Ports (Ports are a subset of Object2D list):\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \
	    << numports << "\n"						\
	    << endl;


    ARRAY< ARRAY<int> * > groups;

    int maxg = -1;
    for(int i = 0; i<uid_to_group_3D.Size(); i++)
      if(uid_to_group_3D[i] > maxg)
	maxg = uid_to_group_3D[i];
    for(int i = 0; i<uid_to_group_2D.Size(); i++)
      if(uid_to_group_2D[i] > maxg)
	maxg = uid_to_group_2D[i];
    for(int i = 0; i<uid_to_group_1D.Size(); i++)
      if(uid_to_group_1D[i] > maxg)
	maxg = uid_to_group_1D[i];
    for(int i = 0; i<uid_to_group_0D.Size(); i++)
      if(uid_to_group_0D[i] > maxg)
	maxg = uid_to_group_0D[i];

    groups.SetSize(maxg+1);
    for(int i=0; i<groups.Size(); i++)
      groups[i] = new ARRAY<int>;

    for(ElementIndex i=0; i<mesh.GetNE(); i++)
      if(uid_to_group_3D[mesh[i].GetIndex()] >= 0)
	groups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1);
      
    


    outfile << "// Object3D GroupID, #Elems <immediately followed by> ElemID List:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<numObj3D; i++)
      {
	outfile << i << " " << groups[i]->Size() << "\n";
	for(int j=0; j<groups[i]->Size(); j++)
	  outfile << (*groups[i])[j] << "\n";
      }

    for(int i=0; i<groups.Size(); i++)
      groups[i]->SetSize(0);

    for(int i=0; i<face_ids.Size(); i++)
      if(uid_to_group_2D[face_ids[i]] >= 0)
	groups[uid_to_group_2D[face_ids[i]]]->Append(i+1);
      

    outfile << "// Object2D GroupID, #Faces <immediately followed by> FaceID List:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<numObj2D; i++)
      {
	outfile << i << " " << groups[i]->Size() << "\n";
	for(int j=0; j<groups[i]->Size(); j++)
	  {
	    outfile << (*groups[i])[j];
	    if(ports.Contains(face_ids[(*groups[i])[j]-1]))
	      outfile << " P";
	    outfile << "\n";
	  }
      }
    outfile << endl;

    
    for(int i=0; i<groups.Size(); i++)
      groups[i]->SetSize(0);

    for(int i=0; i<edge_ids.Size(); i++)
      if(uid_to_group_1D[edge_ids[i]] >= 0)
	groups[uid_to_group_1D[edge_ids[i]]]->Append(i+1);



    outfile << "// Object1D GroupID, #Edges <immediately followed by> EdgeID List:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<numObj1D; i++)
      {
	outfile << i << " " << groups[i]->Size() << "\n";
	for(int j=0; j<groups[i]->Size(); j++)
	  outfile << (*groups[i])[j] << "\n";
      }
    outfile << endl;

    
    for(int i=0; i<groups.Size(); i++)
      groups[i]->SetSize(0);
    for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
      {
	if(i-PointIndex::BASE < point_ids.Size())
	  {
	    if(uid_to_group_0D[point_ids[i]] >= 0)
	      groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-PointIndex::BASE);
	  }
	else
	  groups[uid_to_group_0D[0]]->Append(i+1-PointIndex::BASE);
      }


    outfile << "// Object0D GroupID, #Nodes <immediately followed by> NodeID List:\n" \
	    << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n";
    for(int i=0; i<numObj0D; i++)
      {
	outfile << i << " " << groups[i]->Size() << "\n";
	for(int j=0; j<groups[i]->Size(); j++)
	  outfile << (*groups[i])[j] << "\n";
      }
    outfile << endl;

    for(int i=0; i<groups.Size(); i++)
      delete groups[i];


    outfile.close();

    cout << ".tet export done" << endl;
  }
Example #30
0
void WriteFile (int typ,
                const Mesh & mesh,
                const CSGeometry & geom,
                const char * filename,
                const char * geomfile,
                double h)
{


    int inverttets = mparam.inverttets;
    int invertsurf = mparam.inverttrigs;








    if (typ == WRITE_EDGEELEMENT)
    {
        // write edge element file
        // Peter Harscher, ETHZ

        cout << "Write Edge-Element Format" << endl;

        ofstream outfile (filename);

        int i, j;
        int ned;

        // hash table representing edges;
        INDEX_2_HASHTABLE<int> edgeht(mesh.GetNP());

        // list of edges
        ARRAY<INDEX_2> edgelist;

        // edge (point) on boundary ?
        BitArray bedge, bpoint(mesh.GetNP());

        static int eledges[6][2] = { { 1, 2 } , { 1, 3 } , { 1, 4 },
            { 2, 3 } , { 2, 4 } , { 3, 4 }
        };

        // fill hashtable   (point1, point2)  ---->  edgenr
        for (i = 1; i <= mesh.GetNE(); i++)
        {
            const Element & el = mesh.VolumeElement (i);
            INDEX_2 edge;
            for (j = 1; j <= 6; j++)
            {
                edge.I1() = el.PNum (eledges[j-1][0]);
                edge.I2() = el.PNum (eledges[j-1][1]);
                edge.Sort();

                if (!edgeht.Used (edge))
                {
                    edgelist.Append (edge);
                    edgeht.Set (edge, edgelist.Size());
                }
            }
        }


        // set bedges, bpoints
        bedge.SetSize (edgelist.Size());
        bedge.Clear();
        bpoint.Clear();

        for (i = 1; i <= mesh.GetNSE(); i++)
        {
            const Element2d & sel = mesh.SurfaceElement(i);
            for (j = 1; j <= 3; j++)
            {
                bpoint.Set (sel.PNum(j));

                INDEX_2 edge;
                edge.I1() = sel.PNum(j);
                edge.I2() = sel.PNum(j%3+1);
                edge.Sort();

                bedge.Set (edgeht.Get (edge));
            }
        }



        outfile << mesh.GetNE() << endl;
        // write element ---> point
        for (i = 1; i <= mesh.GetNE(); i++)
        {
            const Element & el = mesh.VolumeElement(i);

            outfile.width(8);
            outfile << i;
            for (j = 1; j <= 4; j++)
            {
                outfile.width(8);
                outfile << el.PNum(j);
            }
            outfile << endl;
        }

        // write element ---> edge
        for (i = 1; i <= mesh.GetNE(); i++)
        {
            const Element & el = mesh.VolumeElement (i);
            INDEX_2 edge;
            for (j = 1; j <= 6; j++)
            {
                edge.I1() = el.PNum (eledges[j-1][0]);
                edge.I2() = el.PNum (eledges[j-1][1]);
                edge.Sort();

                outfile.width(8);
                outfile << edgeht.Get (edge);
            }
            outfile << endl;
        }

        // write points
        outfile << mesh.GetNP() << endl;
        outfile.precision (6);
        for (i = 1; i <= mesh.GetNP(); i++)
        {
            const Point3d & p = mesh.Point(i);

            for (j = 1; j <= 3; j++)
            {
                outfile.width(8);
                outfile << p.X(j);
            }
            outfile << "       "
                    << (bpoint.Test(i) ? "1" : 0) << endl;
        }

        // write edges
        outfile << edgelist.Size() << endl;
        for (i = 1; i <= edgelist.Size(); i++)
        {
            outfile.width(8);
            outfile << edgelist.Get(i).I1();
            outfile.width(8);
            outfile << edgelist.Get(i).I2();
            outfile << "       "
                    << (bedge.Test(i) ? "1" : "0") << endl;
        }
    }




}