OptFEM3DP1 Toolbox  V1.0
Matlab/Octave Optimized P1-Lagrange Finite Element Method in 3D
 All Files Functions Variables Pages
load_gmsh2.m
Go to the documentation of this file.
1 function msh = load_gmsh4(filename, which)
2 % Copyright:
3 % See \ref license
4 
5 %% Reads a mesh in msh format, version 1 or 2
6 
7 % Usage:
8 % To define all variables m.LINES, M.TRIANGLES, etc
9 % (Warning: This creates a very large structure. Do you really need it?)
10 % m = load_gmsh4('a.msh')
11 %
12 % To define only certain variables (for example TETS and HEXS)
13 % m = load_gmsh4('a.msh', [ 5 6])
14 %
15 % To define no variables (i.e. if you prefer to use m.ELE_INFOS(i,2))
16 % m = load_gmsh4('a.msh', -1)
17 % m = load_gmsh4('a.msh', [])
18 %
19 % Copyright (C) 2007 JP Moitinho de Almeida (moitinho@civil.ist.utl.pt)
20 % and R Lorphevre(r(point)lorphevre(at)ulg(point)ac(point)be)
21 %
22 % based on load_gmsh.m supplied with gmsh-2.0
23 
24 % Structure msh always has the following elements:
25 %
26 % msh.MIN, msh.MAX - Bounding box
27 % msh.nbNod - Number of nodes
28 % msh.nbElm - Total number of elements
29 % msh.nbType(i) - Number of elements of type i (i in 1:19)
30 % msh.POS(i,j) - j'th coordinate of node i (j in 1:3, i in 1:msh.nbNod)
31 % msh.ELE_INFOS(i,1) - id of element i (i in 1:msh.nbElm)
32 % msh.ELE_INFOS(i,2) - type of element i
33 % msh.ELE_INFOS(i,3) - number of tags for element i
34 % msh.ELE_INFOS(i,4) - Dimension (0D, 1D, 2D or 3D) of element i
35 % msh.ELE_TAGS(i,j) - Tags of element i (j in 1:msh.ELE_INFOS(i,3))
36 % msh.ELE_NODES(i,j) - Nodes of element i (j in 1:k, with
37 % k = msh.NODES_PER_TYPE_OF_ELEMENT(msh.ELE_INFOS(i,2)))
38 %
39 % These elements are created if requested:
40 %
41 % msh.nbLines - number of 2 node lines
42 % msh.LINES(i,1:2) - nodes of line i
43 % msh.LINES(i,3) - tag (WHICH ?????) of line i
44 %
45 % msh.nbTriangles - number of 2 node triangles
46 % msh.TRIANGLES(i,1:3) - nodes of triangle i
47 % msh.TRIANGLES(i,4) - tag (WHICH ?????) of triangle i
48 %
49 % Etc
50 
51 % These definitions need to be updated when new elemens types are added to gmsh
52 %
53 % msh.Types{i}{1} Number of an element of type i
54 % msh.Types{i}{2} Dimension (0D, 1D, 2D or 3D) of element of type i
55 % msh.Types{i}{3} Name to add to the structure with elements of type i
56 % msh.Types{i}{4} Name to add to the structure with the number of elements of type i
57 %
58 
59 nargchk(1, 2, nargin);
60 
61 msh.Types = { ...
62  { 2, 1, 'LINES', 'nbLines'}, ... % 1
63  { 3, 2, 'TRIANGLES', 'nbTriangles'}, ...
64  { 4, 2, 'QUADS', 'nbQuads'}, ...
65  { 4, 3, 'TETS', 'nbTets'}, ...
66  { 8, 3, 'HEXAS', 'nbHexas'}, ... %5
67  { 6, 3, 'PRISMS', 'nbPrisms'}, ...
68  { 5, 3, 'PYRAMIDS', 'nbPyramids'}, ...
69  { 3, 1, 'LINES3', 'nbLines3'}, ...
70  { 6, 2, 'TRIANGLES6', 'nbTriangles6'}, ...
71  { 9, 2, 'QUADS9', 'nbQuads9'}, ... % 10
72  { 10, 3, 'TETS10', 'nbTets10'}, ...
73  { 27, 3, 'HEXAS27', 'nbHexas27'}, ...
74  { 18, 3, 'PRISMS18', 'nbPrisms18'}, ...
75  { 14, 3, 'PYRAMIDS14', 'nbPyramids14'}, ...
76  { 1, 0, 'POINTS', 'nbPoints'}, ... % 15
77  { 8, 3, 'QUADS8', 'nbQuads8'}, ...
78  { 20, 3, 'HEXAS20', 'nbHexas20'}, ...
79  { 15, 3, 'PRISMS15', 'nbPrisms15'}, ...
80  { 13, 3, 'PYRAMIDS13', 'nbPyramids13'}, ...
81 };
82 
83 ntypes = length(msh.Types);
84 
85 if (nargin==1)
86  which = 1:ntypes;
87 else
88  if isscalar(which) && which == -1
89  which = [];
90  end
91 end
92 
93 % Could check that "which" is properlly defined....
94 
95 fid = fopen(filename, 'r');
96 fileformat = 0; % Assume wrong file
97 
98 tline = fgetl(fid);
99 if (feof(fid))
100  disp (sprintf('Empty file: %s', filename));
101  msh = [];
102  return;
103 end
104 
105 %% Read mesh type
106 if (strcmp(tline, '$NOD'))
107  fileformat = 1;
108 elseif (strcmp(tline, '$MeshFormat'))
109  fileformat = 2;
110  tline = fgetl(fid);
111  if (feof(fid))
112  disp (sprintf('Syntax error (no version) in: %s', filename));
113  fileformat = 0;
114  end
115  [ form ] = sscanf( tline, '%f %d %d');
116  if (form(1) ~= 2)
117  disp (sprintf('Unknown mesh format: %s', tline));
118  fileformat = 0;
119  end
120  if (form(2) ~= 0)
121  disp ('Sorry, this program can only read ASCII format');
122  fileformat = 0;
123  end
124  fgetl(fid); % this should be $EndMeshFormat
125  if (feof(fid))
126  disp (sprintf('Syntax error (no $EndMeshFormat) in: %s', filename));
127  fileformat = 0;
128  end
129  tline = fgetl(fid); % this should be $Nodes
130  if (feof(fid))
131  disp (sprintf('Syntax error (no $Nodes) in: %s', filename));
132  fileformat = 0;
133  end
134 end
135 
136 if (~fileformat)
137  msh = [];
138  return
139 end
140 
141 %% Read nodes
142 
143 if strcmp(tline, '$NOD') || strcmp(tline, '$Nodes')
144  msh.nbNod = fscanf(fid, '%d', 1);
145  aux = fscanf(fid, '%g', [4 msh.nbNod]);
146  msh.POS = aux(2:4,:)';
147  numids = max(aux(1,:));
148  IDS = zeros(1, numids);
149  IDS(aux(1,:)) = 1:msh.nbNod; % This may not be an identity
150  msh.MAX = max(msh.POS);
151  msh.MIN = min(msh.POS);
152  fgetl(fid); % End previous line
153  fgetl(fid); % Has to be $ENDNOD $EndNodes
154 else
155  disp (sprintf('Syntax error (no $Nodes/$NOD) in: %s', filename));
156  fileformat = 0;
157 end
158 
159 %% Read elements
160 tline = fgetl(fid);
161 if strcmp(tline,'$ELM') || strcmp(tline, '$Elements')
162  msh.nbElm = fscanf(fid, '%d', 1);
163  % read all info about elements into aux (it is faster!)
164  aux = fscanf(fid, '%g', inf);
165  start = 1;
166  msh.ELE_INFOS = zeros(msh.nbElm, 4); % 1 - id, 2 - type, 3 - ntags, 4 - Dimension
167  msh.ELE_NODES = zeros(msh.nbElm,6); % i - Element, j - ElNodes
168  if (fileformat == 1)
169  ntags = 2;
170  else
171  ntags = 3; % just a prediction
172  end
173  msh.ELE_TAGS = zeros(msh.nbElm, ntags); % format 1: 1 - physical number, 2 - geometrical number
174  % format 2: 1 - physical number, 2 - geometrical number, 3 - mesh partition number
175  msh.nbType = zeros(ntypes,1);
176  for I = 1:msh.nbElm
177  if (fileformat == 2)
178  finnish = start + 2;
179  msh.ELE_INFOS(I, 1:3) = aux(start:finnish);
180  ntags = aux(finnish);
181  start = finnish + 1;
182  finnish = start + ntags -1;
183  msh.ELE_TAGS(I, 1:ntags) = aux(start:finnish);
184  start = finnish + 1;
185  else
186  finnish = start + 1;
187  msh.ELE_INFOS(I, 1:2) = aux(start:finnish);
188  start = finnish + 1; % the third element is nnodes, which we get from the type
189  msh.ELE_INFOS(I, 3) = 2;
190  finnish = start + 1;
191  msh.ELE_TAGS(I, 1:2) = aux(start:finnish);
192  start = finnish + 2;
193  end
194  type = msh.ELE_INFOS(I, 2);
195  msh.nbType(type) = msh.nbType(type) + 1;
196  msh.ELE_INFOS(I, 4) = msh.Types{type}{2};
197  nnodes = msh.Types{type}{1};
198  finnish = start + nnodes - 1;
199  msh.ELE_NODES(I, 1:nnodes) = IDS(aux(start:finnish));
200  start=finnish + 1;
201  end
202  fgetl(fid); % Has to be $ENDELM or $EndElements
203 else
204  disp (sprintf('Syntax error (no $Elements/$ELM) in: %s', filename));
205  fileformat = 0;
206 end
207 
208 if (fileformat == 0)
209  msh = [];
210 end
211 
212 fclose(fid);
213 
214 %% This is used to create the explicit lists for types of elements
215 
216 for i = which
217  if (~isempty(msh.Types{i}{3}))
218  cmd = sprintf('msh.%s=msh.nbType(%d);', msh.Types{i}{4}, i);
219  eval(cmd);
220  % Dimension
221  cmd = sprintf('msh.%s=zeros(%d,%d);', msh.Types{i}{3}, msh.nbType(i), msh.Types{i}{1}+1);
222  eval(cmd);
223  % Clear nbType for counting, next loop will recompute it
224  msh.nbType(i) = 0;
225  end
226 end
227 
228 for i = 1:msh.nbElm
229  type = msh.ELE_INFOS(i,2);
230  if (find(which == type))
231  if (~isempty(msh.Types{type}{3}))
232  msh.nbType(type) = msh.nbType(type)+1;
233  aux=[ msh.ELE_NODES(i,1:msh.Types{type}{1}), msh.ELE_TAGS(i,1) ];
234  cmd = sprintf('msh.%s(%d,:)=aux;', msh.Types{type}{3}, msh.nbType(type));
235  eval(cmd);
236  end
237  end
238 end
239 
240 return;