Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Conditions.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: BoundaryConditions.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description:
33 //
34 //
35 ////////////////////////////////////////////////////////////////////////////////
36 
39 #include <tinyxml.h>
40 
41 namespace Nektar
42 {
43  namespace SpatialDomains
44  {
46  : m_meshGraph(meshGraph),
47  m_session (pSession)
48 
49  {
50  Read(m_session->GetElement("Nektar/Conditions"));
51  }
52 
53 
55  {
56  }
57 
59  {
60  }
61 
62 
63  /**
64  *
65  */
66  void BoundaryConditions::Read(TiXmlElement *conditions)
67  {
68  ASSERTL0(conditions, "Unable to find CONDITIONS tag in file.");
69 
70  TiXmlElement *boundaryRegions = conditions->FirstChildElement("BOUNDARYREGIONS");
71 
72  if(boundaryRegions)
73  {
74  ReadBoundaryRegions(conditions);
75 
76  ReadBoundaryConditions(conditions);
77  }
78  }
79 
80 
81  /**
82  *
83  */
84  void BoundaryConditions::ReadBoundaryRegions(TiXmlElement *conditions)
85  {
86  // ensure boundary regions only read once per class definition
87  if(m_boundaryRegions.size() != 0)
88  {
89  return;
90  }
91 
92  TiXmlElement *boundaryRegions = conditions->FirstChildElement("BOUNDARYREGIONS");
93  ASSERTL0(boundaryRegions, "Unable to find BOUNDARYREGIONS block.");
94 
95  // See if we have boundary regions defined.
96  TiXmlElement *boundaryRegionsElement = boundaryRegions->FirstChildElement("B");
97 
98  while (boundaryRegionsElement)
99  {
100  /// All elements are of the form: "<B ID="#"> ... </B>", with
101  /// ? being the element type.
102  int indx;
103  int err = boundaryRegionsElement->QueryIntAttribute("ID", &indx);
104  ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
105 
106  TiXmlNode* boundaryRegionChild = boundaryRegionsElement->FirstChild();
107  // This is primarily to skip comments that may be present.
108  // Comments appear as nodes just like elements.
109  // We are specifically looking for text in the body
110  // of the definition.
111  while(boundaryRegionChild && boundaryRegionChild->Type() != TiXmlNode::TINYXML_TEXT)
112  {
113  boundaryRegionChild = boundaryRegionChild->NextSibling();
114  }
115 
116  ASSERTL0(boundaryRegionChild, "Unable to read variable definition body.");
117  std::string boundaryRegionStr = boundaryRegionChild->ToText()->ValueStr();
118 
119  std::string::size_type indxBeg = boundaryRegionStr.find_first_of('[') + 1;
120  std::string::size_type indxEnd = boundaryRegionStr.find_last_of(']') - 1;
121 
122  ASSERTL0(indxBeg <= indxEnd, (std::string("Error reading boundary region definition:") + boundaryRegionStr).c_str());
123 
124  std::string indxStr = boundaryRegionStr.substr(indxBeg, indxEnd - indxBeg + 1);
125 
126  if (!indxStr.empty())
127  {
128  // Extract the composites from the string and return them in a list.
130 
131  ASSERTL0(m_boundaryRegions.count(indx) == 0,
132  "Boundary region "+indxStr+ " defined more than "
133  "once!");
134 
135  m_meshGraph->GetCompositeList(indxStr, *boundaryRegion);
136  m_boundaryRegions[indx] = boundaryRegion;
137  }
138 
139  boundaryRegionsElement = boundaryRegionsElement->NextSiblingElement("B");
140  }
141  }
142 
143 
144  /**
145  *
146  */
147  void BoundaryConditions::ReadBoundaryConditions(TiXmlElement *conditions)
148  {
149  // Protect against multiple reads.
150  if(m_boundaryConditions.size() != 0)
151  {
152  return;
153  }
154 
155  // Read REGION tags
156  TiXmlElement *boundaryConditionsElement = conditions->FirstChildElement("BOUNDARYCONDITIONS");
157  ASSERTL0(boundaryConditionsElement, "Boundary conditions must be specified.");
158 
159  TiXmlElement *regionElement = boundaryConditionsElement->FirstChildElement("REGION");
160 
161  // Read R (Robin), D (Dirichlet), N (Neumann), P (Periodic) C(Cauchy) tags
162  while (regionElement)
163  {
165 
166  int boundaryRegionID;
167  int err = regionElement->QueryIntAttribute("REF", &boundaryRegionID);
168  ASSERTL0(err == TIXML_SUCCESS, "Error reading boundary region reference.");
169 
170  ASSERTL0(m_boundaryConditions.count(boundaryRegionID) == 0,
171  "Boundary region '" + boost::lexical_cast<std::string>(boundaryRegionID)
172  + "' appears multiple times.");
173 
174  // Find the boundary region corresponding to this ID.
175  std::string boundaryRegionIDStr;
176  std::ostringstream boundaryRegionIDStrm(boundaryRegionIDStr);
177  boundaryRegionIDStrm << boundaryRegionID;
178 
179  ASSERTL0(m_boundaryRegions.count(boundaryRegionID) == 1,
180  "Boundary region " + boost::lexical_cast<
181  string>(boundaryRegionID)+ " not found");
182 
183  TiXmlElement *conditionElement = regionElement->FirstChildElement();
184  std::vector<std::string> vars = m_session->GetVariables();
185 
186  while (conditionElement)
187  {
188  // Check type.
189  std::string conditionType = conditionElement->Value();
190  std::string attrData;
191 
192  // All have var specified, or else all variables are zero.
193  TiXmlAttribute *attr = conditionElement->FirstAttribute();
194 
196  std::string attrName;
197 
198  attrData = conditionElement->Attribute("VAR");
199 
200  if (!attrData.empty())
201  {
202  iter = std::find(vars.begin(), vars.end(), attrData);
203  ASSERTL0(iter != vars.end(), (std::string("Cannot find variable: ") + attrData).c_str());
204  }
205 
206  if (conditionType == "N")
207  {
208  if (attrData.empty())
209  {
210  // All variables are Neumann and are set to zero.
211  for (std::vector<std::string>::iterator varIter = vars.begin();
212  varIter != vars.end(); ++varIter)
213  {
215  (*boundaryConditions)[*varIter] = neumannCondition;
216  }
217  }
218  else
219  {
220  // Use the iterator from above, which must point to the variable.
221  attr = attr->Next();
222 
223  if (attr)
224  {
225  std::string equation, userDefined, filename;
226 
227  while(attr)
228  {
229 
230  attrName = attr->Name();
231 
232  if (attrName=="USERDEFINEDTYPE")
233  {
234 
235  // Do stuff for the user defined attribute
236  attrData = attr->Value();
237  ASSERTL0(!attrData.empty(), "USERDEFINEDTYPE attribute must have associated value.");
238 
239  // Suppose to go here?
240  m_session->SubstituteExpressions(attrData);
241 
242  userDefined = attrData;
243  }
244  else if(attrName=="VALUE")
245  {
246  ASSERTL0(attrName == "VALUE", (std::string("Unknown attribute: ") + attrName).c_str());
247 
248  attrData = attr->Value();
249  ASSERTL0(!attrData.empty(), "VALUE attribute must be specified.");
250 
251  m_session->SubstituteExpressions(attrData);
252 
253  equation = attrData;
254  }
255  else if(attrName=="FILE")
256  {
257  ASSERTL0(attrName == "FILE", (std::string("Unknown attribute: ") + attrName).c_str());
258 
259  attrData = attr->Value();
260  ASSERTL0(!attrData.empty(), "FILE attribute must be specified.");
261 
262  m_session->SubstituteExpressions(attrData);
263 
264  filename = attrData;
265  }
266  attr = attr->Next();
267  }
268  BoundaryConditionShPtr neumannCondition(MemoryManager<NeumannBoundaryCondition>::AllocateSharedPtr(m_session, equation, userDefined, filename));
269  (*boundaryConditions)[*iter] = neumannCondition;
270  }
271  else
272  {
273  // This variable's condition is zero.
275  (*boundaryConditions)[*iter] = neumannCondition;
276  }
277  }
278  }
279  else if (conditionType == "D")
280  {
281  if (attrData.empty())
282  {
283  // All variables are Dirichlet and are set to zero.
284  for (std::vector<std::string>::iterator varIter = vars.begin();
285  varIter != vars.end(); ++varIter)
286  {
288  (*boundaryConditions)[*varIter] = dirichletCondition;
289  }
290  }
291  else
292  {
293  // Use the iterator from above, which must point to the variable.
294  attr = attr->Next();
295 
296  if (attr)
297  {
298  std::string equation, userDefined, filename;
299 
300  while(attr) {
301 
302  attrName = attr->Name();
303 
304  if (attrName=="USERDEFINEDTYPE") {
305 
306  // Do stuff for the user defined attribute
307  attrData = attr->Value();
308  ASSERTL0(!attrData.empty(), "USERDEFINEDTYPE attribute must have associated value.");
309 
310  m_session->SubstituteExpressions(attrData);
311 
312  userDefined = attrData;
313  }
314  else if(attrName=="VALUE")
315  {
316  ASSERTL0(attrName == "VALUE", (std::string("Unknown attribute: ") + attrName).c_str());
317 
318  attrData = attr->Value();
319  ASSERTL0(!attrData.empty(), "VALUE attribute must have associated value.");
320 
321  m_session->SubstituteExpressions(attrData);
322 
323  equation = attrData;
324  }
325  else if(attrName=="FILE")
326  {
327  ASSERTL0(attrName == "FILE", (std::string("Unknown attribute: ") + attrName).c_str());
328 
329  attrData = attr->Value();
330  ASSERTL0(!attrData.empty(), "FILE attribute must be specified.");
331 
332  m_session->SubstituteExpressions(attrData);
333 
334  filename = attrData;
335  }
336  attr = attr->Next();
337  }
338 
339  BoundaryConditionShPtr dirichletCondition(MemoryManager<DirichletBoundaryCondition>::AllocateSharedPtr(m_session, equation, userDefined, filename));
340  (*boundaryConditions)[*iter] = dirichletCondition;
341  }
342  else
343  {
344  // This variable's condition is zero.
346  (*boundaryConditions)[*iter] = dirichletCondition;
347  }
348  }
349  }
350  else if (conditionType == "R") // Read du/dn + PRIMCOEFF u = VALUE
351  {
352  if (attrData.empty())
353  {
354  // All variables are Robin and are set to zero.
355  for (std::vector<std::string>::iterator varIter = vars.begin();
356  varIter != vars.end(); ++varIter)
357  {
359  (*boundaryConditions)[*varIter] = robinCondition;
360  }
361  }
362  else
363  {
364  // Use the iterator from above, which must
365  // point to the variable. Read the A and
366  // B attributes.
367  attr = attr->Next();
368 
369  if (attr)
370  {
371  std::string attrName1;
372  std::string attrData1;
373  std::string equation1, equation2, userDefined;
374  std::string filename;
375 
376  while(attr){
377 
378  attrName1 = attr->Name();
379 
380  if (attrName1=="USERDEFINEDTYPE") {
381 
382  // Do stuff for the user defined attribute
383  attrData1 = attr->Value();
384  ASSERTL0(!attrData1.empty(), "USERDEFINEDTYPE attribute must have associated value.");
385 
386  m_session->SubstituteExpressions(attrData1);
387 
388  userDefined = attrData1;
389 
390  }
391  else if(attrName1 == "VALUE"){
392 
393  ASSERTL0(attrName1 == "VALUE", (std::string("Unknown attribute: ") + attrName1).c_str());
394 
395  attrData1 = attr->Value();
396  ASSERTL0(!attrData1.empty(), "VALUE attributes must have associated values.");
397 
398  m_session->SubstituteExpressions(attrData1);
399 
400  equation1 = attrData1;
401 
402  attr = attr->Next();
403  ASSERTL0(attr, "Unable to read PRIMCOEFF attribute.");
404 
405  attrName1= attr->Name();
406  ASSERTL0(attrName1 == "PRIMCOEFF", (std::string("Unknown attribute: ") + attrName1).c_str());
407 
408  attrData1 = attr->Value();
409  ASSERTL0(!attrData1.empty(), "PRIMCOEFF attributes must have associated values.");
410 
411  m_session->SubstituteExpressions(attrData1);
412 
413  equation2 = attrData1;
414 
415  }
416  else if(attrName1=="FILE")
417  {
418  ASSERTL0(attrName1 == "FILE", (std::string("Unknown attribute: ") + attrName1).c_str());
419 
420  attrData1 = attr->Value();
421  ASSERTL0(!attrData1.empty(), "FILE attribute must be specified.");
422 
423  m_session->SubstituteExpressions(attrData1);
424 
425  filename = attrData1;
426  }
427  attr = attr->Next();
428 
429  }
430 
431  BoundaryConditionShPtr robinCondition(MemoryManager<RobinBoundaryCondition>::AllocateSharedPtr(m_session, equation1, equation2, userDefined, filename));
432  (*boundaryConditions)[*iter] = robinCondition;
433  }
434  else
435  {
436  // This variable's condition is zero.
438  (*boundaryConditions)[*iter] = robinCondition;
439  }
440  }
441  }
442  else if (conditionType == "P")
443  {
444  if (attrData.empty())
445  {
446  attr = attr->Next();
447 
448  if (attr)
449  {
450  attrName = attr->Name();
451 
452  ASSERTL0(attrName == "VALUE", (std::string("Unknown attribute: ") + attrName).c_str());
453 
454  attrData = attr->Value();
455  ASSERTL0(!attrData.empty(), "VALUE attribute must have associated value.");
456 
457  int beg = attrData.find_first_of("[");
458  int end = attrData.find_first_of("]");
459  std::string periodicBndRegionIndexStr = attrData.substr(beg+1,end-beg-1);
460  ASSERTL0(beg < end, (std::string("Error reading periodic boundary region definition for boundary region: ")
461  + boundaryRegionIDStrm.str()).c_str());
462 
463  vector<unsigned int> periodicBndRegionIndex;
464  bool parseGood = ParseUtils::GenerateSeqVector(periodicBndRegionIndexStr.c_str(), periodicBndRegionIndex);
465 
466  ASSERTL0(parseGood && (periodicBndRegionIndex.size()==1), (std::string("Unable to read periodic boundary condition for boundary region: ")
467  + boundaryRegionIDStrm.str()).c_str());
468 
469  BoundaryConditionShPtr periodicCondition(MemoryManager<PeriodicBoundaryCondition>::AllocateSharedPtr(periodicBndRegionIndex[0]));
470 
471  for (std::vector<std::string>::iterator varIter = vars.begin();
472  varIter != vars.end(); ++varIter)
473  {
474  (*boundaryConditions)[*varIter] = periodicCondition;
475  }
476  }
477  else
478  {
479  ASSERTL0(false, "Periodic boundary conditions should be explicitely defined");
480  }
481  }
482  else
483  {
484  // Use the iterator from above, which must point to the variable.
485  // Read the VALUE attribute. It is the next and only other attribute.
486  attr = attr->Next();
487 
488  if (attr)
489  {
490  attrName = attr->Name();
491 
492  ASSERTL0(attrName == "VALUE", (std::string("Unknown attribute: ") + attrName).c_str());
493 
494  attrData = attr->Value();
495  ASSERTL0(!attrData.empty(), "VALUE attribute must have associated value.");
496 
497  int beg = attrData.find_first_of("[");
498  int end = attrData.find_first_of("]");
499  std::string periodicBndRegionIndexStr = attrData.substr(beg+1,end-beg-1);
500  ASSERTL0(beg < end, (std::string("Error reading periodic boundary region definition for boundary region: ") + boundaryRegionIDStrm.str()).c_str());
501 
502  vector<unsigned int> periodicBndRegionIndex;
503  bool parseGood = ParseUtils::GenerateSeqVector(periodicBndRegionIndexStr.c_str(), periodicBndRegionIndex);
504 
505  ASSERTL0(parseGood && (periodicBndRegionIndex.size()==1), (std::string("Unable to read periodic boundary condition for boundary region: ") + boundaryRegionIDStrm.str()).c_str());
506 
507  BoundaryConditionShPtr periodicCondition(MemoryManager<PeriodicBoundaryCondition>::AllocateSharedPtr(periodicBndRegionIndex[0]));
508  (*boundaryConditions)[*iter] = periodicCondition;
509  }
510  else
511  {
512  ASSERTL0(false, "Periodic boundary conditions should be explicitely defined");
513  }
514  }
515  }
516  else if (conditionType == "C")
517  {
518  NEKERROR(ErrorUtil::ewarning, "Cauchy type boundary conditions not implemented.");
519  }
520 
521  conditionElement = conditionElement->NextSiblingElement();
522  }
523 
524  m_boundaryConditions[boundaryRegionID] = boundaryConditions;
525  regionElement = regionElement->NextSiblingElement("REGION");
526  }
527  }
528  }
529 }