Пример #1
0
  MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d)
  {
    int i, oldne;
    PointIndex pi;

    int meshed;
    int cntsteps; 


    ARRAY<INDEX_2> connectednodes;

    mesh3d.Compress();

    //  mesh3d.PrintMemInfo (cout);

    if (mp.checkoverlappingboundary)
      if (mesh3d.CheckOverlappingBoundary())
	throw NgException ("Stop meshing since boundary mesh is overlapping");

    int nonconsist = 0;
    for (int k = 1; k <= mesh3d.GetNDomains(); k++)
      {
	PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains());

	mesh3d.FindOpenElements(k);

	/*
	bool res = mesh3d.CheckOverlappingBoundary();
	if (res)
	  {
	    PrintError ("Surface is overlapping !!");
	    nonconsist = 1;
	  }
	*/

	bool res = (mesh3d.CheckConsistentBoundary() != 0);
	if (res)
	  {
	    PrintError ("Surface mesh not consistent");
	    nonconsist = 1;
	  }
      }

    if (nonconsist)
      {
	PrintError ("Stop meshing since surface mesh not consistent");
	throw NgException ("Stop meshing since surface mesh not consistent");
      }

    double globmaxh = mp.maxh;

    for (int k = 1; k <= mesh3d.GetNDomains(); k++)
      {
	if (multithread.terminate)
	  break;

	PrintMessage (2, "");
	PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains());
	(*testout) << "Meshing subdomain " << k << endl;
 
	mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k));

	mesh3d.CalcSurfacesOfNode();
	mesh3d.FindOpenElements(k);

	if (!mesh3d.GetNOpenElements())
	  continue;


	
	Box<3> domain_bbox( Box<3>::EMPTY_BOX ); 
        /*
        Point<3> (1e10, 1e10, 1e10),
        Point<3> (-1e10, -1e10, -1e10));
        */

	for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++)
	  {
	    const Element2d & el = mesh3d[sei];
	    if (el.IsDeleted() ) continue;
	    
	    if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k ||
		mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k)

	      for (int j = 0; j < el.GetNP(); j++)
		domain_bbox.Add (mesh3d[el[j]]);
	  }
	domain_bbox.Increase (0.01 * domain_bbox.Diam());


	for (int qstep = 1; qstep <= 3; qstep++)
	  {
	    if (mesh3d.HasOpenQuads())
	      {
		string rulefile = ngdir;

		const char ** rulep = NULL;
		switch (qstep)
		  {
		  case 1:
		    rulefile += "/rules/prisms2.rls";
		    rulep = prismrules2;
		    break;
		  case 2: // connect pyramid to triangle
		    rulefile += "/rules/pyramids2.rls";
		    rulep = pyramidrules2;
		    break;
		  case 3: // connect to vis-a-vis point
		    rulefile += "/rules/pyramids.rls";
		    rulep = pyramidrules;
		    break;
		  }
	      
		//		Meshing3 meshing(rulefile);
		Meshing3 meshing(rulep); 
	      
		MeshingParameters mpquad = mp;
	      
		mpquad.giveuptol = 15;
		mpquad.baseelnp = 4;
		mpquad.starshapeclass = 1000;
		mpquad.check_impossible = qstep == 1;   // for prisms only (air domain in trafo)


		for (pi = PointIndex::BASE; 
		     pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
		  meshing.AddPoint (mesh3d[pi], pi);

		mesh3d.GetIdentifications().GetPairs (0, connectednodes);
		for (i = 1; i <= connectednodes.Size(); i++)
		  meshing.AddConnectedPair (connectednodes.Get(i));
	      
		for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
		  {
		    Element2d hel = mesh3d.OpenElement(i);
		    meshing.AddBoundaryElement (hel);
		  }
	      
		oldne = mesh3d.GetNE();
	      
		meshing.GenerateMesh (mesh3d, mpquad);
	      
		for (i = oldne + 1; i <= mesh3d.GetNE(); i++)
		  mesh3d.VolumeElement(i).SetIndex (k);
	      
		(*testout) 
		  << "mesh has " << mesh3d.GetNE() << " prism/pyramid�elements" << endl;
	      
		mesh3d.FindOpenElements(k);
	      }
	  }


	if (mesh3d.HasOpenQuads())
	  {
	    PrintSysError ("mesh has still open quads");
	    throw NgException ("Stop meshing since too many attempts");
	    // return MESHING3_GIVEUP;
	  }


	if (mp.delaunay && mesh3d.GetNOpenElements())
	  {
	    Meshing3 meshing((const char**)NULL);
	 
	    mesh3d.FindOpenElements(k);
	  

	    for (pi = PointIndex::BASE; 
		 pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
	      meshing.AddPoint (mesh3d[pi], pi);
	  

	    for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
	      meshing.AddBoundaryElement (mesh3d.OpenElement(i));
	  
	    oldne = mesh3d.GetNE();

	    meshing.Delaunay (mesh3d, k, mp);

	    for (i = oldne + 1; i <= mesh3d.GetNE(); i++)
	      mesh3d.VolumeElement(i).SetIndex (k);

	    PrintMessage (3, mesh3d.GetNP(), " points, ",
			  mesh3d.GetNE(), " elements");
	  }


	cntsteps = 0;
	if (mesh3d.GetNOpenElements())
	do
	  {
	    if (multithread.terminate)
	      break;

	    mesh3d.FindOpenElements(k);
	    PrintMessage (5, mesh3d.GetNOpenElements(), " open faces");
	    cntsteps++;

	    if (cntsteps > mp.maxoutersteps) 
	      throw NgException ("Stop meshing since too many attempts");

	    string rulefile = ngdir + "/tetra.rls";
	    PrintMessage (1, "start tetmeshing");

	    //	  Meshing3 meshing(rulefile);
	    Meshing3 meshing(tetrules);
      
	    ARRAY<int, PointIndex::BASE> glob2loc(mesh3d.GetNP());
	    glob2loc = -1;
            
	    for (pi = PointIndex::BASE; 
		 pi < mesh3d.GetNP()+PointIndex::BASE; pi++)
	      
	      if (domain_bbox.IsIn (mesh3d[pi]))
		glob2loc[pi] = 
		  meshing.AddPoint (mesh3d[pi], pi);

	    for (i = 1; i <= mesh3d.GetNOpenElements(); i++)
	      {
		Element2d hel = mesh3d.OpenElement(i);
		for (int j = 0; j < hel.GetNP(); j++)
		  hel[j] = glob2loc[hel[j]];
		meshing.AddBoundaryElement (hel);
	    // meshing.AddBoundaryElement (mesh3d.OpenElement(i));
	      }

	    oldne = mesh3d.GetNE();

	    mp.giveuptol = 15 + 10 * cntsteps; 
	    mp.sloppy = 5;
	    meshing.GenerateMesh (mesh3d, mp);

	    for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++)
	      mesh3d[ei].SetIndex (k);
	  
	  
	    mesh3d.CalcSurfacesOfNode();
	    mesh3d.FindOpenElements(k);
	  
	    teterrpow = 2;
	    if (mesh3d.GetNOpenElements() != 0)
	      {
		meshed = 0;
		PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found");

		//	      mesh3d.Save ("tmp.vol");


		MeshOptimize3d optmesh;

		const char * optstr = "mcmstmcmstmcmstmcm";
		size_t j;
		for (j = 1; j <= strlen(optstr); j++)
		  {
		    mesh3d.CalcSurfacesOfNode();
		    mesh3d.FreeOpenElementsEnvironment(2);
		    mesh3d.CalcSurfacesOfNode();

		    switch (optstr[j-1])
		      {
		      case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break;
		      case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break;
		      case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break;
		      case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break;
		      case 'm': mesh3d.ImproveMesh(OPT_REST); break;
		      }	  

		  }

		mesh3d.FindOpenElements(k);	      
		PrintMessage (3, "Call remove problem");
		RemoveProblem (mesh3d, k);
		mesh3d.FindOpenElements(k);
	      }
	    else
	      {
		meshed = 1;
		PrintMessage (1, "Success !");
	      }
	  }
	while (!meshed);

	PrintMessage (1, mesh3d.GetNP(), " points, ",
		      mesh3d.GetNE(), " elements");
      }

    mp.maxh = globmaxh;

    MeshQuality3d (mesh3d);

    return MESHING3_OK;
  }  
