https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
RevolveGenerator Class Reference

This RevolveGenerator object is designed to revolve a 1D mesh into 2D, or a 2D mesh into 3D based on an axis. More...

#include <RevolveGenerator.h>

Inheritance diagram for RevolveGenerator:
[legend]

Public Types

enum class  PolygonSizeStyle { apothem , radius }
 An enum class for style of input polygon size. More...
 
enum  MESH_TYPE { CORNER_MESH = 1 , BOUNDARY_MESH = 2 , INNER_MESH = 3 }
 
enum  RETURN_TYPE { ANGLE_DEGREE = 1 , ANGLE_TANGENT = 2 }
 
enum  INTRISIC_SUBDOMAIN_ID : subdomain_id_type { PERIPHERAL_ID_SHIFT = 1000 , TRANSITION_LAYER_DEFAULT = 10000 }
 
enum  INTRINSIC_SIDESET_ID : boundary_id_type {
  OUTER_SIDESET_ID = 10000 , OUTER_SIDESET_ID_ALT = 15000 , SLICE_BEGIN = 30000 , SLICE_END = 31000 ,
  SLICE_ALT = 30500
}
 
enum  INTRINSIC_NUM_SIDES { HEXAGON_NUM_SIDES = 6 , SQUARE_NUM_SIDES = 4 }
 
enum class  TRI_ELEM_TYPE { TRI3 , TRI6 , TRI7 }
 
enum class  QUAD_ELEM_TYPE { QUAD4 , QUAD8 , QUAD9 }
 
typedef DataFileName DataFileParameterType
 

Public Member Functions

 RevolveGenerator (const InputParameters &parameters)
 
std::unique_ptr< MeshBasegenerate () override
 
std::unique_ptr< CSG::CSGBasegenerateInternalCSG ()
 
std::unique_ptr< MeshBase > generateInternal ()
 
const std::set< MeshGeneratorName > & getRequestedMeshGenerators () const
 
const std::set< MeshGeneratorName > & getRequestedMeshGeneratorsForSub () const
 
void addParentMeshGenerator (const MeshGenerator &mg, const AddParentChildKey)
 
void addChildMeshGenerator (const MeshGenerator &mg, const AddParentChildKey)
 
const std::set< const MeshGenerator *, Comparator > & getParentMeshGenerators () const
 
const std::set< const MeshGenerator *, Comparator > & getChildMeshGenerators () const
 
const std::set< const MeshGenerator *, Comparator > & getSubMeshGenerators () const
 
bool isParentMeshGenerator (const MeshGeneratorName &name, const bool direct=true) const
 
bool isChildMeshGenerator (const MeshGeneratorName &name, const bool direct=true) const
 
bool isNullMeshName (const MeshGeneratorName &name) const
 
bool hasSaveMesh () const
 
bool hasOutput () const
 
const std::string & getSavedMeshName () const
 
bool hasGenerateData () const
 
bool hasGenerateCSG () const
 
bool isDataOnly () const
 
virtual bool enabled () const
 
std::shared_ptr< MooseObjectgetSharedPtr ()
 
std::shared_ptr< const MooseObjectgetSharedPtr () const
 
bool isKokkosObject () const
 
MooseAppgetMooseApp () const
 
const std::string & type () const
 
const std::string & name () const
 
std::string typeAndName () const
 
MooseObjectParameterName uniqueParameterName (const std::string &parameter_name) const
 
MooseObjectName uniqueName () const
 
const InputParametersparameters () const
 
const hit::Node * getHitNode () const
 
bool hasBase () const
 
const std::string & getBase () const
 
const TgetParam (const std::string &name) const
 
std::vector< std::pair< T1, T2 > > getParam (const std::string &param1, const std::string &param2) const
 
const TqueryParam (const std::string &name) const
 
const TgetRenamedParam (const std::string &old_name, const std::string &new_name) const
 
T getCheckedPointerParam (const std::string &name, const std::string &error_string="") const
 
bool isParamValid (const std::string &name) const
 
bool isParamSetByUser (const std::string &name) const
 
void connectControllableParams (const std::string &parameter, const std::string &object_type, const std::string &object_name, const std::string &object_parameter) const
 
