Esempio n. 1
0
 inline MPI_Request MyMPI_IRecv (FlatArray<T, BASE> s, int dest)
 {
   MPI_Request request;
   MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, 1, MPI_COMM_WORLD, &request);
   return request;
   // MPI_Request_free (&request);
 }
Esempio n. 2
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]);
}
Esempio n. 3
0
 void Append (FlatArray<T2, B2> a2)
 {
   if (this->size+a2.Size() > allocsize)
     ReSize (this->size+a2.Size());
   for (int i = 0; i < a2.Size(); i++)
     this->data[this->size+i] = a2[i+B2];
   this->size += a2.Size();
 }
Esempio n. 4
0
inline void BubbleSort (const FlatArray<T> & data)
{
  T hv;
  for (int i = 0; i < data.Size(); i++)
    for (int j = i+1; j < data.Size(); j++)
      if (data[i] > data[j])
	{
	  hv = data[i];
	  data[i] = data[j];
	  data[j] = hv;
	}
}
Esempio n. 5
0
inline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table)
{
  for (int i = BASE; i < table.Size()+BASE; i++)
    {
      ost << i << ": ";
      FlatArray<T> row = table[i];
      ost << "(" << row.Size() << ") ";
      for (int j = 0; j < row.Size(); j++)
	ost << row[j] << " ";
      ost << endl;
    }
  return ost;
}
Esempio n. 6
0
inline void BubbleSort (FlatArray<T> & data, FlatArray<S> & slave)
{
  T hv;
  S hvs;
  for (int i = 0; i < data.Size(); i++)
    for (int j = i+1; j < data.Size(); j++)
      if (data[i] > data[j])
	{
	  hv = data[i];
	  data[i] = data[j];
	  data[j] = hv;

	  hvs = slave[i];
	  slave[i] = slave[j];
	  slave[j] = hvs;
	}
}
Esempio n. 7
0
  BASE_TABLE :: BASE_TABLE (const FlatArray<int> & entrysizes, int elemsize)
    : data(entrysizes.Size())
  {
    int i, cnt = 0;
    int n = entrysizes.Size();

    for (i = 0; i < n; i++)
      cnt += entrysizes[i];
    oneblock = new char[elemsize * cnt];
    // mem_total_alloc_table += elemsize * cnt;

    cnt = 0;
    for (i = 0; i < n; i++)
      {
	data[i].maxsize = entrysizes[i];
	data[i].size = 0;

	data[i].col = &oneblock[elemsize * cnt];
	cnt += entrysizes[i];
      }
  }
Esempio n. 8
0
    void Add (int blocknr, const FlatArray<int> & dofs)
    {
      switch (mode)
	{
	case 1:
	  if (blocknr+1 > nd) nd = blocknr+1; 
	  break;
	case 2:
	  cnt[blocknr]+=dofs.Size();
	  break;
	case 3:
	  for (int j = 0; j < dofs.Size(); j++)
	    (*table)[blocknr][cnt[blocknr]+j] = dofs[j];
	  cnt[blocknr]+=dofs.Size();
          /*
	  for (int j = 0; j < dofs.Size(); j++)
	    table->Data()[cnt[blocknr]+j] = dofs[j];
	  cnt[blocknr]+=dofs.Size();
          */
	  break;
	}
    }
Esempio n. 9
0
  /// Construct table of variable entrysize
  INLINE Table (FlatArray<int> entrysize)
  {
    size_t cnt = 0;
    size  = entrysize.Size();
    
    index = new size_t[size+1];
    for (int i = 0; i < size; i++)
      {
	index[i] = cnt;
	cnt += entrysize[i];
      }
    index[size] = cnt;
    data = new T[cnt];
  }
Esempio n. 10
0
  std::tuple<int,int*>  Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const
  {
    
    switch (nodetype)
      {
      case 0:
	{
	  FlatArray<int> dn = mesh->GetParallelTopology().GetDistantPNums(locnum);
	  return std::tuple<int,int*>(dn.Size(), &dn[0]);
	}
      case 1:
	{
	  FlatArray<int> dn = mesh->GetParallelTopology().GetDistantEdgeNums(locnum);
	  return std::tuple<int,int*>(dn.Size(), &dn[0]);
	}
      case 2:
	{
	  FlatArray<int> dn = mesh->GetParallelTopology().GetDistantFaceNums(locnum);
	  return std::tuple<int,int*>(dn.Size(), &dn[0]);
	}
      default:
	return std::tuple<int,int*>(0,nullptr);
      }
  }
