A Simple Boundary Generator

P.-A. Chevalier, december 1999

This Notebook makes it possible to create the geometry of a boundary, and to save the corresponding data directly in a file in the special EasyMesh format. The filename can be defined by user, but its extension must be "*.d"  for compatibility with EasyMesh.

Instructions and example:

Suppose you want to use the program "EasyMesh" to generate a mesh on a particular given 2D domain, for example in a FEM problem. The information Easymesh needs the know is the exact description of the boundary of the domain, in a specially structured datafile. This program help you to create the boundary and the corresponding datafile, under the following assumptions:

1) the domain is simply connected and not too much complicated
2) the boundary consists of a set of closed smooth curves (smoothness can be relaxed in special cases)
3) all what you do must be coherent !

To achieve your work, you have to do the following steps:

1) First, give a name for the outputfile and a short header which will appear as a comment at the beginning of 
    the file.
    The extension of the filename must be ".d". 
    For example:
		filename = "test6.d" ;
		header = "test6.d";
		
2) Secondly, you have to assign the variable  npieces  the total number of separated closed curves which
    compose the complete boundary:
 		npieces = 2; 
 	
 3) For each closed curve (that is: for each k = 1 to npieces), you define the 4 following variables: 
 
 		pts[k]  	: contains the list of xy-coordinates of the successive points which compose the kth
 				 closed curve, in a logical order ;
 		                   Attention: the curve must be closed, but the end point (= first point) must be given 
 		                   only once in the list !
 		                   The points have to be numbered anticlockwise for an external boundary of the domain
 		                   and clockwise for an internal boundary (for example: a hole).

		conditions[k] : for each pair of successive points in the curve:  give 1 for a Dirichlet condition or 
				2 for a Neuman condition. The length of the list must be the same that for pts[k]. 
		
		raffinment[k]: give here a number corresponding to the raffinment of the mesh you want in the 
				neighborhood of the point (see EasyMesh for more informations).
		
		marker[1]: give here any special marker for the corresponding piece of curve.

	Example: we construct here the boundary of a simple rectangular domain with a circular hole:
		
		pts[1] =  {{0, 0}, {2, 0}, {2, 1}, {0, 1}} ; 
		conditions[1]  =  {2, 1, 2, 1} ; 
		\(raffinment[1]\  = \ 0.05; 
marker[1]\  = \ 1\ ; \)

		nphi = 10 ;
		dphi = 2 Pi/nphi ;
		pts[2]= Table[{1 + 0.3 Cos[-dphi k], 0.5 + 0.3 Sin[-dphi k]}, {k,0,nphi-1}] ;
		conditions[2] = Table[2, {k,0,nphi-1}] ;
		raffinment[2] = 0.05;
		marker[2] = 2 ;


4) Then, you only have to execute the three following instructions:

	-    assembleboundary  generates a list  bpoints and bndry which contain the informations of the
				 boundary ;
	-    showboundary[bpoints, bndry]  shows you a graphic of the boundary you have defined ;
	-    createfile[bpoints, bndry, filename, header] creates the outputfile for EasyMesh.
	
	
Thats All. Have a nice Work !

Initializations

Off[General::spell1]

\(createPointsList[pts_List, raff_, marker_]\  := \ \ 
	\ \ 
      Module[{length, npts}, 
		\ \ length = Length[pts]\ ; 
	\ \ \ \ 
        npts\  = 
          Table[{\(pPointer++\), pts[\([k]\)], raff, marker}, 
            \ {k, 1, length}]\ ; 
		Return[npts]]\)

\(createSegmentsList[newpts_List, bcond_List]\  := 
	\ \ 
      Module[{length, sgts}, 
		\ length\  = \ Length[newpts]\ ; 
		\ 
        sgts\  = \ 
          Table[{{newpts[\([k, 1]\)], newpts[\([k + 1, 1]\)]}, 
              bcond[\([k]\)]}, {k, 1, length - 1}]\ ; 
\ \ \ \ \ \ 
        sgts\  = \ 
          Append[sgts, 
            \ {{newpts[\([length, 1]\)], newpts[\([1, 1]\)]}, 
              bcond[\([length]\)]}]\ ; 
	\ Return[sgts]\ 
		]\)

