├── SU2_PER
├── COMPILE
├── README
└── su2_periodic.f90
├── Matlab
├── angle2dcm.m
├── example_MergeMeshes.m
├── plotElem.m
├── plotFace.m
├── getElemTypeInfo.m
├── plotMarkers.m
├── MergeSU2.m
├── WriteSU2.m
└── ReadSU2.m
├── Python
├── Expandp3d.py
├── p3d2su2_OGrid.py
├── p3d2su2_CGrid.py
├── p3d2su2_3D.py
├── 3DChannel.py
└── 2DChannel.py
├── Fortran
├── dpl2su2_2D.f
├── gmsh2su2_3D.f90
└── gmsh2su2_2D.f90
└── COPYING
/SU2_PER/COMPILE:
--------------------------------------------------------------------------------
1 | gfortran -O3 -o SU2_PER su2_periodic.f90
2 |
--------------------------------------------------------------------------------
/Matlab/angle2dcm.m:
--------------------------------------------------------------------------------
1 | function [dcm] = angle2dcm(r,seq)
2 | % dcm = angle2dcm(r1,r2,r3,seq)
3 | % builds euler angle rotation matrix
4 | %
5 | % r = [r1 r2 r3]
6 | % seq = 'ZYX' (default)
7 | % 'ZXZ'
8 | % dcm = direction cosine matrix
9 |
10 | if nargin == 1
11 | seq = 'ZYX';
12 | end
13 |
14 | switch seq
15 | case 'ZYX'
16 | dcm = Tx(r(3))*Ty(r(2))*Tz(r(1));
17 | case 'ZXZ'
18 | dcm = Tz(r(3))*Tx(r(2))*Tz(r(1));
19 | end
20 |
21 | function A = Tx(a)
22 | A = [1 0 0;0 cosd(a) sind(a);0 -sind(a) cosd(a)];
23 |
24 | function A = Ty(a)
25 | A = [cosd(a) 0 -sind(a);0 1 0;sind(a) 0 cosd(a)];
26 |
27 | function A = Tz(a)
28 | A = [cosd(a) sind(a) 0;-sind(a) cosd(a) 0;0 0 1];
--------------------------------------------------------------------------------
/Matlab/example_MergeMeshes.m:
--------------------------------------------------------------------------------
1 | % MergeMeshes.m
2 | % merges two SU2 meshes
3 | % beware of large meshes!!
4 | %
5 |
6 | %% SETUP
7 |
8 | meshname1 = 'mesh_bipara_1.su2';
9 | meshname2 = 'mesh_bipara_2.su2';
10 | meshnameout = 'mesh_bipara_merged.su2';
11 |
12 |
13 | %% READ
14 |
15 | mesh1 = ReadSU2(meshname1);
16 | mesh2 = ReadSU2(meshname2);
17 |
18 | figure(1); clf; hold on;
19 | plotMarkers(mesh1,{mesh1.mark(:).tag},'b-');
20 | plotMarkers(mesh2,{mesh2.mark(:).tag},'r-');
21 |
22 |
23 | %% MERGE
24 |
25 | meshout = MergeSU2(mesh1,mesh2);
26 |
27 | figure(2); clf; hold on;
28 | plotMarkers(meshout,'k-');
29 |
30 |
31 | %% WRITE
32 |
33 | WriteSU2(meshout,'mesh_bipara_merged.su2');
34 |
35 |
36 | %% DONE
37 |
38 |
39 |
--------------------------------------------------------------------------------
/SU2_PER/README:
--------------------------------------------------------------------------------
1 | The SU2_PER is a fortran serial executable that generates periodic mesh for SU2.
2 | The code was developed by Antonio Ghidoni from the University of Brescia.
3 |
4 | TO COMPILE
5 | run the compiling script "./COMPILE" available in the folder.
6 |
7 |
8 | TO RUN
9 | run the program followed by a "<" sign and the SU2 config file "./SU2_PER < su2config.cfg".
10 | The SU2_PER program uses the same config options of the SU2_MSH binary.
11 |
12 |
13 | LIMITATIONS
14 |
15 | 1) It can only be run in serial
16 | 2) To avoid that the program occupies too much memory SU2_PER is limited to mesh containing
17 | less than 1E+05 periodic nodes and less than 8E+06 nodes in total. However,
18 | if bigger meshes must be converted, this limit can be adjusted by modifying line 35 of
19 | the su2_periodic.f90 file.
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Matlab/plotElem.m:
--------------------------------------------------------------------------------
1 | function plotElem(poin,elem,plotstyle)
2 | % plotElem(poin,elem,plotstyle)
3 | % plots points of the element array
4 | %
5 | % poin: 3d point locations
6 | % elem: element connectivity
7 | % plotstyle: element plot style
8 | % i.e. 'b' plots a blue patch
9 | % 'b-' plots a blue line
10 | %
11 |
12 | %% SETUP
13 |
14 | % element type plot list
15 | etype_list = [3 5 9]; % line, triangle, rectangle
16 |
17 |
18 | %% ELEMENTS
19 |
20 | for elem_type = etype_list
21 |
22 | % find element rows of this type
23 | i_plotelem = elem(:,1) == elem_type;
24 |
25 | if any(i_plotelem)
26 |
27 | % pull how many points
28 | elem_leng = getElemTypeInfo(elem_type);
29 | elem_range = 2:(1+elem_leng);
30 |
31 | % pull plotable element array
32 | this_elem = elem(i_plotelem,elem_range);
33 | this_elem = this_elem + 1;
34 |
35 | % plot elements
36 | plotFace(this_elem,poin,plotstyle)
37 |
38 | end
39 |
40 | end
41 |
42 |
43 | %% DONE
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Matlab/plotFace.m:
--------------------------------------------------------------------------------
1 | function plotFace(varargin)
2 | % plotFace(FP,P,s)
3 | % plotFace(F,FP,P,s)
4 | %
5 | % P: 3d point coordinates
6 | % FP: face-to-point connectivity (aka elem)
7 | % F: face indeces to plot (within FP), optional
8 | % s: plot style
9 | % example: 'b' plots a blue patch
10 | % 'b-' plots a blue line
11 | %
12 |
13 | %% SETUP
14 |
15 | switch nargin
16 | case 3
17 | s = varargin{3};
18 | P = varargin{2};
19 | FP = varargin{1};
20 | F = (1:size(FP,1))';
21 | case 4
22 | s = varargin{4};
23 | P = varargin{3};
24 | FP = varargin{2};
25 | F = varargin{1};
26 | end
27 |
28 | [nF,nFP] = size(FP);
29 |
30 |
31 | %% COORDS
32 |
33 | X = zeros(nF,nFP+1);
34 | Y = zeros(nF,nFP+1);
35 | Z = zeros(nF,nFP+1);
36 |
37 | lFP = [1:nFP 1];
38 | for iFP = 1:nFP+1;
39 | X(:,iFP) = P(FP(F,lFP(iFP)),1);
40 | Y(:,iFP) = P(FP(F,lFP(iFP)),2);
41 | Z(:,iFP) = P(FP(F,lFP(iFP)),3);
42 | end
43 |
44 |
45 | %% PLOT
46 |
47 | % plot style
48 | if length(s) == 1
49 | patch(X',Y',Z',s)
50 | else
51 | plot3(X',Y',Z',s,'LineWidth',1)
52 | end
53 |
54 |
55 | %% DONE
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Matlab/getElemTypeInfo.m:
--------------------------------------------------------------------------------
1 | function [elem_leng,elem_type] = getElemTypeInfo(elem_type)
2 | % get vtk element type data
3 | % input -
4 | % elem_type = name or vtk type number
5 | % output -
6 | % elem_leng = number of nodes in element
7 | % elem_type = vtk type number
8 |
9 |
10 | if isnumeric(elem_type)
11 | switch elem_type
12 | case 3
13 | elem_leng = 2;
14 | case 5
15 | elem_leng = 3;
16 | case 9
17 | elem_leng = 4;
18 | case 10
19 | elem_leng = 4;
20 | case 12
21 | elem_leng = 8;
22 | case 13
23 | elem_leng = 6;
24 | case 14
25 | elem_leng = 5;
26 | end
27 |
28 | else
29 | switch elem_type
30 | case 'line'
31 | elem_type = 3;
32 | elem_leng = 2;
33 | case 'triangle'
34 | elem_type = 5;
35 | elem_leng = 3;
36 | case 'rectangle'
37 | elem_type = 9;
38 | elem_leng = 4;
39 | case 'tetrahedral'
40 | elem_type = 10;
41 | elem_leng = 4;
42 | case 'hexahedral'
43 | elem_type = 12;
44 | elem_leng = 8;
45 | case 'wedge'
46 | elem_type = 13;
47 | elem_leng = 6;
48 | case 'pyramid'
49 | elem_type = 14;
50 | elem_leng = 5;
51 | end
52 | end
--------------------------------------------------------------------------------
/Matlab/plotMarkers.m:
--------------------------------------------------------------------------------
1 | function plotMarkers(varargin)
2 | % plotMarkers(meshdata,plotstyle)
3 | % plotMarkers(meshdata,marklist,plotstyle)
4 | %
5 | % plots markers from the meshdata
6 | %
7 | % meshdata: mesh data struct
8 | % marklist: cell array of marker names, optional
9 | % plotstyle: element plot style
10 | % i.e.: 'b' plots a blue patch
11 | % 'b-' plots a blue line
12 | %
13 |
14 | %% SETUP
15 |
16 | switch nargin
17 | case 2
18 | meshdata = varargin{1};
19 | marklist = {meshdata.mark(:).tag};
20 | plotstyle = varargin{2};
21 | case 3
22 | meshdata = varargin{1};
23 | marklist = varargin{2};
24 | plotstyle = varargin{3};
25 | end
26 |
27 | % number of markers
28 | nmark = meshdata.nmark;
29 |
30 | % dimension
31 | dim = meshdata.dim;
32 |
33 | % point array
34 | poin = meshdata.poin(:,1:dim);
35 | if dim == 2
36 | poin(:,3) = 0;
37 | end
38 |
39 |
40 | %% MARKERS
41 |
42 | % plot nodes for each marker
43 | for imark = 1:nmark
44 |
45 | % pull marker tag
46 | this_tag = meshdata.mark(imark).tag;
47 |
48 | % check if this tag exists
49 | if any(strcmp(this_tag,marklist))
50 |
51 | % pull elements and plot
52 | this_elem = meshdata.mark(imark).elem;
53 | plotElem(poin,this_elem,plotstyle);
54 |
55 | end
56 |
57 | end
58 |
59 |
60 | %% DONE
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Matlab/MergeSU2.m:
--------------------------------------------------------------------------------
1 | function meshout = MergeSU2(mesh1,mesh2)
2 | % meshout = MergeSU2(mesh1,mesh2)
3 | % concatenates mesh2 information below mesh1
4 |
5 | %% SETUP
6 |
7 | assert( mesh1.dim == mesh2.dim , 'mesh dimension mismatch' );
8 |
9 | meshout = mesh1;
10 |
11 |
12 | %% POINTS
13 |
14 | mesh2.poin(:,end) = mesh2.poin(:,end) + mesh1.npoin;
15 |
16 | meshout.poin = [ meshout.poin ; mesh2.poin ];
17 | meshout.npoin = size( meshout.poin, 1 );
18 |
19 |
20 | %% ELEMENTS
21 |
22 | for ielem = 1:mesh2.nelem
23 | elem_leng = getElemTypeInfo( mesh2.elem(ielem,1) );
24 | elem_range = 2:(1+elem_leng);
25 | mesh2.elem( ielem, elem_range ) = mesh1.npoin + mesh2.elem( ielem, elem_range );
26 | mesh2.elem( ielem, elem_leng+2 ) = mesh1.nelem + mesh2.elem( ielem, elem_leng+2 );
27 | end
28 |
29 | meshout.elem = [ meshout.elem ; mesh2.elem ];
30 | meshout.nelem = size( meshout.elem, 1 );
31 |
32 |
33 | %% MARKERS
34 |
35 | mesh1_marklist = { mesh1.mark(:).tag };
36 |
37 | for imark = 1:mesh2.nmark;
38 |
39 | % Elements
40 | for ielem = 1:mesh2.mark(imark).nelem
41 | elem_leng = getElemTypeInfo( mesh2.mark(imark).elem(ielem,1) );
42 | elem_range = 2:(1+elem_leng);
43 | mesh2.mark(imark).elem( ielem, elem_range ) = mesh1.npoin + mesh2.mark(imark).elem( ielem, elem_range );
44 | end
45 |
46 | jmark = find( strcmp( mesh2.mark(imark).tag, mesh1_marklist ) );
47 | njmark = length(jmark);
48 |
49 | % Existing Marker
50 | if njmark == 1
51 |
52 | meshout.mark(jmark).elem = [ meshout.mark(jmark).elem ; mesh2.mark(imark).elem ];
53 | meshout.mark(jmark).nelem = size( meshout.mark(jmark).elem, 1 );
54 |
55 | % New Marker
56 | elseif njmark == 0
57 |
58 | jmark = length(meshout.mark)+1;
59 |
60 | meshout.mark(jmark).tag = mesh2.mark(imark).tag;
61 | meshout.mark(jmark).elem = mesh2.mark(imark).elem;
62 | meshout.mark(jmark).nelem = size( meshout.mark(jmark).elem, 1 );
63 |
64 | else
65 | error('duplicate markers?')
66 |
67 | end
68 |
69 | end
70 |
71 | meshout.nmark = length(meshout.mark);
72 |
73 |
74 | %% DONE
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Python/Expandp3d.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file Expandp3d.py
4 | # \brief Python script for converting from plot3D to SU2
5 | # \author _________
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 | import string
34 |
35 | parser=OptionParser()
36 | parser.add_option("-f", "--file", dest="filename", default="default.p3d",
37 | help="write mesh to FILE", metavar="FILE")
38 | (options, args)=parser.parse_args()
39 |
40 | # Read the input file
41 | p3d_File = open(options.filename,"r")
42 |
43 | # Read the body
44 | body = p3d_File.read().replace("\n"," ").replace("\t"," ").split()
45 |
46 | # Write the body
47 | filename = options.filename.rsplit( ".", 1 )[ 0 ] + ".Expp3d"
48 |
49 |
50 | Expp3d_File = open(filename,"w")
51 |
52 | for x in range(0, len(body)):
53 |
54 | if len(body[x].rsplit("*")) == 2:
55 | mult = int(body[x].rsplit("*")[0])
56 | for y in range(0, mult):
57 | Expp3d_File.write("%s " % body[x].rsplit("*")[1])
58 |
59 | else:
60 | Expp3d_File.write("%s " % body[x])
61 |
62 |
63 | Expp3d_File.close()
64 | p3d_File.close()
--------------------------------------------------------------------------------
/Matlab/WriteSU2.m:
--------------------------------------------------------------------------------
1 | function WriteSU2(meshout,meshname)
2 | % WriteSU2(meshout,meshname)
3 | % writes meshname.su2 from struct meshout
4 | % for some reason it will only write single precision
5 | %
6 | % meshout =
7 | % dim: mesh dimension
8 | % npoin: number of points
9 | % poin: point array [x y (z) ip]
10 | % nelem: number of elements
11 | % elem: element array [ type p1 p2 ... pn ielem ]
12 | % nmark: number of markers
13 | % mark: marker struct array
14 | % meshout.mark(imark) =
15 | % tag: marker tag
16 | % nelem: number of marker elements
17 | % elem: element array [ type p1 p2 ... pn ]
18 | %
19 | % note: element array is right-padded with zeros to
20 | % accomodate multiple element types. use getElemTypeInfo()
21 | % to get how many points are in an element.
22 | %
23 |
24 | %% Open File
25 |
26 | fprintf('Write %s \n',meshname);
27 | fid = fopen(meshname,'w');
28 |
29 |
30 | %% Dimension
31 |
32 | fprintf(fid,'%% \n%% Problem dimension \n%% \n');
33 | fprintf(fid,'NDIME= %i\n%',meshout.dim);
34 |
35 |
36 | %% Elements
37 |
38 | fprintf(fid,'%% \n%% Inner element connectivity \n%% \n');
39 | fprintf(fid,'NELEM= %i\n%',meshout.nelem);
40 | % fprintf(fid,'%-2i %5i %5i %5i %5i \n',data.elem');
41 | for i = 1:meshout.nelem
42 | this_elem = meshout.elem(i,:);
43 | elem_type = this_elem(1);
44 | elem_leng = getElemTypeInfo(elem_type);
45 | elem_range = 1:(2+elem_leng);
46 | printElement( fid, this_elem(elem_range) );
47 | end
48 |
49 |
50 | %% Nodes
51 |
52 | fprintf(fid,'%% \n%% Node coordinates \n%% \n');
53 | fprintf(fid,'NPOIN= %i\n%',meshout.npoin);
54 | if meshout.dim == 2
55 | fprintf(fid,'%#28.16g %#28.18g %i \n',meshout.poin');
56 | else
57 | fprintf(fid,'%#28.18g %#28.18g %#28.18g %i \n',meshout.poin');
58 | end
59 |
60 |
61 | %% Markers
62 |
63 | fprintf(fid,'%%\n%% Boundary elements \n%% \n');
64 | fprintf(fid,'NMARK= %i\n%',meshout.nmark);
65 |
66 | nM = meshout.nmark;
67 | for i = 1:nM
68 | fprintf(fid,'MARKER_TAG= %s\n',meshout.mark(i).tag);
69 | fprintf(fid,'MARKER_ELEMS= %i\n',meshout.mark(i).nelem);
70 | for j = 1:meshout.mark(i).nelem
71 | this_elem = meshout.mark(i).elem(j,:);
72 | elem_type = this_elem(1);
73 | elem_leng = getElemTypeInfo(elem_type);
74 | elem_range = 1:(1+elem_leng);
75 | printElement( fid, this_elem(elem_range) );
76 | end
77 | end
78 |
79 | fclose all;
80 |
81 |
82 | %% Helper Function
83 | function printElement(fid,elem)
84 | fprintf(fid,'%-2i ',elem(1));
85 | fprintf(fid,'%5i ',elem(2:end));
86 | fprintf(fid,'\n');
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Python/p3d2su2_OGrid.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file p3d2su2_OGrid.py
4 | # \brief Python script for converting O-Grids from plot3D to SU2
5 | # \author F. Palacios
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 | import string
34 |
35 | parser=OptionParser()
36 | parser.add_option("-f", "--file", dest="filename", default="default.p2d",
37 | help="write mesh to FILE", metavar="FILE")
38 | (options, args)=parser.parse_args()
39 |
40 | # Read the input file
41 | p2d_File = open(options.filename,"r")
42 |
43 | # Read the header
44 | header = p2d_File.readline()
45 | header = p2d_File.readline().replace("\n"," ").replace("\t"," ").split()
46 | nNode = int(header[0].strip())
47 | mNode = int(header[1].strip())
48 |
49 | # Read the body
50 | body = p2d_File.read().replace("\n"," ").replace("\t"," ").split()
51 |
52 | p2d_File.close()
53 |
54 | # Write the .su2 file
55 | filename = options.filename.rsplit( ".", 1 )[ 0 ] + ".su2"
56 | su2_File = open(filename,"w")
57 |
58 | # Write the header
59 | su2_File.write( "NDIME=2\n" )
60 | su2_File.write( "NELEM=%s\n" % ((mNode-1)*(nNode-1)))
61 |
62 | # Write the connectivity
63 | iElem = 0
64 | for jNode in range(mNode-1):
65 | for iNode in range(nNode-1):
66 |
67 | Point0 = iNode + (jNode*(nNode-1))
68 | Point1 = (iNode+1) + (jNode*(nNode-1))
69 | Point2 = (iNode+1) + (jNode+1)*(nNode-1)
70 | Point3 = iNode + (jNode+1)*(nNode-1)
71 |
72 | if iNode == nNode-2:
73 | Point1 = jNode*(nNode-1)
74 | Point2 = (jNode+1)*(nNode-1)
75 |
76 | su2_File.write( "9 \t %s \t %s \t %s \t %s \t %s\n" % (Point0, Point1, Point2, Point3, iElem) )
77 | iElem = iElem + 1
78 |
79 | # Write the coordinates
80 | nPoint = (nNode)*(mNode)
81 | su2_File.write( "NPOIN=%s\n" % ((nNode-1)*(mNode)))
82 | iPoint = 0
83 | for jNode in range(mNode):
84 | for iNode in range(nNode):
85 | XCoord = body[jNode*nNode + iNode]
86 | YCoord = body[(nNode*mNode) + jNode*nNode + iNode]
87 |
88 | if iNode != (nNode-1) :
89 | su2_File.write( "%s \t %s \t %s\n" % (XCoord, YCoord, iPoint) )
90 | iPoint = iPoint + 1
91 |
92 | # Write the boundaries
93 | su2_File.write( "NMARK=2\n" )
94 |
95 | su2_File.write( "MARKER_TAG= airfoil\n" )
96 | points = (nNode-1)
97 | FirstPoint = 1
98 | su2_File.write( "MARKER_ELEMS=%s\n" % points )
99 | for iNode in range(points-1):
100 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + iNode -1 , FirstPoint + iNode + 1 - 1) ) # minus 1 because C++ uses 0
101 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + points -1 -1, FirstPoint -1 ) ) # minus 1 because C++ uses 0
102 |
103 |
104 | su2_File.write( "MARKER_TAG= farfield\n" )
105 | points = (nNode-1)
106 | elems = points
107 | FirstPoint = 1+(nNode-1)*(mNode-1)
108 | su2_File.write( "MARKER_ELEMS=%s\n" % points )
109 | for iNode in range(points-1):
110 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + iNode -1 , FirstPoint + iNode + 1 - 1) ) # minus 1 because C++ uses 0
111 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + points -1 -1, FirstPoint -1 ) ) # minus 1 because C++ uses 0
112 |
113 | su2_File.close()
--------------------------------------------------------------------------------
/Matlab/ReadSU2.m:
--------------------------------------------------------------------------------
1 | function meshout = ReadSU2(meshname)
2 | % meshout = ReadSU2(meshname)
3 | % reads meshname.su2 into struct meshout
4 | %
5 | % meshout =
6 | % dim: mesh dimension
7 | % npoin: number of points
8 | % poin: point array [x y (z) ip]
9 | % nelem: number of elements
10 | % elem: element array [ type p1 p2 ... pn ielem ]
11 | % nmark: number of markers
12 | % mark: marker struct array
13 | % meshout.mark(imark) =
14 | % tag: marker tag
15 | % nelem: number of marker elements
16 | % elem: element array [ type p1 p2 ... pn ]
17 | %
18 | % note: element array is right-padded with zeros to
19 | % accomodate multiple element types. use getElemTypeInfo()
20 | % to get how many points are in an element.
21 | %
22 |
23 | %% Open File
24 |
25 | fprintf('Read %s \n',meshname);
26 | fid = fopen(meshname,'r');
27 |
28 | % make sure file opened
29 | if fid == -1
30 | error('file open error')
31 | end
32 |
33 | %% Setup
34 |
35 | % initialize data
36 | meshout.dim = 0;
37 | meshout.npoin = 0;
38 | meshout.poin = [0];
39 | meshout.nelem = 0;
40 | meshout.elem = [0];
41 | meshout.nmark = 0;
42 | meshout.mark(1).tag = '';
43 | meshout.mark(1).nelem = 0;
44 | meshout.mark(1).elem = [0];
45 |
46 | % marker index
47 | imarkr = 1;
48 |
49 |
50 | %% Read
51 |
52 | % scan file until end of file
53 | while ~feof(fid)
54 |
55 | % look for mesh keywords
56 | % read one line
57 | C = textscan(fid,'%s %s',1,'CommentStyle','%');
58 |
59 | % check for end of file
60 | if feof(fid)
61 | break
62 | end
63 |
64 | % tokenize line
65 | key = C{1}{1};
66 | val = C{2}{1};
67 |
68 | % check if val is a double or a string
69 | temp = str2double(val);
70 | if ~isnan(temp)
71 | val = temp;
72 | end
73 |
74 | % handle the keyword
75 | switch key
76 |
77 | % dimension number
78 | case 'NDIME='
79 | % save to data struct
80 | meshout.dim=val;
81 |
82 | % elements
83 | case 'NELEM='
84 | % save to data struct
85 | meshout.nelem = val;
86 |
87 | % read next lines for element data
88 | % builds a potentially oversized matrix
89 | E = textscan(fid, '%u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64', ...
90 | meshout.nelem, ...
91 | 'CollectOutput',true,'CommentStyle','%' );
92 | E = E{1};
93 |
94 | % save to data struct
95 | meshout.elem = E;
96 |
97 | % points
98 | case 'NPOIN='
99 | % save to data struct
100 | meshout.npoin = val;
101 |
102 | % read next lines for point data
103 | E = textscan(fid, '%f64 %f64 %f64 %f64 %f64', ...
104 | meshout.npoin , ...
105 | 'CollectOutput',true,'CommentStyle','%' );
106 | E = E{1};
107 |
108 | % save to data struct
109 | meshout.poin = E(:,1:(meshout.dim+1));
110 |
111 | % number of markers
112 | case 'NMARK='
113 | % save to data struct
114 | meshout.nmark = val;
115 |
116 | % a marker
117 | case 'MARKER_TAG='
118 | % save name to data.mark struct
119 | meshout.mark(imarkr).tag=val;
120 |
121 | % read next line to get marker nelems
122 | C = textscan(fid,'%s %s',1,'CommentStyle','%');
123 | % tokenize line
124 | key = C{1}{1};
125 | val = C{2}{1};
126 |
127 | if ~strcmp(key,'MARKER_ELEMS=')
128 | error('marker specification error')
129 | end
130 |
131 | % save number of elements to data.mark struct
132 | meshout.mark(imarkr).nelem = str2double(val);
133 |
134 | % read next lines to get marker elements
135 | E = textscan(fid, '%u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64 %u64', ...
136 | meshout.mark(imarkr).nelem, ...
137 | 'CollectOutput',true,'CommentStyle','%' );
138 | E = E{1};
139 |
140 | % save elements to data.mark struct
141 | meshout.mark(imarkr).elem = E;
142 |
143 | % increment marker index
144 | imarkr = imarkr+1;
145 |
146 | end % switch key
147 |
148 |
149 |
150 | end % while read file line
151 |
152 |
153 | %% Done
154 |
155 | % close
156 | fclose(fid);
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/Python/p3d2su2_CGrid.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file p3d2su2_CGrid.py
4 | # \brief Python script for converting C-Grids from plot3D to SU2
5 | # \author F. Palacios
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 | import string
34 |
35 | parser=OptionParser()
36 | parser.add_option("-f", "--file", dest="filename", default="default.p2d",
37 | help="write mesh to FILE", metavar="FILE")
38 | (options, args)=parser.parse_args()
39 |
40 | # Read the input file
41 | p2d_File = open(options.filename,"r")
42 |
43 | # Read the header
44 | header = p2d_File.readline()
45 | header = p2d_File.readline().replace("\n"," ").replace("\t"," ").split()
46 | nNode = int(header[0].strip())
47 | mNode = int(header[1].strip())
48 |
49 | # Read the body
50 | body = p2d_File.read().replace("\n"," ").replace("\t"," ").split()
51 |
52 | p2d_File.close()
53 |
54 | # Write the .su2 file
55 | filename = options.filename.rsplit( ".", 1 )[ 0 ] + ".su2"
56 | su2_File = open(filename,"w")
57 |
58 | # Write the header
59 | su2_File.write( "NDIME=2\n" )
60 | su2_File.write( "NELEM=%s\n" % ((mNode-1)*(nNode-1)))
61 |
62 | #Extra points to remove to adjust the conectivity
63 | points_airfoil = (mNode-1)*2
64 | points_remove = ((nNode+1)-points_airfoil)/2
65 | FirstPoint = points_remove + points_airfoil - 1 # minus 1 because C++ uses 0
66 | LastPoint = FirstPoint + points_remove - 1
67 |
68 | # Write the connectivity
69 | iElem = 0
70 | for jNode in range(mNode-1):
71 | for iNode in range(nNode-1):
72 | Point0 = jNode*nNode + iNode
73 | Point1 = jNode*nNode + iNode + 1
74 | Point2 = (jNode+1)*nNode + (iNode+1)
75 | Point3 = (jNode+1)*nNode + iNode
76 |
77 | if Point0 >= FirstPoint and Point0 <= LastPoint :
78 | Point0 = nNode - Point0 - 1
79 | if Point0 > LastPoint :
80 | Point0 = Point0 - points_remove
81 |
82 |
83 | if Point1 >= FirstPoint and Point1 <= LastPoint :
84 | Point1 = nNode - Point1 - 1
85 | if Point1 > LastPoint :
86 | Point1 = Point1 - points_remove
87 |
88 | Point2 = Point2 - points_remove
89 |
90 | Point3 = Point3 - points_remove
91 |
92 | su2_File.write( "9 \t %s \t %s \t %s \t %s \t %s\n" % (Point0, Point1, Point2, Point3, iElem) )
93 | iElem = iElem + 1
94 |
95 | # Write the coordinates
96 | nPoint = (nNode)*(mNode)
97 | su2_File.write( "NPOIN=%s\n" % ((nNode)*(mNode) - points_remove))
98 | iPoint = 0
99 | for jNode in range(mNode):
100 | for iNode in range(nNode):
101 | XCoord = body[jNode*nNode + iNode]
102 | YCoord = body[(nNode*mNode) + jNode*nNode + iNode]
103 |
104 | if iPoint < FirstPoint or iPoint > LastPoint :
105 | su2_File.write( "%s \t %s \t %s\n" % (XCoord, YCoord, iPoint) )
106 |
107 | iPoint = iPoint + 1
108 |
109 | # Write the boundaries
110 | su2_File.write( "NMARK=2\n" )
111 |
112 | su2_File.write( "MARKER_TAG= airfoil\n" )
113 | points = (mNode-1)*2
114 | elems = points
115 | FirstPoint = ( (nNode+1)-points )/2
116 | su2_File.write( "MARKER_ELEMS=%s\n" % elems )
117 | for iNode in range(points-1):
118 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + iNode -1 , FirstPoint + iNode + 1 - 1) ) # minus 1 because C++ uses 0
119 |
120 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + points -1 -1, FirstPoint -1 ) ) # minus 1 because C++ uses 0
121 |
122 |
123 | su2_File.write( "MARKER_TAG= farfield\n" )
124 | TotalElem = (nNode-1) + (mNode-1) + (mNode-1)
125 | su2_File.write( "MARKER_ELEMS=%s\n" % TotalElem)
126 |
127 | points_airfoil = (mNode-1)*2
128 | elems = (nNode-1)
129 | FirstPoint = nNode*(points_airfoil/2) + 1 # minus 1 because C++ uses 0
130 | for iNode in range(elems):
131 | su2_File.write( "3 \t %s \t %s\n" % (FirstPoint + iNode - 1 - points_remove, FirstPoint + iNode + 1 - 1 - points_remove) )
132 |
133 | elems = (mNode-1)
134 | for jNode in range(elems):
135 | if jNode == 0 :
136 | su2_File.write( "3 \t 0 \t %s\n" % ((jNode*nNode + 1) + nNode - 1 - points_remove) )
137 | else :
138 | su2_File.write( "3 \t %s \t %s\n" % ((jNode*nNode + 1) - 1 - points_remove, (jNode*nNode + 1) + nNode - 1 - points_remove) )
139 |
140 | elems = (mNode-1)
141 | for jNode in range(elems):
142 | if jNode == 0 :
143 | su2_File.write( "3 \t 0 \t %s\n" % ( (jNode + 1)*nNode + nNode - 1 - points_remove) )
144 | else :
145 | su2_File.write( "3 \t %s \t %s\n" % (jNode*nNode + nNode - 1 - points_remove, (jNode + 1)*nNode + nNode - 1 - points_remove) )
146 |
147 |
148 | su2_File.close()
--------------------------------------------------------------------------------
/Python/p3d2su2_3D.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file p3d2su2_3D.py
4 | # \brief Python script for converting from plot3D to SU2
5 | # \author F. Palacios
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 | import string
34 |
35 | parser=OptionParser()
36 | parser.add_option("-f", "--file", dest="filename", default="default.p3d",
37 | help="write mesh to FILE", metavar="FILE")
38 | (options, args)=parser.parse_args()
39 |
40 | # Read the input file
41 | p3d_File = open(options.filename,"r")
42 |
43 | # Read the header
44 | header = p3d_File.readline().replace("\n"," ").replace("\t"," ").split()
45 | nNode = int(header[0].strip())
46 | mNode = int(header[1].strip())
47 | lNode = int(header[2].strip())
48 |
49 | # Read the body
50 | body = p3d_File.read().replace("\n"," ").replace("\t"," ").split()
51 |
52 | p3d_File.close()
53 |
54 | # Write the .su2 file
55 | filename = options.filename.rsplit( ".", 1 )[ 0 ] + ".su2"
56 | su2_File = open(filename,"w")
57 |
58 | # Write the header
59 | su2_File.write( "NDIME=3\n" )
60 | su2_File.write( "NELEM=%s\n" % ((lNode-1)*(nNode-1)*(mNode-1)))
61 |
62 | # Write the connectivity
63 | iElem = 0
64 | for kNode in range(lNode-1):
65 | for jNode in range(mNode-1):
66 | for iNode in range(nNode-1):
67 | Point0 = kNode*mNode*nNode + jNode*nNode + iNode
68 | Point1 = kNode*mNode*nNode + jNode*nNode + iNode + 1
69 | Point2 = kNode*mNode*nNode + (jNode+1)*nNode + (iNode+1)
70 | Point3 = kNode*mNode*nNode + (jNode+1)*nNode + iNode
71 | Point4 = (kNode+1)*mNode*nNode + jNode*nNode + iNode
72 | Point5 = (kNode+1)*mNode*nNode + jNode*nNode + iNode + 1
73 | Point6 = (kNode+1)*mNode*nNode + (jNode + 1)*nNode + (iNode + 1)
74 | Point7 = (kNode+1)*mNode*nNode + (jNode + 1)*nNode + iNode
75 | su2_File.write( "12 \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s\n" % (Point0, Point1, Point2, Point3, Point4, Point5, Point6, Point7, iElem) )
76 | iElem = iElem + 1
77 |
78 | # Write the coordinates
79 | nPoint = (nNode)*(mNode)*(lNode)
80 | su2_File.write( "NPOIN=%s\n" % ((nNode)*(mNode)*(lNode)))
81 | iPoint = 0
82 | for kNode in range(lNode):
83 | for jNode in range(mNode):
84 | for iNode in range(nNode):
85 | XCoord = body[kNode*(mNode*nNode) + jNode*nNode + iNode]
86 | YCoord = body[(nNode*mNode*lNode) + kNode*(mNode*nNode) + jNode*nNode + iNode]
87 | ZCoord = body[2*(nNode*mNode*lNode) + kNode*(mNode*nNode) + jNode*nNode + iNode]
88 | su2_File.write( "%s \t %s \t %s \t %s\n" % (XCoord, YCoord, ZCoord, iPoint) )
89 | iPoint = iPoint + 1
90 |
91 | # Write the boundaries
92 | su2_File.write( "NMARK=6\n" )
93 |
94 | su2_File.write( "MARKER_TAG= Xplane_0\n" )
95 | elem = (mNode-1)*(lNode-1)
96 | su2_File.write( "MARKER_ELEMS=%s\n" % elem )
97 | for jNode in range(mNode-1):
98 | for kNode in range(lNode-1):
99 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % (jNode*nNode + (nNode - 1) + kNode*nNode*mNode, (jNode + 1)*nNode + (nNode - 1) + kNode*nNode*mNode, (jNode + 1)*nNode + (nNode - 1)+ (kNode+1)*nNode*mNode, jNode*nNode + (nNode - 1)+ (kNode+1)*nNode*mNode ) )
100 |
101 | su2_File.write( "MARKER_TAG= Xplane_1\n" )
102 | elem = (mNode-1)*(lNode-1)
103 | su2_File.write( "MARKER_ELEMS=%s\n" % elem )
104 | for jNode in range(mNode-2, -1, -1):
105 | for kNode in range(lNode-1):
106 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % ((jNode + 1)*nNode + kNode*nNode*mNode, jNode*nNode + kNode*nNode*mNode, jNode*nNode+ (kNode+1)*nNode*mNode, (jNode + 1)*nNode+ (kNode+1)*nNode*mNode ) )
107 |
108 | su2_File.write( "MARKER_TAG= Yplane_0\n" )
109 | elem = (nNode-1)*(lNode-1)
110 | su2_File.write( "MARKER_ELEMS=%s\n" % elem )
111 | for iNode in range(nNode-1):
112 | for kNode in range(lNode-1):
113 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % (iNode + kNode*nNode*mNode, iNode + (kNode+1)*nNode*mNode, iNode + 1 + (kNode+1)*nNode*mNode, iNode + 1 + kNode*nNode*mNode) )
114 |
115 | su2_File.write( "MARKER_TAG= Yplane_1\n" )
116 | elem = (nNode-1)*(lNode-1)
117 | su2_File.write( "MARKER_ELEMS=%s\n" % elem )
118 | for iNode in range(nNode-1):
119 | for kNode in range(lNode-1):
120 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % ((nNode*mNode - 1) - iNode + kNode*nNode*mNode, (nNode*mNode - 1) - iNode + (kNode+1)*nNode*mNode, (nNode*mNode - 1) - (iNode + 1) + (kNode+1)*nNode*mNode, (nNode*mNode - 1) - (iNode + 1) + kNode*nNode*mNode) )
121 |
122 | su2_File.write( "MARKER_TAG= Zplane_0\n" )
123 | elem = (nNode-1)*(mNode-1);
124 | su2_File.write( "MARKER_ELEMS=%s\n" % elem)
125 | for jNode in range(mNode-1):
126 | for iNode in range(nNode-1):
127 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % (jNode*nNode + iNode, jNode*nNode + (iNode+1), (jNode + 1)*nNode + (iNode + 1), (jNode + 1)*nNode + iNode) )
128 |
129 | su2_File.write( "MARKER_TAG= Zplane_1\n" )
130 | elem = (nNode-1)*(mNode-1)
131 | su2_File.write( "MARKER_ELEMS=%s\n" % elem )
132 | for jNode in range(mNode-1):
133 | for iNode in range(nNode-1):
134 | su2_File.write( "9 \t %s \t %s \t %s \t %s\n" % (nNode*mNode*(lNode - 1) + jNode*nNode + iNode, nNode*mNode*(lNode - 1) + jNode*nNode + iNode + 1, nNode*mNode*(lNode - 1) + (jNode + 1)*nNode + (iNode + 1), nNode*mNode*(lNode - 1) + (jNode + 1)*nNode + iNode) )
135 |
136 | su2_File.close()
--------------------------------------------------------------------------------
/Fortran/dpl2su2_2D.f:
--------------------------------------------------------------------------------
1 | PROGRAM dpl2su2
2 |
3 | C Code provided by Dr. Aldo Bonfiglioli
4 | C Associate professor of Fluid Flow Machinery
5 | C Scuola di Ingegneria
6 | C Universita' della Basilicata
7 |
8 | C
9 | C This routine reads a .dpl unstructured datafile
10 | C and creates a SU2 mesh file
11 | C
12 | C dplot is a:
13 | C write (*,*) 'STRUCTURED/UNSTRUCTURED CONTOUR PLOTTING PACKAGE'
14 | C write (*,*) ' -Written by DARREN DE ZEEUW '
15 | C write (*,*) ' -Last Modified 02/93 '
16 | C write (*,*) ' '
17 | C
18 | C the dplot format is described in format 110-130
19 | C
20 | C Unstructured dplot file are created using the
21 | C Delaundo mesh generator
22 | C http://www.cerfacs.fr/~muller/delaundo.html
23 | C
24 | IMPLICIT NONE
25 | C
26 | INTEGER NELEMAX,NODEMAX,NFACMAX,NDIM,NOFVERT
27 | PARAMETER (NELEMAX=525000,NODEMAX=265000,
28 | & NFACMAX=5000,NDIM=2,NOFVERT=NDIM+1)
29 | C
30 | INTEGER nCells,nNodes,nCorners,nBoundaryFaces,NFAC,nBodies,
31 | + nBodyFaces,iBodyType
32 | INTEGER node1,node2,ntriangle
33 | INTEGER i,j,k,npo
34 | INTEGER NELEM,NPOIN,NBFAC,NHOLE
35 | C
36 | INTEGER Corner(3,NELEMAX)
37 | C
38 | DOUBLE PRECISION XY(2,NODEMAX)
39 | CHARACTER*80 filename,title
40 | C
41 | EQUIVALENCE (nCells,NELEM)
42 | EQUIVALENCE (nNodes,NPOIN)
43 | EQUIVALENCE (NFAC,NBFAC)
44 | C
45 | WRITE (6,*)
46 | WRITE (6,*) ' Give the input filename in dpl format :'
47 | WRITE (6,*)
48 | READ (5,'(A80)') filename
49 | C
50 | WRITE(6,150)
51 | 5 OPEN (1,FILE=filename,STATUS='OLD',FORM='formatted')
52 | OPEN(UNIT=12,FILE="MESH.su2")
53 | C
54 | C UNSTRUCTURED DATA FILE
55 | C
56 | READ (1,'(A80)') title
57 | WRITE (6,'(A80)') title
58 | c
59 | c..Needs "unstr" or "UNSTR" as first five characters
60 | c
61 | READ (1,*) nCells
62 | IF (nCells.GT.NELEMAX) THEN
63 | WRITE(6,*)'Actual nof cells ',nCells,' > Max allowed = ',
64 | & NELEMAX
65 | STOP 'Increase NELEMAX within dpl2su2'
66 | ENDIF
67 | DO 19 i = 1,nCells
68 | READ (1,*) nCorners, (Corner(j,i),j=1,nCorners)
69 | 19 CONTINUE
70 | WRITE (6,*) nCells,' Cells read !'
71 | WRITE(12,FMT=201)NDIM
72 | WRITE(12,FMT=202)NELEM
73 | do I= 1,NELEM
74 | WRITE(12,FMT=80)5,((Corner(j,I)-1),j=1,NOFVERT),I-1
75 | enddo
76 | WRITE (6,*) nCells,' Cells have been written !'
77 | C
78 | READ (1,*) nNodes
79 | IF (nNodes.GT.NODEMAX) THEN
80 | WRITE(6,*)'Actual nof nodes ',nNodes,' > Max allowed = ',
81 | & NODEMAX
82 | STOP 'Increase NODEMAX within dpl2su2'
83 | ENDIF
84 | READ (1,*)
85 | c
86 | c..read gridpoints
87 | c
88 | DO 21 i = 1,nNodes
89 | READ (1,*) XY(1,i),XY(2,i)
90 | 21 CONTINUE
91 | WRITE (6,*) nNodes,' Nodes read !'
92 | C
93 | WRITE(12,FMT=203) NPOIN
94 | do 125 I=1,NPOIN
95 | WRITE(12,FMT=*)(XY(j,I),j=1,NDIM),I-1
96 | 125 CONTINUE
97 | WRITE (6,*) nNodes,' Nodes written !'
98 | C
99 | READ (1,*) nBodies
100 | Write(6,*)nBodies,' have been found in the dpl file'
101 | WRITE(12,FMT=204)nBodies
102 | DO 25 j = 1,nBodies
103 | READ (1,*) nBodyFaces,iBodyType
104 | WRITE (6,*) 'There are ',nBodyFaces,' edges on bndry # ',j,
105 | &' type is ',iBodyType
106 | write(12,FMT=205)iBodyType
107 | write(12,FMT=206)nBodyFaces
108 | DO 25 i = 1,nBodyFaces
109 | READ (1,*) node1,node2,ntriangle
110 | write(12,FMT=95)3,node1-1,node2-1
111 | 25 CONTINUE
112 | c
113 | c REM: dplot files created by Delaundo have nBoundaryFaces=0
114 | c
115 | c
116 | READ (1,*) nBoundaryFaces
117 | IF (nBoundaryFaces.NE.0) THEN
118 | WRITE (*,*) ' nBoundaryFaces is NOT 0 but ... ',
119 | + nBoundaryFaces
120 | CALL EXIT(1)
121 |
122 | ENDIF
123 | CLOSE (1)
124 | C
125 | C
126 | WRITE(6,*)
127 | WRITE(6,*)'REMEMBER:'
128 | WRITE(6,*)
129 | WRITE(6,*)'Give a meaningful name to MARKER_TAG in the mesh file'
130 | WRITE(6,*)'It needs to have a corresponding boundary condition'
131 | WRITE(6,*)'in the configuration file!!!!'
132 | C
133 | C
134 | C
135 | 80 FORMAT(I1,1X,5(I6,1X))
136 | 95 FORMAT(I1,1X,4(I6,1X))
137 | 110 format (' '/
138 | + 'UNSTRUCTURED DATA FILE '/
139 | + ' write (1,"(a22)") "unstructured grid data" '/
140 | + 'c..Needs "unstr" or "UNSTR" as first five characters '/
141 | + ' write (1,*) nCells '/
142 | + ' do i=1,nCells '/
143 | + ' write (1,*) nCorners,(Corner(j,i),j=1,nCorners) '/
144 | + ' end do ')
145 | 120 format (' write (1,*) nNodes '/
146 | + ' write (1,*) U1(inf),U2(inf),U3(inf),U4(inf) '/
147 | + 'c..Freestream state values '/
148 | + ' do i=1,nNodes '/
149 | + ' write (1,*) X(i),Y(i),U1(i),U2(i),U3(i),U4(i) '/
150 | + ' end do ')
151 | 130 format (' write (1,*) nBodies '/
152 | + ' do j=1,nBodies '/
153 | + ' write (1,*) nBodyFaces(j) '/
154 | + ' do i=1,nBodyFaces(j) '/
155 | + ' write (1,*) node1(i),node2(i) '/
156 | + ' end do '/
157 | + ' end do '/
158 | + 'c..Two nodes for face on body numbered as above '/
159 | + ' write (1,*) nBoundaryFaces '/
160 | + ' do i=1,nBoundaryFaces '/
161 | + ' write (1,*) node1(i),node2(i) '/
162 | + ' end do '/
163 | + 'c..Two nodes for face on boundary numbered as above '/
164 | + ' ')
165 | 111 FORMAT('.',$)
166 | 135 FORMAT(5X,'Writing the coordinates ... ')
167 | 145 FORMAT(5X,'Writing the variables ... ')
168 | 150 FORMAT(5X,'I am opening the Dplot file ... ',/)
169 | 175 FORMAT(' done !',/)
170 | 180 FORMAT(5X,'Su2 file WRITTEN',/)
171 | 201 FORMAT('NDIME= ',I1)
172 | 202 FORMAT('NELEM= ',I8)
173 | 203 FORMAT('NPOIN= ',I8)
174 | 204 FORMAT('NMARK= ',I8)
175 | 205 FORMAT('MARKER_TAG= ',I2)
176 | 206 FORMAT('MARKER_ELEMS= ',I8)
177 | END
178 |
--------------------------------------------------------------------------------
/Python/3DChannel.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file 3DChannel.py
4 | # \brief Python script for box meshing
5 | # \author F. Palacios
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 |
34 | parser=OptionParser()
35 | parser.add_option("-f", "--file", dest="filename", default="channel.su2",
36 | help="write mesh to FILE", metavar="FILE")
37 | parser.add_option("-n", "--nNode", dest="nNode", default=5,
38 | help="use this NNODE in x direction", metavar="NNODE")
39 | parser.add_option("-m", "--mNode", dest="mNode", default=5,
40 | help="use this MNODE in y direction", metavar="MNODE")
41 | parser.add_option("-l", "--lNode", dest="lNode", default=5,
42 | help="use this LNODE in z direction", metavar="LNODE")
43 | parser.add_option("-x", "--xLength", dest="xLength", default=1.0,
44 | help="use this XLENGTH", metavar="XLENGTH")
45 | parser.add_option("-y", "--yLength", dest="yLength", default=1.0,
46 | help="use this YLENGTH", metavar="YLENGTH")
47 | parser.add_option("-z", "--zLength", dest="zLength", default=1.0,
48 | help="use this ZLENGTH", metavar="ZLENGTH")
49 | (options, args)=parser.parse_args()
50 |
51 | KindElem = 12
52 | KindBound = 9
53 | nNode = int(options.nNode)
54 | mNode = int(options.mNode)
55 | lNode = int(options.lNode)
56 | xLength = float(options.xLength)
57 | yLength = float(options.yLength)
58 | zLength = float(options.zLength)
59 |
60 | Mesh_File = open(options.filename,"w")
61 |
62 | Mesh_File.write( "%\n" )
63 | Mesh_File.write( "% Problem dimension\n" )
64 | Mesh_File.write( "%\n" )
65 | Mesh_File.write( "NDIME=3\n" )
66 | Mesh_File.write( "%\n" )
67 | Mesh_File.write( "% Inner elements\n" )
68 | Mesh_File.write( "%\n" )
69 | Mesh_File.write( "NELEM=%s\n" % ((lNode-1)*(nNode-1)*(mNode-1)))
70 |
71 |
72 | iElem = 0
73 | for kNode in range(lNode-1):
74 | for jNode in range(mNode-1):
75 | for iNode in range(nNode-1):
76 | Point0 = kNode*mNode*nNode + jNode*nNode + iNode
77 | Point1 = kNode*mNode*nNode + jNode*nNode + iNode + 1
78 | Point2 = kNode*mNode*nNode + (jNode+1)*nNode + (iNode+1)
79 | Point3 = kNode*mNode*nNode + (jNode+1)*nNode + iNode
80 | Point4 = (kNode+1)*mNode*nNode + jNode*nNode + iNode
81 | Point5 = (kNode+1)*mNode*nNode + jNode*nNode + iNode + 1
82 | Point6 = (kNode+1)*mNode*nNode + (jNode + 1)*nNode + (iNode + 1)
83 | Point7 = (kNode+1)*mNode*nNode + (jNode + 1)*nNode + iNode
84 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s\n" % (KindElem, Point0, Point1, Point2, Point3, Point4, Point5, Point6, Point7, iElem) )
85 | iElem = iElem + 1
86 |
87 | nPoint = (nNode)*(mNode)*(lNode)
88 | Mesh_File.write( "%\n" )
89 | Mesh_File.write( "NPOIN=%s\n" % ((nNode)*(mNode)*(lNode)))
90 | iPoint = 0
91 | for kNode in range(lNode):
92 | for jNode in range(mNode):
93 | for iNode in range(nNode):
94 | Mesh_File.write( "%15.14f \t %15.14f \t %15.14f \t %s\n" % (xLength*float(iNode)/float(nNode-1), zLength*float(kNode)/float(lNode-1), yLength*float(jNode)/float(mNode-1), iPoint) )
95 | iPoint = iPoint + 1
96 |
97 | Mesh_File.write( "%\n" )
98 | Mesh_File.write( "% Boundary elements\n" )
99 | Mesh_File.write( "%\n" )
100 | Mesh_File.write( "NMARK=6\n" )
101 |
102 | Mesh_File.write( "MARKER_TAG= left\n" )
103 | elem = (nNode-1)*(mNode-1);
104 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem)
105 | for jNode in range(mNode-1):
106 | for iNode in range(nNode-1):
107 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, jNode*nNode + iNode, jNode*nNode + (iNode+1), (jNode + 1)*nNode + (iNode + 1), (jNode + 1)*nNode + iNode) )
108 |
109 | Mesh_File.write( "MARKER_TAG= right\n" )
110 | elem = (nNode-1)*(mNode-1)
111 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem )
112 | for jNode in range(mNode-1):
113 | for iNode in range(nNode-1):
114 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, nNode*mNode*(lNode - 1) + jNode*nNode + iNode, nNode*mNode*(lNode - 1) + jNode*nNode + iNode + 1, nNode*mNode*(lNode - 1) + (jNode + 1)*nNode + (iNode + 1), nNode*mNode*(lNode - 1) + (jNode + 1)*nNode + iNode) )
115 |
116 | Mesh_File.write( "MARKER_TAG= lower\n" )
117 | elem = (nNode-1)*(lNode-1)
118 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem )
119 | for iNode in range(nNode-1):
120 | for kNode in range(lNode-1):
121 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, iNode + kNode*nNode*mNode, iNode + (kNode+1)*nNode*mNode, iNode + 1 + (kNode+1)*nNode*mNode, iNode + 1 + kNode*nNode*mNode) )
122 |
123 | Mesh_File.write( "MARKER_TAG= upper\n" )
124 | elem = (nNode-1)*(lNode-1)
125 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem )
126 | for iNode in range(nNode-1):
127 | for kNode in range(lNode-1):
128 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, (nNode*mNode - 1) - iNode + kNode*nNode*mNode, (nNode*mNode - 1) - iNode + (kNode+1)*nNode*mNode, (nNode*mNode - 1) - (iNode + 1) + (kNode+1)*nNode*mNode, (nNode*mNode - 1) - (iNode + 1) + kNode*nNode*mNode) )
129 |
130 | Mesh_File.write( "MARKER_TAG= outlet\n" )
131 | elem = (mNode-1)*(lNode-1)
132 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem )
133 | for jNode in range(mNode-1):
134 | for kNode in range(lNode-1):
135 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, jNode*nNode + (nNode - 1) + kNode*nNode*mNode, (jNode + 1)*nNode + (nNode - 1) + kNode*nNode*mNode, (jNode + 1)*nNode + (nNode - 1)+ (kNode+1)*nNode*mNode, jNode*nNode + (nNode - 1)+ (kNode+1)*nNode*mNode ) )
136 |
137 | Mesh_File.write( "MARKER_TAG= inlet\n" )
138 | elem = (mNode-1)*(lNode-1)
139 | Mesh_File.write( "MARKER_ELEMS=%s\n" % elem )
140 | for jNode in range(mNode-2, -1, -1):
141 | for kNode in range(lNode-1):
142 | Mesh_File.write( "%s \t %s \t %s \t %s \t %s\n" % (KindBound, (jNode + 1)*nNode + kNode*nNode*mNode, jNode*nNode + kNode*nNode*mNode, jNode*nNode+ (kNode+1)*nNode*mNode, (jNode + 1)*nNode+ (kNode+1)*nNode*mNode ) )
143 |
144 | Mesh_File.write( "FFD_NBOX=1\n")
145 | Mesh_File.write( "FFD_NLEVEL=1\n")
146 | Mesh_File.write( "FFD_TAG=0\n")
147 | Mesh_File.write( "FFD_LEVEL=0\n")
148 | Mesh_File.write( "FFD_DEGREE_I=6\n")
149 | Mesh_File.write( "FFD_DEGREE_J=6\n")
150 | Mesh_File.write( "FFD_DEGREE_K=1\n")
151 | Mesh_File.write( "FFD_PARENTS=0\n")
152 | Mesh_File.write( "FFD_CHILDREN=0\n")
153 | Mesh_File.write( "FFD_CORNER_POINTS=8\n")
154 | Mesh_File.write( "4.0 0 -0.1\n")
155 | Mesh_File.write( "6.0 0 -0.1\n")
156 | Mesh_File.write( "6.0 2.0 -0.1\n")
157 | Mesh_File.write( "4.0 2.0 -0.1\n")
158 | Mesh_File.write( "4.0 0 0.1\n")
159 | Mesh_File.write( "6.0 0 0.1\n")
160 | Mesh_File.write( "6.0 2.0 0.1\n")
161 | Mesh_File.write( "4.0 2.0 0.1\n")
162 | Mesh_File.write( "FFD_CONTROL_POINTS=0\n")
163 | Mesh_File.write( "FFD_SURFACE_POINTS=0\n")
164 |
165 |
166 |
167 | Mesh_File.close()
168 |
--------------------------------------------------------------------------------
/Python/2DChannel.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | ## \file 2DChannel.py
4 | # \brief Python script for creating grid for freesurface channels.
5 | # \author F. Palacios
6 | # \version 3.2.8 "eagle"
7 | #
8 | # SU2 Lead Developers: Dr. Francisco Palacios (fpalacios@stanford.edu).
9 | # Dr. Thomas D. Economon (economon@stanford.edu).
10 | #
11 | # SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
12 | # Prof. Piero Colonna's group at Delft University of Technology.
13 | # Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
14 | # Prof. Alberto Guardone's group at Polytechnic University of Milan.
15 | # Prof. Rafael Palacios' group at Imperial College London.
16 | #
17 | # Copyright (C) 2012-2015 SU2, the open-source CFD code.
18 | #
19 | # SU2 is free software; you can redistribute it and/or
20 | # modify it under the terms of the GNU Lesser General Public
21 | # License as published by the Free Software Foundation; either
22 | # version 2.1 of the License, or (at your option) any later version.
23 | #
24 | # SU2 is distributed in the hope that it will be useful,
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 | # Lesser General Public License for more details.
28 | #
29 | # You should have received a copy of the GNU Lesser General Public
30 | # License along with SU2. If not, see .
31 |
32 | from optparse import OptionParser
33 |
34 | parser=OptionParser()
35 | parser.add_option("-f", "--file", dest="filename", default="Channel.su2",
36 | help="write mesh to FILE", metavar="FILE")
37 | parser.add_option("-n", "--nNode", dest="nNode", default=125,
38 | help="use this NNODE in x direction", metavar="NNODE")
39 | parser.add_option("-m", "--mNode", dest="mNode", default=100,
40 | help="use this MNODE in y direction", metavar="MNODE")
41 | parser.add_option("-x", "--xLength", dest="xLength", default=7.0,
42 | help="use this XLENGTH", metavar="XLENGTH")
43 | parser.add_option("--offsetx", dest="offsetx", default=1.0,
44 | help="use this OFFSETX", metavar="OFFSETX")
45 | parser.add_option("--xAdapt", dest="xAdapt", default="True",
46 | help="Adapt the grid XADAPT", metavar="XADAPT")
47 | parser.add_option("-y", "--yLength", dest="yLength", default=1.0,
48 | help="use this YLENGTH", metavar="YLENGTH")
49 | parser.add_option("--offsety", dest="offsety", default=0.5,
50 | help="use this OFFSETY", metavar="OFFSETY")
51 | parser.add_option("--yAdapt", dest="yAdapt", default="True",
52 | help="Adapt the grid YADAPT", metavar="YADAPT")
53 | (options, args)=parser.parse_args()
54 |
55 | nNode = int(options.nNode)
56 | mNode = int(options.mNode)
57 | xLength = float(options.xLength)
58 | yLength = float(options.yLength)
59 | xAdapt = options.xAdapt
60 | yAdapt = options.yAdapt
61 |
62 | Mesh_File = open(options.filename,"w")
63 |
64 | Mesh_File.write( "%\n" )
65 | Mesh_File.write( "% Problem dimension\n" )
66 | Mesh_File.write( "%\n" )
67 | Mesh_File.write( "NDIME=2\n" )
68 | Mesh_File.write( "%\n" )
69 | Mesh_File.write( "% Inner elements\n" )
70 | Mesh_File.write( "%\n" )
71 | Mesh_File.write( "NELEM=%s\n" % ((nNode-1)*(mNode-1)))
72 |
73 |
74 | iElem = 0
75 | for jNode in range(mNode-1):
76 | for iNode in range(nNode-1):
77 | iPoint = jNode*nNode + iNode
78 | jPoint = jNode*nNode + iNode + 1
79 | kPoint = (jNode + 1)*nNode + iNode
80 | mPoint = (jNode + 1)*nNode + (iNode + 1)
81 | Mesh_File.write( "9 \t %s \t %s \t %s \t %s \t %s\n" % (iPoint, jPoint, mPoint, kPoint, iElem) )
82 | iElem = iElem + 1
83 |
84 | nPoint = (nNode)*(mNode)
85 | Mesh_File.write( "%\n" )
86 | Mesh_File.write( "NPOIN=%s\n" % ((nNode)*(mNode)) )
87 | iPoint = 0
88 |
89 | for jNode in range(mNode):
90 | for iNode in range(nNode):
91 | xCoord = float(iNode)/float(nNode-1)
92 | yCoord = float(jNode)/float(mNode-1)
93 |
94 | if xAdapt == "True":
95 |
96 | x0 = 0.0; x1 = 0.12; x2 = 0.30; x3 = 1.0;
97 | fp3 = 10.0; fp0 = fp3; fpp2 = 0.0; fpp1 = -fpp2;
98 | if (xCoord >= x0) and (xCoord < x1):
99 | incr = x1-x0; incr2 = x1*x1-x0*x0; incr3 = x1*x1*x1-x0*x0*x0
100 | d = ((1.0 - fp0) - fpp1*incr)/ (3.0*incr2-6.0*x1*incr); c = (fpp1/2.0) -3.0*d*x1
101 | b = 1.0 - 2.0*c*x1 - 3.0*d*x1*x1; a = x1 - b*x1-c*x1*x1-d*x1*x1*x1
102 | x = a + b*xCoord + c*xCoord*xCoord + d*xCoord*xCoord*xCoord
103 | if (xCoord >= x1) and (xCoord <= x2):
104 | x = xCoord
105 | if (xCoord > x2) and (xCoord <= x3):
106 | incr = x2-x3; incr2 = x2*x2-x3*x3; incr3 = x2*x2*x2-x3*x3*x3
107 | d = ((1.0 - fp3) - fpp2*incr)/ (3.0*incr2-6.0*x2*incr); c = (fpp2/2.0) - 3.0*d*x2
108 | b = 1.0 - 2.0*c*x2 - 3.0*d*x2*x2; a = x2 - b*x2-c*x2*x2-d*x2*x2*x2
109 | x = a + b*xCoord + c*xCoord*xCoord + d*xCoord*xCoord*xCoord
110 |
111 | incr = x1-x0; incr2 = x1*x1-x0*x0; incr3 = x1*x1*x1-x0*x0*x0
112 | d = ((1.0 - fp0) - fpp1*incr)/ (3.0*incr2-6.0*x1*incr); c = (fpp1/2.0) -3.0*d*x1
113 | b = 1.0 - 2.0*c*x1 - 3.0*d*x1*x1; a = x1 - b*x1-c*x1*x1-d*x1*x1*x1
114 | x_min = a + b*x0 + c*x0*x0 + d*x0*x0*x0
115 | incr = x2-x3; incr2 = x2*x2-x3*x3; incr3 = x2*x2*x2-x3*x3*x3
116 | d = ((1.0 - fp3) - fpp2*incr)/ (3.0*incr2-6.0*x2*incr); c = (fpp2/2.0) - 3.0*d*x2
117 | b = 1.0 - 2.0*c*x2 - 3.0*d*x2*x2; a = x2 - b*x2-c*x2*x2-d*x2*x2*x2
118 | x_max = a + b*x3 + c*x3*x3 + d*x3*x3*x3
119 |
120 | xCoord_new = xLength*((x-x_min)/(x_max-x_min)) - float(options.offsetx)
121 |
122 | else:
123 |
124 | xCoord_new = xLength*xCoord - float(options.offsetx)
125 |
126 | if yAdapt == "True":
127 |
128 | y0 = 0.0; y1 = 0.000001; y2 = 0.001; y3 = 1.0;
129 | fp3 = 10.0; fp0 = fp3; fpp2 = 0.0; fpp1 = -fpp2;
130 | if (yCoord >= y0) and (yCoord < y1):
131 | incr = y1-y0; incr2 = y1*y1-y0*y0; incr3 = y1*y1*y1-y0*y0*y0
132 | d = ((1.0 - fp0) - fpp1*incr)/ (3.0*incr2-6.0*y1*incr); c = (fpp1/2.0) -3.0*d*y1
133 | b = 1.0 - 2.0*c*y1 - 3.0*d*y1*y1; a = y1 - b*y1-c*y1*y1-d*y1*y1*y1
134 | y = a + b*yCoord + c*yCoord*yCoord + d*yCoord*yCoord*yCoord
135 | if (yCoord >= y1) and (yCoord <= y2):
136 | y = yCoord
137 | if (yCoord > y2) and (yCoord <= y3):
138 | incr = y2-y3; incr2 = y2*y2-y3*y3; incr3 = y2*y2*y2-y3*y3*y3
139 | d = ((1.0 - fp3) - fpp2*incr)/ (3.0*incr2-6.0*y2*incr); c = (fpp2/2.0) - 3.0*d*y2
140 | b = 1.0 - 2.0*c*y2 - 3.0*d*y2*y2; a = y2 - b*y2-c*y2*y2-d*y2*y2*y2
141 | y = a + b*yCoord + c*yCoord*yCoord + d*yCoord*yCoord*yCoord
142 |
143 | incr = y1-y0; incr2 = y1*y1-y0*y0; incr3 = y1*y1*y1-y0*y0*y0
144 | d = ((1.0 - fp0) - fpp1*incr)/ (3.0*incr2-6.0*y1*incr); c = (fpp1/2.0) -3.0*d*y1
145 | b = 1.0 - 2.0*c*y1 - 3.0*d*y1*y1; a = y1 - b*y1-c*y1*y1-d*y1*y1*y1
146 | y_min = a + b*y0 + c*y0*y0 + d*y0*y0*y0
147 |
148 | incr = y2-y3; incr2 = y2*y2-y3*y3; incr3 = y2*y2*y2-y3*y3*y3
149 | d = ((1.0 - fp3) - fpp2*incr)/ (3.0*incr2-6.0*y2*incr); c = (fpp2/2.0) - 3.0*d*y2
150 | b = 1.0 - 2.0*c*y2 - 3.0*d*y2*y2; a = y2 - b*y2-c*y2*y2-d*y2*y2*y2
151 | y_max = a + b*y3 + c*y3*y3 + d*y3*y3*y3
152 |
153 | yCoord_new = yLength*((y-y_min)/(y_max-y_min)) - float(options.offsety)
154 |
155 | else:
156 |
157 | yCoord_new = yLength*yCoord - float(options.offsety)
158 |
159 | Mesh_File.write( "%15.14f \t %15.14f \t %s\n" % (xCoord_new, yCoord_new, iPoint) )
160 | iPoint = iPoint + 1
161 |
162 | Mesh_File.write( "%\n" )
163 | Mesh_File.write( "% Boundary elements\n" )
164 | Mesh_File.write( "%\n" )
165 | Mesh_File.write( "NMARK=4\n" )
166 | Mesh_File.write( "MARKER_TAG= lower\n" )
167 | Mesh_File.write( "MARKER_ELEMS=%s\n" % (nNode-1))
168 | for iNode in range(nNode-1):
169 | Mesh_File.write( "3 \t %s \t %s\n" % (iNode, iNode + 1) )
170 |
171 | Mesh_File.write( "MARKER_TAG= outlet\n" )
172 | Mesh_File.write( "MARKER_ELEMS=%s\n" % (mNode-1))
173 | for jNode in range(mNode-1):
174 | Mesh_File.write( "3 \t %s \t %s\n" % (jNode*nNode + (nNode - 1), (jNode + 1)*nNode + (nNode - 1) ) )
175 | Mesh_File.write( "MARKER_TAG= upper\n" )
176 | Mesh_File.write( "MARKER_ELEMS=%s\n" % (nNode-1))
177 | for iNode in range(nNode-1):
178 | Mesh_File.write( "3 \t %s \t %s\n" % ((nNode*mNode - 1) - iNode, (nNode*mNode - 1) - (iNode + 1)) )
179 | Mesh_File.write( "MARKER_TAG= inlet\n" )
180 | Mesh_File.write( "MARKER_ELEMS=%s\n" % (mNode-1))
181 | for jNode in range(mNode-2, -1, -1):
182 | Mesh_File.write( "3 \t %s \t %s\n" % ((jNode + 1)*nNode, jNode*nNode ) )
183 |
184 | Mesh_File.close()
185 |
--------------------------------------------------------------------------------
/Fortran/gmsh2su2_3D.f90:
--------------------------------------------------------------------------------
1 | ! ====================
2 | ! README Gmsh2SU3D ver 0.02
3 | ! ====================
4 | !
5 | ! Original version by Ceanwang@gmail.com, Jan 2012
6 | !
7 | ! Adapted from gmsh2dolfyn.f90 developed by dolfyn team.
8 | ! For dolfyn, please visit http://www.dolfyn.net/index_en.html
9 | !
10 | ! Support Gmsh 2.5.0
11 | !
12 | ! Purpose
13 | ! -------
14 | ! This Fortran95 program translates a mesh file from Gmsh (.msh) format
15 | ! to Su2 format.
16 | !
17 | ! Input and Output
18 | ! ----------------
19 | ! Input : A Gmsh .msh file (version 2.0, ascii format).
20 | ! Output: SU2 files.
21 | !
22 | ! Running the Program
23 | !--------------------
24 | ! First compile it using a Fortran95 compiler (eg g95 or gfortran).
25 | ! Run it from the command line.
26 | ! The program prompts for the name of the input file.
27 | !
28 | ! Bug reports
29 | ! -----------
30 | ! Please report bugs to ceanwang@gmail.com
31 | !
32 | ! Important note about the Gmsh msh format and Physical Groups.
33 | ! -------------------------------------------------------------
34 | ! In order to define boundary conditions, the Gmsh geometry-builder allows a
35 | ! group of faces to be assigned a common 'physical group' label. The mesh
36 | ! inherits this label, and the label is used in the .su2 file.
37 | !
38 | ! When saving the mesh, the default is to save only mesh elements with a
39 | ! physical group label. This means that some mesh elements will be missing,
40 | ! unless every mesh element belongs to a physical group.
41 | !
42 | ! For example in the adapted gmsh tutorial t2.geo enter:
43 | !
44 | ! Physical Volume ("Fluid") = {119,120};
45 | ! Physical Surface("Inlet") = {111};
46 | ! Physical Surface("Outlet") = {132};
47 | !
48 | ! Mesh 3D and save it as t2.msh
49 | !
50 | !========================================================================
51 | !========================================================================
52 | !========================================================================
53 | SUBROUTINE UPPERCASE(STR)
54 |
55 | IMPLICIT NONE
56 |
57 | CHARACTER(LEN=*), INTENT(IN OUT) :: STR
58 | INTEGER :: I, DEL
59 |
60 | DEL = IACHAR('a') - IACHAR('A')
61 |
62 | DO I = 1, LEN_TRIM(STR)
63 | IF (LGE(STR(I:I),'a') .AND. LLE(STR(I:I),'z')) THEN
64 | STR(I:I) = ACHAR(IACHAR(STR(I:I)) - DEL)
65 | END IF
66 | END DO
67 |
68 | RETURN
69 |
70 | END SUBROUTINE UPPERCASE
71 |
72 | integer function lens(string)
73 |
74 | character(len=*) string
75 |
76 | do i=len(string),0,-1
77 | if( string(i:i) .ne. ' ') goto 10
78 | end do
79 | i = 0
80 | 10 continue
81 |
82 | lens = i
83 |
84 | end function lens
85 | !======================================================================
86 | subroutine openfile(iunit,casename,extension,reqform,status,idebug)
87 |
88 | character(len=*) casename
89 | character(len=*) extension
90 | character(len=*) reqform
91 | character(len=*) status
92 | character(len=48) filename
93 | character(len=11) form
94 |
95 | logical exists
96 |
97 | filename = casename(1:lens(casename))//extension(1:lens(extension))
98 | length = lens(filename)
99 |
100 | if( idebug > 2 )write(*,*) 'Opening ',filename(1:length)
101 |
102 | if( status(1:3) == 'OLD' )then
103 | inquire(file=filename(1:length),exist=exists,form=form)
104 | if( .not. exists )then
105 | write(*,*) '*** Error: File ',filename(1:length),' does not exist'
106 | stop
107 | endif
108 | endif
109 |
110 | open(iunit,file=filename(1:length),form=reqform,status=status)
111 |
112 | if( idebug >= 2 ) write(*,*) 'File ',filename(1:length),' opened'
113 |
114 | end subroutine openfile
115 | !==============================================================================
116 | program gmsh2SU2
117 |
118 | implicit none
119 |
120 | integer, parameter :: IOinp = 13, IOcel = 14 ! I/O file numbers
121 | integer, parameter :: IOdbg = 63, IOcfg = 12
122 | integer, parameter :: IOgmsh= 24 !Gmsh mesh file
123 |
124 | integer :: Ninlet = 0
125 | integer :: Noutlet = 0
126 | integer :: Nsurface = 0
127 | integer :: isur = 0
128 |
129 | integer :: debug = 0
130 |
131 | integer, parameter :: version = 0530
132 |
133 | character(len=128) :: line
134 |
135 | integer, parameter :: MaxNames = 100
136 | integer, parameter :: MaxNperBnd = 500
137 | integer, parameter :: MaxNodes = 90000
138 |
139 | character(len=64), dimension(MaxNames) :: Names
140 | character(len=64), dimension(MaxNames) :: Regions
141 | integer, dimension(MaxNames) :: ICTID = -1
142 | integer, dimension(MaxNames) :: Partition= 1
143 |
144 | logical, dimension(MaxNames) :: Fluid = .false.
145 | logical, dimension(MaxNames) :: Boundary = .false.
146 |
147 | character(len=64) :: casename = 'su2'
148 | character(len=72) :: c_input1, c_input2, c_input3
149 |
150 | integer i, j, k, ie, icel, ibnd, iloop,ii
151 | integer tbnd(maxnames)
152 | integer nbnd
153 | !
154 | ! nodes/vertices
155 | !
156 | integer n_nodes,inode
157 | real node(MaxNodes,3)
158 | integer mytags(MaxNames)
159 | integer tv0(MaxNperBnd,MaxNames)
160 | integer tv1(MaxNperBnd,MaxNames)
161 | integer tv2(MaxNperBnd,MaxNames)
162 | integer tv3(MaxNperBnd,MaxNames)
163 | integer tv4(MaxNperBnd,MaxNames)
164 |
165 | !
166 | ! there are 19 gmsh element types: \
167 | !
168 | ! 1 : 2-node line
169 | ! 2 : 3-node triangle (face)
170 | ! 3 : 4-node quadrangle (face)
171 | ! 4 : 4-node tetrahedron
172 | ! 5 : 8-node hexahedron (eg cube)
173 | ! 6 : 6-node triangular-prism
174 | ! 7 : 5-node pyramid
175 | !
176 | ! 8-14: 'second-order' elements. Ref Gmsh manual.
177 | ! 15 : 1-node point
178 | ! 16-19: more second-order FEM elements
179 | !
180 | ! the nodes/vertices for each element are read into the
181 | ! v array.
182 | !
183 | ! each element can have several tags.
184 | ! the first tag gives the physical_group number.
185 | ! all elements on the same boundary have the same physical_group number.
186 | !
187 | integer, parameter :: element_type(19) = &
188 | (/ 2,3,4,4,8,6,5,3,6,9,10,27,18,14,1,8,20,15,13 /)
189 |
190 | integer :: n_elements, ielement, ielement_type, n_tags, n_names, lens
191 | integer :: tags(64), v(27)
192 | integer :: bmarknew,bmarkold
193 | integer :: i3, i4q, i4, i5, i6, i8
194 | integer :: i2
195 | integer :: ivs = 0
196 |
197 |
198 |
199 | if( size(v) /= maxval(element_type) )then
200 | stop'bug: error in dimensions of array v'
201 | endif
202 |
203 | !
204 | ! read the gmsh filename, then open the .msh file
205 | !
206 | write(*,*) 'Gmsh2SU2: Converts a Gmsh mesh file to SU2 format.'
207 | write(*,*) '(Input must be in Gmsh version 2.0 ascii format.'
208 | write(*,*) ' Output is in SU2 format.)'
209 | write(*,*) ' '
210 | write(*,*) 'Input Gmsh filename, excluding the .msh suffix'
211 | read(*,'(A)') casename
212 |
213 | write(*,*) 'Opening the Gmsh file'
214 | call openfile(IOgmsh,casename,'.msh','FORMATTED','OLD',debug)
215 |
216 | !
217 | ! read the Gmsh file header
218 | !
219 | write(*,*)'Reading MeshFormat'
220 | read(IOgmsh,*) c_input1
221 | call check_input_character(c_input1,'$MeshFormat')
222 |
223 | read(IOgmsh,*) c_input1,c_input2,c_input3
224 | if( c_input1 == '2.2' )then
225 | ivs = 22
226 | else if( c_input1 == '2.1' )then
227 | ivs = 21
228 | else if( c_input1 == '2' )then
229 | ivs = 20
230 | else
231 | write(*,*) '*** WARNING: unknown Gmsh version'
232 | write(*,*) '*** Unexpected results might happen'
233 | ivs = 21
234 | endif
235 |
236 | if( ivs == 20 )then
237 | call check_input_character(c_input1,'2')
238 | else if( ivs == 21 )then
239 | call check_input_character(c_input1,'2.1')
240 | else if( ivs == 22 )then
241 | call check_input_character(c_input1,'2.2')
242 | else
243 | write(*,*) '*** Version found ',c_input1
244 | endif
245 |
246 | call check_input_character(c_input2,'0')
247 | call check_input_character(c_input3,'8')
248 |
249 | write(*,*) 'MeshFormat: ', c_input1(1:lens(c_input1)),' ', &
250 | c_input2(1:lens(c_input2)),' ', &
251 | c_input3(1:lens(c_input3))
252 |
253 | read(IOgmsh,*) c_input1
254 | call check_input_character(c_input1,'$EndMeshFormat')
255 |
256 | !
257 | ! read the Gmsh PhysicalNames
258 | !
259 | write(*,*)'Reading PhysicalNames'
260 | read(IOgmsh,*) c_input1
261 | call check_input_character(c_input1,'$PhysicalNames')
262 |
263 | read(IOgmsh,*) n_names
264 | if( n_names <= 0 )then
265 | write(*,*) 'error: number of names must be a positive number'
266 | stop
267 | endif
268 |
269 | if( ivs == 20 )then
270 | do i=1,n_names
271 | !read(IOgmsh,*) k,j,c_input1
272 | read(IOgmsh,*) j,c_input1
273 | write(*,*) 'Name ',j,'-> ', c_input1
274 | Names(j) = c_input1
275 | end do
276 | else if( ivs == 21 )then
277 | do i=1,n_names
278 | read(IOgmsh,*) k,j,c_input1
279 | write(*,*) 'Name ',j,'-> ', c_input1
280 | Names(j) = c_input1
281 | end do
282 | else
283 | do i=1,n_names
284 | read(IOgmsh,*) k,j,c_input1
285 | write(*,*) 'Name ',j,'-> ', c_input1
286 | Names(j) = c_input1
287 | end do
288 | endif
289 |
290 |
291 | do i=1,n_names
292 | CALL UPPERCASE(Names(i))
293 | enddo
294 |
295 | read(IOgmsh,*) c_input1
296 | call check_input_character(c_input1,'$EndPhysicalNames')
297 | !
298 | ! read the nodes from the .msh file and write them
299 | ! to the .vrt file.
300 | !
301 | write(*,*)'Reading Nodes'
302 | read(IOgmsh,*) c_input1
303 | call check_input_character(c_input1,'$Nodes')
304 | !nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
305 | read(IOgmsh,*) n_nodes
306 | if( n_nodes <= 0 )then
307 | write(*,*) 'error: number of nodes must be a positive number'
308 | stop
309 | endif
310 |
311 | if( n_nodes > MaxNodes )then
312 | write(*,*) 'error: The Gmsh file contains ',n_nodes,' nodes.'
313 | write(*,*) 'Gmsh2Su2 is hard-wired for a maximum of ',MaxNodes,&
314 | 'nodes. The dimension of this array needs to be increased.'
315 | stop
316 | endif
317 |
318 | !
319 | ! open the su2 .vrt.su2 file
320 | !
321 | !write(*,*) 'Creating the su2 .vrt.su2 file'
322 | !call openfile(IOvrt,casename,'.vrt.su2','FORMATTED','UNKNOWN',debug)
323 |
324 | nodes: do iloop=1,n_nodes
325 | read(IOgmsh,*) inode,(node(iloop,i), i=1,3)
326 | !write(IOvrt,'(3g16.9,6x,i9)') (node(iloop,i),i=1,3),inode-1
327 | enddo nodes
328 |
329 | write(*,*) 'Nodes written ',n_nodes
330 | !
331 | ! close the su2 .vrt.su2 file
332 | !
333 | !close(IOvrt)
334 |
335 | read(IOgmsh,*) c_input1
336 | call check_input_character(c_input1,'$EndNodes')
337 | !eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
338 | !
339 | ! read the elements from the .msh file and write them
340 | ! to the .cel and .bnd files.
341 | !
342 | read(IOgmsh,*) c_input1
343 | call check_input_character(c_input1,'$Elements')
344 |
345 | read(IOgmsh,*) n_elements
346 | if( n_elements <= 0 )then
347 | write(*,*) 'error: number of elements must be a positive number'
348 | stop
349 | endif
350 |
351 | write(*,*) 'Total Gmsh elements to be read in:',n_elements
352 | !
353 | ! open the su2 .cel files
354 | !
355 | write(*,*) 'Creating the .su2 files'
356 | call openfile(IOcel,casename,'.su2','FORMATTED','UNKNOWN',debug)
357 | write(IOcel,101) 3
358 | 101 format('NDIME= ',i1)
359 |
360 |
361 | !
362 | ! note in Gmsh fluid cells and boudaries can be mixed
363 | ! we just keep track on them both
364 | ! remind default region is not assigned
365 | !
366 | icel = 0
367 | ibnd = 0
368 | nbnd=0
369 | tbnd(nbnd)=0
370 |
371 | i2 = 0
372 | i3 = 0
373 | i4q = 0
374 | i4 = 0
375 | i5 = 0
376 | i6 = 0
377 | i8 = 0
378 |
379 | bmarkOld=0
380 | do ie=1,n_elements
381 |
382 | read(IOgmsh,*) ielement, ielement_type, n_tags
383 | if( ivs <= 21 )then
384 | if( n_tags /= 3 ) write(*,*) 'tag error n_tags /= 3:',ielement,n_tags
385 | else
386 | if( n_tags /= 2 ) write(*,*) 'tag error n_tags /= 2:',ielement,n_tags
387 | endif
388 | call check_element_type(ielement_type,element_type)
389 | call check_n_tags(n_tags,tags)
390 | backspace(IOgmsh)
391 |
392 | !
393 | ! we need to circumvent backspace but
394 | ! advance='no' requires fixed format
395 | ! just keep it for now.
396 | !
397 |
398 | !
399 | ! now we know what to to expect to find on the line
400 | !
401 | read(IOgmsh,*) ielement, ielement_type, &
402 | n_tags, (tags(i),i=1,n_tags),&
403 | (v(i),i=1,element_type(ielement_type))
404 |
405 | do ii=1,element_type(ielement_type)
406 | v(ii)=v(ii)-1
407 | end do
408 |
409 | bmarkNew=tags(1)
410 | if( 4 <= ielement_type .and. ielement_type <= 7 )then
411 | if (icel==0) then
412 | write(IOcel,121) n_elements-ibnd
413 | 121 format('NELEM= ',i10)
414 | endif
415 | icel = icel + 1
416 |
417 | if( .not. Fluid(tags(1)) ) Fluid(tags(1)) = .true.
418 | if( Boundary(tags(1)) )then
419 | write(*,*) 'Inconsistent data: Physical names ids overlap 1'
420 | endif
421 |
422 | 1 format(i8,8(1x,i8),2(1x,i4))
423 | select case(ielement_type)
424 |
425 | case(4) ! 4-node tet
426 |
427 | write(IOcel,*) 10,v(1),v(2),v(3),v(4),icel-1
428 | i4 = i4 + 1
429 |
430 | case(5) ! 8-node hex
431 |
432 | write(IOcel,*) 12,v(1),v(2),v(3),v(4), v(5),v(6),v(7),v(8),icel-1
433 | !tags(1),tags(3)
434 | i8 = i8 + 1
435 |
436 | case(6) ! 6-node prism or wedge
437 |
438 | write(IOcel,*) 13,v(1),v(2),v(3), v(4),v(5),v(6),icel-1
439 | i6 = i6 + 1
440 |
441 | case(7) ! 5-node pyramid
442 |
443 | write(IOcel,*) 14,v(1),v(2),v(3),v(4), v(5),icel-1
444 | i5 = i5 + 1
445 |
446 | case default
447 |
448 | write(*,*)'internal error 1'
449 |
450 | end select
451 |
452 | elseif( ielement_type == 2 .or. ielement_type == 3 )then
453 |
454 | if (bmarkNew/=bmarkOld) then
455 | bmarkOld=bmarkNew
456 | nbnd=nbnd+1
457 | tbnd(nbnd)=0
458 | endif
459 |
460 | ibnd = ibnd + 1
461 | tbnd(nbnd) = tbnd(nbnd) + 1
462 |
463 |
464 | if( .not. Boundary(tags(1)) ) Boundary(tags(1)) = .true.
465 | if( Fluid(tags(1)) )then
466 | write(*,*) 'Inconsistent data: Physical names ids overlap 2'
467 | endif
468 |
469 | select case(ielement_type)
470 |
471 | case(2) ! 3-node tri
472 |
473 | !write(IObnd,*) 5, v(1),v(2),v(3)
474 | mytags(nbnd)=tags(1)
475 | tv0(tbnd(nbnd),nbnd)=5
476 | tv1(tbnd(nbnd),nbnd)=v(1)
477 | tv2(tbnd(nbnd),nbnd)=v(2)
478 | tv3(tbnd(nbnd),nbnd)=v(3)
479 | i3 = i3 + 1
480 |
481 | case(3) ! 4-node quad
482 |
483 | !write(IObnd,1) 8, v(1),v(2),v(3),v(4)
484 | mytags(nbnd)=tags(1)
485 | tv0(tbnd(nbnd),nbnd)=8
486 | tv1(tbnd(nbnd),nbnd)=v(1)
487 | tv2(tbnd(nbnd),nbnd)=v(2)
488 | tv3(tbnd(nbnd),nbnd)=v(3)
489 | tv4(tbnd(nbnd),nbnd)=v(4)
490 | i4q = i4q + 1
491 |
492 | case default
493 |
494 | write(*,*)'internal error 2'
495 |
496 | end select
497 |
498 | elseif( ielement_type == 1 )then
499 | ! 2- nodes line
500 |
501 | !write(IObnd,*) 3, v(1),v(2)
502 | mytags(nbnd)=tags(1)
503 | tv0(tbnd(nbnd),nbnd)=3
504 | tv1(tbnd(nbnd),nbnd)=v(1)
505 | tv2(tbnd(nbnd),nbnd)=v(2)
506 | i2 = i2 + 1
507 |
508 | else
509 |
510 | write(*,*)'internal error 3'
511 |
512 | endif
513 |
514 | end do
515 |
516 | read(IOgmsh,*) c_input1
517 | call check_input_character(c_input1,'$EndElements')
518 | !------------------------------------------------------------
519 | ! write out points
520 | !------------------------------------------------------------
521 | write(IOcel,91) n_nodes
522 | 91 format('NPOIN= ',i10)
523 |
524 | do iloop=1,n_nodes
525 | write(IOcel,'(3g16.9,6x,i9)') (node(iloop,i),i=1,3),iloop-1
526 | enddo
527 |
528 | write(IOcel,111) n_names-1
529 | 111 format('NMARK= ',i10)
530 | do j=1,n_names-1
531 | write(IOcel,141) mytags(j)
532 | write(IOcel,151) tbnd(j)
533 | do i=1,tbnd(j)
534 | if (tv0(i,j)==5) then
535 | write(IOcel,*) tv0(i,j), tv1(i,j),tv2(i,j),tv3(i,j)
536 | endif
537 | 201 format(1x, i10,3f15.6)
538 | if (tv0(i,j)==8) then
539 | write(IOcel,*) tv0(i,j), tv1(i,j),tv2(i,j),tv3(i,j),tv4(i,j)
540 | endif
541 | 211 format(1x, i10,4f15.6)
542 |
543 | enddo
544 | end do
545 | 141 format('MARKER_TAG= ',i3)
546 | 151 format('MARKER_ELEMS= ', i10)
547 | close(IOcel)
548 |
549 |
550 | if( i3 > 0 ) write(*,*) 'Triangle boundaries: ',i3
551 | if( i4q > 0 ) write(*,*) 'Quad boundaries: ',i4q
552 | if( i4 > 0 ) write(*,*) 'Tetrahedral cells: ',i4
553 | if( i5 > 0 ) write(*,*) 'Pyramid cells: ',i5
554 | if( i6 > 0 ) write(*,*) 'Prism cells: ',i6
555 | if( i8 > 0 ) write(*,*) 'Hexahedral cells: ',i8
556 |
557 | !------------------------------------------------------------
558 | ! finally write out the boundary names
559 | !------------------------------------------------------------
560 | do i=1,n_Names
561 | if (Names(i)=='INLET') then
562 | Ninlet=Ninlet+1
563 | endif
564 | if (Names(i)=='OUTLET') then
565 | Noutlet=Noutlet+1
566 | endif
567 | enddo
568 | Nsurface=N_names-Ninlet-Noutlet-1
569 |
570 | write(*,*) 'Writing the .inp file'
571 | call openfile(IOinp,casename,'_inp.txt','FORMATTED','UNKNOWN',debug)
572 |
573 | write(IOinp,'('''')')
574 | write(IOinp,'(''% -------------------- BOUNDARY CONDITION DEFINITION --------------------------%'')')
575 | write(IOinp,'(''%'')')
576 | write(IOinp,'(''% Euler wall boundary marker(s) (NONE = no marker)'')')
577 | !write(IOinp,'(''MARKER_EULER='')') !( 3,4,5,6,7,8,9,10 )
578 | if (N_names>0) then
579 | write(IOinp,'( "MARKER_EULER=(" )',ADVANCE = "NO")
580 | do i=1,N_names
581 | if (Names(i) .ne. 'INLET' .and. Names(i) .ne. 'OUTLET' .and. Names(i) .ne. 'FLUID') then
582 | write(IOinp,'( i4 )',ADVANCE = "NO") i
583 | isur=isur+1
584 | if (isur0) then
600 | do i=1,MaxNames
601 | if (Names(i)=='INLET') then
602 | write(IOinp,'( "MARKER_INLET=(",i4,",288.6, 102010.0, 1.0, 0.0, 0.0)" )') i
603 | endif
604 | end do
605 | else
606 | write(IOinp,'(''MARKER_INLET= NONE'')')
607 | endif
608 | write(IOinp,'(''%'')')
609 | !1001 format(1x,'MARKER_INLET=(',i10,'288.6, 102010.0, 1.0, 0.0, 0.0)')
610 |
611 | write(IOinp,'(''% Outlet boundary marker(s) (NONE = no marker)'')')
612 | write(IOinp,'(''% Format: ( outlet marker, back pressure (static), ... )'')')
613 | if (Noutlet>0) then
614 | do i=1,MaxNames
615 | if (Names(i)=='OUTLET') then
616 | write(IOinp,'( "MARKER_OUTLET=(",i4,",101300.0)" )') i
617 | endif
618 | end do
619 | else
620 | write(IOinp,'(''MARKER_OUTLET= NONE'')')
621 | endif
622 | write(IOinp,'(''%'')')
623 |
624 | write(IOinp,'(''% Marker(s) of the surface to be plotted or designed'')')
625 | write(IOinp,'( ''MARKER_PLOTTING=(4,5)'' )') ! ( 5,4 )
626 | write(IOinp,'(''%'')')
627 |
628 | write(IOinp,'(''% Marker(s) of the surface where the functional (Cd, Cl, etc.) will be evaluated'')')
629 | write(IOinp,'( ''MARKER_MONITORING=(4,5)'' )') ! ( 5, 4 )
630 | write(IOinp,'('''')')
631 |
632 | !do i=1,MaxNames
633 | ! if( Boundary(i) )then
634 | ! if( i <= 9 )then
635 | ! write(IOinp,'(''rname,'',i1,'','',A64)') i,Names(i)
636 | ! elseif( i <= 99 )then
637 | ! write(IOinp,'(''rname,'',i2,'','',A64)') i,Names(i)
638 | ! elseif( i <= 999 )then
639 | ! write(IOinp,'(''rname,'',i3,'','',A64)') i,Names(i)
640 | ! elseif( i <= 9999 )then
641 | ! write(IOinp,'(''rname,'',i4,'','',A64)') i,Names(i)
642 | ! elseif( i <= 99999 )then
643 | ! write(IOinp,'(''rname,'',i5,'','',A64)') i,Names(i)
644 | ! else
645 | ! write(IOinp,'(''rname,'',i6,'','',A64)') i,Names(i)
646 | ! endif
647 | ! endif
648 | ! end do
649 |
650 | close(IOinp)
651 |
652 | write(*,*) 'Done gmsh2su2'
653 |
654 | contains
655 | !------------------------------------------------------------------------------------
656 | subroutine check_input_character(c1,c2)
657 |
658 | implicit none
659 |
660 | character (len=*) :: c1, c2
661 |
662 | if( c1(1:len(c2)) /= c2 )then
663 | write(*,*) 'error reading Gmsh input file: ',&
664 | 'the following two characters should be the ',&
665 | 'same but differ ',c1(1:len(c2)),c2
666 | stop
667 | endif
668 |
669 | end subroutine
670 | subroutine check_element_type(ielement_type,element_type)
671 |
672 | implicit none
673 | integer ielement_type
674 | integer element_type(:)
675 |
676 | if( ielement_type < 0 )then
677 | write(*,*) 'error reading Gmsh file: element type must be positive'
678 | write(*,*) 'element type = ',ielement_type
679 | stop
680 | endif
681 |
682 | if( ielement_type > size(element_type) )then
683 | write(*,*) 'error reading Gmsh file: unrecognised element type'
684 | write(*,*) 'element type ',ielement_type
685 | write(*,*) 'max recognised element type ',size(element_type)
686 | stop
687 | endif
688 |
689 | end subroutine
690 | subroutine check_n_tags(ntags,itags)
691 |
692 | implicit none
693 |
694 | integer ntags
695 | integer itags(:)
696 |
697 | if( ntags > size(itags) )then
698 | write(*,*) 'error: The Gmsh file contains ',ntags,' tags per element'
699 | write(*,*) 'Gmsh2Su2 is hard-wired for a maximum of ',size(itags),&
700 | 'tags. The dimension of this array needs to be increased.'
701 | stop
702 | endif
703 |
704 | end subroutine
705 | end
706 |
707 |
--------------------------------------------------------------------------------
/Fortran/gmsh2su2_2D.f90:
--------------------------------------------------------------------------------
1 | ! ====================
2 | ! README Gmsh2SU2D ver 0.06
3 | ! ====================
4 | !
5 | ! Original version by Ceanwang@gmail.com, Jan 2012
6 | !
7 | ! Adapted from gmsh2dolfyn.f90 developed by dolfyn team.
8 | ! For dolfyn, please visit http://www.dolfyn.net/index_en.html
9 | !
10 | ! Support Gmsh 2.5.0
11 | !
12 | ! Purpose
13 | ! -------
14 | ! This Fortran95 program translates a mesh file from Gmsh (.msh) format
15 | ! to Su2 format.
16 | !
17 | ! Input and Output
18 | ! ----------------
19 | ! Input : A Gmsh .msh file (version 2.0, ascii format).
20 | ! Output: SU2 files.
21 | !
22 | ! Running the Program
23 | !--------------------
24 | ! First compile it using a Fortran95 compiler (eg g95 or gfortran).
25 | ! Run it from the command line.
26 | ! The program prompts for the name of the input file.
27 | !
28 | ! Bug reports
29 | ! -----------
30 | ! Please report bugs to ceanwang@gmail.com
31 | !
32 | ! Important note about the Gmsh msh format and Physical Groups.
33 | ! -------------------------------------------------------------
34 | ! In order to define boundary conditions, the Gmsh geometry-builder allows a
35 | ! group of faces to be assigned a common 'physical group' label. The mesh
36 | ! inherits this label, and the label is used in the .su2 file.
37 | !
38 | ! When saving the mesh, the default is to save only mesh elements with a
39 | ! physical group label. This means that some mesh elements will be missing,
40 | ! unless every mesh element belongs to a physical group.
41 | !
42 | ! For example in the adapted gmsh tutorial t2.geo enter:
43 | !
44 | ! Physical Volume ("Fluid") = {119,120};
45 | ! Physical Surface("Inlet") = {111};
46 | ! Physical Surface("Outlet") = {132};
47 | !
48 | ! Mesh 3D and save it as t2.msh
49 | !
50 | !========================================================================
51 | ! ver 0.06 Fixed rectangle element output
52 | ! Fixed MARKER_FAR output
53 | !========================================================================
54 | !========================================================================
55 | SUBROUTINE UPPERCASE(STR)
56 |
57 | IMPLICIT NONE
58 |
59 | CHARACTER(LEN=*), INTENT(IN OUT) :: STR
60 | INTEGER :: I, DEL
61 |
62 | DEL = IACHAR('a') - IACHAR('A')
63 |
64 | DO I = 1, LEN_TRIM(STR)
65 | IF (LGE(STR(I:I),'a') .AND. LLE(STR(I:I),'z')) THEN
66 | STR(I:I) = ACHAR(IACHAR(STR(I:I)) - DEL)
67 | END IF
68 | END DO
69 |
70 | RETURN
71 |
72 | END SUBROUTINE UPPERCASE
73 |
74 | integer function lens(string)
75 |
76 | character(len=*) string
77 |
78 | do i=len(string),0,-1
79 | if( string(i:i) .ne. ' ') goto 10
80 | end do
81 | i = 0
82 | 10 continue
83 |
84 | lens = i
85 |
86 | end function lens
87 | !======================================================================
88 | subroutine openfile(iunit,casename,extension,reqform,status,idebug)
89 |
90 | character(len=*) casename
91 | character(len=*) extension
92 | character(len=*) reqform
93 | character(len=*) status
94 | character(len=48) filename
95 | character(len=11) form
96 |
97 | logical exists
98 |
99 | filename = casename(1:lens(casename))//extension(1:lens(extension))
100 | length = lens(filename)
101 |
102 | if( idebug > 2 )write(*,*) 'Opening ',filename(1:length)
103 |
104 | if( status(1:3) == 'OLD' )then
105 | inquire(file=filename(1:length),exist=exists,form=form)
106 | if( .not. exists )then
107 | write(*,*) '*** Error: File ',filename(1:length),' does not exist'
108 | stop
109 | endif
110 | endif
111 |
112 | open(iunit,file=filename(1:length),form=reqform,status=status)
113 |
114 | if( idebug >= 2 ) write(*,*) 'File ',filename(1:length),' opened'
115 |
116 | end subroutine openfile
117 | !==============================================================================
118 | program gmsh2SU2
119 |
120 | implicit none
121 |
122 | integer, parameter :: IOinp = 13, IOcel = 14 ! I/O file numbers
123 | integer, parameter :: IOdbg = 63, IOcfg = 12
124 | integer, parameter :: IOgmsh= 24 !Gmsh mesh file
125 |
126 | integer :: NFluid = 0
127 | integer :: Nfarfield = 0
128 | integer :: Ninlet = 0
129 | integer :: Noutlet = 0
130 | integer :: Nsurface = 0
131 | integer :: isur = 0
132 |
133 | integer :: debug = 0
134 |
135 | integer, parameter :: version = 0530
136 |
137 | character(len=128) :: line
138 |
139 | integer, parameter :: MaxNames = 100
140 | integer, parameter :: MaxNperBnd = 500
141 | integer, parameter :: MaxNodes = 90000
142 |
143 | character(len=64), dimension(MaxNames) :: Names
144 | character(len=64), dimension(MaxNames) :: Regions
145 | integer, dimension(MaxNames) :: ICTID = -1
146 | integer, dimension(MaxNames) :: Partition= 1
147 |
148 | logical, dimension(MaxNames) :: Fluid = .false.
149 | logical, dimension(MaxNames) :: Boundary = .false.
150 |
151 | character(len=64) :: casename = 'su2'
152 | character(len=72) :: c_input1, c_input2, c_input3
153 |
154 | integer i, j, k, ie, icel, ibnd, iloop,ii
155 | integer tbnd(maxnames)
156 | integer nbnd
157 | !
158 | ! nodes/vertices
159 | !
160 | integer n_nodes,inode
161 | real node(MaxNodes,3)
162 | integer mytags(MaxNames)
163 | integer tv0(MaxNperBnd,MaxNames)
164 | integer tv1(MaxNperBnd,MaxNames)
165 | integer tv2(MaxNperBnd,MaxNames)
166 | integer tv3(MaxNperBnd,MaxNames)
167 | integer tv4(MaxNperBnd,MaxNames)
168 |
169 | !
170 | ! there are 19 gmsh element types: \
171 | !
172 | ! 1 : 2-node line
173 | ! 2 : 3-node triangle (face)
174 | ! 3 : 4-node quadrangle (face)
175 | ! 4 : 4-node tetrahedron
176 | ! 5 : 8-node hexahedron (eg cube)
177 | ! 6 : 6-node triangular-prism
178 | ! 7 : 5-node pyramid
179 | !
180 | ! 8-14: 'second-order' elements. Ref Gmsh manual.
181 | ! 15 : 1-node point
182 | ! 16-19: more second-order FEM elements
183 | !
184 | ! the nodes/vertices for each element are read into the
185 | ! v array.
186 | !
187 | ! each element can have several tags.
188 | ! the first tag gives the physical_group number.
189 | ! all elements on the same boundary have the same physical_group number.
190 | !
191 | integer, parameter :: element_type(19) = &
192 | (/ 2,3,4,4,8,6,5,3,6,9,10,27,18,14,1,8,20,15,13 /)
193 |
194 | integer :: n_elements, ielement, ielement_type, n_tags, n_names, lens
195 | integer :: tags(64), v(27)
196 | integer :: bmarknew,bmarkold
197 | integer :: i3, i4q, i4, i5, i6, i8
198 | integer :: i2
199 | integer :: ivs = 0
200 |
201 |
202 |
203 | if( size(v) /= maxval(element_type) )then
204 | stop'bug: error in dimensions of array v'
205 | endif
206 |
207 | !
208 | ! read the gmsh filename, then open the .msh file
209 | !
210 | write(*,*) 'Gmsh2SU2: Converts a Gmsh mesh file to SU2 format.'
211 | write(*,*) '(Input must be in Gmsh version 2.0 ascii format.'
212 | write(*,*) ' Output is in SU2 format.)'
213 | write(*,*) ' '
214 | write(*,*) 'Input Gmsh filename, excluding the .msh suffix'
215 | read(*,'(A)') casename
216 |
217 | write(*,*) 'Opening the Gmsh file'
218 | call openfile(IOgmsh,casename,'.msh','FORMATTED','OLD',debug)
219 |
220 | !
221 | ! read the Gmsh file header
222 | !
223 | write(*,*)'Reading MeshFormat'
224 | read(IOgmsh,*) c_input1
225 | call check_input_character(c_input1,'$MeshFormat')
226 |
227 | read(IOgmsh,*) c_input1,c_input2,c_input3
228 | if( c_input1 == '2.2' )then
229 | ivs = 22
230 | else if( c_input1 == '2.1' )then
231 | ivs = 21
232 | else if( c_input1 == '2' )then
233 | ivs = 20
234 | else
235 | write(*,*) '*** WARNING: unknown Gmsh version'
236 | write(*,*) '*** Unexpected results might happen'
237 | ivs = 21
238 | endif
239 |
240 | if( ivs == 20 )then
241 | call check_input_character(c_input1,'2')
242 | else if( ivs == 21 )then
243 | call check_input_character(c_input1,'2.1')
244 | else if( ivs == 22 )then
245 | call check_input_character(c_input1,'2.2')
246 | else
247 | write(*,*) '*** Version found ',c_input1
248 | endif
249 |
250 | call check_input_character(c_input2,'0')
251 | call check_input_character(c_input3,'8')
252 |
253 | write(*,*) 'MeshFormat: ', c_input1(1:lens(c_input1)),' ', &
254 | c_input2(1:lens(c_input2)),' ', &
255 | c_input3(1:lens(c_input3))
256 |
257 | read(IOgmsh,*) c_input1
258 | call check_input_character(c_input1,'$EndMeshFormat')
259 |
260 | !
261 | ! read the Gmsh PhysicalNames
262 | !
263 | write(*,*)''
264 | write(*,*)'Reading PhysicalNames'
265 | read(IOgmsh,*) c_input1
266 | call check_input_character(c_input1,'$PhysicalNames')
267 |
268 | read(IOgmsh,*) n_names
269 | if( n_names <= 0 )then
270 | write(*,*) 'error: number of names must be a positive number'
271 | stop
272 | endif
273 |
274 | if( ivs == 20 )then
275 | do i=1,n_names
276 | !read(IOgmsh,*) k,j,c_input1
277 | read(IOgmsh,*) j,c_input1
278 | write(*,*) 'Name ',j,'-> ', c_input1
279 | Names(j) = c_input1
280 | end do
281 | else if( ivs == 21 )then
282 | do i=1,n_names
283 | read(IOgmsh,*) k,j,c_input1
284 | write(*,*) 'Name ',j,'-> ', c_input1
285 | Names(j) = c_input1
286 | end do
287 | else
288 | do i=1,n_names
289 | read(IOgmsh,*) k,j,c_input1
290 | write(*,*) 'Name ',j,'-> ', c_input1
291 | Names(j) = c_input1
292 | end do
293 | endif
294 |
295 | do i=1,n_names
296 | CALL UPPERCASE(Names(i))
297 | enddo
298 |
299 | read(IOgmsh,*) c_input1
300 | call check_input_character(c_input1,'$EndPhysicalNames')
301 | !
302 | ! read the nodes from the .msh file and write them
303 | ! to the .vrt file.
304 | !
305 | write(*,*)'Reading Nodes'
306 | read(IOgmsh,*) c_input1
307 | call check_input_character(c_input1,'$Nodes')
308 | !nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
309 | read(IOgmsh,*) n_nodes
310 | if( n_nodes <= 0 )then
311 | write(*,*) 'error: number of nodes must be a positive number'
312 | stop
313 | endif
314 |
315 | if( n_nodes > MaxNodes )then
316 | write(*,*) 'error: The Gmsh file contains ',n_nodes,' nodes.'
317 | write(*,*) 'Gmsh2Su2 is hard-wired for a maximum of ',MaxNodes,&
318 | 'nodes. The dimension of this array needs to be increased.'
319 | stop
320 | endif
321 |
322 | !
323 | ! open the su2 .vrt.su2 file
324 | !
325 | !write(*,*) 'Creating the su2 .vrt.su2 file'
326 | !call openfile(IOvrt,casename,'.vrt.su2','FORMATTED','UNKNOWN',debug)
327 |
328 | nodes: do iloop=1,n_nodes
329 | read(IOgmsh,*) inode,(node(iloop,i), i=1,3)
330 | !write(IOvrt,'(3g16.9,6x,i9)') (node(iloop,i),i=1,3),inode-1
331 | enddo nodes
332 |
333 | write(*,*) 'Nodes written ',n_nodes
334 | !
335 | ! close the su2 .vrt.su2 file
336 | !
337 | !close(IOvrt)
338 |
339 | read(IOgmsh,*) c_input1
340 | call check_input_character(c_input1,'$EndNodes')
341 | !eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
342 | !
343 | ! read the elements from the .msh file and write them
344 | ! to the .cel and .bnd files.
345 | !
346 | read(IOgmsh,*) c_input1
347 | call check_input_character(c_input1,'$Elements')
348 |
349 | read(IOgmsh,*) n_elements
350 | if( n_elements <= 0 )then
351 | write(*,*) 'error: number of elements must be a positive number'
352 | stop
353 | endif
354 |
355 | write(*,*) 'Total Gmsh elements to be read in:',n_elements
356 | !
357 | ! open the su2 .cel files
358 | !
359 | write(*,*) ''
360 | write(*,*) 'Creating the .su2 files'
361 | call openfile(IOcel,casename,'.su2','FORMATTED','UNKNOWN',debug)
362 | write(IOcel,101) 2
363 | 101 format('NDIME= ',i1)
364 |
365 |
366 | !
367 | ! note in Gmsh fluid cells and boudaries can be mixed
368 | ! we just keep track on them both
369 | ! remind default region is not assigned
370 | !
371 | icel = 0
372 | ibnd = 0
373 | nbnd=0
374 | tbnd(nbnd)=0
375 |
376 | i2 = 0
377 | i3 = 0
378 | i4q = 0
379 | i4 = 0
380 | i5 = 0
381 | i6 = 0
382 | i8 = 0
383 |
384 | bmarkOld=0
385 | do ie=1,n_elements
386 |
387 | read(IOgmsh,*) ielement, ielement_type, n_tags
388 | if( ivs <= 21 )then
389 | if( n_tags /= 3 ) write(*,*) 'tag error n_tags /= 3:',ielement,n_tags
390 | else
391 | if( n_tags /= 2 ) write(*,*) 'tag error n_tags /= 2:',ielement,n_tags
392 | endif
393 | call check_element_type(ielement_type,element_type)
394 | call check_n_tags(n_tags,tags)
395 | backspace(IOgmsh)
396 |
397 | !
398 | ! we need to circumvent backspace but
399 | ! advance='no' requires fixed format
400 | ! just keep it for now.
401 | !
402 |
403 | !
404 | ! now we know what to to expect to find on the line
405 | !
406 | !write (*,*) element_type(ielement_type)
407 | read(IOgmsh,*) ielement, ielement_type, &
408 | n_tags, (tags(i),i=1,n_tags),&
409 | (v(i),i=1,element_type(ielement_type))
410 |
411 | do ii=1,element_type(ielement_type)
412 | v(ii)=v(ii)-1
413 | end do
414 |
415 | bmarkNew=tags(1)
416 | if( 2 <= ielement_type .and. ielement_type <= 3 )then
417 | if (icel==0) then
418 | write(IOcel,121) n_elements-ibnd
419 | 121 format('NELEM= ',i10)
420 | endif
421 | icel = icel + 1
422 |
423 | if( .not. Fluid(tags(1)) ) Fluid(tags(1)) = .true.
424 | if( Boundary(tags(1)) )then
425 | write(*,*) 'Inconsistent data: Physical names ids overlap 1'
426 | endif
427 |
428 | 1 format(i8,8(1x,i8),2(1x,i4))
429 | select case(ielement_type)
430 |
431 | case(2) ! 3-node tri
432 |
433 | write(IOcel,*) 5, v(1),v(2),v(3),icel-1
434 | i3 = i3 + 1
435 |
436 | case(3) ! 4-node quad
437 |
438 | write(IOcel,*) 9,v(1),v(2),v(3),v(4),icel-1
439 | i4q = i4q + 1
440 |
441 | case default
442 |
443 | write(*,*)'internal error 1'
444 |
445 | end select
446 |
447 | elseif( ielement_type == 1 )then
448 |
449 | if (bmarkNew/=bmarkOld) then
450 | bmarkOld=bmarkNew
451 | nbnd=nbnd+1
452 | tbnd(nbnd)=0
453 | endif
454 |
455 | ibnd = ibnd + 1
456 | tbnd(nbnd) = tbnd(nbnd) + 1
457 |
458 | if( .not. Boundary(tags(1)) ) Boundary(tags(1)) = .true.
459 | if( Fluid(tags(1)) )then
460 | write(*,*) 'Inconsistent data: Physical names ids overlap 2'
461 | endif
462 |
463 | !write(IObnd,*) 3, v(1),v(2)
464 | mytags(nbnd)=tags(1)
465 | tv0(tbnd(nbnd),nbnd)=3
466 | tv1(tbnd(nbnd),nbnd)=v(1)
467 | tv2(tbnd(nbnd),nbnd)=v(2)
468 | i2 = i2 + 1
469 |
470 | else
471 |
472 | write(*,*)'internal error 3'
473 |
474 | endif
475 |
476 | end do
477 |
478 | read(IOgmsh,*) c_input1
479 | call check_input_character(c_input1,'$EndElements')
480 | !------------------------------------------------------------
481 | ! write out points
482 | !------------------------------------------------------------
483 | write(IOcel,91) n_nodes
484 | 91 format('NPOIN= ',i10)
485 |
486 | do iloop=1,n_nodes
487 | write(IOcel,'(3g16.9,6x,i9)') (node(iloop,i),i=1,2),iloop-1
488 | enddo
489 | !------------------------------------------------------------
490 | ! write out markers
491 | !------------------------------------------------------------
492 | write(IOcel,111) n_names-1
493 | 111 format('NMARK= ',i10)
494 | do j=1,n_names-1
495 | write(IOcel,141) mytags(j)
496 | write(IOcel,151) tbnd(j)
497 | do i=1,tbnd(j)
498 | if (tv0(i,j)==3) then
499 | write(IOcel,*) tv0(i,j),tv1(i,j),tv2(i,j)
500 | endif
501 | enddo
502 | end do
503 | 141 format('MARKER_TAG= ',i3)
504 | 151 format('MARKER_ELEMS= ', i10)
505 | close(IOcel)
506 |
507 |
508 | if( i3 > 0 ) write(*,*) 'Triangle boundaries: ',i3
509 | if( i4q > 0 ) write(*,*) 'Quad boundaries: ',i4q
510 | if( i4 > 0 ) write(*,*) 'Tetrahedral cells: ',i4
511 | if( i5 > 0 ) write(*,*) 'Pyramid cells: ',i5
512 | if( i6 > 0 ) write(*,*) 'Prism cells: ',i6
513 | if( i8 > 0 ) write(*,*) 'Hexahedral cells: ',i8
514 |
515 | write(*,*) 'Done su2 file.'
516 |
517 | !------------------------------------------------------------
518 | ! finally write out the boundary names
519 | !------------------------------------------------------------
520 | do i=1,n_Names
521 | if (Names(i)=='INLET') then
522 | Ninlet=Ninlet+1
523 | endif
524 | if (Names(i)=='OUTLET') then
525 | Noutlet=Noutlet+1
526 | endif
527 | if (Names(i)=='FARFIELD') then
528 | Nfarfield=Nfarfield+1
529 | endif
530 | if (Names(i)=='FLUID') then
531 | Nfluid=Nfluid+1
532 | endif
533 | enddo
534 | Nsurface=N_names-Ninlet-Noutlet-Nfarfield-1
535 | !------------------------------------------------------------------------------------
536 | ! Write out the .inp file
537 | !------------------------------------------------------------------------------------
538 | write(*,*) ''
539 | write(*,*) 'Writing the .inp file'
540 | call openfile(IOinp,casename,'_inp.txt','FORMATTED','UNKNOWN',debug)
541 |
542 | write(IOinp,'('''')')
543 | write(IOinp,'(''% -------------------- BOUNDARY CONDITION DEFINITION --------------------------%'')')
544 | write(IOinp,'(''%'')')
545 | write(IOinp,'(''% Euler wall boundary marker(s) (NONE = no marker)'')')
546 | !write(IOinp,'(''MARKER_EULER='')') !( 3,4,5,6,7,8,9,10 )
547 | if (N_names>0) then
548 | write(IOinp,'( "MARKER_EULER=(" )',ADVANCE = "NO")
549 | do i=1,N_names
550 | if (Names(i) .ne. 'INLET' .and. Names(i) .ne. 'OUTLET' .and. Names(i) .ne. 'FLUID'.and. Names(i) .ne. 'FARFIELD') then
551 | write(IOinp,'( i4 )',ADVANCE = "NO") i
552 | isur=isur+1
553 | if (isur0) then
568 | do i=1,MaxNames
569 | if (Names(i)=='FARFIELD') then
570 | write(IOinp,'( "MARKER_FAR=(",i4,")" )') i
571 | endif
572 | end do
573 | write(*,*) Nfarfield,'Farfield.'
574 | else
575 | write(IOinp,'(''MARKER_FAR= NONE'')')
576 | write(*,*) 'No farfield.'
577 | endif
578 | write(IOinp,'(''%'')')
579 |
580 | write(IOinp,'(''% Inlet boundary marker(s) (NONE = no marker) '')')
581 | write(IOinp,'(''% Format: ( inlet marker, total temperature, total pressure, flow_direction_x, '')')
582 | write(IOinp,'(''% flow_direction_y, flow_direction_z, ... ) where flow_direction is'')')
583 | write(IOinp,'(''% a unit vector.'')')
584 | if (Ninlet>0) then
585 | do i=1,MaxNames
586 | if (Names(i)=='INLET') then
587 | write(IOinp,'( "MARKER_INLET=(",i4,",288.6, 102010.0, 1.0, 0.0, 0.0)" )') i
588 | endif
589 | end do
590 | write(*,*) Ninlet,'Inlet.'
591 | else
592 | write(IOinp,'(''MARKER_INLET= NONE'')')
593 | write(*,*) 'No inlet.'
594 | endif
595 | write(IOinp,'(''%'')')
596 | !1001 format(1x,'MARKER_INLET=(',i10,'288.6, 102010.0, 1.0, 0.0, 0.0)')
597 |
598 | write(IOinp,'(''% Outlet boundary marker(s) (NONE = no marker)'')')
599 | write(IOinp,'(''% Format: ( outlet marker, back pressure (static), ... )'')')
600 | if (Noutlet>0) then
601 | do i=1,MaxNames
602 | if (Names(i)=='OUTLET') then
603 | write(IOinp,'( "MARKER_OUTLET=(",i4,",101300.0)" )') i
604 | endif
605 | end do
606 | write(*,*) Noutlet,'Outlet.'
607 | else
608 | write(IOinp,'(''MARKER_OUTLET= NONE'')')
609 | write(*,*) 'No outlet.'
610 | endif
611 | write(IOinp,'(''%'')')
612 |
613 | write(IOinp,'(''% Marker(s) of the surface to be plotted or designed'')')
614 | write(IOinp,'( ''MARKER_PLOTTING=(4,5)'' )') ! ( 5,4 )
615 | write(IOinp,'(''%'')')
616 |
617 | write(IOinp,'(''% Marker(s) of the surface where the functional (Cd, Cl, etc.) will be evaluated'')')
618 | write(IOinp,'( ''MARKER_MONITORING=(4,5)'' )') ! ( 5, 4 )
619 | write(IOinp,'('''')')
620 |
621 | if (Nfluid>0) then
622 | write(*,*) Nfluid,'Fluid.'
623 | else
624 | write(*,*) 'Error: No fluid. One 2D physical surface must be FLUID.'
625 | endif
626 | write(IOinp,'(''%'')')
627 |
628 | !do i=1,MaxNames
629 | ! if( Boundary(i) )then
630 | ! if( i <= 9 )then
631 | ! write(IOinp,'(''rname,'',i1,'','',A64)') i,Names(i)
632 | ! elseif( i <= 99 )then
633 | ! write(IOinp,'(''rname,'',i2,'','',A64)') i,Names(i)
634 | ! elseif( i <= 999 )then
635 | ! write(IOinp,'(''rname,'',i3,'','',A64)') i,Names(i)
636 | ! elseif( i <= 9999 )then
637 | ! write(IOinp,'(''rname,'',i4,'','',A64)') i,Names(i)
638 | ! elseif( i <= 99999 )then
639 | ! write(IOinp,'(''rname,'',i5,'','',A64)') i,Names(i)
640 | ! else
641 | ! write(IOinp,'(''rname,'',i6,'','',A64)') i,Names(i)
642 | ! endif
643 | ! endif
644 | ! end do
645 |
646 | close(IOinp)
647 | write(*,*) 'Done .inp file'
648 |
649 | write(*,*) ''
650 | write(*,*) 'Done gmsh2su2'
651 |
652 |
653 |
654 | contains
655 | !------------------------------------------------------------------------------------
656 | !
657 | !------------------------------------------------------------------------------------
658 | subroutine check_input_character(c1,c2)
659 |
660 | implicit none
661 |
662 | character (len=*) :: c1, c2
663 |
664 | if( c1(1:len(c2)) /= c2 )then
665 | write(*,*) 'error reading Gmsh input file: ',&
666 | 'the following two characters should be the ',&
667 | 'same but differ ',c1(1:len(c2)),c2
668 | stop
669 | endif
670 |
671 | end subroutine
672 | !------------------------------------------------------------------------------------
673 | !
674 | !------------------------------------------------------------------------------------
675 | subroutine check_element_type(ielement_type,element_type)
676 |
677 | implicit none
678 | integer ielement_type
679 | integer element_type(:)
680 |
681 | if( ielement_type < 0 )then
682 | write(*,*) 'error reading Gmsh file: element type must be positive'
683 | write(*,*) 'element type = ',ielement_type
684 | stop
685 | endif
686 |
687 | if( ielement_type > size(element_type) )then
688 | write(*,*) 'error reading Gmsh file: unrecognised element type'
689 | write(*,*) 'element type ',ielement_type
690 | write(*,*) 'max recognised element type ',size(element_type)
691 | stop
692 | endif
693 |
694 | end subroutine
695 | !------------------------------------------------------------------------------------
696 | !
697 | !------------------------------------------------------------------------------------
698 | subroutine check_n_tags(ntags,itags)
699 |
700 | implicit none
701 |
702 | integer ntags
703 | integer itags(:)
704 |
705 | if( ntags > size(itags) )then
706 | write(*,*) 'error: The Gmsh file contains ',ntags,' tags per element'
707 | write(*,*) 'Gmsh2Su2 is hard-wired for a maximum of ',size(itags),&
708 | 'tags. The dimension of this array needs to be increased.'
709 | stop
710 | endif
711 |
712 | end subroutine
713 | end
714 |
715 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 2.1, February 1999
3 |
4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | [This is the first released version of the Lesser GPL. It also counts
10 | as the successor of the GNU Library Public License, version 2, hence
11 | the version number 2.1.]
12 |
13 | Preamble
14 |
15 | The licenses for most software are designed to take away your
16 | freedom to share and change it. By contrast, the GNU General Public
17 | Licenses are intended to guarantee your freedom to share and change
18 | free software--to make sure the software is free for all its users.
19 |
20 | This license, the Lesser General Public License, applies to some
21 | specially designated software packages--typically libraries--of the
22 | Free Software Foundation and other authors who decide to use it. You
23 | can use it too, but we suggest you first think carefully about whether
24 | this license or the ordinary General Public License is the better
25 | strategy to use in any particular case, based on the explanations below.
26 |
27 | When we speak of free software, we are referring to freedom of use,
28 | not price. Our General Public Licenses are designed to make sure that
29 | you have the freedom to distribute copies of free software (and charge
30 | for this service if you wish); that you receive source code or can get
31 | it if you want it; that you can change the software and use pieces of
32 | it in new free programs; and that you are informed that you can do
33 | these things.
34 |
35 | To protect your rights, we need to make restrictions that forbid
36 | distributors to deny you these rights or to ask you to surrender these
37 | rights. These restrictions translate to certain responsibilities for
38 | you if you distribute copies of the library or if you modify it.
39 |
40 | For example, if you distribute copies of the library, whether gratis
41 | or for a fee, you must give the recipients all the rights that we gave
42 | you. You must make sure that they, too, receive or can get the source
43 | code. If you link other code with the library, you must provide
44 | complete object files to the recipients, so that they can relink them
45 | with the library after making changes to the library and recompiling
46 | it. And you must show them these terms so they know their rights.
47 |
48 | We protect your rights with a two-step method: (1) we copyright the
49 | library, and (2) we offer you this license, which gives you legal
50 | permission to copy, distribute and/or modify the library.
51 |
52 | To protect each distributor, we want to make it very clear that
53 | there is no warranty for the free library. Also, if the library is
54 | modified by someone else and passed on, the recipients should know
55 | that what they have is not the original version, so that the original
56 | author's reputation will not be affected by problems that might be
57 | introduced by others.
58 |
59 | Finally, software patents pose a constant threat to the existence of
60 | any free program. We wish to make sure that a company cannot
61 | effectively restrict the users of a free program by obtaining a
62 | restrictive license from a patent holder. Therefore, we insist that
63 | any patent license obtained for a version of the library must be
64 | consistent with the full freedom of use specified in this license.
65 |
66 | Most GNU software, including some libraries, is covered by the
67 | ordinary GNU General Public License. This license, the GNU Lesser
68 | General Public License, applies to certain designated libraries, and
69 | is quite different from the ordinary General Public License. We use
70 | this license for certain libraries in order to permit linking those
71 | libraries into non-free programs.
72 |
73 | When a program is linked with a library, whether statically or using
74 | a shared library, the combination of the two is legally speaking a
75 | combined work, a derivative of the original library. The ordinary
76 | General Public License therefore permits such linking only if the
77 | entire combination fits its criteria of freedom. The Lesser General
78 | Public License permits more lax criteria for linking other code with
79 | the library.
80 |
81 | We call this license the "Lesser" General Public License because it
82 | does Less to protect the user's freedom than the ordinary General
83 | Public License. It also provides other free software developers Less
84 | of an advantage over competing non-free programs. These disadvantages
85 | are the reason we use the ordinary General Public License for many
86 | libraries. However, the Lesser license provides advantages in certain
87 | special circumstances.
88 |
89 | For example, on rare occasions, there may be a special need to
90 | encourage the widest possible use of a certain library, so that it becomes
91 | a de-facto standard. To achieve this, non-free programs must be
92 | allowed to use the library. A more frequent case is that a free
93 | library does the same job as widely used non-free libraries. In this
94 | case, there is little to gain by limiting the free library to free
95 | software only, so we use the Lesser General Public License.
96 |
97 | In other cases, permission to use a particular library in non-free
98 | programs enables a greater number of people to use a large body of
99 | free software. For example, permission to use the GNU C Library in
100 | non-free programs enables many more people to use the whole GNU
101 | operating system, as well as its variant, the GNU/Linux operating
102 | system.
103 |
104 | Although the Lesser General Public License is Less protective of the
105 | users' freedom, it does ensure that the user of a program that is
106 | linked with the Library has the freedom and the wherewithal to run
107 | that program using a modified version of the Library.
108 |
109 | The precise terms and conditions for copying, distribution and
110 | modification follow. Pay close attention to the difference between a
111 | "work based on the library" and a "work that uses the library". The
112 | former contains code derived from the library, whereas the latter must
113 | be combined with the library in order to run.
114 |
115 | GNU LESSER GENERAL PUBLIC LICENSE
116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117 |
118 | 0. This License Agreement applies to any software library or other
119 | program which contains a notice placed by the copyright holder or
120 | other authorized party saying it may be distributed under the terms of
121 | this Lesser General Public License (also called "this License").
122 | Each licensee is addressed as "you".
123 |
124 | A "library" means a collection of software functions and/or data
125 | prepared so as to be conveniently linked with application programs
126 | (which use some of those functions and data) to form executables.
127 |
128 | The "Library", below, refers to any such software library or work
129 | which has been distributed under these terms. A "work based on the
130 | Library" means either the Library or any derivative work under
131 | copyright law: that is to say, a work containing the Library or a
132 | portion of it, either verbatim or with modifications and/or translated
133 | straightforwardly into another language. (Hereinafter, translation is
134 | included without limitation in the term "modification".)
135 |
136 | "Source code" for a work means the preferred form of the work for
137 | making modifications to it. For a library, complete source code means
138 | all the source code for all modules it contains, plus any associated
139 | interface definition files, plus the scripts used to control compilation
140 | and installation of the library.
141 |
142 | Activities other than copying, distribution and modification are not
143 | covered by this License; they are outside its scope. The act of
144 | running a program using the Library is not restricted, and output from
145 | such a program is covered only if its contents constitute a work based
146 | on the Library (independent of the use of the Library in a tool for
147 | writing it). Whether that is true depends on what the Library does
148 | and what the program that uses the Library does.
149 |
150 | 1. You may copy and distribute verbatim copies of the Library's
151 | complete source code as you receive it, in any medium, provided that
152 | you conspicuously and appropriately publish on each copy an
153 | appropriate copyright notice and disclaimer of warranty; keep intact
154 | all the notices that refer to this License and to the absence of any
155 | warranty; and distribute a copy of this License along with the
156 | Library.
157 |
158 | You may charge a fee for the physical act of transferring a copy,
159 | and you may at your option offer warranty protection in exchange for a
160 | fee.
161 |
162 | 2. You may modify your copy or copies of the Library or any portion
163 | of it, thus forming a work based on the Library, and copy and
164 | distribute such modifications or work under the terms of Section 1
165 | above, provided that you also meet all of these conditions:
166 |
167 | a) The modified work must itself be a software library.
168 |
169 | b) You must cause the files modified to carry prominent notices
170 | stating that you changed the files and the date of any change.
171 |
172 | c) You must cause the whole of the work to be licensed at no
173 | charge to all third parties under the terms of this License.
174 |
175 | d) If a facility in the modified Library refers to a function or a
176 | table of data to be supplied by an application program that uses
177 | the facility, other than as an argument passed when the facility
178 | is invoked, then you must make a good faith effort to ensure that,
179 | in the event an application does not supply such function or
180 | table, the facility still operates, and performs whatever part of
181 | its purpose remains meaningful.
182 |
183 | (For example, a function in a library to compute square roots has
184 | a purpose that is entirely well-defined independent of the
185 | application. Therefore, Subsection 2d requires that any
186 | application-supplied function or table used by this function must
187 | be optional: if the application does not supply it, the square
188 | root function must still compute square roots.)
189 |
190 | These requirements apply to the modified work as a whole. If
191 | identifiable sections of that work are not derived from the Library,
192 | and can be reasonably considered independent and separate works in
193 | themselves, then this License, and its terms, do not apply to those
194 | sections when you distribute them as separate works. But when you
195 | distribute the same sections as part of a whole which is a work based
196 | on the Library, the distribution of the whole must be on the terms of
197 | this License, whose permissions for other licensees extend to the
198 | entire whole, and thus to each and every part regardless of who wrote
199 | it.
200 |
201 | Thus, it is not the intent of this section to claim rights or contest
202 | your rights to work written entirely by you; rather, the intent is to
203 | exercise the right to control the distribution of derivative or
204 | collective works based on the Library.
205 |
206 | In addition, mere aggregation of another work not based on the Library
207 | with the Library (or with a work based on the Library) on a volume of
208 | a storage or distribution medium does not bring the other work under
209 | the scope of this License.
210 |
211 | 3. You may opt to apply the terms of the ordinary GNU General Public
212 | License instead of this License to a given copy of the Library. To do
213 | this, you must alter all the notices that refer to this License, so
214 | that they refer to the ordinary GNU General Public License, version 2,
215 | instead of to this License. (If a newer version than version 2 of the
216 | ordinary GNU General Public License has appeared, then you can specify
217 | that version instead if you wish.) Do not make any other change in
218 | these notices.
219 |
220 | Once this change is made in a given copy, it is irreversible for
221 | that copy, so the ordinary GNU General Public License applies to all
222 | subsequent copies and derivative works made from that copy.
223 |
224 | This option is useful when you wish to copy part of the code of
225 | the Library into a program that is not a library.
226 |
227 | 4. You may copy and distribute the Library (or a portion or
228 | derivative of it, under Section 2) in object code or executable form
229 | under the terms of Sections 1 and 2 above provided that you accompany
230 | it with the complete corresponding machine-readable source code, which
231 | must be distributed under the terms of Sections 1 and 2 above on a
232 | medium customarily used for software interchange.
233 |
234 | If distribution of object code is made by offering access to copy
235 | from a designated place, then offering equivalent access to copy the
236 | source code from the same place satisfies the requirement to
237 | distribute the source code, even though third parties are not
238 | compelled to copy the source along with the object code.
239 |
240 | 5. A program that contains no derivative of any portion of the
241 | Library, but is designed to work with the Library by being compiled or
242 | linked with it, is called a "work that uses the Library". Such a
243 | work, in isolation, is not a derivative work of the Library, and
244 | therefore falls outside the scope of this License.
245 |
246 | However, linking a "work that uses the Library" with the Library
247 | creates an executable that is a derivative of the Library (because it
248 | contains portions of the Library), rather than a "work that uses the
249 | library". The executable is therefore covered by this License.
250 | Section 6 states terms for distribution of such executables.
251 |
252 | When a "work that uses the Library" uses material from a header file
253 | that is part of the Library, the object code for the work may be a
254 | derivative work of the Library even though the source code is not.
255 | Whether this is true is especially significant if the work can be
256 | linked without the Library, or if the work is itself a library. The
257 | threshold for this to be true is not precisely defined by law.
258 |
259 | If such an object file uses only numerical parameters, data
260 | structure layouts and accessors, and small macros and small inline
261 | functions (ten lines or less in length), then the use of the object
262 | file is unrestricted, regardless of whether it is legally a derivative
263 | work. (Executables containing this object code plus portions of the
264 | Library will still fall under Section 6.)
265 |
266 | Otherwise, if the work is a derivative of the Library, you may
267 | distribute the object code for the work under the terms of Section 6.
268 | Any executables containing that work also fall under Section 6,
269 | whether or not they are linked directly with the Library itself.
270 |
271 | 6. As an exception to the Sections above, you may also combine or
272 | link a "work that uses the Library" with the Library to produce a
273 | work containing portions of the Library, and distribute that work
274 | under terms of your choice, provided that the terms permit
275 | modification of the work for the customer's own use and reverse
276 | engineering for debugging such modifications.
277 |
278 | You must give prominent notice with each copy of the work that the
279 | Library is used in it and that the Library and its use are covered by
280 | this License. You must supply a copy of this License. If the work
281 | during execution displays copyright notices, you must include the
282 | copyright notice for the Library among them, as well as a reference
283 | directing the user to the copy of this License. Also, you must do one
284 | of these things:
285 |
286 | a) Accompany the work with the complete corresponding
287 | machine-readable source code for the Library including whatever
288 | changes were used in the work (which must be distributed under
289 | Sections 1 and 2 above); and, if the work is an executable linked
290 | with the Library, with the complete machine-readable "work that
291 | uses the Library", as object code and/or source code, so that the
292 | user can modify the Library and then relink to produce a modified
293 | executable containing the modified Library. (It is understood
294 | that the user who changes the contents of definitions files in the
295 | Library will not necessarily be able to recompile the application
296 | to use the modified definitions.)
297 |
298 | b) Use a suitable shared library mechanism for linking with the
299 | Library. A suitable mechanism is one that (1) uses at run time a
300 | copy of the library already present on the user's computer system,
301 | rather than copying library functions into the executable, and (2)
302 | will operate properly with a modified version of the library, if
303 | the user installs one, as long as the modified version is
304 | interface-compatible with the version that the work was made with.
305 |
306 | c) Accompany the work with a written offer, valid for at
307 | least three years, to give the same user the materials
308 | specified in Subsection 6a, above, for a charge no more
309 | than the cost of performing this distribution.
310 |
311 | d) If distribution of the work is made by offering access to copy
312 | from a designated place, offer equivalent access to copy the above
313 | specified materials from the same place.
314 |
315 | e) Verify that the user has already received a copy of these
316 | materials or that you have already sent this user a copy.
317 |
318 | For an executable, the required form of the "work that uses the
319 | Library" must include any data and utility programs needed for
320 | reproducing the executable from it. However, as a special exception,
321 | the materials to be distributed need not include anything that is
322 | normally distributed (in either source or binary form) with the major
323 | components (compiler, kernel, and so on) of the operating system on
324 | which the executable runs, unless that component itself accompanies
325 | the executable.
326 |
327 | It may happen that this requirement contradicts the license
328 | restrictions of other proprietary libraries that do not normally
329 | accompany the operating system. Such a contradiction means you cannot
330 | use both them and the Library together in an executable that you
331 | distribute.
332 |
333 | 7. You may place library facilities that are a work based on the
334 | Library side-by-side in a single library together with other library
335 | facilities not covered by this License, and distribute such a combined
336 | library, provided that the separate distribution of the work based on
337 | the Library and of the other library facilities is otherwise
338 | permitted, and provided that you do these two things:
339 |
340 | a) Accompany the combined library with a copy of the same work
341 | based on the Library, uncombined with any other library
342 | facilities. This must be distributed under the terms of the
343 | Sections above.
344 |
345 | b) Give prominent notice with the combined library of the fact
346 | that part of it is a work based on the Library, and explaining
347 | where to find the accompanying uncombined form of the same work.
348 |
349 | 8. You may not copy, modify, sublicense, link with, or distribute
350 | the Library except as expressly provided under this License. Any
351 | attempt otherwise to copy, modify, sublicense, link with, or
352 | distribute the Library is void, and will automatically terminate your
353 | rights under this License. However, parties who have received copies,
354 | or rights, from you under this License will not have their licenses
355 | terminated so long as such parties remain in full compliance.
356 |
357 | 9. You are not required to accept this License, since you have not
358 | signed it. However, nothing else grants you permission to modify or
359 | distribute the Library or its derivative works. These actions are
360 | prohibited by law if you do not accept this License. Therefore, by
361 | modifying or distributing the Library (or any work based on the
362 | Library), you indicate your acceptance of this License to do so, and
363 | all its terms and conditions for copying, distributing or modifying
364 | the Library or works based on it.
365 |
366 | 10. Each time you redistribute the Library (or any work based on the
367 | Library), the recipient automatically receives a license from the
368 | original licensor to copy, distribute, link with or modify the Library
369 | subject to these terms and conditions. You may not impose any further
370 | restrictions on the recipients' exercise of the rights granted herein.
371 | You are not responsible for enforcing compliance by third parties with
372 | this License.
373 |
374 | 11. If, as a consequence of a court judgment or allegation of patent
375 | infringement or for any other reason (not limited to patent issues),
376 | conditions are imposed on you (whether by court order, agreement or
377 | otherwise) that contradict the conditions of this License, they do not
378 | excuse you from the conditions of this License. If you cannot
379 | distribute so as to satisfy simultaneously your obligations under this
380 | License and any other pertinent obligations, then as a consequence you
381 | may not distribute the Library at all. For example, if a patent
382 | license would not permit royalty-free redistribution of the Library by
383 | all those who receive copies directly or indirectly through you, then
384 | the only way you could satisfy both it and this License would be to
385 | refrain entirely from distribution of the Library.
386 |
387 | If any portion of this section is held invalid or unenforceable under any
388 | particular circumstance, the balance of the section is intended to apply,
389 | and the section as a whole is intended to apply in other circumstances.
390 |
391 | It is not the purpose of this section to induce you to infringe any
392 | patents or other property right claims or to contest validity of any
393 | such claims; this section has the sole purpose of protecting the
394 | integrity of the free software distribution system which is
395 | implemented by public license practices. Many people have made
396 | generous contributions to the wide range of software distributed
397 | through that system in reliance on consistent application of that
398 | system; it is up to the author/donor to decide if he or she is willing
399 | to distribute software through any other system and a licensee cannot
400 | impose that choice.
401 |
402 | This section is intended to make thoroughly clear what is believed to
403 | be a consequence of the rest of this License.
404 |
405 | 12. If the distribution and/or use of the Library is restricted in
406 | certain countries either by patents or by copyrighted interfaces, the
407 | original copyright holder who places the Library under this License may add
408 | an explicit geographical distribution limitation excluding those countries,
409 | so that distribution is permitted only in or among countries not thus
410 | excluded. In such case, this License incorporates the limitation as if
411 | written in the body of this License.
412 |
413 | 13. The Free Software Foundation may publish revised and/or new
414 | versions of the Lesser General Public License from time to time.
415 | Such new versions will be similar in spirit to the present version,
416 | but may differ in detail to address new problems or concerns.
417 |
418 | Each version is given a distinguishing version number. If the Library
419 | specifies a version number of this License which applies to it and
420 | "any later version", you have the option of following the terms and
421 | conditions either of that version or of any later version published by
422 | the Free Software Foundation. If the Library does not specify a
423 | license version number, you may choose any version ever published by
424 | the Free Software Foundation.
425 |
426 | 14. If you wish to incorporate parts of the Library into other free
427 | programs whose distribution conditions are incompatible with these,
428 | write to the author to ask for permission. For software which is
429 | copyrighted by the Free Software Foundation, write to the Free
430 | Software Foundation; we sometimes make exceptions for this. Our
431 | decision will be guided by the two goals of preserving the free status
432 | of all derivatives of our free software and of promoting the sharing
433 | and reuse of software generally.
434 |
435 | NO WARRANTY
436 |
437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446 |
447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456 | DAMAGES.
457 |
458 | END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
/SU2_PER/su2_periodic.f90:
--------------------------------------------------------------------------------
1 | program su2_periodic
2 |
3 | !-----------------------------------------------------------------------------!
4 | ! Algorith to create periodic data structure (SU2 format) !
5 | !-----------------------------------------------------------------------------!
6 | ! Author: Prof. Antonio Ghidoni !
7 | ! email: antonio.ghidoni@unibs.it !
8 | ! University of Brescia, Department of Mechanical and Industrial Engineering !
9 | !-----------------------------------------------------------------------------!
10 |
11 | implicit none
12 |
13 | character(30) :: rmesh, wmesh
14 | integer(4), allocatable :: ne(:), np(:), nmark(:), nb(:,:)
15 | integer(4), allocatable :: neg(:), npg(:), nmarkg(:), nbg(:,:)
16 | integer(4) :: nf, nd, nperio, id2np(15)
17 |
18 | ! Grid arrays
19 | real(8), allocatable :: xp(:,:,:)
20 | real(8), allocatable :: xpg(:,:,:)
21 | integer(4), allocatable :: s2p(:,:,:), topo(:,:), b2p(:,:,:,:), npp2(:), &
22 | bp2bp(:,:,:), bperio(:,:), npp1(:), p2p(:,:), p3p4(:,:)
23 | character(20), allocatable :: cbc(:,:)
24 |
25 | ! Temporary grid arrays
26 | integer(4), allocatable :: s2ptmp(:,:,:), b2ptmp(:,:,:,:), po2pn(:)
27 | real(8), allocatable :: xptmp(:,:,:)
28 |
29 | ! Periodic bcs
30 | character(20) :: perio(2,20)
31 | integer(4) :: dperio(20)
32 | real(8) :: lperio(9,20), ax_perio(3,20), lnper(20)
33 | logical :: axial
34 |
35 | integer(4), parameter :: mtb = 20, mb = 100000, me = 8000000, mp = 8000000, &
36 | md = 3
37 |
38 | real(8), parameter :: tol0 = 1.e-8
39 |
40 | real(8) :: scaling
41 |
42 | id2np = 0
43 | ! 2D
44 | id2np(3) = 2
45 | id2np(5) = 3
46 | id2np(9) = 4
47 | ! 3D
48 | id2np(10) = 4
49 | id2np(12) = 8
50 | id2np(13) = 6
51 | id2np(14) = 5
52 |
53 | write(*,*)
54 | write(*,*)'===================================================='
55 | write(*,*)'READING cfg file'
56 | write(*,*)
57 | call read_cfg
58 | write(*,*)'===================================================='
59 |
60 | write(*,*)
61 | write(*,*)'===================================================='
62 | write(*,*)'READING mesh file: ',rmesh
63 | write(*,*)
64 | call read_mesh
65 | call write_tec
66 | write(*,*)'===================================================='
67 |
68 | write(*,*)
69 | write(*,*)'===================================================='
70 | write(*,*)'BUILD periodic data structure'
71 | write(*,*)
72 | call build_perio
73 | write(*,*)'===================================================='
74 |
75 | write(*,*)
76 | write(*,*)'===================================================='
77 | write(*,*)'WRITING mesh file: ',wmesh
78 | call write_mesh
79 | call write_tec_perio
80 | write(*,*)'===================================================='
81 |
82 | contains
83 |
84 | subroutine read_cfg
85 |
86 | character(200) :: str200
87 | integer(4) :: i, l, idf, m(12), mm
88 | logical :: rmsh, wmsh
89 |
90 |
91 | scaling = 1.0
92 | nperio = 0
93 | rmsh = .false.
94 | wmsh = .false.
95 | do l = 1, 10000
96 | do i = 1, 200
97 | str200(i:i) = ' '
98 | enddo
99 |
100 | read (*,'(a200)',end=9) str200
101 |
102 | if ( str200(1:16) == 'MARKER_PERIODIC=' ) then
103 | nperio = nperio +1
104 | mm = 0
105 | m = 0
106 | do i = 1, 200
107 | if ( str200(i:i) == '(' ) then
108 | mm = mm +1
109 | m(mm) = i+1
110 | elseif ( str200(i:i) == ',' ) then
111 | mm = mm +1
112 | m(mm) = i-1
113 | elseif ( str200(i:i) == ')' ) then
114 | mm = mm +1
115 | m(mm) = i-1
116 | endif
117 | enddo
118 | read (str200(m(1):m(2)),*)perio(1,nperio)
119 | read (str200(m(2)+2:m(3)),*) perio(2,nperio)
120 | read (str200(m(3)+2:m(4)),*)lperio(1,nperio)
121 | read (str200(m(4)+2:m(5)),*)lperio(2,nperio)
122 | read (str200(m(5)+2:m(6)),*)lperio(3,nperio)
123 | read (str200(m(6)+2:m(7)),*)lperio(4,nperio)
124 | read (str200(m(7)+2:m(8)),*)lperio(5,nperio)
125 | read (str200(m(8)+2:m(9)),*)lperio(6,nperio)
126 | read (str200(m(9)+2:m(10)),*)lperio(7,nperio)
127 | read (str200(m(10)+2:m(11)),*)lperio(8,nperio)
128 | read (str200(m(11)+2:m(12)),*)lperio(9,nperio)
129 |
130 | write(*,*)'Periodic condition:',nperio
131 | write(*,'(3a25)')'FLAG=',perio(1,nperio), perio(2,nperio)
132 | write(*,*)'Rotation_center_(x,y,z)'
133 | write(*,'(3f15.8)')lperio(1:3,nperio)
134 | write(*,*)'Rotation_angle_(x,y,z)-axis'
135 | write(*,'(3f15.8)')lperio(4:6,nperio)
136 | write(*,*)'Translation_(x,y,z)'
137 | write(*,'(3f15.8)')lperio(7:9,nperio)
138 | elseif ( str200(1:14) == 'MESH_FILENAME=' ) then
139 | read (str200(15:34),*)rmesh
140 | rmsh = .true.
141 | elseif ( str200(1:18) == 'MESH_OUT_FILENAME=' ) then
142 | read (str200(19:38),*)wmesh
143 | wmsh = .true.
144 | elseif ( str200(1:16) == 'MSH_PERIO_SCALE=' ) then
145 | read (str200(17:38),*)scaling
146 | wmsh = .true.
147 | endif
148 | enddo
149 |
150 | 9 continue
151 |
152 | if ( .not. rmsh ) then
153 | write(*,*)'ERROR! INPUT mesh file not specified!'
154 | stop
155 | endif
156 | if ( .not. wmsh ) then
157 | write(*,*)'WARNING! OUTPUT mesh file not specified!'
158 | write(*,*)'Default name will be used: mesh_out.su2'
159 | wmesh = 'mesh_out.su2'
160 | stop
161 | endif
162 |
163 | if ( lperio(4,1) == 0. .and. lperio(5,1) == 0. .and. lperio(6,1) == 0. ) then
164 | axial = .true.
165 | else
166 | axial = .false.
167 | endif
168 |
169 | do i = 1, nperio
170 | if ( lperio(4,i) /= 0. ) then
171 | dperio(i) = 1
172 | lnper(i) = lperio(4,i)*acos(-1.0)/180.
173 | ax_perio(1,i) = 1.
174 | ax_perio(2,i) = 0.
175 | ax_perio(3,i) = 0.
176 | elseif ( lperio(5,i) /= 0. ) then
177 | dperio(i) = 2
178 | lnper(i) = lperio(5,i)*acos(-1.0)/180.
179 | ax_perio(1,i) = 0.
180 | ax_perio(2,i) = 1.
181 | ax_perio(3,i) = 0.
182 | elseif ( lperio(6,i) /= 0. ) then
183 | dperio(i) = 3
184 | lnper(i) = lperio(6,i)*acos(-1.0)/180.
185 | ax_perio(1,i) = 0.
186 | ax_perio(2,i) = 0.
187 | ax_perio(3,i) = 1.
188 | endif
189 | enddo
190 |
191 | end subroutine read_cfg
192 |
193 | subroutine read_mesh
194 |
195 | integer(4) :: iunit, i, j, k, io, last, m, npri, npyr, ntet, nhex, ntri, nqua
196 | character(6) :: c6, control
197 | character(200) :: str200
198 | real(8) :: ct(3,4)
199 |
200 |
201 | iunit = 15
202 | open(unit=iunit,file=rmesh,form="formatted")
203 |
204 | ! nf: number of zones
205 | control = 'NZONE='
206 | call tstlin2(iunit,control,io)
207 | if ( io == 0 ) then
208 | read(iunit,'(a6,i5)') c6, nf
209 | else
210 | nf = 1
211 | endif
212 |
213 |
214 | allocate (ne(nf), np(nf), nmark(nf))
215 |
216 | allocate (xp(md,mp,nf))
217 | allocate (p2p(mp,nf))
218 | allocate (p3p4(mp,nf))
219 | allocate (s2p(8,me,nf))
220 | allocate (topo(me,nf))
221 |
222 | allocate (nb(mtb,nf))
223 | allocate (b2p(5,mb,mtb,nf))
224 | allocate (cbc(mtb,nf))
225 |
226 | allocate (xptmp(md,mp,nf))
227 | allocate (s2ptmp(8,me,nf))
228 | allocate (b2ptmp(5,mb,mtb,nf))
229 | allocate ( po2pn(mp) )
230 |
231 | do i = 1, nf
232 |
233 | rewind(iunit)
234 | control = 'NDIME='
235 | call tstlin2(iunit,control,io)
236 | if ( io == 0 ) then
237 | read(iunit,'(a6,i5)') c6, nd
238 | else
239 | write(*,*)'Error! Cannot read mesh dimension'
240 | stop
241 | endif
242 |
243 | ! ne(:): number of elements for each zone
244 | rewind(iunit)
245 | control = 'NELEM='
246 | call tstlin2(iunit,control,io)
247 | if ( io == 0 ) then
248 | read(iunit,'(a6,i15)') c6, ne(i)
249 | else
250 | write(*,*)'Error! Cannot read mesh elements'
251 | stop
252 | endif
253 |
254 | ! topo(:,:): element ID
255 | ! s2p(:,:,:): connectivity of each element
256 | do j = 1, ne(i)
257 | read(iunit,*)topo(j,i), s2ptmp(1:id2np(topo(j,i)),j,i)
258 | enddo
259 |
260 | ! np(:): number of points for each zone
261 | rewind(iunit)
262 | control = 'NPOIN='
263 | call tstlin2(iunit,control,io)
264 | if ( io == 0 ) then
265 | read(iunit,'(a6,i15)') c6, np(i)
266 | else
267 | write(*,*)'Error! Cannot read points coordinates'
268 | stop
269 | endif
270 |
271 | ! xp(:,:,:): points coordinates for each zone
272 | do j = 1, np(i)
273 | read(iunit,*)xptmp(1:nd,j,i)
274 | enddo
275 | p2p(:,i) = -1
276 | p3p4(:,i) = -1
277 |
278 | rewind(iunit)
279 | control = 'NMARK='
280 | call tstlin2(iunit,control,io)
281 |
282 | ! nmark(:): number of bcs for each zone
283 | if ( io == 0 ) then
284 | read(iunit,'(a6,i15)') c6, nmark(i)
285 | else
286 | write(*,*)'Error! Cannot read number of bcs'
287 | stop
288 | endif
289 |
290 | ! cbc(:,:): ID of the bcs for each zone
291 | ! nb(:,:): number of boundary elements for each bcs
292 | ! b2p(:,:,:,:): connectivity of every boundary element for each bcs
293 | do j = 1, nmark(i)
294 | read (iunit,'(a200)') str200
295 | read (str200(12:31),*)cbc(j,i)
296 | read (iunit,'(a200)') str200
297 | read (str200(14:28),*)nb(j,i)
298 | do k = 1, nb(j,i)
299 | read(iunit,*)b2ptmp(1,k,j,i), b2ptmp(2:id2np(b2ptmp(1,k,j,i))+1,k,j,i)
300 | enddo
301 | enddo
302 | enddo
303 |
304 | close(iunit)
305 |
306 | ! Change numbering
307 |
308 | do i = 1, nf
309 |
310 | po2pn = -1
311 |
312 | do j = 1, nmark(i)
313 | if ( cbc(j,i) == perio(1,i) ) then
314 | last = np(i)-1
315 | do k = 1, nb(j,i)
316 | do m = 2, id2np(b2ptmp(1,k,j,i))+1
317 | if ( po2pn(b2ptmp(m,k,j,i)+1) == -1 ) then
318 | po2pn(b2ptmp(m,k,j,i)+1) = last
319 | last = last -1
320 | endif
321 | enddo
322 | enddo
323 | endif
324 | enddo
325 |
326 | last = 0
327 | do j = 1, ne(i)
328 | do k = 1, id2np(topo(j,i))
329 | if ( po2pn(s2ptmp(k,j,i)+1) == -1 ) then
330 | po2pn(s2ptmp(k,j,i)+1) = last
331 | last = last +1
332 | endif
333 | enddo
334 | enddo
335 |
336 | do j = 1, ne(i)
337 | do k = 1, id2np(topo(j,i))
338 | s2p(k,j,i) = po2pn(s2ptmp(k,j,i)+1)
339 | xp(:,s2p(k,j,i)+1,i) = xptmp(:,s2ptmp(k,j,i)+1,i)
340 | enddo
341 | enddo
342 |
343 | do j = 1, nmark(i)
344 | do k = 1, nb(j,i)
345 | b2p(1,k,j,i) = b2ptmp(1,k,j,i)
346 | do m = 2, id2np(b2ptmp(1,k,j,i))+1
347 | b2p(m,k,j,i) = po2pn(b2ptmp(m,k,j,i)+1)
348 | enddo
349 | enddo
350 | enddo
351 |
352 | npri = 0
353 | ntet = 0
354 | nhex = 0
355 | npyr = 0
356 | ntri = 0
357 | nqua = 0
358 | do j = 1, ne(i)
359 | if ( topo(j,i) == 5 ) ntri = ntri +1
360 | if ( topo(j,i) == 9 ) nqua = nqua +1
361 | if ( topo(j,i) == 10 ) ntet = ntet +1
362 | if ( topo(j,i) == 12 ) nhex = nhex +1
363 | if ( topo(j,i) == 13 ) npri = npri +1
364 | if ( topo(j,i) == 14 ) npyr = npyr +1
365 | enddo
366 |
367 |
368 | write(*,*)'Domain=',i
369 | if ( nd == 2 ) then
370 | write(*,'(a12,i15)')'Triangles=', ntri
371 | write(*,'(a12,i15)')'Quads=', nqua
372 | else
373 | write(*,'(a12,i15)')'Tetrahedra=', ntet
374 | write(*,'(a12,i15)')'Prysm=', npri
375 | write(*,'(a12,i15)')'Pyramid=', npyr
376 | write(*,'(a12,i15)')'Hexahedra=', nhex
377 | endif
378 | write(*,*)
379 | write(*,*)'Boundary conditions'
380 | do j = 1, nmark(i)
381 | write(*,*)cbc(j,i),'=',nb(j,i)
382 | enddo
383 | enddo
384 |
385 |
386 | end subroutine read_mesh
387 |
388 | subroutine build_perio
389 |
390 | integer(4) :: i, j, k, ii, iii, e1, e2, m, n, kkk, w, npri, ntet, nhex, npyr, ntri, nqua
391 | integer(4) :: jj, jjj, kk, coun
392 | logical :: found, exist
393 | real(8) :: xa(3), xb(3), r1, r2, dx(3), da, db, dc, alp1, alp2, &
394 | delta, delteta, oo(3), xap(3), tol
395 |
396 |
397 | allocate( bperio(2,nf) )
398 | bperio = 0
399 |
400 | ! bperio(:,:): numbering of two periodic bc for every zone
401 | do j = 1, nf
402 | do k = 1, nmark(j)
403 | if ( cbc(k,j) == perio(1,j) ) then
404 | bperio(1,j) = k
405 | elseif ( cbc(k,j) == perio(2,j) ) then
406 | bperio(2,j) = k
407 | endif
408 | enddo
409 | enddo
410 |
411 | allocate( bp2bp(4,mb+1,nf) )
412 | allocate( npp1(nf) )
413 |
414 | bp2bp = 0
415 | npp1 = 0
416 |
417 | ! bp2bp(1,:,:): list of points associated to side e1
418 | ! npp1(:): number of periodic points on the edge e1
419 | do j = 1, nf
420 | e1 = bperio(1,j)
421 |
422 | do i = 1, nb(e1,j)
423 | do k = 2, id2np(b2p(1,i,e1,j))+1
424 | found = .false.
425 | do ii = 1, npp1(j)
426 | if ( bp2bp(1,ii,j) == b2p(k,i,e1,j) ) then
427 | found = .true.
428 | exit
429 | endif
430 | enddo
431 | if ( .not. found ) then
432 | npp1(j) = npp1(j) +1
433 | bp2bp(1,npp1(j),j) = b2p(k,i,e1,j)
434 | endif
435 | enddo
436 | enddo
437 |
438 | ! do i = 1, npp1(j)
439 | ! write(555,*)xp(1:nd,bp2bp(1,i,j)+1,j)
440 | ! enddo
441 | enddo
442 |
443 | ! bp2bp(2,:,:): list of points associated to side e2
444 | ! p2p(:,:): for each periodic point of e1, the number of the corresponding point
445 | ! on e2 is given
446 |
447 | xa = 0.
448 | xb = 0.
449 |
450 |
451 | do j = 1, nf
452 |
453 | tol = tol0
454 |
455 | m = 0
456 | n = 0
457 | do kkk = 1, 3
458 | if ( dperio(j) == kkk ) cycle
459 | if ( m == 0 ) then
460 | m = kkk
461 | else
462 | n = kkk
463 | endif
464 | enddo
465 |
466 | e1 = bperio(1,j)
467 | e2 = bperio(2,j)
468 |
469 | do i = 1, npp1(j)
470 | xa(1:nd) = xp(:,bp2bp(1,i,j)+1,j)
471 |
472 | if ( axial ) then
473 | xap = xa +lperio(7:9,j)
474 | else
475 | oo = lperio(1:nd,j)
476 | oo(dperio(j)) = xa(dperio(j))
477 | dx = xa -oo
478 | r1 = sqrt(dx(1)**2 +dx(2)**2 +dx(3)**2)
479 | alp1 = atan2(dx(n),dx(m))
480 |
481 | xap(1:nd) = xa
482 | xap(m) = lperio(m,j) +r1*cos(alp1 +lnper(j))
483 | xap(n) = lperio(n,j) +r1*sin(alp1 +lnper(j))
484 | endif
485 |
486 | 100 found = .false.
487 | do k = 1, nb(e2,j)
488 | do ii = 2, id2np(b2p(1,k,e2,j))+1
489 | xb(1:nd) = xp(:,b2p(ii,k,e2,j)+1,j)
490 |
491 | da = sqrt((xap(1)-xb(1))**2+(xap(2)-xb(2))**2+(xap(3)-xb(3))**2)
492 |
493 | if ( da < tol ) then
494 | write(*,*)i, da
495 | bp2bp(2,i,j) = b2p(ii,k,e2,j)
496 | p2p(bp2bp(1,i,j)+1,j) = bp2bp(2,i,j)
497 | found = .true.
498 | exit
499 | endif
500 | enddo
501 | if ( found ) exit
502 | enddo
503 | if ( .not. found .and. tol <= 1.e-3) then
504 | tol = tol*10.
505 | goto 100
506 | elseif ( .not. found) then
507 | write(*,*)'ERROR! Cannot find periodic point'
508 | stop
509 | endif
510 | enddo
511 | ! do i = 1, npp1(j)
512 | ! write(777,*)xp(1:nd,bp2bp(2,i,j)+1,j)
513 | ! enddo
514 | enddo
515 |
516 | allocate ( neg(nf), npg(nf), nmarkg(nf), nbg(mtb,nf) )
517 | allocate( npp2(nf) )
518 | allocate (xpg(md,mp,nf))
519 |
520 | npp2 = 0
521 |
522 | xpg = 0.0
523 | do i = 1, nf
524 | do j = 1, np(i)
525 | xpg(:,j,i) = xp(:,j,i)
526 | enddo
527 | enddo
528 |
529 | ! nmarkg(:): number of bcs for each zone with halos
530 | do i = 1, nf
531 | nmarkg(i) = nmark(i) +2
532 | enddo
533 |
534 | do i = 1, nf
535 | do j = nmark(i)+1, nmarkg(i)
536 | cbc(j,i)="SEND_RECEIVE"
537 | enddo
538 | enddo
539 |
540 | ! neg(:): number of elements for each zone (with halos)
541 | ! npg(:): number of points for each zone (with halos)
542 | ! bp2bp(3,:,:): list of points (inside domain) for the elements sharing the side e1
543 | ! bp2bp(4,:,:): list of points for the elements sharing the side e1
544 | do i = 1, nf
545 | neg(i) = ne(i)
546 | npg(i) = np(i)
547 | do j = 1, ne(i)
548 | found = .false.
549 | do ii = 1, id2np(topo(j,i))
550 | if ( p2p(s2p(ii,j,i)+1,i) >= 0 ) then
551 | neg(i) = neg(i) +1
552 | topo(neg(i),i) = topo(j,i)
553 | found = .true.
554 | exit
555 | endif
556 | enddo
557 | if ( found ) then
558 | do ii = 1, id2np(topo(j,i))
559 | if ( p2p(s2p(ii,j,i)+1,i) >= 0 ) then
560 | s2p(ii,neg(i),i) = p2p(s2p(ii,j,i)+1,i)
561 | else
562 | exist = .false.
563 | do iii = 1, npp2(i)
564 | if ( bp2bp(3,iii,i) == s2p(ii,j,i) ) then
565 | exist = .true.
566 | exit
567 | endif
568 | enddo
569 | if ( .not. exist ) then
570 | npp2(i) = npp2(i) +1
571 | npg(i) = npg(i) +1
572 | s2p(ii,neg(i),i) = npg(i) -1
573 | bp2bp(3,npp2(i),i) = s2p(ii,j,i)
574 | bp2bp(4,npp2(i),i) = s2p(ii,neg(i),i)
575 | if ( axial ) then
576 | xpg(1:nd,npg(i),i) = xp(1:nd,s2p(ii,j,i)+1,i) +lperio(7:7+nd-1,i)
577 | else
578 | m = 0
579 | n = 0
580 | do kkk = 1, 3
581 | if ( dperio(i) == kkk ) cycle
582 | if ( m == 0 ) then
583 | m = kkk
584 | else
585 | n = kkk
586 | endif
587 | enddo
588 |
589 | oo = lperio(1:nd,i)
590 | oo(dperio(i)) = xp(dperio(i),s2p(ii,j,i)+1,i)
591 | dx = xp(1:nd,s2p(ii,j,i)+1,i) -oo
592 | r1 = sqrt(dx(1)**2 +dx(2)**2 +dx(3)**2)
593 | alp1 = atan2(dx(n),dx(m))
594 |
595 | xpg(1:nd,npg(i),i) = xp(1:nd,s2p(ii,j,i)+1,i)
596 | xpg(m,npg(i),i) = lperio(m,i) +r1*cos(alp1 +lnper(i))
597 | xpg(n,npg(i),i) = lperio(n,i) +r1*sin(alp1 +lnper(i))
598 | endif
599 | else
600 | s2p(ii,neg(i),i) = bp2bp(4,iii,i)
601 | endif
602 | endif
603 | enddo
604 | endif
605 | enddo
606 | npri = 0
607 | ntet = 0
608 | nhex = 0
609 | npyr = 0
610 | ntri = 0
611 | nqua = 0
612 | do j = 1, neg(i)
613 | if ( topo(j,i) == 5 ) ntri = ntri +1
614 | if ( topo(j,i) == 9 ) nqua = nqua +1
615 | if ( topo(j,i) == 10 ) ntet = ntet +1
616 | if ( topo(j,i) == 12 ) nhex = nhex +1
617 | if ( topo(j,i) == 13 ) npri = npri +1
618 | if ( topo(j,i) == 14 ) npyr = npyr +1
619 | enddo
620 |
621 |
622 | write(*,*)'Domain=',i
623 | if ( nd == 2 ) then
624 | write(*,'(a12,i15)')'Triangles=', ntri
625 | write(*,'(a12,i15)')'Quads=', nqua
626 | else
627 | write(*,'(a12,i15)')'Tetrahedra=', ntet
628 | write(*,'(a12,i15)')'Prysm=', npri
629 | write(*,'(a12,i15)')'Pyramid=', npyr
630 | write(*,'(a12,i15)')'Hexahedra=', nhex
631 | endif
632 | enddo
633 |
634 | do i = 1, nf
635 | do j = 1, npp2(i)
636 | p3p4(bp2bp(3,j,i)+1,i) = bp2bp(4,j,i)
637 | ! write(888,*)xpg(1:nd,bp2bp(3,j,i)+1,i)
638 | ! write(999,*)xpg(1:nd,bp2bp(4,j,i)+1,i)
639 | enddo
640 | enddo
641 |
642 | nbg = nb
643 | do i = 1, nf
644 | do j = 1, nmark(i)
645 | if ( j == bperio(1,i) .or. j == bperio(2,i) ) cycle
646 | !
647 | !Bisogna verififcare quali boundary intersecano il periodico
648 | ! do w = 1, nwall
649 | ! if ( cbc(j,i) == cwall(w,i) ) goto 100
650 | ! enddo
651 |
652 | do k = 1, nb(j,i)
653 | iii = 0
654 | jjj = 0
655 | do ii = 2, id2np(b2p(1,k,j,i))+1
656 | if ( p2p(b2p(ii,k,j,i)+1,i) >= 0 ) jjj = jjj +1
657 | if ( p3p4(b2p(ii,k,j,i)+1,i) >= 0 ) iii = iii +1
658 | enddo
659 | if ( (iii+jjj) == id2np(b2p(1,k,j,i)) .and. jjj > 0) then
660 | nbg(j,i) = nbg(j,i) +1
661 | do ii = 2, id2np(b2p(1,k,j,i))+1
662 | if ( p2p(b2p(ii,k,j,i)+1,i) >= 0 ) then
663 | b2p(ii,nbg(j,i),j,i) = p2p(b2p(ii,k,j,i)+1,i)
664 | elseif ( p3p4(b2p(ii,k,j,i)+1,i) >= 0 ) then
665 | b2p(ii,nbg(j,i),j,i) = p3p4(b2p(ii,k,j,i)+1,i)
666 | endif
667 | enddo
668 | b2p(1,nbg(j,i),j,i) = b2p(1,k,j,i)
669 | endif
670 | enddo
671 | ! 100 continue
672 | enddo
673 | write(*,*)
674 | write(*,*)'Boundary conditions'
675 | do j = 1, nmark(i)
676 | write(*,*)cbc(j,i),'=',nbg(j,i)
677 | enddo
678 |
679 |
680 | !!!! do j = 1, nmark(i)
681 | !!!! do jj = 1, nbg(j,i)
682 | !!!! do k = 1, neg(i)
683 | !!!! coun = 0
684 | !!!! found = .false.
685 | !!!! do jjj = 2, id2np(b2p(1,jj,j,i))+1
686 | !!!! do kk = 1, id2np(topo(k,i))
687 | !!!! if ( b2p(jjj,jj,j,i) == s2p(kk,k,i) ) coun = coun +1
688 | !!!! enddo
689 | !!!! if ( coun == id2np(b2p(1,jj,j,i)) ) then
690 | !!!! found = .true.
691 | !!!! exit
692 | !!!! endif
693 | !!!! enddo
694 | !!!! if ( found ) exit
695 | !!!! enddo
696 | !!!! if ( .not. found ) then
697 | !!!! write(*,*)'ERROR! Face without corresponding element'
698 | !!!! write(*,*)b2p(1:id2np(b2p(1,jj,j,i))+1,jj,j,i)
699 | !!!! write(*,*)xpg(1:nd,b2p(2,jj,j,i),i)
700 | !!!! write(*,*)xpg(1:nd,b2p(3,jj,j,i),i)
701 | !!!! write(*,*)xpg(1:nd,b2p(4,jj,j,i),i)
702 | !!!! stop
703 | !!!! endif
704 | !!!! enddo
705 | !!!! enddo
706 | enddo
707 |
708 | end subroutine build_perio
709 |
710 | subroutine write_tec
711 |
712 | integer(4) :: i, j, idf
713 |
714 |
715 | idf = 10
716 | open(unit=idf,file='periodic_original.dat')
717 |
718 | if ( nd == 2 ) then
719 | do i = 1, nf
720 | write (idf,*) 'VARIABLES = "X", "Y"'
721 | write (idf,*) 'ZONE N=',np(i),', E=',ne(i),', F=FEPOINT, ET=QUADRILATERAL'
722 | do j = 1, np(i)
723 | write (idf,'(2f20.10)') xp(1:nd,j,i)
724 | enddo
725 | write(idf,*)
726 | do j = 1, ne(i)
727 | if ( topo(j,i) == 5 ) then
728 | write (idf,'(4i15)') s2p(1:3,j,i)+1, s2p(1,j,i)+1
729 | else
730 | write (idf,'(4i15)') s2p(1:4,j,i)+1
731 | endif
732 | enddo
733 | enddo
734 | else
735 | do i = 1, nf
736 | write (idf,*) 'VARIABLES = "X", "Y", "Z"'
737 | write (idf,*) 'ZONE N=',np(i),', E=',ne(i),', &
738 | F=FEPOINT, ET=BRICK'
739 | do j = 1, np(i)
740 | write (idf,'(2f20.10)') xp(:,j,i)
741 | enddo
742 | write(idf,*)
743 | do j = 1, ne(i)
744 | if ( topo(j,i) == 10 ) then
745 | ! TET
746 | write (idf,'(8i10)') s2p(1:3,j,i)+1, s2p(3,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1
747 | elseif ( topo(j,i) == 12 ) then
748 | ! HEX
749 | write (idf,'(8i10)') s2p(1:8,j,i)+1
750 | elseif ( topo(j,i) == 13 ) then
751 | ! PRISM
752 | write (idf,'(8i10)') s2p(1:3,j,i)+1, s2p(3,j,i)+1, s2p(4:6,j,i)+1, s2p(6,j,i)+1
753 | elseif ( topo(j,i) == 14 ) then
754 | ! PYRAMID
755 | write (idf,'(8i10)') s2p(1:4,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1
756 | endif
757 | enddo
758 | enddo
759 | endif
760 |
761 | close(idf)
762 |
763 | end subroutine write_tec
764 |
765 | subroutine write_tec_perio
766 |
767 | integer(4) :: i, j, idf
768 |
769 |
770 | idf = 10
771 | open(unit=idf,file='periodic_halo.dat')
772 |
773 | if ( nd == 2 ) then
774 | do i = 1, nf
775 | write (idf,*) 'VARIABLES = "X", "Y"'
776 | write (idf,*) 'ZONE N=',npg(i),', E=',neg(i),', F=FEPOINT, ET=QUADRILATERAL'
777 | do j = 1, npg(i)
778 | write (idf,'(2f20.10)') xpg(1:nd,j,i)
779 | enddo
780 | write(idf,*)
781 | do j = 1, neg(i)
782 | if ( topo(j,i) == 5 ) then
783 | write (idf,'(4i15)') s2p(1:3,j,i)+1, s2p(1,j,i)+1
784 | else
785 | write (idf,'(4i15)') s2p(1:4,j,i)+1
786 | endif
787 | enddo
788 | enddo
789 | else
790 | do i = 1, nf
791 | write (idf,*) 'VARIABLES = "X", "Y", "Z"'
792 | write (idf,*) 'ZONE NODES=',npg(i),', ELEMENTS=',neg(i),', &
793 | DATAPACKING=POINT, ZONETYPE=FEBRICK'
794 | do j = 1, npg(i)
795 | write (idf,'(3f20.10)') xpg(:,j,i)
796 | enddo
797 | write(idf,*)
798 | do j = 1, neg(i)
799 | if ( topo(j,i) == 10 ) then
800 | ! TET
801 | write (idf,'(8i15)') s2p(1:3,j,i)+1, s2p(3,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1, s2p(4,j,i)+1
802 | elseif ( topo(j,i) == 12 ) then
803 | ! HEX
804 | write (idf,'(8i15)') s2p(1:8,j,i)+1
805 | elseif ( topo(j,i) == 13 ) then
806 | ! PRISM
807 | write (idf,'(8i15)') s2p(1:2,j,i)+1, s2p(2,j,i)+1,s2p(3,j,i)+1, s2p(4:5,j,i)+1, s2p(5,j,i)+1,s2p(6,j,i)+1
808 | elseif ( topo(j,i) == 14 ) then
809 | ! PYRAMID
810 | write (idf,'(8i15)') s2p(1:4,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1, s2p(5,j,i)+1
811 | endif
812 | enddo
813 | enddo
814 | endif
815 |
816 | close(idf)
817 |
818 | end subroutine write_tec_perio
819 |
820 | subroutine write_mesh
821 |
822 | integer(4) :: idf, if, i, j, ip, iel
823 | character(2) :: sz
824 |
825 | write(*,*)'Scaling=',scaling
826 | idf = 25
827 | open(unit=idf,file=wmesh,form="formatted")
828 |
829 | write(idf,'(a6,i3)') 'NZONE=', nf
830 |
831 | do if = 1, nf
832 |
833 | write(idf,*)
834 | write(idf,'(a6,i3)') 'IZONE=', if
835 |
836 | write(idf,*) '%'
837 | write(idf,*) '% Problem dimension'
838 | write(idf,*) '%'
839 | write(idf,'(a6,i3)') 'NDIME=', nd
840 |
841 | write(idf,*) '%'
842 | write(idf,*) '% Inner element connectivity'
843 | write(idf,*) '%'
844 |
845 | write(idf,'(a6,i10)') 'NELEM=', neg(if)
846 |
847 | ! Write the interior element connectivity...
848 |
849 | iel = 0
850 | do i = 1, neg(if)
851 | sz = int2ch2( id2np(topo(i,if)) )
852 | write (idf,'(1i3,'//sz//'i10,i10)') topo(i,if), ( s2p(j,i,if), j=1,id2np(topo(i,if)) ), iel
853 | iel = iel +1
854 | enddo
855 |
856 | write(idf,*) '%'
857 | write(idf,*) '% Node coordinates'
858 | write(idf,*) '%'
859 | write(idf,'(a6,2i10)') 'NPOIN=', npg(if), npg(if)-npp1(if)-npp2(if)
860 |
861 | do ip = 1, npg(if)
862 | sz = int2ch2( nd )
863 | write (idf,'('//sz//'f25.15,i10)') scaling*xpg(1:nd,ip,if), ip-1
864 | enddo
865 |
866 | write(idf,'(a6,i3)') 'NMARK=', nmarkg(if)
867 |
868 | do j = 1, nmark(if)
869 | write(idf,'(a11,a10)') 'MARKER_TAG=', cbc(j,if)
870 | write(idf,'(a13,i10)') 'MARKER_ELEMS=', nbg(j,if)
871 | do i = 1, nbg(j,if)
872 | sz = int2ch2( id2np(b2p(1,i,j,if)))
873 | write(idf,'(1i3,'//sz//'i10)') b2p(1,i,j,if), b2p(2:id2np(b2p(1,i,j,if))+1,i,j,if)
874 | enddo
875 | enddo
876 |
877 | j = nmark(if)+1
878 | write(idf,'(a11,a20)') 'MARKER_TAG=', cbc(j,if)
879 | write(idf,'(a13,i10)') 'MARKER_ELEMS=', npp1(if) +npp2(if)
880 | write(idf,'(a10)') 'SEND_TO= 1'
881 | do i = 1, npp1(if)
882 | write(idf,*)1, bp2bp(2,i,if), 1
883 | enddo
884 | do i = 1, npp2(if)
885 | write(idf,*)1, bp2bp(3,i,if), 2
886 | enddo
887 |
888 | j = nmarkg(if)
889 | write(idf,'(a11,a20)') 'MARKER_TAG=', cbc(j,if)
890 | write(idf,'(a13,i10)') 'MARKER_ELEMS=', npp1(if) +npp2(if)
891 | write(idf,'(a10)') 'SEND_TO=-1'
892 | do i = 1, npp1(if)
893 | write(idf,*)1, bp2bp(1,i,if), 1
894 | enddo
895 | do i = 1, npp2(if)
896 | write(idf,*)1, bp2bp(4,i,if), 2
897 | enddo
898 |
899 | write(idf,'(a12)') 'NPERIODIC= 3'
900 | write(idf,'(a15,i4)') 'PERIODIC_INDEX=',0
901 | write(idf,'(3f15.9)') lperio(1:3,if)
902 | write(idf,'(3f15.9)') lperio(1:3,if)
903 | write(idf,'(3f15.9)') lperio(1:3,if)
904 | write(idf,'(a15,i4)') 'PERIODIC_INDEX=',1
905 | write(idf,'(3f15.9)') lperio(1:3,if)
906 | write(idf,'(3f15.9)') lperio(4:6,if)*acos(-1.0)/180.
907 | write(idf,'(3f15.9)') scaling*lperio(7:9,if)
908 | write(idf,'(a15,i4)') 'PERIODIC_INDEX=',2
909 | write(idf,'(3f15.9)')-lperio(1:3,if)
910 | write(idf,'(3f15.9)')-lperio(4:6,if)*acos(-1.0)/180.
911 | write(idf,'(3f15.9)')-scaling*lperio(7:9,if)
912 |
913 | enddo
914 |
915 | close(idf)
916 |
917 | end subroutine write_mesh
918 |
919 | subroutine tstlin2 ( iunit, string, io )
920 |
921 | integer(4) :: iunit, io
922 | character(6) :: string
923 |
924 | character(80) :: text
925 |
926 | 2002 read(iunit,'(A80)',IOSTAT=io)text
927 |
928 | if ( io == 0 ) then
929 | if ( text(1:6) /= string ) goto 2002
930 |
931 | backspace (iunit)
932 | endif
933 |
934 | end subroutine tstlin2
935 |
936 | function int2ch2 ( n ) result ( c2 )
937 |
938 | integer(4), intent(in) :: n
939 | character(2) :: c2
940 |
941 | integer(4) :: m, n0, n1
942 |
943 |
944 | m = n
945 | n1 = m/10
946 | n0 = m -10*n1
947 |
948 | m = ichar('0')
949 | c2 = char(m+n1)//char(m+n0)
950 |
951 | end function int2ch2
952 |
953 | function voltet( ct ) result ( vol )
954 |
955 | ! tetrahedron volume
956 |
957 | real(8) :: ct(3,4), v(3,4), vol
958 |
959 | integer(4) :: j, i
960 |
961 |
962 | do j=2,4
963 | do i=1,3
964 | v(i,j) = ct(i,j) - ct(i,1)
965 | enddo
966 | enddo
967 |
968 | vol = v(1,4)*(v(2,2)*v(3,3)-v(3,2)*v(2,3))+ &
969 | v(2,4)*(v(3,2)*v(1,3)-v(1,2)*v(3,3))+ &
970 | v(3,4)*(v(1,2)*v(2,3)-v(2,2)*v(1,3))
971 | vol =(1./6.)*vol
972 |
973 | end function voltet
974 |
975 | end program su2_periodic
976 |
--------------------------------------------------------------------------------