Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrea Rovinelli committed Oct 5, 2020
2 parents 8843bc6 + d332a43 commit 651131c
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 39 deletions.
11 changes: 8 additions & 3 deletions framework/include/meshgenerators/BreakMeshByBlockGenerator.h
Expand Up @@ -10,6 +10,7 @@
#pragma once

#include "BreakMeshByBlockGeneratorBase.h"
#include <unordered_set>

class BreakMeshByBlockGenerator;

Expand All @@ -26,15 +27,19 @@ class BreakMeshByBlockGenerator : public BreakMeshByBlockGeneratorBase
std::unique_ptr<MeshBase> generate() override;

protected:
int blockRestricteElementSubdomainID(const Elem * elem);

std::unique_ptr<MeshBase> & _input;
std::vector<SubdomainID> _block;
std::unordered_set<SubdomainID> _block_set;
const bool _block_restricted;
const bool _create_transition_boundary;

private:
/// generate the new boundary interface
void addInterfaceBoundary(MeshBase & mesh);

std::set<std::pair<subdomain_id_type, subdomain_id_type>> _neighboring_block_list;
std::map<std::pair<subdomain_id_type, subdomain_id_type>,
std::set<std::pair<dof_id_type, unsigned int>>>
std::map<std::pair<int, int>, std::set<std::pair<dof_id_type, unsigned int>>>
_new_boundary_sides_map;
};

Expand Up @@ -44,8 +44,8 @@ class BreakMeshByBlockGeneratorBase : public MeshGenerator
/// given the primary and secondary blocks this method return the appropriate
/// boundary id and name
void findBoundaryNameAndInd(MeshBase & mesh,
const subdomain_id_type & /*primaryBlockID*/,
const subdomain_id_type & /*secondaryBlockID*/,
const int & /*primaryBlockID*/,
const int & /*secondaryBlockID*/,
std::string & /*boundaryName*/,
boundary_id_type & /*boundaryID*/,
BoundaryInfo & /*boundary_info*/);
Expand All @@ -58,11 +58,10 @@ class BreakMeshByBlockGeneratorBase : public MeshGenerator
private:
/// this method generate the boundary name by assembling subdomain names
std::string generateBoundaryName(MeshBase & mesh,
const subdomain_id_type & /*primaryBlockID*/,
const subdomain_id_type & /*secondaryBlockID*/);
const int & /*primaryBlockID*/,
const int & /*secondaryBlockID*/);

/// this method save the boundary name/id pair
void mapBoundaryIdAndBoundaryName(boundary_id_type & /*boundaryID*/,
const std::string & /*boundaryName*/);
};

120 changes: 93 additions & 27 deletions framework/src/meshgenerators/BreakMeshByBlockGenerator.C
Expand Up @@ -28,11 +28,26 @@ BreakMeshByBlockGenerator::validParams()
"attached. Naming convention for the new boundaries will be the old "
"boundary name plus \"_to_\" plus the subdomain name. At the moment"
"this only works on REPLICATED mesh");
params.addParam<std::vector<SubdomainID>>(
"block",
"The list of subdomain names where neml mehcanisc should be used, "
"default all blocks.");
params.addParam<bool>("create_transition_boundary",
true,
"If true (default) and block is not empty, a special boundary named "
"interface_transition is generate between listed blocks and other blocks. "
"The transition boundary will not be split if split_interface=true");
return params;
}