void paramError (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramWarning (const std::string &param, Args... args) const
 
void paramInfo (const std::string &param, Args... args) const
 
std::string messagePrefix (const bool hit_prefix=true) const
 
std::string errorPrefix (const std::string &) const
 
void mooseError (Args &&... args) const
 
void mooseDocumentedError (const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
 
void mooseErrorNonPrefixed (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarning (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseWarningNonPrefixed (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecated (Args &&... args) const
 
void mooseDeprecatedNoTrace (Args &&... args) const
 
void mooseInfo (Args &&... args) const
 
void callMooseError (std::string msg, const bool with_prefix, const hit::Node *node=nullptr, const bool show_trace=true) const
 
std::string getDataFileName (const std::string &param) const
 
std::string getDataFileNameByName (const std::string &relative_path) const
 
std::string getDataFilePath (const std::string &relative_path) const
 
const Parallel::Communicator & comm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Member Functions

static InputParameters validParams ()
 
static bool hasGenerateData (const InputParameters &params)
 
static bool hasGenerateCSG (const InputParameters &params)
 
static void callMooseError (MooseApp *const app, const InputParameters &params, std::string msg, const bool with_prefix, const hit::Node *node, const bool show_trace=true)
 
static void setHasGenerateData (InputParameters &params)
 
static void setHasGenerateCSG (InputParameters &params)
 

Public Attributes

 usingCombinedWarningSolutionWarnings
 
const ConsoleStream _console
 

Static Public Attributes

static const std::string data_only_param
 
static const std::string type_param
 
static const std::string name_param
 
static const std::string unique_name_param
 
static const std::string app_param
 
static const std::string moose_base_param
 
static const std::string kokkos_object_param
 
static constexpr auto SYSTEM
 
static constexpr auto NAME
 

Protected Member Functions

std::pair< Real, PointgetRotationCenterAndRadius (const Point &p_ext, const Point &p_axis, const Point &dir_axis) const
 Get the rotation center and radius of the circular rotation based on the rotation axis and the external point.
 
std::vector< PointrotationVectors (const Point &p_axis, const Point &dir_axis, const Point &p_input) const
 Calculate the transform matrix between the rotation coordinate system and the original coordinate system.
 
std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > onAxisNodesIdentifier (const Elem &elem, const std::vector< dof_id_type > &nodes_on_axis) const
 Categorize the nodes of an element into two groups: nodes on the axis and nodes off the axis.
 
void nodeModification (Node &node)
 Modify the position of a node to account for radius correction.
 
void createQUADfromEDGE (const ElemType quad_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
 Create a new QUAD element from an existing EDGE element by revolving it.
 
void createTRIfromEDGE (const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType tri_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
 Create a new TRI element from an existing EDGE element by revolving it.
 
void createPRISMfromTRI (const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
 Create a new PRISM element from an existing TRI element by revolving it.
 
void createPYRAMIDfromTRI (const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType pyramid_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
 Create a new PYRAMID element from an existing TRI element by revolving it.
 
void createTETfromTRI (const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType tet_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
 Create a new TET element from an existing TRI element by revolving it.
 
void createHEXfromQUAD (const ElemType hex_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
 Create a new HEX element from an existing QUAD element by revolving it.
 
void createPRISMfromQUAD (const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
 Create a new PRISM element from an existing QUAD element by revolving it.
 
void createPYRAMIDPRISMfromQUAD (const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType pyramid_elem_type, const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, std::unique_ptr< Elem > &new_elem_1, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped, bool &is_flipped_additional) const
 Create a new PYRAMID element and a new PRISM element from an existing QUAD element by revolving it.
 
std::unique_ptr< ReplicatedMeshbuildSimpleSlice (std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< Real > ring_radial_biases, const multiBdryLayerParams &ring_inner_boundary_layer_params, const multiBdryLayerParams &ring_outer_boundary_layer_params, std::vector< Real > ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< Real > duct_radial_biases, const multiBdryLayerParams &duct_inner_boundary_layer_params, const multiBdryLayerParams &duct_outer_boundary_layer_params, const Real pitch, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const Real background_radial_bias, const singleBdryLayerParams &background_inner_boundary_layer_params, const singleBdryLayerParams &background_outer_boundary_layer_params, dof_id_type &node_id_background_meta, const unsigned int side_number, const unsigned int side_index, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const bool quad_center_elements=false, const Real center_quad_factor=0.0, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const bool generate_side_specific_boundaries=true, const TRI_ELEM_TYPE tri_elem_type=TRI_ELEM_TYPE::TRI3, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4)
 Creates a mesh of a slice that corresponds to a single side of the polygon to be generated.
 
std::unique_ptr< ReplicatedMeshbuildGeneralSlice (std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< Real > ring_radial_biases, const multiBdryLayerParams &ring_inner_boundary_layer_params, const multiBdryLayerParams &ring_outer_boundary_layer_params, std::vector< Real > ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< Real > duct_radial_biases, const multiBdryLayerParams &duct_inner_boundary_layer_params, const multiBdryLayerParams &duct_outer_boundary_layer_params, const Real primary_side_length, const Real secondary_side_length, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const Real background_radial_bias, const singleBdryLayerParams &background_inner_boundary_layer_params, const singleBdryLayerParams &background_outer_boundary_layer_params, dof_id_type &node_id_background_meta, const Real azimuthal_angle, const std::vector< Real > azimuthal_tangent, const unsigned int side_index, const bool quad_center_elements, const Real center_quad_factor, const Real rotation_angle, const bool generate_side_specific_boundaries=true)
 Creates a mesh of a general polygon slice with a triangular shape and circular regions on one of its vertex.
 
std::unique_ptr< ReplicatedMeshbuildSlice (std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< Real > ring_radial_biases, const multiBdryLayerParams &ring_inner_boundary_layer_params, const multiBdryLayerParams &ring_outer_boundary_layer_params, std::vector< Real > ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< Real > duct_radial_biases, const multiBdryLayerParams &duct_inner_boundary_layer_params, const multiBdryLayerParams &duct_outer_boundary_layer_params, const Real pitch, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const Real background_radial_bias, const singleBdryLayerParams &background_inner_boundary_layer_params, const singleBdryLayerParams &background_outer_boundary_layer_params, dof_id_type &node_id_background_meta, const Real virtual_side_number, const unsigned int side_index, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const bool quad_center_elements=false, const Real center_quad_factor=0.0, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const Real pitch_scale_factor=1.0, const bool generate_side_specific_boundaries=true, const TRI_ELEM_TYPE tri_elem_type=TRI_ELEM_TYPE::TRI3, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4)
 Generates a mesh of a polygon slice, which is the foundation of both buildGeneralSlice and buildSimpleSlice.
 
void centerNodes (ReplicatedMesh &mesh, const Real virtual_side_number, const unsigned int div_num, const Real ring_radii_0, std::vector< std::vector< Node * > > &nodes) const
 Creates nodes of the very central mesh layer of the polygon for quad central elements.
 
void ringNodes (ReplicatedMesh &mesh, const std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< std::vector< Real > > biased_terms, const unsigned int num_sectors_per_side, const Real corner_p[2][2], const Real corner_to_corner, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
 Creates nodes for the ring-geometry region of a single slice.
 
void backgroundNodes (ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const std::vector< Real > biased_terms, const Real background_corner_distance, const Real background_corner_radial_interval_length, const Real corner_p[2][2], const Real corner_to_corner, const Real background_in, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
 Creates nodes for the ring-to-polygon transition region (i.e., background) of a single slice.
 
void ductNodes (ReplicatedMesh &mesh, std::vector< Real > *const ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< std::vector< Real > > biased_terms, const unsigned int num_sectors_per_side, const Real corner_p[2][2], const Real corner_to_corner, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
 Creates nodes for the duct-geometry region of a single slice.
 
void cenQuadElemDef (ReplicatedMesh &mesh, const unsigned int div_num, const subdomain_id_type block_id_shift, const bool create_outward_interface_boundaries, const boundary_id_type boundary_id_shift, std::vector< std::vector< Node * > > &nodes, const bool assign_external_boundary=false, const unsigned int side_index=0, const bool generate_side_specific_boundaries=true, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4) const
 Defines quad elements in the very central region of the polygon.
 
void cenTriElemDef (ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const bool assign_external_boundary=false, const unsigned int side_index=0, const bool generate_side_specific_boundaries=true, const TRI_ELEM_TYPE tri_elem_type=TRI_ELEM_TYPE::TRI3) const
 Defines triangular elements in the very central region of the polygon.
 
void quadElemDef (ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const std::vector< unsigned int > subdomain_rings, const unsigned int side_index, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const dof_id_type nodeid_shift=0, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const bool generate_side_specific_boundaries=true, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4) const
 Defines general quad elements for the polygon.
 
std::unique_ptr< ReplicatedMeshbuildSimplePeripheral (const unsigned int num_sectors_per_side, const unsigned int peripheral_invervals, const std::vector< std::pair< Real, Real > > &position_inner, const std::vector< std::pair< Real, Real > > &d_position_outer, const subdomain_id_type id_shift, const QUAD_ELEM_TYPE quad_elem_type, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true)
 Creates peripheral area mesh for the patterned hexagon mesh.
 
void adjustPeripheralQuadraticElements (MeshBase &out_mesh, const QUAD_ELEM_TYPE boundary_quad_elem_type) const
 Adjusts the mid-edge node locations in boundary regions when using quadratic elements with uniform boundary node spacing enabled.
 
std::pair< Real, Real > pointInterpolate (const Real pi_1_x, const Real pi_1_y, const Real po_1_x, const Real po_1_y, const Real pi_2_x, const Real pi_2_y, const Real po_2_x, const Real po_2_y, const unsigned int i, const unsigned int j, const unsigned int num_sectors_per_side, const unsigned int peripheral_intervals) const
 Calculates the point coordinates of within a parallelogram region using linear interpolation.
 
void nodeCoordRotate (Real &x, Real &y, const Real theta) const
 Calculates x and y coordinates after rotating by theta angle.
 
void cutOffPolyDeform (MeshBase &mesh, const Real orientation, const Real y_max_0, const Real y_max_n, const Real y_min, const unsigned int mesh_type, const Real unit_angle=60.0, const Real tols=1E-5) const
 Deforms peripheral region when the external side of a polygon assembly of stitched meshes cuts off the stitched meshes.
 
std::pair< Real, Real > fourPointIntercept (const std::pair< Real, Real > &p1, const std::pair< Real, Real > &p2, const std::pair< Real, Real > &p3, const std::pair< Real, Real > &p4) const
 Finds the center of a quadrilateral based on four vertices.
 
std::vector< Real > azimuthalAnglesCollector (ReplicatedMesh &mesh, std::vector< Point > &boundary_points, const Real lower_azi=-30.0, const Real upper_azi=30.0, const unsigned int return_type=ANGLE_TANGENT, const unsigned int num_sides=6, const boundary_id_type bid=OUTER_SIDESET_ID, const bool calculate_origin=true, const Real input_origin_x=0.0, const Real input_origin_y=0.0, const Real tol=1.0E-10) const
 Collects sorted azimuthal angles of the external boundary.
 
std::vector< Real > azimuthalAnglesCollector (ReplicatedMesh &mesh, const Real lower_azi=-30.0, const Real upper_azi=30.0, const unsigned int return_type=ANGLE_TANGENT, const unsigned int num_sides=6, const boundary_id_type bid=OUTER_SIDESET_ID, const bool calculate_origin=true, const Real input_origin_x=0.0, const Real input_origin_y=0.0, const Real tol=1.0E-10) const
 Collects sorted azimuthal angles of the external boundary.
 
std::vector< std::vector< Real > > biasTermsCalculator (const std::vector< Real > radial_biases, const std::vector< unsigned int > intervals, const multiBdryLayerParams inner_boundary_layer_params, const multiBdryLayerParams outer_boundary_layer_params) const
 Creates bias terms for multiple blocks.
 
std::vector< Real > biasTermsCalculator (const Real radial_bias, const unsigned int intervals, const singleBdryLayerParams inner_boundary_layer_params={0.0, 0.0, 0, 1.0}, const singleBdryLayerParams outer_boundary_layer_params={0.0, 0.0, 0, 1.0}) const
 Creates bias terms for a single block.
 
void setSectorExtraIDs (MeshBase &mesh, const std::string id_name, const unsigned int num_sides, const std::vector< unsigned int > num_sectors_per_side)
 assign sector extra ids to polygon mesh
 
void setRingExtraIDs (MeshBase &mesh, const std::string id_name, const unsigned int num_sides, const std::vector< unsigned int > num_sectors_per_side, const std::vector< unsigned int > ring_intervals, const bool ring_wise_id, const bool quad_center_elements)
 assign ring extra ids to polygon mesh
 
void reassignBoundaryIDs (MeshBase &mesh, const boundary_id_type id_shift, const std::set< boundary_id_type > &boundary_ids, const bool reverse=false)
 reassign interface boundary IDs on the input mesh by applying the boundary ID shift
 
std::set< boundary_id_typegetInterfaceBoundaryIDs (const std::vector< std::vector< unsigned int > > &pattern, const std::vector< std::vector< boundary_id_type > > &interface_boundary_id_shift_pattern, const std::set< boundary_id_type > &boundary_ids, const std::vector< std::set< boundary_id_type > > &input_interface_boundary_ids, const bool use_interface_boundary_id_shift, const bool create_interface_boundary_id, const unsigned int num_extra_layers) const
 returns a list of interface boundary IDs on the mesh generated by this mesh generator
 
multiBdryLayerParams modifiedMultiBdryLayerParamsCreator (const multiBdryLayerParams &original_multi_bdry_layer_params, const unsigned int order) const
 Modifies the input multi boundary layer parameters for node generation, especially for the quadratic elements.
 
singleBdryLayerParams modifiedSingleBdryLayerParamsCreator (const singleBdryLayerParams &original_single_bdry_layer_params, const unsigned int order) const
 Modifies the input single boundary layer parameters for node generation, especially for the quadratic elements.
 
std::string pitchMetaDataErrorGenerator (const std::vector< MeshGeneratorName > &input_names, const std::vector< Real > &metadata_vals, const std::string &metadata_name) const
 Generate a string that contains the detailed metadata information for inconsistent input mesh metadata error messages.
 
virtual void generateData ()
 
virtual std::unique_ptr< CSG::CSGBasegenerateCSG ()
 
TcopyMeshProperty (const std::string &target_data_name, const std::string &source_data_name, const std::string &source_mesh)
 
TcopyMeshProperty (const std::string &source_data_name, const std::string &source_mesh)
 
std::unique_ptr< MeshBase > & getMesh (const std::string &param_name, const bool allow_invalid=false)
 
std::vector< std::unique_ptr< MeshBase > * > getMeshes (const std::string &param_name)
 
std::unique_ptr< MeshBase > & getMeshByName (const MeshGeneratorName &mesh_generator_name)
 
std::vector< std::unique_ptr< MeshBase > * > getMeshesByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
std::unique_ptr< CSG::CSGBase > & getCSGBase (const std::string &param_name)
 
std::unique_ptr< CSG::CSGBase > & getCSGBaseByName (const MeshGeneratorName &mesh_generator_name)
 
std::vector< std::unique_ptr< CSG::CSGBase > * > getCSGBases (const std::string &param_name)
 
std::vector< std::unique_ptr< CSG::CSGBase > * > getCSGBasesByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
void declareMeshForSub (const std::string &param_name)
 
void declareMeshesForSub (const std::string &param_name)
 
void declareMeshForSubByName (const MeshGeneratorName &mesh_generator_name)
 
void declareMeshesForSubByName (const std::vector< MeshGeneratorName > &mesh_generator_names)
 
std::unique_ptr< MeshBase > buildMeshBaseObject (unsigned int dim=libMesh::invalid_uint)
 
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh (unsigned int dim=libMesh::invalid_uint)
 
std::unique_ptr< DistributedMesh > buildDistributedMesh (unsigned int dim=libMesh::invalid_uint)
 
void addMeshSubgenerator (const std::string &type, const std::string &name, Ts... extra_input_parameters)
 
void addMeshSubgenerator (const std::string &type, const std::string &name, InputParameters params)
 
void declareNullMeshName (const MeshGeneratorName &name)
 
void flagInvalidSolutionInternal (const InvalidSolutionID invalid_solution_id) const
 
InvalidSolutionID registerInvalidSolutionInternal (const std::string &message, const bool warning) const
 
const TgetMeshProperty (const std::string &data_name, const std::string &prefix)
 
const TgetMeshProperty (const std::string &data_name)
 
bool hasMeshProperty (const std::string &data_name, const std::string &prefix) const
 
bool hasMeshProperty (const std::string &data_name, const std::string &prefix) const
 
bool hasMeshProperty (const std::string &data_name) const
 
bool hasMeshProperty (const std::string &data_name) const
 
std::string meshPropertyName (const std::string &data_name) const
 
TdeclareMeshProperty (const std::string &data_name, Args &&... args)
 
TdeclareMeshProperty (const std::string &data_name, const T &data_value)
 
TdeclareMeshProperty (const std::string &data_name, Args &&... args)
 
TdeclareMeshProperty (const std::string &data_name, const T &data_value)
 
TsetMeshProperty (const std::string &data_name, Args &&... args)
 
TsetMeshProperty (const std::string &data_name, const T &data_value)
 
TsetMeshProperty (const std::string &data_name, Args &&... args)
 
TsetMeshProperty (const std::string &data_name, const T &data_value)
 

Static Protected Member Functions

static void addRingAndSectorIDParams (InputParameters &params)
 Add InputParameters which are used by ring and sector IDs.
 
static std::string meshPropertyName (const std::string &data_name, const std::string &prefix)
 

Protected Attributes

std::unique_ptr< MeshBase > & _input
 Lower dimensional mesh from another generator.
 
const Point & _axis_point
 A point of the axis of revolution.
 
const Point & _axis_direction
 A direction vector of the axis of revolution.
 
const std::vector< Real > _revolving_angles
 Angles of revolution delineating each azimuthal section.
 
const std::vector< std::vector< subdomain_id_type > > & _subdomain_swaps
 Subdomains to swap out for each azimuthal section.
 
const std::vector< std::vector< boundary_id_type > > & _boundary_swaps
 Boundaries to swap out for each elevation.
 
const std::vector< std::string > & _elem_integer_names_to_swap
 Names and indices of extra element integers to swap.
 
std::vector< unsigned int_elem_integer_indices_to_swap
 
const std::vector< std::vector< std::vector< dof_id_type > > > & _elem_integers_swaps
 Extra element integers to swap out for each elevation and each element integer name.
 
const bool & _clockwise
 Revolving direction.
 
const std::vector< unsigned int > & _nums_azimuthal_intervals
 Numbers of azimuthal mesh intervals in each azimuthal section.
 
const bool _preserve_volumes
 Volume preserving function is optional.
 
bool _has_start_boundary
 Whether a starting boundary is specified.
 
boundary_id_type _start_boundary
 Boundary ID of the starting boundary.
 
bool _has_end_boundary
 Whether an ending boundary is specified.
 
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
 Easier to work with version of _sudomain_swaps.
 
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
 Easier to work with version of _boundary_swaps.
 
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
 Easier to work with version of _elem_integers_swaps.
 
bool _full_circle_revolving
 Whether to revolve for a full circle or not.
 
std::vector< Real > _unit_angles
 Unit angles of all azimuthal sections of revolution.
 
boundary_id_type _end_boundary
 Boundary ID of the ending boundary.
 
Real _radius_correction_factor
 Radius correction factor.
 
MooseMesh *const _mesh
 
const bool & _enabled
 
MooseApp_app
 
Factory_factory
 
ActionFactory_action_factory
 
const std::string & _type
 
const std::string & _name
 
const InputParameters_pars
 
const Parallel::Communicator & _communicator
 

Private Member Functions

virtual std::string meshPropertyPrefix (const std::string &) const override final
 
void checkGetMesh (const MeshGeneratorName &mesh_generator_name, const std::string &param_name) const
 
const MeshGeneratorName * getMeshGeneratorNameFromParam (const std::string &param_name, const bool allow_invalid) const
 
const std::vector< MeshGeneratorName > & getMeshGeneratorNamesFromParam (const std::string &param_name) const
 
RestartableDataValuesetMeshPropertyHelper (const std::string &data_name)
 
const RestartableDataValuegetMeshPropertyInternal (const std::string &data_name, const std::string &prefix) const
 
void mooseErrorInternal (Args &&... args) const
 

Static Private Member Functions

static const hit::Node * getHitNode (const InputParameters &params)
 
static std::string messagePrefix (const InputParameters &params, const bool hit_prefix)
 

Private Attributes

std::set< MeshGeneratorName > _requested_mesh_generators
 
std::set< MeshGeneratorName > _requested_mesh_generators_for_sub
 
std::vector< std::pair< std::string, std::unique_ptr< MeshBase > * > > _requested_meshes
 
std::vector< std::pair< std::string, std::unique_ptr< CSG::CSGBase > * > > _requested_csg_bases
 
std::unique_ptr< MeshBase > _null_mesh
 
std::unique_ptr< CSG::CSGBase_null_csg_base
 
std::set< const MeshGenerator *, Comparator > _parent_mesh_generators
 
std::set< const MeshGenerator *, Comparator > _child_mesh_generators
 
std::set< const MeshGenerator *, Comparator > _sub_mesh_generators
 
std::set< std::string > _null_mesh_names
 
const std::string & _save_with_name
 
const bool _data_only
 
const ParallelParamObject_parent
 
const MooseBase_si_moose_base
 
const FEProblemBase_si_problem
 
MooseApp_meta_data_app
 
const MooseObject *const _meta_data_object
 

Detailed Description

This RevolveGenerator object is designed to revolve a 1D mesh into 2D, or a 2D mesh into 3D based on an axis.

Definition at line 18 of file RevolveGenerator.h.

Member Enumeration Documentation

◆ INTRINSIC_NUM_SIDES

Enumerator
HEXAGON_NUM_SIDES 
SQUARE_NUM_SIDES 

Definition at line 75 of file PolygonMeshGeneratorBase.h.

◆ INTRINSIC_SIDESET_ID

enum PolygonMeshGeneratorBase::INTRINSIC_SIDESET_ID : boundary_id_type
inherited
Enumerator
OUTER_SIDESET_ID 
OUTER_SIDESET_ID_ALT 
SLICE_BEGIN 
SLICE_END 
SLICE_ALT 

Definition at line 66 of file PolygonMeshGeneratorBase.h.

◆ INTRISIC_SUBDOMAIN_ID

enum PolygonMeshGeneratorBase::INTRISIC_SUBDOMAIN_ID : subdomain_id_type
inherited
Enumerator
PERIPHERAL_ID_SHIFT 
TRANSITION_LAYER_DEFAULT 

Definition at line 60 of file PolygonMeshGeneratorBase.h.

◆ MESH_TYPE

Enumerator
CORNER_MESH 
BOUNDARY_MESH 
INNER_MESH 

Definition at line 47 of file PolygonMeshGeneratorBase.h.

◆ PolygonSizeStyle

enum class PolygonMeshGeneratorBase::PolygonSizeStyle
stronginherited

An enum class for style of input polygon size.

Enumerator
apothem 
radius 

Definition at line 41 of file PolygonMeshGeneratorBase.h.

◆ QUAD_ELEM_TYPE

enum class PolygonMeshGeneratorBase::QUAD_ELEM_TYPE
stronginherited

◆ RETURN_TYPE

Enumerator
ANGLE_DEGREE 
ANGLE_TANGENT 

Definition at line 54 of file PolygonMeshGeneratorBase.h.

◆ TRI_ELEM_TYPE

enum class PolygonMeshGeneratorBase::TRI_ELEM_TYPE
stronginherited

Constructor & Destructor Documentation

◆ RevolveGenerator()

RevolveGenerator::RevolveGenerator ( const InputParameters parameters)

Definition at line 110 of file RevolveGenerator.C.

112 _input(getMesh("input")),
113 _axis_point(getParam<Point>("axis_point")),
114 _axis_direction(getParam<Point>("axis_direction")),
115 _revolving_angles(isParamValid("revolving_angles")
116 ? getParam<std::vector<Real>>("revolving_angles")
117 : std::vector<Real>(1, 360.0)),
118 _subdomain_swaps(getParam<std::vector<std::vector<subdomain_id_type>>>("subdomain_swaps")),
119 _boundary_swaps(getParam<std::vector<std::vector<boundary_id_type>>>("boundary_swaps")),
120 _elem_integer_names_to_swap(getParam<std::vector<std::string>>("elem_integer_names_to_swap")),
122 getParam<std::vector<std::vector<std::vector<dof_id_type>>>>("elem_integers_swaps")),
123 _clockwise(getParam<bool>("clockwise")),
124 _nums_azimuthal_intervals(getParam<std::vector<unsigned int>>("nums_azimuthal_intervals")),
125 _preserve_volumes(getParam<bool>("preserve_volumes")),
126 _has_start_boundary(isParamValid("start_boundary")),
127 _start_boundary(isParamValid("start_boundary") ? getParam<boundary_id_type>("start_boundary")
128 : 0),
129 _has_end_boundary(isParamValid("end_boundary")),
130 _end_boundary(isParamValid("end_boundary") ? getParam<boundary_id_type>("end_boundary") : 0),
132{
133 if (_revolving_angles.size() != _nums_azimuthal_intervals.size())
134 paramError("nums_azimuthal_intervals",
135 "The number of azimuthal intervals should be the same as the number of revolving "
136 "angles.");
137 if (_subdomain_swaps.size() && (_subdomain_swaps.size() != _nums_azimuthal_intervals.size()))
139 "subdomain_swaps",
140 "If specified, 'subdomain_swaps' must be the same length as 'nums_azimuthal_intervals'.");
141
142 if (_boundary_swaps.size() && (_boundary_swaps.size() != _nums_azimuthal_intervals.size()))
144 "boundary_swaps",
145 "If specified, 'boundary_swaps' must be the same length as 'nums_azimuthal_intervals'.");
146
147 for (const auto & unit_elem_integers_swaps : _elem_integers_swaps)
148 if (unit_elem_integers_swaps.size() != _nums_azimuthal_intervals.size())
149 paramError("elem_integers_swaps",
150 "If specified, each element of 'elem_integers_swaps' must have the same length as "
151 "the length of 'nums_azimuthal_intervals'.");
152
153 if (_elem_integers_swaps.size() &&
155 paramError("elem_integers_swaps",
156 "If specified, 'elem_integers_swaps' must have the same length as the length of "
157 "'elem_integer_names_to_swap'.");
158
160 MooseUtils::absoluteFuzzyEqual(
161 std::accumulate(_revolving_angles.begin(), _revolving_angles.end(), 0), 360.0)
162 ? true
163 : false;
164 if (MooseUtils::absoluteFuzzyGreaterThan(
165 std::accumulate(_revolving_angles.begin(), _revolving_angles.end(), 0), 360.0))
166 paramError("revolving_angles",
167 "The sum of revolving angles should be less than or equal to 360.");
168
171 paramError("full_circle_revolving",
172 "starting or ending boundaries can only be assigned for partial revolving.");
173
174 try
175 {
177 name(), "subdomain_swaps", _subdomain_swaps, _subdomain_swap_pairs);
178 }
179 catch (const MooseException & e)
180 {
181 paramError("subdomain_swaps", e.what());
182 }
183
184 try
185 {
187 name(), "boundary_swaps", _boundary_swaps, _boundary_swap_pairs);
188 }
189 catch (const MooseException & e)
190 {
191 paramError("boundary_swaps", e.what());
192 }
193
194 try
195 {
201 }
202 catch (const MooseException & e)
203 {
204 paramError("elem_integers_swaps", e.what());
205 }
206}
void ErrorVector unsigned int
std::unique_ptr< MeshBase > & getMesh(const std::string &param_name, const bool allow_invalid=false)
const InputParameters & parameters() const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
const T & getParam(const std::string &name) const
bool isParamValid(const std::string &name) const
virtual const char * what() const
A base class that contains common members for Reactor module mesh generators.
const std::vector< std::vector< boundary_id_type > > & _boundary_swaps
Boundaries to swap out for each elevation.
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
Easier to work with version of _sudomain_swaps.
boundary_id_type _start_boundary
Boundary ID of the starting boundary.
bool _has_start_boundary
Whether a starting boundary is specified.
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
Easier to work with version of _boundary_swaps.
const bool & _clockwise
Revolving direction.
std::unique_ptr< MeshBase > & _input
Lower dimensional mesh from another generator.
const std::vector< unsigned int > & _nums_azimuthal_intervals
Numbers of azimuthal mesh intervals in each azimuthal section.
const std::vector< std::vector< std::vector< dof_id_type > > > & _elem_integers_swaps
Extra element integers to swap out for each elevation and each element integer name.
bool _full_circle_revolving
Whether to revolve for a full circle or not.
bool _has_end_boundary
Whether an ending boundary is specified.
const bool _preserve_volumes
Volume preserving function is optional.
boundary_id_type _end_boundary
Boundary ID of the ending boundary.
const Point & _axis_direction
A direction vector of the axis of revolution.
const std::vector< std::vector< subdomain_id_type > > & _subdomain_swaps
Subdomains to swap out for each azimuthal section.
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
Easier to work with version of _elem_integers_swaps.
const std::vector< std::string > & _elem_integer_names_to_swap
Names and indices of extra element integers to swap.
Real _radius_correction_factor
Radius correction factor.
const std::vector< Real > _revolving_angles
Angles of revolution delineating each azimuthal section.
const Point & _axis_point
A point of the axis of revolution.
void extraElemIntegerSwapParametersProcessor(const std::string &class_name, const unsigned int num_sections, const unsigned int num_integers, const std::vector< std::vector< std::vector< dof_id_type > > > &elem_integers_swaps, std::vector< std::unordered_map< dof_id_type, dof_id_type > > &elem_integers_swap_pairs)
void idSwapParametersProcessor(const std::string &class_name, const std::string &id_name, const std::vector< std::vector< T > > &id_swaps, std::vector< std::unordered_map< T, T > > &id_swap_pairs, const unsigned int row_index_shift=0)
int8_t boundary_id_type
if(subdm)
uint8_t dof_id_type
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

Member Function Documentation

◆ addRingAndSectorIDParams()

void PolygonMeshGeneratorBase::addRingAndSectorIDParams ( InputParameters params)
staticprotectedinherited

Add InputParameters which are used by ring and sector IDs.

Parameters
paramsInputParameters to be modified with the added params

Definition at line 1598 of file PolygonMeshGeneratorBase.C.

1599{
1600 params.addParam<std::string>("sector_id_name",
1601 "Name of integer (reporting) ID for sector regions to use the "
1602 "reporting ID for azimuthal sector regions of ring geometry block.");
1603 params.addParam<std::string>("ring_id_name",
1604 "Name of integer (reporting) ID for ring regions to use the "
1605 "reporting ID for annular regions of ring geometry block.");
1606 MooseEnum ring_id_option("block_wise ring_wise", "block_wise");
1607 params.addParam<MooseEnum>(
1608 "ring_id_assign_type", ring_id_option, "Type of ring ID assignment: block_wise or ring_wise");
1609 params.addParamNamesToGroup("sector_id_name ring_id_name ring_id_assign_type", "Ring/Sector IDs");
1610}
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)

Referenced by PolygonConcentricCircleMeshGeneratorBase::validParams(), and TriPinHexAssemblyGenerator::validParams().

◆ adjustPeripheralQuadraticElements()

void PolygonMeshGeneratorBase::adjustPeripheralQuadraticElements ( MeshBase out_mesh,
const QUAD_ELEM_TYPE  boundary_quad_elem_type 
) const
protectedinherited

Adjusts the mid-edge node locations in boundary regions when using quadratic elements with uniform boundary node spacing enabled.

Parameters
out_meshmesh to be adjusted.
boundary_quad_elem_typeboundary quad element type.

Definition at line 1253 of file PolygonMeshGeneratorBase.C.

1255{
1256 const auto side_list = out_mesh.get_boundary_info().build_side_list();
1257
1258 // select out elements on outer boundary
1259 // std::set used to filter duplicate elem_ids
1260 std::set<dof_id_type> elem_set;
1261 for (auto side_item : side_list)
1262 {
1263 boundary_id_type boundary_id = std::get<2>(side_item);
1264 dof_id_type elem_id = std::get<0>(side_item);
1265
1266 if (boundary_id == OUTER_SIDESET_ID)
1267 elem_set.insert(elem_id);
1268 }
1269
1270 // adjust nodes for outer boundary elements
1271 for (const auto elem_id : elem_set)
1272 {
1273 Elem * elem = out_mesh.elem_ptr(elem_id);
1274
1275 // adjust right side mid-edge node
1276 Point pt_5 = (elem->point(1) + elem->point(2)) / 2.0;
1277 out_mesh.add_point(pt_5, elem->node_ptr(5)->id());
1278
1279 // adjust left side mid-edge node
1280 Point pt_7 = (elem->point(0) + elem->point(3)) / 2.0;
1281 out_mesh.add_point(pt_7, elem->node_ptr(7)->id());
1282
1283 // adjust central node when using QUAD9
1284 if (boundary_quad_elem_type == QUAD_ELEM_TYPE::QUAD9)
1285 {
1286 Point pt_8 = elem->true_centroid();
1287 out_mesh.add_point(pt_8, elem->node_ptr(8)->id());
1288 }
1289 }
1290}
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
dof_id_type id() const
const Point & point(const unsigned int i) const
virtual Point true_centroid() const
const Node * node_ptr(const unsigned int i) const
const BoundaryInfo & get_boundary_info() const
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
virtual const Elem * elem_ptr(const dof_id_type i) const=0

Referenced by PatternedCartesianMeshGenerator::generate(), and PatternedHexMeshGenerator::generate().

◆ azimuthalAnglesCollector() [1/2]

std::vector< Real > PolygonMeshGeneratorBase::azimuthalAnglesCollector ( ReplicatedMesh mesh,
const Real  lower_azi = -30.0,
const Real  upper_azi = 30.0,
const unsigned int  return_type = ANGLE_TANGENT,
const unsigned int  num_sides = 6,
const boundary_id_type  bid = OUTER_SIDESET_ID,
const bool  calculate_origin = true,
const Real  input_origin_x = 0.0,
const Real  input_origin_y = 0.0,
const Real  tol = 1.0E-10 
) const
protectedinherited

Collects sorted azimuthal angles of the external boundary.

Parameters
meshinput mesh whose boundary node azimuthal angles need to be collected
lower_azilower boundary of the azimuthal angles to be collected
upper_aziupper boundary of the azimuthal angles to be collected
return_typewhether angle values or tangent values are returned
num_sidesnumber of sides of the input mesh (only used if return type is ANGLE_TANGENT)
bidid of the boundary of which the nodes' azimuthal angles are collected
calculate_originwhether the mesh origin is calculated based on the centroid position
input_origin_xprecalculated mesh origin coordinate x
input_origin_yprecalculated mesh origin coordinate y
toltolerence that the minimum azimuthal angle is
Returns
the list of azimuthal angles of all the nodes on the external grain boundary within the given range

Definition at line 1497 of file PolygonMeshGeneratorBase.C.

1507{
1508 std::vector<Point> boundary_points;
1509 return azimuthalAnglesCollector(mesh,
1510 boundary_points,
1511 lower_azi,
1512 upper_azi,
1513 return_type,
1514 num_sides,
1515 bid,
1516 calculate_origin,
1517 input_origin_x,
1518 input_origin_y,
1519 tol);
1520}
const double tol
std::vector< Real > azimuthalAnglesCollector(ReplicatedMesh &mesh, std::vector< Point > &boundary_points, const Real lower_azi=-30.0, const Real upper_azi=30.0, const unsigned int return_type=ANGLE_TANGENT, const unsigned int num_sides=6, const boundary_id_type bid=OUTER_SIDESET_ID, const bool calculate_origin=true, const Real input_origin_x=0.0, const Real input_origin_y=0.0, const Real tol=1.0E-10) const
Collects sorted azimuthal angles of the external boundary.

◆ azimuthalAnglesCollector() [2/2]

std::vector< Real > PolygonMeshGeneratorBase::azimuthalAnglesCollector ( ReplicatedMesh mesh,
std::vector< Point > &  boundary_points,
const Real  lower_azi = -30.0,
const Real  upper_azi = 30.0,
const unsigned int  return_type = ANGLE_TANGENT,
const unsigned int  num_sides = 6,
const boundary_id_type  bid = OUTER_SIDESET_ID,
const bool  calculate_origin = true,
const Real  input_origin_x = 0.0,
const Real  input_origin_y = 0.0,
const Real  tol = 1.0E-10 
) const
protectedinherited

Collects sorted azimuthal angles of the external boundary.

Parameters
meshinput mesh whose boundary node azimuthal angles need to be collected
boundary_pointsreference vector to contain the Points corresponding to the collected azimuthal angles
lower_azilower boundary of the azimuthal angles to be collected
upper_aziupper boundary of the azimuthal angles to be collected
return_typewhether angle values or tangent values are returned
num_sidesnumber of sides of the input mesh (only used if return type is ANGLE_TANGENT)
bidid of the boundary of which the nodes' azimuthal angles are collected
calculate_originwhether the mesh origin is calculated based on the centroid position
input_origin_xprecalculated mesh origin coordinate x
input_origin_yprecalculated mesh origin coordinate y
toltolerance that the minimum azimuthal angle is
Returns
the list of azimuthal angles of all the nodes on the external grain boundary within the given range

Definition at line 1419 of file PolygonMeshGeneratorBase.C.

1430{
1431 std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> side_list =
1434 std::vector<std::tuple<dof_id_type, boundary_id_type>> node_list =
1436
1437 std::vector<Real> bd_x_list;
1438 std::vector<Real> bd_y_list;
1439 std::vector<Point> bd_p_list;
1440 Real origin_x = 0.0;
1441 Real origin_y = 0.0;
1442 Real tmp_azi;
1443 const Real mid_azi = lower_azi <= upper_azi ? (lower_azi + upper_azi) / 2.0
1444 : (lower_azi + upper_azi + 360.0) / 2.0;
1445 for (unsigned int i = 0; i < node_list.size(); ++i)
1446 if (std::get<1>(node_list[i]) == bid)
1447 {
1448 bd_x_list.push_back((mesh.node_ref(std::get<0>(node_list[i])))(0));
1449 bd_y_list.push_back((mesh.node_ref(std::get<0>(node_list[i])))(1));
1450 bd_p_list.push_back((mesh.node_ref(std::get<0>(node_list[i]))));
1451 }
1452
1453 if (calculate_origin)
1454 {
1455 const Point origin_pt = MooseMeshUtils::meshCentroidCalculator(mesh);
1456 origin_x = origin_pt(0);
1457 origin_y = origin_pt(1);
1458 }
1459 else
1460 {
1461 origin_x = input_origin_x;
1462 origin_y = input_origin_y;
1463 }
1464
1465 std::vector<std::pair<Real, Point>> azi_point_pairs;
1466
1467 for (unsigned int i = 0; i < bd_x_list.size(); ++i)
1468 {
1469 tmp_azi = atan2(bd_y_list[i] - origin_y, bd_x_list[i] - origin_x) * 180.0 / M_PI;
1470 if ((lower_azi <= upper_azi && (tmp_azi >= lower_azi - tol && tmp_azi <= upper_azi + tol)) ||
1471 (lower_azi > upper_azi && (tmp_azi >= lower_azi - tol || tmp_azi <= upper_azi + tol)))
1472 {
1473 azi_point_pairs.push_back(
1474 std::make_pair(return_type == ANGLE_DEGREE
1475 ? (tmp_azi - mid_azi)
1476 : (1.0 + std::cos(M_PI / num_sides) / std::sin(M_PI / num_sides) *
1477 std::tan((tmp_azi - mid_azi) / 180.0 * M_PI)),
1478 bd_p_list[i]));
1479 }
1480 }
1481 std::sort(azi_point_pairs.begin(), azi_point_pairs.end());
1482
1483 std::vector<Real> azimuthal_output;
1484 for (auto it = std::make_move_iterator(azi_point_pairs.begin()),
1485 end = std::make_move_iterator(azi_point_pairs.end());
1486 it != end;
1487 it++)
1488 {
1489 azimuthal_output.push_back(std::move(it->first));
1490 boundary_points.push_back(std::move(it->second));
1491 }
1492
1493 return azimuthal_output;
1494}
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
void build_node_list_from_side_list(const std::set< boundary_id_type > &sideset_list={})
virtual const Node & node_ref(const dof_id_type i) const
MeshBase & mesh
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
Point meshCentroidCalculator(const MeshBase &mesh)

Referenced by PolygonMeshGeneratorBase::azimuthalAnglesCollector(), AzimuthalBlockSplitGenerator::generate(), PatternedPolygonPeripheralModifierBase::generate(), and PolygonConcentricCircleMeshGeneratorBase::generate().

◆ backgroundNodes()

void PolygonMeshGeneratorBase::backgroundNodes ( ReplicatedMesh mesh,
const unsigned int  num_sectors_per_side,
const unsigned int  background_intervals,
const std::vector< Real >  biased_terms,
const Real  background_corner_distance,
const Real  background_corner_radial_interval_length,
const Real  corner_p[2][2],
const Real  corner_to_corner,
const Real  background_in,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>() 
) const
protectedinherited

Creates nodes for the ring-to-polygon transition region (i.e., background) of a single slice.

Parameters
meshinput mesh to add the nodes onto
num_sectors_per_sidenumber of azimuthal intervals
background_intervalsnumber of radial intervals of the background region
biased_termsnormalized spacing values used for radial meshing biasing in background region
background_corner_distancecenter to duct (innermost duct) corner distance
background_corner_radial_interval_lengthradial interval distance
corner_p[2][2]array contains the coordinates of the corner positions
corner_to_cornerdiameter of the circumscribed circle of the polygon
background_inradius of the inner boundary of the background region
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
Returns
a mesh with background region nodes created

Definition at line 720 of file PolygonMeshGeneratorBase.C.

730{
731 unsigned int angle_number =
732 azimuthal_tangent.size() == 0 ? num_sectors_per_side : (azimuthal_tangent.size() - 1);
733 for (unsigned int k = 0; k < (background_intervals); k++)
734 {
735 const Real background_corner_p_x =
736 background_corner_distance / (0.5 * corner_to_corner) * corner_p[0][0] *
737 (background_in +
738 biased_terms[k] * background_intervals * background_corner_radial_interval_length) /
739 background_corner_distance;
740 const Real background_corner_p_y =
741 background_corner_distance / (0.5 * corner_to_corner) * corner_p[0][1] *
742 (background_in +
743 biased_terms[k] * background_intervals * background_corner_radial_interval_length) /
744 background_corner_distance;
745
746 // background_corner_p(s) are the points in the background region, on the bins towards the six
747 // corners, at different intervals
748 mesh.add_point(Point(background_corner_p_x, background_corner_p_y, 0.0));
749
750 for (unsigned int j = 1; j <= angle_number; j++)
751 {
752 const Real cell_boundary_p_x =
753 background_corner_distance / (0.5 * corner_to_corner) *
754 (corner_p[0][0] + (corner_p[1][0] - corner_p[0][0]) *
755 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
756 : (azimuthal_tangent[j] / 2.0)));
757 const Real cell_boundary_p_y =
758 background_corner_distance / (0.5 * corner_to_corner) *
759 (corner_p[0][1] + (corner_p[1][1] - corner_p[0][1]) *
760 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
761 : (azimuthal_tangent[j] / 2.0)));
762 // cell_boundary_p(s) are the points on the cell's six boundaries (flat sides) at different
763 // azimuthal angles
764 const Real pin_boundary_p_x =
765 cell_boundary_p_x * background_in /
766 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
767 const Real pin_boundary_p_y =
768 cell_boundary_p_y * background_in /
769 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
770 // pin_boundary_p(s) are the points on pin boundary (outside ring) at different azimuthal
771 // angles
772 const Real background_radial_interval =
773 std::sqrt(Utility::pow<2>(cell_boundary_p_x - pin_boundary_p_x) +
774 Utility::pow<2>(cell_boundary_p_y - pin_boundary_p_y)) /
775 background_intervals;
776 const Real background_azimuthal_p_x =
777 cell_boundary_p_x *
778 (background_in + biased_terms[k] * background_intervals * background_radial_interval) /
779 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
780 const Real background_azimuthal_p_y =
781 cell_boundary_p_y *
782 (background_in + biased_terms[k] * background_intervals * background_radial_interval) /
783 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
784 // background_azimuthal_p are the points on the bins towards different azimuthal angles, at
785 // different intervals; excluding the ones produced by background_corner_p
786 mesh.add_point(Point(background_azimuthal_p_x, background_azimuthal_p_y, 0.0));
787 }
788 }
789}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ biasTermsCalculator() [1/2]

std::vector< Real > PolygonMeshGeneratorBase::biasTermsCalculator ( const Real  radial_bias,
const unsigned int  intervals,
const singleBdryLayerParams  inner_boundary_layer_params = {0.0, 0.0, 0, 1.0},
const singleBdryLayerParams  outer_boundary_layer_params = {0.0, 0.0, 0, 1.0} 
) const
protectedinherited

Creates bias terms for a single block.

Parameters
radial_biasbias growth factor of the elements within the main region of the block
intervalsradial interval number of the main region of the block
inner_boundary_layer_paramswidth, radial fraction, radial sector, and growth factor of the inner boundary layer
outer_boundary_layer_paramswidth, radial fraction, radial sector, and growth factor of the outer boundary layer
Returns
bias terms describing the cumulative radial fractions of the nodes within a single block

Definition at line 1545 of file PolygonMeshGeneratorBase.C.

1550{
1551 // To get biased indices:
1552 // If no bias is involved, namely bias factor = 1.0, the increment in indices is uniform.
1553 // Thus, (i + 1) is used to get such linearly increasing indices.
1554 // If a non-trivial bias factor q is used, the increment in the indices is geometric
1555 // progression. So, if first (i = 0) increment is 1.0, second (i = 1) is q, third (i = 2) is
1556 // q^2,..., last or n_interval'th is q^(n_interval - 1). Then, the summation of the first (i +
1557 // 1) increments over the summation of all n_interval increments is the (i + 1)th index The
1558 // summation of the first (i + 1) increments is (1.0 - q^(i + 1)) / (1 - q); The summation of
1559 // all n_interval increments is (1.0 - q^n_interval) / (1 - q); Thus, the index is (1.0 - q^(i +
1560 // 1)) / (1.0 - q^n_interval)
1561 // This approach is used by inner boundary layer, main region, outer boundary layer separately.
1562
1563 std::vector<Real> biased_terms;
1564 for (unsigned int i = 0; i < inner_boundary_layer_params.intervals; i++)
1565 biased_terms.push_back(
1566 MooseUtils::absoluteFuzzyEqual(inner_boundary_layer_params.bias, 1.0)
1567 ? ((Real)(i + 1) * inner_boundary_layer_params.fraction /
1568 (Real)inner_boundary_layer_params.intervals)
1569 : ((1.0 - std::pow(inner_boundary_layer_params.bias, (Real)(i + 1))) /
1570 (1.0 - std::pow(inner_boundary_layer_params.bias,
1571 (Real)(inner_boundary_layer_params.intervals))) *
1572 inner_boundary_layer_params.fraction));
1573 for (unsigned int i = 0; i < intervals; i++)
1574 biased_terms.push_back(inner_boundary_layer_params.fraction +
1575 (MooseUtils::absoluteFuzzyEqual(radial_bias, 1.0)
1576 ? ((Real)(i + 1) *
1577 (1.0 - inner_boundary_layer_params.fraction -
1578 outer_boundary_layer_params.fraction) /
1579 (Real)intervals)
1580 : ((1.0 - std::pow(radial_bias, (Real)(i + 1))) /
1581 (1.0 - std::pow(radial_bias, (Real)(intervals))) *
1582 (1.0 - inner_boundary_layer_params.fraction -
1583 outer_boundary_layer_params.fraction))));
1584 for (unsigned int i = 0; i < outer_boundary_layer_params.intervals; i++)
1585 biased_terms.push_back(
1586 1.0 - outer_boundary_layer_params.fraction +
1587 (MooseUtils::absoluteFuzzyEqual(outer_boundary_layer_params.bias, 1.0)
1588 ? ((Real)(i + 1) * outer_boundary_layer_params.fraction /
1589 (Real)outer_boundary_layer_params.intervals)
1590 : ((1.0 - std::pow(outer_boundary_layer_params.bias, (Real)(i + 1))) /
1591 (1.0 - std::pow(outer_boundary_layer_params.bias,
1592 (Real)(outer_boundary_layer_params.intervals))) *
1593 outer_boundary_layer_params.fraction)));
1594 return biased_terms;
1595}
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)

◆ biasTermsCalculator() [2/2]

std::vector< std::vector< Real > > PolygonMeshGeneratorBase::biasTermsCalculator ( const std::vector< Real >  radial_biases,
const std::vector< unsigned int intervals,
const multiBdryLayerParams  inner_boundary_layer_params,
const multiBdryLayerParams  outer_boundary_layer_params 
) const
protectedinherited

Creates bias terms for multiple blocks.

Parameters
radial_biasesbias growth factors of the elements within the main regions of the blocks
intervalsradial interval numbers of the main regions of the blocks
inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layers
outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layers
Returns
bias list of terms describing the cumulative radial fractions of the nodes within multiple blocks

Definition at line 1523 of file PolygonMeshGeneratorBase.C.

1528{
1529 std::vector<std::vector<Real>> bias_terms_vec;
1530 for (unsigned int i = 0; i < radial_biases.size(); i++)
1531 bias_terms_vec.push_back(biasTermsCalculator(radial_biases[i],
1532 intervals[i],
1533 {0.0,
1534 inner_boundary_layer_params.fractions[i],
1535 inner_boundary_layer_params.intervals[i],
1536 inner_boundary_layer_params.biases[i]},
1537 {0.0,
1538 outer_boundary_layer_params.fractions[i],
1539 outer_boundary_layer_params.intervals[i],
1540 outer_boundary_layer_params.biases[i]}));
1541 return bias_terms_vec;
1542}
std::vector< std::vector< Real > > biasTermsCalculator(const std::vector< Real > radial_biases, const std::vector< unsigned int > intervals, const multiBdryLayerParams inner_boundary_layer_params, const multiBdryLayerParams outer_boundary_layer_params) const
Creates bias terms for multiple blocks.

Referenced by PolygonMeshGeneratorBase::biasTermsCalculator(), PolygonMeshGeneratorBase::buildSlice(), and PeripheralRingMeshGenerator::generate().

◆ buildGeneralSlice()

std::unique_ptr< ReplicatedMesh > PolygonMeshGeneratorBase::buildGeneralSlice ( std::vector< Real >  ring_radii,
const std::vector< unsigned int ring_layers,
const std::vector< Real >  ring_radial_biases,
const multiBdryLayerParams ring_inner_boundary_layer_params,
const multiBdryLayerParams ring_outer_boundary_layer_params,
std::vector< Real >  ducts_center_dist,
const std::vector< unsigned int ducts_layers,
const std::vector< Real >  duct_radial_biases,
const multiBdryLayerParams duct_inner_boundary_layer_params,
const multiBdryLayerParams duct_outer_boundary_layer_params,
const Real  primary_side_length,
const Real  secondary_side_length,
const unsigned int  num_sectors_per_side,
const unsigned int  background_intervals,
const Real  background_radial_bias,
const singleBdryLayerParams background_inner_boundary_layer_params,
const singleBdryLayerParams background_outer_boundary_layer_params,
dof_id_type node_id_background_meta,
const Real  azimuthal_angle,
const std::vector< Real >  azimuthal_tangent,
const unsigned int  side_index,
const bool  quad_center_elements,
const Real  center_quad_factor,
const Real  rotation_angle,
const bool  generate_side_specific_boundaries = true 
)
protectedinherited

Creates a mesh of a general polygon slice with a triangular shape and circular regions on one of its vertex.

Parameters
ring_radiiradii of the ring regions
ring_layersnumbers of radial intervals of the ring regions
ring_radial_biasesvalues used for radial meshing biasing in ring regions
ring_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the ring regions
ring_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the ring regions
ducts_center_distdistance parameters of the duct regions
ducts_layersnumbers of radial intervals of the duct regions
duct_radial_biasesvalues used for radial meshing biasing in duct regions
duct_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the duct regions
duct_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the duct regions
primary_side_lengthlength of the first side (i.e., the side that is parallel to y-axis when rotation_angle is zero) that involves the ring center vertex
secondary_side_lengthlength of the second side (obtained by clockwise rotating the fist side by azimuthal_angle) that involves the ring center vertex
num_sectors_per_sidenumber of azimuthal intervals
background_intervalsnumber of radial intervals of the background region
background_radial_biasvalue used for radial meshing biasing in background region
background_inner_boundary_layer_paramswidth, radial sectors, and growth factor of the inner boundary layer of the background region
background_outer_boundary_layer_paramswidth, radial sectors, and growth factor of the outer boundary layer of the background region
node_id_background_metapointer to the first node's id of the background region
azimuthal_anglethe angle defined by the primary and secondary sides
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
side_indexindex of the polygon side
quad_center_elementswhether the central region contains quad elements or not
center_quad_factorA fractional radius factor used to determine the radial positions of transition nodes in the center region meshed by quad elements (default is 1.0 - 1.0/div_num)
rotation_angleazimuthal angle of the primary side
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
Returns
a mesh of a general slice

Definition at line 42 of file PolygonMeshGeneratorBase.C.

68{
69 const Real virtual_pitch = 2.0 * primary_side_length * cos(azimuthal_angle / 360.0 * M_PI);
70 const Real virtual_side_number = 360.0 / azimuthal_angle;
71 const Real pitch_scale_factor = secondary_side_length / primary_side_length;
72
73 auto mesh = buildSlice(ring_radii,
74 ring_layers,
75 ring_radial_biases,
76 ring_inner_boundary_layer_params,
77 ring_outer_boundary_layer_params,
78 ducts_center_dist,
79 ducts_layers,
80 duct_radial_biases,
81 duct_inner_boundary_layer_params,
82 duct_outer_boundary_layer_params,
83 virtual_pitch,
84 num_sectors_per_side,
85 background_intervals,
86 background_radial_bias,
87 background_inner_boundary_layer_params,
88 background_outer_boundary_layer_params,
89 node_id_background_meta,
90 virtual_side_number,
91 side_index,
92 azimuthal_tangent,
93 0,
94 quad_center_elements,
95 center_quad_factor,
96 false,
97 true,
98 0,
99 pitch_scale_factor,
100 generate_side_specific_boundaries);
101 MeshTools::Modification::rotate(*mesh, rotation_angle, 0, 0);
102 return mesh;
103}
std::unique_ptr< ReplicatedMesh > buildSlice(std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< Real > ring_radial_biases, const multiBdryLayerParams &ring_inner_boundary_layer_params, const multiBdryLayerParams &ring_outer_boundary_layer_params, std::vector< Real > ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< Real > duct_radial_biases, const multiBdryLayerParams &duct_inner_boundary_layer_params, const multiBdryLayerParams &duct_outer_boundary_layer_params, const Real pitch, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const Real background_radial_bias, const singleBdryLayerParams &background_inner_boundary_layer_params, const singleBdryLayerParams &background_outer_boundary_layer_params, dof_id_type &node_id_background_meta, const Real virtual_side_number, const unsigned int side_index, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const bool quad_center_elements=false, const Real center_quad_factor=0.0, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const Real pitch_scale_factor=1.0, const bool generate_side_specific_boundaries=true, const TRI_ELEM_TYPE tri_elem_type=TRI_ELEM_TYPE::TRI3, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4)
Generates a mesh of a polygon slice, which is the foundation of both buildGeneralSlice and buildSimpl...
RealTensorValue rotate(MeshBase &mesh, const Real phi, const Real theta=0., const Real psi=0.)

Referenced by TriPinHexAssemblyGenerator::buildSinglePinSection().

◆ buildSimplePeripheral()

std::unique_ptr< ReplicatedMesh > PolygonMeshGeneratorBase::buildSimplePeripheral ( const unsigned int  num_sectors_per_side,
const unsigned int  peripheral_invervals,
const std::vector< std::pair< Real, Real > > &  position_inner,
const std::vector< std::pair< Real, Real > > &  d_position_outer,
const subdomain_id_type  id_shift,
const QUAD_ELEM_TYPE  quad_elem_type,
const bool  create_inward_interface_boundaries = false,
const bool  create_outward_interface_boundaries = true 
)
protectedinherited

Creates peripheral area mesh for the patterned hexagon mesh.

Note that the function create the peripheral area for each side of the unit hexagon mesh before stitching. An edge unit hexagon has two sides that need peripheral areas, whereas a corner unit hexagon has three such sides. The positions of the inner and outer boundary nodes are pre-calculated as positions_inner and d_positions_outer; This function performs interpolation to generate the mesh grid.

Parameters
meshinput mesh to create the peripheral area mesh onto
num_sectors_per_sidenumber of azimuthal intervals
peripheral_invervalsnumber of radial intervals of the peripheral region
position_innerkey positions of the inner side of the peripheral region
d_position_outerkey inremental positions of the outer side of the peripheral region
id_shiftshift of subdomain id of the peripheral region
create_inward_interface_boundarieswhether inward interface boundary sidesets are created
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
quad_elem_typetype of quad element to be created
Returns
a mesh with the peripheral region added to a hexagon input mesh

Definition at line 1153 of file PolygonMeshGeneratorBase.C.

1162{
1163 auto mesh = buildReplicatedMesh(2);
1164 std::pair<Real, Real> positions_p;
1165
1166 // generate node positions
1167 for (unsigned int i = 0; i <= peripheral_invervals; i++)
1168 {
1169 for (unsigned int j = 0; j <= num_sectors_per_side / 2; j++)
1170 {
1171 positions_p = pointInterpolate(positions_inner[0].first,
1172 positions_inner[0].second,
1173 d_positions_outer[0].first,
1174 d_positions_outer[0].second,
1175 positions_inner[1].first,
1176 positions_inner[1].second,
1177 d_positions_outer[1].first,
1178 d_positions_outer[1].second,
1179 i,
1180 j,
1181 num_sectors_per_side,
1182 peripheral_invervals);
1183 mesh->add_point(Point(positions_p.first, positions_p.second, 0.0));
1184 }
1185 for (unsigned int j = 1; j <= num_sectors_per_side / 2; j++)
1186 {
1187 positions_p = pointInterpolate(positions_inner[1].first,
1188 positions_inner[1].second,
1189 d_positions_outer[1].first,
1190 d_positions_outer[1].second,
1191 positions_inner[2].first,
1192 positions_inner[2].second,
1193 d_positions_outer[2].first,
1194 d_positions_outer[2].second,
1195 i,
1196 j,
1197 num_sectors_per_side,
1198 peripheral_invervals);
1199 mesh->add_point(Point(positions_p.first, positions_p.second, 0.0));
1200 }
1201 }
1202
1203 // element definition
1204 BoundaryInfo & boundary_info = mesh->get_boundary_info();
1205
1206 for (unsigned int i = 0; i < peripheral_invervals; i++)
1207 {
1208 for (unsigned int j = 0; j < num_sectors_per_side; j++)
1209 {
1210 std::unique_ptr<Elem> new_elem;
1211
1212 new_elem = std::make_unique<Quad4>();
1213 new_elem->set_node(0, mesh->node_ptr(j + (num_sectors_per_side + 1) * (i)));
1214 new_elem->set_node(1, mesh->node_ptr(j + 1 + (num_sectors_per_side + 1) * (i)));
1215 new_elem->set_node(2, mesh->node_ptr(j + 1 + (num_sectors_per_side + 1) * (i + 1)));
1216 new_elem->set_node(3, mesh->node_ptr(j + (num_sectors_per_side + 1) * (i + 1)));
1217
1218 Elem * elem = mesh->add_elem(std::move(new_elem));
1219
1220 // add subdoamin and boundary IDs
1221 elem->subdomain_id() = PERIPHERAL_ID_SHIFT + id_shift;
1222 if (i == 0)
1223 {
1224 boundary_info.add_side(elem, 0, OUTER_SIDESET_ID);
1225 if (create_inward_interface_boundaries)
1226 boundary_info.add_side(elem, 0, SLICE_ALT + id_shift * 2);
1227 }
1228 if (i == peripheral_invervals - 1)
1229 {
1230 boundary_info.add_side(elem, 2, OUTER_SIDESET_ID);
1231 if (create_outward_interface_boundaries)
1232 boundary_info.add_side(elem, 2, SLICE_ALT + id_shift * 2 + 1);
1233 }
1234 if (j == 0)
1235 boundary_info.add_side(elem, 3, OUTER_SIDESET_ID);
1236 if (j == num_sectors_per_side - 1)
1237 boundary_info.add_side(elem, 1, OUTER_SIDESET_ID);
1238 }
1239 }
1240
1241 // convert element to second order if needed
1242 if (quad_elem_type != QUAD_ELEM_TYPE::QUAD4)
1243 {
1244 // full_ordered 2nd order element --> QUAD9, otherwise QUAD8
1245 const bool full_ordered = (quad_elem_type == QUAD_ELEM_TYPE::QUAD9);
1246 mesh->all_second_order(full_ordered);
1247 }
1248
1249 return mesh;
1250}
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
std::pair< Real, Real > pointInterpolate(const Real pi_1_x, const Real pi_1_y, const Real po_1_x, const Real po_1_y, const Real pi_2_x, const Real pi_2_y, const Real po_2_x, const Real po_2_y, const unsigned int i, const unsigned int j, const unsigned int num_sectors_per_side, const unsigned int peripheral_intervals) const
Calculates the point coordinates of within a parallelogram region using linear interpolation.
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
subdomain_id_type subdomain_id() const
virtual const Node * node_ptr(const dof_id_type i) const=0
void all_second_order(const bool full_ordered=true)
virtual Elem * add_elem(Elem *e)=0

Referenced by PatternedCartesianMeshGenerator::addPeripheralMesh(), and PatternedHexMeshGenerator::addPeripheralMesh().

◆ buildSimpleSlice()

std::unique_ptr< ReplicatedMesh > PolygonMeshGeneratorBase::buildSimpleSlice ( std::vector< Real >  ring_radii,
const std::vector< unsigned int ring_layers,
const std::vector< Real >  ring_radial_biases,
const multiBdryLayerParams ring_inner_boundary_layer_params,
const multiBdryLayerParams ring_outer_boundary_layer_params,
std::vector< Real >  ducts_center_dist,
const std::vector< unsigned int ducts_layers,
const std::vector< Real >  duct_radial_biases,
const multiBdryLayerParams duct_inner_boundary_layer_params,
const multiBdryLayerParams duct_outer_boundary_layer_params,
const Real  pitch,
const unsigned int  num_sectors_per_side,
const unsigned int  background_intervals,
const Real  background_radial_bias,
const singleBdryLayerParams background_inner_boundary_layer_params,
const singleBdryLayerParams background_outer_boundary_layer_params,
dof_id_type node_id_background_meta,
const unsigned int  side_number,
const unsigned int  side_index,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>(),
const subdomain_id_type  block_id_shift = 0,
const bool  quad_center_elements = false,
const Real  center_quad_factor = 0.0,
const bool  create_inward_interface_boundaries = false,
const bool  create_outward_interface_boundaries = true,
const boundary_id_type  boundary_id_shift = 0,
const bool  generate_side_specific_boundaries = true,
const TRI_ELEM_TYPE  tri_elem_type = TRI_ELEM_TYPE::TRI3,
const QUAD_ELEM_TYPE  quad_elem_type = QUAD_ELEM_TYPE::QUAD4 
)
protectedinherited

Creates a mesh of a slice that corresponds to a single side of the polygon to be generated.

Parameters
ring_radiiradii of the ring regions
ring_layersnumbers of radial intervals of the ring regions
ring_radial_biasesvalues used for radial meshing biasing in ring regions
ring_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the ring regions
ring_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the ring regions
ducts_center_distdistance parameters of the duct regions
ducts_layersnumbers of radial intervals of the duct regions
duct_radial_biasesvalues used for radial meshing biasing in duct regions
duct_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the duct regions
duct_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the duct regions
pitchtwice the distance from the ring center vertex to the side defined by the other vertices
num_sectors_per_sidenumber of azimuthal intervals
background_intervalsnumber of radial intervals of the background region
background_radial_biasvalue used for radial meshing biasing in background region
background_inner_boundary_layer_paramswidth, radial sectors, and growth factor of the inner boundary layer of the background region
background_outer_boundary_layer_paramswidth, radial sectors, and growth factor of the outer boundary layer of the background region
node_id_background_metapointer to the first node's id of the background region
side_numbernumber of sides of the polygon
side_indexindex of the polygon side
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
block_id_shiftshift of the subdomain ids generated by this function
quad_center_elementswhether the central region contrains quad elements or not
center_quad_factorA fractional radius factor used to determine the radial positions of transition nodes in the center region meshed by quad elements (default is 1.0 - 1.0/div_num)
create_inward_interface_boundarieswhether inward interface boundary sidesets are created
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
boundary_id_shiftshift of the interface boundary ids
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
tri_elem_typetype of the triangular elements to be generated
quad_elem_typetype of the quadrilateral elements to be generated
Returns
a mesh of a polygon slice

Definition at line 106 of file PolygonMeshGeneratorBase.C.

136{
137 return buildSlice(ring_radii,
138 ring_layers,
139 ring_radial_biases,
140 ring_inner_boundary_layer_params,
141 ring_outer_boundary_layer_params,
142 ducts_center_dist,
143 ducts_layers,
144 duct_radial_biases,
145 duct_inner_boundary_layer_params,
146 duct_outer_boundary_layer_params,
147 pitch,
148 num_sectors_per_side,
149 background_intervals,
150 background_radial_bias,
151 background_inner_boundary_layer_params,
152 background_outer_boundary_layer_params,
153 node_id_background_meta,
154 side_number,
155 side_index,
156 azimuthal_tangent,
157 block_id_shift,
158 quad_center_elements,
159 center_quad_factor,
160 create_inward_interface_boundaries,
161 create_outward_interface_boundaries,
162 boundary_id_shift,
163 1.0,
164 generate_side_specific_boundaries,
165 tri_elem_type,
166 quad_elem_type);
167}

Referenced by PolygonConcentricCircleMeshGeneratorBase::generate().

◆ buildSlice()

std::unique_ptr< ReplicatedMesh > PolygonMeshGeneratorBase::buildSlice ( std::vector< Real >  ring_radii,
const std::vector< unsigned int ring_layers,
const std::vector< Real >  ring_radial_biases,
const multiBdryLayerParams ring_inner_boundary_layer_params,
const multiBdryLayerParams ring_outer_boundary_layer_params,
std::vector< Real >  ducts_center_dist,
const std::vector< unsigned int ducts_layers,
const std::vector< Real >  duct_radial_biases,
const multiBdryLayerParams duct_inner_boundary_layer_params,
const multiBdryLayerParams duct_outer_boundary_layer_params,
const Real  pitch,
const unsigned int  num_sectors_per_side,
const unsigned int  background_intervals,
const Real  background_radial_bias,
const singleBdryLayerParams background_inner_boundary_layer_params,
const singleBdryLayerParams background_outer_boundary_layer_params,
dof_id_type node_id_background_meta,
const Real  virtual_side_number,
const unsigned int  side_index,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>(),
const subdomain_id_type  block_id_shift = 0,
const bool  quad_center_elements = false,
const Real  center_quad_factor = 0.0,
const bool  create_inward_interface_boundaries = false,
const bool  create_outward_interface_boundaries = true,
const boundary_id_type  boundary_id_shift = 0,
const Real  pitch_scale_factor = 1.0,
const bool  generate_side_specific_boundaries = true,
const TRI_ELEM_TYPE  tri_elem_type = TRI_ELEM_TYPE::TRI3,
const QUAD_ELEM_TYPE  quad_elem_type = QUAD_ELEM_TYPE::QUAD4 
)
protectedinherited

Generates a mesh of a polygon slice, which is the foundation of both buildGeneralSlice and buildSimpleSlice.

Parameters
ring_radiiradii of the ring regions
ring_layersnumbers of radial intervals of the ring regions
ring_radial_biasesvalues used for radial meshing biasing in ring regions
ring_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the ring regions
ring_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the ring regions
ducts_center_distdistance parameters of the duct regions
ducts_layersnumbers of radial intervals of the duct regions
duct_radial_biasesvalues used for radial meshing biasing in duct regions
duct_inner_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the inner boundary layer of the duct regions
duct_outer_boundary_layer_paramswidths, radial fractions, radial sectors, and growth factors of the outer boundary layer of the duct regions
pitchtwice of the length of the first side times cosine of the azimuthal angle
num_sectors_per_sidenumber of azimuthal intervals
background_intervalsnumber of radial intervals of the background region
background_radial_biasvalue used for radial meshing biasing in background region
background_inner_boundary_layer_paramswidth, radial sectors, and growth factor of the inner boundary layer of the background region
background_outer_boundary_layer_paramswidth, radial sectors, and growth factor of the outer boundary layer of the background region
node_id_background_metapointer to the first node's id of the background region
virtual_side_number360.0 over the azimuthal angle of the slice (happens to be number of sides of the polygon if a regular polygon is to be generated)
side_indexindex of the polygon side
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
block_id_shiftshift of the subdomain ids generated by this function
quad_center_elementswhether the central region contrains quad elements or not
center_quad_factorA fractional radius factor used to determine the radial positions of transition nodes in the center region meshed by quad elements (default is 1.0 - 1.0/div_num)
create_inward_interface_boundarieswhether inward interface boundary sidesets are created
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
boundary_id_shiftshift of the interface boundary ids
pitch_scale_factorthe ratio between the secondary side length to the primary side length.
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
tri_elem_typetype of the triangular elements to be generated
quad_elem_typetype of the quadrilateral elements to be generated
Returns
a mesh of a slice

Definition at line 170 of file PolygonMeshGeneratorBase.C.

201{
202 const unsigned short order = quad_elem_type == QUAD_ELEM_TYPE::QUAD4 ? 1 : 2;
203 if (order != (tri_elem_type == TRI_ELEM_TYPE::TRI3 ? 1 : 2))
204 mooseError("In mesh generator ",
205 this->name(),
206 ", an incompatible elements type combination is used when calling "
207 "PolygonMeshGeneratorBase::buildSlice().");
208 // In order to create quadratic elements (i.e., order = 2), we creates nodes with double mesh
209 // density. Thus, the related parameters need to be modified accordingly. A prefix "mod_" is used
210 // to indicate the modified parameters.
211
212 // For ring_layers, modification is to double the number of layers for order = 2
213 std::vector<unsigned int> mod_ring_layers(ring_layers);
214 std::for_each(
215 mod_ring_layers.begin(), mod_ring_layers.end(), [&order](unsigned int & n) { n *= order; });
216 // For ring_radial_biases, modification is to take the square root of the original biases for
217 // order = 2
218 std::vector<Real> mod_ring_radial_biases(ring_radial_biases);
219 std::for_each(mod_ring_radial_biases.begin(),
220 mod_ring_radial_biases.end(),
221 [&order](Real & n) { n = std::pow(n, 1.0 / order); });
222 // ducts_layers is similar to ring_layers
223 std::vector<unsigned int> mod_ducts_layers(ducts_layers);
224 std::for_each(
225 mod_ducts_layers.begin(), mod_ducts_layers.end(), [&order](unsigned int & n) { n *= order; });
226 // duct_radial_biases is similar to ring_radial_biases
227 std::vector<Real> mod_duct_radial_biases(duct_radial_biases);
228 std::for_each(mod_duct_radial_biases.begin(),
229 mod_duct_radial_biases.end(),
230 [&order](Real & n) { n = std::pow(n, 1.0 / order); });
231 // Azimuthal mesh density is also doubled for order = 2
232 const unsigned int mod_num_sectors_per_side = num_sectors_per_side * order;
233 const unsigned int mod_background_intervals = background_intervals * order;
234 // background_radial_bias is similar to ring_radial_biases
235 const Real mod_background_radial_bias = std::pow(background_radial_bias, 1.0 / order);
236 // Perform similar modifications for boundary layer parameters
237 const auto mod_ring_inner_boundary_layer_params =
238 modifiedMultiBdryLayerParamsCreator(ring_inner_boundary_layer_params, order);
239 const auto mod_ring_outer_boundary_layer_params =
240 modifiedMultiBdryLayerParamsCreator(ring_outer_boundary_layer_params, order);
241 const auto mod_duct_inner_boundary_layer_params =
242 modifiedMultiBdryLayerParamsCreator(duct_inner_boundary_layer_params, order);
243 const auto mod_duct_outer_boundary_layer_params =
244 modifiedMultiBdryLayerParamsCreator(duct_outer_boundary_layer_params, order);
245
246 const auto mod_background_inner_boundary_layer_params =
247 modifiedSingleBdryLayerParamsCreator(background_inner_boundary_layer_params, order);
248 const auto mod_background_outer_boundary_layer_params =
249 modifiedSingleBdryLayerParamsCreator(background_outer_boundary_layer_params, order);
250
251 // The distance parameters of the rings and duct need to be modified too as they may be involved
252 // in the boundary layer cases.
253 std::vector<Real> mod_ducts_center_dist(ducts_center_dist);
254 std::vector<Real> mod_ring_radii(ring_radii);
255 bool has_rings(ring_radii.size());
256 bool has_ducts(ducts_center_dist.size());
257 bool has_background(background_intervals);
258 auto mesh = buildReplicatedMesh(2);
259
260 // Calculate biasing terms
261 // background region needs to be split into three parts
262 const auto main_background_bias_terms =
263 biasTermsCalculator(background_radial_bias, background_intervals);
264 const auto inner_background_bias_terms =
265 biasTermsCalculator(background_inner_boundary_layer_params.bias,
266 background_inner_boundary_layer_params.intervals);
267 const auto outer_background_bias_terms =
268 biasTermsCalculator(background_outer_boundary_layer_params.bias,
269 background_outer_boundary_layer_params.intervals);
270 auto rings_bias_terms = biasTermsCalculator(ring_radial_biases,
271 ring_layers,
272 ring_inner_boundary_layer_params,
273 ring_outer_boundary_layer_params);
274 auto duct_bias_terms = biasTermsCalculator(duct_radial_biases,
275 ducts_layers,
276 duct_inner_boundary_layer_params,
277 duct_outer_boundary_layer_params);
278 // Equivalent "mod_" parts
279 const auto mod_main_background_bias_terms =
280 biasTermsCalculator(mod_background_radial_bias, mod_background_intervals);
281 const auto mod_inner_background_bias_terms =
282 biasTermsCalculator(mod_background_inner_boundary_layer_params.bias,
283 mod_background_inner_boundary_layer_params.intervals);
284 const auto mod_outer_background_bias_terms =
285 biasTermsCalculator(mod_background_outer_boundary_layer_params.bias,
286 mod_background_outer_boundary_layer_params.intervals);
287 auto mod_rings_bias_terms = biasTermsCalculator(mod_ring_radial_biases,
288 mod_ring_layers,
289 mod_ring_inner_boundary_layer_params,
290 mod_ring_outer_boundary_layer_params);
291 auto mod_duct_bias_terms = biasTermsCalculator(mod_duct_radial_biases,
292 mod_ducts_layers,
293 mod_duct_inner_boundary_layer_params,
294 mod_duct_outer_boundary_layer_params);
295
296 std::vector<unsigned int> total_ring_layers;
297 for (unsigned int i = 0; i < ring_layers.size(); i++)
298 total_ring_layers.push_back(ring_layers[i] + ring_inner_boundary_layer_params.intervals[i] +
299 ring_outer_boundary_layer_params.intervals[i]);
300
301 if (background_inner_boundary_layer_params.intervals)
302 {
303 total_ring_layers.push_back(background_inner_boundary_layer_params.intervals);
304 rings_bias_terms.push_back(inner_background_bias_terms);
305 ring_radii.push_back((ring_radii.empty() ? 0.0 : ring_radii.back()) +
306 background_inner_boundary_layer_params.width);
307 has_rings = true;
308 }
309 std::vector<unsigned int> mod_total_ring_layers;
310 for (unsigned int i = 0; i < mod_ring_layers.size(); i++)
311 mod_total_ring_layers.push_back(mod_ring_layers[i] +
312 mod_ring_inner_boundary_layer_params.intervals[i] +
313 mod_ring_outer_boundary_layer_params.intervals[i]);
314
315 if (mod_background_inner_boundary_layer_params.intervals)
316 {
317 mod_total_ring_layers.push_back(mod_background_inner_boundary_layer_params.intervals);
318 mod_rings_bias_terms.push_back(mod_inner_background_bias_terms);
319 mod_ring_radii.push_back((mod_ring_radii.empty() ? 0.0 : mod_ring_radii.back()) +
320 mod_background_inner_boundary_layer_params.width);
321 // has_rings should be modified before in the none "mod_" part
322 }
323
324 std::vector<unsigned int> total_ducts_layers;
325 if (background_outer_boundary_layer_params.intervals)
326 {
327 total_ducts_layers.push_back(background_outer_boundary_layer_params.intervals);
328 duct_bias_terms.insert(duct_bias_terms.begin(), outer_background_bias_terms);
329 ducts_center_dist.insert(ducts_center_dist.begin(),
330 (ducts_center_dist.empty()
331 ? pitch / 2.0 / std::cos(M_PI / virtual_side_number)
332 : ducts_center_dist.front()) -
333 background_outer_boundary_layer_params.width);
334 has_ducts = true;
335 }
336 for (unsigned int i = 0; i < ducts_layers.size(); i++)
337 total_ducts_layers.push_back(ducts_layers[i] + duct_inner_boundary_layer_params.intervals[i] +
338 duct_outer_boundary_layer_params.intervals[i]);
339
340 std::vector<unsigned int> mod_total_ducts_layers;
341 if (mod_background_outer_boundary_layer_params.intervals)
342 {
343 mod_total_ducts_layers.push_back(mod_background_outer_boundary_layer_params.intervals);
344 mod_duct_bias_terms.insert(mod_duct_bias_terms.begin(), mod_outer_background_bias_terms);
345 mod_ducts_center_dist.insert(mod_ducts_center_dist.begin(),
346 (mod_ducts_center_dist.empty()
347 ? pitch / 2.0 / std::cos(M_PI / virtual_side_number)
348 : mod_ducts_center_dist.front()) -
349 mod_background_outer_boundary_layer_params.width);
350 // has_ducts should be modified before in the none "mod_" part
351 }
352 for (unsigned int i = 0; i < mod_ducts_layers.size(); i++)
353 mod_total_ducts_layers.push_back(mod_ducts_layers[i] +
354 mod_duct_inner_boundary_layer_params.intervals[i] +
355 mod_duct_outer_boundary_layer_params.intervals[i]);
356
357 unsigned int angle_number = azimuthal_tangent.size() == 0
358 ? num_sectors_per_side
359 : ((azimuthal_tangent.size() - 1) / order);
360 unsigned int mod_angle_number =
361 azimuthal_tangent.size() == 0 ? mod_num_sectors_per_side : (azimuthal_tangent.size() - 1);
362
363 // Geometries
364 const Real corner_to_corner =
365 pitch / std::cos(M_PI / virtual_side_number); // distance of bin center to cell corner
366 const Real corner_p[2][2] = {
367 {0.0, 0.5 * corner_to_corner},
368 {0.5 * corner_to_corner * pitch_scale_factor * std::sin(2.0 * M_PI / virtual_side_number),
369 0.5 * corner_to_corner * pitch_scale_factor * std::cos(2.0 * M_PI / virtual_side_number)}};
370 const unsigned int div_num = angle_number / 2 + 1;
371 const unsigned int mod_div_num = mod_angle_number / 2 + 1;
372
373 // From now on, we work on the nodes, which need the "mod_" parameters
374 std::vector<std::vector<Node *>> nodes(mod_div_num, std::vector<Node *>(mod_div_num));
375 if (quad_center_elements)
376 {
377 Real ring_radii_0;
378
379 if (has_rings)
380 ring_radii_0 = ring_radii.front() * mod_rings_bias_terms.front()[order - 1];
381 else if (has_ducts)
382 ring_radii_0 = mod_ducts_center_dist.front() * std::cos(M_PI / virtual_side_number) *
383 mod_main_background_bias_terms[order - 1];
384 else
385 ring_radii_0 = pitch / 2.0 * mod_main_background_bias_terms[order - 1];
386 // If center_quad_factor is zero, default value (div_num - 1)/div_num is used.
387 // We use div_num instead of mod_div_num because we are dealing wth elements here
388 // This approach ensures that the order = 2 mesh elements are consistent with the order = 1
389 ring_radii_0 *=
390 center_quad_factor == 0.0 ? (((Real)div_num - 1.0) / (Real)div_num) : center_quad_factor;
391
392 centerNodes(*mesh, virtual_side_number, mod_div_num, ring_radii_0, nodes);
393 }
394 else // pin-cell center
395 mesh->add_point(Point(0.0, 0.0, 0.0));
396
397 // create nodes for the ring regions
398 if (has_rings)
399 ringNodes(*mesh,
400 ring_radii,
401 mod_total_ring_layers,
402 mod_rings_bias_terms,
403 mod_num_sectors_per_side,
404 corner_p,
405 corner_to_corner,
406 azimuthal_tangent);
407
408 if (has_background)
409 {
410 // add nodes in background region; the background region is defined as the area between the
411 // outermost pin (if there is a pin; if no pin, the center) and the innermost hex/duct; if
412 // _has_ducts is false, the background region is the area between the pin and enclosing hexagon
413 Real background_corner_radial_interval_length;
414 Real background_corner_distance;
415 Real background_in;
416 Real background_out; // background outer frontier
417 if (has_rings)
418 background_in = ring_radii.back();
419 else
420 background_in = 0;
421
422 if (has_ducts)
423 {
424 background_out = mod_ducts_center_dist.front();
425 background_corner_distance =
426 mod_ducts_center_dist
427 .front(); // it is the center to duct (innermost duct) corner distance
428 }
429 else
430 {
431 background_out = 0.5 * corner_to_corner;
432 background_corner_distance =
433 0.5 * corner_to_corner; // it is the center to hex corner distance
434 }
435
436 background_corner_radial_interval_length =
437 (background_out - background_in) / mod_background_intervals;
438
439 node_id_background_meta = mesh->n_nodes();
440
441 // create nodes for background region
442 backgroundNodes(*mesh,
443 mod_num_sectors_per_side,
444 mod_background_intervals,
445 mod_main_background_bias_terms,
446 background_corner_distance,
447 background_corner_radial_interval_length,
448 corner_p,
449 corner_to_corner,
450 background_in,
451 azimuthal_tangent);
452 }
453
454 // create nodes for duct regions
455 if (has_ducts)
456 ductNodes(*mesh,
457 &mod_ducts_center_dist,
458 mod_total_ducts_layers,
459 mod_duct_bias_terms,
460 mod_num_sectors_per_side,
461 corner_p,
462 corner_to_corner,
463 azimuthal_tangent);
464
465 // See if the central region is the only part of the innermost part
466 // The central region of the slice is special.
467 // Unlike the outer regions, which are layered quad elements,
468 // the central region is either a layer of tri elements or a specially-patterned quad elements.
469 // If there is at least one `ring` defined in the slice,
470 // the central region must belong to the innermost (first) ring.
471 // Otherwise the central region belongs to the `background`
472 // In either case, if the innermost ring or background has only one radial interval,
473 // the central region is an independent ring or background
474 // Otherwise, the central region and one or several quad element layers together form the
475 // innermost ring or background
476 bool is_central_region_independent;
477 if (ring_layers.empty())
478 is_central_region_independent = mod_background_inner_boundary_layer_params.intervals +
479 mod_background_intervals +
480 mod_background_outer_boundary_layer_params.intervals ==
481 1;
482 else
483 is_central_region_independent = mod_ring_layers[0] +
484 mod_ring_inner_boundary_layer_params.intervals[0] +
485 mod_ring_outer_boundary_layer_params.intervals[0] ==
486 1;
487
488 // From now on, we work on the elements, which need the none "mod_" parameters
489 // Assign elements, boundaries, and subdomains;
490 // Add Tri3/Tri6/Tri7 or Quad4/Quad8/Quad9 mesh into innermost (central) region
491 if (quad_center_elements)
492 cenQuadElemDef(*mesh,
493 div_num,
494 block_id_shift,
495 create_outward_interface_boundaries && is_central_region_independent,
496 boundary_id_shift,
497 nodes,
498 (!has_rings) && (!has_ducts) && (background_intervals == 1),
499 // Note here, has_ring means either there are ring regions or background inner
500 // boundary layer; has_ducts means either there are duct regions or background
501 // outer boundary layer. Same in cenTriElemDef()
502 side_index,
503 generate_side_specific_boundaries,
504 quad_elem_type);
505 else
507 *mesh,
508 num_sectors_per_side,
509 azimuthal_tangent,
510 block_id_shift,
511 create_outward_interface_boundaries && is_central_region_independent,
512 boundary_id_shift,
513 ((!has_rings) && (!has_ducts) && (background_intervals == 1)) ||
514 ((!has_background) &&
515 (std::accumulate(total_ring_layers.begin(), total_ring_layers.end(), 0) == 1)),
516 // Only for ACCG, it is possible that the entire mesh is a single-layer ring.
517 // cenQuadElemDef() does not need this as it does not work for ACCG.
518 side_index,
519 generate_side_specific_boundaries,
520 tri_elem_type);
521
522 // Add Quad4 mesh into outer circle
523 // total number of mesh should be all the rings for pin regions + background regions;
524 // total number of quad mesh should be total number of mesh -1 (-1 is because the inner circle for
525 // tri/quad mesh has been added above)
526
527 std::vector<unsigned int> subdomain_rings;
528 if (has_rings) // define the rings in each subdomain
529 {
530 subdomain_rings = total_ring_layers;
531 subdomain_rings.front() -= 1; // remove the inner TRI mesh subdomain
532 if (background_inner_boundary_layer_params.intervals)
533 {
534 subdomain_rings.back() =
535 background_inner_boundary_layer_params.intervals + background_intervals +
536 background_outer_boundary_layer_params.intervals; // add the background region
537 if (ring_radii.size() == 1)
538 subdomain_rings.back() -= 1; // remove the inner TRI mesh subdomain
539 }
540 else if (has_background)
541 subdomain_rings.push_back(background_inner_boundary_layer_params.intervals +
542 background_intervals +
543 background_outer_boundary_layer_params.intervals);
544 }
545 else
546 {
547 subdomain_rings.push_back(
548 background_inner_boundary_layer_params.intervals + background_intervals +
549 background_outer_boundary_layer_params.intervals); // add the background region
550 subdomain_rings[0] -= 1; // remove the inner TRI mesh subdomain
551 }
552
553 if (has_ducts)
554 for (unsigned int i = (background_outer_boundary_layer_params.intervals > 0);
555 i < total_ducts_layers.size();
556 i++)
557 subdomain_rings.push_back(total_ducts_layers[i]);
558
559 quadElemDef(*mesh,
560 num_sectors_per_side,
561 subdomain_rings,
562 side_index,
563 azimuthal_tangent,
564 block_id_shift,
565 quad_center_elements ? (mod_div_num * mod_div_num - 1) : 0,
566 create_inward_interface_boundaries,
567 create_outward_interface_boundaries,
568 boundary_id_shift,
569 generate_side_specific_boundaries,
570 quad_elem_type);
571 if (tri_elem_type == TRI_ELEM_TYPE::TRI6 || quad_elem_type == QUAD_ELEM_TYPE::QUAD8)
573 return mesh;
574}
void mooseError(Args &&... args) const
void cenTriElemDef(ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const bool assign_external_boundary=false, const unsigned int side_index=0, const bool generate_side_specific_boundaries=true, const TRI_ELEM_TYPE tri_elem_type=TRI_ELEM_TYPE::TRI3) const
Defines triangular elements in the very central region of the polygon.
void backgroundNodes(ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const unsigned int background_intervals, const std::vector< Real > biased_terms, const Real background_corner_distance, const Real background_corner_radial_interval_length, const Real corner_p[2][2], const Real corner_to_corner, const Real background_in, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
Creates nodes for the ring-to-polygon transition region (i.e., background) of a single slice.
singleBdryLayerParams modifiedSingleBdryLayerParamsCreator(const singleBdryLayerParams &original_single_bdry_layer_params, const unsigned int order) const
Modifies the input single boundary layer parameters for node generation, especially for the quadratic...
multiBdryLayerParams modifiedMultiBdryLayerParamsCreator(const multiBdryLayerParams &original_multi_bdry_layer_params, const unsigned int order) const
Modifies the input multi boundary layer parameters for node generation, especially for the quadratic ...
void ringNodes(ReplicatedMesh &mesh, const std::vector< Real > ring_radii, const std::vector< unsigned int > ring_layers, const std::vector< std::vector< Real > > biased_terms, const unsigned int num_sectors_per_side, const Real corner_p[2][2], const Real corner_to_corner, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
Creates nodes for the ring-geometry region of a single slice.
void quadElemDef(ReplicatedMesh &mesh, const unsigned int num_sectors_per_side, const std::vector< unsigned int > subdomain_rings, const unsigned int side_index, const std::vector< Real > azimuthal_tangent=std::vector< Real >(), const subdomain_id_type block_id_shift=0, const dof_id_type nodeid_shift=0, const bool create_inward_interface_boundaries=false, const bool create_outward_interface_boundaries=true, const boundary_id_type boundary_id_shift=0, const bool generate_side_specific_boundaries=true, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4) const
Defines general quad elements for the polygon.
void centerNodes(ReplicatedMesh &mesh, const Real virtual_side_number, const unsigned int div_num, const Real ring_radii_0, std::vector< std::vector< Node * > > &nodes) const
Creates nodes of the very central mesh layer of the polygon for quad central elements.
void ductNodes(ReplicatedMesh &mesh, std::vector< Real > *const ducts_center_dist, const std::vector< unsigned int > ducts_layers, const std::vector< std::vector< Real > > biased_terms, const unsigned int num_sectors_per_side, const Real corner_p[2][2], const Real corner_to_corner, const std::vector< Real > azimuthal_tangent=std::vector< Real >()) const
Creates nodes for the duct-geometry region of a single slice.
void cenQuadElemDef(ReplicatedMesh &mesh, const unsigned int div_num, const subdomain_id_type block_id_shift, const bool create_outward_interface_boundaries, const boundary_id_type boundary_id_shift, std::vector< std::vector< Node * > > &nodes, const bool assign_external_boundary=false, const unsigned int side_index=0, const bool generate_side_specific_boundaries=true, const QUAD_ELEM_TYPE quad_elem_type=QUAD_ELEM_TYPE::QUAD4) const
Defines quad elements in the very central region of the polygon.
virtual dof_id_type n_nodes() const=0
void remove_orphaned_nodes()

Referenced by PolygonMeshGeneratorBase::buildGeneralSlice(), PolygonMeshGeneratorBase::buildSimpleSlice(), and AdvancedConcentricCircleGenerator::generate().

◆ cenQuadElemDef()

void PolygonMeshGeneratorBase::cenQuadElemDef ( ReplicatedMesh mesh,
const unsigned int  div_num,
const subdomain_id_type  block_id_shift,
const bool  create_outward_interface_boundaries,
const boundary_id_type  boundary_id_shift,
std::vector< std::vector< Node * > > &  nodes,
const bool  assign_external_boundary = false,
const unsigned int  side_index = 0,
const bool  generate_side_specific_boundaries = true,
const QUAD_ELEM_TYPE  quad_elem_type = QUAD_ELEM_TYPE::QUAD4 
) const
protectedinherited

Defines quad elements in the very central region of the polygon.

Parameters
meshinput mesh to create the elements onto
div_numdivision number of the central mesh layer
block_id_shiftshift of the subdomain ids generated by this function
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
boundary_id_shiftshift of the interface boundary ids
id_arraypointer to a vector that contains the node_ids with basic geometry information
assign_external_boundarywhether the external boundary ids are assigned
side_indexindex of the polygon side (only used if external boundary ids are assigned)
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
quad_elem_typetype of the quadrilateral elements to be generated

Definition at line 853 of file PolygonMeshGeneratorBase.C.

863{
864
865 BoundaryInfo & boundary_info = mesh.get_boundary_info();
866
867 // This loop defines quad elements for the central regions except for the outermost layer
868 for (unsigned int i = 0; i < div_num - 1; i++)
869 {
870 unsigned int id_x = 0;
871 unsigned int id_y = i;
872 for (unsigned int j = 0; j < 2 * i + 1; j++)
873 {
874 std::unique_ptr<Elem> new_elem;
875 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD4)
876 {
877 new_elem = std::make_unique<Quad4>();
878 new_elem->set_node(0, nodes[id_x][id_y]);
879 new_elem->set_node(3, nodes[id_x][id_y + 1]);
880 new_elem->set_node(2, nodes[id_x + 1][id_y + 1]);
881 new_elem->set_node(1, nodes[id_x + 1][id_y]);
882 new_elem->subdomain_id() = 1 + block_id_shift;
883 }
884 else // QUAD8/QUAD9
885 {
886 new_elem = std::make_unique<Quad8>();
887 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD9)
888 {
889 new_elem = std::make_unique<Quad9>();
890 new_elem->set_node(8, nodes[id_x * 2 + 1][id_y * 2 + 1]);
891 }
892 new_elem->set_node(0, nodes[id_x * 2][id_y * 2]);
893 new_elem->set_node(3, nodes[id_x * 2][id_y * 2 + 2]);
894 new_elem->set_node(2, nodes[id_x * 2 + 2][id_y * 2 + 2]);
895 new_elem->set_node(1, nodes[id_x * 2 + 2][id_y * 2]);
896 new_elem->set_node(4, nodes[id_x * 2 + 1][id_y * 2]);
897 new_elem->set_node(5, nodes[id_x * 2 + 2][id_y * 2 + 1]);
898 new_elem->set_node(6, nodes[id_x * 2 + 1][id_y * 2 + 2]);
899 new_elem->set_node(7, nodes[id_x * 2][id_y * 2 + 1]);
900 new_elem->subdomain_id() = 1 + block_id_shift;
901 }
902 Elem * elem_Quad = mesh.add_elem(std::move(new_elem));
903
904 if (id_x == 0)
905 boundary_info.add_side(elem_Quad, 3, SLICE_BEGIN);
906 if (id_y == 0)
907 boundary_info.add_side(elem_Quad, 0, SLICE_END);
908 if (j < i)
909 id_x++;
910 if (j >= i)
911 id_y--;
912 }
913 }
914 // This loop defines the outermost layer quad elements of the central region
915 for (unsigned int i = (div_num - 1) * (div_num - 1); i < div_num * div_num - 1; i++)
916 {
917 std::unique_ptr<Elem> new_elem;
918 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD4)
919 {
920 new_elem = std::make_unique<Quad4>();
921 new_elem->set_node(0, mesh.node_ptr(i));
922 new_elem->set_node(3, mesh.node_ptr(i + 2 * div_num - 1));
923 new_elem->set_node(2, mesh.node_ptr(i + 2 * div_num));
924 new_elem->set_node(1, mesh.node_ptr(i + 1));
925 }
926 else // QUAD8/QUAD9
927 {
928 new_elem = std::make_unique<Quad8>();
929 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD9)
930 {
931 new_elem = std::make_unique<Quad9>();
932 new_elem->set_node(8,
933 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
934 (i - (div_num - 1) * (div_num - 1)) * 2 + 1 +
935 ((div_num - 1) * 4 + 1)));
936 }
937 new_elem->set_node(0,
938 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
939 (i - (div_num - 1) * (div_num - 1)) * 2));
940 new_elem->set_node(3,
941 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
942 (i - (div_num - 1) * (div_num - 1)) * 2 +
943 ((div_num - 1) * 4 + 1) * 2));
944 new_elem->set_node(2,
945 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
946 (i - (div_num - 1) * (div_num - 1)) * 2 + 2 +
947 ((div_num - 1) * 4 + 1) * 2));
948 new_elem->set_node(1,
949 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
950 (i - (div_num - 1) * (div_num - 1)) * 2 + 2));
951 new_elem->set_node(4,
952 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
953 (i - (div_num - 1) * (div_num - 1)) * 2 + 1));
954 new_elem->set_node(5,
955 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
956 (i - (div_num - 1) * (div_num - 1)) * 2 + 2 +
957 ((div_num - 1) * 4 + 1)));
958 new_elem->set_node(6,
959 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
960 (i - (div_num - 1) * (div_num - 1)) * 2 + 1 +
961 ((div_num - 1) * 4 + 1) * 2));
962 new_elem->set_node(7,
963 mesh.node_ptr((div_num - 1) * (div_num - 1) * 4 +
964 (i - (div_num - 1) * (div_num - 1)) * 2 +
965 ((div_num - 1) * 4 + 1)));
966 }
967
968 Elem * elem_Quad = mesh.add_elem(std::move(new_elem));
969 elem_Quad->subdomain_id() = 1 + block_id_shift;
970 if (create_outward_interface_boundaries)
971 boundary_info.add_side(elem_Quad, 2, 1 + boundary_id_shift);
972 if (i == (div_num - 1) * (div_num - 1))
973 boundary_info.add_side(elem_Quad, 3, SLICE_BEGIN);
974 if (i == div_num * div_num - 2)
975 boundary_info.add_side(elem_Quad, 1, SLICE_END);
976 if (assign_external_boundary)
977 {
978 boundary_info.add_side(elem_Quad, 2, OUTER_SIDESET_ID);
979 if (generate_side_specific_boundaries)
980 boundary_info.add_side(
981 elem_Quad,
982 2,
983 (i < div_num * (div_num - 1) ? OUTER_SIDESET_ID : OUTER_SIDESET_ID_ALT) + side_index);
984 }
985 }
986}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ centerNodes()

