G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsBoundaryConditions.hpp
Go to the documentation of this file.
1 
14 #include <gsIO/gsXml.h>
15 #include <gsCore/gsFunctionExpr.h>
17 #include <gsUtils/gsSortedVector.h>
19 
20 namespace gismo
21 {
22 
23 namespace internal
24 {
25 
27 template<class T>
28 class gsXml< gsBoundaryConditions<T> >
29 {
30 private:
31  gsXml() { }
32  typedef gsBoundaryConditions<T> Object;
33 public:
34  GSXML_COMMON_FUNCTIONS(Object);
35  static std::string tag () { return "boundaryConditions"; }
36  static std::string type () { return ""; }
37 
38  GSXML_GET_POINTER(Object);
39 
40  static void get_into(gsXmlNode * node, Object & result)
41  {
42  GISMO_ASSERT(!strcmp(node->name(), tag().c_str()),
43  "Something went wrong. Expected tag "<< tag());
44 
45  std::istringstream str;
46  std::map<int, int> ids;
47 
48  // Check if any of the BCs is defined on a boundary set name
49  const int mp_index = atoi(node->first_attribute("multipatch")->value());
50  gsXmlNode* toplevel = node->parent();
51  std::vector< patchSide > allboundaries;
52  for (gsXmlNode * child = node->first_node("bc"); child;
53  child = child->next_sibling("bc"))
54  {
55  std::map<int, int> tmp_ids;;
56 
57  const gsXmlAttribute * att_name = child->first_attribute("name");
58  if (NULL != att_name)
59  {
60  gsXmlNode* mp_node = searchId(mp_index, toplevel);
61  GISMO_ASSERT( mp_node != NULL,
62  "No Multipatch with Id "<<mp_index<<" found in the XML data.");
63 
64  gsXmlNode * tmp = mp_node->first_node("patches");
65  std::istringstream tmp_str ;
66  tmp_str.str( tmp->value() );
67  // Handle id_range or id_index for multipatches. This is needed to assign the right indices for the BCs
68  if ( ! strcmp( tmp->first_attribute("type")->value(),"id_range") )
69  {
70  int first, last;
71  gsGetInt(tmp_str, first);
72  gsGetInt(tmp_str, last);
73  for ( int i = first; i<=last; ++i )
74  tmp_ids[i] = i - first;
75  }
76  else if ( ! strcmp( tmp->first_attribute("type")->value(),"id_index") )
77  {
78  int c = 0;
79  for (int pindex; gsGetInt(tmp_str, pindex);)
80  tmp_ids[pindex] = c++;
81  }
82  else
83  {
84  gsWarn<<"Unknown tag in XML multipatch object.\n";
85  }
86 
87  for (gsXmlNode * ch= mp_node->first_node("boundary"); ch;
88  ch = ch->next_sibling("boundary"))
89  {
90  std::vector< patchSide > tmp_boundaries;
91  if (ch)
92  {
93  getBoundaries(ch, tmp_ids, tmp_boundaries);
94  allboundaries.insert( allboundaries.end(), tmp_boundaries.begin(), tmp_boundaries.end() );
95  }
96  }
97  break;
98  }
99  }
100 
101  //gsXmlNode * tmp = node->first_node("patches");
102  //GISMO_ASSERT(tmp, "No pathes tag");
103 //
104 // std::istringstream str;
105 // str.str( tmp->value() );
106 // // Resolve ID numbers
107 // std::map<int,int> ids;
108 // if ( ! strcmp( tmp->first_attribute("type")->value(), "id_range") )
109 // {
110 // int first, last;
111 // gsGetInt(str, first);
112 // gsGetInt(str, last);
113 // for ( int i = first; i<=last; ++i )
114 // ids[i] = i - first;
115 // }
116 // else if ( ! strcmp( tmp->first_attribute("type")->value(),"id_index") )
117 // {
118 // int c = 0;
119 // for (int pindex; gsGetInt(str, pindex);)
120 // ids[pindex] = c++;
121 // }
122 // else
123 // {
124 // gsWarn<<"Incomplete tag \"patch\" in boundaryConditions.\n";
125 // }
126 
127  // Read function inventory using a map, in case indices are not
128  // consecutive
129  std::map<int, typename gsFunctionExpr<T>::Ptr> function_map{};
130  for (gsXmlNode* child = node->first_node("Function"); child;
131  child = child->next_sibling("Function")) {
132  const int function_index =
133  atoi(child->first_attribute("index")->value());
134  function_map[function_index] =
135  memory::make_shared(new gsFunctionExpr<T>);
136  internal::gsXml<gsFunctionExpr<T> >::get_into(
137  child, *function_map[function_index]);
138  }
139 
140  // Read boundary conditions
141  std::vector<patchSide> boundaries;
142  for (gsXmlNode* child = node->first_node("bc"); child;
143  child = child->next_sibling("bc")) {
144  const int uIndex = atoi(child->first_attribute("unknown")->value());
145  const int fIndex = atoi(child->first_attribute("function")->value());
146 
147  const gsXmlAttribute* comp = child->first_attribute("component");
148  int cIndex = -1;
149  if (NULL != comp) cIndex = atoi(comp->value());
150 
151  const gsXmlAttribute* att_ispar =
152  child->first_attribute("parametric");
153  bool ispar = false;
154  if (NULL != att_ispar) ispar = atoi(att_ispar->value());
155 
156  const gsXmlAttribute* att_name = child->first_attribute("name");
157  if (NULL != att_name) {
158  boundaries.clear();
159  std::string name = att_name->value();
160  for (typename std::vector<patchSide>::const_iterator it =
161  allboundaries.begin();
162  it != allboundaries.end(); it++)
163  if (it->label() == name) boundaries.push_back(*it);
164  } else
165  getBoundaries(child, ids, boundaries);
166 
167  if (boundaries.size() == 0) {
168  gsWarn << "Boundary condition without boundary to apply to. The"
169  " following bc will be unused\n"
170  << *child << std::endl;
171  }
172 
173  const gsXmlAttribute* bcat = child->first_attribute("type");
174  GISMO_ASSERT(NULL != bcat, "No type provided");
175  const char* bctype = bcat->value();
176  for (std::vector<patchSide>::const_iterator it = boundaries.begin();
177  it != boundaries.end(); ++it)
178  result.add(it->patch, it->side(), bctype, function_map[fIndex], uIndex,
179  cIndex, ispar);
180  }
181 
182  T val(0);
183  for (gsXmlNode * child = node->first_node("cv"); child;
184  child = child->next_sibling("cv"))
185  {
186  str.clear();
187  str.str(child->value());
188  GISMO_ENSURE(gsGetReal(str, val), "No value");
189 
190  // Unknown is optional, otherwise 0
191  const gsXmlAttribute * unk = child->first_attribute("unknown");
192  int uIndex = 0;
193  if (NULL != unk)
194  uIndex = atoi( unk->value() );
195 
196  // Component is optional, otherwise -1
197  const gsXmlAttribute * comp = child->first_attribute("component");
198  int cIndex = -1;
199  if (NULL != comp)
200  cIndex = atoi( comp->value() );
201 
202  const int cornIndex = atoi(child->first_attribute("corner")->value());
203  int pIndex = atoi(child->first_attribute("patch")->value());
204 
205  result.addCornerValue(cornIndex, val, pIndex, uIndex, cIndex);
206  }
207  }
208 
209  static gsXmlNode * put(const Object & obj, gsXmlTree & data)
210  {
211  // Check if the last node is a multipatch
212  //gsXmlNode * mp = data.getRoot()->last_node("MultiPatch");
213 
214  gsXmlNode * BCs = internal::makeNode("boundaryConditions", data);
215  //data.appendToRoot(BCs);
216  gsXmlAttribute * multi = internal::makeAttribute("multipatch", "0",
217  data);
218 
219  BCs->append_attribute(multi);
220 
221  // inventory of functions
222  typedef typename gsBoundaryConditions<T>::const_bciterator bctype_it;
223  typedef typename Object::const_iterator bc_it;
224 
225  std::vector<typename gsFunctionSet<T>::Ptr> fun;
226  //gsSortedVector<typename gsFunction<T>::Ptr> fun;
227  typedef typename std::vector<const boundary_condition<T>*> bctype_vec;
228  typedef typename std::map<int, bctype_vec> bctype_map;
229  std::map<std::string, bctype_map> fi;
230 
231  for (bctype_it it = obj.beginAll(); it != obj.endAll(); ++it)
232  {
233  std::string label = it->first;
234  bctype_map map;
235  for (bc_it bc = it->second.begin(); bc != it->second.end(); ++bc)
236  {
237  typename gsFunctionSet<T>::Ptr ptr = bc->function();
238  bool contains = std::find(fun.begin(), fun.end(), ptr)
239  != fun.end();
240  if (!contains)
241  {
242  fun.push_back(ptr);
243  }
244  int index = std::find(fun.begin(), fun.end(), ptr)
245  - fun.begin();
246 // fun.push_sorted_unique(ptr);
247 // int index = fun.getIndex(ptr);
248  std::vector<const boundary_condition<T>*> vec = map[index];
249  const boundary_condition<T>* b = &(*bc);
250  vec.push_back(b);
251  map[index] = vec;
252  }
253  std::pair<std::string, bctype_map> pair(label, map);
254  fi.insert(pair);
255  }
256 
257  int count = 0;
258  typedef typename std::vector<typename gsFunctionSet<T>::Ptr>::const_iterator fun_it;
259  for (fun_it fit = fun.begin(); fit != fun.end(); ++fit)
260  {
261  gsXmlNode * ff = putFunctionToXml<T>(*fit, data, count);
262  BCs->append_node(ff);
263  ++count;
264  }
265 
266  // for all bcs, append bc, cv
267  typedef typename std::map<std::string, bctype_map>::const_iterator bctype_map_it;
268  typedef typename std::map<int, bctype_vec>::const_iterator bctype_iv_it;
269  typedef typename bctype_vec::const_iterator bctype_vec_it;
270 
271  count = 0;
272  for (bctype_map_it it = fi.begin(); it != fi.end(); ++it)
273  {
274  std::string label = it->first;
275  //gsDebug << "Label='" << label << "'\n";
276  bctype_map map = it->second;
277 
278  for (bctype_iv_it bcV = map.begin(); bcV != map.end(); ++bcV)
279  {
280  int index = bcV->first;
281  bctype_vec vec = bcV->second;
282  //gsDebug << "index='" << index << "'\n";
283  //gsDebug << "vec='" << vec.size() << "'\n";
284  gsXmlNode * bcNode = internal::makeNode("bc", data);
285  gsXmlAttribute * typeNode = internal::makeAttribute("type",
286  label, data);
287  gsXmlAttribute * indexNode = internal::makeAttribute("function",
288  index, data);
289  bcNode->append_attribute(typeNode);
290  bcNode->append_attribute(indexNode);
291  bool first = true;
292  std::ostringstream oss;
293  for (bctype_vec_it bc = vec.begin(); bc != vec.end(); ++bc)
294  {
295  const boundary_condition<T> b = (**bc);
296  //gsDebug << "iterate over boundary condition with '"
297  // << b.m_label << "'\n";
298  if (first)
299  {
300  gsXmlAttribute * unknownNode = internal::makeAttribute(
301  "unknown", b.m_unknown, data);
302  gsXmlAttribute * componentNode = internal::makeAttribute("component",
303  b.unkComponent(), data);
304  bcNode->append_attribute(componentNode);
305  bcNode->append_attribute(unknownNode);
306  first = false;
307  }
308  else
309  {
310  oss << " ";
311  }
312  oss << b.ps.patch << " " << b.ps.m_index;
313  }
314  char * value = data.allocate_string(oss.str().c_str());
315  bcNode->value(value);
316  BCs->append_node(bcNode);
317  ++count;
318  }
319  }
320  typename gsBoundaryConditions<T>::const_citerator ci;
321  for (ci = obj.cornerValues().begin(); ci != obj.cornerValues().end();
322  ci++)
323  {
324  corner_value<T> c = *ci;
325  gsXmlNode * cvNode = internal::makeNode("cv", data);
326  gsXmlAttribute * unknownNode = internal::makeAttribute("unknown",
327  c.unknown, data);
328  gsXmlAttribute * componentNode = internal::makeAttribute("component",
329  c.component, data);
330  gsXmlAttribute * patchNode = internal::makeAttribute("patch",
331  c.patch, data);
332  gsXmlAttribute * cornerNode = internal::makeAttribute("corner",
333  c.corner.m_index, data);
334  cvNode->append_attribute(unknownNode);
335  cvNode->append_attribute(componentNode);
336  cvNode->append_attribute(patchNode);
337  cvNode->append_attribute(cornerNode);
338  std::ostringstream oss;
339  oss << c.value;
340  char * value = data.allocate_string(oss.str().c_str());
341  cvNode->value(value);
343  BCs->append_node(cvNode);
344  }
345  return BCs;
346  }
347 };
348 
349 } // end namespace internal
350 
351 } // end namespace gismo
Provides declaration of FunctionExpr class.
Provides declaration of ConstantFunction class.
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
gsXmlNode * searchId(const int id, gsXmlNode *root, const char *tag_name=NULL, const bool print_warning=true)
Definition: gsXml.h:254
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides implementation of generic XML functions.
#define gsWarn
Definition: gsDebug.h:50
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
An std::vector with sorting capabilities.
Provides declaration of input/output XML utilities struct.
shared_ptr< T > make_shared(T *x)
Definition: gsMemory.h:181