https://mooseframework.inl.gov
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Static Protected Member Functions | Protected 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  PolygonSizeStyle { PolygonSizeStyle::apothem, PolygonSizeStyle::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  TRI_ELEM_TYPE { TRI_ELEM_TYPE::TRI3, TRI_ELEM_TYPE::TRI6, TRI_ELEM_TYPE::TRI7 }
 
enum  QUAD_ELEM_TYPE { QUAD_ELEM_TYPE::QUAD4, QUAD_ELEM_TYPE::QUAD8, QUAD_ELEM_TYPE::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 haveParameter (const std::string &name) 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. More...
 
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. More...
 
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. More...
 
void nodeModification (Node &node)
 Modify the position of a node to account for radius correction. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
std::pair< Real, RealpointInterpolate (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. More...
 
void nodeCoordRotate (Real &x, Real &y, const Real theta) const
 Calculates x and y coordinates after rotating by theta angle. More...
 
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. More...
 
std::pair< Real, RealfourPointIntercept (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. More...
 
std::vector< RealazimuthalAnglesCollector (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. More...
 
std::vector< RealazimuthalAnglesCollector (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. More...
 
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. More...
 
std::vector< RealbiasTermsCalculator (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. More...
 
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 More...
 
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 More...
 
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 More...
 
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 More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
const Point & _axis_point
 A point of the axis of revolution. More...
 
const Point & _axis_direction
 A direction vector of the axis of revolution. More...
 
const std::vector< Real_revolving_angles
 Angles of revolution delineating each azimuthal section. More...
 
const std::vector< std::vector< subdomain_id_type > > & _subdomain_swaps
 Subdomains to swap out for each azimuthal section. More...
 
const std::vector< std::vector< boundary_id_type > > & _boundary_swaps
 Boundaries to swap out for each elevation. More...
 
const std::vector< std::string > & _elem_integer_names_to_swap
 Names and indices of extra element integers to swap. More...
 
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. More...
 
const bool & _clockwise
 Revolving direction. More...
 
const std::vector< unsigned int > & _nums_azimuthal_intervals
 Numbers of azimuthal mesh intervals in each azimuthal section. More...
 
const bool _preserve_volumes
 Volume preserving function is optional. More...
 
bool _has_start_boundary
 Whether a starting boundary is specified. More...
 
boundary_id_type _start_boundary
 Boundary ID of the starting boundary. More...
 
bool _has_end_boundary
 Whether an ending boundary is specified. More...
 
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
 Easier to work with version of _sudomain_swaps. More...
 
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
 Easier to work with version of _boundary_swaps. More...
 
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
 Easier to work with version of _elem_integers_swaps. More...
 
bool _full_circle_revolving
 Whether to revolve for a full circle or not. More...
 
std::vector< Real_unit_angles
 Unit angles of all azimuthal sections of revolution. More...
 
boundary_id_type _end_boundary
 Boundary ID of the ending boundary. More...
 
Real _radius_correction_factor
 Radius correction factor. More...
 
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
 

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

◆ INTRISIC_SUBDOMAIN_ID

◆ MESH_TYPE

◆ PolygonSizeStyle

An enum class for style of input polygon size.

Enumerator
apothem 
radius 

Definition at line 41 of file PolygonMeshGeneratorBase.h.

42  {
43  apothem,
44  radius
45  };
const double radius

◆ QUAD_ELEM_TYPE

Enumerator
QUAD4 
QUAD8 
QUAD9 

Definition at line 88 of file PolygonMeshGeneratorBase.h.

89  {
90  QUAD4,
91  QUAD8,
92  QUAD9
93  };
QUAD8
QUAD4
QUAD9

◆ RETURN_TYPE

Enumerator
ANGLE_DEGREE 
ANGLE_TANGENT 

Definition at line 54 of file PolygonMeshGeneratorBase.h.

◆ TRI_ELEM_TYPE

Enumerator
TRI3 
TRI6 
TRI7 

Definition at line 81 of file PolygonMeshGeneratorBase.h.

82  {
83  TRI3,
84  TRI6,
85  TRI7
86  };
TRI3
TRI6
TRI7

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()))
138  paramError(
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()))
143  paramError(
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 }
const bool _preserve_volumes
Volume preserving function is optional.
bool _has_start_boundary
Whether a starting boundary is specified.
virtual const char * what() const
void paramError(const std::string &param, Args... args) const
const T & getParam(const std::string &name) const
boundary_id_type _start_boundary
Boundary ID of the starting boundary.
boundary_id_type _end_boundary
Boundary ID of the ending boundary.
const Point & _axis_direction
A direction vector of the axis of revolution.
const InputParameters & parameters() const
std::unique_ptr< MeshBase > & _input
Lower dimensional mesh from another generator.
const std::vector< std::string > & _elem_integer_names_to_swap
Names and indices of extra element integers to swap.
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 _has_end_boundary
Whether an ending boundary is specified.
const std::string & name() const
bool _full_circle_revolving
Whether to revolve for a full circle or not.
const std::vector< std::vector< subdomain_id_type > > & _subdomain_swaps
Subdomains to swap out for each azimuthal section.
const std::vector< Real > _revolving_angles
Angles of revolution delineating each azimuthal section.
std::unique_ptr< MeshBase > & getMesh(const std::string &param_name, const bool allow_invalid=false)
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)
const bool & _clockwise
Revolving direction.
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
Easier to work with version of _boundary_swaps.
const Point & _axis_point
A point of the axis of revolution.
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
Easier to work with version of _sudomain_swaps.
const std::vector< std::vector< boundary_id_type > > & _boundary_swaps
Boundaries to swap out for each elevation.
Real _radius_correction_factor
Radius correction factor.
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)
bool isParamValid(const std::string &name) const
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
Easier to work with version of _elem_integers_swaps.
PolygonMeshGeneratorBase(const InputParameters &parameters)

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.

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

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 addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)

◆ 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.

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

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 }
virtual Point true_centroid() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) 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
int8_t boundary_id_type
dof_id_type id() const
virtual const Elem * elem_ptr(const dof_id_type i) const=0
const Node * node_ptr(const unsigned int i) const
const Point & point(const unsigned int i) const
uint8_t dof_id_type

