Hermes2D  2.0
mesh_reader_h1d_xml.cpp
1 // This file is part of Hermes2D
2 //
3 // Hermes2D is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D; if not, see <http://www.gnu.prg/licenses/>.
15 
16 #include "mesh.h"
17 #include "mesh_reader_h1d_xml.h"
18 #include <iostream>
19 #include <limits>
20 
21 using namespace std;
22 
23 namespace Hermes
24 {
25  namespace Hermes2D
26  {
27  MeshReaderH1DXML::MeshReaderH1DXML()
28  {
29  }
30 
31  MeshReaderH1DXML::~MeshReaderH1DXML()
32  {
33  }
34 
35  bool MeshReaderH1DXML::load(const char *filename, Mesh *mesh)
36  {
37  mesh->free();
38 
39  try
40  {
41  ::xml_schema::flags parsing_flags = 0;
42  if(!this->validate)
43  parsing_flags = xml_schema::flags::dont_validate;
44 
45  std::auto_ptr<XMLMesh1D::mesh> parsed_xml_mesh(XMLMesh1D::mesh_(filename, parsing_flags));
46 
47  // Variables //
48  unsigned int variables_count = parsed_xml_mesh->variables().present() ? parsed_xml_mesh->variables()->var().size() : 0;
49  std::map<std::string, double> variables;
50  for (unsigned int variables_i = 0; variables_i < variables_count; variables_i++)
51 #ifdef _MSC_VER
52  variables.insert(std::make_pair<std::string, double>((std::string)parsed_xml_mesh->variables()->var().at(variables_i).name(), (double&&)parsed_xml_mesh->variables()->var().at(variables_i).value()));
53 #else
54  variables.insert(std::make_pair<std::string, double>((std::string)parsed_xml_mesh->variables()->var().at(variables_i).name(), parsed_xml_mesh->variables()->var().at(variables_i).value()));
55 #endif
56 
57  // Vertices //
58  int vertices_count = parsed_xml_mesh->v().size();
59 
60  // Initialize mesh.
61  int size = HashTable::H2D_DEFAULT_HASH_SIZE;
62  while (size < 8 * vertices_count)
63  size *= 2;
64  mesh->init(size);
65 
66  double a = std::numeric_limits<double>::infinity();
67  double b = -std::numeric_limits<double>::infinity();
68 
69  // Create top-level vertex nodes.
70  for (int vertices_i = 0; vertices_i < 2 * vertices_count; vertices_i++)
71  {
72  Node* node = mesh->nodes.add();
73  assert(node->id == vertices_i);
74  node->ref = TOP_LEVEL_REF;
75  node->type = HERMES_TYPE_VERTEX;
76  node->bnd = 0;
77  node->p1 = node->p2 = -1;
78  node->next_hash = NULL;
79 
80  // variables matching.
81  std::string x = parsed_xml_mesh->v().at(vertices_i % vertices_count).x();
82  double x_value;
83 
84  // variables lookup.
85  bool x_found = false;
86  if(variables.find(x) != variables.end())
87  {
88  x_value = variables.find(x)->second;
89  x_found = true;
90  }
91 
92  // test of value if no variable found.
93  if(!x_found)
94  if(std::strtod(x.c_str(), NULL) != 0.0)
95  x_value = std::strtod(x.c_str(), NULL);
96  else
97  {
98  // This is a hard part, to find out if it is really zero.
99  int dot_position = strchr(x.c_str(), '.') == NULL ? -1 : strchr(x.c_str(), '.') - x.c_str();
100  for(int i = 0; i < dot_position; i++)
101  if(strncmp(x.c_str() + i, "0", 1) != 0)
102  throw Hermes::Exceptions::MeshLoadFailureException("Wrong syntax in the x coordinate of vertex no. %i.", vertices_i % vertices_count + 1);
103  for(int i = dot_position + 1; i < x.length(); i++)
104  if(strncmp(x.c_str() + i, "0", 1) != 0)
105  throw Hermes::Exceptions::MeshLoadFailureException("Wrong syntax in the x coordinate of vertex no. %i.", vertices_i % vertices_count + 1);
106  x_value = std::strtod(x.c_str(), NULL);
107  }
108 
109  // assignment.
110  node->x = x_value;
111  if(x_value > b)
112  b = x_value;
113  if(x_value < a)
114  a = x_value;
115 
116  if(vertices_i < vertices_count)
117  node->y = 0;
118  else
119  node->y = 1;
120  }
121  mesh->ntopvert = 2 * vertices_count;
122 
123  Node* node;
124  for_all_nodes(node, mesh)
125  if(node->y == 0)
126  node->y = 0;
127  else
128  node->y = (b-a) / 100;
129 
130  // Elements //
131  mesh->nbase = mesh->nactive = mesh->ninitial = vertices_count - 1;
132 
133  Element* e;
134  for (int element_i = 0; element_i < vertices_count - 1; element_i++)
135  {
136  mesh->element_markers_conversion.insert_marker(mesh->element_markers_conversion.min_marker_unused, "H1DMarker");
137 
138  int element_marker;
139  if(parsed_xml_mesh->v().at(element_i % vertices_count).m().present())
140  {
141  mesh->element_markers_conversion.insert_marker(mesh->element_markers_conversion.min_marker_unused, parsed_xml_mesh->v().at(element_i % vertices_count).m().get());
142  element_marker = mesh->element_markers_conversion.get_internal_marker(parsed_xml_mesh->v().at(element_i % vertices_count).m().get()).marker;
143  }
144  else
145  element_marker = mesh->element_markers_conversion.get_internal_marker("H1DMarker").marker;
146 
147  e = mesh->create_quad(element_marker,
148  &mesh->nodes[element_i],
149  &mesh->nodes[element_i + 1],
150  &mesh->nodes[element_i + vertices_count + 1],
151  &mesh->nodes[element_i + vertices_count],
152  NULL);
153 
154  mesh->boundary_markers_conversion.insert_marker(mesh->boundary_markers_conversion.min_marker_unused, "Unused");
155 
156  node = mesh->peek_edge_node(element_i, element_i + 1);
157  node->bnd = 1;
158  node->marker = mesh->boundary_markers_conversion.get_internal_marker("Unused").marker;
159  mesh->nodes[element_i].bnd = 1;
160  mesh->nodes[element_i + 1].bnd = 1;
161 
162  node = mesh->peek_edge_node(vertices_count + element_i, vertices_count + element_i + 1);
163  node->bnd = 1;
164  node->marker = mesh->boundary_markers_conversion.get_internal_marker("Unused").marker;
165  mesh->nodes[vertices_count + element_i].bnd = 1;
166  mesh->nodes[vertices_count + element_i + 1].bnd = 1;
167  }
168 
169  // Boundaries //
170  Node* en;
171  int v1_1 = 0;
172  int v2_1 = vertices_count;
173  int v1_2 = vertices_count - 1;
174  int v2_2 = 2 * vertices_count - 1;
175 
176  en = mesh->peek_edge_node(v1_1, v2_1);
177  // This functions check if the user-supplied marker on this element has been
178  // already used, and if not, inserts it in the appropriate structure.
179  mesh->boundary_markers_conversion.insert_marker(mesh->boundary_markers_conversion.min_marker_unused, "Left");
180  int marker = mesh->boundary_markers_conversion.get_internal_marker("Left").marker;
181  en->marker = marker;
182  en->bnd = 1;
183 
184  en = mesh->peek_edge_node(v1_2, v2_2);
185  // This functions check if the user-supplied marker on this element has been
186  // already used, and if not, inserts it in the appropriate structure.
187  mesh->boundary_markers_conversion.insert_marker(mesh->boundary_markers_conversion.min_marker_unused, "Right");
188  marker = mesh->boundary_markers_conversion.get_internal_marker("Right").marker;
189  en->marker = marker;
190  en->bnd = 1;
191 
192  mesh->nodes[v1_1].bnd = 1;
193  mesh->nodes[v2_1].bnd = 1;
194 
195  mesh->nodes[v1_2].bnd = 1;
196  mesh->nodes[v2_2].bnd = 1;
197  }
198  catch (const xml_schema::exception& e)
199  {
200  throw Hermes::Exceptions::MeshLoadFailureException(e.what());
201  }
202  }
203 
204  bool MeshReaderH1DXML::save(const char *filename, Mesh *mesh)
205  {
207  return true;
208  }
209  }
210 }