MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
nurbs_curveint.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, 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// NURBS CurveInt Miniapp: Interpolate a Curve in a NURBS Patch
14// ------------------------------------------------------------
15//
16// Compile with: make nurbs_curveint
17//
18// Sample runs: nurbs_curveint -uw -n 9
19// nurbs_curveint -nw -n 9
20//
21// Description: This example code demonstrates the use of MFEM to interpolate a
22// curve in a NURBS patch. We first define a square shaped NURBS
23// patch. We then interpolate a sine function on the bottom
24// edge. The results can be viewed in VisIt.
25//
26// We use curve interpolation for curves with all weights being 1,
27// B-splines, and curves with not all weights being 1, NURBS. The
28// spacing in both cases is chosen differently.
29
30#include "mfem.hpp"
31#include <fstream>
32#include <iostream>
33
34using namespace std;
35using namespace mfem;
36
37KnotVector *UniformKnotVector(int order, int ncp)
38{
39 if (order>=ncp)
40 {
41 mfem_error("UniformKnotVector: ncp should be at least order + 1");
42 }
43 KnotVector *kv = new KnotVector(order, ncp);
44
45 for (int i = 0; i < order+1; i++)
46 {
47 (*kv)[i] = 0.0;
48 }
49 for (int i = order+1; i < ncp; i++)
50 {
51 (*kv)[i] = (i-order)/real_t(ncp-order);
52 }
53 for (int i = ncp ; i < ncp + order + 1; i++)
54 {
55 (*kv)[i] = 1.0;
56 }
57 return kv;
58}
59
60int main(int argc, char *argv[])
61{
62 // Parse command-line options.
63 OptionsParser args(argc, argv);
64
65 real_t l = 1.0;
66 real_t a = 0.1;
67 int ncp = 9;
68 int order = 2;
69 bool ifbspline = true;
70 bool visualization = true;
71 bool visit = true;
72
73 args.AddOption(&l, "-l", "--box-side-length",
74 "Height and width of the box");
75 args.AddOption(&a, "-a", "--sine-ampl",
76 "Amplitude of the fitted sine function.");
77 args.AddOption(&ncp, "-n", "--ncp",
78 "Number of control points used over four box sides.");
79 args.AddOption(&order, "-o", "--order",
80 "Order of the NURBSPatch");
81 args.AddOption(&ifbspline, "-uw", "--unit-weight", "-nw",
82 "--non-unit-weight",
83 "Use a unit-weight for B-splines (default) or not: for general NURBS");
84 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
85 "--no-visualization",
86 "Enable or disable GLVis visualization. This is a dummy option to enable testing.");
87 args.AddOption(&visit, "-visit", "--visit", "-no-visit", "--no-visit",
88 "Enable or disable VisIt visualization.");
89
90 // Parse and print command line options
91 args.Parse();
92 if (!args.Good())
93 {
94 args.PrintUsage(cout);
95 return 1;
96 }
97 args.PrintOptions(cout);
98
99 if (order < 2 && ifbspline == false)
100 {
101 mfem_error("For a non unity weight, the order should be at least 2.");
102 }
103
104 KnotVector *kv_o1 = UniformKnotVector(1, 2);
105 KnotVector *kv = UniformKnotVector(order, ncp);
106
107 // 1. Create a box shaped NURBS patch
108 NURBSPatch patch(kv_o1, kv_o1, 3);
109
110 // Set weights
111 for (int j = 0; j < 2; j++)
112 for (int i = 0; i < 2; i++)
113 {
114 patch(i,j,2) = 1.0;
115 }
116
117 // Define patch corners which are box corners
118 patch(0,0,0) = -0.5*l;
119 patch(0,0,1) = -0.5*l;
120
121 patch(1,0,0) = 0.5*l;
122 patch(1,0,1) = -0.5*l;
123
124 patch(0,1,0) = -0.5*l;
125 patch(0,1,1) = 0.5*l;
126
127 patch(1,1,0) = 0.5*l;
128 patch(1,1,1) = 0.5*l;
129
130 // Refine direction which has fitting
131 if (!ifbspline)
132 {
133 // We alter the weight for demonstration purposes to a random value. This
134 // is not necessary for general curve fitting.
135 patch.DegreeElevate(0, 1);
136 patch(1,0,2) = sqrt(2)/2;
137 patch.DegreeElevate(0, order-kv_o1->GetOrder()-1);
138 }
139 else
140 {
141 patch.DegreeElevate(0, order-kv_o1->GetOrder());
142 }
143 patch.KnotInsert(0, *kv);
144
145 // We locate the control points at the demko points.
146 Vector u(ncp),x(ncp),interp(ncp);
147 kv->GetDemko(u);
148
149 for (int i = 0; i < ncp; i++)
150 {
151 x[i] = (u[i] - 0.5)*l;
152 }
153 kv->GetInterpolant(x,u,interp);
154 for (int i = 0; i < ncp; i++)
155 {
156 patch(i,0,0) = interp[i];
157 }
158
159 for (int i = 0; i < ncp; i++)
160 {
161 x[i] = a * sin(u[i]*2*M_PI)-0.5*l;
162 }
163 kv->GetInterpolant(x,u,interp);
164 for (int i = 0; i < ncp; i++)
165 {
166 patch(i,0,1) = interp[i];
167 }
168
169 if (!ifbspline)
170 {
171 // Convert to homogeneous coordinates. FindInterpolant returns
172 // Cartesian coordinates.
173 for (int i = 0; i < ncp; i++)
174 {
175 patch(i,0,0) *= patch(i,0,2);
176 patch(i,0,1) *= patch(i,0,2);
177 }
178 }
179
180 // Refinement in curve interpolation direction
181 patch.DegreeElevate(1, order-kv_o1->GetOrder());
182 patch.KnotInsert(1, *kv);
183
184 // 3. Open and write mesh output file
185 string mesh_file("sin-fit.mesh");
186 ofstream output(mesh_file.c_str());
187
188 output<<"MFEM NURBS mesh v1.0"<<endl;
189 output<< endl << "# Square nurbs mesh with a sine fitted at its bottom edge" <<
190 endl << endl;
191 output<< "dimension"<<endl;
192 output<< 2 <<endl;
193 output<< endl;
194
195 output<<"elements"<<endl;
196 output<<"1"<<endl;
197 output<<"1 3 0 1 2 3"<<endl;
198 output<<endl;
199
200 output<<"boundary"<<endl;
201 output<<"0"<<endl;
202 output<<endl;
203
204 output << "edges" <<endl;
205 output << "4" <<endl;
206 output << "0 0 1"<<endl;
207 output << "0 3 2"<<endl;
208 output << "1 0 3"<<endl;
209 output << "1 1 2"<<endl;
210 output<<endl;
211
212 output << "vertices" << endl;
213 output << 4 << endl;
214
215 output<<"patches"<<endl;
216 output<<endl;
217
218 output << "# Patch 1 " << endl;
219 patch.Print(output);
220 output.close();
221
222 // Print mesh info to screen
223 cout << "=========================================================="<< endl;
224 cout << " Attempting to read mesh: " <<mesh_file.c_str()<< endl ;
225 cout << "=========================================================="<< endl;
226 Mesh *mesh = new Mesh(mesh_file.c_str(), 1, 1);
227 mesh->PrintInfo();
228
229 if (visit)
230 {
231 // Print mesh to file for visualization
232 VisItDataCollection dc = VisItDataCollection("mesh", mesh);
233 dc.SetPrefixPath("CurveInt");
234 dc.SetCycle(0);
235 dc.SetTime(0.0);
236 dc.Save();
237 }
238
239 delete mesh;
240 delete kv_o1;
241 delete kv;
242
243 return 0;
244}
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
A vector of knots in one dimension, with B-spline basis functions of a prescribed order.
Definition nurbs.hpp:38
void GetInterpolant(Array< Vector * > &x, const Vector &u, bool reuse_inverse=false) const
Global curve interpolation through the points x (overwritten) at the knot location u....
Definition nurbs.cpp:1092
real_t GetDemko(int i) const
Definition nurbs.cpp:281
int GetOrder() const
Return the order.
Definition nurbs.hpp:114
Mesh data type.
Definition mesh.hpp:67
virtual void PrintInfo(std::ostream &os=mfem::out)
In serial, this method calls PrintCharacteristics(). In parallel, additional information about the pa...
Definition mesh.hpp:2699
A NURBS patch can be 1D, 2D, or 3D, and is defined as a tensor product of KnotVectors.
Definition nurbs.hpp:324
void KnotInsert(int dir, const KnotVector &knot)
Insert any new knots from knot in direction dir. If the order of knot is higher than the current orde...
Definition nurbs.cpp:1714
void Print(std::ostream &os) const
Writes KnotVectors and data to the stream os.
Definition nurbs.cpp:1484
void DegreeElevate(int dir, int t)
Increase the order in direction dir by t >= 0.
Definition nurbs.cpp:2082
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
Data collection with VisIt I/O routines.
void Save() override
Save the collection and a VisIt root file.
int main()
real_t a
Definition lissajous.cpp:41
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
void mfem_error(const char *msg)
Definition error.cpp:154
float real_t
Definition config.hpp:46
STL namespace.
KnotVector * UniformKnotVector(int order, int ncp)