Beispiel #1
0
 // Manually add a volume element of a given type to an existing mesh object
 DLL_HEADER void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et,
                                      int * pi)
 {
    Mesh * m = (Mesh*)mesh;
    Element el (4);
    el.SetIndex (1);
    el.PNum(1) = pi[0];
    el.PNum(2) = pi[1];
    el.PNum(3) = pi[2];
    el.PNum(4) = pi[3];
    m->AddVolumeElement (el);
 }
Beispiel #2
0
  void RefinePrisms (Mesh & mesh, const CSGeometry * geom, 
		     ZRefinementOptions & opt)
  {
    int i, j;
    bool found, change;
    int cnt = 0;


    // markers for z-refinement:  p1, p2, levels  
    // p1-p2 is an edge to be refined
    ARRAY<INDEX_3> ref_uniform;
    ARRAY<INDEX_3> ref_singular;
    ARRAY<INDEX_4 > ref_slices;

    BitArray first_id(geom->identifications.Size());
    first_id.Set();

  
    INDEX_2_HASHTABLE<int> & identpts = 
      mesh.GetIdentifications().GetIdentifiedPoints ();

    if (&identpts)
      {
	for (i = 1; i <= identpts.GetNBags(); i++)
	  for (j = 1; j <= identpts.GetBagSize(i); j++)
	    {
	      INDEX_2 pair;
	      int idnr;
	      identpts.GetData(i, j, pair, idnr);
	      const CloseSurfaceIdentification * csid = 
		dynamic_cast<const CloseSurfaceIdentification*> 
		(geom->identifications.Get(idnr));
	      if (csid)
		{
		  if (!csid->GetSlices().Size())
		    {
		      if (first_id.Test (idnr))
			{
			  first_id.Clear(idnr);
			  ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels()));
			  ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1()));
			  ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2()));
			}
		    }
		  else
		    {   
		      //const ARRAY<double> & slices = csid->GetSlices();
		      INDEX_4 i4;
		      i4[0] = pair.I1();
		      i4[1] = pair.I2();
		      i4[2] = idnr;
		      i4[3] = csid->GetSlices().Size();
		      ref_slices.Append (i4);
		    }
		}
	    }
      }

  
  
    ARRAY<EdgePointGeomInfo> epgi;

    while (1)
      {
	cnt++;
	PrintMessage (3, "Z-Refinement, level = ", cnt);
	INDEX_2_HASHTABLE<int> refedges(mesh.GetNSE()+1);


	found = 0;
	// mark prisms due to close surface flags:
	int oldsize = ref_uniform.Size();
	for (i = 1; i <= oldsize; i++)
	  {
	    int pi1 = ref_uniform.Get(i).I1();
	    int pi2 = ref_uniform.Get(i).I2();
	    int levels = ref_uniform.Get(i).I3();

	    if (levels > 0)
	      {
		const Point3d & p1 = mesh.Point(pi1);
		const Point3d & p2 = mesh.Point(pi2);
		int npi(0);
	      
		INDEX_2 edge(pi1, pi2);
		edge.Sort();
		if (!refedges.Used(edge))
		  {
		    Point3d np = Center (p1, p2);
		    npi = mesh.AddPoint (np);
		    refedges.Set (edge, npi);
		    found = 1;
		  }

		ref_uniform.Elem(i) = INDEX_3(pi1, npi, levels-1);
		ref_uniform.Append (INDEX_3(pi2, npi, levels-1));
	      }
	  }
	for (i = 1; i <= ref_singular.Size(); i++)
	  {
	    int pi1 = ref_singular.Get(i).I1();
	    int pi2 = ref_singular.Get(i).I2();
	    int levels = ref_singular.Get(i).I3();

	    if (levels > 0)
	      {
		const Point3d & p1 = mesh.Point(pi1);
		const Point3d & p2 = mesh.Point(pi2);
		int npi;
	      
		INDEX_2 edge(pi1, pi2);
		edge.Sort();
		if (!refedges.Used(edge))
		  {
		    Point3d np = Center (p1, p2);
		    npi = mesh.AddPoint (np);
		    refedges.Set (edge, npi);
		    found = 1;
		  }
		else
		  npi = refedges.Get (edge);

		ref_singular.Elem(i) = INDEX_3(pi1, npi, levels-1);
	      }
	  }

	for (i = 1; i <= ref_slices.Size(); i++)
	  {
	    int pi1 = ref_slices.Get(i)[0];
	    int pi2 = ref_slices.Get(i)[1];
	    int idnr = ref_slices.Get(i)[2];
	    int slicenr = ref_slices.Get(i)[3];

	    if (slicenr > 0)
	      {
		const Point3d & p1 = mesh.Point(pi1);
		const Point3d & p2 = mesh.Point(pi2);
		int npi;

		const CloseSurfaceIdentification * csid = 
		  dynamic_cast<const CloseSurfaceIdentification*> 
		  (geom->identifications.Get(idnr));

	      
		INDEX_2 edge(pi1, pi2);
		edge.Sort();
		if (!refedges.Used(edge))
		  {
		    const ARRAY<double> & slices = csid->GetSlices();
		    //(*testout) << "idnr " << idnr << " i " << i << endl;
		    //(*testout) << "slices " << slices << endl;
		    double slicefac = slices.Get(slicenr);
		    double slicefaclast = 
		      (slicenr == slices.Size()) ? 1 : slices.Get(slicenr+1);
		    
		    Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1);
		    //(*testout) << "slicenr " << slicenr << " slicefac " << slicefac << " quot " << (slicefac / slicefaclast) << " np " << np << endl;
		    npi = mesh.AddPoint (np);
		    refedges.Set (edge, npi);
		    found = 1;
		  }
		else
		  npi = refedges.Get (edge);
		
		ref_slices.Elem(i)[1] = npi;
		ref_slices.Elem(i)[3] --;
	      }
	  }




	for (i = 1; i <= mesh.GetNE(); i++)
	  {
	    Element & el = mesh.VolumeElement (i);
	    if (el.GetType() != PRISM)
	      continue;

	    for (j = 1; j <= 3; j++)
	      {
		int pi1 = el.PNum(j);
		int pi2 = el.PNum(j+3);
		const Point3d & p1 = mesh.Point(pi1);
		const Point3d & p2 = mesh.Point(pi2);

		bool ref = 0;

		/*
		  if (Dist (p1, p2) > mesh.GetH (Center (p1, p2)))
		  ref = 1;
		*/

		/*
		  if (cnt <= opt.minref)
		  ref = 1;
		*/

		/*
		  if ((pi1 == 460 || pi2 == 460 ||
		  pi1 == 461 || pi2 == 461) && cnt <= 8) ref = 1;
		*/
		if (ref == 1)
		  {
		    INDEX_2 edge(pi1, pi2);
		    edge.Sort();
		    if (!refedges.Used(edge))
		      {
			Point3d np = Center (p1, p2);
			int npi = mesh.AddPoint (np);
			refedges.Set (edge, npi);
			found = 1;
		      }
		  }
	      }
	  }
      
	if (!found) break;

	// build closure:
	PrintMessage (5, "start closure");
	do
	  {
	    PrintMessage (5, "start loop");
	    change = 0;
	    for (i = 1; i <= mesh.GetNE(); i++)
	      {
		Element & el = mesh.VolumeElement (i);
		if (el.GetType() != PRISM)
		  continue;
	      
		bool hasref = 0, hasnonref = 0;
		for (j = 1; j <= 3; j++)
		  {
		    int pi1 = el.PNum(j);
		    int pi2 = el.PNum(j+3);
		    if (pi1 != pi2)
		      {
			INDEX_2 edge(pi1, pi2);
			edge.Sort();
			if (refedges.Used(edge))
			  hasref = 1;
			else 
			  hasnonref = 1;
		      }
		  }

		if (hasref && hasnonref)
		  {
		    //		  cout << "el " << i << " in closure" << endl;
		    change = 1;
		    for (j = 1; j <= 3; j++)
		      {
			int pi1 = el.PNum(j);
			int pi2 = el.PNum(j+3);
			const Point3d & p1 = mesh.Point(pi1);
			const Point3d & p2 = mesh.Point(pi2);
		      
			INDEX_2 edge(pi1, pi2);
			edge.Sort();
			if (!refedges.Used(edge))
			  {
			    Point3d np = Center (p1, p2);
			    int npi = mesh.AddPoint (np);
			    refedges.Set (edge, npi);
			  }
		      }
		  }
	      }
	  }
	while (change);

	PrintMessage (5, "Do segments");

	//      (*testout) << "closure formed, np = " << mesh.GetNP() << endl;

	int oldns = mesh.GetNSeg();

	for (i = 1; i <= oldns; i++)
	  {
	    const Segment & el = mesh.LineSegment(i);

	    INDEX_2 i2(el.p1, el.p2);
	    i2.Sort();
	  
	    int pnew;
	    EdgePointGeomInfo ngi;
      
	    if (refedges.Used(i2))
	      {
		pnew = refedges.Get(i2);
		//	      ngi = epgi.Get(pnew);
	      }
	    else
	      {
		continue;

		// 	      Point3d pb;

		// 	      /*
		// 	      geom->PointBetween (mesh.Point (el.p1),
		// 				  mesh.Point (el.p2),
		// 				  el.surfnr1, el.surfnr2,
		// 				  el.epgeominfo[0], el.epgeominfo[1],
		// 				  pb, ngi);
		// 	      */
		// 	      pb = Center (mesh.Point (el.p1), mesh.Point (el.p2));

		// 	      pnew = mesh.AddPoint (pb);
	      
		// 	      refedges.Set (i2, pnew);
	      
		// 	      if (pnew > epgi.Size())
		// 		epgi.SetSize (pnew);
		// 	      epgi.Elem(pnew) = ngi;
	      }
	  
	    Segment ns1 = el;
	    Segment ns2 = el;
	    ns1.p2 = pnew;
	    ns1.epgeominfo[1] = ngi;
	    ns2.p1 = pnew;
	    ns2.epgeominfo[0] = ngi;

	    mesh.LineSegment(i) = ns1;
	    mesh.AddSegment (ns2);
	  }
      
	PrintMessage (5, "Segments done, NSeg = ", mesh.GetNSeg());

	// do refinement
	int oldne = mesh.GetNE();
	for (i = 1; i <= oldne; i++)
	  {
	    Element & el = mesh.VolumeElement (i);
	    if (el.GetNP() != 6)
	      continue;

	    int npi[3];
	    for (j = 1; j <= 3; j++)
	      {
		int pi1 = el.PNum(j);
		int pi2 = el.PNum(j+3);

		if (pi1 == pi2)
		  npi[j-1] = pi1;
		else
		  {
		    INDEX_2 edge(pi1, pi2);
		    edge.Sort();
		    if (refedges.Used (edge))
		      npi[j-1] = refedges.Get(edge);
		    else
		      {
			/*
			  (*testout) << "ERROR: prism " << i << " has hanging node !!" 
			  << ", edge = " << edge << endl;
			  cerr << "ERROR: prism " << i << " has hanging node !!" << endl;
			*/
			npi[j-1] = 0;
		      }
		  }
	      }

	    if (npi[0])
	      {
		Element nel1(6), nel2(6);
		for (j = 1; j <= 3; j++)
		  {
		    nel1.PNum(j) = el.PNum(j);
		    nel1.PNum(j+3) = npi[j-1];
		    nel2.PNum(j) = npi[j-1];
		    nel2.PNum(j+3) = el.PNum(j+3);
		  }
		nel1.SetIndex (el.GetIndex());
		nel2.SetIndex (el.GetIndex());
		mesh.VolumeElement (i) = nel1;
		mesh.AddVolumeElement (nel2);
	      }
	  }

      
	PrintMessage (5, "Elements done, NE = ", mesh.GetNE());


	// do surface elements
	int oldnse = mesh.GetNSE();
	//      cout << "oldnse = " << oldnse << endl;
	for (i = 1; i <= oldnse; i++)
	  {
	    Element2d & el = mesh.SurfaceElement (i);
	    if (el.GetType() != QUAD)
	      continue;

	    int index = el.GetIndex();
	    int npi[2];
	    for (j = 1; j <= 2; j++)
	      {
		int pi1, pi2;

		if (j == 1)
		  {
		    pi1 = el.PNum(1);
		    pi2 = el.PNum(4);
		  }
		else
		  {
		    pi1 = el.PNum(2);
		    pi2 = el.PNum(3);
		  }

		if (pi1 == pi2)
		  npi[j-1] = pi1;
		else
		  {
		    INDEX_2 edge(pi1, pi2);
		    edge.Sort();
		    if (refedges.Used (edge))
		      npi[j-1] = refedges.Get(edge);
		    else
		      {
			npi[j-1] = 0;
		      }
		  }
	      }

	    if (npi[0])
	      {
		Element2d nel1(QUAD), nel2(QUAD);
		for (j = 1; j <= 4; j++)
		  {
		    nel1.PNum(j) = el.PNum(j);
		    nel2.PNum(j) = el.PNum(j);
		  }
		nel1.PNum(3) = npi[1];
		nel1.PNum(4) = npi[0];
		nel2.PNum(1) = npi[0];
		nel2.PNum(2) = npi[1];
		/*
		  for (j = 1; j <= 2; j++)
		  {
		  nel1.PNum(j) = el.PNum(j);
		  nel1.PNum(j+2) = npi[j-1];
		  nel2.PNum(j) = npi[j-1];
		  nel2.PNum(j+2) = el.PNum(j+2);
		  }
		*/
		nel1.SetIndex (el.GetIndex());
		nel2.SetIndex (el.GetIndex());

		mesh.SurfaceElement (i) = nel1;
		mesh.AddSurfaceElement (nel2);

		int si = mesh.GetFaceDescriptor (index).SurfNr();

		Point<3> hp = mesh.Point(npi[0]);
		geom->GetSurface(si)->Project (hp);
		mesh.Point (npi[0]).SetPoint (hp);

		hp = mesh.Point(npi[1]);
		geom->GetSurface(si)->Project (hp);
		mesh.Point (npi[1]).SetPoint (hp);

		//	      geom->GetSurface(si)->Project (mesh.Point(npi[0]));
		//	      geom->GetSurface(si)->Project (mesh.Point(npi[1]));
	      }
	  }

	PrintMessage (5, "Surface elements done, NSE = ", mesh.GetNSE());

      }
  }
