MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
mobius-strip.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// Mobius Strip Miniapp: Generate Mobius strip meshes
14// ---------------------------------------------------
15//
16// This miniapp generates various Mobius strip-like surface meshes. It is a good
17// way to generate complex surface meshes. Manipulating the mesh topology and
18// performing mesh transformation are demonstrated. The mobius-strip mesh in the
19// data/ directory was generated with this miniapp.
20//
21// Compile with: make mobius-strip
22//
23// Sample runs: mobius-strip
24// mobius-strip -t 4.5 -nx 16
25// mobius-strip -c 1 -t 1
26// mobius-strip -c 1 -t 4 -nx 16
27// mobius-strip -c 0 -t 0.75
28
29#include "mfem.hpp"
30#include <fstream>
31#include <iostream>
32
33using namespace std;
34using namespace mfem;
35
37void mobius_trans(const Vector &x, Vector &p);
38
39int main(int argc, char *argv[])
40{
41 const char *new_mesh_file = "mobius-strip.mesh";
42 int nx = 8;
43 int ny = 2;
44 int order = 3;
45 int close_strip = 2;
46 bool dg_mesh = false;
47 int visport = 19916;
48 bool visualization = true;
49
50 OptionsParser args(argc, argv);
51 args.AddOption(&new_mesh_file, "-m", "--mesh-out-file",
52 "Output Mesh file to write.");
53 args.AddOption(&nx, "-nx", "--num-elements-x",
54 "Number of elements in x-direction.");
55 args.AddOption(&ny, "-ny", "--num-elements-y",
56 "Number of elements in y-direction.");
57 args.AddOption(&order, "-o", "--mesh-order",
58 "Order (polynomial degree) of the mesh elements.");
59 args.AddOption(&close_strip, "-c", "--close-strip",
60 "How to close the strip: 0 - open, 1 - closed, 2 - twisted.");
61 args.AddOption(&dg_mesh, "-dm", "--discont-mesh", "-cm", "--cont-mesh",
62 "Use discontinuous or continuous space for the mesh nodes.");
63 args.AddOption(&num_twists, "-t", "--num-twists",
64 "Number of twists of the strip.");
65 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
66 "--no-visualization",
67 "Enable or disable GLVis visualization.");
68 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
69 args.Parse();
70 if (!args.Good())
71 {
72 args.PrintUsage(cout);
73 return 1;
74 }
75 args.PrintOptions(cout);
76
77 // The mesh could use quads (default) or triangles
79 // Element::Type el_type = Element::TRIANGLE;
80 Mesh mesh = Mesh::MakeCartesian2D(nx, ny, el_type, 1, 2*M_PI, 2.0);
81
82 mesh.SetCurvature(order, true, 3, Ordering::byVDIM);
83
84 if (close_strip)
85 {
86 Array<int> v2v(mesh.GetNV());
87 for (int i = 0; i < v2v.Size(); i++)
88 {
89 v2v[i] = i;
90 }
91 // identify vertices on vertical lines (with a flip)
92 for (int j = 0; j <= ny; j++)
93 {
94 int v_old = nx + j * (nx + 1);
95 int v_new = ((close_strip == 1) ? j : (ny - j)) * (nx + 1);
96 v2v[v_old] = v_new;
97 }
98 // renumber elements
99 for (int i = 0; i < mesh.GetNE(); i++)
100 {
101 Element *el = mesh.GetElement(i);
102 int *v = el->GetVertices();
103 int nv = el->GetNVertices();
104 for (int j = 0; j < nv; j++)
105 {
106 v[j] = v2v[v[j]];
107 }
108 }
109 // renumber boundary elements
110 for (int i = 0; i < mesh.GetNBE(); i++)
111 {
112 Element *el = mesh.GetBdrElement(i);
113 int *v = el->GetVertices();
114 int nv = el->GetNVertices();
115 for (int j = 0; j < nv; j++)
116 {
117 v[j] = v2v[v[j]];
118 }
119 }
122 }
123
125
126 if (!dg_mesh)
127 {
128 mesh.SetCurvature(order, false, 3, Ordering::byVDIM);
129 }
130
131 GridFunction &nodes = *mesh.GetNodes();
132 for (int i = 0; i < nodes.Size(); i++)
133 {
134 if (std::abs(nodes(i)) < 1e-12)
135 {
136 nodes(i) = 0.0;
137 }
138 }
139
140 ofstream ofs(new_mesh_file);
141 ofs.precision(8);
142 mesh.Print(ofs);
143 ofs.close();
144
145 if (visualization)
146 {
147 char vishost[] = "localhost";
148 socketstream sol_sock(vishost, visport);
149 sol_sock.precision(8);
150 sol_sock << "mesh\n" << mesh << flush;
151 }
152
153 return 0;
154}
155
156void mobius_trans(const Vector &x, Vector &p)
157{
158 real_t a = 1.0 + 0.5 * (x[1] - 1.0) * cos( num_twists * x[0] );
159
160 p.SetSize(3);
161 p[0] = a * cos( x[0] );
162 p[1] = a * sin( x[0] );
163 p[2] = 0.5 * (x[1] - 1.0) * sin( num_twists * x[0] );
164}
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
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Mesh data type.
Definition mesh.hpp:64
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Definition mesh.hpp:1339
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Definition mesh.hpp:2433
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
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
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 GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
Definition mesh.cpp:4471
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 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 a
Definition lissajous.cpp:41
void mobius_trans(const Vector &x, Vector &p)
real_t num_twists
float real_t
Definition config.hpp:43
const char vishost[]
real_t p(const Vector &x, real_t t)
std::array< int, NCMesh::MaxFaceNodes > nodes