103 bool by_vdim =
false;
104 bool snapshot =
false;
105 bool vis_mesh =
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
127 Surface(Opt &opt,
const char *file):
Mesh(file, true), opt(opt) { }
137 Surface(Opt &opt,
int nv,
int ne,
int nbe):
152 mesh =
new Mesh(*
this,
true);
154 BoundaryConditions();
166 ByVDim(*
this, opt).Solve();
170 ByNodes(*
this, opt).Solve();
172 if (opt.vis && opt.snapshot)
175 Visualize(glvis, opt, mesh, mesh->
GetNodes());
182 if (opt.vis) { glvis.
close(); }
183 delete mesh;
delete fec;
delete fes;
186 virtual void Prefix()
191 virtual void Transform() {
if (opt.Tptr) {
Mesh::Transform(opt.Tptr); } }
193 virtual void Postfix()
198 virtual void Refine()
200 for (
int l = 0; l < opt.refine; l++)
209 for (
int i = 0; i < nodes.
Size(); i++)
211 if (std::abs(nodes(i)) <
EPS)
218 void SnapNodesToUnitSphere()
222 for (
int i = 0; i < nodes.
FESpace()->GetNDofs(); i++)
224 for (
int d = 0; d <
SDIM; d++)
228 node /= node.Norml2();
229 for (
int d = 0; d <
SDIM; d++)
236 virtual void BoundaryConditions()
249 Opt &opt,
const Mesh *mesh,
250 const int w,
const int h,
254 if (opt.vis_mesh) { glvis <<
"mesh\n" << *mesh; }
255 else { glvis <<
"solution\n" << *mesh << solution; }
257 glvis <<
"window_size " << w <<
" " << h <<
"\n";
258 glvis <<
"keys " << opt.keys <<
"\n";
260 if (opt.wait) { glvis <<
"pause\n"; }
266 const Opt &opt,
const Mesh *mesh,
270 if (opt.vis_mesh) { glvis <<
"mesh\n" << *mesh; }
271 else { glvis <<
"solution\n" << *mesh << solution; }
272 if (opt.wait) { glvis <<
"pause\n"; }
273 if (opt.snapshot && opt.keys) { glvis <<
"keys " << opt.keys <<
"\n"; }
280 const char *mesh_file =
"surface.mesh";
281 const char *sol_file =
"sol.gf";
284 mfem::out <<
"Printing " << mesh_file <<
", " << sol_file << std::endl;
287 std::ofstream mesh_ofs(mesh_file);
288 mesh_ofs.precision(8);
289 mesh->
Print(mesh_ofs);
292 std::ofstream sol_ofs(sol_file);
293 sol_ofs.precision(8);
310 const int print_iter = -1, max_num_iter = 2000;
313 Solver(Surface &S, Opt &opt): opt(opt), S(S), cg(),
314 a(S.fes), x(S.fes), x0(S.fes),
b(S.fes), one(1.0)
326 constexpr bool converged =
true;
327 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL);}
328 for (
int i=0; i < opt.niters; ++i)
330 if (opt.amr) { Amr(); }
331 if (opt.vis) { Surface::Visualize(S.glvis, opt, S.mesh); }
332 if (!opt.id) {
mfem::out <<
"Iteration " << i <<
": "; }
336 if (Step() == converged) {
break; }
338 if (opt.print) { Surface::Print(opt, S.mesh, S.mesh->
GetNodes()); }
341 virtual bool Step() = 0;
344 bool Converged(
const real_t rnorm) {
return rnorm <
NRM; }
350 a.FormLinearSystem(S.bc, x, b, A, X, B);
355 a.RecoverFEMSolution(X, b, x);
356 const bool by_vdim = opt.by_vdim;
361 if (!opt.id) {
mfem::out <<
"rnorm = " << rnorm << std::endl; }
362 const real_t lambda = opt.lambda;
365 MFEM_VERIFY(!opt.radial,
"'VDim solver can't use radial option!");
366 return Converged(rnorm);
374 for (
int i = 0; i <
delta.Size()/
SDIM; i++)
378 for (
int d = 0; d <
SDIM; d++)
380 ni(d) = (*nodes)(d*ndof + i);
381 di(d) =
delta(d*ndof + i);
384 const real_t ndotd = (ni*di) / (ni*ni);
387 for (
int d = 0; d <
SDIM; d++) {
delta(d*ndof + i) = di(d); }
392 add(lambda, *nodes, (1.0-lambda), x, x);
393 return Converged(rnorm);
398 MFEM_VERIFY(opt.amr_threshold >= 0.0 && opt.amr_threshold <= 1.0,
"");
399 Mesh *smesh = S.mesh;
401 const int NE = smesh->
GetNE();
403 for (
int e = 0; e < NE; e++)
412 for (
int q = 0; q < NQ; q++)
420 minW = std::min(minW, w);
421 maxW = std::max(maxW, w);
423 if (std::abs(maxW) != 0.0)
425 const real_t rho = minW / maxW;
426 MFEM_VERIFY(rho <= 1.0,
"");
440 S.BoundaryConditions();
446 class ByNodes:
public Solver
449 ByNodes(Surface &S, Opt &opt):
Solver(S, opt)
455 bool converge = ParAXeqB();
457 return converge ? true :
false;
462 class ByVDim:
public Solver
467 auto d_Xi = Xi.
Read();
472 d_nodes[c*ndof + i] = d_Xi[i];
478 auto d_Xi = Xi.
Write();
483 d_Xi[i] = d_nodes[c*ndof + i];
487 ByVDim(Surface &S, Opt &opt):
Solver(S, opt)
492 bool cvg[
SDIM] {
false};
493 for (
int c=0; c <
SDIM; ++c)
500 const bool converged = cvg[0] && cvg[1] && cvg[2];
501 return converged ? true :
false;
507struct MeshFromFile:
public Surface
509 MeshFromFile(Opt &opt): Surface(opt, opt.mesh_file) { }
513struct Catenoid:
public Surface
515 Catenoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
521 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
523 for (
int j = 0; j <= opt.ny; j++)
525 const int v_old = opt.nx + j * (opt.nx + 1);
526 const int v_new = j * (opt.nx + 1);
530 for (
int i = 0; i <
GetNE(); i++)
535 for (
int j = 0; j < nv; j++)
541 for (
int i = 0; i <
GetNBE(); i++)
546 for (
int j = 0; j < nv; j++)
568struct Helicoid:
public Surface
570 Helicoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
577 const real_t v = 2.0*
PI*(2.0*x[1]-1.0)/3.0;
585struct Enneper:
public Surface
587 Enneper(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
593 const real_t u = 4.0*(x[0]-0.5);
594 const real_t v = 4.0*(x[1]-0.5);
595 p[0] = +
u -
u*
u*
u/3.0 +
u*v*v;
596 p[1] = -v -
u*
u*v + v*v*v/3.0;
602struct Hold:
public Surface
604 Hold(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
610 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
612 for (
int j = 0; j <= opt.ny; j++)
614 const int v_old = opt.nx + j * (opt.nx + 1);
615 const int v_new = j * (opt.nx + 1);
619 for (
int i = 0; i <
GetNE(); i++)
624 for (
int j = 0; j < nv; j++)
630 for (
int i = 0; i <
GetNBE(); i++)
635 for (
int j = 0; j < nv; j++)
650 p[0] = cos(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
651 p[1] = sin(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
659#define I cdouble(0.0, 1.0)
746 if (abs(q2n) <
EPS) { q2n = 0.0; }
769static real_t ALPHA[4] {0.0};
770struct Costa:
public Surface
772 Costa(Opt &opt): Surface((opt.Tptr = Parametrization, opt), false) { }
777 const int nx = opt.nx, ny = opt.ny;
778 MFEM_VERIFY(nx>2 && ny>2,
"");
779 const int nXhalf = (nx%2)==0 ? 4 : 2;
780 const int nYhalf = (ny%2)==0 ? 4 : 2;
781 const int nxh = nXhalf + nYhalf;
782 const int NVert = (nx+1) * (ny+1);
783 const int NElem = nx*ny - 4 - nxh;
784 const int NBdrElem = 0;
787 for (
int j = 0; j <= ny; j++)
790 for (
int i = 0; i <= nx; i++)
798 for (
int j = 0; j < ny; j++)
800 for (
int i = 0; i < nx; i++)
802 if (i == 0 && j == 0) {
continue; }
803 if (i+1 == nx && j == 0) {
continue; }
804 if (i == 0 && j+1 == ny) {
continue; }
805 if (i+1 == nx && j+1 == ny) {
continue; }
806 if ((j == 0 || j+1 == ny) && (abs(nx-(i<<1)-1)<=1)) {
continue; }
807 if ((i == 0 || i+1 == nx) && (abs(ny-(j<<1)-1)<=1)) {
continue; }
808 const int i0 = i + j*(nx+1);
809 const int i1 = i+1 + j*(nx+1);
810 const int i2 = i+1 + (j+1)*(nx+1);
811 const int i3 = i + (j+1)*(nx+1);
812 const int ind[4] = {i0, i1, i2, i3};
824 const real_t tau = ALPHA[3];
831 const bool y_top = x[1] > 0.5;
832 const bool x_top = x[0] > 0.5;
835 if (y_top) { v = 1.0 - x[1]; }
836 if (x_top) {
u = 1.0 - x[0]; }
846 p[2] = sqrt(
PI/2.)*log(abs((pw-e1)/(pw+e1)));
847 if (y_top) {
p[1] *= -1.0; }
848 if (x_top) {
p[0] *= -1.0; }
849 const bool nan = std::isnan(
p[0]) || std::isnan(
p[1]) || std::isnan(
p[2]);
850 MFEM_VERIFY(!nan,
"nan");
851 ALPHA[0] = std::max(
p[0], ALPHA[0]);
852 ALPHA[1] = std::max(
p[1], ALPHA[1]);
853 ALPHA[2] = std::max(
p[2], ALPHA[2]);
859 MFEM_VERIFY(ALPHA[0] > 0.0,
"");
860 MFEM_VERIFY(ALPHA[1] > 0.0,
"");
861 MFEM_VERIFY(ALPHA[2] > 0.0,
"");
863 const real_t phi = (1.0 + sqrt(5.0)) / 2.0;
866 for (
int d = 0; d <
SDIM; d++)
870 nodes(vdof) /=
alpha * ALPHA[d];
877struct Shell:
public Surface
879 Shell(Opt &opt): Surface((opt.niters = 1, opt.Tptr = Parametrization, opt)) { }
886 const real_t v = 21.0*x[1]-15.0;
887 p[0] = +1.0*pow(1.16,v)*cos(v)*(1.0+cos(
u));
888 p[1] = -1.0*pow(1.16,v)*sin(v)*(1.0+cos(
u));
889 p[2] = -2.0*pow(1.16,v)*(1.0+sin(
u));
894struct Scherk:
public Surface
905 p[2] = log(cos(v)/cos(
u));
908 Scherk(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
912struct FullPeach:
public Surface
914 static constexpr int NV = 8;
915 static constexpr int NE = 6;
918 Surface((opt.niters = std::min(4, opt.niters), opt), NV, NE, 0) { }
924 {-1, -1, -1}, {+1, -1, -1}, {+1, +1, -1}, {-1, +1, -1},
925 {-1, -1, +1}, {+1, -1, +1}, {+1, +1, +1}, {-1, +1, +1}
927 const int quad_e[NE][4] =
929 {3, 2, 1, 0}, {0, 1, 5, 4}, {1, 2, 6, 5},
930 {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}
933 for (
int j = 0; j < NV; j++) {
AddVertex(quad_v[j]); }
934 for (
int j = 0; j < NE; j++) {
AddQuad(quad_e[j], j+1); }
942 void Snap() { SnapNodesToUnitSphere(); }
944 void BoundaryConditions()
954 for (
int e = 0; e < fes->
GetNE(); e++)
961 for (
int dof = 0; dof < dofs.
Size(); dof++)
965 const int k = dofs[dof];
966 MFEM_ASSERT(k >= 0,
"");
967 PointMat.
Mult(one, X);
968 const bool halfX = std::abs(X[0]) <
EPS && X[1] <= 0.0;
969 const bool halfY = std::abs(X[2]) <
EPS && X[1] >= 0.0;
970 const bool is_on_bc = halfX || halfY;
971 for (
int c = 0; c <
SDIM; c++)
972 { ess_vdofs[fes->
DofToVDof(k, c)] = is_on_bc; }
990struct QuarterPeach:
public Surface
992 QuarterPeach(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
997 const real_t x = 2.0*X[0]-1.0;
999 const real_t r = sqrt(x*x + y*y);
1001 (y==0.0 && x>0.0) ? 0. :
1002 (y==0.0 && x<0.0) ?
PI : acos(x/r);
1003 const real_t sqrtx = sqrt(1.0 + x*x);
1004 const real_t sqrty = sqrt(1.0 + y*y);
1005 const bool yaxis =
PI/4.0<
t &&
t < 3.0*
PI/4.0;
1006 const real_t R = yaxis?sqrtx:sqrty;
1007 const real_t gamma = r/R;
1008 p[0] = gamma * cos(
t);
1009 p[1] = gamma * sin(
t);
1015 for (
int i = 0; i <
GetNBE(); i++)
1025 for (
int v = 0; v < 2; v++)
1029 for (
int d = 0; d <
SDIM; d++)
1032 const real_t x = X[v][d] = nval[iv];
1033 if (d < 2) { R[v] += x*x; }
1036 if (std::abs(X[0][1])<=
EPS && std::abs(X[1][1])<=
EPS &&
1037 (R[0]>0.1 || R[1]>0.1))
1045struct SlottedSphere:
public Surface
1047 SlottedSphere(Opt &opt): Surface((opt.niters = 4, opt), 64, 40, 0) { }
1052 constexpr int NV1D = 4;
1053 constexpr int NV = NV1D*NV1D*NV1D;
1054 constexpr int NEPF = (NV1D-1)*(NV1D-1);
1055 constexpr int NE = NEPF*6;
1058 for (
int iv=0; iv<NV; ++iv)
1061 int iy = (iv / NV1D) % NV1D;
1062 int iz = (iv / NV1D) / NV1D;
1064 QV[iv][0] = V1D[ix];
1065 QV[iv][1] = V1D[iy];
1066 QV[iv][2] = V1D[iz];
1069 for (
int ix=0; ix<NV1D-1; ++ix)
1071 for (
int iy=0; iy<NV1D-1; ++iy)
1073 int el_offset = ix + iy*(NV1D-1);
1075 QE[0*NEPF + el_offset][0] = NV1D*ix + NV1D*NV1D*iy;
1076 QE[0*NEPF + el_offset][1] = NV1D*(ix+1) + NV1D*NV1D*iy;
1077 QE[0*NEPF + el_offset][2] = NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1078 QE[0*NEPF + el_offset][3] = NV1D*ix + NV1D*NV1D*(iy+1);
1081 QE[1*NEPF + el_offset][3] = x_off + NV1D*ix + NV1D*NV1D*iy;
1082 QE[1*NEPF + el_offset][2] = x_off + NV1D*(ix+1) + NV1D*NV1D*iy;
1083 QE[1*NEPF + el_offset][1] = x_off + NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1084 QE[1*NEPF + el_offset][0] = x_off + NV1D*ix + NV1D*NV1D*(iy+1);
1086 QE[2*NEPF + el_offset][0] = NV1D*NV1D*iy + ix;
1087 QE[2*NEPF + el_offset][1] = NV1D*NV1D*iy + ix + 1;
1088 QE[2*NEPF + el_offset][2] = NV1D*NV1D*(iy+1) + ix + 1;
1089 QE[2*NEPF + el_offset][3] = NV1D*NV1D*(iy+1) + ix;
1091 int y_off = NV1D*(NV1D-1);
1092 QE[3*NEPF + el_offset][0] = y_off + NV1D*NV1D*iy + ix;
1093 QE[3*NEPF + el_offset][1] = y_off + NV1D*NV1D*iy + ix + 1;
1094 QE[3*NEPF + el_offset][2] = y_off + NV1D*NV1D*(iy+1) + ix + 1;
1095 QE[3*NEPF + el_offset][3] = y_off + NV1D*NV1D*(iy+1) + ix;
1097 QE[4*NEPF + el_offset][0] = NV1D*iy + ix;
1098 QE[4*NEPF + el_offset][1] = NV1D*iy + ix + 1;
1099 QE[4*NEPF + el_offset][2] = NV1D*(iy+1) + ix + 1;
1100 QE[4*NEPF + el_offset][3] = NV1D*(iy+1) + ix;
1102 int z_off = NV1D*NV1D*(NV1D-1);
1103 QE[5*NEPF + el_offset][0] = z_off + NV1D*iy + ix;
1104 QE[5*NEPF + el_offset][1] = z_off + NV1D*iy + ix + 1;
1105 QE[5*NEPF + el_offset][2] = z_off + NV1D*(iy+1) + ix + 1;
1106 QE[5*NEPF + el_offset][3] = z_off + NV1D*(iy+1) + ix;
1110 QE[0*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1111 QE[0*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1113 QE[1*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1114 QE[1*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1116 QE[3*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1117 QE[3*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1119 QE[5*NEPF + 0 + 1*(NV1D-1)][0] = -1;
1120 QE[5*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1121 QE[5*NEPF + 2 + 1*(NV1D-1)][0] = -1;
1123 QE[4*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1124 QE[4*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1125 QE[4*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1127 QE[2*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1128 QE[2*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1129 for (
int j = 0; j < NV; j++) {
AddVertex(QV[j]); }
1130 for (
int j = 0; j < NE; j++)
1132 if (QE[j][0] < 0) {
continue; }
1141 void Snap() { SnapNodesToUnitSphere(); }
1144static int Problem0(Opt &opt)
1147 Surface *S =
nullptr;
1148 switch (opt.surface)
1150 case 0: S =
new MeshFromFile(opt);
break;
1151 case 1: S =
new Catenoid(opt);
break;
1152 case 2: S =
new Helicoid(opt);
break;
1153 case 3: S =
new Enneper(opt);
break;
1154 case 4: S =
new Hold(opt);
break;
1155 case 5: S =
new Costa(opt);
break;
1156 case 6: S =
new Shell(opt);
break;
1157 case 7: S =
new Scherk(opt);
break;
1158 case 8: S =
new FullPeach(opt);
break;
1159 case 9: S =
new QuarterPeach(opt);
break;
1160 case 10: S =
new SlottedSphere(opt);
break;
1161 default: MFEM_ABORT(
"Unknown surface (surface <= 10)!");
1171static real_t u0(
const Vector &x) {
return sin(3.0 *
PI * (x[1] + x[0])); }
1175static real_t qf(
const int order,
const int ker,
Mesh &m,
1182 const int NE(m.
GetNE());
1190 MFEM_VERIFY(ND == D1D*D1D,
"");
1191 MFEM_VERIFY(NQ == Q1D*Q1D,
"");
1193 Vector Eu(ND*NE), grad_u(
DIM*NQ*NE), sum(NE*NQ), one(NE*NQ);
1194 qi->SetOutputLayout(QVectorLayout::byVDIM);
1198 qi->Derivatives(Eu, grad_u);
1203 auto grdU =
Reshape(grad_u.Read(),
DIM, Q1D, Q1D, NE);
1204 auto S =
Reshape(sum.Write(), Q1D, Q1D, NE);
1208 MFEM_FOREACH_THREAD(qy,y,Q1D)
1210 MFEM_FOREACH_THREAD(qx,x,Q1D)
1212 const real_t w = W(qx, qy);
1213 const real_t J11 = J(qx, qy, 0, 0, e);
1214 const real_t J12 = J(qx, qy, 1, 0, e);
1215 const real_t J21 = J(qx, qy, 0, 1, e);
1216 const real_t J22 = J(qx, qy, 1, 1, e);
1217 const real_t det = detJ(qx, qy, e);
1218 const real_t area = w * det;
1219 const real_t gu0 = grdU(0, qx, qy, e);
1220 const real_t gu1 = grdU(1, qx, qy, e);
1221 const real_t tgu0 = (J22*gu0 - J12*gu1)/det;
1222 const real_t tgu1 = (J11*gu1 - J21*gu0)/det;
1223 const real_t ngu = tgu0*tgu0 + tgu1*tgu1;
1224 const real_t s = (ker ==
AREA) ? sqrt(1.0 + ngu) :
1225 (ker ==
NORM) ? ngu : 0.0;
1226 S(qx, qy, e) = area *
s;
1234static int Problem1(Opt &opt)
1236 const int order = opt.order;
1251 u.ProjectCoefficient(u0_fc);
1254 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh,
GLVIZ_W,
GLVIZ_H, &
u); }
1263 for (
int i = 0; i < opt.niters; i++)
1268 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
1269 const real_t q_uold = qf(order,
AREA, mesh, fes, uold);
1270 MFEM_VERIFY(std::abs(q_uold) >
EPS,
"");
1274 a.FormLinearSystem(ess_tdof_list,
u,
b, A, X, B);
1277 a.RecoverFEMSolution(X,
b,
u);
1279 const real_t norm = sqrt(std::abs(qf(order,
NORM, mesh, fes, eps)));
1280 const real_t area = qf(order,
AREA, mesh, fes,
u);
1283 mfem::out <<
"Iteration " << i <<
", norm: " << norm
1284 <<
", area: " << area << std::endl;
1286 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh, &
u); }
1287 if (opt.print) { Surface::Print(opt, &mesh, &
u); }
1288 if (norm <
NRM) {
break; }
1296 opt.sz = opt.id = 0;
1299 args.
AddOption(&opt.pb,
"-p",
"--problem",
"Problem to solve.");
1300 args.
AddOption(&opt.mesh_file,
"-m",
"--mesh",
"Mesh file to use.");
1301 args.
AddOption(&opt.wait,
"-w",
"--wait",
"-no-w",
"--no-wait",
1302 "Enable or disable a GLVis pause.");
1303 args.
AddOption(&opt.radial,
"-rad",
"--radial",
"-no-rad",
"--no-radial",
1304 "Enable or disable radial constraints in solver.");
1305 args.
AddOption(&opt.nx,
"-x",
"--num-elements-x",
1306 "Number of elements in x-direction.");
1307 args.
AddOption(&opt.ny,
"-y",
"--num-elements-y",
1308 "Number of elements in y-direction.");
1309 args.
AddOption(&opt.order,
"-o",
"--order",
"Finite element order.");
1310 args.
AddOption(&opt.refine,
"-r",
"--ref-levels",
"Refinement");
1311 args.
AddOption(&opt.niters,
"-n",
"--niter-max",
"Max number of iterations");
1312 args.
AddOption(&opt.surface,
"-s",
"--surface",
"Choice of the surface.");
1313 args.
AddOption(&opt.pa,
"-pa",
"--partial-assembly",
"-no-pa",
1314 "--no-partial-assembly",
"Enable Partial Assembly.");
1315 args.
AddOption(&opt.tau,
"-t",
"--tau",
"Costa scale factor.");
1316 args.
AddOption(&opt.lambda,
"-l",
"--lambda",
"Lambda step toward solution.");
1317 args.
AddOption(&opt.amr,
"-a",
"--amr",
"-no-a",
"--no-amr",
"Enable AMR.");
1318 args.
AddOption(&opt.amr_threshold,
"-at",
"--amr-threshold",
"AMR threshold.");
1319 args.
AddOption(&opt.device_config,
"-d",
"--device",
1320 "Device configuration string, see Device::Configure().");
1321 args.
AddOption(&opt.keys,
"-k",
"--keys",
"GLVis configuration keys.");
1322 args.
AddOption(&opt.vis,
"-vis",
"--visualization",
"-no-vis",
1323 "--no-visualization",
"Enable or disable visualization.");
1324 args.
AddOption(&opt.vis_mesh,
"-vm",
"--vis-mesh",
"-no-vm",
1325 "--no-vis-mesh",
"Enable or disable mesh visualization.");
1326 args.
AddOption(&opt.by_vdim,
"-c",
"--solve-byvdim",
1327 "-no-c",
"--solve-bynodes",
1328 "Enable or disable the 'ByVdim' solver");
1329 args.
AddOption(&opt.print,
"-print",
"--print",
"-no-print",
"--no-print",
1330 "Enable or disable result output (files in mfem format).");
1331 args.
AddOption(&opt.snapshot,
"-ss",
"--snapshot",
"-no-ss",
"--no-snapshot",
1332 "Enable or disable GLVis snapshot.");
1335 MFEM_VERIFY(opt.lambda >= 0.0 && opt.lambda <= 1.0,
"");
1339 Device device(opt.device_config);
1340 if (!opt.id) { device.
Print(); }
1342 if (opt.pb == 0) { Problem0(opt); }
1344 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...
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
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 SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
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 ...
static void MarkerToList(const Array< int > &marker, Array< int > &list)
Convert a Boolean marker array to a list containing all marked indices.
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.
Data type for Gauss-Seidel smoother of sparse matrix.
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 Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
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.
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.
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.
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.
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)
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)
constexpr Element::Type QUAD
cdouble WeierstrassZeta(const cdouble z, const cdouble w1=0.5, const cdouble w3=real_t(0.5) *I)
cdouble WeierstrassP(const cdouble z, const cdouble w1=0.5, const cdouble w3=real_t(0.5) *I)