45 Params2(
double r0,
double r1,
double a0,
double a1)
46 : r(r0), dr(r1 - r0),
a(a0), da(a1 - a0) {}
49 Mesh*
Make2D(
int nsteps,
double rstep,
double phi,
double aspect,
int order,
58 while (phi * rstep/2 / n * aspect > rstep) { n++; }
67 double prev_alpha = 0.0;
68 for (
int i = 0; i < n; i++)
70 double alpha = phi * (i+1) / n;
71 mesh->
AddVertex(r*cos(alpha), r*sin(alpha));
74 params.
Append(Params2(0, r, prev_alpha, alpha));
81 for (
int k = 1; k < nsteps; k++)
85 int prev_first = first;
90 if (phi * (r + prev_r)/2 / n * aspect < rstep * sqrt(2))
99 for (
int i = 0; i < n; i++)
101 double alpha = phi * (i+1) / n;
102 mesh->
AddVertex(r*cos(alpha), r*sin(alpha));
103 mesh->
AddQuad(prev_first+i, first+i, first+i+1, prev_first+i+1);
105 params.
Append(Params2(prev_r, r, prev_alpha, alpha));
119 for (
int i = 0; i < m; i++)
121 double alpha = phi * (2*i+1) / n;
122 int index = mesh->
AddVertex(prev_r*cos(alpha), prev_r*sin(alpha));
124 if (!i) { hang =
index; }
128 int a = prev_first,
b = first;
134 for (
int i = 0; i < m; i++)
136 int c = hang+i, e = a+1;
138 double alpha_half = phi * (2*i+1) / n;
139 int d = mesh->
AddVertex(r*cos(alpha_half), r*sin(alpha_half));
141 double alpha = phi * (2*i+2) / n;
142 int f = mesh->
AddVertex(r*cos(alpha), r*sin(alpha));
149 params.
Append(Params2(prev_r, r, prev_alpha, alpha_half));
150 params.
Append(Params2(prev_r, r, alpha_half, alpha));
158 for (
int i = 0; i < n; i++)
171 for (
int i = 0; i < blocks[0].one; i++)
174 new_params[i] = params[i];
178 for (
int i = 0; i < blocks.
Size()-1; i++)
180 int beg = blocks[i].one;
181 int width = blocks[i].two;
182 int height = (blocks[i+1].one - blocks[i].one) / width;
186 for (
int j = 0, k = 0; j < coords.
Size(); k++, j += 2)
188 int sfc_index = ((i & 1) ? coords[j] : (width-1 - coords[j]))
190 int old_index = beg + sfc_index;
192 ordering[old_index] = beg + k;
193 new_params[beg + k] = params[old_index];
213 MFEM_ASSERT(params.
Size() == mesh->
GetNE(),
"");
215 for (
int i = 0; i < mesh->
GetNE(); i++)
217 const Params2 &par = params[i];
222 for (
int j = 0; j < dofs.
Size(); j++)
227 r = par.r + ir[j].x * par.dr;
228 a = par.a + ir[j].y * par.da;
232 double rr = ir[j].x + ir[j].y;
233 if (std::abs(rr) < 1e-12) {
continue; }
234 r = par.r + rr * par.dr;
235 a = par.a + ir[j].y/rr * par.da;
237 (*nodes)(fes->
DofToVDof(dofs[j], 0)) = r*cos(a);
238 (*nodes)(fes->
DofToVDof(dofs[j], 1)) = r*sin(a);
249 const double pi2 = M_PI / 2;
258 Params3(
double r0,
double r1,
259 double u1,
double v1,
double u2,
double v2,
double u3,
double v3)
260 : r(r0), dr(r1 - r0), u1(u1), u2(u2), u3(u3), v1(v1), v2(v2), v3(v3) {}
268 int GetMidVertex(
int v1,
int v2,
double r,
double u,
double v,
bool hanging,
271 int vmid = hash.
FindId(v1, v2);
274 vmid = hash.
GetId(v1, v2);
276 double w = 1.0 - u - v;
277 double q = r / sqrt(u*u + v*v + w*w);
282 hash[vmid].id =
index;
284 return hash[vmid].id;
287 void MakeLayer(
int vx1,
int vy1,
int vz1,
int vx2,
int vy2,
int vz2,
int level,
288 double r1,
double r2,
double u1,
double v1,
double u2,
double v2,
289 double u3,
double v3,
bool bnd1,
bool bnd2,
bool bnd3,
bool bnd4,
294 mesh->
AddWedge(vx1, vy1, vz1, vx2, vy2, vz2);
296 if (bnd1) { mesh->
AddBdrQuad(vx1, vy1, vy2, vx2, 1); }
297 if (bnd2) { mesh->
AddBdrQuad(vy1, vz1, vz2, vy2, 2); }
298 if (bnd3) { mesh->
AddBdrQuad(vz1, vx1, vx2, vz2, 3); }
301 params.
Append(Params3(r1, r2, u1, v1, u2, v2, u3, v3));
305 double u12 = (u1+u2)/2, v12 = (v1+v2)/2;
306 double u23 = (u2+u3)/2, v23 = (v2+v3)/2;
307 double u31 = (u3+u1)/2, v31 = (v3+v1)/2;
309 bool hang = (level == 1);
311 int vxy1 =
GetMidVertex(vx1, vy1, r1, u12, v12, hang, mesh, hash);
312 int vyz1 =
GetMidVertex(vy1, vz1, r1, u23, v23, hang, mesh, hash);
313 int vxz1 =
GetMidVertex(vx1, vz1, r1, u31, v31, hang, mesh, hash);
314 int vxy2 =
GetMidVertex(vx2, vy2, r2, u12, v12,
false, mesh, hash);
315 int vyz2 =
GetMidVertex(vy2, vz2, r2, u23, v23,
false, mesh, hash);
316 int vxz2 =
GetMidVertex(vx2, vz2, r2, u31, v31,
false, mesh, hash);
318 MakeLayer(vx1, vxy1, vxz1, vx2, vxy2, vxz2, level-1,
319 r1, r2, u1, v1, u12, v12, u31, v31,
320 bnd1,
false, bnd3, bnd4, mesh, hash, params);
321 MakeLayer(vxy1, vy1, vyz1, vxy2, vy2, vyz2, level-1,
322 r1, r2, u12, v12, u2, v2, u23, v23,
323 bnd1, bnd2,
false, bnd4, mesh, hash, params);
324 MakeLayer(vxz1, vyz1, vz1, vxz2, vyz2, vz2, level-1,
325 r1, r2, u31, v31, u23, v23, u3, v3,
326 false, bnd2, bnd3, bnd4, mesh, hash, params);
327 MakeLayer(vyz1, vxz1, vxy1, vyz2, vxz2, vxy2, level-1,
328 r1, r2, u23, v23, u31, v31, u12, v12,
329 false,
false,
false, bnd4, mesh, hash, params);
333 void MakeCenter(
int origin,
int vx,
int vy,
int vz,
int level,
double r,
334 double u1,
double v1,
double u2,
double v2,
double u3,
double v3,
335 bool bnd1,
bool bnd2,
bool bnd3,
bool bnd4,
340 mesh->
AddTet(origin, vx, vy, vz);
347 params.
Append(Params3(0, r, u1, v1, u2, v2, u3, v3));
351 double u12 = (u1+u2)/2, v12 = (v1+v2)/2;
352 double u23 = (u2+u3)/2, v23 = (v2+v3)/2;
353 double u31 = (u3+u1)/2, v31 = (v3+v1)/2;
355 int vxy =
GetMidVertex(vx, vy, r, u12, v12,
false, mesh, hash);
356 int vyz =
GetMidVertex(vy, vz, r, u23, v23,
false, mesh, hash);
357 int vxz =
GetMidVertex(vx, vz, r, u31, v31,
false, mesh, hash);
359 MakeCenter(origin, vx, vxy, vxz, level-1, r, u1, v1, u12, v12, u31, v31,
360 bnd1,
false, bnd3, bnd4, mesh, hash, params);
361 MakeCenter(origin, vxy, vy, vyz, level-1, r, u12, v12, u2, v2, u23, v23,
362 bnd1, bnd2,
false, bnd4, mesh, hash, params);
363 MakeCenter(origin, vxz, vyz, vz, level-1, r, u31, v31, u23, v23, u3, v3,
364 false, bnd2, bnd3, bnd4, mesh, hash, params);
365 MakeCenter(origin, vyz, vxz, vxy, level-1, r, u23, v23, u31, v31, u12, v12,
366 false,
false,
false, bnd4, mesh, hash, params);
370 Mesh*
Make3D(
int nsteps,
double rstep,
double aspect,
int order,
bool sfc)
385 while (
pi2 * rstep / (1 << levels) * aspect > rstep) { levels++; }
387 MakeCenter(origin, a, b, c, levels, r, 1, 0, 0, 1, 0, 0,
388 true,
true,
true, (nsteps == 1), mesh, hash, params);
390 for (
int k = 1; k < nsteps; k++)
395 if ((prev_r + rstep/2) *
pi2 * aspect / (1 << levels) > rstep * sqrt(2))
404 MakeLayer(a, b, c, d, e, f, levels, prev_r, r,
405 1, 0, 0, 1, 0, 0,
true,
true,
true, (k == nsteps-1),
421 for (
int i = 0; i < ordering.
Size(); i++)
423 new_params[ordering[i]] = params[i];
439 MFEM_ASSERT(params.
Size() == mesh->
GetNE(),
"");
441 for (
int i = 0; i < mesh->
GetNE(); i++)
443 const Params3 &par = params[i];
448 for (
int j = 0; j < dofs.
Size(); j++)
455 double l1 = 1.0 - ip.
x - ip.
y;
456 double l2 = ip.
x, l3 = ip.
y;
457 u = l1 * par.u1 + l2 * par.u2 + l3 * par.u3;
458 v = l1 * par.v1 + l2 * par.v2 + l3 * par.v3;
460 r = par.r + ip.
z * par.dr;
464 u = ip.
x * par.u1 + ip.
y * par.u2 + ip.
z * par.u3;
465 v = ip.
x * par.v1 + ip.
y * par.v2 + ip.
z * par.v3;
466 double rr = ip.
x + ip.
y + ip.
z;
467 if (std::abs(rr) < 1e-12) {
continue; }
469 r = par.r + rr * par.dr;
472 double q = r / sqrt(u*u + v*v + w*w);
473 (*nodes)(fes->
DofToVDof(dofs[j], 0)) = u*q;
474 (*nodes)(fes->
DofToVDof(dofs[j], 1)) = v*q;
475 (*nodes)(fes->
DofToVDof(dofs[j], 2)) = w*q;
486 int main(
int argc,
char *argv[])
495 bool visualization =
true;
499 args.
AddOption(&dim,
"-d",
"--dim",
"Mesh dimension (2 or 3).");
500 args.
AddOption(&radius,
"-r",
"--radius",
"Radius of the domain.");
501 args.
AddOption(&nsteps,
"-n",
"--nsteps",
502 "Number of elements along the radial direction");
503 args.
AddOption(&aspect,
"-a",
"--aspect",
504 "Target aspect ratio of the elements.");
505 args.
AddOption(&angle,
"-phi",
"--phi",
"Angular range (2D only).");
507 "Polynomial degree of mesh curvature.");
508 args.
AddOption(&sfc,
"-sfc",
"--sfc",
"-no-sfc",
"--no-sfc",
509 "Try to order elements along a space-filling curve.");
510 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
511 "--no-visualization",
512 "Enable or disable GLVis visualization.");
522 MFEM_VERIFY(radius > 0,
"");
523 MFEM_VERIFY(aspect > 0,
"");
524 MFEM_VERIFY(dim >= 2 && dim <= 3,
"");
525 MFEM_VERIFY(angle > 0 && angle < 360,
"");
526 MFEM_VERIFY(nsteps > 0,
"");
528 double phi = angle * M_PI / 180;
534 mesh =
Make2D(nsteps, radius/nsteps, phi, aspect, order, sfc);
538 mesh =
Make3D(nsteps, radius/nsteps, aspect, order, sfc);
542 ofstream ofs(
"polar-nc.mesh");
552 sol_sock.precision(8);
553 sol_sock <<
"mesh\n" << *mesh << flush;
Mesh * Make3D(int nsteps, double rstep, double aspect, int order, bool sfc)
int Size() const
Return the logical size of the array.
static void GridSfcOrdering2D(int width, int height, Array< int > &coords)
Class for an integration rule - an Array of IntegrationPoint.
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
void MakeCenter(int origin, int vx, int vy, int vz, int level, double r, double u1, double v1, double u2, double v2, double u3, double v3, bool bnd1, bool bnd2, bool bnd3, bool bnd4, Mesh *mesh, HashTable< Vert > &hash, Array< Params3 > ¶ms)
int GetMidVertex(int v1, int v2, double r, double u, double v, bool hanging, Mesh *mesh, HashTable< Vert > &hash)
void RestrictConforming()
int AddTriangle(int v1, int v2, int v3, int attr=1)
int GetNE() const
Returns number of elements.
Geometry::Type GetElementBaseGeometry(int i) const
void MakeLayer(int vx1, int vy1, int vz1, int vx2, int vy2, int vz2, int level, double r1, double r2, double u1, double v1, double u2, double v2, double u3, double v3, bool bnd1, bool bnd2, bool bnd3, bool bnd4, Mesh *mesh, HashTable< Vert > &hash, Array< Params3 > ¶ms)
int AddBdrTriangle(int v1, int v2, int v3, int attr=1)
Mesh * Make2D(int nsteps, double rstep, double phi, double aspect, int order, bool sfc)
int AddVertex(double x, double y=0.0, double z=0.0)
double f(const Vector &xvec)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
int Append(const T &el)
Append element 'el' to array, resize if necessary.
int AddTet(int v1, int v2, int v3, int v4, int attr=1)
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
int AddBdrSegment(int v1, int v2, int attr=1)
void GetHilbertElementOrdering(Array< int > &ordering)
void PrintUsage(std::ostream &out) const
Print the usage message.
virtual DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'.
void Swap(Array< T > &, Array< T > &)
void FinalizeMesh(int refine=0, bool fix_orientation=true)
Finalize the construction of any type of Mesh.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
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...
int AddBdrQuad(int v1, int v2, int v3, int v4, int attr=1)
Class for integration point with weight.
const FiniteElementSpace * GetNodalFESpace() const
virtual void Print(std::ostream &os=mfem::out) const
void ReorderElements(const Array< int > &ordering, bool reorder_vertices=true)
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int index(int i, int j, int nx, int ny)
void PrintOptions(std::ostream &out) const
Print the options.
int AddWedge(int v1, int v2, int v3, int v4, int v5, int v6, int attr=1)
void GetNodes(Vector &node_coord) const
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
double u(const Vector &xvec)
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
bool Good() const
Return true if the command line options were parsed successfully.
void AddVertexParents(int i, int p1, int p2)
Mark vertex i as nonconforming, with parent vertices p1 and p2.