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

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

#include <RevolveGenerator.h>

Inheritance diagram for RevolveGenerator:
[legend]

Public Types

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

Public Member Functions

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

Static Public Member Functions

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

Public Attributes

 usingCombinedWarningSolutionWarnings
 
const ConsoleStream _console
 

Static Public Attributes

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

Protected Member Functions

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

Static Protected Member Functions

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

Protected Attributes

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

Private Member Functions

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

Static Private Member Functions

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

Private Attributes

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

Detailed Description

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

Definition at line 18 of file RevolveGenerator.h.

Member Enumeration Documentation

◆ INTRINSIC_NUM_SIDES

Enumerator
HEXAGON_NUM_SIDES 
SQUARE_NUM_SIDES 

Definition at line 75 of file PolygonMeshGeneratorBase.h.

◆ INTRINSIC_SIDESET_ID

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

Definition at line 66 of file PolygonMeshGeneratorBase.h.

◆ INTRISIC_SUBDOMAIN_ID

enum PolygonMeshGeneratorBase::INTRISIC_SUBDOMAIN_ID : subdomain_id_type
inherited
Enumerator
PERIPHERAL_ID_SHIFT 
TRANSITION_LAYER_DEFAULT 

Definition at line 60 of file PolygonMeshGeneratorBase.h.

◆ MESH_TYPE

Enumerator
CORNER_MESH 
BOUNDARY_MESH 
INNER_MESH 

Definition at line 47 of file PolygonMeshGeneratorBase.h.

◆ PolygonSizeStyle

enum class PolygonMeshGeneratorBase::PolygonSizeStyle
stronginherited

An enum class for style of input polygon size.

Enumerator
apothem 
radius 

Definition at line 41 of file PolygonMeshGeneratorBase.h.

◆ QUAD_ELEM_TYPE

enum class PolygonMeshGeneratorBase::QUAD_ELEM_TYPE
stronginherited

◆ RETURN_TYPE

Enumerator
ANGLE_DEGREE 
ANGLE_TANGENT 

Definition at line 54 of file PolygonMeshGeneratorBase.h.

◆ TRI_ELEM_TYPE

enum class PolygonMeshGeneratorBase::TRI_ELEM_TYPE
stronginherited

Constructor & Destructor Documentation

◆ RevolveGenerator()

RevolveGenerator::RevolveGenerator ( const InputParameters parameters)

Definition at line 108 of file RevolveGenerator.C.

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

Member Function Documentation

◆ addRingAndSectorIDParams()

void PolygonMeshGeneratorBase::addRingAndSectorIDParams ( InputParameters params)
staticprotectedinherited

Add InputParameters which are used by ring and sector IDs.

Parameters
paramsInputParameters to be modified with the added params

Definition at line 1596 of file PolygonMeshGeneratorBase.C.

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

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

◆ adjustPeripheralQuadraticElements()

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

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

Parameters
out_meshmesh to be adjusted.
boundary_quad_elem_typeboundary quad element type.

Definition at line 1251 of file PolygonMeshGeneratorBase.C.

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

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

◆ azimuthalAnglesCollector() [1/2]

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

Collects sorted azimuthal angles of the external boundary.

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

Definition at line 1495 of file PolygonMeshGeneratorBase.C.

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

◆ azimuthalAnglesCollector() [2/2]

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

Collects sorted azimuthal angles of the external boundary.

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

Definition at line 1417 of file PolygonMeshGeneratorBase.C.

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

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

◆ backgroundNodes()

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

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

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

Definition at line 718 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ biasTermsCalculator() [1/2]

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

Creates bias terms for a single block.

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

Definition at line 1543 of file PolygonMeshGeneratorBase.C.

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

◆ biasTermsCalculator() [2/2]

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

Creates bias terms for multiple blocks.

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

Definition at line 1521 of file PolygonMeshGeneratorBase.C.

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

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

◆ buildGeneralSlice()

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

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

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

Definition at line 40 of file PolygonMeshGeneratorBase.C.

