MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
nurbs_curveint.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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 // 2. Interpolation process
131 Array<Vector*> xy(2);
132 xy[0] = new Vector();
133 xy[1] = new Vector();
134 Vector xi_args, u_args;
135 Array<int> i_args;
136 xy[0]->SetSize(ncp); xy[1]->SetSize(ncp);
137
138 // Refine direction which has fitting
139 if (!ifbspline)
140 {
141 // We alter the weight for demonstration purposes to a random value. This
142 // is not necessary for general curve fitting.
143 patch.DegreeElevate(0, 1);
144 patch(1,0,2) = sqrt(2)/2;
145 patch.DegreeElevate(0, order-kv_o1->GetOrder()-1);
146 }
147 else
148 {
149 patch.DegreeElevate(0, order-kv_o1->GetOrder());
150 }
151 patch.KnotInsert(0, *kv);
152
153 // We locate the control points at the location of the maxima of the
154 // knot vectors. This works very well for patches with unit weights.
155 kv->FindMaxima(i_args,xi_args, u_args);
156
157 for (int i = 0; i < ncp; i++)
158 {
159 (*xy[0])[i] = u_args[i]*l;
160 (*xy[1])[i] = a * sin((*xy[0])[i]/l*2*M_PI)-0.5*l;
161 (*xy[0])[i] -= 0.5*l;
162 }
163
164 kv->FindInterpolant(xy);
165
166 // Apply interpolation to patch
167 for (int i = 0; i < ncp; i++)
168 {
169 patch(i,0,0) = (*xy[0])[i];
170 patch(i,0,1) = (*xy[1])[i];
171 }
172
173 if (!ifbspline)
174 {
175 // Convert to homogeneous coordinates. FindInterpolant returns
176 // Cartesian coordinates.
177 for (int i = 0; i < ncp; i++)
178 {
179 patch(i,0,0) *= patch(i,0,2);
180 patch(i,0,1) *= patch(i,0,2);
181 }
182 }
183
184 // Refinement in curve interpolation direction
185 patch.DegreeElevate(1, order-kv_o1->GetOrder());
186 patch.KnotInsert(1, *kv);
187
188 // 3. Open and write mesh output file
189 string mesh_file("sin-fit.mesh");
190 ofstream output(mesh_file.c_str());
191
192 output<<"MFEM NURBS mesh v1.0"<<endl;
193 output<< endl << "# Square nurbs mesh with a sine fitted at its bottom edge" <<
194 endl << endl;
195 output<< "dimension"<<endl;
196 output<< 2 <<endl;
197 output<< endl;
198
199 output<<"elements"<<endl;
200 output<<"1"<<endl;
201 output<<"1 3 0 1 2 3"<<endl;
202 output<<endl;
203
204 output<<"boundary"<<endl;
205 output<<"0"<<endl;
206 output<<endl;
207
208 output << "edges" <<endl;
209 output << "4" <<endl;
210 output << "0 0 1"<<endl;
211 output << "0 3 2"<<endl;
212 output << "1 0 3"<<endl;
213 output << "1 1 2"<<endl;
214 output<<endl;
215
216 output << "vertices" << endl;
217 output << 4 << endl;
218
219 output<<"patches"<<endl;
220 output<<endl;
221
222 output << "# Patch 1 " << endl;
223 patch.Print(output);
224 output.close();
225
226 // Print mesh info to screen
227 cout << "=========================================================="<< endl;
228 cout << " Attempting to read mesh: " <<mesh_file.c_str()<< endl ;
229 cout << "=========================================================="<< endl;
230 Mesh *mesh = new Mesh(mesh_file.c_str(), 1, 1);
231 mesh->PrintInfo();
232
233 if (visit)
234 {
235 // Print mesh to file for visualization
236 VisItDataCollection dc = VisItDataCollection("mesh", mesh);
237 dc.SetPrefixPath("CurveInt");
238 dc.SetCycle(0);
239 dc.SetTime(0.0);
240 dc.Save();
241 }
242
243 delete mesh;
244 delete kv_o1;
245 delete kv;
246 delete xy[0];
247 delete xy[1];
248
249 return 0;
250}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:697
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.
void FindMaxima(Array< int > &ks, Vector &xi, Vector &u) const
Definition nurbs.cpp:482
void FindInterpolant(Array< Vector * > &x)
Definition nurbs.cpp:543
int GetOrder() const
Definition nurbs.hpp:53
Mesh data type.
Definition mesh.hpp:56
virtual void PrintInfo(std::ostream &os=mfem::out)
In serial, this method calls PrintCharacteristics(). In parallel, additional information about the pa...
Definition mesh.hpp:2367
void KnotInsert(int dir, const KnotVector &knot)
Insert knots from knot determined by Difference, in direction dir.
Definition nurbs.cpp:1001
void Print(std::ostream &os) const
Definition nurbs.cpp:836
void DegreeElevate(int dir, int t)
Definition nurbs.cpp:1368
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:80
Data collection with VisIt I/O routines.
virtual void Save() override
Save the collection and a VisIt root file.
int main()
real_t a
Definition lissajous.cpp:41
void mfem_error(const char *msg)
Definition error.cpp:154
float real_t
Definition config.hpp:43
KnotVector * UniformKnotVector(int order, int ncp)