GRINS-0.6.0
bc_handling_base.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
7 // Copyright (C) 2010-2013 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 
26 // This class
27 #include "grins/bc_handling_base.h"
28 
29 // GRINS
30 #include "grins/string_utils.h"
31 
32 // libMesh
33 #include "libmesh/composite_function.h"
34 #include "libmesh/composite_fem_function.h"
35 #include "libmesh/fem_context.h"
36 #include "libmesh/fem_system.h"
37 #include "libmesh/dof_map.h"
38 #include "libmesh/dirichlet_boundaries.h"
39 #include "libmesh/periodic_boundary.h"
40 #include "libmesh/dof_map.h"
41 #include "libmesh/const_function.h"
42 #include "libmesh/parsed_function.h"
43 #include "libmesh/parsed_fem_function.h"
44 
45 namespace GRINS
46 {
47  bool BCHandlingBase::_axisymmetric = false;
48 
49  BCHandlingBase::BCHandlingBase(const std::string& physics_name)
50  : _num_periodic_bcs(0),
51  _physics_name( physics_name )
52  {
53  return;
54  }
55 
57  {
58  return;
59  }
60 
62  {
63  _neumann_bound_funcs.insert( std::make_pair( neumann_bcs.get_bc_id(), neumann_bcs ) );
64  return;
65  }
66 
68  {
69  _dirichlet_bound_funcs.push_back( dirichlet_bc );
70  return;
71  }
72 
73  void BCHandlingBase::read_bc_data( const GetPot& input, const std::string& id_str,
74  const std::string& bc_str,
75  const std::string& var_str,
76  const std::string& val_str)
77  {
78  int num_ids = input.vector_variable_size(id_str);
79  int num_bcs = input.vector_variable_size(bc_str);
80  // int num_vars = input.vector_variable_size(var_str);
81  // int num_vals = input.vector_variable_size(val_str);
82 
83  if( num_ids != num_bcs )
84  {
85  std::cerr << "Error: Must specify equal number of boundary ids and boundary conditions"
86  << std::endl;
87  libmesh_error();
88  }
89 
90  for( int i = 0; i < num_ids; i++ )
91  {
92  int bc_id = input(id_str, -1, i );
93  std::string bc_type_in = input(bc_str, "NULL", i );
94 
95  int bc_type = this->string_to_int( bc_type_in );
96 
97  std::stringstream ss;
98  ss << bc_id;
99  std::string bc_id_string = ss.str();
100 
101  std::string bc_val = input(val_str, std::string(""), i );
102 
103  std::string bc_vars = input(var_str, std::string(""), i );
104 
105  this->init_bc_types( bc_id, bc_id_string, bc_type, bc_vars, bc_val, input );
106  }
107 
108  return;
109  }
110 
111  void BCHandlingBase::init_bc_data( const libMesh::FEMSystem& /*system*/ )
112  {
113  return;
114  }
115 
116  void BCHandlingBase::init_dirichlet_bc_func_objs( libMesh::FEMSystem* system ) const
117  {
118  libMesh::DofMap& dof_map = system->get_dof_map();
119 
120  for( std::vector< DBCContainer >::const_iterator
121  it = _dirichlet_bound_funcs.begin();
122  it != _dirichlet_bound_funcs.end();
123  it++ )
124  {
125  // First, get variable names. We convert them to variable ids,
126  // both to tell the DirichletBoundary what variables to
127  // project and to tell the CompositeFunction what remapping to
128  // do.
129  std::vector<VariableName> var_names = (*it).get_var_names();
130 
131  std::vector<VariableIndex> dbc_vars;
132 
133  for( std::vector<VariableName>::const_iterator name = var_names.begin();
134  name != var_names.end();
135  name++ )
136  {
137  dbc_vars.push_back( system->variable_number( *name ) );
138  }
139 
140  // Get bc_id's
141  std::set<BoundaryID> bc_ids = (*it).get_bc_ids();
142 
143  // Get Dirichlet bc functor
144  std::tr1::shared_ptr<libMesh::FunctionBase<libMesh::Number> >
145  func = (*it).get_func();
146 
147  // Remap indices as necessary
148  if (func.get())
149  {
151  remapped_func.attach_subfunction(*func, dbc_vars);
152 
153  // Now create DirichletBoundary object and give it to libMesh
154  // libMesh makes it own copy of the DirichletBoundary so we can
155  // let this one die.
156  libMesh::DirichletBoundary dbc( bc_ids, dbc_vars,
157  remapped_func );
158 
159  dof_map.add_dirichlet_boundary( dbc );
160  }
161  else
162  {
163  // Get Dirichlet bc functor
164  const std::string& func_string = (*it).get_fem_func_string();
165 
166  libmesh_assert_not_equal_to(func_string, "");
167 
168  // Need to belatedly create Dirichlet functor since we
169  // didn't have a System object handy until now.
170  libMesh::ParsedFEMFunction<libMesh::Number>
171  func(*system, func_string);
172 
173  libMesh::CompositeFEMFunction<libMesh::Number> remapped_func;
174  remapped_func.attach_subfunction(func, dbc_vars);
175 
176  // Now create DirichletBoundary object and give it to libMesh
177  // libMesh makes it own copy of the DirichletBoundary so we can
178  // let this one die.
179  libMesh::DirichletBoundary dbc( bc_ids, dbc_vars,
180  *system,
181  remapped_func );
182 
183  dof_map.add_dirichlet_boundary( dbc );
184  }
185  }
186 
187  return;
188  }
189 
190  void BCHandlingBase::init_dirichlet_bcs( libMesh::FEMSystem* system ) const
191  {
192  libMesh::DofMap& dof_map = system->get_dof_map();
193 
194  for( std::vector<std::pair<BoundaryID,BCType> >::const_iterator it = _dirichlet_bc_map.begin();
195  it != _dirichlet_bc_map.end(); it++ )
196  {
197  this->user_init_dirichlet_bcs( system, dof_map, it->first, it->second );
198  }
199 
200  return;
201  }
202 
203  void BCHandlingBase::init_periodic_bcs( libMesh::FEMSystem* system ) const
204  {
205  /* Consistency check required to make sure user actually set periodic bc data.
206  This is needed because of the way we parse periodic boundary conditions. */
207  if( _periodic_bcs.size() != _num_periodic_bcs/2 )
208  {
209  std::cerr << "==========================================================" << std::endl
210  << "Error: Inconsistency in perioidic boundary conditions." << std::endl
211  << " There were " << _num_periodic_bcs << " deteced but " << std::endl
212  << " only " << _periodic_bcs.size() << " pairs of data " << std::endl
213  << " were set." << std::endl
214  << "==========================================================" << std::endl;
215  libmesh_error();
216  }
217 
218  libMesh::DofMap& dof_map = system->get_dof_map();
219 
220  for( std::vector< PBCContainer >::const_iterator it = _periodic_bcs.begin();
221  it != _periodic_bcs.end();
222  it++ )
223  {
224  libMesh::PeriodicBoundary bc( it->get_offset_vector() );
225  bc.myboundary = it->get_master_bcid();
226  bc.pairedboundary = it->get_slave_bcid();
227 
228  dof_map.add_periodic_boundary( bc );
229  }
230 
231  return;
232  }
233 
235  const GRINS::CachedValues& cache,
236  const bool request_jacobian,
237  const BoundaryID bc_id ) const
238  {
239  std::map< BoundaryID, BCType>::const_iterator
240  bc_map_it = _neumann_bc_map.find( bc_id );
241 
242  /* We assume that if you didn't put a boundary id in, then you didn't want to
243  set a boundary condition on that boundary. */
244  if( bc_map_it != _neumann_bc_map.end() )
245  {
246  this->user_apply_neumann_bcs( context, cache, request_jacobian,
247  bc_id, bc_map_it->second );
248  }
249  return;
250  }
251 
253  {
254  _dirichlet_bc_map.push_back( std::make_pair(bc_id, bc_type) );
255  return;
256  }
257 
259  {
260  _neumann_bc_map[bc_id] = bc_type;
261  return;
262  }
263 
265  libMesh::Real value,
266  int component )
267  {
268  _dirichlet_values[bc_id](component) = value;
269  return;
270  }
271 
273  ( BoundaryID bc_id, int component ) const
274  {
275  return (_dirichlet_values.find(bc_id)->second)(component);
276  }
277 
278  void BCHandlingBase::set_neumann_bc_value( BoundaryID bc_id, const libMesh::Point& q_in )
279  {
280  _q_values[bc_id] = q_in;
281  }
282 
283  int BCHandlingBase::string_to_int( const std::string& bc_type_in ) const
284  {
285  int bc_type_out;
286  if( bc_type_in == "periodic" )
287  {
288  bc_type_out = PERIODIC;
289  }
290  else if( bc_type_in == "constant_dirichlet" )
291  {
292  bc_type_out = CONSTANT_DIRICHLET;
293  }
294  else if( bc_type_in == "parsed_dirichlet" )
295  {
296  bc_type_out = PARSED_DIRICHLET;
297  }
298  else if( bc_type_in == "parsed_fem_dirichlet" )
299  {
300  bc_type_out = PARSED_FEM_DIRICHLET;
301  }
302  else if( bc_type_in == "axisymmetric" )
303  {
304  bc_type_out = AXISYMMETRIC;
305  this->_axisymmetric = true;
306  }
307  else
308  {
309  std::cerr << "==========================================================" << std::endl
310  << "Error: Invalid bc_type " << bc_type_in << std::endl
311  << " Physics class is " << _physics_name << std::endl
312  << "==========================================================" << std::endl;
313  libmesh_error();
314  }
315  return bc_type_out;
316  }
317 
319  const std::string& bc_id_string,
320  const int bc_type,
321  const std::string& bc_vars,
322  const std::string& bc_value,
323  const GetPot& input )
324  {
325  switch(bc_type)
326  {
327  case(PERIODIC):
328  {
329  /* We assume the periodic boundary pair will be listed by the master bc id.
330  Thus, if we have a periodic id and we don't see a list of bc ids with the
331  under the current id, we assume it's the slave id. We'll do consistency
332  checks later. */
333  _num_periodic_bcs += 1;
334  int pbc_size = input.vector_variable_size("Physics/"+_physics_name+"/periodic_wall_"+bc_id_string );
335  if( pbc_size == 0 ) break;
336 
337  // We'd better have only 2 bc ids if this is the bc list
338  if( pbc_size != 2 )
339  {
340  std::cerr << "=========================================================="
341  << "Error: Must specify exactly two boundary condition ids " << std::endl
342  << " for periodic boundary conditions. Found " << pbc_size << std::endl
343  << "==========================================================" << std::endl;
344  libmesh_error();
345  }
346 
347  int id0 = input( "Physics/"+_physics_name+"/periodic_wall_"+bc_id_string, -1, 0 );
348  int id1 = input( "Physics/"+_physics_name+"/periodic_wall_"+bc_id_string, -1, 1 );
349 
350  if( id0 == -1 || id1 == -1 )
351  {
352  std::cerr << "=========================================================="
353  << "Error: Default bc id detected for periodic bc." << std::endl
354  << " Please explicitly set periodic bc ids." << std::endl
355  << " Detected ids " << id0 << ", " << id1 << std::endl
356  << " for bc id = " << bc_id << std::endl
357  << "==========================================================" << std::endl;
358  libmesh_error();
359  }
360 
361  PBCContainer pbc;
362 
363  if( id0 == bc_id )
364  {
365  pbc.set_master_bcid( id0 );
366  pbc.set_slave_bcid( id1 );
367  }
368  else if( id1 == bc_id )
369  {
370  pbc.set_master_bcid( id1 );
371  pbc.set_slave_bcid( id0 );
372  }
373  else
374  {
375  // At least one of them had better be the master id
376  std::cerr << "=========================================================="
377  << "Error: At least one of the bcs must be the master id." << std::endl
378  << " Detected master id = " << bc_id << std::endl
379  << " Found bc ids (" << id0 << "," << id1 << ")." << std::endl
380  << "==========================================================" << std::endl;
381  libmesh_error();
382  }
383 
384  // Now populate offset vector
385  {
386  int offset_size = input.vector_variable_size("Physics/"+_physics_name+"/periodic_offset_"+bc_id_string );
387  if( offset_size == 0 )
388  {
389  // User needs to set the offset vector for the periodic boundary
390  std::cerr << "=========================================================="
391  << "Error: Offset vector not found for bc id " << bc_id << std::endl
392  << "==========================================================" << std::endl;
393  libmesh_error();
394  }
395  libMesh::RealVectorValue offset_vector;
396  for( int i = 0; i < offset_size; i++ )
397  {
398  offset_vector(i) = input("Physics/"+_physics_name+"/periodic_offset_"+bc_id_string, 0.0, i );
399  }
400 
401  pbc.set_offset_vector( offset_vector );
402  }
403 
404  // Now stash the container object for use later in initialization
405  _periodic_bcs.push_back( pbc );
406 
407  }
408  break;
409 
410  case(CONSTANT_DIRICHLET):
411  {
412  DBCContainer dirichlet_bc;
413 
414  dirichlet_bc.add_var_name(bc_vars);
415 
416  dirichlet_bc.add_bc_id(bc_id);
417 
418  libMesh::Number bc_val_num = StringUtilities::string_to_T<libMesh::Number>(bc_value);
419 
420  dirichlet_bc.set_func
421  (std::tr1::shared_ptr<libMesh::FunctionBase<libMesh::Number> >
422  (new libMesh::ConstFunction<libMesh::Number>(bc_val_num)));
423 
424  this->attach_dirichlet_bound_func(dirichlet_bc);
425  }
426  break;
427 
428  case(PARSED_DIRICHLET):
429  {
430  DBCContainer dirichlet_bc;
431 
432  dirichlet_bc.add_var_name(bc_vars);
433 
434  dirichlet_bc.add_bc_id(bc_id);
435 
436  dirichlet_bc.set_func
437  (std::tr1::shared_ptr<libMesh::FunctionBase<libMesh::Number> >
438  (new libMesh::ParsedFunction<libMesh::Number>(bc_value)));
439 
440  this->attach_dirichlet_bound_func(dirichlet_bc);
441  }
442  break;
443 
444  case(PARSED_FEM_DIRICHLET):
445  {
446  DBCContainer dirichlet_bc;
447 
448  dirichlet_bc.add_var_name(bc_vars);
449 
450  dirichlet_bc.add_bc_id(bc_id);
451 
452  dirichlet_bc.set_fem_func_string (bc_value);
453 
454  this->attach_dirichlet_bound_func(dirichlet_bc);
455  }
456  break;
457 
458  default:
459  {
460  std::cerr << "=========================================================="
461  << "Error: Invalid BC type for " << _physics_name << std::endl
462  << " Detected BC type was " << bc_type << std::endl
463  << "==========================================================" << std::endl;
464  libmesh_error();
465  }
466  }
467  return;
468  }
469 
470  void BCHandlingBase::user_init_dirichlet_bcs( libMesh::FEMSystem* /*system*/,
471  libMesh::DofMap& /*dof_map*/,
472  BoundaryID /*bc_id*/,
473  BCType /*bc_type*/ ) const
474  {
475  // Not all Physics need this so we have a do nothing default.
476  return;
477  }
478 
480  const GRINS::CachedValues& /*cache*/,
481  const bool /*request_jacobian*/,
482  const GRINS::BoundaryID /*bc_id*/,
483  const GRINS::BCType /*bc_type*/ ) const
484  {
485  // Not all Physics need this so we have a do nothing default.
486  return;
487  }
488 
489 } // namespace GRINS
void set_master_bcid(const GRINS::BoundaryID bc_id)
Add variables that are constrained by the Dirichlet bc.
Definition: pbc_container.C:44
virtual void read_bc_data(const GetPot &input, const std::string &id_str, const std::string &bc_str, const std::string &var_str, const std::string &val_str)
virtual void user_init_dirichlet_bcs(libMesh::FEMSystem *system, libMesh::DofMap &dof_map, GRINS::BoundaryID bc_id, GRINS::BCType bc_type) const
Simple helper class to setup general Dirichlet boundary conditions.
Definition: dbc_container.h:49
std::vector< GRINS::PBCContainer > _periodic_bcs
Simple helper class to setup periodic boundary conditions.
Definition: pbc_container.h:43
libMesh::boundary_id_type BoundaryID
More descriptive name of the type used for boundary ids.
Definition: var_typedefs.h:54
void attach_dirichlet_bound_func(const GRINS::DBCContainer &dirichlet_bc)
std::vector< GRINS::DBCContainer > _dirichlet_bound_funcs
void set_fem_func_string(const std::string &s)
Definition: dbc_container.C:64
virtual void apply_neumann_bcs(AssemblyContext &context, const GRINS::CachedValues &cache, const bool request_jacobian, const GRINS::BoundaryID bc_id) const
std::map< GRINS::BoundaryID, libMesh::Point > _dirichlet_values
Stash prescribed Dirichlet boundary values.
void attach_neumann_bound_func(GRINS::NBCContainer &neumann_bcs)
void set_dirichlet_bc_value(GRINS::BoundaryID bc_id, libMesh::Real value, int component=0)
void set_neumann_bc_value(GRINS::BoundaryID bc_id, const libMesh::Point &q_in)
void add_var_name(const GRINS::VariableName &var)
Add variables that are constrained by the Dirichlet bc.
Definition: dbc_container.C:46
GRINS namespace.
unsigned int _num_periodic_bcs
void set_slave_bcid(const GRINS::BoundaryID bc_id)
Definition: pbc_container.C:50
Simple helper class to setup general Neumann boundary conditions.
Definition: nbc_container.h:41
virtual void init_bc_types(const GRINS::BoundaryID bc_id, const std::string &bc_id_string, const int bc_type, const std::string &bc_vars, const std::string &bc_value, const GetPot &input)
std::vector< std::pair< BoundaryID, BCType > > _dirichlet_bc_map
Map between boundary id and Dirichlet boundary condition type.
virtual void init_dirichlet_bcs(libMesh::FEMSystem *system) const
virtual int string_to_int(const std::string &bc_type_in) const
BoundaryID get_bc_id() const
Definition: nbc_container.C:46
virtual void init_periodic_bcs(libMesh::FEMSystem *system) const
static bool _axisymmetric
Flag to cache whether or not there is an axisymmetric boundary present.
virtual void init_dirichlet_bc_func_objs(libMesh::FEMSystem *system) const
std::map< GRINS::BoundaryID, GRINS::NBCContainer > _neumann_bound_funcs
void set_offset_vector(const libMesh::RealVectorValue &offset_vector)
Definition: pbc_container.C:56
virtual void init_bc_data(const libMesh::FEMSystem &system)
Override this method to initialize any system-dependent data.
std::map< GRINS::BoundaryID, libMesh::Point > _q_values
Stash prescribed boundary fluxes.
void add_bc_id(const GRINS::BoundaryID bc_id)
Add boundary id's for which this Dirichlet bc is to be applied.
Definition: dbc_container.C:52
std::map< GRINS::BoundaryID, GRINS::BCType > _neumann_bc_map
Map between boundary id and Neumann boundary condition type.
void set_func(std::tr1::shared_ptr< libMesh::FunctionBase< libMesh::Number > > func)
Add the Dirichlet bc functor.
Definition: dbc_container.C:58
void set_neumann_bc_type(GRINS::BoundaryID bc_id, int bc_type)
int BCType
Definition: bc_types.h:32
void set_dirichlet_bc_type(GRINS::BoundaryID bc_id, int bc_type)
libMesh::Real get_dirichlet_bc_value(GRINS::BoundaryID bc_id, int component=0) const
virtual void user_apply_neumann_bcs(AssemblyContext &context, const GRINS::CachedValues &cache, const bool request_jacobian, const GRINS::BoundaryID bc_id, const GRINS::BCType bc_type) const

Generated on Mon Jun 22 2015 21:32:19 for GRINS-0.6.0 by  doxygen 1.8.9.1