37 #include "libmesh/getpot.h"
38 #include "libmesh/mesh_base.h"
39 #include "libmesh/boundary_info.h"
40 #include "libmesh/parallel_mesh.h"
41 #include "libmesh/elem.h"
47 std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs )
49 libMesh::DofMap& dof_map = system.get_dof_map();
52 std::map<std::string,std::set<BoundaryID> > bc_id_map;
63 std::set<std::string> var_sections;
70 std::map<BoundaryID,std::vector<libMesh::subdomain_id_type> >
71 bc_id_to_subdomain_id_map;
74 bc_id_to_subdomain_id_map );
76 for( std::map<std::string,std::set<BoundaryID> >::const_iterator bc_it = bc_id_map.begin();
77 bc_it != bc_id_map.end(); ++bc_it )
79 const std::string& bc_name = bc_it->first;
81 const std::set<BoundaryID>& bc_ids = bc_it->second;
86 std::string type_input = type_input_section+
"/type";
88 if( input.have_variable(type_input) )
91 type_input_section,var_sections,
99 var_sections,bc_id_to_subdomain_id_map,
107 const std::set<BoundaryID>& bc_ids,
108 libMesh::DofMap& dof_map,
109 const std::string& type_input_section,
110 std::set<std::string>& var_sections,
111 std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs)
113 std::string type_input = type_input_section+
"/type";
114 std::string bc_type = input( type_input, std::string(
"DIE!") );
120 libmesh_error_msg(
"ERROR: Must specify Physics/is_axisymmetric = true for axisymmetric BC!");
124 bc_type,var_sections,neumann_bcs);
132 std::string error_msg =
"ERROR: Invalid type '"+bc_type+
"' for "+type_input+
"!\n";
135 error_msg +=
" If your boundary condition is not one of these types, then \n";
136 error_msg +=
" you must specify the boundary condition type for each Variable\n";
137 error_msg +=
" section. Please have a look at the examples.\n";
138 libmesh_error_msg(error_msg);
144 const std::set<BoundaryID>& bc_ids,
145 libMesh::DofMap& dof_map,
146 const std::string& bc_type,
147 std::set<std::string>& var_sections,
148 std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs )
154 for( std::set<std::string>::const_iterator vars = var_sections.begin();
155 vars != var_sections.end(); ++vars )
157 const std::string& var_section = *vars;
167 std::string full_bc_type = var_section+
"_"+bc_type;
176 std::string(
"dummy"),
186 std::string(
"dummy"),
191 libmesh_error_msg(
"ERROR! Invalid axisymmetric type: "+full_bc_type);
197 const std::string& bc_name,
198 const std::set<BoundaryID>& bc_ids,
199 libMesh::DofMap& dof_map,
200 std::set<std::string>& var_sections,
201 const std::map<
BoundaryID,std::vector<libMesh::subdomain_id_type> >& bc_id_to_subdomain_id_map,
202 std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs)
204 for( std::set<std::string>::const_iterator vars = var_sections.begin();
205 vars != var_sections.end(); ++vars )
207 const std::string& var_section = *vars;
217 std::map<BoundaryID,std::vector<libMesh::subdomain_id_type> >::const_iterator
218 subdomain_ids_iter = bc_id_to_subdomain_id_map.find(*bc_ids.begin());
222 std::vector<libMesh::subdomain_id_type> subdomain_ids;
223 if (subdomain_ids_iter != bc_id_to_subdomain_id_map.end())
224 subdomain_ids = subdomain_ids_iter->second;
225 system.comm().allgather(subdomain_ids);
226 std::sort( subdomain_ids.begin(), subdomain_ids.end() );
228 (std::unique(subdomain_ids.begin(), subdomain_ids.end()),
229 subdomain_ids.end() );
235 bool var_active = this->
is_var_active( fe_var, subdomain_ids );
239 if( !var_active && input.have_section(input_section) )
241 std::stringstream error_msg;
242 error_msg <<
"ERROR: Cannot specify boundary condition for variable "
243 << var_section <<
" on boundary " << bc_name << std::endl
244 <<
"since it is inactive on the subdomain associated "
245 <<
"with this boundary." << std::endl;
246 libmesh_error_msg(error_msg.str());
252 if( !input.have_section(input_section) )
257 libmesh_error_msg(
"ERROR: Could not find boundary condition specification for "+input_section+
"!");
264 std::string bc_type_section = input_section+
"/type";
265 unsigned int n_bc_types = input.vector_variable_size(bc_type_section);
267 for(
unsigned int bc_type_idx = 0; bc_type_idx < n_bc_types; bc_type_idx++ )
269 std::string bc_type = input(bc_type_section, std::string(
"DIE!"), bc_type_idx);
274 fe_var, input_section,
280 fe_var, input_section,
281 bc_type, neumann_bcs );
284 libmesh_error_msg(
"ERROR: Invalid bc_type "+bc_type+
"!");
292 std::map<std::string,std::set<BoundaryID> >& bc_id_map )
300 libmesh_error_msg(error_msg);
307 if( n_ids != n_names )
308 libmesh_error_msg(
"ERROR: Must have matching number of boundary id sets and boundary names!");
313 std::set<BoundaryID> all_bc_ids;
316 for(
unsigned int i = 0; i < n_names; i++ )
322 std::vector<std::string> bc_ids_str;
324 std::set<BoundaryID> bc_ids;
326 for(std::vector<std::string>::const_iterator it = bc_ids_str.begin();
327 it < bc_ids_str.end(); ++it )
329 BoundaryID id = StringUtilities::string_to_T<BoundaryID>(*it);
332 if( (bc_ids.find(
id) != bc_ids.end()) ||
333 (all_bc_ids.find(
id) != all_bc_ids.end()) )
334 libmesh_error_msg(
"ERROR: Can only specify a boundary ID once!");
337 all_bc_ids.insert(
id);
341 bc_id_map.insert( std::make_pair( bc_name, bc_ids ) );
346 const std::map<std::string,std::set<BoundaryID> >& bc_id_map )
const
348 const libMesh::MeshBase& mesh = system.get_mesh();
349 const libMesh::BoundaryInfo& boundary_info = mesh.get_boundary_info();
351 std::set<BoundaryID> mesh_ids = boundary_info.get_boundary_ids();
352 mesh.comm().set_union(mesh_ids);
355 std::set<BoundaryID> all_ids;
357 for( std::map<std::string,std::set<BoundaryID> >::const_iterator bc_it = bc_id_map.begin();
358 bc_it != bc_id_map.end(); ++bc_it )
359 all_ids.insert( (bc_it->second).begin(), (bc_it->second).end() );
361 if( mesh_ids != all_ids )
363 std::string err_msg =
"ERROR: Mismatch between specified boundary ids and the boundary ids in the mesh!\n";
364 err_msg +=
"User specified ids: ";
366 for( std::set<BoundaryID>::const_iterator it = all_ids.begin();
367 it != all_ids.end(); ++it )
368 err_msg += StringUtilities::T_to_string<BoundaryID>(*it)+
" ";
372 err_msg +=
"Mesh specified ids: ";
374 for( std::set<BoundaryID>::const_iterator it = mesh_ids.begin();
375 it != mesh_ids.end(); ++it )
376 err_msg += StringUtilities::T_to_string<BoundaryID>(*it)+
" ";
380 libmesh_error_msg(err_msg);
385 libMesh::System& system,
386 const std::set<BoundaryID>& bc_ids,
387 const std::string& section )
391 const libMesh::MeshBase& mesh = system.get_mesh();
392 const libMesh::ParallelMesh* pmesh =
dynamic_cast<const libMesh::ParallelMesh*
>(&mesh);
395 std::stringstream error_msg;
396 error_msg <<
"ERROR: Cannot use ParallelMesh with periodic boundary conditions!"
398 <<
" See https://github.com/libMesh/libmesh/issues/977 for discussion."
400 libmesh_error_msg(error_msg.str());
403 libMesh::boundary_id_type invalid_bid =
404 std::numeric_limits<libMesh::boundary_id_type>::max();
406 libMesh::boundary_id_type slave_id = invalid_bid;
407 libMesh::boundary_id_type master_id = invalid_bid;
411 if( bc_ids.find(slave_id) == bc_ids.end() ||
412 bc_ids.find(master_id) == bc_ids.end() )
413 libmesh_error_msg(
"ERROR: Mismatch between bc_ids and master/slave ids for perioid bcs!");
415 libMesh::RealVectorValue offset_vector =
418 libMesh::DofMap& dof_map = system.get_dof_map();
424 (
const GetPot& input,
const std::string& section,
425 libMesh::boundary_id_type& master_id,
426 libMesh::boundary_id_type& slave_id )
const
428 if( !input.have_variable(section+
"/master_id") )
429 libmesh_error_msg(
"ERROR: Could not find master_id in section "+section);
431 if( !input.have_variable(section+
"/slave_id") )
432 libmesh_error_msg(
"ERROR: Could not find slave_id in section "+section);
434 libMesh::boundary_id_type invalid_bid =
435 std::numeric_limits<libMesh::boundary_id_type>::max();
437 master_id = input(section+
"/master_id", invalid_bid);
438 slave_id = input(section+
"/slave_id", invalid_bid);
442 (
const GetPot& input,
const std::string& section)
const
444 std::string input_section = section+
"/boundary_offset";
445 if( !input.have_variable(input_section) )
446 libmesh_error_msg(
"ERROR: Could not find boundary_offset in section "+section);
448 unsigned int n_comps = input.vector_variable_size(input_section);
451 libmesh_error_msg(
"ERROR: Cannot specify more than 3 components for boundary_offset!");
453 libMesh::RealVectorValue offset;
454 libMesh::Real invalid_real = std::numeric_limits<libMesh::Real>::max();
456 for(
unsigned int i = 0; i < n_comps; i++ )
457 offset(i) = input(input_section, invalid_real, i );
464 std::map<
BoundaryID,std::vector<libMesh::subdomain_id_type> >& bc_id_to_subdomain_id_map )
const
466 std::vector<libMesh::dof_id_type> elem_ids;
467 std::vector<unsigned short int> side_ids;
468 std::vector<BoundaryID> bc_ids;
470 const libMesh::MeshBase& mesh = system.get_mesh();
473 mesh.get_boundary_info().build_active_side_list( elem_ids, side_ids, bc_ids );
475 libmesh_assert_equal_to( elem_ids.size(), side_ids.size() );
476 libmesh_assert_equal_to( elem_ids.size(), bc_ids.size() );
478 for(
unsigned int i = 0; i < elem_ids.size(); i++ )
480 const libMesh::Elem* elem_ptr = mesh.elem_ptr(elem_ids[i]);
482 libMesh::subdomain_id_type subdomain_id = elem_ptr->subdomain_id();
484 std::map<BoundaryID,std::vector<libMesh::subdomain_id_type> >::iterator
485 map_it = bc_id_to_subdomain_id_map.find(bc_ids[i]);
487 if( map_it == bc_id_to_subdomain_id_map.end() )
489 std::vector<libMesh::subdomain_id_type> sid(1,subdomain_id);
490 bc_id_to_subdomain_id_map.insert(std::make_pair(bc_ids[i],sid));
494 std::vector<libMesh::subdomain_id_type>& sids = map_it->second;
495 bool found_sid =
false;
497 for(
unsigned int i = 0; i < sids.size(); i++ )
499 if( sids[i] == subdomain_id )
503 if( !found_sid && (sids.size() > 2) )
504 libmesh_error_msg(
"ERROR: How do you have more than 2 subdomain ids for a boundary id?!");
505 else if( !found_sid && sids.size() < 2 )
506 sids.push_back(subdomain_id);
512 const std::vector<libMesh::subdomain_id_type>& subdomain_ids )
const
514 bool var_active =
false;
524 const std::set<libMesh::subdomain_id_type>& var_subdomain_ids =
527 for(std::vector<libMesh::subdomain_id_type>::const_iterator
id = subdomain_ids.begin();
id < subdomain_ids.end(); ++id )
529 if( var_subdomain_ids.find(*
id) != var_subdomain_ids.end() )
static bool is_axisymmetric()
void parse_and_build_bc_id_map(const GetPot &input, std::map< std::string, std::set< BoundaryID > > &bc_id_map)
void construct_dbc_core(const GetPot &input, MultiphysicsSystem &system, const std::set< BoundaryID > &bc_ids, const FEVariablesBase &fe_var, const std::string §ion, const std::string &bc_type, libMesh::DofMap &dof_map)
void construct_nbc_core(const GetPot &input, MultiphysicsSystem &system, const std::set< BoundaryID > &bc_ids, const FEVariablesBase &fe_var, const std::string §ion, const std::string &bc_type, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
libMesh::boundary_id_type BoundaryID
More descriptive name of the type used for boundary ids.
bool is_dirichlet_bc_type(const std::string &bc_type)
void build_periodic_bc(const GetPot &input, libMesh::System &system, const std::set< BoundaryID > &bc_ids, const std::string §ion)
bool is_var_active(const FEVariablesBase &var, const std::vector< libMesh::subdomain_id_type > &subdomain_ids) const
Check if the Variable var is active on the given subdomain_id.
void add_periodic_bc_to_dofmap(libMesh::boundary_id_type master_id, libMesh::boundary_id_type slave_id, const libMesh::RealVectorValue &offset_vector, libMesh::DofMap &dof_map)
void build_type_based_bcs(const GetPot &input, MultiphysicsSystem &system, const std::set< BoundaryID > &bc_ids, libMesh::DofMap &dof_map, const std::string &type_input_section, std::set< std::string > &var_sections, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
Helper function to build boundary conditions specified by a single type.
void parse_periodic_master_slave_ids(const GetPot &input, const std::string §ion, libMesh::boundary_id_type &master_id, libMesh::boundary_id_type &slave_id) const
void verify_bc_ids_with_mesh(const MultiphysicsSystem &system, const std::map< std::string, std::set< BoundaryID > > &bc_id_map) const
libMesh::RealVectorValue parse_periodic_offset(const GetPot &input, const std::string §ion) const
static FEVariablesBase & get_variable(const std::string &var_name)
void build_bcs_by_var_section(const GetPot &input, MultiphysicsSystem &system, const std::string &bc_name, const std::set< BoundaryID > &bc_ids, libMesh::DofMap &dof_map, std::set< std::string > &var_sections, const std::map< BoundaryID, std::vector< libMesh::subdomain_id_type > > &bc_id_to_subdomain_id_map, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
Helper function to build boundary conditions using Variable sections.
const std::set< libMesh::subdomain_id_type > & subdomain_ids() const
void build_bc_to_subdomain_map_check_with_mesh(const MultiphysicsSystem &system, std::map< BoundaryID, std::vector< libMesh::subdomain_id_type > > &bc_id_to_subdomain_id_map) const
Build up bc_id to subdomain_id map.
static std::string axisymmetric()
Interface with libMesh for solving Multiphysics problems.
virtual void build_bcs(const GetPot &input, MultiphysicsSystem &system, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
void split_string(const std::string &input, const std::string &delimiter, std::vector< std::string > &results)
bool is_constraint_var() const
static std::string bc_section()
Outer section name for boundary conditions section in input file.
static std::string periodic()
bool is_neumann_bc_type(const std::string &bc_type)
static std::string bc_id_name_map_var()
Names of boundaries to correspond with bc_ids.
static std::string bc_ids_var()
Variable for list boundary ids to correspond with bc_id_name_map.
void build_axisymmetric_bcs(const GetPot &input, MultiphysicsSystem &system, const std::set< BoundaryID > &bc_ids, libMesh::DofMap &dof_map, const std::string &bc_type, std::set< std::string > &var_sections, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
static void parse_var_sections(const GetPot &input, std::set< std::string > §ions)
Parses the input file for [Variables] first-level subsections.