◆ azimuthalAnglesCollector() [1/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

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

◆ azimuthalAnglesCollector() [2/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

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
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
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:134

◆ biasTermsCalculator() [1/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.

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

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.

◆ biasTermsCalculator() [2/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 }
MooseUnits pow(const MooseUnits &, int)

◆ 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.

Referenced by TriPinHexAssemblyGenerator::buildSinglePinSection().

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...
MeshBase & mesh
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string ring_radii

◆ 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.

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

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)
MeshBase & mesh
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 Elem * add_elem(Elem *e)=0
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.
subdomain_id_type subdomain_id() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
void all_second_order(const bool full_ordered=true)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by PolygonConcentricCircleMeshGeneratorBase::generate().

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 }
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...
static const std::string pitch
static const std::string ring_radii

◆ 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.

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

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 }
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
void remove_orphaned_nodes()
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.
if(subdm)
MeshBase & mesh
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 ...
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
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.
const std::string & name() const
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.
static const std::string pitch
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 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 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.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string ring_radii
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 mooseError(Args &&... args) const
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...
MooseUnits pow(const MooseUnits &, int)
virtual dof_id_type n_nodes() const=0
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.

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
subdomain_id_type subdomain_id() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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.
MeshBase & mesh
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
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
subdomain_id_type subdomain_id() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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)
HEX8
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
PRISM6
virtual const Node * node_ptr(const dof_id_type i) const=0
uint8_t dof_id_type

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
PRISM6
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
PYRAMID5
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
PYRAMID5
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
QUAD4
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
TET4
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

Referenced by generate().

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 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
MeshBase & mesh
TRI3
bool _full_circle_revolving
Whether to revolve for a full circle or not.
dof_id_type id() const
const Node * node_ptr(const unsigned int i) const
void mooseError(Args &&... args) const
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ 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.

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

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 }
MeshBase & mesh
const std::vector< double > y
void nodeCoordRotate(Real &x, Real &y, const Real theta) const
Calculates x and y coordinates after rotating by theta angle.
const std::vector< double > x
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
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
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:134