BreakMeshByBlockGenerator::BreakMeshByBlockGenerator(const InputParameters & parameters)
: BreakMeshByBlockGeneratorBase(parameters), _input(getMesh("input"))
: BreakMeshByBlockGeneratorBase(parameters),
_input(getMesh("input")),
_block(parameters.isParamSetByUser("block") ? getParam<std::vector<SubdomainID>>("block")
: std::vector<SubdomainID>(0)),
_block_set(_block.begin(), _block.end()),
_block_restricted(parameters.isParamSetByUser("block")),
_create_transition_boundary(getParam<bool>("create_transition_boundary"))
{
if (typeid(_input).name() == typeid(DistributedMesh).name())
mooseError("BreakMeshByBlockGenerator only works with ReplicatedMesh.");
Expand All @@ -57,11 +72,11 @@ BreakMeshByBlockGenerator::generate()
if (current_node != nullptr)
{
// find node multiplicity
std::set<subdomain_id_type> connected_blocks;
std::set<int> connected_blocks;
for (auto elem_id = node_it->second.begin(); elem_id != node_it->second.end(); elem_id++)
{
const Elem * current_elem = mesh->elem_ptr(*elem_id);
connected_blocks.insert(current_elem->subdomain_id());
connected_blocks.insert(blockRestricteElementSubdomainID(current_elem));
}

unsigned int node_multiplicity = connected_blocks.size();
Expand All @@ -74,8 +89,7 @@ BreakMeshByBlockGenerator::generate()

// find reference_subdomain_id (e.g. the subdomain with lower id)
auto subdomain_it = connected_blocks.begin();
subdomain_id_type reference_subdomain_id = *subdomain_it;

int reference_subdomain_id = *subdomain_it;
// multiplicity counter to keep track of how many nodes we added
unsigned int multiplicity_counter = node_multiplicity;
for (auto elem_id : connected_elems)
Expand All @@ -85,7 +99,7 @@ BreakMeshByBlockGenerator::generate()
break;

Elem * current_elem = mesh->elem_ptr(elem_id);
if (current_elem->subdomain_id() != reference_subdomain_id)
if (blockRestricteElementSubdomainID(current_elem) != reference_subdomain_id)
{
// assign the newly added node to current_elem
Node * new_node = nullptr;
Expand All @@ -99,8 +113,9 @@ BreakMeshByBlockGenerator::generate()
// add new node
new_node = Node::build(*current_node, mesh->n_nodes()).release();

// We're duplicating nodes so that each subdomain elem has its own copy, so it seems
// natural to assign this new node the same proc id as corresponding subdomain elem
// We're duplicating nodes so that each subdomain elem has its own copy, so it
// seems natural to assign this new node the same proc id as corresponding
// subdomain elem
new_node->processor_id() = current_elem->processor_id();
mesh->add_node(new_node);

Expand Down Expand Up @@ -142,14 +157,22 @@ BreakMeshByBlockGenerator::generate()
{
Elem * current_elem = mesh->elem_ptr(elem_id);
Elem * connected_elem = mesh->elem_ptr(connected_elem_id);
int curr_elem_subid = blockRestricteElementSubdomainID(current_elem);
int connected_elem_subid = blockRestricteElementSubdomainID(connected_elem);

if (current_elem != connected_elem &&
current_elem->subdomain_id() < connected_elem->subdomain_id())
if (current_elem != connected_elem && curr_elem_subid < connected_elem_subid)
{
if (current_elem->has_neighbor(connected_elem))
{
std::pair<subdomain_id_type, subdomain_id_type> blocks_pair =
std::make_pair(current_elem->subdomain_id(), connected_elem->subdomain_id());

std::pair<int, int> blocks_pair =
std::make_pair(curr_elem_subid, connected_elem_subid);

// we want to create a special boundary for the transition, much easier to do it
// here than later
if (_block_restricted && _create_transition_boundary &&
(curr_elem_subid == -1 || connected_elem_subid == -1))
blocks_pair = std::make_pair(-1, -1);

_new_boundary_sides_map[blocks_pair].insert(std::make_pair(
current_elem->id(), current_elem->which_neighbor_am_i(connected_elem)));
Expand All @@ -172,27 +195,70 @@ BreakMeshByBlockGenerator::addInterfaceBoundary(MeshBase & mesh)
{
BoundaryInfo & boundary_info = mesh.get_boundary_info();

boundary_id_type boundaryID = findFreeBoundaryId(mesh);
std::string boundaryName = _interface_name;
boundary_id_type boundaryID;
boundary_id_type boundaryID_interface = findFreeBoundaryId(mesh);
std::string boundaryName;

// loop over boundary sides
for (auto & boundary_side_map : _new_boundary_sides_map)
{

// find the appropriate boundary name and id
// given primary and secondary block ID
if (_split_interface)
findBoundaryNameAndInd(mesh,
boundary_side_map.first.first,
boundary_side_map.first.second,
boundaryName,
boundaryID,
boundary_info);
else
boundary_info.sideset_name(boundaryID) = boundaryName;

if (!_block_restricted || (_block_restricted && !_create_transition_boundary))
{
// find the appropriate boundary name and id
// given primary and secondary block ID
if (_split_interface)
findBoundaryNameAndInd(mesh,
boundary_side_map.first.first,
boundary_side_map.first.second,
boundaryName,
boundaryID,
boundary_info);
else
{
boundaryName = _interface_name;
boundaryID = boundaryID_interface;
boundary_info.sideset_name(boundaryID_interface) = boundaryName;
}
}
else // block resticted with transition boundary
{
if (boundary_side_map.first.first == -1 ||
boundary_side_map.first.second == -1) // we are creating the transition boundary
{
boundaryID = findFreeBoundaryId(mesh);
boundaryName = "interface_transition";
boundary_info.sideset_name(boundaryID) = boundaryName;
boundaryID_interface = boundaryID + 1;
}
else
{
if (_split_interface)
findBoundaryNameAndInd(mesh,
boundary_side_map.first.first,
boundary_side_map.first.second,
boundaryName,
boundaryID,
boundary_info);
else
{
boundaryName = _interface_name;
boundaryID = boundaryID_interface;
boundary_info.sideset_name(boundaryID_interface) = boundaryName;
}
}
}
// loop over all the side belonging to each pair and add it to the proper interface
for (auto & element_side : boundary_side_map.second)
boundary_info.add_side(element_side.first, element_side.second, boundaryID);
}
}

int
BreakMeshByBlockGenerator::blockRestricteElementSubdomainID(const Elem * elem)
{
int elem_subdomain_id = elem->subdomain_id();
if (_block_restricted && (_block_set.find(elem_subdomain_id) == _block_set.end()))
elem_subdomain_id = -1;

return elem_subdomain_id;
}
8 changes: 4 additions & 4 deletions framework/src/meshgenerators/BreakMeshByBlockGeneratorBase.C
Expand Up @@ -69,8 +69,8 @@ BreakMeshByBlockGeneratorBase::findFreeBoundaryId(MeshBase & mesh)

std::string
BreakMeshByBlockGeneratorBase::generateBoundaryName(MeshBase & mesh,
const subdomain_id_type & primaryBlockID,
const subdomain_id_type & secondaryBlockID)
const int & primaryBlockID,
const int & secondaryBlockID)
{
std::string primary_block_name = mesh.subdomain_name(primaryBlockID);
std::string secondary_block_name = mesh.subdomain_name(secondaryBlockID);
Expand All @@ -91,8 +91,8 @@ BreakMeshByBlockGeneratorBase::mapBoundaryIdAndBoundaryName(boundary_id_type & b

void
BreakMeshByBlockGeneratorBase::findBoundaryNameAndInd(MeshBase & mesh,
const subdomain_id_type & primaryBlockID,
const subdomain_id_type & secondaryBlockID,
const int & primaryBlockID,
const int & secondaryBlockID,
std::string & boundaryName,
boundary_id_type & boundaryID,
BoundaryInfo & boundary_info)
Expand Down
@@ -0,0 +1,25 @@
[Mesh]
[msh]
type = CartesianMeshGenerator
dim = 3
dx = '0.25 0.25 0.25 0.25'
dy = '0.25 0.25 0.25 0.25'
dz = '0.25 0.25 0.25 0.25'
subdomain_id = '0 1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29 30 31 32 33 34 35 36 37 38
39 40 41 42 43 44 45 46 47 48 49 50 51
52 53 54 55 56 57 58 59 60 61 62 63'
[]
[split]
input = msh
type = BreakMeshByBlockGenerator
block = '16 17 18 19 20 21 22 23 24 25
26 27 28 29 30 31 32 34 35 36 37 38
39 40 41 42 43 44 45 46 47'
[]
[]

[Outputs]
nemesis = true
[]
Binary file not shown.
11 changes: 11 additions & 0 deletions test/tests/meshgenerators/break_mesh_by_block_generator/tests
Expand Up @@ -85,4 +85,15 @@
recover = false
method = 'dbg'
[../]

[./block_restricted]
type = 'Exodiff'
input = 'break_mesh_block_restricted.i'
cli_args = '--mesh-only'
exodiff = 'break_mesh_block_restricted_in.e'
requirement = 'The system shall be able to break teh mesh only for some blocks'
design = 'meshgenerators/BreakMeshByBlockGenerator.md'
issues = '#15793'
mesh_mode = 'REPLICATED'
[../]
[]

0 comments on commit 651131c

Please sign in to comment.