Esempio n. 11
0
 inline void MyMPI_ISend (FlatArray<T, BASE> s, int dest, MPI_Request & request)
 {
   MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, 1, MPI_COMM_WORLD, & request);
 }
 inline void MyMPI_Send (FlatArray<T, BASE> s, int dest, int tag)
 {
   MPI_Send( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD);
 }
void WriteDiffPackFormat (const Mesh & mesh,
			  const CSGeometry & /*geom*/,
			  const string & filename)
{
  //   double scale = globflags.GetNumFlag ("scale", 1);
  double scale = 1;

  ofstream outfile(filename.c_str());
  outfile.precision(14);


  if (mesh.GetDimension() == 3)

    {
      // Output compatible to Diffpack grid format
      // Bartosz Sawicki <*****@*****.**>

      int np = mesh.GetNP();
      int ne = mesh.GetNE();
      int nse = mesh.GetNSE();
      Array <int> BIname;
      Array <int> BCsinpoint;
      int i, j, k, l;


      outfile.precision(6);
      outfile.setf (ios::fixed, ios::floatfield);
      outfile.setf (ios::showpoint);

      const Element & eldummy = mesh.VolumeElement((int)1);
      outfile << "\n\n"
	"Finite element mesh (GridFE):\n\n"
	"  Number of space dim. =   3\n"
	"  Number of elements   =  " << ne << "\n"
	"  Number of nodes      =  " << np << "\n\n"
	"  All elements are of the same type : dpTRUE\n"
	"  Max number of nodes in an element: "<< eldummy.GetNP() << "\n"
	"  Only one subdomain               : dpFALSE\n"
	"  Lattice data                     ? 0\n\n\n\n";

      for (i = 1; i <= nse; i++)
	{
	  int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty();
	  int nbi=BIname.Size();
	  int found=0;
	  for (j = 1; j <= nbi; j++)
	    if(BI == BIname.Get(j)) found = 1;
	  if( ! found ) BIname.Append(BI);
	}

      outfile << "  " << BIname.Size() <<  " Boundary indicators:  ";
      for (i =1 ; i <= BIname.Size(); i++)
	outfile << BIname.Get(i) << " ";
      outfile << "\n\n\n";

      outfile << "  Nodal coordinates and nodal boundary indicators,\n"
	"  the columns contain:\n"
	"   - node number\n"
	"   - coordinates\n"
	"   - no of boundary indicators that are set (ON)\n"
	"   - the boundary indicators that are set (ON) if any.\n"
	"#\n";


      // setup point-to-surfaceelement table
      TABLE<SurfaceElementIndex, PointIndex::BASE> point2sel(np);
      for (SurfaceElementIndex sei = 0; sei < nse; sei++)
	{
	  const Element2d & el = mesh[sei];
	  for (int j = 0; j < el.GetNP(); j++)
	    point2sel.Add (el[j], sei);
	}


      for (i = 1; i <= np; i++)
        {
          const Point3d & p = mesh.Point(i);

          outfile.width(12);
          outfile << i << "  (";
          outfile.width(16);
          outfile << p.X()/scale << ", ";
          outfile.width(16);
          outfile << p.Y()/scale << ", ";
          outfile.width(16);
          outfile << p.Z()/scale << ") ";

	  if(mesh[PointIndex(i)].Type() != INNERPOINT)
	    {
	      BCsinpoint.DeleteAll();
	      /*
	      for (j = 1; j <= nse; j++)
	      */
	      FlatArray<SurfaceElementIndex> sels = point2sel[i];
	      for (int jj = 0; jj < sels.Size(); jj++)
		{
		  for (k = 1; k <= mesh[sels[jj]].GetNP(); k++)
		    {
		      if(mesh[sels[jj]].PNum(k)==i)
			{
			  int BC=mesh.GetFaceDescriptor(mesh[sels[jj]].GetIndex()).BCProperty();
			  int nbcsp=BCsinpoint.Size();
			  int found = 0;
			  for (l = 1; l <= nbcsp; l++)
			    if(BC == BCsinpoint.Get(l)) found = 1;
			  if( ! found ) BCsinpoint.Append(BC);
			}
		    }
		}
	      int nbcsp = BCsinpoint.Size();
	      outfile << "[" << nbcsp << "] ";
	      for (j = 1; j <= nbcsp; j++)
		outfile << BCsinpoint.Get(j) << " ";
	      outfile << "\n";
            }
          else outfile << "[0]\n";

        }

      outfile << "\n"
	"  Element types and connectivity\n"
	"  the columns contain:\n"
	"   - element number\n"
	"   - element type\n"
	"   - subdomain number\n"
	"   - the global node numbers of the nodes in the element.\n"
	"#\n";

      for (i = 1; i <= ne; i++)
        {
          const Element & el = mesh.VolumeElement(i);
          outfile.width(5);
          if(el.GetNP()==4)
            outfile << i << "  ElmT4n3D ";
          else
            outfile << i << "  ElmT10n3D ";
          outfile.width(4);
          outfile << el.GetIndex() << "    ";
          if(el.GetNP()==10)
            {
	      outfile.width(8);
	      outfile << el.PNum(1);
	      outfile.width(8);
	      outfile << el.PNum(3);
	      outfile.width(8);
	      outfile << el.PNum(2);
	      outfile.width(8);
	      outfile << el.PNum(4);
	      outfile.width(8);
	      outfile << el.PNum(6);
	      outfile.width(8);
	      outfile << el.PNum(8);
	      outfile.width(8);
	      outfile << el.PNum(5);
	      outfile.width(8);
	      outfile << el.PNum(7);
	      outfile.width(8);
	      outfile << el.PNum(10);
	      outfile.width(8);
	      outfile << el.PNum(9);
            }
          else
            {
	      outfile.width(8);
	      outfile << el.PNum(1);
	      outfile.width(8);
	      outfile << el.PNum(3);
	      outfile.width(8);
	      outfile << el.PNum(2);
	      outfile.width(8);
	      outfile << el.PNum(4);
            }
          outfile << "\n";
        }
    } /* Diffpack */

  else

    {
      // Output compatible to Diffpack grid format 2D

      int np = mesh.GetNP();
      //int ne = mesh.GetNE();
      int nse = mesh.GetNSE();
      Array <int> BIname;
      Array <int> BCsinpoint;
      int i, j, k, l;


      outfile.precision(6);
      outfile.setf (ios::fixed, ios::floatfield);
      outfile.setf (ios::showpoint);
      const Element2d & eldummy = mesh.SurfaceElement((int)1);
      outfile << "\n\n"
	"Finite element mesh (GridFE):\n\n"
	"  Number of space dim. =  2\n"
	"  Number of elements   =  " << nse << "\n"
	"  Number of nodes      =  " << np << "\n\n"
	"  All elements are of the same type : dpTRUE\n"
	"  Max number of nodes in an element: "<<eldummy.GetNP()<<"\n"
	"  Only one subdomain               : dpFALSE\n"
	"  Lattice data                     ? 0\n\n\n\n";

      for (i = 1; i <= nse; i++)
	{
	  int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty();
	  int nbi=BIname.Size();
	  int found=0;
	  for (j = 1; j <= nbi; j++)
	    if(BI == BIname.Get(j)) found = 1;
	  if( ! found ) BIname.Append(BI);
	}

      outfile << "  " << BIname.Size() <<  " Boundary indicators:  ";
      for (i =1 ; i <= BIname.Size(); i++)
	outfile << BIname.Get(i) << " ";
      outfile << "\n\n\n";

      outfile << "  Nodal coordinates and nodal boundary indicators,\n"
	"  the columns contain:\n"
	"   - node number\n"
	"   - coordinates\n"
	"   - no of boundary indicators that are set (ON)\n"
	"   - the boundary indicators that are set (ON) if any.\n"
	"#\n";

      for (i = 1; i <= np; i++)
        {
          const Point3d & p = mesh.Point(i);

          outfile.width(12);
          outfile << i << "  (";
          outfile.width(16);
          outfile << p.X()/scale << ", ";
          outfile.width(16);
          outfile << p.Y()/scale << ", ";

	  if(mesh[PointIndex(i)].Type() != INNERPOINT)
	    {
	      BCsinpoint.DeleteAll();
	      for (j = 1; j <= nse; j++)
		{
		  for (k = 1; k <= 2; k++)
		    {
		      if(mesh.SurfaceElement(j).PNum(k)==i)
			{
			  int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).GetIndex()).BCProperty();
			  int nbcsp=BCsinpoint.Size();
			  int found = 0;
			  for (l = 1; l <= nbcsp; l++)
			    if(BC == BCsinpoint.Get(l)) found = 1;
			  if( ! found ) BCsinpoint.Append(BC);
			}
		    }
		}
	      int nbcsp = BCsinpoint.Size();
	      outfile << "[" << nbcsp << "] ";
	      for (j = 1; j <= nbcsp; j++)
		outfile << BCsinpoint.Get(j) << " ";
	      outfile << "\n";
            }
          else outfile << "[0]\n";

        }

      outfile << "\n"
	"  Element types and connectivity\n"
	"  the columns contain:\n"
	"   - element number\n"
	"   - element type\n"
	"   - subdomain number\n"
	"   - the global node numbers of the nodes in the element.\n"
	"#\n";

      for (i = 1; i <= nse; i++)
        {
          const Element2d & el = mesh.SurfaceElement(i);
          outfile.width(12);
          if(eldummy.GetNP()==3)
            outfile << i << "  ElmT3n2D ";
          else
            outfile << i << "  ElmT6n2D ";
          outfile.width(12);
          outfile << el.GetIndex() << "    ";
	  outfile.width(16);
	  outfile << el.PNum(1);
	  outfile.width(16);
	  outfile << el.PNum(2);
	  outfile.width(16);
	  outfile << el.PNum(3);
          if(eldummy.GetNP()==6)
            {
	     outfile.width(16);
	     outfile << el.PNum(6);
	     outfile.width(16);
	     outfile << el.PNum(4);
	     outfile.width(16);
	     outfile << el.PNum(5);
            }
          outfile << "\n";
        }
    }
}
Esempio n. 14
0
 inline void MyMPI_IRecvTag (FlatArray<T, BASE> s, int dest, int tag, MPI_Request & request)
 {
   MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request);
 }