void PolygonMeshGeneratorBase::centerNodes ( ReplicatedMesh mesh,
const Real  virtual_side_number,
const unsigned int  div_num,
const Real  ring_radii_0,
std::vector< std::vector< Node * > > &  nodes 
) const
protectedinherited

Creates nodes of the very central mesh layer of the polygon for quad central elements.

Parameters
meshinput mesh to add the nodes onto
virtual_side_numbervirtual number of sides of the polygon (360/slice_azimuthal)
div_numdivision number of the central mesh layer
ring_radii_0radius of the central mesh layer
nodespointer to the mesh's nodes
nodesvector that contains the nodes with basic geometry information

Definition at line 577 of file PolygonMeshGeneratorBase.C.

582{
583 const std::pair<Real, Real> p_origin = std::make_pair(0.0, 0.0);
584 const std::pair<Real, Real> p_bottom =
585 std::make_pair(0.0, ring_radii_0 * std::cos(M_PI / virtual_side_number));
586 const std::pair<Real, Real> p_top =
587 std::make_pair(p_bottom.second * std::sin(2.0 * M_PI / virtual_side_number),
588 p_bottom.second * std::cos(2.0 * M_PI / virtual_side_number));
589 const std::pair<Real, Real> p_diag =
590 std::make_pair(ring_radii_0 * std::sin(M_PI / virtual_side_number),
591 ring_radii_0 * std::cos(M_PI / virtual_side_number));
592
593 // The four vertices of the central quad region are defined above.
594 // The following loops transverse all the nodes within this central quad region by moving p1 thru
595 // p4 and calculate the four-point intercept (pc).
596 // p_top------o-------p4--------o-----p_diag
597 // | | | | |
598 // | | | | |
599 // o--------o--------o--------o--------o
600 // | | | | |
601 // | | | | |
602 // p1--------o-------pc--------o-------p2
603 // | | | | |
604 // | | | | |
605 // o--------o--------o--------o--------o
606 // | | | | |
607 // | | | | |
608 // p_origin-----o-------p3--------o----p_bottom
609 //
610 // The loops are designed to transverse the nodes as shown below to facilitate elements
611 // and sides creation.
612 //
613 // 25-------24-------23-------22-------21
614 // | | | | |
615 // | | | | |
616 // 16-------15-------14-------13-------20
617 // | | | | |
618 // | | | | |
619 // 9--------8------- 7-------12-------19
620 // | | | | |
621 // | | | | |
622 // 4--------3--------6-------11-------18
623 // | | | | |
624 // | | | | |
625 // 1--------2--------5-------10-------17
626
627 for (unsigned int i = 0; i < div_num; i++)
628 {
629 unsigned int id_x = 0;
630 unsigned int id_y = i;
631 for (unsigned int j = 0; j < 2 * i + 1; j++)
632 {
633 std::pair<Real, Real> p1 = std::make_pair(
634 (p_origin.first * (div_num - 1 - id_x) + p_top.first * id_x) / (div_num - 1),
635 (p_origin.second * (div_num - 1 - id_x) + p_top.second * id_x) / (div_num - 1));
636 std::pair<Real, Real> p2 = std::make_pair(
637 (p_bottom.first * (div_num - 1 - id_x) + p_diag.first * id_x) / (div_num - 1),
638 (p_bottom.second * (div_num - 1 - id_x) + p_diag.second * id_x) / (div_num - 1));
639 std::pair<Real, Real> p3 = std::make_pair(
640 (p_origin.first * (div_num - 1 - id_y) + p_bottom.first * id_y) / (div_num - 1),
641 (p_origin.second * (div_num - 1 - id_y) + p_bottom.second * id_y) / (div_num - 1));
642 std::pair<Real, Real> p4 = std::make_pair(
643 (p_top.first * (div_num - 1 - id_y) + p_diag.first * id_y) / (div_num - 1),
644 (p_top.second * (div_num - 1 - id_y) + p_diag.second * id_y) / (div_num - 1));
645 std::pair<Real, Real> pc = fourPointIntercept(p1, p2, p3, p4);
646 nodes[id_x][id_y] = mesh.add_point(Point(pc.first, pc.second, 0.0));
647 if (j < i)
648 id_x++;
649 if (j >= i)
650 id_y--;
651 }
652 }
653}
std::pair< Real, Real > fourPointIntercept(const std::pair< Real, Real > &p1, const std::pair< Real, Real > &p2, const std::pair< Real, Real > &p3, const std::pair< Real, Real > &p4) const
Finds the center of a quadrilateral based on four vertices.

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ cenTriElemDef()