Пример #2
0
void LocalH :: 
FindInnerBoxesRec2 (GradingBox * box,
		    class AdFront3 * adfront, 
		    ARRAY<Box3d> & faceboxes,
		    ARRAY<int> & faceinds, int nfinbox)
{
  if (!box) return;
  
  int i, j;
  
  GradingBox * father = box -> father;
  
  Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]);
  Vec3d v(box->h2, box->h2, box->h2);
  Box3d boxc(c-v, c+v);

  Point3d fc(father->xmid[0], father->xmid[1], father->xmid[2]);
  Vec3d fv(father->h2, father->h2, father->h2);
  Box3d fboxc(fc-fv, fc+fv);

  Box3d boxcfc(c,fc);


  static ARRAY<int> faceused;
  static ARRAY<int> faceused2;
  static ARRAY<int> facenotused;

  faceused.SetSize(0);
  facenotused.SetSize(0);
  faceused2.SetSize(0);

  for (j = 1; j <= nfinbox; j++)
    {
      //      adfront->GetFaceBoundingBox (faceinds.Get(j), facebox);
      const Box3d & facebox = faceboxes.Get(faceinds.Get(j));
  
      if (boxc.Intersect (facebox))
	faceused.Append(faceinds.Get(j));
      else
	facenotused.Append(faceinds.Get(j));

      if (boxcfc.Intersect (facebox))
	faceused2.Append (faceinds.Get(j));
    }
  
  for (j = 1; j <= faceused.Size(); j++)
    faceinds.Elem(j) = faceused.Get(j);
  for (j = 1; j <= facenotused.Size(); j++)
    faceinds.Elem(j+faceused.Size()) = facenotused.Get(j);

  
  if (!father->flags.cutboundary)
    {
      box->flags.isinner = father->flags.isinner;
      box->flags.pinner = father->flags.pinner;
    }
  else
    {
      Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]);
      
      if (father->flags.isinner)
	box->flags.pinner = 1;
      else
	{
	  if (adfront->SameSide (c, cf, &faceused2))
	    box->flags.pinner = father->flags.pinner;
	  else
	    box->flags.pinner = 1 - father->flags.pinner;
	}
      
      if (box->flags.cutboundary)
	box->flags.isinner = 0;
      else
	box->flags.isinner = box->flags.pinner;
    }

  int nf = faceused.Size();
  for (i = 0; i < 8; i++)
    FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf);
}
Пример #3
0
twoint GetOLimit(int i) const {return olimit->Get(i);}
Пример #4
0
twoint GetILimit(int i) const {return ilimit->Get(i);}
Пример #5
0
 //get all trigs:
 int GetTrig(int i) const
   {
     if (i <= charttrigs->Size()) {return charttrigs->Get(i);}
     else {return outertrigs->Get(i-charttrigs->Size());}
   }
Пример #6
0
 int GetOuterTrig(int i) const {return outertrigs->Get(i);}
Пример #7
0
 int GetChartTrig(int i) const {return charttrigs->Get(i);}
Пример #8
0
 const STLBoundarySeg & GetSegment(int i) {return boundary.Get(i);}
Пример #9
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");
      }
  }