Esempio n. 15
0
  /// Creates fixed element size table
  inline TABLE (const FlatArray<int,BASE> & entrysizes)
    : BASE_TABLE (FlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])), 
		  sizeof(T))
  { ; }
 inline MPI_Request MyMPI_IRecv (FlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD)
 {
   MPI_Request request;
   MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, comm, &request);
   return request;
 }
Esempio n. 17
0
  ParallelDofs :: ParallelDofs (MPI_Comm acomm, Table<int> && adist_procs, 
				int dim, bool iscomplex)
    : comm(acomm), dist_procs(adist_procs)
    
  {
    int ntasks = MyMPI_GetNTasks(comm);
    int id = MyMPI_GetId(comm);
      
    ndof = dist_procs.Size();
    
    if (ntasks == 1)
      {
	Array<int> nexdofs(ntasks), ndistprocs(ndof);
	nexdofs = 0;
	ndistprocs = 0;
	
	exchangedofs = Table<int> (nexdofs);
	dist_procs = Table<int> (ndistprocs);
	
	ismasterdof.SetSize(ndof);
	ismasterdof.Set();

        global_ndof = ndof;
	return;
      }
    
    // transpose table
    Array<int> nexdofs(ntasks);
    nexdofs = 0;
    
    for (int i = 0; i < ndof; i++)
      for (int d : dist_procs[i])
	nexdofs[d]++;
    
    exchangedofs = Table<int>(nexdofs);
    nexdofs = 0;

    for (int i = 0; i < ndof; i++)
      for (int d : dist_procs[i])
	exchangedofs[d][nexdofs[d]++] = i;
      
    ismasterdof.SetSize (ndof);
    ismasterdof.Set();

    for (int i = 0; i < id; i++)
      for (int ex : exchangedofs[i])
	ismasterdof.Clear (ex);


    mpi_t.SetSize (ntasks); 
    
    MPI_Datatype mpi_type;
    
    mpi_type = iscomplex ?
      MyGetMPIType<Complex>() : MyGetMPIType<double>(); 
    
    if (dim != 1)
      {
	MPI_Datatype htype;
	MPI_Type_contiguous (dim, mpi_type, &htype);
	mpi_type = htype;
      }
    
    for (int dest = 0; dest < ntasks; dest++ )
      {
	if ( !IsExchangeProc(dest) ) continue;
	
	FlatArray<int> exdofs = GetExchangeDofs(dest);
	int len_vec = exdofs.Size();
	if (len_vec == 0) continue;
	
	Array<int> blocklen(len_vec);
	blocklen = 1;
	
	MPI_Type_indexed (len_vec, &blocklen[0], &exdofs[0], 
			  mpi_type, &mpi_t[dest]);
	MPI_Type_commit (&mpi_t[dest]);
      }
    
    for (int i = 0; i < ntasks; i++)
      if (IsExchangeProc (i))
	all_dist_procs.Append (i);



    size_t nlocal = 0;
    for (int i = 0; i < ndof; i++)
      if (ismasterdof.Test(i)) nlocal++;
    global_ndof = MyMPI_AllReduce (nlocal, MPI_SUM, comm);
  }
 inline void MyMPI_Recv ( FlatArray<T, BASE> s, int src, int tag)
 {
   MPI_Status status;
   MPI_Recv( &s.First(), s.Size(), MyGetMPIType<T>(), src, tag, MPI_COMM_WORLD, &status);
 }