void PolygonMeshGeneratorBase::cenTriElemDef ( ReplicatedMesh mesh,
const unsigned int  num_sectors_per_side,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>(),
const subdomain_id_type  block_id_shift = 0,
const bool  create_outward_interface_boundaries = true,
const boundary_id_type  boundary_id_shift = 0,
const bool  assign_external_boundary = false,
const unsigned int  side_index = 0,
const bool  generate_side_specific_boundaries = true,
const TRI_ELEM_TYPE  tri_elem_type = TRI_ELEM_TYPE::TRI3 
) const
protectedinherited

Defines triangular elements in the very central region of the polygon.

Parameters
meshinput mesh to create the elements onto
num_sectors_per_sidenumber of azimuthal intervals
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
block_id_shiftshift of the subdomain ids generated by this function
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
boundary_id_shiftshift of the interface boundary ids
assign_external_boundarywhether the external boundary ids are assigned
side_indexindex of the polygon side (only used if external boundary ids are assigned)
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
tri_elem_typetype of the triangular elements to be generated

Definition at line 989 of file PolygonMeshGeneratorBase.C.

999{
1000 const unsigned short order = tri_elem_type == TRI_ELEM_TYPE::TRI3 ? 1 : 2;
1001 unsigned int angle_number = azimuthal_tangent.size() == 0
1002 ? num_sectors_per_side
1003 : ((azimuthal_tangent.size() - 1) / order);
1004
1005 BoundaryInfo & boundary_info = mesh.get_boundary_info();
1006 for (unsigned int i = 1; i <= angle_number; i++)
1007 {
1008 std::unique_ptr<Elem> new_elem;
1009 if (tri_elem_type == TRI_ELEM_TYPE::TRI3)
1010 {
1011 new_elem = std::make_unique<Tri3>();
1012 new_elem->set_node(0, mesh.node_ptr(0));
1013 new_elem->set_node(2, mesh.node_ptr(i));
1014 new_elem->set_node(1, mesh.node_ptr(i + 1));
1015 }
1016 else // TRI6/TRI7
1017 {
1018 new_elem = std::make_unique<Tri6>();
1019 if (tri_elem_type == TRI_ELEM_TYPE::TRI7)
1020 {
1021 new_elem = std::make_unique<Tri7>();
1022 new_elem->set_node(6, mesh.node_ptr(i * 2));
1023 }
1024 new_elem->set_node(0, mesh.node_ptr(0));
1025 new_elem->set_node(2, mesh.node_ptr(i * 2 + angle_number * order));
1026 new_elem->set_node(1, mesh.node_ptr((i + 1) * 2 + angle_number * order));
1027 new_elem->set_node(3, mesh.node_ptr(i * 2 + 1));
1028 new_elem->set_node(5, mesh.node_ptr(i * 2 - 1));
1029 new_elem->set_node(4, mesh.node_ptr(i * 2 + 1 + angle_number * order));
1030 }
1031
1032 Elem * elem = mesh.add_elem(std::move(new_elem));
1033 if (create_outward_interface_boundaries)
1034 boundary_info.add_side(elem, 1, 1 + boundary_id_shift);
1035 elem->subdomain_id() = 1 + block_id_shift;
1036 if (i == 1)
1037 boundary_info.add_side(elem, 2, SLICE_BEGIN);
1038 if (i == angle_number)
1039 boundary_info.add_side(elem, 0, SLICE_END);
1040 if (assign_external_boundary)
1041 {
1042 boundary_info.add_side(elem, 1, OUTER_SIDESET_ID);
1043 if (generate_side_specific_boundaries)
1044 boundary_info.add_side(elem,
1045 1,
1046 (i <= angle_number / 2 ? OUTER_SIDESET_ID : OUTER_SIDESET_ID_ALT) +
1047 side_index);
1048 }
1049 }
1050}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ createHEXfromQUAD()

void RevolveGenerator::createHEXfromQUAD ( const ElemType  hex_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
bool &  is_flipped 
) const
protected

Create a new HEX element from an existing QUAD element by revolving it.

Parameters
hex_elem_typethe type of the new HEX element
elemthe QUAD element to be revolved
meshthe mesh that the new HEX element will be added to
new_elemthe new HEX element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 2046 of file RevolveGenerator.C.

2055{
2056 if (hex_elem_type != HEX8 && hex_elem_type != HEX20 && hex_elem_type != HEX27)
2057 mooseError("unsupported situation");
2058
2059 side_pairs.push_back(std::make_pair(0, 5));
2060 const unsigned int order = hex_elem_type == HEX8 ? 1 : 2;
2061
2062 new_elem = std::make_unique<Hex8>();
2063 if (order == 2)
2064 {
2065 new_elem = std::make_unique<Hex20>();
2066 if (hex_elem_type == HEX27)
2067 {
2068 new_elem = std::make_unique<Hex27>();
2069 new_elem->set_node(
2070 20, mesh->node_ptr(elem->node_ptr(8)->id() + (current_layer * 2 * orig_nodes)));
2071 new_elem->set_node(
2072 25,
2073 mesh->node_ptr(elem->node_ptr(8)->id() + ((current_layer + 1) %
2074 (total_num_azimuthal_intervals + 1 -
2075 (unsigned int)_full_circle_revolving) *
2076 2 * orig_nodes)));
2077 new_elem->set_node(
2078 26, mesh->node_ptr(elem->node_ptr(8)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2079 new_elem->set_node(
2080 21, mesh->node_ptr(elem->node_ptr(4)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2081 new_elem->set_node(
2082 22, mesh->node_ptr(elem->node_ptr(5)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2083 new_elem->set_node(
2084 23, mesh->node_ptr(elem->node_ptr(6)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2085 new_elem->set_node(
2086 24, mesh->node_ptr(elem->node_ptr(7)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2087 }
2088 new_elem->set_node(8,
2089 mesh->node_ptr(elem->node_ptr(4)->id() + (current_layer * 2 * orig_nodes)));
2090 new_elem->set_node(9,
2091 mesh->node_ptr(elem->node_ptr(5)->id() + (current_layer * 2 * orig_nodes)));
2092 new_elem->set_node(10,
2093 mesh->node_ptr(elem->node_ptr(6)->id() + (current_layer * 2 * orig_nodes)));
2094 new_elem->set_node(11,
2095 mesh->node_ptr(elem->node_ptr(7)->id() + (current_layer * 2 * orig_nodes)));
2096 new_elem->set_node(
2097 16,
2098 mesh->node_ptr(elem->node_ptr(4)->id() +
2099 ((current_layer + 1) %
2100 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2101 2 * orig_nodes)));
2102 new_elem->set_node(
2103 17,
2104 mesh->node_ptr(elem->node_ptr(5)->id() +
2105 ((current_layer + 1) %
2106 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2107 2 * orig_nodes)));
2108 new_elem->set_node(
2109 18,
2110 mesh->node_ptr(elem->node_ptr(6)->id() +
2111 ((current_layer + 1) %
2112 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2113 2 * orig_nodes)));
2114 new_elem->set_node(
2115 19,
2116 mesh->node_ptr(elem->node_ptr(7)->id() +
2117 ((current_layer + 1) %
2118 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2119 2 * orig_nodes)));
2120 new_elem->set_node(
2121 12, mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2122 new_elem->set_node(
2123 13, mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2124 new_elem->set_node(
2125 14, mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2126 new_elem->set_node(
2127 15, mesh->node_ptr(elem->node_ptr(3)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2128 }
2129 new_elem->set_node(
2130 0, mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * order * orig_nodes)));
2131 new_elem->set_node(
2132 1, mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * order * orig_nodes)));
2133 new_elem->set_node(
2134 2, mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * order * orig_nodes)));
2135 new_elem->set_node(
2136 3, mesh->node_ptr(elem->node_ptr(3)->id() + (current_layer * order * orig_nodes)));
2137 new_elem->set_node(
2138 4,
2139 mesh->node_ptr(elem->node_ptr(0)->id() +
2140 ((current_layer + 1) %
2141 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2142 order * orig_nodes)));
2143 new_elem->set_node(
2144 5,
2145 mesh->node_ptr(elem->node_ptr(1)->id() +
2146 ((current_layer + 1) %
2147 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2148 order * orig_nodes)));
2149 new_elem->set_node(
2150 6,
2151 mesh->node_ptr(elem->node_ptr(2)->id() +
2152 ((current_layer + 1) %
2153 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2154 order * orig_nodes)));
2155 new_elem->set_node(
2156 7,
2157 mesh->node_ptr(elem->node_ptr(3)->id() +
2158 ((current_layer + 1) %
2159 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2160 order * orig_nodes)));
2161
2162 if (new_elem->volume() < 0.0)
2163 {
2164 MooseMeshUtils::swapNodesInElem(*new_elem, 0, 4);
2165 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 5);
2166 MooseMeshUtils::swapNodesInElem(*new_elem, 2, 6);
2167 MooseMeshUtils::swapNodesInElem(*new_elem, 3, 7);
2168 if (order == 2)
2169 {
2170 MooseMeshUtils::swapNodesInElem(*new_elem, 8, 16);
2171 MooseMeshUtils::swapNodesInElem(*new_elem, 9, 17);
2172 MooseMeshUtils::swapNodesInElem(*new_elem, 10, 18);
2173 MooseMeshUtils::swapNodesInElem(*new_elem, 11, 19);
2174 if (hex_elem_type == HEX27)
2175 {
2176 MooseMeshUtils::swapNodesInElem(*new_elem, 20, 25);
2177 }
2178 }
2179 is_flipped = true;
2180 }
2181}
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)

Referenced by generate().

◆ createPRISMfromQUAD()

void RevolveGenerator::createPRISMfromQUAD ( const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &  nodes_cates,
const ElemType  prism_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
dof_id_type axis_node_case,
bool &  is_flipped 
) const
protected

Create a new PRISM element from an existing QUAD element by revolving it.

Parameters
nodes_catesa pair of two lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis
prism_elem_typethe type of the new PRISM element
elemthe QUAD element to be revolved
meshthe mesh that the new PRISM element will be added to
new_elemthe new PRISM element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
axis_node_casea parameter to record on-axis node(s)
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 2184 of file RevolveGenerator.C.

2196{
2197 if (prism_elem_type != PRISM6 && prism_elem_type != PRISM15 && prism_elem_type != PRISM18)
2198 mooseError("unsupported situation");
2199
2200 side_pairs.push_back(std::make_pair(1, 3));
2201 const unsigned int order = prism_elem_type == PRISM6 ? 1 : 2;
2202 if (order == 2)
2203 {
2204 // Sanity check to filter unsupported cases
2205 if (nodes_cates.first[0] > 3 || nodes_cates.first[1] > 3 || nodes_cates.first[2] < 4)
2206 mooseError("unsupported situation 2");
2207 }
2208 // Can only be 0-1, 1-2, 2-3, 3-0, we only consider vetices here.
2209 // nodes_cates are natually sorted
2210 const dof_id_type min_on_axis = nodes_cates.first[0];
2211 const dof_id_type max_on_axis = nodes_cates.first[1];
2212 axis_node_case = max_on_axis - min_on_axis == 1 ? min_on_axis : max_on_axis;
2213
2214 new_elem = std::make_unique<Prism6>();
2215 if (order == 2)
2216 {
2217 new_elem = std::make_unique<Prism15>();
2218 if (prism_elem_type == PRISM18)
2219 {
2220 new_elem = std::make_unique<Prism18>();
2221 new_elem->set_node(
2222 15, mesh->node_ptr(elem->node_ptr(8)->id() + (current_layer * 2 * orig_nodes)));
2223 new_elem->set_node(16,
2224 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2225 ((current_layer * 2 + 1) * orig_nodes)));
2226 new_elem->set_node(
2227 17,
2228 mesh->node_ptr(elem->node_ptr(8)->id() + ((current_layer + 1) %
2229 (total_num_azimuthal_intervals + 1 -
2230 (unsigned int)_full_circle_revolving) *
2231 2 * orig_nodes)));
2232 }
2233 new_elem->set_node(9, mesh->node_ptr(elem->node_ptr(axis_node_case + 4)->id()));
2234 new_elem->set_node(10,
2235 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2236 (current_layer * 2 * orig_nodes)));
2237 new_elem->set_node(12,
2238 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4 + 4)->id() +
2239 (current_layer * 2 * orig_nodes)));
2240 new_elem->set_node(6,
2241 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4 + 4)->id() +
2242 (current_layer * 2 * orig_nodes)));
2243 new_elem->set_node(
2244 14,
2245 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4 + 4)->id() +
2246 ((current_layer + 1) %
2247 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2248 2 * orig_nodes)));
2249 new_elem->set_node(
2250 8,
2251 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4 + 4)->id() +
2252 ((current_layer + 1) %
2253 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2254 2 * orig_nodes)));
2255 new_elem->set_node(
2256 11,
2257 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2258 ((current_layer + 1) %
2259 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2260 2 * orig_nodes)));
2261 new_elem->set_node(7,
2262 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2263 ((current_layer * 2 + 1) * orig_nodes)));
2264 new_elem->set_node(13,
2265 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2266 ((current_layer * 2 + 1) * orig_nodes)));
2267 }
2268 new_elem->set_node(0, mesh->node_ptr(elem->node_ptr(axis_node_case)->id()));
2269 new_elem->set_node(3, mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id()));
2270 new_elem->set_node(4,
2271 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2272 (current_layer * order * orig_nodes)));
2273 new_elem->set_node(1,
2274 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2275 (current_layer * order * orig_nodes)));
2276 new_elem->set_node(
2277 5,
2278 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2279 ((current_layer + 1) %
2280 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2281 order * orig_nodes)));
2282 new_elem->set_node(
2283 2,
2284 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2285 ((current_layer + 1) %
2286 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2287 order * orig_nodes)));
2288
2289 if (new_elem->volume() < 0.0)
2290 {
2291 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 2);
2292 MooseMeshUtils::swapNodesInElem(*new_elem, 4, 5);
2293 if (order == 2)
2294 {
2295 MooseMeshUtils::swapNodesInElem(*new_elem, 12, 14);
2296 MooseMeshUtils::swapNodesInElem(*new_elem, 6, 8);
2297 MooseMeshUtils::swapNodesInElem(*new_elem, 10, 11);
2298 if (prism_elem_type == PRISM18)
2299 {
2300 MooseMeshUtils::swapNodesInElem(*new_elem, 15, 17);
2301 }
2302 }
2303 is_flipped = true;
2304 }
2305}

Referenced by generate().

◆ createPRISMfromTRI()

void RevolveGenerator::createPRISMfromTRI ( const ElemType  prism_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
bool &  is_flipped 
) const
protected

Create a new PRISM element from an existing TRI element by revolving it.

Parameters
prism_elem_typethe type of the new TET element
elemthe TRI element to be revolved
meshthe mesh that the new TET element will be added to
new_elemthe new TET element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 1692 of file RevolveGenerator.C.