\(\(createfile[bpoints_List, bndry_List, filename_String, header_String]
        \  := \ 
	
      Module[{npoints, nsegments, real2string, int2string, n, l1, str1, k, 
          outstream}, 
npoints\  = \ \ Length[bpoints]\ ; 

        nsegments\  = \ \ Length[bndry]\ ; 
l1\  = \ StringLength[header]\ ; 
        
str1\  = \ ""\ ; 

        Do[str1\  = \ StringJoin[str1, "#"], {k, 1, l1 + 4}]\ ; 

        str1\  = \ StringJoin[str1, "
"]\ ; 		

        real2string[n_]\  := \ ToString[PaddedForm[n, {4, 2}]]\ ; 

        int2string[n_]\  := \ ToString[PaddedForm[n, 2]]\ ; 

        outstream = OpenWrite[filename]; 
WriteString[outstream, str1]\ ; 

        WriteString[outstream, "# ", header, " #
"]\ ; 

        WriteString[outstream, str1, "
"]\ ; 

        WriteString[outstream, "# ======== #"\ , "
"]\ ; 

        WriteString[outstream, "#| "<>"POINTS |#
"\ ]\ ; 

        WriteString[outstream, "# ======== #

"]\ ; 

        WriteString[outstream, int2string[npoints], 
          "  # Number of points #

"]\ ; 

        WriteString[outstream, "# Nodes which define the boundary #
"]
          \ ; 
Do[
	
          WriteString[outstream, 
		int2string[bpoints[\([k, 1]\)]\ ], 
            ": "\ , 
	\ \ real2string[bpoints[\([k, 2, 1]\)]\ ], \ 
            " ", 	\ \ 
		real2string[bpoints[\([k, 2, 2]\)]\ ], \ 
            " ", \ 
	\ real2string[bpoints[\([k, 3]\)]], \ " ", 

            \ \ \ \ int2string[bpoints[\([k, 4]\)]], "
"
	], 
          
{k, 1, Length[bndry]}
]\ ; 

        WriteString[outstream, "
# ========== #"\ , "
"]\ ; 

        WriteString[outstream, "#| "<>"SEGMENTS |#
"\ ]\ ; 

        WriteString[outstream, "# ========== #

"]\ ; 

        WriteString[outstream, 
	\ \ \ \ ToString[nsegments], 
          "  # Number of segments #

"]\ ; 

        WriteString[outstream, "# Boundary segments #
"]\ ; 

        Do[
	WriteString[outstream, int2string[k - 1], ": "\ , 
	\ \ 
            int2string[bndry[\([k, 1, 1]\)]\ ], \ " ", \ 
	\ \ 
            int2string[bndry[\([k, 1, 2]\)]\ ]\ , " ", 
\ \ \ \ 
            int2string[bndry[\([k, 2]\)]], "
"], 
          
{k, 1, Length[bndry]}
]\ ; 

        Print["The data file '", filename, 
          "' has been created successfully."]\ ; 
Close[outstream]\ ; 
]
        	\)\)

\(assembleboundary\  := \ 
      Module[
		\ \ {pointsList, bpiece, k}, 
		pPointer\  = \ 0\ ; 

        Do[
	\ \ \ \ 
          pointsList[k] = 
            createPointsList[pts[k], raffinment[k], marker[k]]\ ; 

          \ \ \ \ \ \ 
          bpiece[k]\  = createSegmentsList[pointsList[k], conditions[k]]\ , 
          
{k, 1, npieces}]\ \ ; 

        bpoints\  = \ 
          Flatten[Join[Table[pointsList[k], {k, 1, npieces}]], 1]\ ; 

        bndry\  = \ Flatten[Join[Table[bpiece[k], {k, 1, npieces}]\ ], 1]\ ; 
        
		Print[
          "List of points 'bpoints' has been successfully created."]\ ; 
        Print["List of segments 'bndry' has been successfully created."]
          \ ; 
]\)

\(showboundary[bpoints_List, bndry_List]\  := \ 
      Module[
		\ \ \ {sgmntsList, k, textsList}, 
	
        sgmntsList\  = \ 
	\ 
          Table[
		\ 
            Line[{\ bpoints[\([bndry[\([k, 1, 1]\)] + 1, 2]\)], 

                				\ \ \ \ \ \ \ \ \ \ \ 
                bpoints[\([bndry[\([k, 1, 2]\)] + 1, 2]\)]}], 
            \ {k, 1, Length[bndry]}]\ ; 

        textsList\  = \ 
	\ \ 
          Table[Text[bpoints[\([k, 1]\)], bpoints[\([k, 2]\)]\ ], 
            \ \ \ \ \ \ \ \ \ \ \ \ \ 
			{k, 1, Length[bpoints]}]\ ; 

        Show[Graphics[{
		sgmntsList, 
		textsList\ 
		}], 

          AspectRatio -> Automatic]]\)

Some inputs:

Please give the name of outputfile for EasyMesh and a short header (the header will be wroten as a comment at the beginning of the datafile):

\(filename\  = \ "test.d"\ ; 
header\  = \ "test.d"; \)

Please give the exact number of the closed curves  which compose the complete boundary:

npieces  =  2;

Construction of the boundary

You have to define here the two closed curves which compose the boundary of your domain:

First part of boundary (a rectangle):

pts[1] =  {{0, 0}, {2, 0}, {2, 1}, {0, 1}} ;

conditions[1]  =  {2, 1, 2, 1} ;

\(raffinment[1]\  = \ 0.05; 
marker[1]\  = \ 1\ ; \)

2nd part of boundary

\(nphi\  = \ 20\ ; 
dphi\  = \ 2\ Pi/nphi\ ; \)

pts[2] =  
      Table[{1  +  0.3  Cos[-dphi k],  
          0.5  +  0.3 Sin[-dphi k] },  {k, 0, nphi - 1}] ;

conditions[2]  =  Table[2,  {k, 0, nphi - 1}] ;

\(raffinment[2]\  = \ 0.04; 
marker[2]\  = \ 2\ ; \)

Assembling pieces of boundary

assembleboundary

Graphic of actual boundary

showboundary[bpoints, bndry]

Generation of the datafile

createfile[bpoints, bndry, filename, header]