66{
67 const Real virtual_pitch = 2.0 * primary_side_length * cos(azimuthal_angle / 360.0 * M_PI);
68 const Real virtual_side_number = 360.0 / azimuthal_angle;
69 const Real pitch_scale_factor = secondary_side_length / primary_side_length;
70
71 auto mesh = buildSlice(ring_radii,
72 ring_layers,
73 ring_radial_biases,
74 ring_inner_boundary_layer_params,
75 ring_outer_boundary_layer_params,
76 ducts_center_dist,
77 ducts_layers,
78 duct_radial_biases,
79 duct_inner_boundary_layer_params,
80 duct_outer_boundary_layer_params,
81 virtual_pitch,
82 num_sectors_per_side,
83 background_intervals,
84 background_radial_bias,
85 background_inner_boundary_layer_params,
86 background_outer_boundary_layer_params,
87 node_id_background_meta,
88 virtual_side_number,
89 side_index,
90 azimuthal_tangent,
91 0,
92 quad_center_elements,
93 center_quad_factor,
94 false,
95 true,
96 0,
97 pitch_scale_factor,
98 generate_side_specific_boundaries);
99 MeshTools::Modification::rotate(*mesh, rotation_angle, 0, 0);
100 return mesh;
101}
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...

Referenced by TriPinHexAssemblyGenerator::buildSinglePinSection().

◆ buildSimplePeripheral()

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

Creates peripheral area mesh for the patterned hexagon mesh.

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

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

Definition at line 1151 of file PolygonMeshGeneratorBase.C.

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

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

◆ buildSimpleSlice()

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

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

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

Definition at line 104 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonConcentricCircleMeshGeneratorBase::generate().

◆ buildSlice()

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

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

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

Definition at line 168 of file PolygonMeshGeneratorBase.C.

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

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

◆ cenQuadElemDef()

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

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

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

Definition at line 851 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ centerNodes()

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

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

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

Definition at line 575 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ cenTriElemDef()

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

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

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

Definition at line 987 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ createHEXfromQUAD()

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

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

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

Definition at line 2044 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createPRISMfromQUAD()

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

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

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

Definition at line 2182 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createPRISMfromTRI()

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

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

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

Definition at line 1690 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createPYRAMIDfromTRI()

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

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

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

Definition at line 1807 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createPYRAMIDPRISMfromQUAD()

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

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

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

Definition at line 2306 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createQUADfromEDGE()

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

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

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

Definition at line 1566 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createTETfromTRI()

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

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

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

Definition at line 1927 of file RevolveGenerator.C.

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

Referenced by generate().

◆ createTRIfromEDGE()

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

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

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

Definition at line 1630 of file RevolveGenerator.C.

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

Referenced by generate().

◆ cutOffPolyDeform()

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

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

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

Definition at line 1327 of file PolygonMeshGeneratorBase.C.

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

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

◆ ductNodes()

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

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

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

Definition at line 790 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ fourPointIntercept()

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

Finds the center of a quadrilateral based on four vertices.

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

Definition at line 1394 of file PolygonMeshGeneratorBase.C.

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

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

◆ generate()

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

Reimplemented from PolygonMeshGeneratorBase.

Definition at line 207 of file RevolveGenerator.C.

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

◆ getInterfaceBoundaryIDs()

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

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

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

Definition at line 1720 of file PolygonMeshGeneratorBase.C.

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

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

◆ getRotationCenterAndRadius()

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

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

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

Definition at line 1503 of file RevolveGenerator.C.

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

Referenced by generate().

◆ modifiedMultiBdryLayerParamsCreator()

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

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

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

Definition at line 1773 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ modifiedSingleBdryLayerParamsCreator()

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

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

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

Definition at line 1787 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ nodeCoordRotate()

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

Calculates x and y coordinates after rotating by theta angle.

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

Definition at line 1318 of file PolygonMeshGeneratorBase.C.

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

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

◆ nodeModification()

void RevolveGenerator::nodeModification ( Node &  node)
protected

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

Parameters
nodethe node to be modified

Definition at line 1557 of file RevolveGenerator.C.

1558{
1559 const Point axis_component =
1560 ((node - _axis_point) * _axis_direction.unit()) * _axis_direction.unit();
1561 const Point rad_component = ((node - _axis_point) - axis_component) * _radius_correction_factor;
1562 node = _axis_point + axis_component + rad_component;
1563}

Referenced by generate().

◆ onAxisNodesIdentifier()

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

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

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

Definition at line 1536 of file RevolveGenerator.C.

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

Referenced by generate().

◆ pitchMetaDataErrorGenerator()

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

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

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

Definition at line 1797 of file PolygonMeshGeneratorBase.C.

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

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

◆ pointInterpolate()

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

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

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

Definition at line 1291 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSimplePeripheral().

◆ quadElemDef()

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

Defines general quad elements for the polygon.

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

Definition at line 1051 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ reassignBoundaryIDs()

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

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

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

Definition at line 1701 of file PolygonMeshGeneratorBase.C.

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

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

◆ ringNodes()

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

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

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

Definition at line 654 of file PolygonMeshGeneratorBase.C.

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

Referenced by PolygonMeshGeneratorBase::buildSlice().

◆ rotationVectors()

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

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

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

Definition at line 1517 of file RevolveGenerator.C.

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

Referenced by generate().

◆ setRingExtraIDs()

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

assign ring extra ids to polygon mesh

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

Definition at line 1636 of file PolygonMeshGeneratorBase.C.

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

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

◆ setSectorExtraIDs()

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

assign sector extra ids to polygon mesh

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

Definition at line 1611 of file PolygonMeshGeneratorBase.C.

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

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

◆ validParams()

InputParameters RevolveGenerator::validParams ( )
static

Definition at line 40 of file RevolveGenerator.C.

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

Member Data Documentation

◆ _axis_direction

const Point& RevolveGenerator::_axis_direction
protected

A direction vector of the axis of revolution.

Definition at line 35 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _axis_point

const Point& RevolveGenerator::_axis_point
protected

A point of the axis of revolution.

Definition at line 32 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _boundary_swap_pairs

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

Easier to work with version of _boundary_swaps.

Definition at line 75 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _boundary_swaps

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

Boundaries to swap out for each elevation.

Definition at line 44 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _clockwise

const bool& RevolveGenerator::_clockwise
protected

Revolving direction.

Definition at line 54 of file RevolveGenerator.h.

Referenced by generate().

◆ _elem_integer_indices_to_swap

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

Definition at line 48 of file RevolveGenerator.h.

Referenced by generate().

◆ _elem_integer_names_to_swap

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

Names and indices of extra element integers to swap.

Definition at line 47 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _elem_integers_swap_pairs

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

Easier to work with version of _elem_integers_swaps.

Definition at line 78 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _elem_integers_swaps

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

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

Definition at line 51 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _end_boundary

boundary_id_type RevolveGenerator::_end_boundary
protected

Boundary ID of the ending boundary.

Definition at line 87 of file RevolveGenerator.h.

Referenced by generate().

◆ _full_circle_revolving

bool RevolveGenerator::_full_circle_revolving
protected

◆ _has_end_boundary

bool RevolveGenerator::_has_end_boundary
protected

Whether an ending boundary is specified.

Definition at line 69 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _has_start_boundary

bool RevolveGenerator::_has_start_boundary
protected

Whether a starting boundary is specified.

Definition at line 63 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _input

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

Lower dimensional mesh from another generator.

Definition at line 29 of file RevolveGenerator.h.

Referenced by generate().

◆ _nums_azimuthal_intervals

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

Numbers of azimuthal mesh intervals in each azimuthal section.

Definition at line 57 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _preserve_volumes

const bool RevolveGenerator::_preserve_volumes
protected

Volume preserving function is optional.

Definition at line 60 of file RevolveGenerator.h.

Referenced by generate().

◆ _radius_correction_factor

Real RevolveGenerator::_radius_correction_factor
protected

Radius correction factor.

Definition at line 90 of file RevolveGenerator.h.

Referenced by generate(), and nodeModification().

◆ _revolving_angles

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

Angles of revolution delineating each azimuthal section.

Definition at line 38 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _start_boundary

boundary_id_type RevolveGenerator::_start_boundary
protected

Boundary ID of the starting boundary.

Definition at line 66 of file RevolveGenerator.h.

Referenced by generate().

◆ _subdomain_swap_pairs

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

Easier to work with version of _sudomain_swaps.

Definition at line 72 of file RevolveGenerator.h.

Referenced by generate(), and RevolveGenerator().

◆ _subdomain_swaps

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

Subdomains to swap out for each azimuthal section.

Definition at line 41 of file RevolveGenerator.h.

Referenced by RevolveGenerator().

◆ _unit_angles

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

Unit angles of all azimuthal sections of revolution.

Definition at line 84 of file RevolveGenerator.h.

Referenced by generate().


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