forked from idaholab/moose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SymmetryTransformGenerator.C
113 lines (96 loc) · 4.52 KB
/
SymmetryTransformGenerator.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
#include "SymmetryTransformGenerator.h"
#include "CastUniquePointer.h"
#include "MooseUtils.h"
registerMooseObject("MooseApp", SymmetryTransformGenerator);
InputParameters
SymmetryTransformGenerator::validParams()
{
InputParameters params = MeshGenerator::validParams();
params.addClassDescription("Applies a symmetry transformation to the entire mesh.");
params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
params.addRequiredParam<RealEigenVector>(
"mirror_point",
"Any point on the plane/line over which the reflection operation will be done");
params.addRequiredParam<RealEigenVector>(
"mirror_normal_vector",
"A vector normal to (perpendicular/orthogonal to) the plane/line over which the "
"reflection operation will be done");
params.addParam<std::vector<std::vector<std::string>>>(
"symmetry_stitch_sideset",
std::vector<std::vector<std::string>>(),
"Pairs of boundaries to be stitched together between the 1st mesh in inputs and each "
"consecutive mesh. This parameter will often be the name of the sideset on the symmetry axis"
". If not provided, the stitching is not performed.");
return params;
}
SymmetryTransformGenerator::SymmetryTransformGenerator(const InputParameters & parameters)
: MeshGenerator(parameters),
_input(getMesh("input")),
_mirror_point_vector(getParam<RealEigenVector>("mirror_point")),
_mirror_normal_vector(getParam<RealEigenVector>("mirror_normal_vector")),
_stitch_boundaries_pairs(
getParam<std::vector<std::vector<std::string>>>("symmetry_stitch_sideset"))
{
// enforce 3D coordinates
if (_mirror_point_vector.size() != 3)
mooseError("mirror_point should be a 3d vector, but only ",
_mirror_point_vector.size(),
"components were specified.");
if (_mirror_normal_vector.size() != 3)
mooseError(" mirror_normal_vector should be a 3d vector, but only ",
_mirror_normal_vector.size(),
"components were specified.");
// convert normal vector into a unit normal vector
const auto norm = _mirror_normal_vector.norm();
if (!MooseUtils::absoluteFuzzyEqual(norm, 1))
mooseInfo("Input normal plane vector was not normalized, normalization was performed");
_mirror_normal_vector = _mirror_normal_vector / norm;
// Add stitch sub mesh generator if stitching is requested
if (_stitch_boundaries_pairs.size() > 0)
{
auto params = _app.getFactory().getValidParams("StitchedMeshGenerator");
// order of vector elements matters for this generator
// here order by: original mesh first, our custom mesh second
params.set<std::vector<MeshGeneratorName>>("inputs") = {getParam<MeshGeneratorName>("input"),
name()};
params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") =
_stitch_boundaries_pairs;
// stitch the mirrored mesh and the original mesh
addMeshSubgenerator("StitchedMeshGenerator", name() + "_stitchedMeshGenerator", params);
}
}
std::unique_ptr<MeshBase>
SymmetryTransformGenerator::generate()
{
std::unique_ptr<MeshBase> mesh = std::move(_input);
// https://en.wikipedia.org/wiki/Transformation_matrix#Reflection_2
// variables renamed for readability and verification
const auto a = _mirror_normal_vector[0], b = _mirror_normal_vector[1],
c = _mirror_normal_vector[2],
d = ((RealEigenVector)(-1 * _mirror_point_vector.transpose() * _mirror_normal_vector))(
0);
RealEigenMatrix mirror_transformation(4, 4);
mirror_transformation << (1 - 2 * a * a), (-2 * a * b), (-2 * a * c), (-2 * a * d), (-2 * a * b),
(1 - 2 * b * b), (-2 * b * c), (-2 * b * d), (-2 * a * c), (-2 * b * c), (1 - 2 * c * c),
(-2 * c * d), (0), (0), (0), (1);
for (auto & node : mesh->node_ptr_range())
{
RealEigenVector location_vec(4);
location_vec << (*node)(0), (*node)(1), (*node)(2), 1;
location_vec = mirror_transformation * location_vec;
(*node)(0) = location_vec(0);
(*node)(1) = location_vec(1);
(*node)(2) = location_vec(2);
}
// Fix flipped orientation from the symmetry
MeshTools::Modification::orient_elements(*mesh);
return mesh;
}