103 bool by_vdim =
false;
104 bool snapshot =
false;
108 real_t amr_threshold = 0.6;
109 const char *keys =
"gAm";
110 const char *device_config =
"cpu";
111 const char *mesh_file =
"../../data/mobius-strip.mesh";
115class Surface:
public Mesh
126 Surface(Opt &opt,
const char *file):
Mesh(file, true), opt(opt) { }
136 Surface(Opt &opt,
int nv,
int ne,
int nbe):
151 mesh =
new ParMesh(MPI_COMM_WORLD, *
this);
153 BoundaryConditions();
165 ByVDim(*
this, opt).Solve();
169 ByNodes(*
this, opt).Solve();
171 if (opt.vis && opt.snapshot)
174 Visualize(glvis, opt, mesh, mesh->
GetNodes());
181 if (opt.vis) { glvis.
close(); }
182 delete mesh;
delete fec;
delete fes;
185 virtual void Prefix()
190 virtual void Transform() {
if (opt.Tptr) {
Mesh::Transform(opt.Tptr); } }
192 virtual void Postfix()
197 virtual void Refine()
199 for (
int l = 0; l < opt.refine; l++)
208 for (
int i = 0; i < nodes.
Size(); i++)
210 if (std::abs(nodes(i)) <
EPS)
217 void SnapNodesToUnitSphere()
221 for (
int i = 0; i < nodes.
FESpace()->GetNDofs(); i++)
223 for (
int d = 0; d <
SDIM; d++)
227 node /= node.Norml2();
228 for (
int d = 0; d <
SDIM; d++)
235 virtual void BoundaryConditions()
248 Opt &opt,
const Mesh *mesh,
249 const int w,
const int h,
253 glvis <<
"parallel " << opt.sz <<
" " << opt.id <<
"\n";
254 glvis <<
"solution\n" << *mesh << solution;
256 glvis <<
"window_size " << w <<
" " << h <<
"\n";
257 glvis <<
"keys " << opt.keys <<
"\n";
259 if (opt.wait) { glvis <<
"pause\n"; }
265 const Opt &opt,
const Mesh *mesh,
268 glvis <<
"parallel " << opt.sz <<
" " << opt.id <<
"\n";
270 glvis <<
"solution\n" << *mesh << solution;
271 if (opt.wait) { glvis <<
"pause\n"; }
272 if (opt.snapshot && opt.keys) { glvis <<
"keys " << opt.keys <<
"\n"; }
279 const char *mesh_file =
"surface.mesh";
280 const char *sol_file =
"sol.gf";
283 mfem::out <<
"Printing " << mesh_file <<
", " << sol_file << std::endl;
286 std::ostringstream mesh_name;
287 mesh_name << mesh_file <<
"." << std::setfill(
'0') << std::setw(6) << opt.id;
288 std::ofstream mesh_ofs(mesh_name.str().c_str());
289 mesh_ofs.precision(8);
290 mesh->
Print(mesh_ofs);
293 std::ostringstream sol_name;
294 sol_name << sol_file <<
"." << std::setfill(
'0') << std::setw(6) << opt.id;
295 std::ofstream sol_ofs(sol_name.str().c_str());
296 sol_ofs.precision(8);
313 const int print_iter = -1, max_num_iter = 2000;
316 Solver(Surface &S, Opt &opt): opt(opt), S(S), cg(MPI_COMM_WORLD),
317 a(S.fes), x(S.fes), x0(S.fes),
b(S.fes), one(1.0)
329 constexpr bool converged =
true;
330 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL);}
331 for (
int i=0; i < opt.niters; ++i)
333 if (opt.amr) { Amr(); }
334 if (opt.vis) { Surface::Visualize(S.glvis, opt, S.mesh); }
335 if (!opt.id) {
mfem::out <<
"Iteration " << i <<
": "; }
339 if (Step() == converged) {
break; }
341 if (opt.print) { Surface::Print(opt, S.mesh, S.mesh->
GetNodes()); }
344 virtual bool Step() = 0;
347 bool Converged(
const real_t rnorm) {
return rnorm <
NRM; }
353 a.FormLinearSystem(S.bc, x, b, A, X, B);
358 a.RecoverFEMSolution(X, b, x);
359 const bool by_vdim = opt.by_vdim;
366 MPI_MAX, MPI_COMM_WORLD);
368 if (!opt.id) {
mfem::out <<
"rnorm = " << rnorm << std::endl; }
369 const real_t lambda = opt.lambda;
372 MFEM_VERIFY(!opt.radial,
"'VDim solver can't use radial option!");
373 return Converged(rnorm);
381 for (
int i = 0; i <
delta.Size()/
SDIM; i++)
385 for (
int d = 0; d <
SDIM; d++)
387 ni(d) = (*nodes)(d*ndof + i);
388 di(d) =
delta(d*ndof + i);
391 const real_t ndotd = (ni*di) / (ni*ni);
394 for (
int d = 0; d <
SDIM; d++) {
delta(d*ndof + i) = di(d); }
399 add(lambda, *nodes, (1.0-lambda), x, x);
400 return Converged(rnorm);
405 MFEM_VERIFY(opt.amr_threshold >= 0.0 && opt.amr_threshold <= 1.0,
"");
406 Mesh *smesh = S.mesh;
408 const int NE = smesh->
GetNE();
410 for (
int e = 0; e < NE; e++)
420 for (
int q = 0; q < NQ; q++)
428 minW = std::min(minW, w);
429 maxW = std::max(maxW, w);
431 if (std::abs(maxW) != 0.0)
433 const real_t rho = minW / maxW;
434 MFEM_VERIFY(rho <= 1.0,
"");
448 S.BoundaryConditions();
454 class ByNodes:
public Solver
457 ByNodes(Surface &S, Opt &opt):
Solver(S, opt)
463 bool converge = ParAXeqB();
465 return converge ? true :
false;
470 class ByVDim:
public Solver
475 auto d_Xi = Xi.
Read();
480 d_nodes[c*ndof + i] = d_Xi[i];
486 auto d_Xi = Xi.
Write();
491 d_Xi[i] = d_nodes[c*ndof + i];
495 ByVDim(Surface &S, Opt &opt):
Solver(S, opt)
500 bool cvg[
SDIM] {
false};
501 for (
int c=0; c <
SDIM; ++c)
508 const bool converged = cvg[0] && cvg[1] && cvg[2];
509 return converged ? true :
false;
515struct MeshFromFile:
public Surface
517 MeshFromFile(Opt &opt): Surface(opt, opt.mesh_file) { }
521struct Catenoid:
public Surface
523 Catenoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
529 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
531 for (
int j = 0; j <= opt.ny; j++)
533 const int v_old = opt.nx + j * (opt.nx + 1);
534 const int v_new = j * (opt.nx + 1);
538 for (
int i = 0; i <
GetNE(); i++)
543 for (
int j = 0; j < nv; j++)
549 for (
int i = 0; i <
GetNBE(); i++)
554 for (
int j = 0; j < nv; j++)
576struct Helicoid:
public Surface
578 Helicoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
585 const real_t v = 2.0*
PI*(2.0*x[1]-1.0)/3.0;
593struct Enneper:
public Surface
595 Enneper(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
601 const real_t u = 4.0*(x[0]-0.5);
602 const real_t v = 4.0*(x[1]-0.5);
603 p[0] = +
u -
u*
u*
u/3.0 +
u*v*v;
604 p[1] = -v -
u*
u*v + v*v*v/3.0;
610struct Hold:
public Surface
612 Hold(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
618 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
620 for (
int j = 0; j <= opt.ny; j++)
622 const int v_old = opt.nx + j * (opt.nx + 1);
623 const int v_new = j * (opt.nx + 1);
627 for (
int i = 0; i <
GetNE(); i++)
632 for (
int j = 0; j < nv; j++)
638 for (
int i = 0; i <
GetNBE(); i++)
643 for (
int j = 0; j < nv; j++)
658 p[0] = cos(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
659 p[1] = sin(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
667#define I cdouble(0.0, 1.0)
754 if (abs(q2n) <
EPS) { q2n = 0.0; }
777static real_t ALPHA[4] {0.0};
778struct Costa:
public Surface
780 Costa(Opt &opt): Surface((opt.Tptr = Parametrization, opt), false) { }
785 const int nx = opt.nx, ny = opt.ny;
786 MFEM_VERIFY(nx>2 && ny>2,
"");
787 const int nXhalf = (nx%2)==0 ? 4 : 2;
788 const int nYhalf = (ny%2)==0 ? 4 : 2;
789 const int nxh = nXhalf + nYhalf;
790 const int NVert = (nx+1) * (ny+1);
791 const int NElem = nx*ny - 4 - nxh;
792 const int NBdrElem = 0;
795 for (
int j = 0; j <= ny; j++)
798 for (
int i = 0; i <= nx; i++)
806 for (
int j = 0; j < ny; j++)
808 for (
int i = 0; i < nx; i++)
810 if (i == 0 && j == 0) {
continue; }
811 if (i+1 == nx && j == 0) {
continue; }
812 if (i == 0 && j+1 == ny) {
continue; }
813 if (i+1 == nx && j+1 == ny) {
continue; }
814 if ((j == 0 || j+1 == ny) && (abs(nx-(i<<1)-1)<=1)) {
continue; }
815 if ((i == 0 || i+1 == nx) && (abs(ny-(j<<1)-1)<=1)) {
continue; }
816 const int i0 = i + j*(nx+1);
817 const int i1 = i+1 + j*(nx+1);
818 const int i2 = i+1 + (j+1)*(nx+1);
819 const int i3 = i + (j+1)*(nx+1);
820 const int ind[4] = {i0, i1, i2, i3};
832 const real_t tau = ALPHA[3];
839 const bool y_top = x[1] > 0.5;
840 const bool x_top = x[0] > 0.5;
843 if (y_top) { v = 1.0 - x[1]; }
844 if (x_top) {
u = 1.0 - x[0]; }
854 p[2] = sqrt(
PI/2.)*log(abs((pw-e1)/(pw+e1)));
855 if (y_top) {
p[1] *= -1.0; }
856 if (x_top) {
p[0] *= -1.0; }
857 const bool nan = std::isnan(
p[0]) || std::isnan(
p[1]) || std::isnan(
p[2]);
858 MFEM_VERIFY(!nan,
"nan");
859 ALPHA[0] = std::fmax(
p[0], ALPHA[0]);
860 ALPHA[1] = std::fmax(
p[1], ALPHA[1]);
861 ALPHA[2] = std::fmax(
p[2], ALPHA[2]);
867 MFEM_VERIFY(ALPHA[0] > 0.0,
"");
868 MFEM_VERIFY(ALPHA[1] > 0.0,
"");
869 MFEM_VERIFY(ALPHA[2] > 0.0,
"");
871 const real_t phi = (1.0 + sqrt(5.0)) / 2.0;
874 for (
int d = 0; d <
SDIM; d++)
878 nodes(vdof) /=
alpha * ALPHA[d];
885struct Shell:
public Surface
887 Shell(Opt &opt): Surface((opt.niters = 1, opt.Tptr = Parametrization, opt)) { }
894 const real_t v = 21.0*x[1]-15.0;
895 p[0] = +1.0*pow(1.16,v)*cos(v)*(1.0+cos(
u));
896 p[1] = -1.0*pow(1.16,v)*sin(v)*(1.0+cos(
u));
897 p[2] = -2.0*pow(1.16,v)*(1.0+sin(
u));
902struct Scherk:
public Surface
913 p[2] = log(cos(v)/cos(
u));
916 Scherk(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
920struct FullPeach:
public Surface
922 static constexpr int NV = 8;
923 static constexpr int NE = 6;
926 Surface((opt.niters = std::min(4, opt.niters), opt), NV, NE, 0) { }
932 {-1, -1, -1}, {+1, -1, -1}, {+1, +1, -1}, {-1, +1, -1},
933 {-1, -1, +1}, {+1, -1, +1}, {+1, +1, +1}, {-1, +1, +1}
935 const int quad_e[NE][4] =
937 {3, 2, 1, 0}, {0, 1, 5, 4}, {1, 2, 6, 5},
938 {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}
941 for (
int j = 0; j < NV; j++) {
AddVertex(quad_v[j]); }
942 for (
int j = 0; j < NE; j++) {
AddQuad(quad_e[j], j+1); }
950 void Snap() { SnapNodesToUnitSphere(); }
952 void BoundaryConditions()
962 for (
int e = 0; e < fes->
GetNE(); e++)
969 for (
int dof = 0; dof < dofs.
Size(); dof++)
973 const int k = dofs[dof];
974 MFEM_ASSERT(k >= 0,
"");
975 PointMat.
Mult(one, X);
976 const bool halfX = std::abs(X[0]) <
EPS && X[1] <= 0.0;
977 const bool halfY = std::abs(X[2]) <
EPS && X[1] >= 0.0;
978 const bool is_on_bc = halfX || halfY;
979 for (
int c = 0; c <
SDIM; c++)
980 { ess_vdofs[fes->
DofToVDof(k, c)] = is_on_bc; }
993 ParFiniteElementSpace::MarkerToList(ess_tdofs, bc);
998struct QuarterPeach:
public Surface
1000 QuarterPeach(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
1005 const real_t x = 2.0*X[0]-1.0;
1007 const real_t r = sqrt(x*x + y*y);
1009 (y==0.0 && x>0.0) ? 0. :
1010 (y==0.0 && x<0.0) ?
PI : acos(x/r);
1011 const real_t sqrtx = sqrt(1.0 + x*x);
1012 const real_t sqrty = sqrt(1.0 + y*y);
1013 const bool yaxis =
PI/4.0<
t &&
t < 3.0*
PI/4.0;
1014 const real_t R = yaxis?sqrtx:sqrty;
1015 const real_t gamma = r/R;
1016 p[0] = gamma * cos(
t);
1017 p[1] = gamma * sin(
t);
1023 for (
int i = 0; i <
GetNBE(); i++)
1033 for (
int v = 0; v < 2; v++)
1037 for (
int d = 0; d <
SDIM; d++)
1040 const real_t x = X[v][d] = nval[iv];
1041 if (d < 2) { R[v] += x*x; }
1044 if (std::abs(X[0][1])<=
EPS && std::abs(X[1][1])<=
EPS &&
1045 (R[0]>0.1 || R[1]>0.1))
1053struct SlottedSphere:
public Surface
1055 SlottedSphere(Opt &opt): Surface((opt.niters = 4, opt), 64, 40, 0) { }
1060 constexpr int NV1D = 4;
1061 constexpr int NV = NV1D*NV1D*NV1D;
1062 constexpr int NEPF = (NV1D-1)*(NV1D-1);
1063 constexpr int NE = NEPF*6;
1066 for (
int iv=0; iv<NV; ++iv)
1069 int iy = (iv / NV1D) % NV1D;
1070 int iz = (iv / NV1D) / NV1D;
1072 QV[iv][0] = V1D[ix];
1073 QV[iv][1] = V1D[iy];
1074 QV[iv][2] = V1D[iz];
1077 for (
int ix=0; ix<NV1D-1; ++ix)
1079 for (
int iy=0; iy<NV1D-1; ++iy)
1081 int el_offset = ix + iy*(NV1D-1);
1083 QE[0*NEPF + el_offset][0] = NV1D*ix + NV1D*NV1D*iy;
1084 QE[0*NEPF + el_offset][1] = NV1D*(ix+1) + NV1D*NV1D*iy;
1085 QE[0*NEPF + el_offset][2] = NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1086 QE[0*NEPF + el_offset][3] = NV1D*ix + NV1D*NV1D*(iy+1);
1089 QE[1*NEPF + el_offset][3] = x_off + NV1D*ix + NV1D*NV1D*iy;
1090 QE[1*NEPF + el_offset][2] = x_off + NV1D*(ix+1) + NV1D*NV1D*iy;
1091 QE[1*NEPF + el_offset][1] = x_off + NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1092 QE[1*NEPF + el_offset][0] = x_off + NV1D*ix + NV1D*NV1D*(iy+1);
1094 QE[2*NEPF + el_offset][0] = NV1D*NV1D*iy + ix;
1095 QE[2*NEPF + el_offset][1] = NV1D*NV1D*iy + ix + 1;
1096 QE[2*NEPF + el_offset][2] = NV1D*NV1D*(iy+1) + ix + 1;
1097 QE[2*NEPF + el_offset][3] = NV1D*NV1D*(iy+1) + ix;
1099 int y_off = NV1D*(NV1D-1);
1100 QE[3*NEPF + el_offset][0] = y_off + NV1D*NV1D*iy + ix;
1101 QE[3*NEPF + el_offset][1] = y_off + NV1D*NV1D*iy + ix + 1;
1102 QE[3*NEPF + el_offset][2] = y_off + NV1D*NV1D*(iy+1) + ix + 1;
1103 QE[3*NEPF + el_offset][3] = y_off + NV1D*NV1D*(iy+1) + ix;
1105 QE[4*NEPF + el_offset][0] = NV1D*iy + ix;
1106 QE[4*NEPF + el_offset][1] = NV1D*iy + ix + 1;
1107 QE[4*NEPF + el_offset][2] = NV1D*(iy+1) + ix + 1;
1108 QE[4*NEPF + el_offset][3] = NV1D*(iy+1) + ix;
1110 int z_off = NV1D*NV1D*(NV1D-1);
1111 QE[5*NEPF + el_offset][0] = z_off + NV1D*iy + ix;
1112 QE[5*NEPF + el_offset][1] = z_off + NV1D*iy + ix + 1;
1113 QE[5*NEPF + el_offset][2] = z_off + NV1D*(iy+1) + ix + 1;
1114 QE[5*NEPF + el_offset][3] = z_off + NV1D*(iy+1) + ix;
1118 QE[0*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1119 QE[0*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1121 QE[1*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1122 QE[1*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1124 QE[3*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1125 QE[3*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1127 QE[5*NEPF + 0 + 1*(NV1D-1)][0] = -1;
1128 QE[5*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1129 QE[5*NEPF + 2 + 1*(NV1D-1)][0] = -1;
1131 QE[4*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1132 QE[4*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1133 QE[4*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1135 QE[2*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1136 QE[2*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1137 for (
int j = 0; j < NV; j++) {
AddVertex(QV[j]); }
1138 for (
int j = 0; j < NE; j++)
1140 if (QE[j][0] < 0) {
continue; }
1149 void Snap() { SnapNodesToUnitSphere(); }
1152static int Problem0(Opt &opt)
1155 Surface *S =
nullptr;
1156 switch (opt.surface)
1158 case 0: S =
new MeshFromFile(opt);
break;
1159 case 1: S =
new Catenoid(opt);
break;
1160 case 2: S =
new Helicoid(opt);
break;
1161 case 3: S =
new Enneper(opt);
break;
1162 case 4: S =
new Hold(opt);
break;
1163 case 5: S =
new Costa(opt);
break;
1164 case 6: S =
new Shell(opt);
break;
1165 case 7: S =
new Scherk(opt);
break;
1166 case 8: S =
new FullPeach(opt);
break;
1167 case 9: S =
new QuarterPeach(opt);
break;
1168 case 10: S =
new SlottedSphere(opt);
break;
1169 default: MFEM_ABORT(
"Unknown surface (surface <= 10)!");
1179static real_t u0(
const Vector &x) {
return sin(3.0 *
PI * (x[1] + x[0])); }
1183static real_t qf(
const int order,
const int ker,
Mesh &m,
1190 const int NE(m.
GetNE());
1198 MFEM_VERIFY(ND == D1D*D1D,
"");
1199 MFEM_VERIFY(NQ == Q1D*Q1D,
"");
1201 Vector Eu(ND*NE), grad_u(
DIM*NQ*NE), sum(NE*NQ), one(NE*NQ);
1202 qi->SetOutputLayout(QVectorLayout::byVDIM);
1206 qi->Derivatives(Eu, grad_u);
1211 auto grdU =
Reshape(grad_u.Read(),
DIM, Q1D, Q1D, NE);
1212 auto S =
Reshape(sum.Write(), Q1D, Q1D, NE);
1216 MFEM_FOREACH_THREAD(qy,y,Q1D)
1218 MFEM_FOREACH_THREAD(qx,x,Q1D)
1220 const real_t w = W(qx, qy);
1221 const real_t J11 = J(qx, qy, 0, 0, e);
1222 const real_t J12 = J(qx, qy, 1, 0, e);
1223 const real_t J21 = J(qx, qy, 0, 1, e);
1224 const real_t J22 = J(qx, qy, 1, 1, e);
1225 const real_t det = detJ(qx, qy, e);
1226 const real_t area = w * det;
1227 const real_t gu0 = grdU(0, qx, qy, e);
1228 const real_t gu1 = grdU(1, qx, qy, e);
1229 const real_t tgu0 = (J22*gu0 - J12*gu1)/det;
1230 const real_t tgu1 = (J11*gu1 - J21*gu0)/det;
1231 const real_t ngu = tgu0*tgu0 + tgu1*tgu1;
1232 const real_t s = (ker ==
AREA) ? sqrt(1.0 + ngu) :
1233 (ker ==
NORM) ? ngu : 0.0;
1234 S(qx, qy, e) = area *
s;
1242static int Problem1(Opt &opt)
1244 const int order = opt.order;
1248 ParMesh mesh(MPI_COMM_WORLD, smesh);
1260 u.ProjectCoefficient(u0_fc);
1263 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh,
GLVIZ_W,
GLVIZ_H, &
u); }
1272 for (
int i = 0; i < opt.niters; i++)
1277 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
1278 const real_t q_uold = qf(order,
AREA, mesh, fes, uold);
1279 MFEM_VERIFY(std::abs(q_uold) >
EPS,
"");
1283 a.FormLinearSystem(ess_tdof_list,
u,
b, A, X, B);
1286 a.RecoverFEMSolution(X,
b,
u);
1288 const real_t norm = sqrt(std::abs(qf(order,
NORM, mesh, fes, eps)));
1289 const real_t area = qf(order,
AREA, mesh, fes,
u);
1292 mfem::out <<
"Iteration " << i <<
", norm: " << norm
1293 <<
", area: " << area << std::endl;
1295 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh, &
u); }
1296 if (opt.print) { Surface::Print(opt, &mesh, &
u); }
1297 if (norm <
NRM) {
break; }
1312 args.
AddOption(&opt.pb,
"-p",
"--problem",
"Problem to solve.");
1313 args.
AddOption(&opt.mesh_file,
"-m",
"--mesh",
"Mesh file to use.");
1314 args.
AddOption(&opt.wait,
"-w",
"--wait",
"-no-w",
"--no-wait",
1315 "Enable or disable a GLVis pause.");
1316 args.
AddOption(&opt.radial,
"-rad",
"--radial",
"-no-rad",
"--no-radial",
1317 "Enable or disable radial constraints in solver.");
1318 args.
AddOption(&opt.nx,
"-x",
"--num-elements-x",
1319 "Number of elements in x-direction.");
1320 args.
AddOption(&opt.ny,
"-y",
"--num-elements-y",
1321 "Number of elements in y-direction.");
1322 args.
AddOption(&opt.order,
"-o",
"--order",
"Finite element order.");
1323 args.
AddOption(&opt.refine,
"-r",
"--ref-levels",
"Refinement");
1324 args.
AddOption(&opt.niters,
"-n",
"--niter-max",
"Max number of iterations");
1325 args.
AddOption(&opt.surface,
"-s",
"--surface",
"Choice of the surface.");
1326 args.
AddOption(&opt.pa,
"-pa",
"--partial-assembly",
"-no-pa",
1327 "--no-partial-assembly",
"Enable Partial Assembly.");
1328 args.
AddOption(&opt.tau,
"-t",
"--tau",
"Costa scale factor.");
1329 args.
AddOption(&opt.lambda,
"-l",
"--lambda",
"Lambda step toward solution.");
1330 args.
AddOption(&opt.amr,
"-a",
"--amr",
"-no-a",
"--no-amr",
"Enable AMR.");
1331 args.
AddOption(&opt.amr_threshold,
"-at",
"--amr-threshold",
"AMR threshold.");
1332 args.
AddOption(&opt.device_config,
"-d",
"--device",
1333 "Device configuration string, see Device::Configure().");
1334 args.
AddOption(&opt.keys,
"-k",
"--keys",
"GLVis configuration keys.");
1335 args.
AddOption(&opt.vis,
"-vis",
"--visualization",
"-no-vis",
1336 "--no-visualization",
"Enable or disable visualization.");
1337 args.
AddOption(&opt.by_vdim,
"-c",
"--solve-byvdim",
1338 "-no-c",
"--solve-bynodes",
1339 "Enable or disable the 'ByVdim' solver");
1340 args.
AddOption(&opt.print,
"-print",
"--print",
"-no-print",
"--no-print",
1341 "Enable or disable result output (files in mfem format).");
1342 args.
AddOption(&opt.snapshot,
"-ss",
"--snapshot",
"-no-ss",
"--no-snapshot",
1343 "Enable or disable GLVis snapshot.");
1346 MFEM_VERIFY(opt.lambda >= 0.0 && opt.lambda <= 1.0,
"");
1350 Device device(opt.device_config);
1351 if (!opt.id) { device.
Print(); }
1353 if (opt.pb == 0) { Problem0(opt); }
1355 if (opt.pb == 1) { Problem1(opt); }
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Conjugate gradient method.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the Conjugate Gradient method.
A coefficient that is constant across space and time.
Data type dense matrix using column-major storage.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
void Transpose()
(*this) = (*this)^t
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
Abstract data type element.
Geometry::Type GetGeometryType() const
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
Type
Constants for the classes derived from Element.
virtual int GetNVertices() const =0
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
const QuadratureInterpolator * GetQuadratureInterpolator(const IntegrationRule &ir) const
Return a QuadratureInterpolator that interpolates E-vectors to quadrature point values and/or derivat...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int GetNE() const
Returns number of elements in the mesh.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Mesh * GetMesh() const
Returns the mesh.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
int DofToVDof(int dof, int vd, int ndofs=-1) const
Compute a single vdof corresponding to the index dof and the vector index vd.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
int GetDof() const
Returns the number of degrees of freedom in the finite element.
A general function coefficient.
Structure for storing mesh geometric factors: coordinates, Jacobians, and determinants of the Jacobia...
Vector detJ
Determinants of the Jacobians at all quadrature points.
Vector J
Jacobians of the element transformations at all quadrature points.
Class for grid function - Vector with associated FE space.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
FiniteElementSpace * FESpace()
void GetNodalValues(int i, Array< real_t > &nval, int vdim=1) const
Returns the values in the vertices of i'th element for dimension vdim.
Arbitrary order H1-conforming (continuous) finite elements.
The BoomerAMG solver in hypre.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Class for an integration rule - an Array of IntegrationPoint.
int GetOrder() const
Returns the order of the integration rule.
int GetNPoints() const
Returns the number of the points in the integration rule.
const Array< real_t > & GetWeights() const
Return the quadrature weights in a contiguous array.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
void SetAbsTol(real_t atol)
void InitMesh(int Dim_, int spaceDim_, int NVert, int NElem, int NBdrElem)
Begin construction of a mesh.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
void NodesUpdated()
This function should be called after the mesh node coordinates have been updated externally,...
void EnsureNodes()
Make sure that the mesh has valid nodes, i.e. its geometry is described by a vector finite element gr...
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 GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
bool FaceIsTrueInterior(int FaceNo) const
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
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.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
void FinalizeQuadMesh(int generate_edges=0, int refine=0, bool fix_orientation=true)
Finalize the construction of a quadrilateral Mesh.
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags, MemoryType d_mt=MemoryType::DEFAULT)
Return the mesh geometric factors corresponding to the given integration rule.
void GetNodes(Vector &node_coord) const
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
int GetNBE() const
Returns number of boundary elements.
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
void EnsureNCMesh(bool simplices_nonconforming=false)
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...
void SetNodes(const Vector &node_coord)
Updates the vertex/node locations. Invokes NodesUpdated().
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.
void Transform(void(*f)(const Vector &, Vector &))
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Geometry::Type GetElementBaseGeometry(int i) const
void RemoveInternalBoundaries()
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Pointer to an Operator of a specified type.
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.
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
int GetTrueVSize() const override
Return the number of local vector true dofs.
void GetElementDofs(int i, Array< int > &dofs, DofTransformation &doftrans) const override
The same as GetElementDofs(), but with a user-allocated DofTransformation object. doftrans must be al...
const SparseMatrix * GetRestrictionMatrix() const override
Get the R matrix which restricts a local dof vector to true dof vector.
const FiniteElement * GetFE(int i) const override
Class for parallel grid function.
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Class for parallel meshes.
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
A class that performs interpolation from an E-vector to quadrature point values and/or derivatives (Q...
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
real_t Norml2() const
Returns the l2 norm of the vector.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
real_t DistanceTo(const real_t *p) const
Compute the Euclidean distance to another vector.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
int close()
Close the socketstream.
real_t Surface()
Analytic surface integral.
std::complex< real_t > cdouble
real_t u(const Vector &xvec)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void add(const Vector &v1, const Vector &v2, Vector &v)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void CalcAdjugate(const DenseMatrix &a, DenseMatrix &adja)
void forall_2D(int N, int X, int Y, lambda &&body)
void subtract(const Vector &x, const Vector &y, Vector &z)
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
void forall(int N, lambda &&body)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
real_t p(const Vector &x, real_t t)
cdouble LogEllipticTheta1Prime(const cdouble u, const cdouble q)
constexpr Element::Type QUAD
std::complex< real_t > cdouble
cdouble WeierstrassZeta(const cdouble z, const cdouble w1=0.5, const cdouble w3=real_t(0.5) *I)
cdouble EllipticTheta1Prime(const int k, const cdouble u, const cdouble q)
cdouble WeierstrassP(const cdouble z, const cdouble w1=0.5, const cdouble w3=real_t(0.5) *I)
cdouble EllipticTheta(const int a, const cdouble u, const cdouble q)
Helper struct to convert a C++ type to an MPI type.