Esempio n. 19
0
  void MeshOptimize2d :: GenericImprove (Mesh & mesh)
  {
    if (!faceindex)
      {
	if (writestatus)
	  PrintMessage (3, "Generic Improve");

	for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)
	  GenericImprove (mesh);
      
	faceindex = 0;
      }

    // int j, k, l, ri;
    int np = mesh.GetNP();
    int ne = mesh.GetNSE();
    //    SurfaceElementIndex sei;

    
//     for (SurfaceElementIndex sei = 0; sei < ne; sei++)
//       {
// 	const Element2d & el = mesh[sei];
// 	(*testout) << "element " << sei << ": " <<flush;
// 	for(int j=0; j<el.GetNP(); j++)
// 	  (*testout) << el[j] << " " << flush;
// 	(*testout) << "IsDeleted() " << el.IsDeleted()<< endl;
//       }

    bool ok;
    int olddef, newdef;

    ARRAY<ImprovementRule*> rules;
    ARRAY<SurfaceElementIndex> elmap;
    ARRAY<int> elrot;
    ARRAY<PointIndex> pmap;
    ARRAY<PointGeomInfo> pgi;

    int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();
  
    ImprovementRule * r1;

    // 2 triangles to quad
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3));
    r1->oldels.Append (Element2d (3, 2, 4));
    r1->newels.Append (Element2d (1, 2, 4, 3));
    r1->deledges.Append (INDEX_2 (2,3));
    r1->onp = 4;
    r1->bonus = 2;
    rules.Append (r1);

    // 2 quad to 1 quad
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (4, 3, 2, 5));
    r1->newels.Append (Element2d (1, 2, 5, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->deledges.Append (INDEX_2 (3, 4));
    r1->onp = 5;
    r1->bonus = 0;
    rules.Append (r1);

    // swap quads
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (3, 2, 5, 6));
    r1->newels.Append (Element2d (1, 6, 3, 4));
    r1->newels.Append (Element2d (1, 2, 5, 6));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 6;
    r1->bonus = 0;
    rules.Append (r1);

    // three quads to 2
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 5, 6, 3));
    r1->oldels.Append (Element2d (3, 6, 7, 4));
    r1->newels.Append (Element2d (1, 2, 5, 4));
    r1->newels.Append (Element2d (4, 5, 6, 7));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->deledges.Append (INDEX_2 (3, 4));
    r1->deledges.Append (INDEX_2 (3, 6));
    r1->onp = 7;
    r1->bonus = -1;
    rules.Append (r1);

    // quad + 2 connected trigs to quad
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 5, 3));
    r1->oldels.Append (Element2d (3, 5, 4));
    r1->newels.Append (Element2d (1, 2, 5, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->deledges.Append (INDEX_2 (3, 4));
    r1->deledges.Append (INDEX_2 (3, 5));
    r1->onp = 5;
    r1->bonus = 0;
    rules.Append (r1);

    // quad + 2 non-connected trigs to quad (a and b)
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 6, 3));
    r1->oldels.Append (Element2d (1, 4, 5));
    r1->newels.Append (Element2d (1, 3, 4, 5));
    r1->newels.Append (Element2d (1, 2, 6, 3));
    r1->deledges.Append (INDEX_2 (1, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 6;
    r1->bonus = 0;
    rules.Append (r1);

    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 6, 3));
    r1->oldels.Append (Element2d (1, 4, 5));
    r1->newels.Append (Element2d (1, 2, 4, 5));
    r1->newels.Append (Element2d (4, 2, 6, 3));
    r1->deledges.Append (INDEX_2 (1, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 6;
    r1->bonus = 0;
    rules.Append (r1);

    // two quad + trig -> one quad + trig
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 5, 6, 3));
    r1->oldels.Append (Element2d (4, 3, 6));
    r1->newels.Append (Element2d (1, 2, 6, 4));
    r1->newels.Append (Element2d (2, 5, 6));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->deledges.Append (INDEX_2 (3, 4));
    r1->deledges.Append (INDEX_2 (3, 6));
    r1->onp = 6;
    r1->bonus = -1;
    rules.Append (r1);

    // swap quad + trig (a and b)
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 5, 3));
    r1->newels.Append (Element2d (2, 5, 3, 4));
    r1->newels.Append (Element2d (1, 2, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 5;
    r1->bonus = 0;
    rules.Append (r1);

    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (2, 5, 3));
    r1->newels.Append (Element2d (1, 2, 5, 3));
    r1->newels.Append (Element2d (1, 3, 4));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 5;
    r1->bonus = 0;
    rules.Append (r1);


    // 2 quads to quad + 2 trigs
    r1 = new ImprovementRule;
    r1->oldels.Append (Element2d (1, 2, 3, 4));
    r1->oldels.Append (Element2d (3, 2, 5, 6));
    r1->newels.Append (Element2d (1, 5, 6, 4));
    r1->newels.Append (Element2d (1, 2, 5));
    r1->newels.Append (Element2d (4, 6, 3));
    r1->deledges.Append (INDEX_2 (2, 3));
    r1->onp = 6;
    r1->bonus = 0;
    //    rules.Append (r1);




    ARRAY<int> mapped(rules.Size());
    ARRAY<int> used(rules.Size());
    used = 0;
    mapped = 0;

  

    for (int ri = 0; ri < rules.Size(); ri++)
      {
	ImprovementRule & rule = *rules[ri];
	rule.incelsonnode.SetSize (rule.onp);
	rule.reused.SetSize (rule.onp);

	for (int j = 1; j <= rule.onp; j++)
	  {
	    rule.incelsonnode.Elem(j) = 0;
	    rule.reused.Elem(j) = 0;
	  }

	for (int j = 1; j <= rule.oldels.Size(); j++)
	  {
	    const Element2d & el = rule.oldels.Elem(j);
	    for (int k = 1; k <= el.GetNP(); k++)
	      rule.incelsonnode.Elem(el.PNum(k))--;
	  }

	for (int j = 1; j <= rule.newels.Size(); j++)
	  {
	    const Element2d & el = rule.newels.Elem(j);
	    for (int k = 1; k <= el.GetNP(); k++)
	      {
		rule.incelsonnode.Elem(el.PNum(k))++;
		rule.reused.Elem(el.PNum(k)) = 1;
	      }
	  }
      }



  
    TABLE<int,PointIndex::BASE> elonnode(np);
    ARRAY<int,PointIndex::BASE> nelonnode(np);
    TABLE<SurfaceElementIndex> nbels(ne);

    nelonnode = -4;

    for (SurfaceElementIndex sei = 0; sei < ne; sei++)
      {
	const Element2d & el = mesh[sei];

	if (el.GetIndex() == faceindex && !el.IsDeleted())
	  {
	    for (int j = 0; j < el.GetNP(); j++)
	      elonnode.Add (el[j], sei);
	  }
	if(!el.IsDeleted())
	  {
	    for (int j = 0; j < el.GetNP(); j++)
	      nelonnode[el[j]]++;
	  }
      }

    for (SurfaceElementIndex sei = 0; sei < ne; sei++)
      {
	const Element2d & el = mesh[sei];
	if (el.GetIndex() == faceindex && !el.IsDeleted())
	  {
	    for (int j = 0; j < el.GetNP(); j++)
	      {
		for (int k = 0; k < elonnode[el[j]].Size(); k++)
		  {
		    int nbel = elonnode[el[j]] [k];
		    bool inuse = false;
		    for (int l = 0; l < nbels[sei].Size(); l++)
		      if (nbels[sei][l] == nbel)
			inuse = true;
		    if (!inuse)
		      nbels.Add (sei, nbel);
		  }
	      }
	  }
      }


    for (int ri = 0; ri < rules.Size(); ri++)
      {
	const ImprovementRule & rule = *rules[ri];
      
	elmap.SetSize (rule.oldels.Size());
	elrot.SetSize (rule.oldels.Size());
	pmap.SetSize (rule.onp);
	pgi.SetSize (rule.onp);


	for (SurfaceElementIndex sei = 0; sei < ne; sei++)
	  {
	    if (multithread.terminate)
	      break;
	    if (mesh[sei].IsDeleted()) continue;

	    elmap[0] = sei;
	    FlatArray<SurfaceElementIndex> neighbours = nbels[sei];
	    
	    for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++)
	      {
		const Element2d & el0 = mesh[sei];
		const Element2d & rel0 = rule.oldels[0];

		if (el0.GetIndex() != faceindex) continue;
		if (el0.IsDeleted()) continue;
		if (el0.GetNP() != rel0.GetNP()) continue;


		pmap = -1;
 
		for (int k = 0; k < el0.GetNP(); k++)
		  {
		    pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1);
		    pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1);
		  }
		
		ok = 1;
		for (int i = 1; i < elmap.Size(); i++)
		  {
		    // try to find a mapping for reference-element i

		    const Element2d & rel = rule.oldels[i];
		    bool possible = 0;

		    for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++)
		      {
			const Element2d & el = mesh[neighbours[elmap[i]]];
			if (el.IsDeleted()) continue;
			if (el.GetNP() != rel.GetNP()) continue;

			for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++)
			  {
			    possible = 1;

			    for (int k = 0; k < rel.GetNP(); k++)
			      if (pmap.Elem(rel[k]) != -1 &&
				  pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1))
				possible = 0;

			    if (possible) 
			      {
				for (int k = 0; k < el.GetNP(); k++)
				  {
				    pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1);
				    pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1);
				  }
				break;
			      }
			  }
			if (possible) break;
		      }

		    if (!possible) 
		      {
			ok = 0;
			break;
		      }

		    elmap[i] = neighbours[elmap[i]];
		  }

		for(int i=0; ok && i<rule.deledges.Size(); i++)
		  {
		    ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()),
					 pmap.Elem(rule.deledges[i].I2()));
		  }
								    
								    
		
		
		if (!ok) continue;

		mapped[ri]++;

		olddef = 0;
		for (int j = 1; j <= pmap.Size(); j++)
		  olddef += sqr (nelonnode[pmap.Get(j)]);
		olddef += rule.bonus;

		newdef = 0;
		for (int j = 1; j <= pmap.Size(); j++)
		  if (rule.reused.Get(j))
		    newdef += sqr (nelonnode[pmap.Get(j)] + 
				   rule.incelsonnode.Get(j));

		if (newdef > olddef)
		  continue;

		// calc metric badness
		double bad1 = 0, bad2 = 0;
		Vec<3> n;

		SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1));
		GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n);
		  
		for (int j = 1; j <= rule.oldels.Size(); j++)
		  bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n);
		  
		// check new element:
		for (int j = 1; j <= rule.newels.Size(); j++)
		  {
		    const Element2d & rnel = rule.newels.Get(j);
		    Element2d nel(rnel.GetNP());
		    for (int k = 1; k <= rnel.GetNP(); k++)
		      nel.PNum(k) = pmap.Get(rnel.PNum(k));

		    bad2 += nel.CalcJacobianBadness (mesh.Points(), n);
		  }

		if (bad2 > 1e3) continue;

		if (newdef == olddef && bad2 > bad1) continue;
		  

		// generate new element:
		for (int j = 1; j <= rule.newels.Size(); j++)
		  {
		    const Element2d & rnel = rule.newels.Get(j);
		    Element2d nel(rnel.GetNP());
		    nel.SetIndex (faceindex);
		    for (int k = 1; k <= rnel.GetNP(); k++)
		      {
			nel.PNum(k) = pmap.Get(rnel.PNum(k));
			nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k));
		      }
		      
		    mesh.AddSurfaceElement(nel);
		  }
		  
		for (int j = 0; j < rule.oldels.Size(); j++)
		  mesh.DeleteSurfaceElement ( elmap[j] );

		for (int j = 1; j <= pmap.Size(); j++)
		  nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j);

		used[ri]++;
	      }
	  }
      }

    mesh.Compress();

    for (int ri = 0; ri < rules.Size(); ri++)
      {
	PrintMessage (5, "rule ", ri+1, " ",
		      mapped[ri], "/", used[ri], " mapped/used");
      }
  }