Line data Source code
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>
38 : #include "lib_grid/algorithms/debug_util.h"
39 : #include "lib_grid/global_attachments.h"
40 : #include "lib_grid/refinement/projectors/projection_handler.h"
41 :
42 : namespace ug
43 : {
44 :
45 : ////////////////////////////////////////////////////////////////////////
46 : template <class TAPosition>
47 0 : bool SaveGridToUGX(Grid& grid, ISubsetHandler& sh, const char* filename,
48 : TAPosition& aPos)
49 : {
50 0 : GridWriterUGX ugxWriter;
51 0 : ugxWriter.add_grid(grid, "defGrid", aPos);
52 0 : ugxWriter.add_subset_handler(sh, "defSH", 0);
53 :
54 0 : return ugxWriter.write_to_file(filename);
55 0 : };
56 :
57 : ////////////////////////////////////////////////////////////////////////
58 : template <class TAPosition>
59 0 : 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 0 : GridReaderUGX ugxReader;
63 0 : if(!ugxReader.parse_file(filename)){
64 0 : UG_LOG("ERROR in LoadGridFromUGX: File not found: " << filename << std::endl);
65 : return false;
66 : }
67 :
68 0 : if(ugxReader.num_grids() < 1){
69 : UG_LOG("ERROR in LoadGridFromUGX: File contains no grid.\n");
70 : return false;
71 : }
72 :
73 0 : ugxReader.grid(grid, 0, aPos);
74 :
75 0 : if(ugxReader.num_subset_handlers(0) > 0)
76 0 : ugxReader.subset_handler(sh, 0, 0);
77 :
78 0 : for(size_t i_name = 0; i_name < additionalSHNames.size(); ++i_name){
79 : std::string shName = additionalSHNames[i_name];
80 0 : for(size_t i_sh = 0; i_sh < ugxReader.num_subset_handlers(0); ++i_sh){
81 0 : if(shName == ugxReader.get_subset_handler_name(0, i_sh)){
82 0 : ugxReader.subset_handler(*ash[i_name], i_sh, 0);
83 : }
84 : }
85 : }
86 :
87 0 : if((num_ph = ugxReader.num_projection_handlers(0)) != 0){
88 0 : ugxReader.projection_handler(*ph, 0, 0);
89 0 : size_t shIndex = ugxReader.get_projection_handler_subset_handler_index(0, 0);
90 : std::string shName2;
91 0 : shName2 = std::string(ugxReader.get_subset_handler_name(0, shIndex));
92 :
93 0 : if (shIndex > 0)
94 : {
95 0 : for(size_t i_name = 0; i_name < additionalSHNames.size(); ++i_name)
96 0 : if(shName2==additionalSHNames[i_name])
97 : {
98 0 : try {ph->set_subset_handler(ash[i_name]);}
99 0 : 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 0 : }
107 :
108 : template <class TAPosition>
109 0 : bool LoadGridFromUGX(Grid& grid, ISubsetHandler& sh, const char* filename,
110 : TAPosition& aPos)
111 : {
112 0 : GridReaderUGX ugxReader;
113 0 : if(!ugxReader.parse_file(filename)){
114 0 : UG_LOG("ERROR in LoadGridFromUGX: File not found: " << filename << std::endl);
115 : return false;
116 : }
117 :
118 0 : if(ugxReader.num_grids() < 1){
119 : UG_LOG("ERROR in LoadGridFromUGX: File contains no grid.\n");
120 : return false;
121 : }
122 :
123 0 : ugxReader.grid(grid, 0, aPos);
124 :
125 0 : if(ugxReader.num_subset_handlers(0) > 0)
126 0 : ugxReader.subset_handler(sh, 0, 0);
127 :
128 : return true;
129 0 : }
130 :
131 :
132 : ////////////////////////////////////////////////////////////////////////
133 : template <class TPositionAttachment>
134 0 : bool GridWriterUGX::
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 0 : if(!grid.has_vertex_attachment(aPos)){
142 0 : UG_LOG(" position attachment missing in grid " << name << endl);
143 0 : return false;
144 : }
145 :
146 : Grid::VertexAttachmentAccessor<TPositionAttachment> aaPos(grid, aPos);
147 :
148 : // create a new grid-node
149 0 : xml_node<>* gridNode = m_doc.allocate_node(node_element, "grid");
150 0 : gridNode->append_attribute(m_doc.allocate_attribute("name", name));
151 :
152 : // store the grid and the node in an entry
153 0 : m_vEntries.push_back(Entry(&grid, gridNode));
154 :
155 : // append it to the document
156 0 : m_doc.append_node(gridNode);
157 :
158 : // initialize the grids attachments
159 0 : init_grid_attachments(grid);
160 :
161 : // access indices
162 0 : Grid::EdgeAttachmentAccessor<AInt> aaIndEDGE(grid, m_aInt);
163 : Grid::FaceAttachmentAccessor<AInt> aaIndFACE(grid, m_aInt);
164 :
165 : // write vertices
166 0 : if(grid.num<RegularVertex>() > 0)
167 0 : gridNode->append_node(create_vertex_node(grid.begin<RegularVertex>(),
168 : grid.end<RegularVertex>(), aaPos));
169 :
170 : // write constrained vertices
171 0 : if(grid.num<ConstrainedVertex>() > 0)
172 0 : 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 0 : add_elements_to_node(gridNode, grid);
179 :
180 0 : process_global_attachments<Vertex>(grid, gridNode);
181 0 : process_global_attachments<Edge>(grid, gridNode);
182 0 : process_global_attachments<Face>(grid, gridNode);
183 0 : 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::
197 : attachment_node_name()
198 : {
199 : static const char* attachmentNodeNames[4] = {"vertex_attachment",
200 : "edge_attachment",
201 : "face_attachment",
202 : "volume_attachment"};
203 0 : return attachmentNodeNames[TElem::BASE_OBJECT_ID];
204 : }
205 :
206 :
207 : template <class TElem, class TAttachment>
208 : void GridWriterUGX::
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 : {
232 : attachment_io_traits<TAttachment>::write_value(ss, aaVal[*iter]);
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(
255 : attachment_info_traits<TAttachment>::type_name().c_str())));
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<>*
269 0 : GridWriterUGX::
270 : create_vertex_node(RegularVertexIterator vrtsBegin,
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 0 : stringstream ss;
281 : ss.precision(18);
282 0 : for(RegularVertexIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
283 : {
284 0 : for(int i = 0; i < numCoords; ++i)
285 0 : ss << aaPos[*iter][i] << " ";
286 : }
287 :
288 : // create the node
289 : xml_node<>* node = NULL;
290 :
291 0 : if(ss.str().size() > 0){
292 : // allocate a string and erase last character(' ')
293 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
294 0 : nodeData[ss.str().size()-1] = 0;
295 : // create a node with some data
296 0 : node = m_doc.allocate_node(node_element, "vertices", nodeData);
297 : }
298 : else{
299 : // create an emtpy node
300 0 : node = m_doc.allocate_node(node_element, "vertices");
301 : }
302 :
303 0 : char* buff = m_doc.allocate_string(NULL, 10);
304 : snprintf(buff, 10, "%d", numCoords);
305 0 : node->append_attribute(m_doc.allocate_attribute("coords", buff));
306 :
307 : // return the node
308 0 : return node;
309 0 : }
310 :
311 : template <class TAAPos>
312 : rapidxml::xml_node<>*
313 0 : GridWriterUGX::
314 : create_constrained_vertex_node(ConstrainedVertexIterator vrtsBegin,
315 : ConstrainedVertexIterator vrtsEnd,
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 0 : stringstream ss;
327 : ss.precision(18);
328 0 : for(ConstrainedVertexIterator iter = vrtsBegin; iter != vrtsEnd; ++iter)
329 : {
330 0 : for(int i = 0; i < numCoords; ++i)
331 0 : 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 0 : Edge* ce = dynamic_cast<Edge*>((*iter)->get_constraining_object());
340 0 : Face* cf = dynamic_cast<Face*>((*iter)->get_constraining_object());
341 0 : if(ce)
342 0 : ss << "1 " << aaIndEDGE[ce] << " " << (*iter)->get_local_coordinate_1() << " ";
343 0 : else if(cf)
344 0 : ss << "2 " << aaIndFACE[cf] << " " << (*iter)->get_local_coordinate_1()
345 0 : << " " << (*iter)->get_local_coordinate_2() << " ";
346 : else
347 0 : ss << "-1 ";
348 : }
349 :
350 : // create the node
351 : xml_node<>* node = NULL;
352 :
353 0 : if(ss.str().size() > 0){
354 : // allocate a string and erase last character(' ')
355 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
356 0 : nodeData[ss.str().size()-1] = 0;
357 : // create a node with some data
358 0 : node = m_doc.allocate_node(node_element, "constrained_vertices", nodeData);
359 : }
360 : else{
361 : // create an emtpy node
362 0 : node = m_doc.allocate_node(node_element, "constrained_vertices");
363 : }
364 :
365 0 : char* buff = m_doc.allocate_string(NULL, 10);
366 : snprintf(buff, 10, "%d", numCoords);
367 0 : node->append_attribute(m_doc.allocate_attribute("coords", buff));
368 :
369 : // return the node
370 0 : return node;
371 0 : }
372 :
373 :
374 : template <class TElem>
375 0 : void GridWriterUGX::
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 0 : for(size_t ia = 0; ia < attachmentNames.size(); ++ia){
383 : const std::string& name = attachmentNames[ia];
384 0 : if(!GlobalAttachments::is_attached<TElem>(grid, name))
385 0 : continue;
386 :
387 0 : stringstream ss;
388 0 : GlobalAttachments::write_attachment_values<TElem>(ss, grid, name);
389 :
390 : // create the node
391 0 : xml_node<>* node = m_doc.allocate_node(
392 : node_element,
393 : attachment_node_name<TElem>(),
394 0 : m_doc.allocate_string(ss.str().c_str()));
395 :
396 : // attributes
397 0 : node->append_attribute(
398 : m_doc.allocate_attribute(
399 : "name",
400 0 : m_doc.allocate_string(name.c_str())));
401 :
402 0 : node->append_attribute(
403 : m_doc.allocate_attribute(
404 : "type",
405 0 : m_doc.allocate_string(
406 : GlobalAttachments::type_name(name))));
407 :
408 0 : node->append_attribute(
409 : m_doc.allocate_attribute(
410 : "passOn",
411 0 : m_doc.allocate_string(mkstr(int(
412 : GlobalAttachments::attachment_pass_on_behaviour(name))).c_str())));
413 :
414 0 : node->append_attribute(
415 : m_doc.allocate_attribute(
416 : "global",
417 0 : m_doc.allocate_string("1")));
418 :
419 : gridNode->append_node(node);
420 : }
421 0 : }
422 :
423 :
424 : ////////////////////////////////////////////////////////////////////////
425 : ////////////////////////////////////////////////////////////////////////
426 : // implementation of GridReaderUGX
427 : template <class TPositionAttachment>
428 0 : bool GridReaderUGX::
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 0 : if(num_grids() <= index){
437 : UG_LOG(" GridReaderUGX::read: bad grid index!\n");
438 0 : 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 0 : uint gridopts = grid.get_options();
447 0 : grid.set_options(GRIDOPT_NONE);
448 :
449 : // access node data
450 0 : if(!grid.has_vertex_attachment(aPos)){
451 0 : grid.attach_to_vertices(aPos);
452 : }
453 :
454 : Grid::VertexAttachmentAccessor<TPositionAttachment> aaPos(grid, aPos);
455 :
456 : // store the grid in the grid-vector and assign indices to the vertices
457 0 : m_entries[index].grid = &grid;
458 :
459 : // get the grid-node and the vertex-vector
460 0 : xml_node<>* gridNode = m_entries[index].node;
461 0 : vector<Vertex*>& vertices = m_entries[index].vertices;
462 0 : vector<Edge*>& edges = m_entries[index].edges;
463 0 : vector<Face*>& faces = m_entries[index].faces;
464 0 : 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 0 : for(;curNode; curNode = curNode->next_sibling()){
475 : bool bSuccess = true;
476 : const char* name = curNode->name();
477 0 : if(strcmp(name, "vertices") == 0)
478 0 : bSuccess = create_vertices(vertices, grid, curNode, aaPos);
479 0 : else if(strcmp(name, "constrained_vertices") == 0)
480 0 : bSuccess = create_constrained_vertices(vertices, constrainingObjsVRT,
481 : grid, curNode, aaPos);
482 0 : else if(strcmp(name, "edges") == 0)
483 0 : bSuccess = create_edges(edges, grid, curNode, vertices);
484 0 : else if(strcmp(name, "constraining_edges") == 0)
485 0 : bSuccess = create_constraining_edges(edges, grid, curNode, vertices);
486 0 : else if(strcmp(name, "constrained_edges") == 0)
487 0 : bSuccess = create_constrained_edges(edges, constrainingObjsEDGE,
488 : grid, curNode, vertices);
489 0 : else if(strcmp(name, "triangles") == 0)
490 0 : bSuccess = create_triangles(faces, grid, curNode, vertices);
491 0 : else if(strcmp(name, "constraining_triangles") == 0)
492 0 : bSuccess = create_constraining_triangles(faces, grid, curNode, vertices);
493 0 : else if(strcmp(name, "constrained_triangles") == 0)
494 0 : bSuccess = create_constrained_triangles(faces, constrainingObjsTRI,
495 : grid, curNode, vertices);
496 0 : else if(strcmp(name, "quadrilaterals") == 0)
497 0 : bSuccess = create_quadrilaterals(faces, grid, curNode, vertices);
498 0 : else if(strcmp(name, "constraining_quadrilaterals") == 0)
499 0 : bSuccess = create_constraining_quadrilaterals(faces, grid, curNode, vertices);
500 0 : else if(strcmp(name, "constrained_quadrilaterals") == 0)
501 0 : bSuccess = create_constrained_quadrilaterals(faces, constrainingObjsQUAD,
502 : grid, curNode, vertices);
503 0 : else if(strcmp(name, "tetrahedrons") == 0)
504 0 : bSuccess = create_tetrahedrons(volumes, grid, curNode, vertices);
505 0 : else if(strcmp(name, "hexahedrons") == 0)
506 0 : bSuccess = create_hexahedrons(volumes, grid, curNode, vertices);
507 0 : else if(strcmp(name, "prisms") == 0)
508 0 : bSuccess = create_prisms(volumes, grid, curNode, vertices);
509 0 : else if(strcmp(name, "pyramids") == 0)
510 0 : bSuccess = create_pyramids(volumes, grid, curNode, vertices);
511 0 : else if(strcmp(name, "octahedrons") == 0)
512 0 : bSuccess = create_octahedrons(volumes, grid, curNode, vertices);
513 :
514 0 : else if(strcmp(name, "vertex_attachment") == 0)
515 0 : bSuccess = read_attachment<Vertex>(grid, curNode);
516 0 : else if(strcmp(name, "edge_attachment") == 0)
517 0 : bSuccess = read_attachment<Edge>(grid, curNode);
518 0 : else if(strcmp(name, "face_attachment") == 0)
519 0 : bSuccess = read_attachment<Face>(grid, curNode);
520 0 : else if(strcmp(name, "volume_attachment") == 0)
521 0 : bSuccess = read_attachment<Volume>(grid, curNode);
522 :
523 :
524 0 : if(!bSuccess){
525 0 : grid.set_options(gridopts);
526 : return false;
527 : }
528 : }
529 :
530 : // resolve constrained object relations
531 0 : 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.
536 : ConstrainedVertexIterator hvIter = grid.begin<ConstrainedVertex>();
537 0 : for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsVRT.begin();
538 0 : iter != constrainingObjsVRT.end(); ++iter, ++hvIter)
539 : {
540 : ConstrainedVertex* hv = *hvIter;
541 :
542 0 : switch(iter->first){
543 : case 1: // constraining object is an edge
544 : {
545 : // make sure that the index is valid
546 0 : if(iter->second >= 0 && iter->second < (int)edges.size()){
547 : // get the edge
548 0 : ConstrainingEdge* edge = dynamic_cast<ConstrainingEdge*>(edges[iter->second]);
549 0 : if(edge){
550 : hv->set_constraining_object(edge);
551 0 : edge->add_constrained_object(hv);
552 : }
553 : else{
554 0 : UG_LOG("WARNING: Type-ID / type mismatch. Ignoring edge " << iter->second << ".\n");
555 : }
556 : }
557 : else{
558 0 : 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 0 : if(iter->second >= 0 && iter->second < (int)faces.size()){
566 : // get the edge
567 0 : ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
568 0 : if(face){
569 : hv->set_constraining_object(face);
570 0 : face->add_constrained_object(hv);
571 : }
572 : else{
573 0 : UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
574 : }
575 : }
576 : else{
577 0 : 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 0 : 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.
595 : ConstrainedEdgeIterator ceIter = grid.begin<ConstrainedEdge>();
596 0 : for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsEDGE.begin();
597 0 : iter != constrainingObjsEDGE.end(); ++iter, ++ceIter)
598 : {
599 : ConstrainedEdge* ce = *ceIter;
600 :
601 0 : switch(iter->first){
602 : case 1: // constraining object is an edge
603 : {
604 : // make sure that the index is valid
605 0 : if(iter->second >= 0 && iter->second < (int)edges.size()){
606 : // get the edge
607 0 : ConstrainingEdge* edge = dynamic_cast<ConstrainingEdge*>(edges[iter->second]);
608 0 : if(edge){
609 : ce->set_constraining_object(edge);
610 0 : edge->add_constrained_object(ce);
611 : }
612 : else{
613 0 : 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 0 : if(iter->second >= 0 && iter->second < (int)faces.size()){
624 : // get the edge
625 0 : ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
626 0 : if(face){
627 : ce->set_constraining_object(face);
628 0 : face->add_constrained_object(ce);
629 : }
630 : else{
631 0 : UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
632 : }
633 : }
634 : else{
635 0 : 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 0 : 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.
653 : ConstrainedTriangleIterator cfIter = grid.begin<ConstrainedTriangle>();
654 0 : for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsTRI.begin();
655 0 : iter != constrainingObjsTRI.end(); ++iter, ++cfIter)
656 : {
657 : ConstrainedFace* cdf = *cfIter;
658 :
659 0 : switch(iter->first){
660 : case 2: // constraining object is an face
661 : {
662 : // make sure that the index is valid
663 0 : if(iter->second >= 0 && iter->second < (int)faces.size()){
664 : // get the edge
665 0 : ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
666 0 : if(face){
667 : cdf->set_constraining_object(face);
668 0 : face->add_constrained_object(cdf);
669 : }
670 : else{
671 0 : UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
672 : }
673 : }
674 : else{
675 0 : 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 0 : 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.
693 : ConstrainedQuadrilateralIterator cfIter = grid.begin<ConstrainedQuadrilateral>();
694 0 : for(std::vector<std::pair<int, int> >::iterator iter = constrainingObjsQUAD.begin();
695 0 : iter != constrainingObjsQUAD.end(); ++iter, ++cfIter)
696 : {
697 : ConstrainedFace* cdf = *cfIter;
698 :
699 0 : switch(iter->first){
700 : case 2: // constraining object is an face
701 : {
702 : // make sure that the index is valid
703 0 : if(iter->second >= 0 && iter->second < (int)faces.size()){
704 : // get the edge
705 0 : ConstrainingFace* face = dynamic_cast<ConstrainingFace*>(faces[iter->second]);
706 0 : if(face){
707 : cdf->set_constraining_object(face);
708 0 : face->add_constrained_object(cdf);
709 : }
710 : else{
711 0 : UG_LOG("WARNING in GridReaderUGX: Type-ID / type mismatch. Ignoring face " << iter->second << ".\n");
712 : }
713 : }
714 : else{
715 0 : 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 0 : grid.set_options(gridopts);
731 :
732 : return true;
733 0 : }
734 :
735 : template <class TAAPos>
736 0 : bool GridReaderUGX::
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 0 : int numSrcCoords = -1;
744 0 : xml_attribute<>* attrib = vrtNode->first_attribute("coords");
745 0 : if(attrib)
746 0 : numSrcCoords = atoi(attrib->value());
747 :
748 0 : int numDestCoords = (int)TAAPos::ValueType::Size;
749 :
750 : assert(numDestCoords > 0 && "bad position attachment type");
751 :
752 0 : if(numSrcCoords < 1 || numDestCoords < 1)
753 : return false;
754 :
755 : // create a buffer with which we can access the data
756 0 : string str(vrtNode->value(), vrtNode->value_size());
757 0 : stringstream ss(str, ios_base::in);
758 :
759 : // if numDestCoords == numSrcCoords parsing will be faster
760 0 : if(numSrcCoords == numDestCoords){
761 0 : while(!ss.eof()){
762 : // read the data
763 : typename TAAPos::ValueType v;
764 :
765 0 : for(int i = 0; i < numSrcCoords; ++i)
766 0 : ss >> v[i];
767 :
768 : // make sure that everything went right
769 0 : if(ss.fail())
770 : break;
771 :
772 : // create a new vertex
773 0 : RegularVertex* vrt = *grid.create<RegularVertex>();
774 0 : 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 0 : int minNumCoords = min(numSrcCoords, numDestCoords);
785 0 : typename TAAPos::ValueType::value_type dummy = 0;
786 :
787 0 : while(!ss.eof()){
788 : // read the data
789 : typename TAAPos::ValueType v;
790 :
791 : int iMin;
792 0 : for(iMin = 0; iMin < minNumCoords; ++iMin)
793 0 : ss >> v[iMin];
794 :
795 : // ignore unused entries in the input buffer
796 0 : for(int i = iMin; i < numSrcCoords; ++i)
797 : ss >> dummy;
798 :
799 : // add 0's to the vector
800 0 : for(int i = iMin; i < numDestCoords; ++i)
801 0 : v[i] = 0;
802 :
803 : // make sure that everything went right
804 0 : if(ss.fail())
805 : break;
806 :
807 : // create a new vertex
808 0 : RegularVertex* vrt = *grid.create<RegularVertex>();
809 0 : vrtsOut.push_back(vrt);
810 :
811 : // set the coordinates
812 : aaPos[vrt] = v;
813 : }
814 : }
815 :
816 : return true;
817 0 : }
818 :
819 : template <class TAAPos>
820 0 : bool GridReaderUGX::
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 0 : int numSrcCoords = -1;
829 0 : xml_attribute<>* attrib = vrtNode->first_attribute("coords");
830 0 : if(attrib)
831 0 : numSrcCoords = atoi(attrib->value());
832 :
833 0 : int numDestCoords = (int)TAAPos::ValueType::Size;
834 :
835 : assert(numDestCoords > 0 && "bad position attachment type");
836 :
837 0 : if(numSrcCoords < 1 || numDestCoords < 1)
838 : return false;
839 :
840 : // create a buffer with which we can access the data
841 0 : string str(vrtNode->value(), vrtNode->value_size());
842 0 : 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 0 : int minNumCoords = min(numSrcCoords, numDestCoords);
848 0 : 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 0 : while(!ss.eof()){
852 : // read the data
853 : typename TAAPos::ValueType v;
854 :
855 : int iMin;
856 0 : for(iMin = 0; iMin < minNumCoords; ++iMin)
857 0 : ss >> v[iMin];
858 :
859 : // ignore unused entries in the input buffer
860 0 : for(int i = iMin; i < numSrcCoords; ++i)
861 : ss >> dummy;
862 :
863 : // add 0's to the vector
864 0 : for(int i = iMin; i < numDestCoords; ++i)
865 0 : v[i] = 0;
866 :
867 : // now read the type of the constraining object and its index
868 0 : int conObjType = -1;
869 0 : int conObjIndex = -1;
870 0 : ss >> conObjType;
871 :
872 0 : if(conObjType != -1)
873 0 : ss >> conObjIndex;
874 :
875 : // depending on the constrainings object type, we'll read local coordinates
876 : vector3 localCoords(0, 0, 0);
877 0 : 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 0 : if(ss.fail())
890 : break;
891 :
892 : // create a new vertex
893 0 : ConstrainedVertex* vrt = *grid.create<ConstrainedVertex>();
894 0 : vrtsOut.push_back(vrt);
895 :
896 : // set the coordinates
897 : aaPos[vrt] = v;
898 :
899 : // set local coordinates
900 0 : vrt->set_local_coordinates(localCoords.x(), localCoords.y());
901 :
902 : // add the constraining object id and index to the list
903 0 : constrainingObjsOut.push_back(std::make_pair(conObjType, conObjIndex));
904 : }
905 :
906 : return true;
907 0 : }
908 :
909 :
910 : template <class TElem>
911 0 : bool GridReaderUGX::
912 : read_attachment(Grid& grid, rapidxml::xml_node<>* node)
913 : {
914 : using namespace rapidxml;
915 : using namespace std;
916 :
917 0 : xml_attribute<>* attribName = node->first_attribute("name");
918 0 : UG_COND_THROW(!attribName, "Invalid attachment entry: No 'name' attribute was supplied!");
919 0 : string name = attribName->value();
920 :
921 0 : xml_attribute<>* attribType = node->first_attribute("type");
922 0 : UG_COND_THROW(!attribType, "Invalid attachment entry: No 'type' attribute was supplied!");
923 0 : string type = attribType->value();
924 :
925 : bool global = false;
926 0 : if (xml_attribute<>* attrib = node->first_attribute("global")){
927 0 : global = bool(atoi(attrib->value()));
928 : }
929 :
930 : bool passOn = false;
931 0 : if (xml_attribute<>* attrib = node->first_attribute("passOn")){
932 0 : passOn = bool(atoi(attrib->value()));
933 : }
934 :
935 0 : if(global && !GlobalAttachments::is_declared(name)){
936 0 : if(GlobalAttachments::type_is_registered(type)){
937 0 : GlobalAttachments::declare_attachment(name, type, passOn);
938 : // GlobalAttachments::mark_attachment_as_locally_declared(name);
939 : }
940 : else
941 : return true;
942 : }
943 :
944 0 : UG_COND_THROW(type.compare(GlobalAttachments::type_name(name)) != 0,
945 : "Attachment type mismatch. Expecting type: " <<
946 : GlobalAttachments::type_name(name)
947 : << ", but given type is: " << type);
948 :
949 0 : string str(node->value(), node->value_size());
950 0 : stringstream ss(str, ios_base::in);
951 0 : GlobalAttachments::read_attachment_values<TElem>(ss, grid, name);
952 :
953 : return true;
954 0 : }
955 :
956 : }// end of namespace
957 :
958 : #endif
|