MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
toroid.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11//
12// ------------------------------------------------
13// Toroid Miniapp: Generate simple toroidal meshes
14// ------------------------------------------------
15//
16// This miniapp generates two types of toroidal meshes; one with triangular
17// cross sections and one with square cross sections. It works by defining a
18// stack of individual elements and bending them so that the bottom and top of
19// the stack can be joined to form a torus. The stack can also be twisted so
20// that the vertices of the bottom and top can be joined with any integer
21// offset.
22//
23// Compile with: make toroid
24//
25// Sample runs: toroid
26// toroid -nphi 6
27// toroid -ns 1
28// toroid -ns 0 -t0 -30
29// toroid -R 2 -r 1 -ns 3
30// toroid -R 2 -r 1 -ns -3
31// toroid -R 2 -r 1 -ns 3 -e 1
32// toroid -R 2 -r 1 -ns 3 -e 1 -rs 1
33// toroid -nphi 2 -ns 10 -e 1 -o 4
34
35#include "mfem.hpp"
36#include <fstream>
37#include <iostream>
38
39using namespace std;
40using namespace mfem;
41
42static Element::Type el_type_ = Element::WEDGE;
43static int order_ = 3;
44static int nphi_ = 8;
45static int ns_ = 0;
46static real_t R_ = 1.0;
47static real_t r_ = 0.2;
48static real_t theta0_ = 0.0;
49
50void pts(int iphi, int t, real_t x[]);
51void trans(const Vector &x, Vector &p);
52
53int main(int argc, char *argv[])
54{
55 int ser_ref_levels = 0;
56 int el_type = 0;
57 bool dg_mesh = false;
58 int visport = 19916;
59 bool visualization = true;
60
61 OptionsParser args(argc, argv);
62 args.AddOption(&nphi_, "-nphi", "--num-elements-phi",
63 "Number of elements in phi-direction.");
64 args.AddOption(&ns_, "-ns", "--num-shifts",
65 "Number of shifts.");
66 args.AddOption(&order_, "-o", "--mesh-order",
67 "Order (polynomial degree) of the mesh elements.");
68 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
69 "Number of times to refine the mesh uniformly in serial.");
70 args.AddOption(&R_, "-R", "--major-radius",
71 "Major radius of the torus.");
72 args.AddOption(&r_, "-r", "--minor-radius",
73 "Minor radius of the torus.");
74 args.AddOption(&theta0_, "-t0", "--initial-angle",
75 "Starting angle of the cross section (in degrees).");
76 args.AddOption(&el_type, "-e", "--element-type",
77 "Element type: 0 - Wedge, 1 - Hexahedron.");
78 args.AddOption(&dg_mesh, "-dm", "--discont-mesh", "-cm", "--cont-mesh",
79 "Use discontinuous or continuous space for the mesh nodes.");
80 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
81 "--no-visualization",
82 "Enable or disable GLVis visualization.");
83 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
84 args.Parse();
85 if (!args.Good())
86 {
87 args.PrintUsage(cout);
88 return 1;
89 }
90 args.PrintOptions(cout);
91
92 // The output mesh could be hexahedra or prisms
93 el_type_ = (el_type == 0) ? Element::WEDGE : Element::HEXAHEDRON;
94 if (el_type_ != Element::WEDGE && el_type_ != Element::HEXAHEDRON)
95 {
96 cout << "Unsupported element type" << endl;
97 exit(1);
98 }
99
100 // Determine the number of nodes in the cross section
101 int nnode = (el_type_ == Element::WEDGE)? 3:4;
102 int nshift = (ns_ >= 0) ? 0 : (nnode * (1 - ns_ / nnode));
103
104 // Convert initial angle from degrees to radians
105 theta0_ *= M_PI / 180.0;
106
107 // Define an empty mesh
108 Mesh *mesh;
109 mesh = new Mesh(3, nnode * (nphi_+1), nphi_);
110
111 // Add vertices for a stack of elements
112 real_t c[3];
113 for (int i=0; i<=nphi_; i++)
114 {
115 c[0] = 0.0; c[1] = 0.0; c[2] = i;
116 mesh->AddVertex(c);
117
118 c[0] = 1.0;
119 mesh->AddVertex(c);
120
121 if (el_type_ == Element::HEXAHEDRON)
122 {
123 c[0] = 1.0; c[1] = 1.0;
124 mesh->AddVertex(c);
125 }
126
127 c[0] = 0.0; c[1] = 1.0;
128 mesh->AddVertex(c);
129 }
130
131 // Add Elements of the desired type
132 {
133 int v[8];
134 for (int i=0; i < nphi_; i++)
135 {
136 if (el_type_ == Element::WEDGE)
137 {
138 for (int j = 0; j < 6; j++) { v[j] = 3*i+j; }
139 mesh->AddWedge(v);
140 }
141 else
142 {
143 for (int j = 0; j < 8; j++) { v[j] = 4*i+j; }
144 mesh->AddHex(v);
145 }
146 }
147 }
148 mesh->FinalizeTopology();
149
150 // Promote to high order mesh and transform into a torus shape
151 if (order_ > 1)
152 {
153 mesh->SetCurvature(order_, true, 3, Ordering::byVDIM);
154 }
155 mesh->Transform(trans);
156
157 // Stitch the ends of the stack together
158 {
159 Array<int> v2v(mesh->GetNV());
160 for (int i = 0; i < v2v.Size() - nnode; i++)
161 {
162 v2v[i] = i;
163 }
164 // identify vertices at the extremes of the stack of prisms
165 for (int i=0; i<nnode; i++)
166 {
167 v2v[v2v.Size() - nnode + i] = (nshift + ns_ + i) % nnode;
168 }
169 // renumber elements
170 for (int i = 0; i < mesh->GetNE(); i++)
171 {
172 Element *el = mesh->GetElement(i);
173 int *v = el->GetVertices();
174 int nv = el->GetNVertices();
175 for (int j = 0; j < nv; j++)
176 {
177 v[j] = v2v[v[j]];
178 }
179 }
180 // renumber boundary elements
181 for (int i = 0; i < mesh->GetNBE(); i++)
182 {
183 Element *el = mesh->GetBdrElement(i);
184 int *v = el->GetVertices();
185 int nv = el->GetNVertices();
186 for (int j = 0; j < nv; j++)
187 {
188 v[j] = v2v[v[j]];
189 }
190 }
191 mesh->RemoveUnusedVertices();
193 }
194 if (order_ > 1)
195 {
196 mesh->SetCurvature(order_, dg_mesh, 3, Ordering::byVDIM);
197 }
198
199 // Refine the mesh if desired
200 for (int lev = 0; lev < ser_ref_levels; lev++)
201 {
202 mesh->UniformRefinement();
203 }
204
205 // Output the resulting mesh to a file
206 {
207 ostringstream oss;
208 if (el_type_ == Element::WEDGE)
209 {
210 oss << "toroid-wedge";
211 }
212 else
213 {
214 oss << "toroid-hex";
215 }
216 oss << "-o" << order_ << "-s" << ns_;
217 if (ser_ref_levels > 0)
218 {
219 oss << "-r" << ser_ref_levels;
220 }
221 oss << ".mesh";
222 ofstream ofs(oss.str().c_str());
223 ofs.precision(8);
224 mesh->Print(ofs);
225 ofs.close();
226 }
227
228 // Output the resulting mesh to GLVis
229 if (visualization)
230 {
231 char vishost[] = "localhost";
232 socketstream sol_sock(vishost, visport);
233 sol_sock.precision(8);
234 sol_sock << "mesh\n" << *mesh << flush;
235 }
236
237 // Clean up and exit
238 delete mesh;
239 return 0;
240}
241
242void trans(const Vector &x, Vector &p)
243{
244 int nnode = (el_type_ == Element::WEDGE)? 3:4;
245
246 real_t phi = 2.0 * M_PI * x[2] / nphi_;
247 real_t theta = theta0_ + phi * ns_ / nnode;
248
249 real_t u = (1.5 * (x[0] + x[1]) - 1.0) * r_;
250 real_t v = sqrt(0.75) * (x[0] - x[1]) * r_;
251
252 if (el_type_ == Element::WEDGE)
253 {
254 u = (1.5 * (x[0] + x[1]) - 1.0) * r_;
255 v = sqrt(0.75) * (x[0] - x[1]) * r_;
256 }
257 else
258 {
259 u = M_SQRT2 * (x[1] - 0.5) * r_;
260 v = M_SQRT2 * (x[0] - 0.5) * r_;
261 }
262
263 p[0] = ( R_ + u * cos(theta) + v * sin(theta)) * cos(phi);
264 p[1] = ( R_ + u * cos(theta) + v * sin(theta)) * sin(phi);
265 p[2] = v * cos(theta) - u * sin(theta);
266}
int Size() const
Return the logical size of the array.
Definition array.hpp:147
Abstract data type element.
Definition element.hpp:29
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
Type
Constants for the classes derived from Element.
Definition element.hpp:41
virtual int GetNVertices() const =0
Mesh data type.
Definition mesh.hpp:64
int AddWedge(int v1, int v2, int v3, int v4, int v5, int v6, int attr=1)
Adds a wedge to the mesh given by 6 vertices v1 through v6.
Definition mesh.cpp:1993
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Definition mesh.hpp:1339
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition mesh.cpp:3362
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Definition mesh.hpp:2433
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
Definition mesh.cpp:1873
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1354
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
Definition mesh.hpp:1279
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
Adds a hexahedron to the mesh given by 8 vertices v1 through v8.
Definition mesh.cpp:2021
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Definition mesh.cpp:6484
void Transform(void(*f)(const Vector &, Vector &))
Definition mesh.cpp:13146
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
void RemoveInternalBoundaries()
Definition mesh.cpp:13304
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
Definition mesh.cpp:13197
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
Vector data type.
Definition vector.hpp:82
int main()
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
float real_t
Definition config.hpp:43
const char vishost[]
real_t p(const Vector &x, real_t t)
void trans(const Vector &x, Vector &p)
Definition toroid.cpp:242
void pts(int iphi, int t, real_t x[])