46 : r(r0), dr(r1 - r0),
a(a0), da(a1 - a0) {}
58 while (phi * rstep/2 / n * aspect > rstep) { n++; }
68 for (
int i = 0; i < n; i++)
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++)
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++)
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 real_t alpha_half = phi * (2*i+1) / n;
139 int d = mesh->
AddVertex(r*cos(alpha_half), r*sin(alpha_half));
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 real_t 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);
260 : r(r0), dr(r1 - r0), u1(u1), u2(u2), u3(u3), v1(v1), v2(v2), v3(v3) {}
271 int vmid = hash.
FindId(v1, v2);
274 vmid = hash.
GetId(v1, v2);
277 real_t q = r / sqrt(
u*
u + v*v + w*w);
282 hash[vmid].id =
index;
284 return hash[vmid].id;
287void MakeLayer(
int vx1,
int vy1,
int vz1,
int vx2,
int vy2,
int vz2,
int level,
289 real_t u3,
real_t 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 real_t u12 = (u1+u2)/2, v12 = (v1+v2)/2;
306 real_t u23 = (u2+u3)/2, v23 = (v2+v3)/2;
307 real_t 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);
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 real_t u12 = (u1+u2)/2, v12 = (v1+v2)/2;
352 real_t u23 = (u2+u3)/2, v23 = (v2+v3)/2;
353 real_t 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);
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))
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++)
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;
467 if (std::abs(rr) < 1e-12) {
continue; }
469 r = par.r + rr * par.dr;
472 real_t q = r / sqrt(
u*
u + v*v + w*w);
474 (*nodes)(fes->
DofToVDof(dofs[j], 1)) = v*q;
475 (*nodes)(fes->
DofToVDof(dofs[j], 2)) = w*q;
486int main(
int argc,
char *argv[])
495 bool visualization =
true;
499 args.
AddOption(&
dim,
"-d",
"--dim",
"Mesh dimension (2 or 3).");
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 real_t 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;
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int DofToVDof(int dof, int vd, int ndofs=-1) const
Compute a single vdof corresponding to the index dof and the vector index vd.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Class for grid function - Vector with associated FE space.
void RestrictConforming()
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
Class for integration point with weight.
Class for an integration rule - an Array of IntegrationPoint.
void FinalizeMesh(int refine=0, bool fix_orientation=true)
Finalize the construction of any type of Mesh.
int AddBdrQuad(int v1, int v2, int v3, int v4, int attr=1)
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
Adds a quadrilateral to the mesh given by 4 vertices v1 through v4.
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.
const FiniteElementSpace * GetNodalFESpace() const
int AddTriangle(int v1, int v2, int v3, int attr=1)
Adds a triangle to the mesh given by 3 vertices v1 through v3.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
int GetNE() const
Returns number of elements.
int AddTet(int v1, int v2, int v3, int v4, int attr=1)
Adds a tetrahedron to the mesh given by 4 vertices v1 through v4.
void ReorderElements(const Array< int > &ordering, bool reorder_vertices=true)
int AddBdrSegment(int v1, int v2, int attr=1)
void AddVertexParents(int i, int p1, int p2)
Mark vertex i as nonconforming, with parent vertices p1 and p2.
void GetNodes(Vector &node_coord) const
int AddBdrTriangle(int v1, int v2, int v3, int attr=1)
void GetHilbertElementOrdering(Array< int > &ordering)
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.
Geometry::Type GetElementBaseGeometry(int i) const
static void GridSfcOrdering2D(int width, int height, Array< int > &coords)
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...
bool Good() const
Return true if the command line options were parsed successfully.
int index(int i, int j, int nx, int ny)
void Swap(Array< T > &, Array< T > &)
real_t u(const Vector &xvec)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
int GetMidVertex(int v1, int v2, real_t r, real_t u, real_t v, bool hanging, Mesh *mesh, HashTable< Vert > &hash)
void MakeLayer(int vx1, int vy1, int vz1, int vx2, int vy2, int vz2, int level, real_t r1, real_t r2, real_t u1, real_t v1, real_t u2, real_t v2, real_t u3, real_t v3, bool bnd1, bool bnd2, bool bnd3, bool bnd4, Mesh *mesh, HashTable< Vert > &hash, Array< Params3 > ¶ms)
Mesh * Make3D(int nsteps, real_t rstep, real_t aspect, int order, bool sfc)
Mesh * Make2D(int nsteps, real_t rstep, real_t phi, real_t aspect, int order, bool sfc)
void MakeCenter(int origin, int vx, int vy, int vz, int level, real_t r, real_t u1, real_t v1, real_t u2, real_t v2, real_t u3, real_t v3, bool bnd1, bool bnd2, bool bnd3, bool bnd4, Mesh *mesh, HashTable< Vert > &hash, Array< Params3 > ¶ms)