G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsXmlGenericUtils.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
18 namespace gismo {
19 
20 namespace internal {
21 
22 template<class Object>
23 Object * getTensorBasisFromXml ( gsXmlNode * node)
24 {
25  // Note: we do not check for the Object tag here, to allow some
26  // freedom (eg. BSplineBasis instead of TensorBSplineBasis1
27  GISMO_ASSERT( !strcmp( node->name(),"Basis"), "Invalid tag when \"Basis\" was expected.");
28 
29  // Component container
30  std::vector<typename Object::CoordinateBasis* > bb;
31 
32  // Special case of reading a 1D tensor basis
33  if ( !strcmp(node->first_attribute("type")->value(),
34  gsXml<typename Object::CoordinateBasis>::type().c_str() ) ) // to do in derived
35  {
36  bb.push_back( gsXml<typename Object::CoordinateBasis>::get(node) );
37  return Object::New( bb );
38  }
39 
40  const unsigned d = Object::Dim;
41  gsXmlNode * tmp = node->first_node("Basis");
42  if ( tmp )
43  {
44  for ( unsigned i = 0; i!=d; ++i)
45  {
46  bb.push_back( gsXml<typename Object::CoordinateBasis>::get(tmp) );
47  tmp = tmp->next_sibling("Basis");
48  }
49  }
50  else
51  {
52  GISMO_ASSERT( d == 1, "Wrong data in the xml file.");
53  bb.push_back( gsXml<typename Object::CoordinateBasis>::get(node) );
54  }
55 
56  //gsDebugVar( bb.size() );
57  return Object::New( bb );
58 }
59 
60 template<class Object>
61 gsXmlNode * putTensorBasisToXml ( Object const & obj, gsXmlTree & data)
62 {
63  // Write the component bases
64  static const unsigned d = Object::Dim;
65  if (d==1)
66  return gsXml<typename Object::CoordinateBasis>::put(obj.component(0), data);
67 
68  // Add a new node (without data)
69  gsXmlNode* tp_node = internal::makeNode("Basis" , data);
70  tp_node->append_attribute( makeAttribute("type",
71  internal::gsXml<Object>::type().c_str(), data) );
72 
73  for ( unsigned i = 0; i!=d; ++i )
74  {
75  gsXmlNode* tmp =
76  internal::gsXml< typename Object::CoordinateBasis >::put(obj.component(i), data );
77  tmp->append_attribute( makeAttribute("index", i, data) );
78  tp_node->append_node(tmp);
79  }
80 
81  // All set, return the basis
82  return tp_node;
83 }
84 
85 template<class Object>
86 Object * getRationalBasisFromXml ( gsXmlNode * node)
87 {
88  GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
89  && ( !strcmp(node->first_attribute("type")->value(),
90  internal::gsXml<Object>::type().c_str() ) ),
91  "Something is wrong with the XML data: There should be a node with a "
92  <<internal::gsXml<Object>::type().c_str()<<" Basis.");
93 
94  // Read source basis
95  gsXmlNode * tmp = node->first_node("Basis");
96  typename Object::SourceBasis * src = gsXml<typename Object::SourceBasis>::get(tmp) ;
97 
98  // Read weights
99  tmp = node->first_node("weights");
100  gsMatrix<typename Object::Scalar_t> weights;
101  gsXmlAttribute* format = tmp->first_attribute("format");
102  std::string format_flag = format ? format->value() : "ascii";
103  getMatrixFromXml<typename Object::Scalar_t>(tmp, src->size(), 1, weights,
104  format_flag);
105  return new Object(src, give(weights));
106 }
107 
108 template<class Object>
109 Object * getHTensorBasisFromXml ( gsXmlNode * node)
110 {
111  GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
112  && ( !strcmp(node->first_attribute("type")->value(),
113  internal::gsXml<Object>::type().c_str() ) ),
114  "Something is wrong with the XML data: There should be a node with a "<<
115  internal::gsXml<Object>::type().c_str()<<" Basis.");
116 
117  typedef typename Object::Scalar_t T;
118  static const int d = Object::Dim;
119 
120  // Read max level
121  //unsigned lvl = atoi( node->first_attribute("levels")->value() );
122  gsXmlNode * tmp = node->first_node("Basis");
123  GISMO_ASSERT( tmp , "Expected to find a basis node.");
124 
125  // Read the Tensor-product basis
126  gsTensorBSplineBasis<d,T> * tp =
127  gsXml<gsTensorBSplineBasis<d,T> >::get(tmp);
128 
129  // Initialize the HBSplineBasis
130  std::istringstream str;
131 
132  // Insert all boxes
133  unsigned c;
134  std::vector<index_t> all_boxes;
135  for (tmp = node->first_node("box");
136  tmp; tmp = tmp->next_sibling("box"))
137  {
138  all_boxes.push_back(atoi( tmp->first_attribute("level")->value() ));
139  str.clear();
140  str.str( tmp->value() );
141  for( unsigned i = 0; i < 2*d; i++)
142  {
143  str>> c;
144  all_boxes.push_back(c);
145  }
146  }
147 
148  gsXmlAttribute * manualLevels = node->first_attribute("manualLevels");
149  bool ml = manualLevels && !strcmp(manualLevels->value(),"true");
150  Object * hbs = new Object(*tp, ml);
151  delete tp;
152 
153  if (ml)
154  {
155  index_t lvl = 1;
156  const gsXmlAttribute * id_at;
157  for (gsXmlNode * child = node->first_node("Basis");
158  child; child = child->next_sibling("Basis"))
159  {
160  id_at = child->first_attribute("level");
161  if (id_at && atoi(id_at->value()) == lvl )
162  {
163  ++lvl;
164  auto tb = memory::make_unique(
165  internal::gsXml<gsTensorBSplineBasis<d,T> >::get(child) );
166  hbs->addLevel( give(*tb) );
167  }
168  }
169  }
170 
171  hbs->refineElements(all_boxes);
172  return hbs;
173 }
174 
175 template<class Object>
176 gsXmlNode * putHTensorBasisToXml ( Object const & obj, gsXmlTree & data)
177 {
178  //typedef typename Object::Scalar_t T;
179  const int d = obj.dim();
180 
181  // Add a new node (without data)
182  gsXmlNode* tp_node = internal::makeNode("Basis" , data);
183 
184  tp_node->append_attribute( makeAttribute("type",
185  internal::gsXml<Object>::type().c_str(), data) );
186 
187  //tp_node->append_attribute( makeAttribute( "levels",2 ,data )); // deprecated
188 
189  gsXmlNode * tmp;
190  if (obj.manualLevels())
191  {
192  tp_node->append_attribute( makeAttribute("manualLevels","true", data) );
193  for (index_t l = 0; l != obj.numLevels(); l++)
194  {
195  tmp = putTensorBasisToXml(obj.tensorLevel(l), data);
196  tmp->append_attribute( makeAttribute("level", to_string(l), data ) );
197  tp_node->append_node(tmp);
198  }
199  }
200  else
201  {
202  tp_node->append_attribute( makeAttribute("manualLevels","false", data) );
203  // Write the component bases
204  tmp = putTensorBasisToXml(obj.tensorLevel(0), data);
205  tp_node->append_node(tmp);
206  }
207 
208 
209  //Output boxes
210  gsMatrix<index_t> box(1,2*d);
211 
212  for( typename Object::hdomain_type::const_literator lIter =
213  obj.tree().beginLeafIterator(); lIter.good() ; lIter.next() )
214  {
215  if ( lIter->level > 0 )
216  {
217  box.leftCols(d) = lIter.lowerCorner().transpose();
218  box.rightCols(d) = lIter.upperCorner().transpose();
219 
220  tmp = putMatrixToXml( box, data, "box" );
221 
222  tmp->append_attribute( makeAttribute("level", to_string(lIter->level), data ) );
223  tp_node->append_node(tmp);
224  }
225  }
226 
227 /*
228 // Write box history (deprecated)
229 typename Object::boxHistory const & boxes = obj.get_inserted_boxes();
230 
231 for(unsigned int i = 0; i < boxes.size(); i++)
232 {
233 box.leftCols(d) = boxes[i].lower.transpose();
234 box.rightCols(d) = boxes[i].upper.transpose();
235 
236 tmp = putMatrixToXml( box, data, "box" );
237 tmp->append_attribute( makeAttribute("level", to_string(boxes[i].level), data ) );
238 tp_node->append_node(tmp);
239 }
240 */
241 
242  // All set, return the basis
243  return tp_node;
244 }
245 
246 
247 template<class Object>
248 gsXmlNode * putRationalBasisToXml ( Object const & obj, gsXmlTree & data)
249 {
250  // Add a new node
251  gsXmlNode* rat_node = internal::makeNode("Basis" , data);
252  rat_node->append_attribute( makeAttribute("type",
253  internal::gsXml< Object >::type().c_str(), data) );
254 
255  // Write the source basis
256  gsXmlNode* tmp =
257  internal::gsXml< typename Object::SourceBasis >::put(obj.source(), data );
258  rat_node->append_node(tmp);
259 
260  // Write the weights
261  tmp = putMatrixToXml( obj.weights(), data, "weights" );
262  rat_node->append_node(tmp);
263 
264  // All done, return the node
265  return rat_node;
266 }
267 
268 
269 
270 
271 /*
272 template<class Object>
273 Object * getById(gsXmlNode * node, const int & id)
274 {
275  std::string tag = internal::gsXml<Object>::tag();
276  for (gsXmlNode * child = node->first_node(tag.c_str());
277  child; child = child->next_sibling(tag.c_str()))
278  {
279  if ( atoi(child->first_attribute("id")->value() ) == id )
280  return internal::gsXml<Object>::get(child);
281  }
282  std::cerr<<"gsXmlUtils Warning: "<< internal::gsXml<Object>::tag()
283  <<" with id="<<id<<" not found.\n";
284  return NULL;
285 }
286 */
287 
288 
289 // Helper to get the tag of an id
290 // std::string getTag(gsXmlNode * node, const int & id)
291 // {
292 // for (gsXmlNode * child = node->first_node();
293 // child; child = child->next_sibling() )
294 // if ( atoi(child->first_attribute("id")->value() ) == id )
295 // return child->name();
296 
297 // std::cerr<<"gsXmlUtils Warning: Tag with id="<<id<<" not found.\n";
298 // return "";
299 // }
300 
301 
302 
303 
305 //template<class Object>
306 //Object * getGeometryFromXml ( gsXmlNode * node);
307 template<class Object>
308 Object * getGeometryFromXml ( gsXmlNode * node)
309 {
310  //gsWarn<<"Reading "<< gsXml<Object>::type() <<" Geometry..\n";
311  assert ( ( !strcmp( node->name(),"Geometry") ) &&
312  ( !strcmp(node->first_attribute("type")->value(), gsXml<Object>::type().c_str() ) ) );
313 
314  gsXmlNode * tmp = node->first_node("Basis");
315 
316  // to do: avoid copy object here (remove Ptr)
317  typename Object::Basis::Ptr b( gsXml<typename Object::Basis>::get(tmp) );
318 
319  //gsWarn<<"Read basis from node "<< tmp <<", got "<< *b <<"\n";
320 
321  tmp = node->first_node("coefs");
322  GISMO_ASSERT( tmp, "Did not find any coefficients for "<< gsXml<Object>::type().c_str() );
323  gsXmlAttribute * at_geodim = tmp->first_attribute("geoDim");
324  GISMO_ASSERT( at_geodim , "geoDim attribute not found in Geometry XML tag");
325  unsigned geoDim = atoi(at_geodim->value() ) ;
326 
327  //gsWarn<<"Read mat "<< b->size()<<"x"<< geoDim <<"\n";
328 
329  // Read the Coefficients and store them in a matrix
330  gsMatrix<typename Object::Scalar_t> coefficient_matrix;
331  gsXmlAttribute* format = tmp->first_attribute("format");
332  std::string format_flag = format ? format->value() : "ascii";
333  getMatrixFromXml<typename Object::Scalar_t>(
334  tmp, b->size(), geoDim, coefficient_matrix, format_flag);
335 
336 
337  gsXmlAttribute* coef_order = tmp->first_attribute("order");
338  if (nullptr != coef_order)
339  if (!strcmp(coef_order->value(), "coordinates")) {
340  coefficient_matrix.transposeInPlace();
341  coefficient_matrix.resize(b->size(), geoDim);
342  }
343 
344  // Looking for transformations
345  tmp = node->first_node("transform");
347  if ( tmp )
348  {
349  for (gsXmlNode * tr = tmp->first_node();
350  tr; tr= tr->next_sibling() )
351  {
352  std::string val( tr->name() );
353 
354  if (val == "translation")
355  {
356  getMatrixFromXml<typename Object::Scalar_t>(tmp, 3, 1 ,a);
357  // coefficient_matrix->rowwise() += a->transpose(); // TO DO
358  }
359  if (val == "rotation" ) // 3d
360  {
361  getMatrixFromXml<typename Object::Scalar_t>(tmp, 4, 1, a);
362  gsEigen::Transform<typename Object::Scalar_t,3,gsEigen::Affine>
363  rot( gsEigen::AngleAxis<typename Object::Scalar_t>
364  ( a(3,0), a.template block<3,1>(0,0).normalized() ) );
365  coefficient_matrix = (coefficient_matrix. rowwise().homogeneous() *
366  rot.matrix().transpose() ).leftCols(3) ;
367 
368  }
369  if (val == "scale")
370  {
371 
372  }
373  else
374  {
375  gsWarn<< "Unidentified transform tag in XML.\n";
376  }
377  }
378  }
379 
380  Object * result = new Object(*b, coefficient_matrix);
381  return result;
382 }
383 
385 //template<class Object>
386 //gsXmlNode * putGeometryToXml ( Object const & obj, gsXmlTree & data);
387 template<class Object>
388 gsXmlNode * putGeometryToXml ( Object const & obj, gsXmlTree & data)
389 {
390  // Make a new XML Geometry node
391  gsXmlNode * bs = internal::makeNode("Geometry", data);
392  bs->append_attribute( makeAttribute("type",
393  internal::gsXml<Object>::type().c_str(), data) );
394 
395  // Add the basis
396  gsXmlNode* tmp =
397  internal::gsXml< typename Object::Basis >::put(obj.basis(), data);
398  if ( ! tmp )
399  {
400  gsWarn<<"XML Warning: Writing basis failed.\n";
401  return NULL;
402  }
403 
404  bs->append_node(tmp);
405 
406  // Write the coefficient matrix
407  tmp = putMatrixToXml( obj.coefs(), data, "coefs" );
408  tmp->append_attribute( makeAttribute("geoDim", obj.geoDim(), data) );
409  bs->append_node(tmp);
410  return bs;
411 }
412 
413 template < class T >
414 gsXmlNode * putFunctionExprToXml(const gsFunctionExpr<T> & obj, gsXmlNode * result, gsXmlTree & data)
415 {
416  std::string typeStr = gsXml<gsFunctionExpr<T> >::type();
417  gsXmlAttribute * type = internal::makeAttribute("type", typeStr, data);
418  result->append_attribute(type);
419  gsXmlAttribute * dim = internal::makeAttribute("dim", obj.domainDim(),
420  data);
421  result->append_attribute(dim);
422  // set value
423  const short_t tdim = obj.targetDim();
424  if ( tdim == 1)
425  {
426  result->value( makeValue(obj.expression(), data) );
427  }
428  else
429  {
430  gsXmlNode * cnode;
431  for (short_t c = 0; c!=tdim; ++c)
432  {
433  cnode = makeNode("c", obj.expression(c), data);
434  result->append_node(cnode);
435  }
436  }
437  return result;
438 }
439 
440 template < class T >
441 gsXmlNode * putConstantFunctionToXml(const gsConstantFunction<T> & obj,gsXmlNode * result, gsXmlTree & data)
442 {
443  std::string typeStr = "FunctionExpr";
444  gsXmlAttribute * type = internal::makeAttribute("type", typeStr, data);
445  result->append_attribute(type);
446  gsXmlAttribute * dim = internal::makeAttribute("dim", obj.domainDim(),
447  data);
448  result->append_attribute(dim);
449 
450  // set value
451  gsMatrix<T> value = obj.value();
452  result->value( makeValue( value, data, true) );
453  return result;
454 }
455 
456 template < class T >
457 gsXmlNode * putFunctionToXml ( const typename gsFunctionSet<T>::Ptr & obj, gsXmlTree & data, int index)
458 {
459  gsXmlNode * result = internal::makeNode("Function", data);
460  if (typeid(*obj) == typeid(gsFunctionExpr<T> ))
461  {
462  gsFunctionExpr<T> * ptr2 =
463  dynamic_cast<gsFunctionExpr<T> *>(obj.get());
464  result = putFunctionExprToXml(*ptr2, result, data);
465  }
466  else if (typeid(*obj) == typeid(gsConstantFunction<T> ))
467  {
468  gsConstantFunction<T> * ptr2 =
469  dynamic_cast<gsConstantFunction<T> *>(obj.get());
470  result = putConstantFunctionToXml(*ptr2, result, data);
471  }
472  gsXmlAttribute * indexNode = internal::makeAttribute("index", index,
473  data);
474  result->append_attribute(indexNode);
475  return result;
476 }
477 
478 
479 
480 
481 
482 }// end namespace internal
483 
484 }// end namespace gismo
unique_ptr< T > make_unique(T *x)
Definition: gsMemory.h:198
short_t targetDim() const
Dimension of the target space.
Definition: gsFunctionExpr.hpp:474
#define short_t
Definition: gsConfig.h:35
Provides declaration of ConstantFunction class.
S give(S &x)
Definition: gsMemory.h:266
Object * getGeometryFromXml(gsXmlNode *node)
Helper to fetch geometries.
Definition: gsXmlGenericUtils.hpp:308
#define index_t
Definition: gsConfig.h:32
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition: gsMatrix.h:38
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
gsXmlNode * putGeometryToXml(Object const &obj, gsXmlTree &data)
Helper to put geometries to XML.
Definition: gsXmlGenericUtils.hpp:388
std::string to_string(const unsigned &i)
Helper to convert small unsigned to string.
Definition: gsXml.cpp:74
#define gsWarn
Definition: gsDebug.h:50
short_t domainDim() const
Dimension of the (source) domain.
Definition: gsFunctionExpr.hpp:468
gsXmlAttribute * makeAttribute(const std::string &name, const std::string &value, gsXmlTree &data)
Helper to allocate XML attribute.
Definition: gsXml.cpp:37
gsXmlNode * makeNode(const std::string &name, gsXmlTree &data)
Helper to allocate XML node.
Definition: gsXml.cpp:54
char * makeValue(const std::string &value, gsXmlTree &data)
Helper to allocate XML value.
Definition: gsXml.cpp:32
gsXmlNode * putMatrixToXml(gsMatrix< T > const &mat, gsXmlTree &data, std::string name="Matrix")
Helper to insert matrices into XML.
Definition: gsXml.hpp:103
Class defining a multivariate (real or vector) function given by a string mathematical expression...
Definition: gsFunctionExpr.h:51