◆ 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.

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

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 }
const std::vector< double > y
const std::vector< double > x
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ 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());
412  _unit_angles.push_back(_revolving_angles[i] / _nums_azimuthal_intervals[i] / order);
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  }
416  if (_preserve_volumes)
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  {
581  createQUADfromEDGE(QUAD4,
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  {
617  createQUADfromEDGE(QUAD9,
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  {
655  createPRISMfromTRI(PRISM6,
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  {
712  createPRISMfromTRI(PRISM18,
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
751  mooseError(
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  {
769  createPRISMfromTRI(PRISM21,
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  {
825  createHEXfromQUAD(HEX8,
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  {
887  createHEXfromQUAD(HEX20,
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  {
932  createHEXfromQUAD(HEX27,
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,
1460  _start_boundary);
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,
1471  _end_boundary);
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 }
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::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...
ElemType
virtual void reserve_nodes(const dof_id_type nn)=0
const bool _preserve_volumes
Volume preserving function is optional.
bool _has_start_boundary
Whether a starting boundary is specified.
auto norm() const
QUAD8
HEX8
void remove_orphaned_nodes()
void paramError(const std::string &param, Args... args) const
boundary_id_type _start_boundary
Boundary ID of the starting boundary.
void nodeModification(Node &node)
Modify the position of a node to account for radius correction.
char ** blocks
boundary_id_type _end_boundary
Boundary ID of the ending boundary.
const Point & _axis_direction
A direction vector of the axis of revolution.
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 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.
TET10
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< MeshBase > & _input
Lower dimensional mesh from another generator.
const std::vector< std::string > & _elem_integer_names_to_swap
Names and indices of extra element integers to swap.
PRISM15
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
bool has_elem_integer(std::string_view name) const
MeshBase & mesh
const std::vector< unsigned int > & _nums_azimuthal_intervals
Numbers of azimuthal mesh intervals in each azimuthal section.
unique_id_type unique_id() const
const Parallel::Communicator & comm() const
HEX20
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
PRISM21
virtual void set_next_unique_id(unique_id_type id)=0
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
TRI3
QUAD4
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.
bool _has_end_boundary
Whether an ending boundary is specified.
std::map< boundary_id_type, std::string > & set_sideset_name_map()
TypeVector< Real > unit() const
void libmesh_ignore(const Args &...)
void add_node(const Node *node, const boundary_id_type id)
bool _full_circle_revolving
Whether to revolve for a full circle or not.
TET4
const std::vector< Real > _revolving_angles
Angles of revolution delineating each azimuthal section.
TRI6
virtual Elem * add_elem(Elem *e)=0
HEX27
void set_mesh_dimension(unsigned char d)
TET14
const bool & _clockwise
Revolving direction.
std::vector< std::unordered_map< boundary_id_type, boundary_id_type > > _boundary_swap_pairs
Easier to work with version of _boundary_swaps.
const Point & _axis_point
A point of the axis of revolution.
std::vector< Real > _unit_angles
Unit angles of all azimuthal sections of revolution.
std::vector< std::unordered_map< subdomain_id_type, subdomain_id_type > > _subdomain_swap_pairs
Easier to work with version of _sudomain_swaps.
void set_unique_id(unique_id_type new_id)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
EDGE2
void max(const T &r, T &o, Request &req) const
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.
PYRAMID18
std::map< boundary_id_type, std::string > & set_nodeset_name_map()
PYRAMID5
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
TRI7
Real _radius_correction_factor
Radius correction factor.
std::vector< unsigned int > _elem_integer_indices_to_swap
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.
QUAD9
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
PYRAMID13
Point meshCentroidCalculator(const MeshBase &mesh)
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
PRISM6
virtual void delete_remote_elements()
PRISM18
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.
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...
const DofMap &dof_map LIBMESH_COMMA unsigned int std::string & set_subdomain_name_map()
EDGE3
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.
virtual ElemType type() const=0
virtual void reserve_elem(const dof_id_type ne)=0
uint8_t unique_id_type
static const std::string k
Definition: NS.h:134
void unset_is_prepared()
auto index_range(const T &sizable)
std::vector< std::unordered_map< dof_id_type, dof_id_type > > _elem_integers_swap_pairs
Easier to work with version of _elem_integers_swaps.
void set_extra_integer(const unsigned int index, const dof_id_type value)
virtual void renumber_nodes_and_elements()=0
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.
uint8_t dof_id_type
PYRAMID14

◆ 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.

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

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 }
int8_t boundary_id_type
IntRange< T > make_range(T beg, T end)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
assign the same reporting IDs for all tiles in the pattern with same input

◆ 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.

Referenced by generate().

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 }
TypeVector< Real > unit() const
const double radius
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseUnits pow(const MooseUnits &, int)

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MooseUnits pow(const MooseUnits &, int)

◆ 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.

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

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 }
const std::vector< double > y
const std::vector< double > x
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ 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.

Referenced by generate().

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 }
const Point & _axis_direction
A direction vector of the axis of revolution.
TypeVector< Real > unit() const
const Point & _axis_point
A point of the axis of revolution.
Real _radius_correction_factor
Radius correction factor.

◆ 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.

Referenced by generate().

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

◆ 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.

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

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 addData(const std::string &name, const T &value)
void outputTimeColumn(bool output_time)
void printTable(std::ostream &out, unsigned int last_n_entries=0)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void addRow(Real time)

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSimplePeripheral().

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 }
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
virtual Elem * add_elem(Elem *e)=0
subdomain_id_type subdomain_id() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual const Node * node_ptr(const dof_id_type i) const=0
static const std::string k
Definition: NS.h:134

◆ 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.

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

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 }
MeshBase & mesh
void changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
const BoundaryInfo & get_boundary_info() const
int8_t boundary_id_type
const std::set< boundary_id_type > & get_boundary_ids() const

◆ 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.

Referenced by PolygonMeshGeneratorBase::buildSlice().

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 }
MeshBase & mesh
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
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string ring_radii
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static const std::string k
Definition: NS.h:134

◆ 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.

Referenced by generate().

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< Real > unit() const
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const

◆ 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.

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

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 }
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
MeshBase & mesh
PetscErrorCode PetscInt const PetscInt IS * is
virtual dof_id_type n_elem() const=0
auto index_range(const T &sizable)

◆ 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.

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

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 }
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
MeshBase & mesh
PetscErrorCode PetscInt const PetscInt IS * is
virtual dof_id_type n_elem() const=0

◆ 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 
84  params.addParam<boundary_id_type>(
85  "start_boundary",
86  "The boundary ID to set on the starting boundary for a partial revolution.");
87 
88  params.addParam<boundary_id_type>(
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");
104  params.addParamNamesToGroup(
105  "subdomain_swaps boundary_swaps elem_integer_names_to_swap elem_integers_swaps", "ID Swap");
106 
107  return params;
108 }
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
static InputParameters validParams()
int8_t boundary_id_type
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)
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)

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: