Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "SymmetryTransformGenerator.h" 11 : #include "CastUniquePointer.h" 12 : #include "MooseUtils.h" 13 : #include "libmesh/mesh_modification.h" 14 : 15 : registerMooseObject("MooseApp", SymmetryTransformGenerator); 16 : 17 : InputParameters 18 14285 : SymmetryTransformGenerator::validParams() 19 : { 20 14285 : InputParameters params = MeshGenerator::validParams(); 21 : 22 14285 : params.addClassDescription("Applies a symmetry transformation to the entire mesh."); 23 14285 : params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify"); 24 14285 : params.addRequiredParam<RealEigenVector>( 25 : "mirror_point", 26 : "Any point on the plane/line over which the reflection operation will be done"); 27 14285 : params.addRequiredParam<RealEigenVector>( 28 : "mirror_normal_vector", 29 : "A vector normal to (perpendicular/orthogonal to) the plane/line over which the " 30 : "reflection operation will be done"); 31 : 32 14285 : return params; 33 0 : } 34 : 35 10 : SymmetryTransformGenerator::SymmetryTransformGenerator(const InputParameters & parameters) 36 : : MeshGenerator(parameters), 37 10 : _input(getMesh("input")), 38 10 : _mirror_point_vector(getParam<RealEigenVector>("mirror_point")), 39 20 : _mirror_normal_vector(getParam<RealEigenVector>("mirror_normal_vector")) 40 : { 41 : // enforce 3D coordinates 42 10 : if (_mirror_point_vector.size() != 3) 43 0 : paramError("mirror_point", 44 : "mirror_point should be a 3d vector, but only ", 45 0 : _mirror_point_vector.size(), 46 : "components were specified."); 47 : 48 10 : if (_mirror_normal_vector.size() != 3) 49 0 : paramError("mirror_point", 50 : " mirror_normal_vector should be a 3d vector, but only ", 51 0 : _mirror_normal_vector.size(), 52 : "components were specified."); 53 : 54 : // convert normal vector into a unit normal vector 55 10 : const auto norm = _mirror_normal_vector.norm(); 56 10 : if (!MooseUtils::absoluteFuzzyEqual(norm, 1)) 57 0 : mooseInfo("Input normal plane vector was not normalized, normalization was performed"); 58 10 : _mirror_normal_vector = _mirror_normal_vector / norm; 59 10 : } 60 : 61 : std::unique_ptr<MeshBase> 62 10 : SymmetryTransformGenerator::generate() 63 : { 64 10 : std::unique_ptr<MeshBase> mesh = std::move(_input); 65 : 66 : // https://en.wikipedia.org/wiki/Transformation_matrix#Reflection_2 67 : // variables renamed for readability and verification 68 10 : const auto a = _mirror_normal_vector[0], b = _mirror_normal_vector[1], 69 10 : c = _mirror_normal_vector[2], 70 10 : d = ((RealEigenVector)(-1 * _mirror_point_vector.transpose() * _mirror_normal_vector))( 71 10 : 0); 72 : 73 10 : RealEigenMatrix mirror_transformation(4, 4); 74 10 : mirror_transformation << (1 - 2 * a * a), (-2 * a * b), (-2 * a * c), (-2 * a * d), (-2 * a * b), 75 10 : (1 - 2 * b * b), (-2 * b * c), (-2 * b * d), (-2 * a * c), (-2 * b * c), (1 - 2 * c * c), 76 10 : (-2 * c * d), (0), (0), (0), (1); 77 : 78 250 : for (auto & node : mesh->node_ptr_range()) 79 : { 80 120 : RealEigenVector location_vec(4); 81 120 : location_vec << (*node)(0), (*node)(1), (*node)(2), 1; 82 120 : location_vec = mirror_transformation * location_vec; 83 : 84 120 : (*node)(0) = location_vec(0); 85 120 : (*node)(1) = location_vec(1); 86 120 : (*node)(2) = location_vec(2); 87 130 : } 88 : 89 : // Fix flipped orientation from the symmetry 90 10 : MeshTools::Modification::orient_elements(*mesh); 91 : 92 20 : return mesh; 93 10 : }