1701{
1702 if (prism_elem_type != PRISM6 && prism_elem_type != PRISM18 && prism_elem_type != PRISM21)
1703 mooseError("unsupported situation");
1704
1705 side_pairs.push_back(std::make_pair(0, 4));
1706 const unsigned int order = prism_elem_type == PRISM6 ? 1 : 2;
1707
1708 new_elem = std::make_unique<Prism6>();
1709
1710 if (order == 2)
1711 {
1712 new_elem = std::make_unique<Prism18>();
1713 if (prism_elem_type == PRISM21)
1714 {
1715 new_elem = std::make_unique<Prism21>();
1716 new_elem->set_node(
1717 18, mesh->node_ptr(elem->node_ptr(6)->id() + (current_layer * 2 * orig_nodes)));
1718 new_elem->set_node(
1719 19,
1720 mesh->node_ptr(elem->node_ptr(6)->id() + ((current_layer + 1) %
1721 (total_num_azimuthal_intervals + 1 -
1722 (unsigned int)_full_circle_revolving) *
1723 2 * orig_nodes)));
1724 new_elem->set_node(
1725 20, mesh->node_ptr(elem->node_ptr(6)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1726 }
1727 new_elem->set_node(6,
1728 mesh->node_ptr(elem->node_ptr(3)->id() + (current_layer * 2 * orig_nodes)));
1729 new_elem->set_node(7,
1730 mesh->node_ptr(elem->node_ptr(4)->id() + (current_layer * 2 * orig_nodes)));
1731 new_elem->set_node(8,
1732 mesh->node_ptr(elem->node_ptr(5)->id() + (current_layer * 2 * orig_nodes)));
1733 new_elem->set_node(
1734 9, mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1735 new_elem->set_node(
1736 10, mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1737 new_elem->set_node(
1738 11, mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1739 new_elem->set_node(
1740 12,
1741 mesh->node_ptr(elem->node_ptr(3)->id() +
1742 ((current_layer + 1) %
1743 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1744 2 * orig_nodes)));
1745 new_elem->set_node(
1746 13,
1747 mesh->node_ptr(elem->node_ptr(4)->id() +
1748 ((current_layer + 1) %
1749 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1750 2 * orig_nodes)));
1751 new_elem->set_node(
1752 14,
1753 mesh->node_ptr(elem->node_ptr(5)->id() +
1754 ((current_layer + 1) %
1755 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1756 2 * orig_nodes)));
1757 new_elem->set_node(
1758 15, mesh->node_ptr(elem->node_ptr(3)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1759 new_elem->set_node(
1760 16, mesh->node_ptr(elem->node_ptr(4)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1761 new_elem->set_node(
1762 17, mesh->node_ptr(elem->node_ptr(5)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1763 }
1764 new_elem->set_node(
1765 0, mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * order * orig_nodes)));
1766 new_elem->set_node(
1767 1, mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * order * orig_nodes)));
1768 new_elem->set_node(
1769 2, mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * order * orig_nodes)));
1770 new_elem->set_node(
1771 3,
1772 mesh->node_ptr(elem->node_ptr(0)->id() +
1773 ((current_layer + 1) %
1774 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1775 order * orig_nodes)));
1776 new_elem->set_node(
1777 4,
1778 mesh->node_ptr(elem->node_ptr(1)->id() +
1779 ((current_layer + 1) %
1780 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1781 order * orig_nodes)));
1782 new_elem->set_node(
1783 5,
1784 mesh->node_ptr(elem->node_ptr(2)->id() +
1785 ((current_layer + 1) %
1786 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1787 order * orig_nodes)));
1788
1789 if (new_elem->volume() < 0.0)
1790 {
1791 MooseMeshUtils::swapNodesInElem(*new_elem, 0, 3);
1792 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 4);
1793 MooseMeshUtils::swapNodesInElem(*new_elem, 2, 5);
1794 if (prism_elem_type != PRISM6)
1795 {
1796 MooseMeshUtils::swapNodesInElem(*new_elem, 6, 12);
1797 MooseMeshUtils::swapNodesInElem(*new_elem, 7, 13);
1798 MooseMeshUtils::swapNodesInElem(*new_elem, 8, 14);
1799 if (prism_elem_type == PRISM21)
1800 {
1801 MooseMeshUtils::swapNodesInElem(*new_elem, 18, 19);
1802 }
1803 }
1804 is_flipped = true;
1805 }
1806}

Referenced by generate().

◆ createPYRAMIDfromTRI()

void RevolveGenerator::createPYRAMIDfromTRI ( const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &  nodes_cates,
const ElemType  pyramid_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
dof_id_type axis_node_case,
bool &  is_flipped 
) const
protected

Create a new PYRAMID element from an existing TRI element by revolving it.

Parameters
nodes_catesa pair of two lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis
pyramid_elem_typethe type of the new PYRAMID element
elemthe TRI element to be revolved
meshthe mesh that the new PYRAMID element will be added to
new_elemthe new PYRAMID element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
axis_node_casea parameter to record on-axis node(s)
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 1809 of file RevolveGenerator.C.

1821{
1822 if (pyramid_elem_type != PYRAMID5 && pyramid_elem_type != PYRAMID13 &&
1823 pyramid_elem_type != PYRAMID18)
1824 mooseError("unsupported situation");
1825
1826 side_pairs.push_back(std::make_pair(0, 2));
1827 const unsigned int order = pyramid_elem_type == PYRAMID5 ? 1 : 2;
1828 axis_node_case = nodes_cates.first.front();
1829
1830 new_elem = std::make_unique<Pyramid5>();
1831
1832 if (order == 2)
1833 {
1834 new_elem = std::make_unique<Pyramid13>();
1835 if (pyramid_elem_type == PYRAMID18)
1836 {
1837 new_elem = std::make_unique<Pyramid18>();
1838 new_elem->set_node(13,
1839 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3 + 3)->id() +
1840 ((current_layer * 2 + 1) * orig_nodes)));
1841 new_elem->set_node(15,
1842 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3 + 3)->id() +
1843 ((current_layer * 2 + 1) * orig_nodes)));
1844 new_elem->set_node(17,
1845 mesh->node_ptr(elem->node_ptr(axis_node_case + 3)->id() +
1846 ((current_layer * 2 + 1) * orig_nodes)));
1847 new_elem->set_node(
1848 14, mesh->node_ptr(elem->node_ptr(6)->id() + (current_layer * 2 * orig_nodes)));
1849 new_elem->set_node(
1850 16,
1851 mesh->node_ptr(elem->node_ptr(6)->id() + ((current_layer + 1) %
1852 (total_num_azimuthal_intervals + 1 -
1853 (unsigned int)_full_circle_revolving) *
1854 2 * orig_nodes)));
1855 }
1856 new_elem->set_node(6,
1857 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3)->id() +
1858 ((current_layer * 2 + 1) * orig_nodes)));
1859 new_elem->set_node(8,
1860 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3)->id() +
1861 ((current_layer * 2 + 1) * orig_nodes)));
1862 new_elem->set_node(5,
1863 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3 + 3)->id() +
1864 (current_layer * 2 * orig_nodes)));
1865 new_elem->set_node(
1866 7,
1867 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3 + 3)->id() +
1868 ((current_layer + 1) %
1869 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1870 2 * orig_nodes)));
1871 new_elem->set_node(9,
1872 mesh->node_ptr(elem->node_ptr(axis_node_case + 3)->id() +
1873 (current_layer * 2 * orig_nodes)));
1874 new_elem->set_node(10,
1875 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3 + 3)->id() +
1876 (current_layer * 2 * orig_nodes)));
1877 new_elem->set_node(
1878 12,
1879 mesh->node_ptr(elem->node_ptr(axis_node_case + 3)->id() +
1880 ((current_layer + 1) %
1881 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1882 2 * orig_nodes)));
1883 new_elem->set_node(
1884 11,
1885 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3 + 3)->id() +
1886 ((current_layer + 1) %
1887 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1888 2 * orig_nodes)));
1889 }
1890 new_elem->set_node(4, mesh->node_ptr(elem->node_ptr(axis_node_case)->id()));
1891 new_elem->set_node(0,
1892 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3)->id() +
1893 (current_layer * order * orig_nodes)));
1894 new_elem->set_node(1,
1895 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3)->id() +
1896 (current_layer * order * orig_nodes)));
1897 new_elem->set_node(
1898 2,
1899 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 3)->id() +
1900 ((current_layer + 1) %
1901 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1902 order * orig_nodes)));
1903 new_elem->set_node(
1904 3,
1905 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 3)->id() +
1906 ((current_layer + 1) %
1907 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1908 order * orig_nodes)));
1909
1910 if (new_elem->volume() < 0.0)
1911 {
1912 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 2);
1913 MooseMeshUtils::swapNodesInElem(*new_elem, 0, 3);
1914 if (order == 2)
1915 {
1916 MooseMeshUtils::swapNodesInElem(*new_elem, 5, 7);
1917 MooseMeshUtils::swapNodesInElem(*new_elem, 10, 11);
1918 MooseMeshUtils::swapNodesInElem(*new_elem, 9, 12);
1919 if (pyramid_elem_type == PYRAMID18)
1920 {
1921 MooseMeshUtils::swapNodesInElem(*new_elem, 14, 16);
1922 }
1923 }
1924 is_flipped = true;
1925 }
1926}

Referenced by generate().

◆ createPYRAMIDPRISMfromQUAD()

void RevolveGenerator::createPYRAMIDPRISMfromQUAD ( const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &  nodes_cates,
const ElemType  pyramid_elem_type,
const ElemType  prism_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
std::unique_ptr< Elem > &  new_elem_1,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
dof_id_type axis_node_case,
bool &  is_flipped,
bool &  is_flipped_additional 
) const
protected

Create a new PYRAMID element and a new PRISM element from an existing QUAD element by revolving it.

Parameters
nodes_catesa pair of two lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis
pyramid_elem_typethe type of the new PYRAMID element
prism_elem_typethe type of the new PRISM element
elemthe QUAD element to be revolved
meshthe mesh that the new PYRAMID element will be added to
new_elemthe new PYRAMID element
new_elem_1the new PRISM element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
axis_node_casea parameter to record on-axis node(s)
is_flippeda flag to indicate whether the PYRAMID element is flipped after creation (to ensure a positive element volume)
is_flipped_additionala flag to indicate whether the PRISM element is flipped after (to ensure a positive element volume) creation

Definition at line 2308 of file RevolveGenerator.C.

2323{
2324 if (!(pyramid_elem_type == PYRAMID5 && prism_elem_type == PRISM6) &&
2325 !(pyramid_elem_type == PYRAMID14 && prism_elem_type == PRISM18))
2326 mooseError("unsupported situation");
2327 const unsigned int order = pyramid_elem_type == PYRAMID5 ? 1 : 2;
2328
2329 side_pairs.push_back(std::make_pair(0, 2));
2330 axis_node_case = nodes_cates.first.front();
2331 new_elem = std::make_unique<Pyramid5>();
2332 if (pyramid_elem_type == PYRAMID14)
2333 {
2334 new_elem = std::make_unique<Pyramid14>();
2335 new_elem->set_node(9,
2336 mesh->node_ptr(elem->node_ptr(axis_node_case + 4)->id() +
2337 (current_layer * 2 * orig_nodes)));
2338 new_elem->set_node(10,
2339 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4 + 4)->id() +
2340 (current_layer * 2 * orig_nodes)));
2341 new_elem->set_node(5,
2342 mesh->node_ptr(elem->node_ptr(8)->id() + (current_layer * 2 * orig_nodes)));
2343 new_elem->set_node(8,
2344 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2345 ((current_layer * 2 + 1) * orig_nodes)));
2346 new_elem->set_node(6,
2347 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2348 ((current_layer * 2 + 1) * orig_nodes)));
2349 new_elem->set_node(
2350 13, mesh->node_ptr(elem->node_ptr(8)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2351 new_elem->set_node(
2352 7,
2353 mesh->node_ptr(elem->node_ptr(8)->id() +
2354 ((current_layer + 1) %
2355 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2356 2 * orig_nodes)));
2357 new_elem->set_node(
2358 11,
2359 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4 + 4)->id() +
2360 ((current_layer + 1) %
2361 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2362 2 * orig_nodes)));
2363 new_elem->set_node(
2364 12,
2365 mesh->node_ptr(elem->node_ptr(axis_node_case + 4)->id() +
2366 ((current_layer + 1) %
2367 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2368 2 * orig_nodes)));
2369 }
2370 new_elem->set_node(4, mesh->node_ptr(elem->node_ptr(axis_node_case)->id()));
2371 new_elem->set_node(0,
2372 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2373 (current_layer * order * orig_nodes)));
2374 new_elem->set_node(1,
2375 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2376 (current_layer * order * orig_nodes)));
2377 new_elem->set_node(
2378 2,
2379 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2380 ((current_layer + 1) %
2381 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2382 order * orig_nodes)));
2383 new_elem->set_node(
2384 3,
2385 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2386 ((current_layer + 1) %
2387 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2388 order * orig_nodes)));
2389
2390 if (new_elem->volume() < 0.0)
2391 {
2392 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 2);
2393 MooseMeshUtils::swapNodesInElem(*new_elem, 0, 3);
2394 if (pyramid_elem_type == PYRAMID14)
2395 {
2396 MooseMeshUtils::swapNodesInElem(*new_elem, 5, 7);
2397 MooseMeshUtils::swapNodesInElem(*new_elem, 10, 11);
2398 MooseMeshUtils::swapNodesInElem(*new_elem, 9, 12);
2399 }
2400 is_flipped = true;
2401 }
2402
2403 side_pairs.push_back(std::make_pair(0, 4));
2404 new_elem_1 = std::make_unique<Prism6>();
2405 if (prism_elem_type == PRISM18)
2406 {
2407 new_elem_1 = std::make_unique<Prism18>();
2408 new_elem_1->set_node(
2409 6, mesh->node_ptr(elem->node_ptr(8)->id() + (current_layer * 2 * orig_nodes)));
2410 new_elem_1->set_node(8,
2411 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4 + 4)->id() +
2412 (current_layer * 2 * orig_nodes)));
2413 new_elem_1->set_node(7,
2414 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2415 (current_layer * 2 * orig_nodes)));
2416 new_elem_1->set_node(9,
2417 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2418 ((current_layer * 2 + 1) * orig_nodes)));
2419 new_elem_1->set_node(10,
2420 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2421 ((current_layer * 2 + 1) * orig_nodes)));
2422 new_elem_1->set_node(11,
2423 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2424 ((current_layer * 2 + 1) * orig_nodes)));
2425 new_elem_1->set_node(
2426 15, mesh->node_ptr(elem->node_ptr(8)->id() + ((current_layer * 2 + 1) * orig_nodes)));
2427 new_elem_1->set_node(17,
2428 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4 + 4)->id() +
2429 ((current_layer * 2 + 1) * orig_nodes)));
2430 new_elem_1->set_node(16,
2431 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2432 ((current_layer * 2 + 1) * orig_nodes)));
2433 new_elem_1->set_node(
2434 12,
2435 mesh->node_ptr(elem->node_ptr(8)->id() +
2436 ((current_layer + 1) %
2437 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2438 2 * orig_nodes)));
2439 new_elem_1->set_node(
2440 13,
2441 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4 + 4)->id() +
2442 ((current_layer + 1) %
2443 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2444 2 * orig_nodes)));
2445 new_elem_1->set_node(
2446 14,
2447 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4 + 4)->id() +
2448 ((current_layer + 1) %
2449 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2450 2 * orig_nodes)));
2451 }
2452 new_elem_1->set_node(0,
2453 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2454 (current_layer * order * orig_nodes)));
2455 new_elem_1->set_node(1,
2456 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2457 (current_layer * order * orig_nodes)));
2458 new_elem_1->set_node(2,
2459 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2460 (current_layer * order * orig_nodes)));
2461 new_elem_1->set_node(
2462 3,
2463 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 4)->id() +
2464 ((current_layer + 1) %
2465 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2466 order * orig_nodes)));
2467 new_elem_1->set_node(
2468 4,
2469 mesh->node_ptr(elem->node_ptr((axis_node_case + 3) % 4)->id() +
2470 ((current_layer + 1) %
2471 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2472 order * orig_nodes)));
2473 new_elem_1->set_node(
2474 5,
2475 mesh->node_ptr(elem->node_ptr((axis_node_case + 2) % 4)->id() +
2476 ((current_layer + 1) %
2477 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2478 order * orig_nodes)));
2479
2480 if (new_elem_1->volume() < 0.0)
2481 {
2482 MooseMeshUtils::swapNodesInElem(*new_elem_1, 0, 3);
2483 MooseMeshUtils::swapNodesInElem(*new_elem_1, 1, 4);
2484 MooseMeshUtils::swapNodesInElem(*new_elem_1, 2, 5);
2485 if (prism_elem_type == PRISM18)
2486 {
2487 MooseMeshUtils::swapNodesInElem(*new_elem_1, 6, 12);
2488 MooseMeshUtils::swapNodesInElem(*new_elem_1, 7, 13);
2489 MooseMeshUtils::swapNodesInElem(*new_elem_1, 8, 14);
2490 }
2491 is_flipped_additional = true;
2492 }
2493}

Referenced by generate().

◆ createQUADfromEDGE()

void RevolveGenerator::createQUADfromEDGE ( const ElemType  quad_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
bool &  is_flipped 
) const
protected

Create a new QUAD element from an existing EDGE element by revolving it.

Parameters
quad_elem_typethe type of the new QUAD element
elemthe EDGE element to be revolved
meshthe mesh that the new QUAD element will be added to
new_elemthe new QUAD element
current_layerthe current azimuthal layer
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 1568 of file RevolveGenerator.C.

1577{
1578 if (quad_elem_type != QUAD4 && quad_elem_type != QUAD9)
1579 mooseError("Unsupported element type", quad_elem_type);
1580
1581 side_pairs.push_back(std::make_pair(0, 2));
1582 const unsigned int order = quad_elem_type == QUAD4 ? 1 : 2;
1583
1584 new_elem = std::make_unique<Quad4>();
1585 if (quad_elem_type == QUAD9)
1586 {
1587 new_elem = std::make_unique<Quad9>();
1588 new_elem->set_node(4,
1589 mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * 2 * orig_nodes)));
1590 new_elem->set_node(
1591 5, mesh->node_ptr(elem->node_ptr(1)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1592 new_elem->set_node(
1593 6,
1594 mesh->node_ptr(elem->node_ptr(2)->id() +
1595 ((current_layer + 1) %
1596 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1597 2 * orig_nodes)));
1598 new_elem->set_node(
1599 7, mesh->node_ptr(elem->node_ptr(0)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1600 new_elem->set_node(
1601 8, mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1602 }
1603
1604 new_elem->set_node(
1605 0, mesh->node_ptr(elem->node_ptr(0)->id() + (current_layer * order * orig_nodes)));
1606 new_elem->set_node(
1607 1, mesh->node_ptr(elem->node_ptr(1)->id() + (current_layer * order * orig_nodes)));
1608 new_elem->set_node(
1609 3,
1610 mesh->node_ptr(elem->node_ptr(0)->id() +
1611 ((current_layer + 1) %
1612 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1613 order * orig_nodes)));
1614 new_elem->set_node(
1615 2,
1616 mesh->node_ptr(elem->node_ptr(1)->id() +
1617 ((current_layer + 1) %
1618 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1619 order * orig_nodes)));
1620
1621 if (new_elem->volume() < 0.0)
1622 {
1623 MooseMeshUtils::swapNodesInElem(*new_elem, 0, 3);
1624 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 2);
1625 if (quad_elem_type == QUAD9)
1626 MooseMeshUtils::swapNodesInElem(*new_elem, 4, 6);
1627 is_flipped = true;
1628 }
1629}

Referenced by generate().

◆ createTETfromTRI()

void RevolveGenerator::createTETfromTRI ( const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &  nodes_cates,
const ElemType  tet_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
dof_id_type axis_node_case,
bool &  is_flipped 
) const
protected

Create a new TET element from an existing TRI element by revolving it.

Parameters
nodes_catesa pair of two lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis
tet_elem_typethe type of the new TET element
elemthe TRI element to be revolved
meshthe mesh that the new TET element will be added to
new_elemthe new TET element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
axis_node_casea parameter to record on-axis node(s)
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 1929 of file RevolveGenerator.C.

1941{
1942 if (tet_elem_type != TET4 && tet_elem_type != TET10 && tet_elem_type != TET14)
1943 mooseError("unsupported situation");
1944
1945 side_pairs.push_back(std::make_pair(0, 1));
1946 const unsigned int order = tet_elem_type == TET4 ? 1 : 2;
1947 if (order == 2)
1948 {
1949 // Sanity check to filter unsupported cases
1950 if (nodes_cates.first[0] > 2 || nodes_cates.first[1] > 2 || nodes_cates.first[2] < 3)
1951 mooseError("unsupported situation 2");
1952 }
1953 axis_node_case = nodes_cates.second.front();
1954
1955 new_elem = std::make_unique<Tet4>();
1956 if (order == 2)
1957 {
1958 const bool node_order = nodes_cates.first[1] - nodes_cates.first[0] == 1;
1959 new_elem = std::make_unique<Tet10>();
1960 if (tet_elem_type == TET14)
1961 {
1962 new_elem = std::make_unique<Tet14>();
1963 new_elem->set_node(
1964 12,
1965 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.first[1] + 3)
1966 : (nodes_cates.second.front() + 3))
1967 ->id() +
1968 ((current_layer * 2 + 1) * orig_nodes)));
1969 new_elem->set_node(13,
1970 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.second.front() + 3)
1971 : (nodes_cates.first[0] + 3))
1972 ->id() +
1973 ((current_layer * 2 + 1) * orig_nodes)));
1974 new_elem->set_node(
1975 10, mesh->node_ptr(elem->node_ptr(6)->id() + (current_layer * 2 * orig_nodes)));
1976 new_elem->set_node(
1977 11,
1978 mesh->node_ptr(elem->node_ptr(6)->id() + ((current_layer + 1) %
1979 (total_num_azimuthal_intervals + 1 -
1980 (unsigned int)_full_circle_revolving) *
1981 2 * orig_nodes)));
1982 }
1983 new_elem->set_node(4,
1984 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.first[0] + 3)
1985 : (nodes_cates.first[1] + 3))
1986 ->id()));
1987 new_elem->set_node(5,
1988 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.first[1] + 3)
1989 : (nodes_cates.second.front() + 3))
1990 ->id() +
1991 (current_layer * 2 * orig_nodes)));
1992 new_elem->set_node(6,
1993 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.second.front() + 3)
1994 : (nodes_cates.first[0] + 3))
1995 ->id() +
1996 (current_layer * 2 * orig_nodes)));
1997 new_elem->set_node(
1998 8,
1999 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.first[1] + 3)
2000 : (nodes_cates.second.front() + 3))
2001 ->id() +
2002 ((current_layer + 1) %
2003 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2004 2 * orig_nodes)));
2005 new_elem->set_node(
2006 7,
2007 mesh->node_ptr(elem->node_ptr(node_order ? (nodes_cates.second.front() + 3)
2008 : (nodes_cates.first[0] + 3))
2009 ->id() +
2010 ((current_layer + 1) %
2011 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2012 2 * orig_nodes)));
2013 new_elem->set_node(9,
2014 mesh->node_ptr(elem->node_ptr(nodes_cates.second.front())->id() +
2015 ((current_layer * 2 + 1) * orig_nodes)));
2016 }
2017 new_elem->set_node(0, mesh->node_ptr(elem->node_ptr(nodes_cates.first[0])->id()));
2018 new_elem->set_node(1, mesh->node_ptr(elem->node_ptr(nodes_cates.first[1])->id()));
2019 new_elem->set_node(2,
2020 mesh->node_ptr(elem->node_ptr(nodes_cates.second.front())->id() +
2021 (current_layer * order * orig_nodes)));
2022 new_elem->set_node(
2023 3,
2024 mesh->node_ptr(elem->node_ptr(nodes_cates.second.front())->id() +
2025 ((current_layer + 1) %
2026 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
2027 order * orig_nodes)));
2028
2029 if (new_elem->volume() < 0.0)
2030 {
2031 MooseMeshUtils::swapNodesInElem(*new_elem, 2, 3);
2032 if (order == 2)
2033 {
2034 MooseMeshUtils::swapNodesInElem(*new_elem, 5, 8);
2035 MooseMeshUtils::swapNodesInElem(*new_elem, 6, 7);
2036 if (tet_elem_type == TET14)
2037 {
2038 MooseMeshUtils::swapNodesInElem(*new_elem, 10, 11);
2039 }
2040 }
2041 is_flipped = true;
2042 }
2043}

Referenced by generate().

◆ createTRIfromEDGE()

void RevolveGenerator::createTRIfromEDGE ( const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &  nodes_cates,
const ElemType  tri_elem_type,
const Elem elem,
const std::unique_ptr< MeshBase > &  mesh,
std::unique_ptr< Elem > &  new_elem,
const int  current_layer,
const unsigned int  orig_nodes,
const unsigned int  total_num_azimuthal_intervals,
std::vector< std::pair< dof_id_type, dof_id_type > > &  side_pairs,
dof_id_type axis_node_case,
bool &  is_flipped 
) const
protected

Create a new TRI element from an existing EDGE element by revolving it.

Parameters
nodes_catesa pair of two lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis
tri_elem_typethe type of the new TRI element
elemthe EDGE element to be revolved
meshthe mesh that the new TRI element will be added to
new_elemthe new TRI element
current_layerthe current layer of the revolving
orig_nodesthe number of nodes in the original mesh
total_num_azimuthal_intervalsthe total number of azimuthal intervals for revolving
side_pairsa vector of pairs to record the corresponding side indices of the original and the new elements
axis_node_casea parameter to record on-axis node(s)
is_flippeda flag to indicate whether the new element is flipped after creation (to ensure a positive element volume)

Definition at line 1632 of file RevolveGenerator.C.

1644{
1645 if (tri_elem_type != TRI3 && tri_elem_type != TRI7)
1646 mooseError("Unsupported element type", tri_elem_type);
1647
1648 side_pairs.push_back(std::make_pair(0, 2));
1649 const unsigned int order = tri_elem_type == TRI3 ? 1 : 2;
1650 axis_node_case = nodes_cates.first.front();
1651
1652 new_elem = std::make_unique<Tri3>();
1653 if (tri_elem_type == TRI7)
1654 {
1655 new_elem = std::make_unique<Tri7>();
1656 new_elem->set_node(3,
1657 mesh->node_ptr(elem->node_ptr(2)->id() + (current_layer * 2 * orig_nodes)));
1658 new_elem->set_node(4,
1659 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 2)->id() +
1660 ((current_layer * 2 + 1) * orig_nodes)));
1661 new_elem->set_node(
1662 5,
1663 mesh->node_ptr(elem->node_ptr(2)->id() +
1664 ((current_layer + 1) %
1665 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1666 2 * orig_nodes)));
1667 new_elem->set_node(
1668 6, mesh->node_ptr(elem->node_ptr(2)->id() + ((current_layer * 2 + 1) * orig_nodes)));
1669 }
1670
1671 new_elem->set_node(0, mesh->node_ptr(elem->node_ptr(axis_node_case)->id()));
1672 new_elem->set_node(1,
1673 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 2)->id() +
1674 (current_layer * order * orig_nodes)));
1675 new_elem->set_node(
1676 2,
1677 mesh->node_ptr(elem->node_ptr((axis_node_case + 1) % 2)->id() +
1678 ((current_layer + 1) %
1679 (total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
1680 order * orig_nodes)));
1681
1682 if (new_elem->volume() < 0.0)
1683 {
1684 MooseMeshUtils::swapNodesInElem(*new_elem, 1, 2);
1685 if (tri_elem_type == TRI7)
1686 MooseMeshUtils::swapNodesInElem(*new_elem, 3, 5);
1687 is_flipped = true;
1688 }
1689}

Referenced by generate().

◆ cutOffPolyDeform()

void PolygonMeshGeneratorBase::cutOffPolyDeform ( MeshBase mesh,
const Real  orientation,
const Real  y_max_0,
const Real  y_max_n,
const Real  y_min,
const unsigned int  mesh_type,
const Real  unit_angle = 60.0,
const Real  tols = 1E-5 
) const
protectedinherited

Deforms peripheral region when the external side of a polygon assembly of stitched meshes cuts off the stitched meshes.

Parameters
meshinput mesh to be deformed
orientationorientation angle of the input mesh (move the deformation direction to y)
y_max_0original maximum y position
y_max_nmaximum y position after deformation
y_minminimum y position that is affected by the deformation
mesh_typewhether the peripheral region is for a corner or a side hexagon mesh.
tolstolerance used to determine the boundary of deformation region
unit_angleunit angle of the geometry, which is 60.0 for hexagonal and 90.0 for square
Returns
n/a (input mesh is directly altered)

Definition at line 1329 of file PolygonMeshGeneratorBase.C.

1337{
1338 for (auto & node_ptr : as_range(mesh.nodes_begin(), mesh.nodes_end()))
1339 {
1340 // This function can definitely be optimized in future for better efficiency.
1341 Real & x = (*node_ptr)(0);
1342 Real & y = (*node_ptr)(1);
1343 if (mesh_type == CORNER_MESH)
1344 {
1345 nodeCoordRotate(x, y, orientation);
1346 if (x >= 0.0 && y > y_max_0)
1347 y = y - y_max_0 + y_max_n;
1348 else if (x >= 0.0 && y >= y_min)
1349 y = (y - y_min) / (y_max_0 - y_min) * (y_max_n - y_min) + y_min;
1350 else if (y > -x / std::tan(unit_angle / 360.0 * M_PI) + tols && y > y_max_0)
1351 {
1352 x /= y;
1353 y = y - y_max_0 + y_max_n;
1354 x *= y;
1355 }
1356 else if (y > -x / std::tan(unit_angle / 360.0 * M_PI) + tols && y >= y_min)
1357 {
1358 x /= y;
1359 y = (y - y_min) / (y_max_0 - y_min) * (y_max_n - y_min) + y_min;
1360 x *= y;
1361 }
1362 nodeCoordRotate(x, y, -orientation);
1363
1364 nodeCoordRotate(x, y, orientation - unit_angle);
1365 if (x <= 0 && y > y_max_0)
1366 y = y - y_max_0 + y_max_n;
1367 else if (x <= 0 && y >= y_min)
1368 y = (y - y_min) / (y_max_0 - y_min) * (y_max_n - y_min) + y_min;
1369 else if (y >= x / std::tan(unit_angle / 360.0 * M_PI) - tols && y > y_max_0)
1370 {
1371 x /= y;
1372 y = y - y_max_0 + y_max_n;
1373 x *= y;
1374 }
1375 else if (y >= x / std::tan(unit_angle / 360.0 * M_PI) - tols && y >= y_min)
1376 {
1377 x /= y;
1378 y = (y - y_min) / (y_max_0 - y_min) * (y_max_n - y_min) + y_min;
1379 x *= y;
1380 }
1381 nodeCoordRotate(x, y, unit_angle - orientation);
1382 }
1383 else
1384 {
1385 nodeCoordRotate(x, y, orientation);
1386 if (y > y_max_0)
1387 y = y - y_max_0 + y_max_n;
1388 else if (y >= y_min)
1389 y = (y - y_min) / (y_max_0 - y_min) * (y_max_n - y_min) + y_min;
1390 nodeCoordRotate(x, y, -orientation);
1391 }
1392 }
1393}
const std::vector< double > y
const std::vector< double > x
void nodeCoordRotate(Real &x, Real &y, const Real theta) const
Calculates x and y coordinates after rotating by theta angle.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)