Beispiel #3
0
/*
    Philippose Rajan - 11 June 2009
    
    Added an initial experimental function for 
    generating prismatic boundary layers on 
    a given set of surfaces.
    
    The number of layers, height of the first layer 
    and the growth / shrink factor can be specified 
    by the user

    Currently, the layer height is calculated using:
    height = h_first_layer * (growth_factor^(num_layers - 1))
*/
   void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp)
   {
      int i, j;

      ofstream dbg("BndLayerDebug.log");

      // Angle between a surface element and a growth-vector below which 
      // a prism is project onto that surface as a quad
      // (in degrees)
      double angleThreshold = 5.0;
      
      cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl;

      // Use an array to support creation of boundary 
      // layers for multiple surfaces in the future...
      Array<int> surfid;
      int surfinp = 0;
      int prismlayers = 1;
      double hfirst = 0.01;
      double growthfactor = 1.0;

      // Monitor and print out the number of prism and quad elements 
      // added to the mesh
      int numprisms = 0;
      int numquads = 0;

      while(surfinp >= 0)
      {
         cout << "Enter Surface ID (-1 to end list): ";
         cin >> surfinp;
         if(surfinp >= 0) surfid.Append(surfinp);
      }

      cout << "Number of surfaces entered = " << surfid.Size() << endl; 
      cout << "Selected surfaces are:" << endl;

      for(i = 1; i <= surfid.Size(); i++)
      {
         cout << "Surface " << i << ": " << surfid.Elem(i) << endl;
      }
      
      cout << endl << "Enter number of prism layers: ";
      cin >> prismlayers;
      if(prismlayers < 1) prismlayers = 1;

      cout << "Enter height of first layer: ";
      cin >> hfirst;
      if(hfirst <= 0.0) hfirst = 0.01;

      cout << "Enter layer growth / shrink factor: ";
      cin >> growthfactor;
      if(growthfactor <= 0.0) growthfactor = 0.5;

      cout << "Old NP: " << mesh.GetNP() << endl;
      cout << "Old NSE: " << mesh.GetNSE() << endl;
      
      for(int layer = prismlayers; layer >= 1; layer--)
      {
         cout << "Generating layer: " << layer << endl;

         const MeshTopology& meshtopo = mesh.GetTopology();
         const_cast<MeshTopology &> (meshtopo).SetBuildEdges(true);
         const_cast<MeshTopology &> (meshtopo).SetBuildFaces(true);
         const_cast<MeshTopology &> (meshtopo).Update();

         double layerht = hfirst;

         if(growthfactor == 1)
         {
            layerht = layer * hfirst;
         }
         else
         {
            layerht = hfirst*(pow(growthfactor,(layer+1)) - 1)/(growthfactor - 1);
         }

         cout << "Layer Height = " << layerht << endl;

         // Need to store the old number of points and 
         // surface elements because there are new points and 
         // surface elements being added during the process
         int np = mesh.GetNP();
         int nse = mesh.GetNSE();

         // Safety measure to ensure no issues with mesh 
         // consistency
         int nseg = mesh.GetNSeg();

         // Indicate which points need to be remapped
         BitArray bndnodes(np);

         // Map of the old points to the new points
         Array<int> mapto(np);

         // Growth vectors for the prismatic layer based on 
         // the effective surface normal at a given point
         Array<Vec3d> growthvectors(np);

         // Bit array to identify all the points belonging 
         // to the surface of interest
         bndnodes.Clear();

         // Run through all the surface elements and mark the points 
         // belonging to those where a boundary layer has to be created.
         // In addition, also calculate the effective surface normal 
         // vectors at each of those points to determine the mesh motion 
         // direction
         cout << "Marking points for remapping...." << endl;

         for (i = 1; i <= nse; i++)
         {
            int snr = mesh.SurfaceElement(i).GetIndex();
            // cout << "snr = " << snr << endl;
            if (surfid.Contains(snr))
            {
               Element2d & sel = mesh.SurfaceElement(i);
               int selNP = sel.GetNP();
               for(j = 1; j <= selNP; j++)
               {
                  // Set the bitarray to indicate that the 
                  // point is part of the required set
                  bndnodes.Set(sel.PNum(j));
		  
                  // Vec3d& surfacenormal = Vec3d();   ????
                  Vec3d surfacenormal;

                  // Calculate the surface normal at the current point 
                  // with respect to the current surface element
                  GetSurfaceNormal(mesh,sel,j,surfacenormal);
                  
                  // Add the surface normal to the already existent one 
                  // (This gives the effective normal direction at corners 
                  //  and curved areas)
                  growthvectors.Elem(sel.PNum(j)) = growthvectors.Elem(sel.PNum(j)) 
                                                    + surfacenormal;
               }
            }
         }

         // Add additional points into the mesh structure in order to 
         // clone the surface elements.
         // Also invert the growth vectors so that they point inwards, 
         // and normalize them
         cout << "Cloning points and calculating growth vectors...." << endl;

         for (i = 1; i <= np; i++)
         {
            if (bndnodes.Test(i))
            {
               mapto.Elem(i) = mesh.AddPoint (mesh.Point (i));

               growthvectors.Elem(i).Normalize();
               growthvectors.Elem(i) *= -1.0;
            }
            else
            {
               mapto.Elem(i) = 0;
               growthvectors.Elem(i) = Vec3d(0,0,0);
            }
         }


         // Add quad surface elements at edges for surfaces which 
         // dont have boundary layers

         // Bit array to keep track of segments already processed
         BitArray segsel(nseg);

         // Set them all to "1" to initially activate all segments
         segsel.Set();

         cout << "Adding 2D Quad elements on required surfaces...." << endl;

         for (i = 1; i <= nseg; i++)
         {
            int seg_p1 = mesh.LineSegment(i)[0];
            int seg_p2 = mesh.LineSegment(i)[1];

            // Only go in if the segment is still active, and if both its 
            // surface index is part of the "hit-list"
            if(segsel.Test(i) && surfid.Contains(mesh.LineSegment(i).si))
            {
               // clear the bit to indicate that this segment has been processed
               segsel.Clear(i);

               // Find matching segment pair on other surface
               for(j = 1; j <= nseg; j++)
               {
                  int segpair_p1 = mesh.LineSegment(j)[1];
                  int segpair_p2 = mesh.LineSegment(j)[0];

                  // Find the segment pair on the neighbouring surface element
                  // Identified by: seg1[0] = seg_pair[1] and seg1[1] = seg_pair[0]
                  if(segsel.Test(j) && ((segpair_p1 == seg_p1) && (segpair_p2 == seg_p2)))
                  {
                     // clear bit to indicate that processing of this segment is done
                     segsel.Clear(j);

                     // Only worry about those surfaces which are not in the 
                     // boundary layer list
                     if(!surfid.Contains(mesh.LineSegment(j).si))
                     {
		        int pnt_commelem = 0;
			int pnum_commelem = 0;
                        Array<int> pnt1_elems;
                        Array<int> pnt2_elems;
                       
                            
                        meshtopo.GetVertexSurfaceElements(segpair_p1,pnt1_elems);
                        meshtopo.GetVertexSurfaceElements(segpair_p2,pnt2_elems);
                        for(int k = 1; k <= pnt1_elems.Size(); k++)
                        {
                           Element2d pnt1_sel = mesh.SurfaceElement(pnt1_elems.Elem(k));
                           for(int l = 1; l <= pnt2_elems.Size(); l++)
                           {
                              Element2d pnt2_sel = mesh.SurfaceElement(pnt2_elems.Elem(l));
                              if((pnt1_sel.GetIndex() == mesh.LineSegment(j).si) 
                                 && (pnt2_sel.GetIndex() == mesh.LineSegment(j).si)
                                 && (pnt1_elems.Elem(k) == pnt2_elems.Elem(l)))
                              {
                                 pnt_commelem = pnt1_elems.Elem(k);
                              }
                           }
                        }

                        for(int k = 1; k <= mesh.SurfaceElement(pnt_commelem).GetNP(); k++)
                        {
                           if((mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p1)
                              && (mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p2))
                           {
                              pnum_commelem = mesh.SurfaceElement(pnt_commelem).PNum(k);
                           }
                        }

                        Vec3d surfelem_vect, surfelem_vect1;
                        
                        Element2d & commsel = mesh.SurfaceElement(pnt_commelem);

                        dbg << "NP= " << commsel.GetNP() << " : ";

                        for(int k = 1; k <= commsel.GetNP(); k++)
                        {
                           GetSurfaceNormal(mesh,commsel,k,surfelem_vect1);
                           surfelem_vect += surfelem_vect1;
                        }

                        surfelem_vect.Normalize();

                        double surfangle = Angle(growthvectors.Elem(segpair_p1),surfelem_vect);

                        dbg << "V1= " << surfelem_vect1 
                            << " : V2= " << surfelem_vect1
                            << " : V= " << surfelem_vect
                            << " : GV= " << growthvectors.Elem(segpair_p1)
                            << " : Angle= " << surfangle * 180 / 3.141592;

                  
                        // remap the segments to the new points
                        mesh.LineSegment(i)[0] = mapto.Get(seg_p1);
                        mesh.LineSegment(i)[1] = mapto.Get(seg_p2);
                        mesh.LineSegment(j)[1] = mapto.Get(seg_p1);
                        mesh.LineSegment(j)[0] = mapto.Get(seg_p2);

                        if((surfangle < (90 + angleThreshold) * 3.141592 / 180.0)
                           && (surfangle > (90 - angleThreshold) * 3.141592 / 180.0))
                        {
                           dbg << " : quad\n";
                           // Since the surface is lower than the threshold, change the effective 
                           // prism growth vector to match with the surface vector, so that 
                           // the Quad which is created lies on the original surface
                           //growthvectors.Elem(segpair_p1) = surfelem_vect;

                           // Add a quad element to account for the prism volume
                           // element which is going to be added 
                           Element2d sel(QUAD);
                           sel.PNum(4) = mapto.Get(seg_p1);
                           sel.PNum(3) = mapto.Get(seg_p2);
                           sel.PNum(2) = segpair_p2;
                           sel.PNum(1) = segpair_p1;
                           sel.SetIndex(mesh.LineSegment(j).si);
                           mesh.AddSurfaceElement(sel);
                           numquads++;
                        }
                        else
                        {
                           dbg << "\n";
                           for (int k = 1; k <= pnt1_elems.Size(); k++)
                           {
                              Element2d & pnt_sel = mesh.SurfaceElement(pnt1_elems.Elem(k));
                              if(pnt_sel.GetIndex() == mesh.LineSegment(j).si)
                              {
                                 for(int l = 1; l <= pnt_sel.GetNP(); l++)
                                 {
                                    if(pnt_sel.PNum(l) == segpair_p1)
                                    {
                                       pnt_sel.PNum(l) = mapto.Get(seg_p1);
                                    }
                                    else if(pnt_sel.PNum(l) == segpair_p2)
                                    {
                                       pnt_sel.PNum(l) = mapto.Get(seg_p2);
                                    }
                                 }
                              }
                           }

                           for (int k = 1; k <= pnt2_elems.Size(); k++)
                           {
                              Element2d & pnt_sel = mesh.SurfaceElement(pnt2_elems.Elem(k));
                              if(pnt_sel.GetIndex() == mesh.LineSegment(j).si)
                              {
                                 for(int l = 1; l <= pnt_sel.GetNP(); l++)
                                 {
                                    if(pnt_sel.PNum(l) == segpair_p1)
                                    {
                                       pnt_sel.PNum(l) = mapto.Get(seg_p1);
                                    }
                                    else if(pnt_sel.PNum(l) == segpair_p2)
                                    {
                                       pnt_sel.PNum(l) = mapto.Get(seg_p2);
                                    }
                                 }
                              }
                           }
                        }
                     }
                     else
                     {
                        // If the code comes here, it indicates that we are at 
                        // a line segment pair which is at the intersection 
                        // of two surfaces, both of which have to grow boundary 
                        // layers.... here too, remapping the segments to the 
                        // new points is required
                        mesh.LineSegment(i)[0] = mapto.Get(seg_p1);
                        mesh.LineSegment(i)[1] = mapto.Get(seg_p2);
                        mesh.LineSegment(j)[1] = mapto.Get(seg_p1);
                        mesh.LineSegment(j)[0] = mapto.Get(seg_p2);
                     }
                  }
               }
            }
         }

         // Add prismatic cells at the boundaries
         cout << "Generating prism boundary layer volume elements...." << endl;

         for (i = 1; i <= nse; i++)
         {
            Element2d & sel = mesh.SurfaceElement(i);
            if(surfid.Contains(sel.GetIndex()))
            {
               Element el(PRISM);
               for (j = 1; j <= sel.GetNP(); j++)
               {
                  // Check (Doublecheck) if the corresponding point has a 
                  // copy available for remapping
                  if (mapto.Get(sel.PNum(j)))
                  {
                     // Define the points of the newly added Prism cell
                     el.PNum(j+3) = mapto.Get(sel.PNum(j));
                     el.PNum(j) = sel.PNum(j);
                  }
               }

               el.SetIndex(1);
               el.Invert();
               mesh.AddVolumeElement(el);
               numprisms++;
            }
         }

         // Finally switch the point indices of the surface elements 
         // to the newly added ones
         cout << "Transferring boundary layer surface elements to new vertex references...." << endl;

         for (i = 1; i <= nse; i++)
         {
            Element2d & sel = mesh.SurfaceElement(i);
            if(surfid.Contains(sel.GetIndex()))
            {
               for (j = 1; j <= sel.GetNP(); j++)
               {
                  // Check (Doublecheck) if the corresponding point has a 
                  // copy available for remapping
                  if (mapto.Get(sel.PNum(j)))
                  {
                     // Map the surface elements to the new points
                     sel.PNum(j) = mapto.Get(sel.PNum(j));
                  }
               }
            }
         }

         // Lock all the prism points so that the rest of the mesh can be 
         // optimised without invalidating the entire mesh
         for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++)
         {
           if(bndnodes.Test(i)) mesh.AddLockedPoint(pi);
         }

         // Now, actually pull back the old surface points to create 
         // the actual boundary layers
         cout << "Moving and optimising boundary layer points...." << endl;
         
         for (i = 1; i <= np; i++)
         {
            Array<ElementIndex> vertelems;

            if(bndnodes.Test(i))
            {
               MeshPoint pointtomove;

               pointtomove = mesh.Point(i);

               if(layer == prismlayers)
               {
                  mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i));

                  meshtopo.GetVertexElements(i,vertelems);

                  for(j = 1; j <= vertelems.Size(); j++)
                  {
		    // double sfact = 0.9;
                     Element volel = mesh.VolumeElement(vertelems.Elem(j));
                     if(((volel.GetType() == TET) || (volel.GetType() == TET10)) && (!volel.IsDeleted()))
                     {
                        //while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0))
                        //{
                        //   mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i)));
                        //   mesh.ImproveMesh();

                        //   // Try to move the point back by one step but 
                        //   // if the volume drops to below zero, double back
                        //   mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i)));
                        //   if(volel.Volume(mesh.Points()) <= 0.0)
                        //   {
                        //      mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i)));
                        //   }
                        //   sfact -= 0.1;
                        //}
                        volel.Delete();
                     }
                  }

                  mesh.Compress();
               }
               else
               {
                  mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i));
               }
            }
         }
      }

      // Optimise the tet part of the volume mesh after all the modifications 
      // to the system are completed
      //OptimizeVolume(mparam,mesh);

      cout << "New NP: " << mesh.GetNP() << endl;
      cout << "Num of Quads: " << numquads << endl;
      cout << "Num of Prisms: " << numprisms << endl;
      cout << "Boundary Layer Generation....Done!" << endl;

      dbg.close();
   }