104 bool by_vdim =
false;
105 bool snapshot =
false;
109 real_t amr_threshold = 0.6;
110 const char *keys =
"gAm";
111 const char *device_config =
"cpu";
112 const char *mesh_file =
"../../data/mobius-strip.mesh";
116class 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 ParMesh(MPI_COMM_WORLD, *
this);
154 BoundaryConditions();
160 if (opt.vis) { opt.vis = glvis.
open(
vishost, opt.visport) == 0; }
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++)
218 void SnapNodesToUnitSphere()
222 for (
int i = 0; i <
nodes.FESpace()->GetNDofs(); i++)
224 for (
int d = 0; d <
SDIM; d++)
226 node(d) =
nodes(
nodes.FESpace()->DofToVDof(i, d));
228 node /= node.Norml2();
229 for (
int d = 0; d <
SDIM; d++)
231 nodes(
nodes.FESpace()->DofToVDof(i, d)) = node(d);
236 virtual void BoundaryConditions()
249 Opt &opt,
const Mesh *mesh,
250 const int w,
const int h,
254 glvis <<
"parallel " << opt.sz <<
" " << opt.id <<
"\n";
255 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,
269 glvis <<
"parallel " << opt.sz <<
" " << opt.id <<
"\n";
271 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::ostringstream mesh_name;
288 mesh_name << mesh_file <<
"." << std::setfill(
'0') << std::setw(6) << opt.id;
289 std::ofstream mesh_ofs(mesh_name.str().c_str());
290 mesh_ofs.precision(8);
291 mesh->
Print(mesh_ofs);
294 std::ostringstream sol_name;
295 sol_name << sol_file <<
"." << std::setfill(
'0') << std::setw(6) << opt.id;
296 std::ofstream sol_ofs(sol_name.str().c_str());
297 sol_ofs.precision(8);
314 const int print_iter = -1, max_num_iter = 2000;
317 Solver(Surface &S, Opt &opt): opt(opt), S(S), cg(MPI_COMM_WORLD),
318 a(S.fes), x(S.fes), x0(S.fes),
b(S.fes), one(1.0)
330 constexpr bool converged =
true;
331 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL);}
332 for (
int i=0; i < opt.niters; ++i)
334 if (opt.amr) { Amr(); }
335 if (opt.vis) { Surface::Visualize(S.glvis, opt, S.mesh); }
336 if (!opt.id) {
mfem::out <<
"Iteration " << i <<
": "; }
340 if (Step() == converged) {
break; }
342 if (opt.print) { Surface::Print(opt, S.mesh, S.mesh->
GetNodes()); }
345 virtual bool Step() = 0;
348 bool Converged(
const real_t rnorm) {
return rnorm <
NRM; }
354 a.FormLinearSystem(S.bc, x, b, A, X, B);
359 a.RecoverFEMSolution(X, b, x);
360 const bool by_vdim = opt.by_vdim;
367 MPI_MAX, MPI_COMM_WORLD);
369 if (!opt.id) {
mfem::out <<
"rnorm = " << rnorm << std::endl; }
370 const real_t lambda = opt.lambda;
373 MFEM_VERIFY(!opt.radial,
"'VDim solver can't use radial option!");
374 return Converged(rnorm);
382 for (
int i = 0; i <
delta.Size()/
SDIM; i++)
386 for (
int d = 0; d <
SDIM; d++)
388 ni(d) = (*nodes)(d*ndof + i);
389 di(d) =
delta(d*ndof + i);
392 const real_t ndotd = (ni*di) / (ni*ni);
395 for (
int d = 0; d <
SDIM; d++) {
delta(d*ndof + i) = di(d); }
400 add(lambda, *
nodes, (1.0-lambda), x, x);
401 return Converged(rnorm);
406 MFEM_VERIFY(opt.amr_threshold >= 0.0 && opt.amr_threshold <= 1.0,
"");
407 Mesh *smesh = S.mesh;
409 const int NE = smesh->
GetNE();
411 for (
int e = 0; e < NE; e++)
421 for (
int q = 0; q < NQ; q++)
429 minW = std::min(minW, w);
430 maxW = std::max(maxW, w);
432 if (std::abs(maxW) != 0.0)
434 const real_t rho = minW / maxW;
435 MFEM_VERIFY(rho <= 1.0,
"");
449 S.BoundaryConditions();
455 class ByNodes:
public Solver
458 ByNodes(Surface &S, Opt &opt):
Solver(S, opt)
464 bool converge = ParAXeqB();
466 return converge ? true :
false;
471 class ByVDim:
public Solver
476 auto d_Xi = Xi.
Read();
481 d_nodes[c*ndof + i] = d_Xi[i];
487 auto d_Xi = Xi.
Write();
492 d_Xi[i] = d_nodes[c*ndof + i];
496 ByVDim(Surface &S, Opt &opt):
Solver(S, opt)
501 bool cvg[
SDIM] {
false};
502 for (
int c=0; c <
SDIM; ++c)
509 const bool converged = cvg[0] && cvg[1] && cvg[2];
510 return converged ? true :
false;
516struct MeshFromFile:
public Surface
518 MeshFromFile(Opt &opt): Surface(opt, opt.mesh_file) { }
522struct Catenoid:
public Surface
524 Catenoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
526 void Prefix()
override
530 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
532 for (
int j = 0; j <= opt.ny; j++)
534 const int v_old = opt.nx + j * (opt.nx + 1);
535 const int v_new = j * (opt.nx + 1);
539 for (
int i = 0; i <
GetNE(); i++)
544 for (
int j = 0; j < nv; j++)
550 for (
int i = 0; i <
GetNBE(); i++)
555 for (
int j = 0; j < nv; j++)
577struct Helicoid:
public Surface
579 Helicoid(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
586 const real_t v = 2.0*
PI*(2.0*x[1]-1.0)/3.0;
594struct Enneper:
public Surface
596 Enneper(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
602 const real_t u = 4.0*(x[0]-0.5);
603 const real_t v = 4.0*(x[1]-0.5);
604 p[0] = +
u -
u*
u*
u/3.0 +
u*v*v;
605 p[1] = -v -
u*
u*v + v*v*v/3.0;
611struct Hold:
public Surface
613 Hold(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
615 void Prefix()
override
619 for (
int i = 0; i < v2v.Size(); i++) { v2v[i] = i; }
621 for (
int j = 0; j <= opt.ny; j++)
623 const int v_old = opt.nx + j * (opt.nx + 1);
624 const int v_new = j * (opt.nx + 1);
628 for (
int i = 0; i <
GetNE(); i++)
633 for (
int j = 0; j < nv; j++)
639 for (
int i = 0; i <
GetNBE(); i++)
644 for (
int j = 0; j < nv; j++)
659 p[0] = cos(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
660 p[1] = sin(
u)*(1.0 + 0.3*sin(3.*
u +
PI*v));
668#define I cdouble(0.0, 1.0)
755 if (abs(q2n) <
EPS) { q2n = 0.0; }
778static real_t ALPHA[4] {0.0};
779struct Costa:
public Surface
781 Costa(Opt &opt): Surface((opt.Tptr = Parametrization, opt), false) { }
783 void Prefix()
override
786 const int nx = opt.nx, ny = opt.ny;
787 MFEM_VERIFY(nx>2 && ny>2,
"");
788 const int nXhalf = (nx%2)==0 ? 4 : 2;
789 const int nYhalf = (ny%2)==0 ? 4 : 2;
790 const int nxh = nXhalf + nYhalf;
791 const int NVert = (nx+1) * (ny+1);
792 const int NElem = nx*ny - 4 - nxh;
793 const int NBdrElem = 0;
796 for (
int j = 0; j <= ny; j++)
799 for (
int i = 0; i <= nx; i++)
807 for (
int j = 0; j < ny; j++)
809 for (
int i = 0; i < nx; i++)
811 if (i == 0 && j == 0) {
continue; }
812 if (i+1 == nx && j == 0) {
continue; }
813 if (i == 0 && j+1 == ny) {
continue; }
814 if (i+1 == nx && j+1 == ny) {
continue; }
815 if ((j == 0 || j+1 == ny) && (abs(nx-(i<<1)-1)<=1)) {
continue; }
816 if ((i == 0 || i+1 == nx) && (abs(ny-(j<<1)-1)<=1)) {
continue; }
817 const int i0 = i + j*(nx+1);
818 const int i1 = i+1 + j*(nx+1);
819 const int i2 = i+1 + (j+1)*(nx+1);
820 const int i3 = i + (j+1)*(nx+1);
821 const int ind[4] = {i0, i1, i2, i3};
833 const real_t tau = ALPHA[3];
840 const bool y_top = x[1] > 0.5;
841 const bool x_top = x[0] > 0.5;
844 if (y_top) { v = 1.0 - x[1]; }
845 if (x_top) {
u = 1.0 - x[0]; }
855 p[2] = sqrt(
PI/2.)*log(abs((pw-e1)/(pw+e1)));
856 if (y_top) {
p[1] *= -1.0; }
857 if (x_top) {
p[0] *= -1.0; }
858 const bool nan = std::isnan(
p[0]) || std::isnan(
p[1]) || std::isnan(
p[2]);
859 MFEM_VERIFY(!nan,
"nan");
860 ALPHA[0] = std::fmax(
p[0], ALPHA[0]);
861 ALPHA[1] = std::fmax(
p[1], ALPHA[1]);
862 ALPHA[2] = std::fmax(
p[2], ALPHA[2]);
868 MFEM_VERIFY(ALPHA[0] > 0.0,
"");
869 MFEM_VERIFY(ALPHA[1] > 0.0,
"");
870 MFEM_VERIFY(ALPHA[2] > 0.0,
"");
872 const real_t phi = (1.0 + sqrt(5.0)) / 2.0;
873 for (
int i = 0; i <
nodes.FESpace()->GetNDofs(); i++)
875 for (
int d = 0; d <
SDIM; d++)
878 const int vdof =
nodes.FESpace()->DofToVDof(i, d);
886struct Shell:
public Surface
888 Shell(Opt &opt): Surface((opt.niters = 1, opt.Tptr = Parametrization, opt)) { }
895 const real_t v = 21.0*x[1]-15.0;
896 p[0] = +1.0*pow(1.16,v)*cos(v)*(1.0+cos(
u));
897 p[1] = -1.0*pow(1.16,v)*sin(v)*(1.0+cos(
u));
898 p[2] = -2.0*pow(1.16,v)*(1.0+sin(
u));
903struct Scherk:
public Surface
914 p[2] = log(cos(v)/cos(
u));
917 Scherk(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
921struct FullPeach:
public Surface
923 static constexpr int NV = 8;
924 static constexpr int NE = 6;
927 Surface((opt.niters = std::min(4, opt.niters), opt), NV, NE, 0) { }
929 void Prefix()
override
933 {-1, -1, -1}, {+1, -1, -1}, {+1, +1, -1}, {-1, +1, -1},
934 {-1, -1, +1}, {+1, -1, +1}, {+1, +1, +1}, {-1, +1, +1}
936 const int quad_e[NE][4] =
938 {3, 2, 1, 0}, {0, 1, 5, 4}, {1, 2, 6, 5},
939 {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}
942 for (
int j = 0; j < NV; j++) {
AddVertex(quad_v[j]); }
943 for (
int j = 0; j < NE; j++) {
AddQuad(quad_e[j], j+1); }
951 void Snap()
override { SnapNodesToUnitSphere(); }
953 void BoundaryConditions()
override
963 for (
int e = 0; e < fes->
GetNE(); e++)
970 for (
int dof = 0; dof < dofs.
Size(); dof++)
974 const int k = dofs[dof];
975 MFEM_ASSERT(k >= 0,
"");
976 PointMat.
Mult(one, X);
977 const bool halfX = std::abs(X[0]) <
EPS && X[1] <= 0.0;
978 const bool halfY = std::abs(X[2]) <
EPS && X[1] >= 0.0;
979 const bool is_on_bc = halfX || halfY;
980 for (
int c = 0; c <
SDIM; c++)
981 { ess_vdofs[fes->
DofToVDof(k, c)] = is_on_bc; }
994 ParFiniteElementSpace::MarkerToList(ess_tdofs, bc);
999struct QuarterPeach:
public Surface
1001 QuarterPeach(Opt &opt): Surface((opt.Tptr = Parametrization, opt)) { }
1006 const real_t x = 2.0*X[0]-1.0;
1008 const real_t r = sqrt(x*x + y*y);
1009 const real_t t = (x==0.0) ?
PI/2.0 :
1010 (y==0.0 && x>0.0) ? 0. :
1011 (y==0.0 && x<0.0) ?
PI : acos(x/r);
1012 const real_t sqrtx = sqrt(1.0 + x*x);
1013 const real_t sqrty = sqrt(1.0 + y*y);
1014 const bool yaxis =
PI/4.0<t && t < 3.0*
PI/4.0;
1015 const real_t R = yaxis?sqrtx:sqrty;
1016 const real_t gamma = r/R;
1017 p[0] = gamma * cos(t);
1018 p[1] = gamma * sin(t);
1022 void Postfix()
override
1024 for (
int i = 0; i <
GetNBE(); i++)
1034 for (
int v = 0; v < 2; v++)
1038 for (
int d = 0; d <
SDIM; d++)
1040 nodes->GetNodalValues(nval, d+1);
1041 const real_t x = X[v][d] = nval[iv];
1042 if (d < 2) { R[v] += x*x; }
1045 if (std::abs(X[0][1])<=
EPS && std::abs(X[1][1])<=
EPS &&
1046 (R[0]>0.1 || R[1]>0.1))
1054struct SlottedSphere:
public Surface
1056 SlottedSphere(Opt &opt): Surface((opt.niters = 4, opt), 64, 40, 0) { }
1058 void Prefix()
override
1061 constexpr int NV1D = 4;
1062 constexpr int NV = NV1D*NV1D*NV1D;
1063 constexpr int NEPF = (NV1D-1)*(NV1D-1);
1064 constexpr int NE = NEPF*6;
1067 for (
int iv=0; iv<NV; ++iv)
1070 int iy = (iv / NV1D) % NV1D;
1071 int iz = (iv / NV1D) / NV1D;
1073 QV[iv][0] = V1D[ix];
1074 QV[iv][1] = V1D[iy];
1075 QV[iv][2] = V1D[iz];
1078 for (
int ix=0; ix<NV1D-1; ++ix)
1080 for (
int iy=0; iy<NV1D-1; ++iy)
1082 int el_offset = ix + iy*(NV1D-1);
1084 QE[0*NEPF + el_offset][0] = NV1D*ix + NV1D*NV1D*iy;
1085 QE[0*NEPF + el_offset][1] = NV1D*(ix+1) + NV1D*NV1D*iy;
1086 QE[0*NEPF + el_offset][2] = NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1087 QE[0*NEPF + el_offset][3] = NV1D*ix + NV1D*NV1D*(iy+1);
1090 QE[1*NEPF + el_offset][3] = x_off + NV1D*ix + NV1D*NV1D*iy;
1091 QE[1*NEPF + el_offset][2] = x_off + NV1D*(ix+1) + NV1D*NV1D*iy;
1092 QE[1*NEPF + el_offset][1] = x_off + NV1D*(ix+1) + NV1D*NV1D*(iy+1);
1093 QE[1*NEPF + el_offset][0] = x_off + NV1D*ix + NV1D*NV1D*(iy+1);
1095 QE[2*NEPF + el_offset][0] = NV1D*NV1D*iy + ix;
1096 QE[2*NEPF + el_offset][1] = NV1D*NV1D*iy + ix + 1;
1097 QE[2*NEPF + el_offset][2] = NV1D*NV1D*(iy+1) + ix + 1;
1098 QE[2*NEPF + el_offset][3] = NV1D*NV1D*(iy+1) + ix;
1100 int y_off = NV1D*(NV1D-1);
1101 QE[3*NEPF + el_offset][0] = y_off + NV1D*NV1D*iy + ix;
1102 QE[3*NEPF + el_offset][1] = y_off + NV1D*NV1D*iy + ix + 1;
1103 QE[3*NEPF + el_offset][2] = y_off + NV1D*NV1D*(iy+1) + ix + 1;
1104 QE[3*NEPF + el_offset][3] = y_off + NV1D*NV1D*(iy+1) + ix;
1106 QE[4*NEPF + el_offset][0] = NV1D*iy + ix;
1107 QE[4*NEPF + el_offset][1] = NV1D*iy + ix + 1;
1108 QE[4*NEPF + el_offset][2] = NV1D*(iy+1) + ix + 1;
1109 QE[4*NEPF + el_offset][3] = NV1D*(iy+1) + ix;
1111 int z_off = NV1D*NV1D*(NV1D-1);
1112 QE[5*NEPF + el_offset][0] = z_off + NV1D*iy + ix;
1113 QE[5*NEPF + el_offset][1] = z_off + NV1D*iy + ix + 1;
1114 QE[5*NEPF + el_offset][2] = z_off + NV1D*(iy+1) + ix + 1;
1115 QE[5*NEPF + el_offset][3] = z_off + NV1D*(iy+1) + ix;
1119 QE[0*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1120 QE[0*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1122 QE[1*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1123 QE[1*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1125 QE[3*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1126 QE[3*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1128 QE[5*NEPF + 0 + 1*(NV1D-1)][0] = -1;
1129 QE[5*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1130 QE[5*NEPF + 2 + 1*(NV1D-1)][0] = -1;
1132 QE[4*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1133 QE[4*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1134 QE[4*NEPF + 1 + 2*(NV1D-1)][0] = -1;
1136 QE[2*NEPF + 1 + 0*(NV1D-1)][0] = -1;
1137 QE[2*NEPF + 1 + 1*(NV1D-1)][0] = -1;
1138 for (
int j = 0; j < NV; j++) {
AddVertex(QV[j]); }
1139 for (
int j = 0; j < NE; j++)
1141 if (QE[j][0] < 0) {
continue; }
1150 void Snap()
override { SnapNodesToUnitSphere(); }
1153static int Problem0(Opt &opt)
1156 Surface *S =
nullptr;
1157 switch (opt.surface)
1159 case 0: S =
new MeshFromFile(opt);
break;
1160 case 1: S =
new Catenoid(opt);
break;
1161 case 2: S =
new Helicoid(opt);
break;
1162 case 3: S =
new Enneper(opt);
break;
1163 case 4: S =
new Hold(opt);
break;
1164 case 5: S =
new Costa(opt);
break;
1165 case 6: S =
new Shell(opt);
break;
1166 case 7: S =
new Scherk(opt);
break;
1167 case 8: S =
new FullPeach(opt);
break;
1168 case 9: S =
new QuarterPeach(opt);
break;
1169 case 10: S =
new SlottedSphere(opt);
break;
1170 default: MFEM_ABORT(
"Unknown surface (surface <= 10)!");
1180static real_t u0(
const Vector &x) {
return sin(3.0 *
PI * (x[1] + x[0])); }
1184static real_t qf(
const int order,
const int ker,
Mesh &m,
1191 const int NE(m.
GetNE());
1199 MFEM_VERIFY(ND == D1D*D1D,
"");
1200 MFEM_VERIFY(NQ == Q1D*Q1D,
"");
1202 Vector Eu(ND*NE), grad_u(
DIM*NQ*NE), sum(NE*NQ), one(NE*NQ);
1203 qi->SetOutputLayout(QVectorLayout::byVDIM);
1207 qi->Derivatives(Eu, grad_u);
1212 auto grdU =
Reshape(grad_u.Read(),
DIM, Q1D, Q1D, NE);
1213 auto S =
Reshape(sum.Write(), Q1D, Q1D, NE);
1217 MFEM_FOREACH_THREAD(qy,y,Q1D)
1219 MFEM_FOREACH_THREAD(qx,x,Q1D)
1221 const real_t w = W(qx, qy);
1222 const real_t J11 = J(qx, qy, 0, 0, e);
1223 const real_t J12 = J(qx, qy, 1, 0, e);
1224 const real_t J21 = J(qx, qy, 0, 1, e);
1225 const real_t J22 = J(qx, qy, 1, 1, e);
1226 const real_t det = detJ(qx, qy, e);
1227 const real_t area = w * det;
1228 const real_t gu0 = grdU(0, qx, qy, e);
1229 const real_t gu1 = grdU(1, qx, qy, e);
1230 const real_t tgu0 = (J22*gu0 - J12*gu1)/det;
1231 const real_t tgu1 = (J11*gu1 - J21*gu0)/det;
1232 const real_t ngu = tgu0*tgu0 + tgu1*tgu1;
1233 const real_t s = (ker ==
AREA) ? sqrt(1.0 + ngu) :
1234 (ker ==
NORM) ? ngu : 0.0;
1235 S(qx, qy, e) = area * s;
1243static int Problem1(Opt &opt)
1245 const int order = opt.order;
1249 ParMesh mesh(MPI_COMM_WORLD, smesh);
1261 u.ProjectCoefficient(u0_fc);
1263 if (opt.vis) { opt.vis = glvis.
open(
vishost, opt.visport) == 0; }
1264 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh,
GLVIZ_W,
GLVIZ_H, &
u); }
1273 for (
int i = 0; i < opt.niters; i++)
1278 if (opt.pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
1279 const real_t q_uold = qf(order,
AREA, mesh, fes, uold);
1280 MFEM_VERIFY(std::abs(q_uold) >
EPS,
"");
1284 a.FormLinearSystem(ess_tdof_list,
u,
b, A, X, B);
1287 a.RecoverFEMSolution(X,
b,
u);
1289 const real_t norm = sqrt(std::abs(qf(order,
NORM, mesh, fes, eps)));
1290 const real_t area = qf(order,
AREA, mesh, fes,
u);
1293 mfem::out <<
"Iteration " << i <<
", norm: " << norm
1294 <<
", area: " << area << std::endl;
1296 if (opt.vis) { Surface::Visualize(glvis, opt, &mesh, &
u); }
1297 if (opt.print) { Surface::Print(opt, &mesh, &
u); }
1298 if (norm <
NRM) {
break; }
1313 args.
AddOption(&opt.visport,
"-p",
"--send-port",
"Socket for GLVis.");
1314 args.
AddOption(&opt.pb,
"-p",
"--problem",
"Problem to solve.");
1315 args.
AddOption(&opt.mesh_file,
"-m",
"--mesh",
"Mesh file to use.");
1316 args.
AddOption(&opt.wait,
"-w",
"--wait",
"-no-w",
"--no-wait",
1317 "Enable or disable a GLVis pause.");
1318 args.
AddOption(&opt.radial,
"-rad",
"--radial",
"-no-rad",
"--no-radial",
1319 "Enable or disable radial constraints in solver.");
1320 args.
AddOption(&opt.nx,
"-x",
"--num-elements-x",
1321 "Number of elements in x-direction.");
1322 args.
AddOption(&opt.ny,
"-y",
"--num-elements-y",
1323 "Number of elements in y-direction.");
1324 args.
AddOption(&opt.order,
"-o",
"--order",
"Finite element order.");
1325 args.
AddOption(&opt.refine,
"-r",
"--ref-levels",
"Refinement");
1326 args.
AddOption(&opt.niters,
"-n",
"--niter-max",
"Max number of iterations");
1327 args.
AddOption(&opt.surface,
"-s",
"--surface",
"Choice of the surface.");
1328 args.
AddOption(&opt.pa,
"-pa",
"--partial-assembly",
"-no-pa",
1329 "--no-partial-assembly",
"Enable Partial Assembly.");
1330 args.
AddOption(&opt.tau,
"-t",
"--tau",
"Costa scale factor.");
1331 args.
AddOption(&opt.lambda,
"-l",
"--lambda",
"Lambda step toward solution.");
1332 args.
AddOption(&opt.amr,
"-a",
"--amr",
"-no-a",
"--no-amr",
"Enable AMR.");
1333 args.
AddOption(&opt.amr_threshold,
"-at",
"--amr-threshold",
"AMR threshold.");
1334 args.
AddOption(&opt.device_config,
"-d",
"--device",
1335 "Device configuration string, see Device::Configure().");
1336 args.
AddOption(&opt.keys,
"-k",
"--keys",
"GLVis configuration keys.");
1337 args.
AddOption(&opt.vis,
"-vis",
"--visualization",
"-no-vis",
1338 "--no-visualization",
"Enable or disable visualization.");
1339 args.
AddOption(&opt.by_vdim,
"-c",
"--solve-byvdim",
1340 "-no-c",
"--solve-bynodes",
1341 "Enable or disable the 'ByVdim' solver");
1342 args.
AddOption(&opt.print,
"-print",
"--print",
"-no-print",
"--no-print",
1343 "Enable or disable result output (files in mfem format).");
1344 args.
AddOption(&opt.snapshot,
"-ss",
"--snapshot",
"-no-ss",
"--no-snapshot",
1345 "Enable or disable GLVis snapshot.");
1346 args.
AddOption(&opt.visport,
"-p",
"--send-port",
"Socket for GLVis.");
1349 MFEM_VERIFY(opt.lambda >= 0.0 && opt.lambda <= 1.0,
"");
1353 Device device(opt.device_config);
1354 if (!opt.id) { device.
Print(); }
1356 if (opt.pb == 0) { Problem0(opt); }
1358 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.
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
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...
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().
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry 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.
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.
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.
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
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 *)
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 * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
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).
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.
std::array< int, NCMesh::MaxFaceNodes > nodes