Referenced by PatternedCartesianMeshGenerator::generate(), and PatternedHexMeshGenerator::generate().

◆ ductNodes()

void PolygonMeshGeneratorBase::ductNodes ( ReplicatedMesh mesh,
std::vector< Real > *const  ducts_center_dist,
const std::vector< unsigned int ducts_layers,
const std::vector< std::vector< Real > >  biased_terms,
const unsigned int  num_sectors_per_side,
const Real  corner_p[2][2],
const Real  corner_to_corner,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>() 
) const
protectedinherited

Creates nodes for the duct-geometry region of a single slice.

Parameters
meshinput mesh to add the nodes onto
ducts_center_distdistance parameters of the duct regions
ducts_layersnumbers of radial intervals of the duct regions
biased_termsnormalized spacing values used for radial meshing biasing in duct region
num_sectors_per_sidenumber of azimuthal intervals
corner_p[2][2]array contains the coordinates of the corner positions
corner_to_cornerdiameter of the circumscribed circle of the polygon
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching

Definition at line 792 of file PolygonMeshGeneratorBase.C.

800{
801 unsigned int angle_number =
802 azimuthal_tangent.size() == 0 ? num_sectors_per_side : (azimuthal_tangent.size() - 1);
803 // Add nodes in ducts regions
804 (*ducts_center_dist)
805 .push_back(0.5 * corner_to_corner); // add hex boundary as the last element in this vector
806 std::vector<Real> duct_radius_interval_length(ducts_layers.size());
807
808 Real bin_radial_distance;
809 for (unsigned int l = 0; l < ducts_layers.size(); l++)
810 {
811 duct_radius_interval_length[l] =
812 ((*ducts_center_dist)[l + 1] - (*ducts_center_dist)[l]) /
813 ducts_layers[l]; // the pin radius interval for each ring_radii/subdomain
814
815 // add rings in each pin subdomain
816 for (unsigned int k = 0; k < ducts_layers[l]; k++)
817 {
818 bin_radial_distance = ((*ducts_center_dist)[l] +
819 biased_terms[l][k] * ducts_layers[l] * duct_radius_interval_length[l]);
820 const Real pin_corner_p_x = corner_p[0][0] * bin_radial_distance / (0.5 * corner_to_corner);
821 const Real pin_corner_p_y = corner_p[0][1] * bin_radial_distance / (0.5 * corner_to_corner);
822
823 // pin_corner_p(s) are the points in the pin region, on the bins towards the six corners,
824 // at different intervals
825 mesh.add_point(Point(pin_corner_p_x, pin_corner_p_y, 0.0));
826
827 for (unsigned int j = 1; j <= angle_number; j++)
828 {
829 const Real cell_boundary_p_x =
830 corner_p[0][0] + (corner_p[1][0] - corner_p[0][0]) *
831 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
832 : (azimuthal_tangent[j] / 2.0));
833 const Real cell_boundary_p_y =
834 corner_p[0][1] + (corner_p[1][1] - corner_p[0][1]) *
835 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
836 : (azimuthal_tangent[j] / 2.0));
837 // cell_boundary_p(s) are the points on the cell's six boundaries (flat sides) at
838 // different azimuthal angles
839 const Real pin_azimuthal_p_x =
840 cell_boundary_p_x * bin_radial_distance / (0.5 * corner_to_corner);
841 const Real pin_azimuthal_p_y =
842 cell_boundary_p_y * bin_radial_distance / (0.5 * corner_to_corner);
843
844 // pin_azimuthal_p are the points on the bins towards different azimuthal angles, at
845 // different intervals; excluding the ones produced by pin_corner_p
846 mesh.add_point(Point(pin_azimuthal_p_x, pin_azimuthal_p_y, 0.0));
847 }
848 }
849 }
850}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ fourPointIntercept()

std::pair< Real, Real > PolygonMeshGeneratorBase::fourPointIntercept ( const std::pair< Real, Real > &  p1,
const std::pair< Real, Real > &  p2,
const std::pair< Real, Real > &  p3,
const std::pair< Real, Real > &  p4 
) const
protectedinherited

Finds the center of a quadrilateral based on four vertices.

Parameters
p1vertex 1
p2vertex 2
p3vertex 3
p4vertex 4
Returns
the intecept point coordinate x and y

Definition at line 1396 of file PolygonMeshGeneratorBase.C.

1400{
1401 const Real x1 = p1.first;
1402 const Real y1 = p1.second;
1403 const Real x2 = p2.first;
1404 const Real y2 = p2.second;
1405 const Real x3 = p3.first;
1406 const Real y3 = p3.second;
1407 const Real x4 = p4.first;
1408 const Real y4 = p4.second;
1409
1410 Real x = -((x1 - x2) * (y3 * x4 - x3 * y4) - (x3 - x4) * (y1 * x2 - x1 * y2)) /
1411 ((y1 - y2) * (x3 - x4) - (y3 - y4) * (x1 - x2));
1412 Real y = -((y1 - y2) * (y3 * x4 - x3 * y4) - (y3 - y4) * (y1 * x2 - x1 * y2)) /
1413 ((y1 - y2) * (x3 - x4) - (y3 - y4) * (x1 - x2));
1414
1415 return std::make_pair(x, y);
1416}

Referenced by PolygonMeshGeneratorBase::centerNodes(), and AzimuthalBlockSplitGenerator::nodeModifier().

◆ generate()

std::unique_ptr< MeshBase > RevolveGenerator::generate ( )
overridevirtual

Reimplemented from PolygonMeshGeneratorBase.

Definition at line 209 of file RevolveGenerator.C.

