ug4
file_io_ugx_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3  * Author: Sebastian Reiter
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__LIB_GRID__FILE_IO_UGX_IMPL__
34 #define __H__LIB_GRID__FILE_IO_UGX_IMPL__
35 
36 #include <sstream>
37 #include <cstring>
41 
42 namespace ug
43 {
44 
46 template <class TAPosition>
47 bool SaveGridToUGX(Grid& grid, ISubsetHandler& sh, const char* filename,
48  TAPosition& aPos)
49 {
50  GridWriterUGX ugxWriter;
51  ugxWriter.add_grid(grid, "defGrid", aPos);
52  ugxWriter.add_subset_handler(sh, "defSH", 0);
53 
54  return ugxWriter.write_to_file(filename);
55 };
56 
58 template <class TAPosition>
59 bool LoadGridFromUGX(Grid& grid, SPProjectionHandler& ph, size_t& num_ph, ISubsetHandler& sh, std::vector<std::string> additionalSHNames,
60  std::vector<SmartPtr<ISubsetHandler>> ash, const char* filename, TAPosition& aPos)
61 {
62  GridReaderUGX ugxReader;
63  if(!ugxReader.parse_file(filename)){
64  UG_LOG("ERROR in LoadGridFromUGX: File not found: " << filename << std::endl);
65  return false;
66  }
67 
68  if(ugxReader.num_grids() < 1){
69  UG_LOG("ERROR in LoadGridFromUGX: File contains no grid.\n");
70  return false;
71  }
72 
73  ugxReader.grid(grid, 0, aPos);
74 
75  if(ugxReader.num_subset_handlers(0) > 0)
76  ugxReader.subset_handler(sh, 0, 0);
77 
78  for(size_t i_name = 0; i_name < additionalSHNames.size(); ++i_name){
79  std::string shName = additionalSHNames[i_name];
80  for(size_t i_sh = 0; i_sh < ugxReader.num_subset_handlers(0); ++i_sh){
81  if(shName == ugxReader.get_subset_handler_name(0, i_sh)){
82  ugxReader.subset_handler(*ash[i_name], i_sh, 0);
83  }
84  }
85  }
86 
87  if(ugxReader.num_projection_handlers(0) > 0){
88  ugxReader.projection_handler(*ph, 0, 0);
89  size_t shIndex = ugxReader.get_projection_handler_subset_handler_index(0, 0);
90  std::string shName2;
91  shName2 = std::string(ugxReader.get_subset_handler_name(0, shIndex));
92 
93  if (shIndex > 0)
94  {
95  for(size_t i_name = 0; i_name < additionalSHNames.size(); ++i_name)
96  if(shName2==additionalSHNames[i_name])
97  {
98  try {ph->set_subset_handler(ash[i_name]);}
99  UG_CATCH_THROW("Additional subset handler '"<< shName2 << "' has not been added to the domain.\n"
100  "Do so by using Domain::create_additional_subset_handler(std::string name).");
101  }
102  }
103  }
104 
105  return true;
106 }
107 
108 template <class TAPosition>
109 bool LoadGridFromUGX(Grid& grid, ISubsetHandler& sh, const char* filename,
110  TAPosition& aPos)
111 {
112  GridReaderUGX ugxReader;
113  if(!ugxReader.parse_file(filename)){
114  UG_LOG("ERROR in LoadGridFromUGX: File not found: " << filename << std::endl);
115  return false;
116  }
117 
118  if(ugxReader.num_grids() < 1){
119  UG_LOG("ERROR in LoadGridFromUGX: File contains no grid.\n");
120  return false;
121  }
122 
123  ugxReader.grid(grid, 0, aPos);
124 
125  if(ugxReader.num_subset_handlers(0) > 0)
126  ugxReader.subset_handler(sh, 0, 0);
127 
128  return true;
129 }
130 
131 
133 template <class TPositionAttachment>
135 add_grid(Grid& grid, const char* name,
136  TPositionAttachment& aPos)
137 {
138  using namespace rapidxml;
139  using namespace std;
140 // access node data
141  if(!grid.has_vertex_attachment(aPos)){
142  UG_LOG(" position attachment missing in grid " << name << endl);
143  return false;
144  }
145 
147 
148 // create a new grid-node
149  xml_node<>* gridNode = m_doc.allocate_node(node_element, "grid");
150  gridNode->append_attribute(m_doc.allocate_attribute("name", name));
151 
152 // store the grid and the node in an entry
153  m_vEntries.push_back(Entry(&grid, gridNode));
154 
155 // append it to the document
156  m_doc.append_node(gridNode);
157 
158 // initialize the grids attachments
159  init_grid_attachments(grid);
160 
161 // access indices
164 
165 // write vertices
166  if(grid.num<RegularVertex>() > 0)
167  gridNode->append_node(create_vertex_node(grid.begin<RegularVertex>(),
168  grid.end<RegularVertex>(), aaPos));
169 
170 // write constrained vertices
171  if(grid.num<ConstrainedVertex>() > 0)
172  gridNode->append_node(create_constrained_vertex_node(
173  grid.begin<ConstrainedVertex>(),
174  grid.end<ConstrainedVertex>(),
175  aaPos, aaIndEDGE, aaIndFACE));
176 
177 // add the remaining grid elements to the nodes
178  add_elements_to_node(gridNode, grid);
179 
180  process_global_attachments<Vertex>(grid, gridNode);
181  process_global_attachments<Edge>(grid, gridNode);
182  process_global_attachments<Face>(grid, gridNode);
183  process_global_attachments<Volume>(grid, gridNode);
184 
185  return true;
186 }
187 
188 //template <class TPositionAttachment>
189 //void GridWriterUGX::
190 //add_grid(MultiGrid& mg, const char* name,
191 // TPositionAttachment& aPos)
192 //{
193 //}
194 
195 template <class TElem>
196 const char* GridWriterUGX::
198 {
199  static const char* attachmentNodeNames[4] = {"vertex_attachment",
200  "edge_attachment",
201  "face_attachment",
202  "volume_attachment"};
203  return attachmentNodeNames[TElem::BASE_OBJECT_ID];
204 }
205 
206 
207 template <class TElem, class TAttachment>
209 add_attachment(TAttachment attachment,
210  const char* name,
211  size_t refGridIndex)
212 {
213  using namespace rapidxml;
214  using namespace std;
215 
216  UG_COND_THROW(refGridIndex >= m_vEntries.size(),
217  "Invalid refGridIndex: " << refGridIndex
218  << ", but only " << m_vEntries.size() << " grids available.");
219 
220  Grid& grid = *m_vEntries[refGridIndex].grid;
221  stringstream ss;
222 
223  if(!grid.has_attachment<TElem>(attachment))
224  return;
225 
226  Grid::AttachmentAccessor<TElem, TAttachment> aaVal(grid, attachment);
227 
228  const typename Grid::traits<TElem>::iterator iterEnd = grid.end<TElem>();
229  for(typename Grid::traits<TElem>::iterator iter = grid.begin<TElem>();
230  iter != iterEnd;)
231  {
233  UG_COND_THROW(!ss, "Failed to write attachment entry.\n");
234  ++iter;
235  if(iter != iterEnd)
236  ss << " ";
237  }
238 
239 // create the node
240  xml_node<>* node = m_doc.allocate_node(
241  node_element,
242  attachment_node_name<TElem>(),
243  m_doc.allocate_string(ss.str().c_str()));
244 
245 // attributes
246  node->append_attribute(
247  m_doc.allocate_attribute(
248  "name",
249  m_doc.allocate_string(name)));
250 
251  node->append_attribute(
252  m_doc.allocate_attribute(
253  "type",
254  m_doc.allocate_string(
256 
257 //todo: only default pass-on is stored, not the actual used one!
258  node->append_attribute(
259  m_doc.allocate_attribute(
260  "passOn",
261  m_doc.allocate_string(mkstr(int(attachment.default_pass_on_behaviour())).c_str())));
262 
263  m_vEntries[refGridIndex].node->append_node(node);
264 }
265 
266 
267 template <class TAAPos>
268 rapidxml::xml_node<>*
271  RegularVertexIterator vrtsEnd,
272  TAAPos& aaPos)
273 {
274  using namespace rapidxml;
275  using namespace std;
276 // the number of coordinates
277  const int numCoords = (int)TAAPos::ValueType::Size;
278 
279 // write the vertices to a temporary stream
280  stringstream ss;
281  ss.precision(18);
282  for(RegularVertexIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
283  {
284  for(int i = 0; i < numCoords; ++i)
285  ss << aaPos[*iter][i] << " ";
286  }
287 
288 // create the node
289  xml_node<>* node = NULL;
290 
291  if(ss.str().size() > 0){
292  // allocate a string and erase last character(' ')
293  char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
294  nodeData[ss.str().size()-1] = 0;
295  // create a node with some data
296  node = m_doc.allocate_node(node_element, "vertices", nodeData);
297  }
298  else{
299  // create an emtpy node
300  node = m_doc.allocate_node(node_element, "vertices");
301  }
302 
303  char* buff = m_doc.allocate_string(NULL, 10);
304  snprintf(buff, 10, "%d", numCoords);
305  node->append_attribute(m_doc.allocate_attribute("coords", buff));
306 
307 // return the node
308  return node;
309 }
310 
311 template <class TAAPos>
312 rapidxml::xml_node<>*
316  TAAPos& aaPos,
317  AAEdgeIndex aaIndEDGE,
318  AAFaceIndex aaIndFACE)
319 {
320  using namespace rapidxml;
321  using namespace std;
322 // the number of coordinates
323  const int numCoords = (int)TAAPos::ValueType::Size;
324 
325 // write the vertices to a temporary stream
326  stringstream ss;
327  ss.precision(18);
328  for(ConstrainedVertexIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
329  {
330  for(int i = 0; i < numCoords; ++i)
331  ss << aaPos[*iter][i] << " ";
332 
333  // write index and local coordinate of associated constraining element
334  // codes: -1: no constraining element
335  // 0: vertex. index follows (not yet supported)
336  // 1: edge. index and 1 local coordinate follow.
337  // 2: face. index and 2 local coordinates follow.
338  // 3: volume. index and 3 local coordinates follow. (not yet supported)
339  Edge* ce = dynamic_cast<Edge*>((*iter)->get_constraining_object());
340  Face* cf = dynamic_cast<Face*>((*iter)->get_constraining_object());
341  if(ce)
342  ss << "1 " << aaIndEDGE[ce] << " " << (*iter)->get_local_coordinate_1() << " ";
343  else if(cf)
344  ss << "2 " << aaIndFACE[cf] << " " << (*iter)->get_local_coordinate_1()
345  << " " << (*iter)->get_local_coordinate_2() << " ";
346  else
347  ss << "-1 ";
348  }
349 
350 // create the node
351  xml_node<>* node = NULL;
352 
353  if(ss.str().size() > 0){
354  // allocate a string and erase last character(' ')
355  char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
356  nodeData[ss.str().size()-1] = 0;
357  // create a node with some data
358  node = m_doc.allocate_node(node_element, "constrained_vertices", nodeData);
359  }
360  else{
361  // create an emtpy node
362  node = m_doc.allocate_node(node_element, "constrained_vertices");
363  }
364 
365  char* buff = m_doc.allocate_string(NULL, 10);
366  snprintf(buff, 10, "%d", numCoords);
367  node->append_attribute(m_doc.allocate_attribute("coords", buff));
368 
369 // return the node
370  return node;
371 }
372 
373 
374 template <class TElem>
376 process_global_attachments(Grid& grid, rapidxml::xml_node<>* gridNode)
377 {
378  using namespace std;
379  using namespace rapidxml;
380  const vector<string>& attachmentNames = GlobalAttachments::declared_attachment_names();
381 
382  for(size_t ia = 0; ia < attachmentNames.size(); ++ia){
383  const std::string& name = attachmentNames[ia];
384  if(!GlobalAttachments::is_attached<TElem>(grid, name))
385  continue;
386 
387  stringstream ss;
388  GlobalAttachments::write_attachment_values<TElem>(ss, grid, name);
389 
390  // create the node
391  xml_node<>* node = m_doc.allocate_node(
392  node_element,
393  attachment_node_name<TElem>(),
394  m_doc.allocate_string(ss.str().c_str()));
395 
396  // attributes
397  node->append_attribute(
398  m_doc.allocate_attribute(
399  "name",
400  m_doc.allocate_string(name.c_str())));
401 
402  node->append_attribute(
403  m_doc.allocate_attribute(
404  "type",
405  m_doc.allocate_string(
407 
408  node->append_attribute(
409  m_doc.allocate_attribute(
410  "passOn",
411  m_doc.allocate_string(mkstr(int(
413 
414  node->append_attribute(
415  m_doc.allocate_attribute(
416  "global",
417  m_doc.allocate_string("1")));
418 
419  gridNode->append_node(node);
420  }
421 }
422 
423 
426 // implementation of GridReaderUGX
427 template <class TPositionAttachment>
429 grid(Grid& gridOut, size_t index,
430  TPositionAttachment& aPos)
431 {
432  using namespace rapidxml;
433  using namespace std;
434 
435 // make sure that a node at the given index exists
436  if(num_grids() <= index){
437  UG_LOG(" GridReaderUGX::read: bad grid index!\n");
438  return false;
439  }
440 
441  Grid& grid = gridOut;
442 
443 // Since we have to create all elements in the correct order and
444 // since we have to make sure that no elements are created in between,
445 // we'll first disable all grid-options and reenable them later on
446  uint gridopts = grid.get_options();
448 
449 // access node data
450  if(!grid.has_vertex_attachment(aPos)){
451  grid.attach_to_vertices(aPos);
452  }
453 
455 
456 // store the grid in the grid-vector and assign indices to the vertices
457  m_entries[index].grid = &grid;
458 
459 // get the grid-node and the vertex-vector
460  xml_node<>* gridNode = m_entries[index].node;
461  vector<Vertex*>& vertices = m_entries[index].vertices;
462  vector<Edge*>& edges = m_entries[index].edges;
463  vector<Face*>& faces = m_entries[index].faces;
464  vector<Volume*>& volumes = m_entries[index].volumes;
465 
466 // we'll record constraining objects for constrained-vertices and constrained-edges
467  std::vector<std::pair<int, int> > constrainingObjsVRT;
468  std::vector<std::pair<int, int> > constrainingObjsEDGE;
469  std::vector<std::pair<int, int> > constrainingObjsTRI;
470  std::vector<std::pair<int, int> > constrainingObjsQUAD;
471 
472 // iterate through the nodes in the grid and create the entries
473  xml_node<>* curNode = gridNode->first_node();
474  for(;curNode; curNode = curNode->next_sibling()){
475  bool bSuccess = true;
476  const char* name = curNode->name();
477  if(strcmp(name, "vertices") == 0)
478  bSuccess = create_vertices(vertices, grid, curNode, aaPos);
479  else if(strcmp(name, "constrained_vertices") == 0)
480  bSuccess = create_constrained_vertices(vertices, constrainingObjsVRT,
481  grid, curNode, aaPos);
482  else if(strcmp(name, "edges") == 0)
483  bSuccess = create_edges(edges, grid, curNode, vertices);
484  else if(strcmp(name, "constraining_edges") == 0)
485  bSuccess = create_constraining_edges(edges, grid, curNode, vertices);
486  else if(strcmp(name, "constrained_edges") == 0)
487  bSuccess = create_constrained_edges(edges, constrainingObjsEDGE,
488  grid, curNode, vertices);
489  else if(strcmp(name, "triangles") == 0)
490  bSuccess = create_triangles(faces, grid, curNode, vertices);
491  else if(strcmp(name, "constraining_triangles") == 0)
492  bSuccess = create_constraining_triangles(faces, grid, curNode, vertices);
493  else if(strcmp(name, "constrained_triangles") == 0)
494  bSuccess = create_constrained_triangles(faces, constrainingObjsTRI,
495  grid, curNode, vertices);
496  else if(strcmp(name, "quadrilaterals") == 0)
497  bSuccess = create_quadrilaterals(faces, grid, curNode, vertices);
498  else if(strcmp(name, "constraining_quadrilaterals") == 0)
499  bSuccess = create_constraining_quadrilaterals(faces, grid, curNode, vertices);
500  else if(strcmp(name, "constrained_quadrilaterals") == 0)
501  bSuccess = create_constrained_quadrilaterals(faces, constrainingObjsQUAD,
502  grid, curNode, vertices);
503  else if(strcmp(name, "tetrahedrons") == 0)
504  bSuccess = create_tetrahedrons(volumes, grid, curNode, vertices);
505  else if(strcmp(name, "hexahedrons") == 0)
506  bSuccess = create_hexahedrons(volumes, grid, curNode, vertices);
507  else if(strcmp(name, "prisms") == 0)
508  bSuccess = create_prisms(volumes, grid, curNode, vertices);
509  else if(strcmp(name, "pyramids") == 0)
510  bSuccess = create_pyramids(volumes, grid, curNode, vertices);
511  else if(strcmp(name, "octahedrons") == 0)
512  bSuccess = create_octahedrons(volumes, grid, curNode, vertices);
513 
514  else if(strcmp(name, "vertex_attachment") == 0)
515  bSuccess = read_attachment<Vertex>(grid, curNode);
516  else if(strcmp(name, "edge_attachment") == 0)
517  bSuccess = read_attachment<Edge>(grid, curNode);
518  else if(strcmp(name, "face_attachment") == 0)
519  bSuccess = read_attachment<Face>(grid, curNode);
520  else if(strcmp(name, "volume_attachment") == 0)
521  bSuccess = read_attachment<Volume>(grid, curNode);
522 
523 
524  if(!bSuccess){
525  grid.set_options(gridopts);
526  return false;
527  }
528  }
529 
530 // resolve constrained object relations
531  if(!constrainingObjsVRT.empty()){
532  //UG_LOG("num-edges: " << edges.size() << std::endl);
533  // iterate over the pairs.
534  // at the same time we'll iterate over the constrained vertices since
535  // they are synchronized.
537  for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsVRT.begin();
538  iter != constrainingObjsVRT.end(); ++iter, ++hvIter)
539  {
540  ConstrainedVertex* hv = *hvIter;
541 
542  switch(iter->first){
543  case 1: // constraining object is an edge
544  {
545  // make sure that the index is valid
546  if(iter->second >= 0 && iter->second < (int)edges.size()){
547  // get the edge
548  ConstrainingEdge* edge = dynamic_cast<ConstrainingEdge*>(edges[iter->second]);
549  if(edge){
550  hv->set_constraining_object(edge);
551  edge->add_constrained_object(hv);
552  }
553  else{
554  UG_LOG("WARNING: Type-ID / type mismatch. Ignoring edge " << iter->second << ".\n");
555  }
556  }
557  else{
558  UG_LOG("ERROR in GridReaderUGX: Bad edge index in constrained vertex: " << iter->second << "\n");
559  }
560  }break;
561 
562  case 2: // constraining object is an face
563  {
564  // make sure that the index is valid
565  if(iter->second >= 0 && iter->second < (int)faces.size()){
566  // get the edge
567  ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
568  if(face){
569  hv->set_constraining_object(face);
570  face->add_constrained_object(hv);
571  }
572  else{
573  UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
574  }
575  }
576  else{
577  UG_LOG("ERROR in GridReaderUGX: Bad face index in constrained vertex: " << iter->second << "\n");
578  }
579  }break;
580 
581  default:
582  {
583 // UG_LOG("WARNING in GridReaderUGX: unsupported type-id of constraining vertex"
584 // << " at " << GetGridObjectCenter(grid, hv) << "\n");
585  break;
586  }
587  }
588  }
589  }
590 
591  if(!constrainingObjsEDGE.empty()){
592  // iterate over the pairs.
593  // at the same time we'll iterate over the constrained vertices since
594  // they are synchronized.
596  for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsEDGE.begin();
597  iter != constrainingObjsEDGE.end(); ++iter, ++ceIter)
598  {
599  ConstrainedEdge* ce = *ceIter;
600 
601  switch(iter->first){
602  case 1: // constraining object is an edge
603  {
604  // make sure that the index is valid
605  if(iter->second >= 0 && iter->second < (int)edges.size()){
606  // get the edge
607  ConstrainingEdge* edge = dynamic_cast<ConstrainingEdge*>(edges[iter->second]);
608  if(edge){
609  ce->set_constraining_object(edge);
610  edge->add_constrained_object(ce);
611  }
612  else{
613  UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring edge " << iter->second << ".\n");
614  }
615  }
616  else{
617  UG_LOG("ERROR in GridReaderUGX: Bad edge index in constrained edge.\n");
618  }
619  }break;
620  case 2: // constraining object is an face
621  {
622  // make sure that the index is valid
623  if(iter->second >= 0 && iter->second < (int)faces.size()){
624  // get the edge
625  ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
626  if(face){
627  ce->set_constraining_object(face);
628  face->add_constrained_object(ce);
629  }
630  else{
631  UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
632  }
633  }
634  else{
635  UG_LOG("ERROR in GridReaderUGX: Bad face index in constrained edge: " << iter->second << "\n");
636  }
637  }break;
638 
639  default:
640  {
641 // UG_LOG("WARNING in GridReaderUGX: unsupported type-id of constraining edge"
642 // << " at " << GetGridObjectCenter(grid, ce) << "\n");
643  break;
644  }
645  }
646  }
647  }
648 
649  if(!constrainingObjsTRI.empty()){
650  // iterate over the pairs.
651  // at the same time we'll iterate over the constrained vertices since
652  // they are synchronized.
654  for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsTRI.begin();
655  iter != constrainingObjsTRI.end(); ++iter, ++cfIter)
656  {
657  ConstrainedFace* cdf = *cfIter;
658 
659  switch(iter->first){
660  case 2: // constraining object is an face
661  {
662  // make sure that the index is valid
663  if(iter->second >= 0 && iter->second < (int)faces.size()){
664  // get the edge
665  ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
666  if(face){
667  cdf->set_constraining_object(face);
668  face->add_constrained_object(cdf);
669  }
670  else{
671  UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
672  }
673  }
674  else{
675  UG_LOG("ERROR in GridReaderUGX: Bad face index in constrained face: " << iter->second << "\n");
676  }
677  }break;
678 
679  default:
680  {
681 // UG_LOG("WARNING in GridReaderUGX: unsupported type-id of constraining triangle"
682 // << " at " << GetGridObjectCenter(grid, cdf) << "\n");
683  break;
684  }
685  }
686  }
687  }
688 
689  if(!constrainingObjsQUAD.empty()){
690  // iterate over the pairs.
691  // at the same time we'll iterate over the constrained vertices since
692  // they are synchronized.
694  for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsQUAD.begin();
695  iter != constrainingObjsQUAD.end(); ++iter, ++cfIter)
696  {
697  ConstrainedFace* cdf = *cfIter;
698 
699  switch(iter->first){
700  case 2: // constraining object is an face
701  {
702  // make sure that the index is valid
703  if(iter->second >= 0 && iter->second < (int)faces.size()){
704  // get the edge
705  ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
706  if(face){
707  cdf->set_constraining_object(face);
708  face->add_constrained_object(cdf);
709  }
710  else{
711  UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
712  }
713  }
714  else{
715  UG_LOG("ERROR in GridReaderUGX: Bad face index in constrained face: " << iter->second << "\n");
716  }
717  }break;
718 
719  default:
720  {
721 // UG_LOG("WARNING in GridReaderUGX: unsupported type-id of constraining quadrilateral"
722 // << " at " << GetGridObjectCenter(grid, cdf) << "\n");
723  break;
724  }
725  }
726  }
727  }
728 
729 // reenable the grids options.
730  grid.set_options(gridopts);
731 
732  return true;
733 }
734 
735 template <class TAAPos>
737 create_vertices(std::vector<Vertex*>& vrtsOut, Grid& grid,
738  rapidxml::xml_node<>* vrtNode, TAAPos aaPos)
739 {
740  using namespace rapidxml;
741  using namespace std;
742 
743  int numSrcCoords = -1;
744  xml_attribute<>* attrib = vrtNode->first_attribute("coords");
745  if(attrib)
746  numSrcCoords = atoi(attrib->value());
747 
748  int numDestCoords = (int)TAAPos::ValueType::Size;
749 
750  assert(numDestCoords > 0 && "bad position attachment type");
751 
752  if(numSrcCoords < 1 || numDestCoords < 1)
753  return false;
754 
755 // create a buffer with which we can access the data
756  string str(vrtNode->value(), vrtNode->value_size());
757  stringstream ss(str, ios_base::in);
758 
759 // if numDestCoords == numSrcCoords parsing will be faster
760  if(numSrcCoords == numDestCoords){
761  while(!ss.eof()){
762  // read the data
763  typename TAAPos::ValueType v;
764 
765  for(int i = 0; i < numSrcCoords; ++i)
766  ss >> v[i];
767 
768  // make sure that everything went right
769  if(ss.fail())
770  break;
771 
772  // create a new vertex
773  RegularVertex* vrt = *grid.create<RegularVertex>();
774  vrtsOut.push_back(vrt);
775 
776  // set the coordinates
777  aaPos[vrt] = v;
778  }
779  }
780  else{
781  // we have to be careful with reading.
782  // if numDestCoords < numSrcCoords we'll ignore some coords,
783  // in the other case we'll add some 0's.
784  int minNumCoords = min(numSrcCoords, numDestCoords);
785  typename TAAPos::ValueType::value_type dummy = 0;
786 
787  while(!ss.eof()){
788  // read the data
789  typename TAAPos::ValueType v;
790 
791  int iMin;
792  for(iMin = 0; iMin < minNumCoords; ++iMin)
793  ss >> v[iMin];
794 
795  // ignore unused entries in the input buffer
796  for(int i = iMin; i < numSrcCoords; ++i)
797  ss >> dummy;
798 
799  // add 0's to the vector
800  for(int i = iMin; i < numDestCoords; ++i)
801  v[i] = 0;
802 
803  // make sure that everything went right
804  if(ss.fail())
805  break;
806 
807  // create a new vertex
808  RegularVertex* vrt = *grid.create<RegularVertex>();
809  vrtsOut.push_back(vrt);
810 
811  // set the coordinates
812  aaPos[vrt] = v;
813  }
814  }
815 
816  return true;
817 }
818 
819 template <class TAAPos>
821 create_constrained_vertices(std::vector<Vertex*>& vrtsOut,
822  std::vector<std::pair<int, int> >& constrainingObjsOut,
823  Grid& grid, rapidxml::xml_node<>* vrtNode, TAAPos aaPos)
824 {
825  using namespace rapidxml;
826  using namespace std;
827 
828  int numSrcCoords = -1;
829  xml_attribute<>* attrib = vrtNode->first_attribute("coords");
830  if(attrib)
831  numSrcCoords = atoi(attrib->value());
832 
833  int numDestCoords = (int)TAAPos::ValueType::Size;
834 
835  assert(numDestCoords > 0 && "bad position attachment type");
836 
837  if(numSrcCoords < 1 || numDestCoords < 1)
838  return false;
839 
840 // create a buffer with which we can access the data
841  string str(vrtNode->value(), vrtNode->value_size());
842  stringstream ss(str, ios_base::in);
843 
844 // we have to be careful with reading.
845 // if numDestCoords < numSrcCoords we'll ignore some coords,
846 // in the other case we'll add some 0's.
847  int minNumCoords = min(numSrcCoords, numDestCoords);
848  typename TAAPos::ValueType::value_type dummy = 0;
849 
850 //todo: speed could be improved, if dest and src position types have the same dimension
851  while(!ss.eof()){
852  // read the data
853  typename TAAPos::ValueType v;
854 
855  int iMin;
856  for(iMin = 0; iMin < minNumCoords; ++iMin)
857  ss >> v[iMin];
858 
859  // ignore unused entries in the input buffer
860  for(int i = iMin; i < numSrcCoords; ++i)
861  ss >> dummy;
862 
863  // add 0's to the vector
864  for(int i = iMin; i < numDestCoords; ++i)
865  v[i] = 0;
866 
867  // now read the type of the constraining object and its index
868  int conObjType = -1;
869  int conObjIndex = -1;
870  ss >> conObjType;
871 
872  if(conObjType != -1)
873  ss >> conObjIndex;
874 
875  // depending on the constrainings object type, we'll read local coordinates
876  vector3 localCoords(0, 0, 0);
877  switch(conObjType){
878  case 1: // an edge. read one local coord
879  ss >> localCoords.x();
880  break;
881  case 2: // a face. read two local coords
882  ss >> localCoords.x() >> localCoords.y();
883  break;
884  default:
885  break;
886  }
887 
888  // make sure that everything went right
889  if(ss.fail())
890  break;
891 
892  // create a new vertex
894  vrtsOut.push_back(vrt);
895 
896  // set the coordinates
897  aaPos[vrt] = v;
898 
899  // set local coordinates
900  vrt->set_local_coordinates(localCoords.x(), localCoords.y());
901 
902  // add the constraining object id and index to the list
903  constrainingObjsOut.push_back(std::make_pair(conObjType, conObjIndex));
904  }
905 
906  return true;
907 }
908 
909 
910 template <class TElem>
912 read_attachment(Grid& grid, rapidxml::xml_node<>* node)
913 {
914  using namespace rapidxml;
915  using namespace std;
916 
917  xml_attribute<>* attribName = node->first_attribute("name");
918  UG_COND_THROW(!attribName, "Invalid attachment entry: No 'name' attribute was supplied!");
919  string name = attribName->value();
920 
921  xml_attribute<>* attribType = node->first_attribute("type");
922  UG_COND_THROW(!attribType, "Invalid attachment entry: No 'type' attribute was supplied!");
923  string type = attribType->value();
924 
925  bool global = false;
926  if (xml_attribute<>* attrib = node->first_attribute("global")){
927  global = bool(atoi(attrib->value()));
928  }
929 
930  bool passOn = false;
931  if (xml_attribute<>* attrib = node->first_attribute("passOn")){
932  passOn = bool(atoi(attrib->value()));
933  }
934 
935  if(global && !GlobalAttachments::is_declared(name)){
938  // GlobalAttachments::mark_attachment_as_locally_declared(name);
939  }
940  else
941  return true;
942  }
943 
944  UG_COND_THROW(type.compare(GlobalAttachments::type_name(name)) != 0,
945  "Attachment type mismatch. Expecting type: " <<
947  << ", but given type is: " << type);
948 
949  string str(node->value(), node->value_size());
950  stringstream ss(str, ios_base::in);
951  GlobalAttachments::read_attachment_values<TElem>(ss, grid, name);
952 
953  return true;
954 }
955 
956 }// end of namespace
957 
958 #endif
location name
Definition: checkpoint_util.lua:128
Definition: smart_pointer.h:108
This edge is a sub-edge of a.
Definition: grid_objects_1d.h:146
void set_constraining_object(GridObject *pObj)
Definition: grid_objects_1d.h:218
This class stores the constraining object.
Definition: grid_objects_2d.h:383
void set_constraining_object(GridObject *pObj)
Definition: grid_objects_2d.h:395
a quadrilateral constrained by another object.
Definition: grid_objects_2d.h:501
a triangle constrained by another object.
Definition: grid_objects_2d.h:440
A vertex appearing on edges or faces.
Definition: grid_objects_0d.h:110
void set_constraining_object(GridObject *constrObj)
Definition: grid_objects_0d.h:143
void set_local_coordinates(number x, number y)
Definition: grid_objects_0d.h:167
contains elements of type
Definition: grid_objects_1d.h:279
void add_constrained_object(Vertex *pObj)
Definition: grid_objects_1d.h:353
This class is used to store constrained geometric objects.
Definition: grid_objects_2d.h:562
void add_constrained_object(Vertex *pObj)
Definition: grid_objects_2d.h:584
Base-class for edges.
Definition: grid_base_objects.h:397
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
static const std::vector< std::string > & declared_attachment_names()
Definition: global_attachments.h:105
static bool type_is_registered(const std::string &typeName)
Definition: global_attachments.h:124
static bool attachment_pass_on_behaviour(const std::string &name)
Definition: global_attachments.h:117
static void declare_attachment(const std::string &name, bool passOnBehaviour=false)
Definition: global_attachments.h:47
static bool is_declared(const std::string &name)
Definition: global_attachments.h:111
static const char * type_name(const std::string &name)
Definition: global_attachments.h:213
the generic attachment-accessor for access to grids attachment pipes.
Definition: grid.h:182
Definition: grid.h:211
Definition: grid.h:221
Manages the elements of a grid and their interconnection.
Definition: grid.h:132
size_t num() const
Definition: grid_impl.hpp:230
bool has_attachment(IAttachment &attachment)
Definition: grid.h:796
geometry_traits< TGeomObj >::iterator begin()
Definition: grid_impl.hpp:164
bool has_vertex_attachment(IAttachment &attachment)
Definition: grid.h:798
void set_options(uint options)
Definition: grid.cpp:701
void attach_to_vertices(IAttachment &attachment, bool passOnValues)
Definition: grid.h:728
geometry_traits< TGeomObj >::iterator create(GridObject *pParent=NULL)
create a custom element.
Definition: grid_impl.hpp:69
geometry_traits< TGeomObj >::iterator end()
Definition: grid_impl.hpp:175
uint get_options() const
Definition: grid.cpp:706
Grants read access to ugx files.
Definition: file_io_ugx.h:301
bool parse_file(const char *filename)
parses an xml file
Definition: file_io_ugx.cpp:1304
bool projection_handler(ProjectionHandler &phOut, size_t phIndex, size_t refGridIndex)
fills the given projection-handler
Definition: file_io_ugx.cpp:1266
size_t num_projection_handlers(size_t refGridIndex) const
returns the number of projection-handlers for the given grid
Definition: file_io_ugx.cpp:1196
bool create_vertices(std::vector< Vertex * > &vrtsOut, Grid &grid, rapidxml::xml_node<> *vrtNode, TAAPos aaPos)
creates vertices from a vertex-node.
Definition: file_io_ugx_impl.hpp:737
bool create_constrained_vertices(std::vector< Vertex * > &vrtsOut, std::vector< std::pair< int, int > > &constrainingObjsOut, Grid &grid, rapidxml::xml_node<> *vrtNode, TAAPos aaPos)
Definition: file_io_ugx_impl.hpp:821
size_t num_grids() const
returns the number of grids
Definition: file_io_ugx.h:310
bool read_attachment(Grid &grid, rapidxml::xml_node<> *node)
Definition: file_io_ugx_impl.hpp:912
size_t get_projection_handler_subset_handler_index(size_t phIndex, size_t refGridIndex)
returns the subset handler index for a projection handler
Definition: file_io_ugx.cpp:1221
const char * get_subset_handler_name(size_t refGridIndex, size_t subsetHandlerIndex) const
returns the name of the given subset handler
Definition: file_io_ugx.cpp:957
bool subset_handler(ISubsetHandler &shOut, size_t subsetHandlerIndex, size_t refGridIndex)
fills the given subset-handler
Definition: file_io_ugx.cpp:970
size_t num_subset_handlers(size_t refGridIndex) const
returns the number of subset handlers for the given grid
Definition: file_io_ugx.cpp:945
bool grid(Grid &gridOut, size_t index, TPositionAttachment &aPos)
returns the i-th grid.
Definition: file_io_ugx_impl.hpp:429
Grants write access to ugx files.
Definition: file_io_ugx.h:108
rapidxml::xml_document m_doc
the xml_document which stores the data
Definition: file_io_ugx.h:283
void add_elements_to_node(rapidxml::xml_node<> *node, Grid &grid)
adds grid elements (edges, faces, volumes) to the given node.
Definition: file_io_ugx.cpp:424
void add_attachment(TAttachment attachment, const char *name, size_t refGridIndex)
Definition: file_io_ugx_impl.hpp:209
void process_global_attachments(Grid &grid, rapidxml::xml_node<> *gridNode)
Definition: file_io_ugx_impl.hpp:376
std::vector< Entry > m_vEntries
List of accessible grids.
Definition: file_io_ugx.h:286
rapidxml::xml_node * create_constrained_vertex_node(ConstrainedVertexIterator vrtsBegin, ConstrainedVertexIterator vrtsEnd, TAAPos &aaPos, AAEdgeIndex aaIndEDGE, AAFaceIndex aaIndFACE)
Definition: file_io_ugx_impl.hpp:314
const char * attachment_node_name()
Definition: file_io_ugx_impl.hpp:197
AInt m_aInt
attached to vertices of each grid during add_grid.
Definition: file_io_ugx.h:289
rapidxml::xml_node * create_vertex_node(RegularVertexIterator vrtsBegin, RegularVertexIterator vrtsEnd, TAAPos &aaPos)
Definition: file_io_ugx_impl.hpp:270
bool write_to_file(const char *filename)
Definition: file_io_ugx.cpp:111
void init_grid_attachments(Grid &grid)
Definition: file_io_ugx.cpp:376
bool add_grid(Grid &grid, const char *name, TPositionAttachment &aPos)
Definition: file_io_ugx_impl.hpp:135
void add_subset_handler(ISubsetHandler &sh, const char *name, size_t refGridIndex)
Definition: file_io_ugx.cpp:152
Definition: subset_handler_interface.h:223
A basic vertex-type.
Definition: grid_objects_0d.h:62
@ GRIDOPT_NONE
Definition: grid_constants.h:91
#define UG_CATCH_THROW(msg)
Definition: error.h:64
#define UG_LOG(msg)
Definition: log.h:367
unsigned int uint
Definition: types.h:114
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
std::pair< counting_iterator< size_t >, counting_iterator< size_t > > vertices(ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:60
Definition: smart_pointer.h:814
the ug namespace
geometry_traits< ConstrainedTriangle >::iterator ConstrainedTriangleIterator
Definition: grid_objects_2d.h:487
geometry_traits< ConstrainedQuadrilateral >::iterator ConstrainedQuadrilateralIterator
Definition: grid_objects_2d.h:545
bool LoadGridFromUGX(Grid &grid, ISubsetHandler &sh, const char *filename)
Reads a grid to an ugx file.
Definition: file_io_ugx.cpp:69
bool SaveGridToUGX(Grid &grid, ISubsetHandler &sh, const char *filename)
Writes a grid to a ugx file.
Definition: file_io_ugx.cpp:55
geometry_traits< RegularVertex >::iterator RegularVertexIterator
Definition: grid_objects_0d.h:94
geometry_traits< ConstrainedVertex >::iterator ConstrainedVertexIterator
Definition: grid_objects_0d.h:196
geometry_traits< ConstrainedEdge >::iterator ConstrainedEdgeIterator
Definition: grid_objects_1d.h:264
T value_type
Definition: sparsematrix_interface.h:2
#define mkstr(s)
Comfortable (but not necessarily efficient) string building.
Definition: stringify.h:100
geometry_traits< TElem >::iterator iterator
Definition: grid.h:143
entries are stored for each grid.
Definition: file_io_ugx.h:272
Definition: attachment_info_traits.h:46
static void write_value(std::ostream &out, const_reference_type v)
Definition: attachment_io_traits.h:45