210{
211 // Note: Inspired by AdvancedExtruderGenerator::generate()
212
213 auto mesh = buildMeshBaseObject();
214
215 // Only works for 1D and 2D input meshes
216 if (_input->mesh_dimension() > 2)
217 paramError("input", "This mesh generator only works for 1D and 2D input meshes.");
218
219 mesh->set_mesh_dimension(_input->mesh_dimension() + 1);
220
221 // Check if the element integer names are existent in the input mesh.
222 for (const auto i : index_range(_elem_integer_names_to_swap))
223 if (_input->has_elem_integer(_elem_integer_names_to_swap[i]))
225 _input->get_elem_integer_index(_elem_integer_names_to_swap[i]));
226 else
227 paramError("elem_integer_names_to_swap",
228 "Element ",
229 i + 1,
230 " of 'elem_integer_names_to_swap' is not a valid extra element integer of the "
231 "input mesh.");
232
233 // prepare for transferring extra element integers from original mesh to the revolved mesh.
234 const unsigned int num_extra_elem_integers = _input->n_elem_integers();
235 std::vector<std::string> id_names;
236
237 for (const auto i : make_range(num_extra_elem_integers))
238 {
239 id_names.push_back(_input->get_elem_integer_name(i));
240 if (!mesh->has_elem_integer(id_names[i]))
241 mesh->add_elem_integer(id_names[i]);
242 }
243
244 // retrieve subdomain/sideset/nodeset name maps
245 const auto & input_subdomain_map = _input->get_subdomain_name_map();
246 const auto & input_sideset_map = _input->get_boundary_info().get_sideset_name_map();
247 const auto & input_nodeset_map = _input->get_boundary_info().get_nodeset_name_map();
248
249 std::unique_ptr<MeshBase> input = std::move(_input);
250
251 // If we're using a distributed mesh... then make sure we don't have any remote elements hanging
252 // around
253 if (!input->is_serial())
255
256 // Subdomain IDs for on-axis elements must be new
257 if (!input->preparation().has_cached_elem_data)
258 input->cache_elem_data();
259
260 // check that subdomain swap sources exist in the mesh
261 std::set<subdomain_id_type> blocks;
262 input->subdomain_ids(blocks, true);
263 for (const auto & swap_map : _subdomain_swap_pairs)
264 for (const auto & [bid, tbid] : swap_map)
265 {
266 libmesh_ignore(tbid);
267 if (blocks.count(bid) == 0)
268 paramError("subdomain_swaps",
269 "Source subdomain " + std::to_string(bid) + " was not found in the mesh");
270 }
271
272 std::set<subdomain_id_type> subdomain_ids_set;
273 input->subdomain_ids(subdomain_ids_set);
274 const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
275 const subdomain_id_type tri_to_pyramid_subdomain_id_shift =
276 std::max((int)max_subdomain_id, 1) + 1;
277 const subdomain_id_type tri_to_tet_subdomain_id_shift =
278 std::max((int)max_subdomain_id, 1) * 2 + 1;
279 const subdomain_id_type quad_to_prism_subdomain_id_shift = std::max((int)max_subdomain_id, 1) + 1;
280 const subdomain_id_type quad_to_pyramid_subdomain_id_shift =
281 std::max((int)max_subdomain_id, 1) * 2 + 1;
282 const subdomain_id_type quad_to_hi_pyramid_subdomain_id_shift =
283 std::max((int)max_subdomain_id, 1) * 3 + 1;
284 const subdomain_id_type edge_to_tri_subdomain_id_shift = std::max((int)max_subdomain_id, 1) + 1;
285
286 // Get the centroid of the input mesh
287 const auto input_centroid = MooseMeshUtils::meshCentroidCalculator(*input);
288 const Point axis_centroid_cross = (input_centroid - _axis_point).cross(_axis_direction);
289
290 if (MooseUtils::absoluteFuzzyEqual(axis_centroid_cross.norm(), 0.0))
291 mooseError("The input mesh is either across the axis or overlapped with the axis!");
292
293 Real inner_product_1d(0.0);
294 bool inner_product_1d_initialized(false);
295 // record ids of nodes on the axis
296 std::vector<dof_id_type> node_ids_on_axis;
297 for (const auto & node : input->node_ptr_range())
298 {
299 const Point axis_node_cross = (*node - _axis_point).cross(_axis_direction);
300 // if the cross product is zero, then the node is on the axis
301 if (!MooseUtils::absoluteFuzzyEqual(axis_node_cross.norm(), 0.0))
302 {
303 if (MooseUtils::absoluteFuzzyLessThan(axis_node_cross * axis_centroid_cross, 0.0))
304 mooseError("The input mesh is across the axis.");
305 else if (MooseUtils::absoluteFuzzyLessThan(axis_node_cross * axis_centroid_cross,
306 axis_centroid_cross.norm() *
307 axis_node_cross.norm()))
308 mooseError("The input mesh is not in the same plane with the rotation axis.");
309 }
310 else
311 node_ids_on_axis.push_back(node->id());
312
313 // Only for 1D input mesh, we need to check if the axis is perpendicular to the input mesh
314 if (input->mesh_dimension() == 1)
315 {
316 const Real temp_inner_product = (*node - _axis_point) * _axis_direction.unit();
317 if (inner_product_1d_initialized)
318 {
319 if (!MooseUtils::absoluteFuzzyEqual(temp_inner_product, inner_product_1d))
320 mooseError("The 1D input mesh is not perpendicular to the rotation axis.");
321 }
322 else
323 {
324 inner_product_1d_initialized = true;
325 inner_product_1d = temp_inner_product;
326 }
327 }
328 }
329
330 // If there are any on-axis nodes, we need to check if there are any QUAD8 elements with one
331 // vertex on the axis. If so, we need to replace it with a QUAD9 element.
332 if (!node_ids_on_axis.empty())
333 {
334 // Sort the vector for using set_intersection
335 std::sort(node_ids_on_axis.begin(), node_ids_on_axis.end());
336 // For QUAD8 elements with one vertex on the axis, we need to replace it with a QUAD9 element
337 std::set<subdomain_id_type> converted_quad8_subdomain_ids;
338 for (const auto & elem : input->element_ptr_range())
339 {
340 if (elem->type() == QUAD8)
341 {
342 std::vector<dof_id_type> elem_vertex_node_ids;
343 for (unsigned int i = 0; i < 4; i++)
344 {
345 elem_vertex_node_ids.push_back(elem->node_id(i));
346 }
347 std::sort(elem_vertex_node_ids.begin(), elem_vertex_node_ids.end());
348 std::vector<dof_id_type> common_node_ids;
349 std::set_intersection(node_ids_on_axis.begin(),
350 node_ids_on_axis.end(),
351 elem_vertex_node_ids.begin(),
352 elem_vertex_node_ids.end(),
353 std::back_inserter(common_node_ids));
354 // Temporarily shift the subdomain ID to mark the element
355 if (common_node_ids.size() == 1)
356 {
357 // we borrow quad_to_hi_pyramid_subdomain_id_shift here
358 elem->subdomain_id() += quad_to_hi_pyramid_subdomain_id_shift;
359 converted_quad8_subdomain_ids.emplace(elem->subdomain_id());
360 }
361 }
362 }
363 // Convert the recorded subdomains
364 input->all_second_order_range(
365 input->active_subdomain_set_elements_ptr_range(converted_quad8_subdomain_ids));
366 // Restore the subdomain ID; we do not worry about repeated subdomain IDs because those QUAD9
367 // will become PYRAMID and PRISM elements with new shifts
368 for (auto elem : input->active_subdomain_set_elements_ptr_range(converted_quad8_subdomain_ids))
369 elem->subdomain_id() -= quad_to_hi_pyramid_subdomain_id_shift;
370 }
371
372 // We should only record this info after QUAD8->QUAD9 conversion
373 dof_id_type orig_elem = input->n_elem();
374 dof_id_type orig_nodes = input->n_nodes();
375
376#ifdef LIBMESH_ENABLE_UNIQUE_ID
377 // Add the number of original elements as revolving may create two elements per layer for one
378 // original element
379 unique_id_type orig_unique_ids = input->parallel_max_unique_id() + orig_elem;
380#endif
381
382 // get rotation vectors
383 const auto rotation_vectors = rotationVectors(_axis_point, _axis_direction, input_centroid);
384
385 unsigned int order = 1;
386
387 BoundaryInfo & boundary_info = mesh->get_boundary_info();
388 const BoundaryInfo & input_boundary_info = input->get_boundary_info();
389
390 const unsigned int total_num_azimuthal_intervals =
391 std::accumulate(_nums_azimuthal_intervals.begin(), _nums_azimuthal_intervals.end(), 0);
392 // We know a priori how many elements we'll need
393 // In the worst case, all quad elements will become two elements per layer
394 mesh->reserve_elem(total_num_azimuthal_intervals * orig_elem * 2);
395 const dof_id_type elem_id_shift = total_num_azimuthal_intervals * orig_elem;
396
397 // Look for higher order elements which introduce an extra layer
398 std::set<ElemType> higher_orders = {EDGE3, TRI6, TRI7, QUAD8, QUAD9};
399 std::vector<ElemType> types;
400 MeshTools::elem_types(*input, types);
401 for (const auto elem_type : types)
402 if (higher_orders.count(elem_type))
403 order = 2;
404 mesh->comm().max(order);
405
406 // Collect azimuthal angles and use them to calculate the correction factor if applicable
407 std::vector<Real> azi_array;
408 for (const auto & i : index_range(_revolving_angles))
409 {
410 const Real section_start_angle =
411 azi_array.empty() ? 0.0 : (azi_array.back() + _unit_angles.back());
413 for (unsigned int j = 0; j < _nums_azimuthal_intervals[i] * order; j++)
414 azi_array.push_back(section_start_angle + _unit_angles.back() * (Real)j);
415 }
417 {
419 azi_array, _full_circle_revolving, order);
420
421 // In the meanwhile, modify the input mesh for radius correction if applicable
422 for (const auto & node : input->node_ptr_range())
423 nodeModification(*node);
424 }
425
427 (order * total_num_azimuthal_intervals + 1 - (unsigned int)_full_circle_revolving) *
428 orig_nodes);
429
430 // Container to catch the boundary IDs handed back by the BoundaryInfo object
431 std::vector<boundary_id_type> ids_to_copy;
432
433 Point old_distance;
434 Point current_distance;
435 if (!_clockwise)
436 std::transform(_unit_angles.begin(),
437 _unit_angles.end(),
438 _unit_angles.begin(),
439 [](auto & c) { return c * (-1.0) * M_PI / 180.0; });
440 else
441 std::transform(_unit_angles.begin(),
442 _unit_angles.end(),
443 _unit_angles.begin(),
444 [](auto & c) { return c * M_PI / 180.0; });
445 std::vector<dof_id_type> nodes_on_axis;
446
447 for (const auto & node : input->node_ptr_range())
448 {
449 // Calculate the radius and corresponding center point on the rotation axis
450 // If the radius is 0, then the node is on the axis
451 const auto radius_and_center = getRotationCenterAndRadius(*node, _axis_point, _axis_direction);
452 const bool isOnAxis = MooseUtils::absoluteFuzzyEqual(radius_and_center.first, 0.0);
453 if (isOnAxis)
454 {
455 nodes_on_axis.push_back(node->id());
456 }
457
458 unsigned int current_node_layer = 0;
459
460 old_distance.zero();
461
462 const unsigned int num_rotations = _revolving_angles.size();
463 for (unsigned int e = 0; e < num_rotations; e++)
464 {
465 auto num_layers = _nums_azimuthal_intervals[e];
466
467 auto angle = _unit_angles[e];
468
469 const auto base_angle =
470 std::accumulate(_revolving_angles.begin(), _revolving_angles.begin() + e, 0.0) / 180.0 *
471 M_PI;
472
473 for (unsigned int k = 0;
474 k < order * num_layers + (e == 0 ? 1 : 0) -
475 (e == num_rotations - 1 ? (unsigned int)_full_circle_revolving : 0);
476 ++k)
477 {
478 bool is_node_created(false);
479 if (!isOnAxis)
480 {
481 // For the first layer we don't need to move
482 if (e == 0 && k == 0)
483 current_distance.zero();
484 else
485 {
486 auto layer_index = (k - (e == 0 ? 1 : 0)) + 1;
487
488 // Calculate the rotation angle in XY Plane
489 const Point vector_xy =
490 Point(-2.0 * radius_and_center.first *
491 std::sin((base_angle + angle * (Real)layer_index) / 2.0) *
492 std::sin((base_angle + angle * (Real)layer_index) / 2.0),
493 2.0 * radius_and_center.first *
494 std::sin((base_angle + angle * (Real)layer_index) / 2.0) *
495 std::cos((base_angle + angle * (Real)layer_index) / 2.0),
496 0.0);
497 current_distance = Point(rotation_vectors[0] * vector_xy,
498 rotation_vectors[1] * vector_xy,
499 rotation_vectors[2] * vector_xy);
500 }
501
502 is_node_created = true;
503 }
504 else if (e == 0 && k == 0)
505 {
506 // On-axis nodes are only added once
507 current_distance.zero();
508 is_node_created = true;
509 }
510
511 if (is_node_created)
512 {
513 Node * new_node = mesh->add_point(*node + current_distance,
514 node->id() + (current_node_layer * orig_nodes),
515 node->processor_id());
516#ifdef LIBMESH_ENABLE_UNIQUE_ID
517 // Let's give the base nodes of the revolved mesh the same
518 // unique_ids as the source mesh, in case anyone finds that
519 // a useful map to preserve.
520 const unique_id_type uid =
521 (current_node_layer == 0)
522 ? node->unique_id()
523 : (orig_unique_ids + (current_node_layer - 1) * (orig_nodes + orig_elem * 2) +
524 node->id());
525 new_node->set_unique_id(uid);
526#endif
527
528 input_boundary_info.boundary_ids(node, ids_to_copy);
529 if (_boundary_swap_pairs.empty())
530 boundary_info.add_node(new_node, ids_to_copy);
531 else
532 for (const auto & id_to_copy : ids_to_copy)
533 boundary_info.add_node(new_node,
534 _boundary_swap_pairs[e].count(id_to_copy)
535 ? _boundary_swap_pairs[e][id_to_copy]
536 : id_to_copy);
537 }
538
539 current_node_layer++;
540 }
541 }
542 }
543
544 for (const auto & elem : input->element_ptr_range())
545 {
546 const ElemType etype = elem->type();
547
548 // revolving currently only works on coarse meshes
549 mooseAssert(!elem->parent(), "RevolveGenerator only works on coarse meshes.");
550
551 unsigned int current_layer = 0;
552
553 const unsigned int num_rotations = _revolving_angles.size();
554
555 for (unsigned int e = 0; e < num_rotations; e++)
556 {
557 auto num_layers = _nums_azimuthal_intervals[e];
558
559 for (unsigned int k = 0; k < num_layers; ++k)
560 {
561 std::unique_ptr<Elem> new_elem;
562 std::unique_ptr<Elem> new_elem_1;
563 bool is_flipped(false);
564 // In some cases, two elements per layer are generated by revolving one element. So we
565 // reserve an additional flag for the potential second element.
566 bool is_flipped_additional(false);
567 dof_id_type axis_node_case(-1);
568 std::vector<std::pair<dof_id_type, dof_id_type>> side_pairs;
569 switch (etype)
570 {
571 case EDGE2:
572 {
573 // Possible scenarios:
574 // 1. None of the nodes are on the axis
575 // Then a quad4 element is created
576 // 2. One of the nodes is on the axis
577 // Then a tri3 element is created
578 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
579 if (nodes_cates.first.empty())
580 {
582 elem,
583 mesh,
584 new_elem,
585 current_layer,
586 orig_nodes,
587 total_num_azimuthal_intervals,
588 side_pairs,
589 is_flipped);
590 }
591 else
592 {
593 createTRIfromEDGE(nodes_cates,
594 TRI3,
595 elem,
596 mesh,
597 new_elem,
598 current_layer,
599 orig_nodes,
600 total_num_azimuthal_intervals,
601 side_pairs,
602 axis_node_case,
603 is_flipped);
604 }
605 break;
606 }
607 case EDGE3:
608 {
609 // Possible scenarios:
610 // 1. None of the nodes are on the axis
611 // Then a QUAD9 element is created
612 // 2. One of the nodes is on the axis
613 // Then a TRI7 element is created
614 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
615 if (nodes_cates.first.empty())
616 {
618 elem,
619 mesh,
620 new_elem,
621 current_layer,
622 orig_nodes,
623 total_num_azimuthal_intervals,
624 side_pairs,
625 is_flipped);
626 }
627 else
628 {
629 createTRIfromEDGE(nodes_cates,
630 TRI7,
631 elem,
632 mesh,
633 new_elem,
634 current_layer,
635 orig_nodes,
636 total_num_azimuthal_intervals,
637 side_pairs,
638 axis_node_case,
639 is_flipped);
640 }
641 break;
642 }
643 case TRI3:
644 {
645 // Possible scenarios:
646 // 1. None of the nodes are on the axis
647 // Then a prism6 element is created
648 // 2. One of the nodes is on the axis
649 // Then a pyramid5 element is created
650 // 3. Two of the nodes are on the axis
651 // Then a tet4 element is created
652 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
653 if (nodes_cates.first.empty())
654 {
656 elem,
657 mesh,
658 new_elem,
659 current_layer,
660 orig_nodes,
661 total_num_azimuthal_intervals,
662 side_pairs,
663 is_flipped);
664 }
665 else if (nodes_cates.first.size() == 1)
666 {
667 createPYRAMIDfromTRI(nodes_cates,
668 PYRAMID5,
669 elem,
670 mesh,
671 new_elem,
672 current_layer,
673 orig_nodes,
674 total_num_azimuthal_intervals,
675 side_pairs,
676 axis_node_case,
677 is_flipped);
678 }
679 else if (nodes_cates.first.size() == 2)
680 {
681 createTETfromTRI(nodes_cates,
682 TET4,
683 elem,
684 mesh,
685 new_elem,
686 current_layer,
687 orig_nodes,
688 total_num_azimuthal_intervals,
689 side_pairs,
690 axis_node_case,
691 is_flipped);
692 }
693 else
694 mooseError("A degenerate TRI3 elements overlapped with the rotation axis cannot be "
695 "revolved.");
696
697 break;
698 }
699 case TRI6:
700 {
701 // Possible scenarios:
702 // 1. None of the nodes are on the axis
703 // Then a prism18 element is created
704 // 2. One of the nodes is on the axis
705 // Then a pyramid13 element is created
706 // 3. Three of the nodes are on the axis
707 // Then a tet10 element is created
708 // NOTE: We do not support two nodes on the axis for tri6 elements
709 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
710 if (nodes_cates.first.empty())
711 {
713 elem,
714 mesh,
715 new_elem,
716 current_layer,
717 orig_nodes,
718 total_num_azimuthal_intervals,
719 side_pairs,
720 is_flipped);
721 }
722 else if (nodes_cates.first.size() == 1)
723 {
724 createPYRAMIDfromTRI(nodes_cates,
725 PYRAMID13,
726 elem,
727 mesh,
728 new_elem,
729 current_layer,
730 orig_nodes,
731 total_num_azimuthal_intervals,
732 side_pairs,
733 axis_node_case,
734 is_flipped);
735 }
736 else if (nodes_cates.first.size() == 3)
737 {
738 createTETfromTRI(nodes_cates,
739 TET10,
740 elem,
741 mesh,
742 new_elem,
743 current_layer,
744 orig_nodes,
745 total_num_azimuthal_intervals,
746 side_pairs,
747 axis_node_case,
748 is_flipped);
749 }
750 else
752 "You either have a degenerate TRI6 element, or the mid-point of the "
753 "on-axis edge is not colinear with the two vertices, which is not supported.");
754 break;
755 }
756 case TRI7:
757 {
758 // Possible scenarios:
759 // 1. None of the nodes are on the axis
760 // Then a prism21 element is created
761 // 2. One of the nodes is on the axis
762 // Then a pyramid18 element is created
763 // 3. Three of the nodes are on the axis
764 // Then a tet14 element is created
765 // NOTE: We do not support two nodes on the axis for tri7 elements
766 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
767 if (nodes_cates.first.empty())
768 {
770 elem,
771 mesh,
772 new_elem,
773 current_layer,
774 orig_nodes,
775 total_num_azimuthal_intervals,
776 side_pairs,
777 is_flipped);
778 }
779 else if (nodes_cates.first.size() == 1)
780 {
781 createPYRAMIDfromTRI(nodes_cates,
782 PYRAMID18,
783 elem,
784 mesh,
785 new_elem,
786 current_layer,
787 orig_nodes,
788 total_num_azimuthal_intervals,
789 side_pairs,
790 axis_node_case,
791 is_flipped);
792 }
793 else if (nodes_cates.first.size() == 3)
794 {
795 createTETfromTRI(nodes_cates,
796 TET14,
797 elem,
798 mesh,
799 new_elem,
800 current_layer,
801 orig_nodes,
802 total_num_azimuthal_intervals,
803 side_pairs,
804 axis_node_case,
805 is_flipped);
806 }
807 else
808 mooseError("You either have a degenerate TRI6 element, or the mid-point of the "
809 "on-axis edge of the TRI6 element is not colinear with the two vertices, "
810 "which is not supported.");
811 break;
812 }
813 case QUAD4:
814 {
815 // Possible scenarios:
816 // 1. None of the nodes are on the axis
817 // Then a hex8 element is created
818 // 2. One of the nodes is on the axis
819 // Then a pyramid5 element and a prism6 element are created
820 // 3. Two of the nodes are on the axis
821 // Then a prism6 is created
822 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
823 if (nodes_cates.first.empty())
824 {
826 elem,
827 mesh,
828 new_elem,
829 current_layer,
830 orig_nodes,
831 total_num_azimuthal_intervals,
832 side_pairs,
833 is_flipped);
834 }
835 else if (nodes_cates.first.size() == 1)
836 {
837 createPYRAMIDPRISMfromQUAD(nodes_cates,
838 PYRAMID5,
839 PRISM6,
840 elem,
841 mesh,
842 new_elem,
843 new_elem_1,
844 current_layer,
845 orig_nodes,
846 total_num_azimuthal_intervals,
847 side_pairs,
848 axis_node_case,
849 is_flipped,
850 is_flipped_additional);
851 }
852 else if (nodes_cates.first.size() == 2)
853 {
854 createPRISMfromQUAD(nodes_cates,
855 PRISM6,
856 elem,
857 mesh,
858 new_elem,
859 current_layer,
860 orig_nodes,
861 total_num_azimuthal_intervals,
862 side_pairs,
863 axis_node_case,
864 is_flipped);
865 }
866
867 else
868 mooseError("Degenerate QUAD4 element with 3 or more aligned nodes cannot be "
869 "azimuthally revolved");
870
871 break;
872 }
873 case QUAD8:
874 {
875 // Possible scenarios:
876 // 1. None of the nodes are on the axis
877 // Then a hex20 element is created
878 // 2. One of the nodes is on the axis
879 // In that case, it is already converted to a QUAD9 element before,
880 // SO we do not need to worry about this case
881 // 3. Three of the nodes are on the axis
882 // Then a prism15 is created
883 // NOTE: We do not support two nodes on the axis for quad8 elements
884 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
885 if (nodes_cates.first.empty())
886 {
888 elem,
889 mesh,
890 new_elem,
891 current_layer,
892 orig_nodes,
893 total_num_azimuthal_intervals,
894 side_pairs,
895 is_flipped);
896 }
897 else if (nodes_cates.first.size() == 3)
898 {
899 createPRISMfromQUAD(nodes_cates,
900 PRISM15,
901 elem,
902 mesh,
903 new_elem,
904 current_layer,
905 orig_nodes,
906 total_num_azimuthal_intervals,
907 side_pairs,
908 axis_node_case,
909 is_flipped);
910 }
911 else
912 mooseError("You either have a degenerate QUAD8 element, or the mid-point of the "
913 "on-axis edge of the QUAD8 element is not colinear with the two vertices, "
914 "which is not supported.");
915
916 break;
917 }
918 case QUAD9:
919 {
920 // Possible scenarios:
921 // 1. None of the nodes are on the axis
922 // Then a hex27 element is created
923 // 2. One of the nodes is on the axis
924 // Then a pyramid14 element and a prism18 element are created
925 // 3. Two of the nodes are on the axis
926 // Then a prism18 is created
927 // (we do not create prism20/21 here just to make prism18 the only possible prism
928 // elements for simplicity)
929 const auto nodes_cates = onAxisNodesIdentifier(*elem, nodes_on_axis);
930 if (nodes_cates.first.empty())
931 {
933 elem,
934 mesh,
935 new_elem,
936 current_layer,
937 orig_nodes,
938 total_num_azimuthal_intervals,
939 side_pairs,
940 is_flipped);
941 }
942 else if (nodes_cates.first.size() == 1)
943 {
944 createPYRAMIDPRISMfromQUAD(nodes_cates,
945 PYRAMID14,
946 PRISM18,
947 elem,
948 mesh,
949 new_elem,
950 new_elem_1,
951 current_layer,
952 orig_nodes,
953 total_num_azimuthal_intervals,
954 side_pairs,
955 axis_node_case,
956 is_flipped,
957 is_flipped_additional);
958 }
959 else if (nodes_cates.first.size() == 3)
960 {
961 createPRISMfromQUAD(nodes_cates,
962 PRISM18,
963 elem,
964 mesh,
965 new_elem,
966 current_layer,
967 orig_nodes,
968 total_num_azimuthal_intervals,
969 side_pairs,
970 axis_node_case,
971 is_flipped);
972 }
973 else
974 mooseError("You either have a degenerate QUAD9 element, or the mid-point of the "
975 "on-axis edge of the QUAD9 element is not colinear with the two vertices, "
976 "which is not supported.");
977 break;
978 }
979 default:
980 mooseError("The input mesh contains unsupported element type(s).");
981 }
982 new_elem->set_id(elem->id() + (current_layer * orig_elem));
983 new_elem->processor_id() = elem->processor_id();
984 if (new_elem_1)
985 {
986 new_elem_1->set_id(elem->id() + (current_layer * orig_elem) + elem_id_shift);
987 new_elem_1->processor_id() = elem->processor_id();
988 }
989
990#ifdef LIBMESH_ENABLE_UNIQUE_ID
991 // Let's give the base elements of the revolved mesh the same
992 // unique_ids as the source mesh, in case anyone finds that
993 // a useful map to preserve.
994 const unique_id_type uid =
995 (current_layer == 0)
996 ? elem->unique_id()
997 : (orig_unique_ids + (current_layer - 1) * (orig_nodes + orig_elem * 2) +
998 orig_nodes + elem->id());
999
1000 new_elem->set_unique_id(uid);
1001
1002 // Special case for extra elements
1003 if (new_elem_1)
1004 {
1005 const unique_id_type uid_1 =
1006 (current_layer == 0)
1007 ? (elem->id() + orig_unique_ids - orig_elem)
1008 : (orig_unique_ids + (current_layer - 1) * (orig_nodes + orig_elem * 2) +
1009 orig_nodes + orig_elem + elem->id());
1010
1011 new_elem_1->set_unique_id(uid_1);
1012 }
1013#endif
1014
1015 // maintain the subdomain_id
1016 switch (etype)
1017 {
1018 case EDGE2:
1019 switch (new_elem->type())
1020 {
1021 case QUAD4:
1022 new_elem->subdomain_id() = elem->subdomain_id();
1023 break;
1024 case TRI3:
1025 new_elem->subdomain_id() = edge_to_tri_subdomain_id_shift + elem->subdomain_id();
1026 break;
1027 default:
1028 mooseAssert(false,
1029 "impossible element type generated by revolving an EDGE2 element");
1030 }
1031 break;
1032 case EDGE3:
1033 switch (new_elem->type())
1034 {
1035 case QUAD9:
1036 new_elem->subdomain_id() = elem->subdomain_id();
1037 break;
1038 case TRI7:
1039 new_elem->subdomain_id() = edge_to_tri_subdomain_id_shift + elem->subdomain_id();
1040 break;
1041 default:
1042 mooseAssert(false,
1043 "impossible element type generated by revolving an EDGE3 element");
1044 }
1045 break;
1046 case TRI3:
1047 switch (new_elem->type())
1048 {
1049 case PRISM6:
1050 new_elem->subdomain_id() = elem->subdomain_id();
1051 break;
1052 case PYRAMID5:
1053 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1054 break;
1055 case TET4:
1056 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1057 break;
1058 default:
1059 mooseAssert(false, "impossible element type generated by revolving a TRI3 element");
1060 }
1061 break;
1062 case TRI6:
1063 switch (new_elem->type())
1064 {
1065 case PRISM18:
1066 new_elem->subdomain_id() = elem->subdomain_id();
1067 break;
1068 case PYRAMID13:
1069 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1070 break;
1071 case TET10:
1072 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1073 break;
1074 default:
1075 mooseAssert(false, "impossible element type generated by revolving a TRI6 element");
1076 }
1077 break;
1078 case TRI7:
1079 switch (new_elem->type())
1080 {
1081 case PRISM21:
1082 new_elem->subdomain_id() = elem->subdomain_id();
1083 break;
1084 case PYRAMID18:
1085 new_elem->subdomain_id() = tri_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1086 break;
1087 case TET14:
1088 new_elem->subdomain_id() = tri_to_tet_subdomain_id_shift + elem->subdomain_id();
1089 break;
1090 default:
1091 mooseAssert(false, "impossible element type generated by revolving a TRI7 element");
1092 }
1093 break;
1094 case QUAD4:
1095 switch (new_elem->type())
1096 {
1097 case HEX8:
1098 new_elem->subdomain_id() = elem->subdomain_id();
1099 break;
1100 case PRISM6:
1101 new_elem->subdomain_id() = quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1102 break;
1103 case PYRAMID5:
1104 new_elem->subdomain_id() =
1105 quad_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1106 new_elem_1->subdomain_id() =
1107 quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1108 break;
1109 default:
1110 mooseAssert(false,
1111 "impossible element type generated by revolving a QUAD4 element");
1112 }
1113 break;
1114 case QUAD8:
1115 switch (new_elem->type())
1116 {
1117 case HEX20:
1118 new_elem->subdomain_id() = elem->subdomain_id();
1119 break;
1120 case PRISM15:
1121 new_elem->subdomain_id() = quad_to_prism_subdomain_id_shift + elem->subdomain_id();
1122 break;
1123 default:
1124 mooseAssert(false,
1125 "impossible element type generated by revolving a QUAD8 element");
1126 }
1127 break;
1128 case QUAD9:
1129 switch (new_elem->type())
1130 {
1131 case HEX27:
1132 new_elem->subdomain_id() = elem->subdomain_id();
1133 break;
1134 case PRISM18:
1135 new_elem->subdomain_id() =
1136 quad_to_hi_pyramid_subdomain_id_shift + elem->subdomain_id();
1137 break;
1138 case PYRAMID14:
1139 new_elem->subdomain_id() =
1140 quad_to_pyramid_subdomain_id_shift + elem->subdomain_id();
1141 new_elem_1->subdomain_id() =
1142 quad_to_hi_pyramid_subdomain_id_shift + elem->subdomain_id();
1143 break;
1144 default:
1145 mooseAssert(false,
1146 "impossible element type generated by revolving a QUAD9 element");
1147 }
1148 break;
1149 default:
1150 mooseAssert(false,
1151 "The input mesh contains unsupported element type(s), which should have "
1152 "been checked in prior steps in this code.");
1153 }
1154
1155 if (_subdomain_swap_pairs.size())
1156 {
1157 auto & revolving_swap_pairs = _subdomain_swap_pairs[e];
1158
1159 auto new_id_it = revolving_swap_pairs.find(elem->subdomain_id());
1160
1161 if (new_id_it != revolving_swap_pairs.end())
1162 {
1163 new_elem->subdomain_id() =
1164 new_elem->subdomain_id() - elem->subdomain_id() + new_id_it->second;
1165 if (new_elem_1)
1166 new_elem_1->subdomain_id() =
1167 new_elem_1->subdomain_id() - elem->subdomain_id() + new_id_it->second;
1168 }
1169 }
1170
1171 Elem * added_elem = mesh->add_elem(std::move(new_elem));
1172 Elem * added_elem_1 = NULL;
1173
1174 if (new_elem_1)
1175 added_elem_1 = mesh->add_elem(std::move(new_elem_1));
1176
1177 // maintain extra integers
1178 for (unsigned int i = 0; i < num_extra_elem_integers; i++)
1179 {
1180 added_elem->set_extra_integer(i, elem->get_extra_integer(i));
1181 if (added_elem_1)
1182 added_elem_1->set_extra_integer(i, elem->get_extra_integer(i));
1183 }
1184
1185 if (_elem_integers_swap_pairs.size())
1186 {
1187 for (unsigned int i = 0; i < _elem_integer_indices_to_swap.size(); i++)
1188 {
1189 auto & elevation_extra_swap_pairs =
1191
1192 auto new_extra_id_it = elevation_extra_swap_pairs.find(
1193 elem->get_extra_integer(_elem_integer_indices_to_swap[i]));
1194
1195 if (new_extra_id_it != elevation_extra_swap_pairs.end())
1196 {
1198 new_extra_id_it->second);
1199 if (added_elem_1)
1201 new_extra_id_it->second);
1202 }
1203 }
1204 }
1205
1206 // Copy any old boundary ids on all sides
1207 for (auto s : elem->side_index_range())
1208 {
1209 input_boundary_info.boundary_ids(elem, s, ids_to_copy);
1210 std::vector<boundary_id_type> ids_to_copy_swapped;
1211 if (_boundary_swap_pairs.empty())
1212 ids_to_copy_swapped = ids_to_copy;
1213 else
1214 for (const auto & id_to_copy : ids_to_copy)
1215 ids_to_copy_swapped.push_back(_boundary_swap_pairs[e].count(id_to_copy)
1216 ? _boundary_swap_pairs[e][id_to_copy]
1217 : id_to_copy);
1218
1219 switch (etype)
1220 {
1221 case EDGE2:
1222 switch (added_elem->type())
1223 {
1224 case QUAD4:
1225 boundary_info.add_side(
1226 added_elem, cast_int<unsigned short>(s == 0 ? 3 : 1), ids_to_copy_swapped);
1227 break;
1228 case TRI3:
1229 if (s != axis_node_case)
1230 boundary_info.add_side(
1231 added_elem, cast_int<unsigned short>(s), ids_to_copy_swapped);
1232 break;
1233 default:
1234 mooseAssert(false,
1235 "impossible element type generated by revolving an EDGE2 element");
1236 }
1237 break;
1238 case EDGE3:
1239 switch (added_elem->type())
1240 {
1241 case QUAD9:
1242 boundary_info.add_side(
1243 added_elem, cast_int<unsigned short>(s == 0 ? 3 : 1), ids_to_copy_swapped);
1244 break;
1245 case TRI7:
1246 if (s != axis_node_case)
1247 boundary_info.add_side(
1248 added_elem, cast_int<unsigned short>(s), ids_to_copy_swapped);
1249 break;
1250 default:
1251 mooseAssert(false,
1252 "impossible element type generated by revolving an EDGE3 element");
1253 }
1254 break;
1255 case TRI3:
1256 switch (added_elem->type())
1257 {
1258 case PRISM6:
1259 boundary_info.add_side(
1260 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1261 break;
1262 case PYRAMID5:
1263 if ((s + 3 - axis_node_case) % 3 == 0)
1264 boundary_info.add_side(
1265 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1266 else if ((s + 3 - axis_node_case) % 3 == 1)
1267 boundary_info.add_side(
1268 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1269 else
1270 boundary_info.add_side(
1271 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1272 break;
1273 case TET4:
1274 if ((s + 3 - axis_node_case) % 3 == 0)
1275 boundary_info.add_side(
1276 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1277 else if ((s + 3 - axis_node_case) % 3 == 2)
1278 boundary_info.add_side(
1279 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1280 break;
1281 default:
1282 mooseAssert(false,
1283 "impossible element type generated by revolving a TRI3 element");
1284 }
1285 break;
1286 case TRI6:
1287 switch (added_elem->type())
1288 {
1289 case PRISM18:
1290 boundary_info.add_side(
1291 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1292 break;
1293 case PYRAMID13:
1294 if ((s + 3 - axis_node_case) % 3 == 0)
1295 boundary_info.add_side(
1296 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1297 else if ((s + 3 - axis_node_case) % 3 == 1)
1298 boundary_info.add_side(
1299 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1300 else
1301 boundary_info.add_side(
1302 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1303 break;
1304 case TET10:
1305 if ((s + 3 - axis_node_case) % 3 == 0)
1306 boundary_info.add_side(
1307 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1308 else if ((s + 3 - axis_node_case) % 3 == 2)
1309 boundary_info.add_side(
1310 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1311 break;
1312 default:
1313 mooseAssert(false,
1314 "impossible element type generated by revolving a TRI6 element");
1315 }
1316 break;
1317 case TRI7:
1318 switch (added_elem->type())
1319 {
1320 case PRISM21:
1321 boundary_info.add_side(
1322 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1323 break;
1324 case PYRAMID18:
1325 if ((s + 3 - axis_node_case) % 3 == 0)
1326 boundary_info.add_side(
1327 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1328 else if ((s + 3 - axis_node_case) % 3 == 1)
1329 boundary_info.add_side(
1330 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1331 else
1332 boundary_info.add_side(
1333 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1334 break;
1335 case TET14:
1336 if ((s + 3 - axis_node_case) % 3 == 0)
1337 boundary_info.add_side(
1338 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1339 else if ((s + 3 - axis_node_case) % 3 == 2)
1340 boundary_info.add_side(
1341 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1342 break;
1343 default:
1344 mooseAssert(false,
1345 "impossible element type generated by revolving a TRI7 element");
1346 }
1347 break;
1348 case QUAD4:
1349 switch (added_elem->type())
1350 {
1351 case HEX8:
1352 boundary_info.add_side(
1353 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1354 break;
1355 case PRISM6:
1356 if ((s + 4 - axis_node_case) % 4 == 1)
1357 boundary_info.add_side(
1358 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1359 else if ((s + 4 - axis_node_case) % 4 == 2)
1360 boundary_info.add_side(
1361 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1362 else if ((s + 4 - axis_node_case) % 4 == 3)
1363 boundary_info.add_side(
1364 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1365 break;
1366 case PYRAMID5:
1367 if ((s + 4 - axis_node_case) % 4 == 3)
1368 boundary_info.add_side(
1369 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1370 else if ((s + 4 - axis_node_case) % 4 == 0)
1371 boundary_info.add_side(
1372 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1373 else if ((s + 4 - axis_node_case) % 4 == 1)
1374 boundary_info.add_side(
1375 added_elem_1, cast_int<unsigned short>(3), ids_to_copy_swapped);
1376 else
1377 boundary_info.add_side(
1378 added_elem_1, cast_int<unsigned short>(2), ids_to_copy_swapped);
1379 break;
1380 default:
1381 mooseAssert(false,
1382 "impossible element type generated by revolving a QUAD4 element");
1383 }
1384 break;
1385 case QUAD8:
1386 switch (added_elem->type())
1387 {
1388 case HEX20:
1389 boundary_info.add_side(
1390 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1391 break;
1392 case PRISM15:
1393 if ((s + 4 - axis_node_case) % 4 == 1)
1394 boundary_info.add_side(
1395 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1396 else if ((s + 4 - axis_node_case) % 4 == 2)
1397 boundary_info.add_side(
1398 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1399 else if ((s + 4 - axis_node_case) % 4 == 3)
1400 boundary_info.add_side(
1401 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1402 break;
1403 default:
1404 mooseAssert(false,
1405 "impossible element type generated by revolving a QUAD8 element");
1406 }
1407 break;
1408 case QUAD9:
1409 switch (added_elem->type())
1410 {
1411 case HEX27:
1412 boundary_info.add_side(
1413 added_elem, cast_int<unsigned short>(s + 1), ids_to_copy_swapped);
1414 break;
1415 case PRISM18:
1416 if ((s + 4 - axis_node_case) % 4 == 1)
1417 boundary_info.add_side(
1418 added_elem, cast_int<unsigned short>(4), ids_to_copy_swapped);
1419 else if ((s + 4 - axis_node_case) % 4 == 2)
1420 boundary_info.add_side(
1421 added_elem, cast_int<unsigned short>(2), ids_to_copy_swapped);
1422 else if ((s + 4 - axis_node_case) % 4 == 3)
1423 boundary_info.add_side(
1424 added_elem, cast_int<unsigned short>(0), ids_to_copy_swapped);
1425 break;
1426 case PYRAMID14:
1427 if ((s + 4 - axis_node_case) % 4 == 3)
1428 boundary_info.add_side(
1429 added_elem, cast_int<unsigned short>(1), ids_to_copy_swapped);
1430 else if ((s + 4 - axis_node_case) % 4 == 0)
1431 boundary_info.add_side(
1432 added_elem, cast_int<unsigned short>(3), ids_to_copy_swapped);
1433 else if ((s + 4 - axis_node_case) % 4 == 1)
1434 boundary_info.add_side(
1435 added_elem_1, cast_int<unsigned short>(3), ids_to_copy_swapped);
1436 else
1437 boundary_info.add_side(
1438 added_elem_1, cast_int<unsigned short>(2), ids_to_copy_swapped);
1439 break;
1440 default:
1441 mooseAssert(false,
1442 "impossible element type generated by revolving a QUAD9 element");
1443 }
1444 break;
1445 default:
1446 mooseAssert(false,
1447 "The input mesh contains unsupported element type(s), which should have "
1448 "been checked in prior steps in this code.");
1449 }
1450 }
1451
1452 if (current_layer == 0 && _has_start_boundary)
1453 {
1454 boundary_info.add_side(
1455 added_elem, is_flipped ? side_pairs[0].second : side_pairs[0].first, _start_boundary);
1456 if (side_pairs.size() > 1)
1457 boundary_info.add_side(added_elem_1,
1458 is_flipped_additional ? side_pairs[1].second
1459 : side_pairs[1].first,
1461 }
1462
1463 if (current_layer == num_layers - 1 && _has_end_boundary)
1464 {
1465 boundary_info.add_side(
1466 added_elem, is_flipped ? side_pairs[0].first : side_pairs[0].second, _end_boundary);
1467 if (side_pairs.size() > 1)
1468 boundary_info.add_side(added_elem_1,
1469 is_flipped_additional ? side_pairs[1].first
1470 : side_pairs[1].second,
1472 }
1473 current_layer++;
1474 }
1475 }
1476 }
1477
1478#ifdef LIBMESH_ENABLE_UNIQUE_ID
1479 // Update the value of next_unique_id based on newly created nodes and elements
1480 // Note: the calculation here is quite conservative to ensure uniqueness
1481 unsigned int total_new_node_layers = total_num_azimuthal_intervals * order;
1482 unsigned int new_unique_ids = orig_unique_ids + (total_new_node_layers - 1) * orig_elem * 2 +
1483 total_new_node_layers * orig_nodes;
1484 mesh->set_next_unique_id(new_unique_ids);
1485#endif
1486
1487 // Copy all the subdomain/sideset/nodeset name maps to the revolved mesh
1488 if (!input_subdomain_map.empty())
1489 mesh->set_subdomain_name_map().insert(input_subdomain_map.begin(), input_subdomain_map.end());
1490 if (!input_sideset_map.empty())
1491 mesh->get_boundary_info().set_sideset_name_map().insert(input_sideset_map.begin(),
1492 input_sideset_map.end());
1493 if (!input_nodeset_map.empty())
1494 mesh->get_boundary_info().set_nodeset_name_map().insert(input_nodeset_map.begin(),
1495 input_nodeset_map.end());
1496
1500
1501 return mesh;
1502}
unsigned int count
for(PetscInt i=0;i< nvars;++i)
char ** blocks
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
void nodeModification(Node &node)
Modify the position of a node to account for radius correction.
std::vector< unsigned int > _elem_integer_indices_to_swap
void createPRISMfromTRI(const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
Create a new PRISM element from an existing TRI element by revolving it.
void createTRIfromEDGE(const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType tri_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
Create a new TRI element from an existing EDGE element by revolving it.
std::vector< Point > rotationVectors(const Point &p_axis, const Point &dir_axis, const Point &p_input) const
Calculate the transform matrix between the rotation coordinate system and the original coordinate sys...
std::pair< Real, Point > getRotationCenterAndRadius(const Point &p_ext, const Point &p_axis, const Point &dir_axis) const
Get the rotation center and radius of the circular rotation based on the rotation axis and the extern...
std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > onAxisNodesIdentifier(const Elem &elem, const std::vector< dof_id_type > &nodes_on_axis) const
Categorize the nodes of an element into two groups: nodes on the axis and nodes off the axis.
void createPYRAMIDfromTRI(const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType pyramid_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
Create a new PYRAMID element from an existing TRI element by revolving it.
void createQUADfromEDGE(const ElemType quad_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
Create a new QUAD element from an existing EDGE element by revolving it.
void createHEXfromQUAD(const ElemType hex_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, bool &is_flipped) const
Create a new HEX element from an existing QUAD element by revolving it.
void createPRISMfromQUAD(const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
Create a new PRISM element from an existing QUAD element by revolving it.
std::vector< Real > _unit_angles
Unit angles of all azimuthal sections of revolution.
void createTETfromTRI(const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType tet_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped) const
Create a new TET element from an existing TRI element by revolving it.
void createPYRAMIDPRISMfromQUAD(const std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > &nodes_cates, const ElemType pyramid_elem_type, const ElemType prism_elem_type, const Elem *elem, const std::unique_ptr< MeshBase > &mesh, std::unique_ptr< Elem > &new_elem, std::unique_ptr< Elem > &new_elem_1, const int current_layer, const unsigned int orig_nodes, const unsigned int total_num_azimuthal_intervals, std::vector< std::pair< dof_id_type, dof_id_type > > &side_pairs, dof_id_type &axis_node_case, bool &is_flipped, bool &is_flipped_additional) const
Create a new PYRAMID element and a new PRISM element from an existing QUAD element by revolving it.
void max(const T &r, T &o, Request &req) const
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
std::map< boundary_id_type, std::string > & set_sideset_name_map()
void add_node(const Node *node, const boundary_id_type id)
std::map< boundary_id_type, std::string > & set_nodeset_name_map()
unique_id_type unique_id() const
void set_unique_id(unique_id_type new_id)
void set_extra_integer(const unsigned int index, const dof_id_type value)
virtual ElemType type() const=0
virtual void renumber_nodes_and_elements()=0
void set_mesh_dimension(unsigned char d)
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
virtual void set_next_unique_id(unique_id_type id)=0
bool has_elem_integer(std::string_view name) const
virtual void delete_remote_elements()
virtual void reserve_elem(const dof_id_type ne)=0
std::map< subdomain_id_type, std::string > & set_subdomain_name_map()
virtual void reserve_nodes(const dof_id_type nn)=0
void unset_is_prepared()
const Parallel::Communicator & comm() const
auto norm() const
TypeVector< Real > unit() const
Real radiusCorrectionFactor(const std::vector< Real > &azimuthal_list, const bool full_circle=true, const unsigned int order=1, const bool is_first_value_vertex=true)
Makes radial correction to preserve ring area.
void elem_types(const MeshBase &mesh, std::vector< ElemType > &et)
uint8_t unique_id_type
auto index_range(const T &sizable)
void libmesh_ignore(const Args &...)
IntRange< T > make_range(T beg, T end)

◆ getInterfaceBoundaryIDs()

std::set< boundary_id_type > PolygonMeshGeneratorBase::getInterfaceBoundaryIDs ( const std::vector< std::vector< unsigned int > > &  pattern,
const std::vector< std::vector< boundary_id_type > > &  interface_boundary_id_shift_pattern,
const std::set< boundary_id_type > &  boundary_ids,
const std::vector< std::set< boundary_id_type > > &  input_interface_boundary_ids,
const bool  use_interface_boundary_id_shift,
const bool  create_interface_boundary_id,
const unsigned int  num_extra_layers 
) const
protectedinherited

returns a list of interface boundary IDs on the mesh generated by this mesh generator

Parameters
patternpattern of cells used in this mesh generator
interface_boundary_id_shift_pattern2D pattern of shift values applied to the boundary IDs inside each pattern cells
boundary_idslist of boundary IDs on the mesh generated by this mesh generator
input_interface_boundary_idslist of interface boundary IDs of the pattern cells
use_interface_boundary_id_shiftwhether ID shifts are applied to interface boundary IDs of the pattern cells
create_interface_boundary_idwhether interface boundary IDs are generated by this mesh generator
num_extra_layersnumber of extra layers to define background and duct regions on the patterned mesh generated by this mesh generator

Definition at line 1722 of file PolygonMeshGeneratorBase.C.

1730{
1731 std::set<boundary_id_type> interface_boundary_ids;
1732 // add existing interface boundary ids from input meshes
1733 if (use_interface_boundary_id_shift)
1734 {
1735 for (const auto i : make_range(pattern.size()))
1736 for (const auto j : make_range(pattern[i].size()))
1737 {
1738 const auto & ids = input_interface_boundary_ids[pattern[i][j]];
1739 for (const auto & id : ids)
1740 {
1741 const boundary_id_type new_id = id + interface_boundary_id_shift_pattern[i][j];
1742 auto it = boundary_ids.find(new_id);
1743 if (it != boundary_ids.end())
1744 interface_boundary_ids.insert(new_id);
1745 }
1746 }
1747 }
1748 else
1749 {
1750 for (const auto & ids : input_interface_boundary_ids)
1751 for (const auto & id : ids)
1752 {
1753 auto it = boundary_ids.find(id);
1754 if (it != boundary_ids.end())
1755 interface_boundary_ids.insert(id);
1756 }
1757 }
1758 // add unshifted interface boundary ids for the duct & background regions
1759 if (create_interface_boundary_id)
1760 for (const auto i : make_range(num_extra_layers))
1761 {
1762 boundary_id_type id = SLICE_ALT + i * 2 + 1;
1763 auto it = boundary_ids.find(id);
1764 if (it != boundary_ids.end())
1765 interface_boundary_ids.insert(id);
1766 id = SLICE_ALT + i * 2;
1767 it = boundary_ids.find(id);
1768 if (it != boundary_ids.end())
1769 interface_boundary_ids.insert(id);
1770 }
1771 return interface_boundary_ids;
1772}
@ pattern
assign the same reporting IDs for all tiles in the pattern with same input

Referenced by PatternedCartesianMeshGenerator::generate(), and PatternedHexMeshGenerator::generate().

◆ getRotationCenterAndRadius()

std::pair< Real, Point > RevolveGenerator::getRotationCenterAndRadius ( const Point p_ext,
const Point p_axis,
const Point dir_axis 
) const
protected

Get the rotation center and radius of the circular rotation based on the rotation axis and the external point.

Parameters
p_extexternal point that needs to be rotated
p_axisa point on the rotation axis
dir_axisdirection vector of the rotation axis
Returns
a pair of the rotation center and the radius of the circular rotation

Definition at line 1505 of file RevolveGenerator.C.

1508{
1509 // First use point product to get the distance between the axis point and the projection of the
1510 // external point on the axis
1511 const Real dist = (p_ext - p_axis) * dir_axis.unit();
1512 const Point center_pt = p_axis + dist * dir_axis.unit();
1513 // Then get the radius
1514 const Real radius = (p_ext - center_pt).norm();
1515 return std::make_pair(radius, center_pt);
1516}
auto norm(const T &a)

Referenced by generate().

◆ modifiedMultiBdryLayerParamsCreator()

PolygonMeshGeneratorBase::multiBdryLayerParams PolygonMeshGeneratorBase::modifiedMultiBdryLayerParamsCreator ( const multiBdryLayerParams original_multi_bdry_layer_params,
const unsigned int  order 
) const
protectedinherited

Modifies the input multi boundary layer parameters for node generation, especially for the quadratic elements.

Parameters
original_multi_bdry_layer_paramsoriginal multi boundary layer parameters
orderorder of the elements
Returns
modified multi boundary layer parameters

Definition at line 1775 of file PolygonMeshGeneratorBase.C.

1777{
1778 multiBdryLayerParams mod_multi_bdry_layer_params(original_multi_bdry_layer_params);
1779 std::for_each(mod_multi_bdry_layer_params.intervals.begin(),
1780 mod_multi_bdry_layer_params.intervals.end(),
1781 [&order](unsigned int & n) { n *= order; });
1782 std::for_each(mod_multi_bdry_layer_params.biases.begin(),
1783 mod_multi_bdry_layer_params.biases.end(),
1784 [&order](Real & n) { n = std::pow(n, 1.0 / order); });
1785 return mod_multi_bdry_layer_params;
1786}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ modifiedSingleBdryLayerParamsCreator()

PolygonMeshGeneratorBase::singleBdryLayerParams PolygonMeshGeneratorBase::modifiedSingleBdryLayerParamsCreator ( const singleBdryLayerParams original_single_bdry_layer_params,
const unsigned int  order 
) const
protectedinherited

Modifies the input single boundary layer parameters for node generation, especially for the quadratic elements.

Parameters
original_single_bdry_layer_paramsoriginal single boundary layer parameters
orderorder of the elements
Returns
modified single boundary layer parameters

Definition at line 1789 of file PolygonMeshGeneratorBase.C.

1791{
1792 singleBdryLayerParams mod_single_bdry_layer_params(original_single_bdry_layer_params);
1793 mod_single_bdry_layer_params.intervals *= order;
1794 mod_single_bdry_layer_params.bias = std::pow(mod_single_bdry_layer_params.bias, 1.0 / order);
1795 return mod_single_bdry_layer_params;
1796}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ nodeCoordRotate()

void PolygonMeshGeneratorBase::nodeCoordRotate ( Real &  x,
Real &  y,
const Real  theta 
) const
protectedinherited

Calculates x and y coordinates after rotating by theta angle.

Parameters
xx coordinate of the node to be rotated
yy coordinate of the node to be rotated
thetarotation angle
Returns
n/a

Definition at line 1320 of file PolygonMeshGeneratorBase.C.

1321{
1322 const Real x_tmp = x;
1323 const Real y_tmp = y;
1324 x = x_tmp * std::cos(theta * M_PI / 180.0) - y_tmp * std::sin(theta * M_PI / 180.0);
1325 y = x_tmp * std::sin(theta * M_PI / 180.0) + y_tmp * std::cos(theta * M_PI / 180.0);
1326}

Referenced by PolygonMeshGeneratorBase::cutOffPolyDeform(), FlexiblePatternGenerator::FlexiblePatternGenerator(), PatternedCartesianMeshGenerator::generate(), PatternedHexMeshGenerator::generate(), and PolygonConcentricCircleMeshGeneratorBase::generate().

◆ nodeModification()

void RevolveGenerator::nodeModification ( Node node)
protected

Modify the position of a node to account for radius correction.

Parameters
nodethe node to be modified

Definition at line 1559 of file RevolveGenerator.C.

1560{
1561 const Point axis_component =
1563 const Point rad_component = ((node - _axis_point) - axis_component) * _radius_correction_factor;
1564 node = _axis_point + axis_component + rad_component;
1565}

Referenced by generate().

◆ onAxisNodesIdentifier()

std::pair< std::vector< dof_id_type >, std::vector< dof_id_type > > RevolveGenerator::onAxisNodesIdentifier ( const Elem elem,
const std::vector< dof_id_type > &  nodes_on_axis 
) const
protected

Categorize the nodes of an element into two groups: nodes on the axis and nodes off the axis.

Parameters
elemthe element whose nodes are to be categorized
nodes_on_axisa list of node IDs on the axis
Returns
a pair of lists of node IDs: the first list is for nodes on the axis, and the second list is for nodes off the axis

Definition at line 1538 of file RevolveGenerator.C.

1540{
1541 std::vector<dof_id_type> nodes_on_axis_in_elem;
1542 std::vector<dof_id_type> nodes_not_on_axis_in_elem;
1543 for (unsigned int i = 0; i < elem.n_nodes(); i++)
1544 {
1545 const auto node_id = elem.node_id(i);
1546 if (std::find(nodes_on_axis.begin(), nodes_on_axis.end(), node_id) != nodes_on_axis.end())
1547 {
1548 nodes_on_axis_in_elem.push_back(i);
1549 }
1550 else
1551 {
1552 nodes_not_on_axis_in_elem.push_back(i);
1553 }
1554 }
1555 return std::make_pair(nodes_on_axis_in_elem, nodes_not_on_axis_in_elem);
1556}
virtual unsigned int n_nodes() const=0
dof_id_type node_id(const unsigned int i) const

Referenced by generate().

◆ pitchMetaDataErrorGenerator()

std::string PolygonMeshGeneratorBase::pitchMetaDataErrorGenerator ( const std::vector< MeshGeneratorName > &  input_names,
const std::vector< Real > &  metadata_vals,
const std::string &  metadata_name 
) const
protectedinherited

Generate a string that contains the detailed metadata information for inconsistent input mesh metadata error messages.

Parameters
input_nameslist of input mesh generator names
metadata_valslist of input mesh metadata values
metadata_namename of the input mesh metadata
Returns
a string that contains the detailed metadata information

Definition at line 1799 of file PolygonMeshGeneratorBase.C.

1803{
1804 FormattedTable table;
1805 for (unsigned int i = 0; i < input_names.size(); i++)
1806 {
1807 table.addRow(i);
1808 table.addData<std::string>("input name", (std::string)input_names[i]);
1809 table.addData<Real>(metadata_name, metadata_vals[i]);
1810 }
1811 table.outputTimeColumn(false);
1812 std::stringstream detailed_error;
1813 table.printTable(detailed_error);
1814 return "\n" + detailed_error.str();
1815}
void printTable(std::ostream &out, unsigned int last_n_entries=0)
void addData(const std::string &name, const T &value)
void addRow(Real time)
void outputTimeColumn(bool output_time)

Referenced by PatternedCartesianMeshGenerator::generate(), and PatternedHexMeshGenerator::generate().

◆ pointInterpolate()

std::pair< Real, Real > PolygonMeshGeneratorBase::pointInterpolate ( const Real  pi_1_x,
const Real  pi_1_y,
const Real  po_1_x,
const Real  po_1_y,
const Real  pi_2_x,
const Real  pi_2_y,
const Real  po_2_x,
const Real  po_2_y,
const unsigned int  i,
const unsigned int  j,
const unsigned int  num_sectors_per_side,
const unsigned int  peripheral_intervals 
) const
protectedinherited

Calculates the point coordinates of within a parallelogram region using linear interpolation.

Parameters
pi_1_xx coordinate of the first inner side point (parallelogram vertex)
pi_1_yy coordinate of the first inner side point (parallelogram vertex)
po_1_xx coordinate of the first outer side point (parallelogram vertex)
po_1_yy coordinate of the first outer side point (parallelogram vertex)
pi_2_xx coordinate of the second inner side point (parallelogram vertex)
pi_2_yy coordinate of the second inner side point (parallelogram vertex)
po_2_xx coordinate of the second outer side point (parallelogram vertex)
po_2_yy coordinate of the second outer side point (parallelogram vertex)
ipassed loop index 1
jpassed loop index 2
num_sectors_per_sidenumber of azimuthal intervals
peripheral_invervalsnumber of radial intervals of the peripheral region
Returns
an interpolated position within a parallelogram

Definition at line 1293 of file PolygonMeshGeneratorBase.C.

1305{
1306 auto position_px_inner =
1307 (pi_1_x * (num_sectors_per_side / 2.0 - j) + pi_2_x * j) / (num_sectors_per_side / 2.0);
1308 auto position_py_inner =
1309 (pi_1_y * (num_sectors_per_side / 2.0 - j) + pi_2_y * j) / (num_sectors_per_side / 2.0);
1310 auto position_px_outer =
1311 (d_po_1_x * (num_sectors_per_side / 2.0 - j) + d_po_2_x * j) / (num_sectors_per_side / 2.0);
1312 auto position_py_outer =
1313 (d_po_1_y * (num_sectors_per_side / 2.0 - j) + d_po_2_y * j) / (num_sectors_per_side / 2.0);
1314 auto position_px = position_px_inner + position_px_outer * i / peripheral_intervals;
1315 auto position_py = position_py_inner + position_py_outer * i / peripheral_intervals;
1316 return std::make_pair(position_px, position_py);
1317}

Referenced by PolygonMeshGeneratorBase::buildSimplePeripheral().

◆ quadElemDef()

void PolygonMeshGeneratorBase::quadElemDef ( ReplicatedMesh mesh,
const unsigned int  num_sectors_per_side,
const std::vector< unsigned int subdomain_rings,
const unsigned int  side_index,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>(),
const subdomain_id_type  block_id_shift = 0,
const dof_id_type  nodeid_shift = 0,
const bool  create_inward_interface_boundaries = false,
const bool  create_outward_interface_boundaries = true,
const boundary_id_type  boundary_id_shift = 0,
const bool  generate_side_specific_boundaries = true,
const QUAD_ELEM_TYPE  quad_elem_type = QUAD_ELEM_TYPE::QUAD4 
) const
protectedinherited

Defines general quad elements for the polygon.

Parameters
meshinput mesh to create the elements onto
num_sectors_per_sidenumber of azimuthal intervals
subdomain_ringsnumbers of radial intervals of all involved subdomain layers
side_indexindex of the polygon side
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching
block_id_shiftshift of the subdomain ids generated by this function
nodeid_shiftshift of the node_ids of these elements
create_inward_interface_boundarieswhether inward interface boundary sidesets are created
create_outward_interface_boundarieswhether outward interface boundary sidesets are created
boundary_id_shiftshift of the interface boundary ids
generate_side_specific_boundarieswhether the side-specific external boundaries are generated or not
quad_elem_typetype of the quadrilateral elements to be generated

Definition at line 1053 of file PolygonMeshGeneratorBase.C.

1065{
1066 const unsigned short order = quad_elem_type == QUAD_ELEM_TYPE::QUAD4 ? 1 : 2;
1067 unsigned int angle_number = azimuthal_tangent.size() == 0
1068 ? num_sectors_per_side
1069 : ((azimuthal_tangent.size() - 1) / order);
1070
1071 BoundaryInfo & boundary_info = mesh.get_boundary_info();
1072 unsigned int j = 0;
1073 for (unsigned int k = 0; k < (subdomain_rings.size()); k++)
1074 {
1075 for (unsigned int m = 0; m < subdomain_rings[k]; m++)
1076 {
1077 for (unsigned int i = 1; i <= angle_number; i++)
1078 {
1079 std::unique_ptr<Elem> new_elem;
1080 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD4)
1081 {
1082 new_elem = std::make_unique<Quad4>();
1083 new_elem->set_node(0, mesh.node_ptr(nodeid_shift + i + (angle_number + 1) * j));
1084 new_elem->set_node(1, mesh.node_ptr(nodeid_shift + i + 1 + (angle_number + 1) * j));
1085 new_elem->set_node(2, mesh.node_ptr(nodeid_shift + i + (angle_number + 1) * (j + 1) + 1));
1086 new_elem->set_node(3, mesh.node_ptr(nodeid_shift + i + (angle_number + 1) * (j + 1)));
1087 }
1088 else // QUAD8/QUAD9
1089 {
1090 new_elem = std::make_unique<Quad8>();
1091 if (quad_elem_type == QUAD_ELEM_TYPE::QUAD9)
1092 {
1093 new_elem = std::make_unique<Quad9>();
1094 new_elem->set_node(
1095 8, mesh.node_ptr(nodeid_shift + i * 2 + (angle_number * 2 + 1) * (j * 2 + 2)));
1096 }
1097 new_elem->set_node(
1098 0,
1099 mesh.node_ptr(nodeid_shift + (i - 1) * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 1)));
1100 new_elem->set_node(
1101 1, mesh.node_ptr(nodeid_shift + i * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 1)));
1102 new_elem->set_node(
1103 2, mesh.node_ptr(nodeid_shift + i * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 3)));
1104 new_elem->set_node(
1105 3,
1106 mesh.node_ptr(nodeid_shift + (i - 1) * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 3)));
1107 new_elem->set_node(
1108 4, mesh.node_ptr(nodeid_shift + i * 2 + (angle_number * 2 + 1) * (j * 2 + 1)));
1109 new_elem->set_node(
1110 5, mesh.node_ptr(nodeid_shift + i * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 2)));
1111 new_elem->set_node(
1112 6, mesh.node_ptr(nodeid_shift + i * 2 + (angle_number * 2 + 1) * (j * 2 + 3)));
1113 new_elem->set_node(
1114 7,
1115 mesh.node_ptr(nodeid_shift + (i - 1) * 2 + 1 + (angle_number * 2 + 1) * (j * 2 + 2)));
1116 }
1117 Elem * elem = mesh.add_elem(std::move(new_elem));
1118 if (i == 1)
1119 boundary_info.add_side(elem, 3, SLICE_BEGIN);
1120 if (i == angle_number)
1121 boundary_info.add_side(elem, 1, SLICE_END);
1122
1123 if (subdomain_rings[0] == 0)
1124 elem->subdomain_id() = k + 1 + block_id_shift;
1125 else
1126 elem->subdomain_id() = k + 2 + block_id_shift;
1127
1128 if (m == 0 && create_inward_interface_boundaries && k > 0)
1129 boundary_info.add_side(elem, 0, k * 2 + boundary_id_shift);
1130 if (m == (subdomain_rings[k] - 1))
1131 {
1132 if (k == (subdomain_rings.size() - 1))
1133 {
1134 boundary_info.add_side(elem, 2, OUTER_SIDESET_ID);
1135 if (generate_side_specific_boundaries)
1136 {
1137 if (i <= angle_number / 2)
1138 boundary_info.add_side(elem, 2, OUTER_SIDESET_ID + side_index);
1139 else
1140 boundary_info.add_side(elem, 2, OUTER_SIDESET_ID_ALT + side_index);
1141 }
1142 }
1143 else if (create_outward_interface_boundaries)
1144 boundary_info.add_side(elem, 2, k * 2 + 1 + boundary_id_shift);
1145 }
1146 }
1147 j++;
1148 }
1149 }
1150}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ reassignBoundaryIDs()

void PolygonMeshGeneratorBase::reassignBoundaryIDs ( MeshBase mesh,
const boundary_id_type  id_shift,
const std::set< boundary_id_type > &  boundary_ids,
const bool  reverse = false 
)
protectedinherited

reassign interface boundary IDs on the input mesh by applying the boundary ID shift

Parameters
meshinput mesh
id_shiftID shift value to be applied
boundary_idslist of boundary IDs to be reassigned
reverseremove boundary ID shift

Definition at line 1703 of file PolygonMeshGeneratorBase.C.

1707{
1708 const std::set<boundary_id_type> existing_boundary_ids =
1710 for (const auto id : boundary_ids)
1711 {
1712
1713 const boundary_id_type old_id = (!reverse) ? id : id + id_shift;
1714 const boundary_id_type new_id = (!reverse) ? id + id_shift : id;
1715 auto it = existing_boundary_ids.find(old_id);
1716 if (it != existing_boundary_ids.end())
1717 MooseMesh::changeBoundaryId(mesh, old_id, new_id, true);
1718 }
1719}
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
const std::set< boundary_id_type > & get_boundary_ids() const

Referenced by PatternedCartesianMeshGenerator::generate(), and PatternedHexMeshGenerator::generate().

◆ ringNodes()

void PolygonMeshGeneratorBase::ringNodes ( ReplicatedMesh mesh,
const std::vector< Real >  ring_radii,
const std::vector< unsigned int ring_layers,
const std::vector< std::vector< Real > >  biased_terms,
const unsigned int  num_sectors_per_side,
const Real  corner_p[2][2],
const Real  corner_to_corner,
const std::vector< Real >  azimuthal_tangent = std::vector<Real>() 
) const
protectedinherited

Creates nodes for the ring-geometry region of a single slice.

Parameters
meshinput mesh to add the nodes onto
ring_radiiradii of the ring regions
ring_layersnumbers of radial intervals of the ring regions
biased_termsnormalized spacing values used for radial meshing biasing in ring regions
num_sectors_per_sidenumber of azimuthal intervals
corner_p[2][2]array contains the coordinates of the corner positions
corner_to_cornerdiameter of the circumscribed circle of the polygon
azimuthal_tangentvector of tangent values of the azimuthal angles as reference for adaptive boundary matching

Definition at line 656 of file PolygonMeshGeneratorBase.C.

664{
665 const unsigned int angle_number =
666 azimuthal_tangent.size() == 0 ? num_sectors_per_side : (azimuthal_tangent.size() - 1);
667
668 // Add nodes in pins regions
669 for (unsigned int l = 0; l < ring_layers.size(); l++)
670 {
671 // the pin radius interval for each ring_radii/subdomain
672 const Real pin_radius_interval_length =
673 l == 0 ? ring_radii[l] / ring_layers[l]
674 : (ring_radii[l] - ring_radii[l - 1]) / ring_layers[l];
675
676 // add rings in each pin subdomain
677 for (unsigned int k = 0; k < ring_layers[l]; k++)
678 {
679 const Real bin_radial_distance =
680 l == 0 ? (biased_terms[l][k] * ring_layers[l] *
681 pin_radius_interval_length) // this is from the cell/pin center to
682 // the first circle
683 : (ring_radii[l - 1] +
684 biased_terms[l][k] * ring_layers[l] * pin_radius_interval_length);
685 const Real pin_corner_p_x = corner_p[0][0] * bin_radial_distance / (0.5 * corner_to_corner);
686 const Real pin_corner_p_y = corner_p[0][1] * bin_radial_distance / (0.5 * corner_to_corner);
687
688 // pin_corner_p(s) are the points in the pin region, on the bins towards the six corners,
689 // at different intervals
690 mesh.add_point(Point(pin_corner_p_x, pin_corner_p_y, 0.0));
691
692 for (unsigned int j = 1; j <= angle_number; j++)
693 {
694 const Real cell_boundary_p_x =
695 corner_p[0][0] + (corner_p[1][0] - corner_p[0][0]) *
696 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
697 : (azimuthal_tangent[j] / 2.0));
698 const Real cell_boundary_p_y =
699 corner_p[0][1] + (corner_p[1][1] - corner_p[0][1]) *
700 (azimuthal_tangent.size() == 0 ? ((Real)j / (Real)angle_number)
701 : (azimuthal_tangent[j] / 2.0));
702 // cell_boundary_p(s) are the points on the cell's six boundaries (flat sides) at
703 // different azimuthal angles
704 const Real pin_azimuthal_p_x =
705 cell_boundary_p_x * bin_radial_distance /
706 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
707 const Real pin_azimuthal_p_y =
708 cell_boundary_p_y * bin_radial_distance /
709 std::sqrt(Utility::pow<2>(cell_boundary_p_x) + Utility::pow<2>(cell_boundary_p_y));
710
711 // pin_azimuthal_p are the points on the bins towards different azimuthal angles, at
712 // different intervals; excluding the ones produced by pin_corner_p
713 mesh.add_point(Point(pin_azimuthal_p_x, pin_azimuthal_p_y, 0.0));
714 }
715 }
716 }
717}

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ rotationVectors()

std::vector< Point > RevolveGenerator::rotationVectors ( const Point p_axis,
const Point dir_axis,
const Point p_input 
) const
protected

Calculate the transform matrix between the rotation coordinate system and the original coordinate system.

Parameters
p_axisa point on the rotation axis
dir_axisdirection vector of the rotation axis
p_inputa point in the input mesh
Returns
a transform matrix, stored as 3 points in a vector (each point represents a row of the matrix)

Definition at line 1519 of file RevolveGenerator.C.

1522{
1523 // To make the rotation mathematically simple, we perform rotation in a coordination system
1524 // (x',y',z') defined by rotation axis and the mesh to be rotated.
1525 // z' is the rotation axis, which is trivial dir_axis.unit()
1526 const Point z_prime = dir_axis.unit();
1527 // the x' and z' should form the plane that accommodates input mesh
1528 const Point x_prime = ((p_input - p_axis) - ((p_input - p_axis) * z_prime) * z_prime).unit();
1529 const Point y_prime = z_prime.cross(x_prime);
1530 // Then we transform things back to the original coordination system (x,y,z), which is trivial
1531 // (1,0,0), (0,1,0), (0,0,1)
1532 return {{x_prime(0), y_prime(0), z_prime(0)},
1533 {x_prime(1), y_prime(1), z_prime(1)},
1534 {x_prime(2), y_prime(2), z_prime(2)}};
1535}
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const

Referenced by generate().

◆ setRingExtraIDs()

void PolygonMeshGeneratorBase::setRingExtraIDs ( MeshBase mesh,
const std::string  id_name,
const unsigned int  num_sides,
const std::vector< unsigned int num_sectors_per_side,
const std::vector< unsigned int ring_intervals,
const bool  ring_wise_id,
const bool  quad_center_elements 
)
protectedinherited

assign ring extra ids to polygon mesh

Parameters
meshinput mesh where ring extra ids are assigned
id_namering extra id name
num_sidesnumber of polygon sides
num_sectors_per_sidenumber of sectors of each side of the polygon
ring_intervalsnumber of rings in each circle
ring_wise_idwhether ring ids are assigned to each ring or to each block
quad_center_elementswhether center elements are quad or triangular

Definition at line 1638 of file PolygonMeshGeneratorBase.C.

1645{
1646 // this function assumes that elements are ordered by rings (inner) then by sectors (outer
1647 // ordering)
1648 const auto extra_id_index = mesh.add_elem_integer(id_name);
1649 auto elem_it = mesh.elements_begin();
1650 for (unsigned int is = 0; is < num_sides; ++is)
1651 {
1652 // number of elements in the current sector
1653 unsigned int nelem = mesh.n_elem() * num_sectors_per_side[is] /
1654 (accumulate(num_sectors_per_side.begin(), num_sectors_per_side.end(), 0));
1655 if (!ring_wise_id)
1656 {
1657 for (unsigned int ir : index_range(ring_intervals))
1658 {
1659 // number of elements in the current ring and sector
1660 unsigned int nelem_annular_ring = num_sectors_per_side[is] * ring_intervals[ir];
1661 // if _quad_center_elements is true, the number of elements in center ring are
1662 // _num_sectors_per_side[is] * _num_sectors_per_side[is] / 4
1663 if (quad_center_elements && ir == 0)
1664 nelem_annular_ring = num_sectors_per_side[is] * (ring_intervals[ir] - 1) +
1665 num_sectors_per_side[is] * num_sectors_per_side[is] / 4;
1666 // assign ring id
1667 for (unsigned i = 0; i < nelem_annular_ring; ++i, ++elem_it)
1668 (*elem_it)->set_extra_integer(extra_id_index, ir + 1);
1669 // update number of elements in background region of current side.
1670 nelem -= nelem_annular_ring;
1671 }
1672 }
1673 else
1674 {
1675 unsigned int ir = 0;
1676 for (unsigned int ir0 : index_range(ring_intervals))
1677 {
1678 for (unsigned int ir1 = 0; ir1 < ring_intervals[ir0]; ++ir1)
1679 {
1680 // number of elements in the current ring and sector
1681 unsigned int nelem_annular_ring = num_sectors_per_side[is];
1682 // if _quad_center_elements is true, the number of elements in center ring are
1683 // _num_sectors_per_side[is] * _num_sectors_per_side[is] / 4
1684 if (quad_center_elements && ir == 0)
1685 nelem_annular_ring = num_sectors_per_side[is] * num_sectors_per_side[is] / 4;
1686 // assign ring id
1687 for (unsigned i = 0; i < nelem_annular_ring; ++i, ++elem_it)
1688 (*elem_it)->set_extra_integer(extra_id_index, ir + 1);
1689 // update ring id
1690 ++ir;
1691 // update number of elements in background region of current side.
1692 nelem -= nelem_annular_ring;
1693 }
1694 }
1695 }
1696 // assign ring id of 0 to the background region
1697 for (unsigned i = 0; i < nelem; ++i, ++elem_it)
1698 (*elem_it)->set_extra_integer(extra_id_index, 0);
1699 }
1700}
virtual dof_id_type n_elem() const=0
PetscErrorCode PetscInt const PetscInt IS * is

Referenced by PolygonConcentricCircleMeshGeneratorBase::generate(), and TriPinHexAssemblyGenerator::generate().

◆ setSectorExtraIDs()

void PolygonMeshGeneratorBase::setSectorExtraIDs ( MeshBase mesh,
const std::string  id_name,
const unsigned int  num_sides,
const std::vector< unsigned int num_sectors_per_side 
)
protectedinherited

assign sector extra ids to polygon mesh

Parameters
meshinput mesh where sector extra ids are assigned
id_namesector extra ID name
num_sidenumber of polygon sides
num_sectors_per_sidenumber of sections of each side of the polygon

Definition at line 1613 of file PolygonMeshGeneratorBase.C.

1617{
1618 const auto extra_id_index = mesh.add_elem_integer(id_name);
1619 // vector to store sector ids for each element
1620 auto elem_it = mesh.elements_begin();
1621 unsigned int id = 1;
1622 // starting element id of the current sector
1623 for (unsigned int is = 0; is < num_sides; ++is)
1624 {
1625 // number of elements in the current sector
1626 unsigned int nelem_sector =
1627 mesh.n_elem() * num_sectors_per_side[is] /
1628 (accumulate(num_sectors_per_side.begin(), num_sectors_per_side.end(), 0));
1629 // assign sector ids to mesh
1630 for (unsigned i = 0; i < nelem_sector; ++i, ++elem_it)
1631 (*elem_it)->set_extra_integer(extra_id_index, id);
1632 // update sector id
1633 ++id;
1634 }
1635}

Referenced by PolygonConcentricCircleMeshGeneratorBase::generate(), and TriPinHexAssemblyGenerator::generate().

◆ validParams()

InputParameters RevolveGenerator::validParams ( )
static

Definition at line 42 of file RevolveGenerator.C.

43{
45 params.addClassDescription("This RevolveGenerator object is designed to revolve a 1D mesh into "
46 "2D, or a 2D mesh into 3D based on an axis.");
47
48 params.addRequiredParam<MeshGeneratorName>("input", "The mesh to revolve");
49
50 params.addRequiredParam<Point>("axis_point", "A point on the axis of revolution");
51
52 params.addRequiredParam<Point>("axis_direction", "The direction of the axis of revolution");
53
54 params.addRangeCheckedParam<std::vector<Real>>(
55 "revolving_angles",
56 "revolving_angles<=360.0 & revolving_angles>0.0",
57 "The angles delineating each azimuthal section of revolution around the axis in degrees");
58
59 params.addParam<std::vector<std::vector<subdomain_id_type>>>(
60 "subdomain_swaps",
61 {},
62 "For each row, every two entries are interpreted as a pair of "
63 "'from' and 'to' to remap the subdomains for that azimuthal section");
64
65 params.addParam<std::vector<std::vector<boundary_id_type>>>(
66 "boundary_swaps",
67 {},
68 "For each row, every two entries are interpreted as a pair of "
69 "'from' and 'to' to remap the boundaries for that elevation");
70
71 params.addParam<std::vector<std::string>>(
72 "elem_integer_names_to_swap",
73 {},
74 "Array of element extra integer names that need to be swapped during revolving.");
75
76 params.addParam<std::vector<std::vector<std::vector<dof_id_type>>>>(
77 "elem_integers_swaps",
78 {},
79 "For each row, every two entries are interpreted as a pair of 'from' and 'to' to remap the "
80 "element extra integer for that elevation. If multiple element extra integers need to be "
81 "swapped, the enties are stacked based on the order provided in "
82 "'elem_integer_names_to_swap' to form the third dimension.");
83
85 "start_boundary",
86 "The boundary ID to set on the starting boundary for a partial revolution.");
87
89 "end_boundary", "The boundary ID to set on the ending boundary for partial revolving.");
90
91 params.addParam<bool>(
92 "clockwise", true, "Revolve clockwise around the axis or not (i.e., counterclockwise)");
93
94 params.addRequiredParam<std::vector<unsigned int>>(
95 "nums_azimuthal_intervals",
96 "List of the numbers of azimuthal interval discretization for each azimuthal section");
97
98 params.addParam<bool>("preserve_volumes",
99 false,
100 "Whether the volume of the revolved mesh is preserving the circular area "
101 "by modifying (expanding) the radius to account for polygonization.");
102
103 params.addParamNamesToGroup("start_boundary end_boundary", "Boundary Assignment");
105 "subdomain_swaps boundary_swaps elem_integer_names_to_swap elem_integers_swaps", "ID Swap");
106
107 return params;
108}
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
static InputParameters validParams()

Member Data Documentation

◆ _axis_direction

const Point& RevolveGenerator::_axis_direction
protected

A direction vector of the axis of revolution.

Definition at line 35 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _axis_point

const Point& RevolveGenerator::_axis_point
protected

A point of the axis of revolution.

Definition at line 32 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _boundary_swap_pairs

std::vector<std::unordered_map<boundary_id_type, boundary_id_type> > RevolveGenerator::_boundary_swap_pairs
protected

Easier to work with version of _boundary_swaps.

Definition at line 75 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _boundary_swaps

const std::vector<std::vector<boundary_id_type> >& RevolveGenerator::_boundary_swaps
protected

Boundaries to swap out for each elevation.

Definition at line 44 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _clockwise

const bool& RevolveGenerator::_clockwise
protected

Revolving direction.

Definition at line 54 of file RevolveGenerator.h.

Referenced by generate().

◆ _elem_integer_indices_to_swap

std::vector<unsigned int> RevolveGenerator::_elem_integer_indices_to_swap
protected

Definition at line 48 of file RevolveGenerator.h.

Referenced by generate().

◆ _elem_integer_names_to_swap

const std::vector<std::string>& RevolveGenerator::_elem_integer_names_to_swap
protected

Names and indices of extra element integers to swap.

Definition at line 47 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _elem_integers_swap_pairs

std::vector<std::unordered_map<dof_id_type, dof_id_type> > RevolveGenerator::_elem_integers_swap_pairs
protected

Easier to work with version of _elem_integers_swaps.

Definition at line 78 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _elem_integers_swaps

const std::vector<std::vector<std::vector<dof_id_type> > >& RevolveGenerator::_elem_integers_swaps
protected

Extra element integers to swap out for each elevation and each element integer name.

Definition at line 51 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _end_boundary

boundary_id_type RevolveGenerator::_end_boundary
protected

Boundary ID of the ending boundary.

Definition at line 87 of file RevolveGenerator.h.

Referenced by generate().

◆ _full_circle_revolving

bool RevolveGenerator::_full_circle_revolving
protected

◆ _has_end_boundary

bool RevolveGenerator::_has_end_boundary
protected

Whether an ending boundary is specified.

Definition at line 69 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _has_start_boundary

bool RevolveGenerator::_has_start_boundary
protected

Whether a starting boundary is specified.

Definition at line 63 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _input

std::unique_ptr<MeshBase>& RevolveGenerator::_input
protected

Lower dimensional mesh from another generator.

Definition at line 29 of file RevolveGenerator.h.

Referenced by generate().

◆ _nums_azimuthal_intervals

const std::vector<unsigned int>& RevolveGenerator::_nums_azimuthal_intervals
protected

Numbers of azimuthal mesh intervals in each azimuthal section.

Definition at line 57 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _preserve_volumes

const bool RevolveGenerator::_preserve_volumes
protected

Volume preserving function is optional.

Definition at line 60 of file RevolveGenerator.h.

Referenced by generate().

◆ _radius_correction_factor

Real RevolveGenerator::_radius_correction_factor
protected

Radius correction factor.

Definition at line 90 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _revolving_angles

const std::vector<Real> RevolveGenerator::_revolving_angles
protected

Angles of revolution delineating each azimuthal section.

Definition at line 38 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _start_boundary

boundary_id_type RevolveGenerator::_start_boundary
protected

Boundary ID of the starting boundary.

Definition at line 66 of file RevolveGenerator.h.

Referenced by generate().

◆ _subdomain_swap_pairs

std::vector<std::unordered_map<subdomain_id_type, subdomain_id_type> > RevolveGenerator::_subdomain_swap_pairs
protected

Easier to work with version of _sudomain_swaps.

Definition at line 72 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _subdomain_swaps

const std::vector<std::vector<subdomain_id_type> >& RevolveGenerator::_subdomain_swaps
protected

Subdomains to swap out for each azimuthal section.

Definition at line 41 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _unit_angles

std::vector<Real> RevolveGenerator::_unit_angles
protected

Unit angles of all azimuthal sections of revolution.

Definition at line 84 of file RevolveGenerator.h.

Referenced by generate().


The documentation for this class was generated from the following files: