82using namespace common;
84int main(
int argc,
char *argv[])
87 cout <<
"\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this miniapp\n"
88 <<
"is NOT supported with the GPU version of hypre.\n\n";
89 return MFEM_SKIP_RETURN_VALUE;
98 const char *mesh_file =
"../../data/inline-quad.mesh";
100 bool visualization =
true;
101 int ser_ref_levels = 0;
102 int dirichlet_level_set_type = -1;
103 int neumann_level_set_type = -1;
104 bool dirichlet_combo =
false;
107 bool include_cut_cell =
false;
110 args.
AddOption(&mesh_file,
"-m",
"--mesh",
111 "Mesh file to use.");
113 "Finite element order (polynomial degree) or -1 for"
114 " isoparametric space.");
115 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
116 "--no-visualization",
117 "Enable or disable GLVis visualization.");
118 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
119 "Number of times to refine the mesh uniformly in serial.");
120 args.
AddOption(&dirichlet_level_set_type,
"-lst",
"--level-set-type",
122 args.
AddOption(&neumann_level_set_type,
"-nlst",
"--neumann-level-set-type",
123 "neumann-level-set-type.");
124 args.
AddOption(&dirichlet_combo,
"-dc",
"--dcombo",
125 "no-dc",
"--no-dcombo",
126 "Combination of two Dirichlet level sets.");
127 args.
AddOption(&ho_terms,
"-ho",
"--high-order",
128 "Additional high-order terms to include");
130 "Nitsche penalty parameter (~1 for 2D, ~10 for 3D).");
131 args.
AddOption(&include_cut_cell,
"-cut",
"--cut",
"-no-cut-cell",
133 "Include or not include elements cut by true boundary.");
146 if (dirichlet_level_set_type <= 0 && neumann_level_set_type <= 0)
148 dirichlet_level_set_type = 1;
150 MFEM_VERIFY((neumann_level_set_type > 0 && ho_terms < 1) ==
false,
151 "Shifted Neumann BC requires extra terms, i.e., -ho >= 1.");
156 if (myid == 0) { device.
Print(); }
159 Mesh mesh(mesh_file, 1, 1);
164 std::cout <<
"Number of elements: " << mesh.
GetNE() << std::endl;
166 MFEM_VERIFY(mesh.
Conforming(),
"AMR capability is not implemented yet!");
169 ParMesh pmesh(MPI_COMM_WORLD, mesh);
174 if (order < 1) { order = 1; }
188 int nodes_cnt = vxyz.
Size()/
dim;
189 if (dirichlet_level_set_type == 3)
191 for (
int i = 0; i < nodes_cnt; i++)
194 vxyz(i+nodes_cnt) = (1.+1.e-4)*vxyz(i+nodes_cnt)-1.e-4;
202 cout <<
"Number of finite element unknowns: " << gtsize << endl;
222 if (dirichlet_level_set_type > 0)
227 filter.
Filter(*dirichlet_dist_coef, level_set_gf);
241 MFEM_VERIFY(dirichlet_level_set_type == 5,
242 "The combo level set example has been only set for"
243 " dirichlet_level_set_type == 5.");
252 if (neumann_level_set_type > 0)
267 for (
int i = 0; i < elem_marker_gf.
Size(); i++)
269 elem_marker_gf(i) = (
real_t)elem_marker[i];
275 "Element Flags", 0, 0,
s,
s,
"Rjmpc");
287 for (
int i = 0; i < sb_dofs.
Size(); i++)
289 face_dofs(sb_dofs[i]) = 1.0;
295 "Shifted Face Dofs", 0,
s,
s,
s,
"Rjmplo");
313 if (dirichlet_level_set_type == 1 || dirichlet_level_set_type == 2 ||
314 dirichlet_level_set_type == 3)
326 filter.
Filter(combo_dist_coef, filt_gf);
335 "Input Level Set", 0, 2*
s,
s,
s,
"Rjmm");
352 "Distance Vector",
s,
s,
s,
s,
"Rjmmpcvv", 1);
360 bool inactive_elements =
false;
361 for (
int i = 0; i < pmesh.
GetNE(); i++)
363 if (!include_cut_cell &&
364 (elem_marker[i] == ShiftedFaceMarker::SBElementType::OUTSIDE ||
365 elem_marker[i] >= ShiftedFaceMarker::SBElementType::CUT))
368 inactive_elements =
true;
370 if (include_cut_cell &&
371 elem_marker[i] == ShiftedFaceMarker::SBElementType::OUTSIDE)
374 inactive_elements =
true;
377 bool inactive_elements_global;
378 MPI_Allreduce(&inactive_elements, &inactive_elements_global, 1, MPI_C_BOOL,
379 MPI_LOR, MPI_COMM_WORLD);
380 if (inactive_elements_global) { ess_elem.
Append(0); }
387 if (dirichlet_level_set_type == 1 || dirichlet_level_set_type == 4 ||
388 dirichlet_level_set_type == 5 || dirichlet_level_set_type == 6 ||
389 dirichlet_level_set_type == 8 ||
390 neumann_level_set_type == 1 || neumann_level_set_type == 7)
394 else if (dirichlet_level_set_type == 2 || neumann_level_set_type == 2)
398 else if (dirichlet_level_set_type == 3)
402 else { MFEM_ABORT(
"RHS function not set for level set type.\n"); }
409 if (dirichlet_level_set_type == 1 || dirichlet_level_set_type >= 4)
414 else if (dirichlet_level_set_type == 2)
419 else if (dirichlet_level_set_type == 3)
434 if (neumann_level_set_type == 1)
439 else if (neumann_level_set_type == 2)
445 else if (neumann_level_set_type == 7)
450 else if (neumann_level_set_type > 0)
452 MFEM_ABORT(
" Normal vector coefficient not implemented for level set.");
459 int ls_cut_marker = ShiftedFaceMarker::SBElementType::CUT;
462 Array<int> bf_dirichlet_marker(0), bf_neumann_marker(0);
464 if (dirichlet_level_set_type > 0)
479 bf_dirichlet_marker.Append(ls_cut_marker);
491 bf_dirichlet_marker.Append(ls_cut_marker);
497 if (neumann_level_set_type > 0)
499 MFEM_VERIFY(!include_cut_cell,
"include_cut_cell option must be set to"
500 " false for Neumann boundary conditions.");
502 &pmesh, *nbcCoef, *dist_vec,
503 *normalbcCoef, elem_marker,
504 ho_terms, include_cut_cell,
506 bf_neumann_marker.
Append(ls_cut_marker);
518 if (dirichlet_level_set_type > 0)
530 ho_terms), ess_shift_bdr);
534 if (neumann_level_set_type > 0)
559 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
571 a.RecoverFEMSolution(X,
b, x);
574 ofstream mesh_ofs(
"diffusion.mesh");
575 mesh_ofs.precision(8);
577 ofstream sol_ofs(
"diffusion.gf");
578 sol_ofs.precision(8);
598 "Solution",
s, 0,
s,
s,
"Rj");
602 if (dirichlet_level_set_type == 2 || dirichlet_level_set_type == 3 ||
603 (dirichlet_level_set_type == -1 && neumann_level_set_type == 2))
608 for (
int i = 0; i < nodes_cnt; i++)
611 pxyz(1) = vxyz(i+nodes_cnt);
613 if (dirichlet_level_set_type == 2 || neumann_level_set_type == 2)
617 else if (dirichlet_level_set_type == 3)
621 error(i) = std::fabs(x(i) - exact_val);
630 "Error", 2*
s, 0,
s,
s,
"Rj");
636 std::cout <<
"Global L2 error: " << global_error << endl;
641 if (myid == 0) { std::cout << setprecision(10) << norm << std::endl; }
652 delete neumann_dist_coef;
653 delete dirichlet_dist_coef;
654 delete dirichlet_dist_coef_2;
Combination of level sets: +1 inside the true domain, -1 outside.
void Add_Level_Set_Coefficient(Dist_Level_Set_Coefficient &dls_)
Level set coefficient: +1 inside the true domain, -1 outside.
Distance vector to the zero level-set.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the BiCGSTAB method.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
A coefficient that is constant across space and time.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
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.
Class for domain integration .
A general function coefficient.
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
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(),...
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)
Arbitrary order "L2-conforming" discontinuous finite elements.
void SetAttribute(int i, int attr)
Set the attribute of element i.
void Clear()
Clear the contents of the Mesh.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
void GetNodes(Vector &node_coord) const
void SetNodes(const Vector &node_coord)
Updates the vertex/node locations. Invokes NodesUpdated().
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Array< int > attributes
A list of all unique element attributes used by the Mesh.
static int WorldRank()
Return the MPI rank in 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 ExchangeFaceNbrData()
HYPRE_BigInt GlobalTrueVSize() const
Class for parallel grid function.
void ExchangeFaceNbrData()
real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const override
void ProjectDiscCoefficient(VectorCoefficient &coeff) override
Project a discontinuous vector coefficient as a grid function on a continuous finite element space....
real_t ComputeL1Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL) const override
void ProjectCoefficient(Coefficient &coeff) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void SaveAsOne(const char *fname, int precision=16) const
Class for parallel meshes.
void SetAttributes() override
Determine the sets of unique attribute values in domain and boundary elements.
void SetNodalFESpace(FiniteElementSpace *nfes) override
void PrintAsOne(std::ostream &out=mfem::out, const std::string &comments="") const
Helper class for ParaView visualization data.
void SetLevelsOfDetail(int levels_of_detail_)
virtual void Save() override
void ListShiftedFaceDofs(const Array< int > &elem_marker, Array< int > &sface_dof_list) const
void MarkElements(const ParGridFunction &ls_func, Array< int > &elem_marker)
void ListEssentialTDofs(const Array< int > &elem_marker, const Array< int > &sface_dof_list, Array< int > &ess_tdof_list, Array< int > &ess_shift_bdr) const
Base class for vector Coefficients that optionally depend on time and space.
Vector coefficient defined by a vector GridFunction.
int Size() const
Returns the size of the vector.
IterativeSolver::PrintLevel print_level
virtual void ComputeVectorDistance(Coefficient &zero_level_set, ParGridFunction &distance)
void Filter(ParGridFunction &func, ParGridFunction &ffield)
real_t AvgElementSize(ParMesh &pmesh)
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
real_t rhs_fun_xy_exponent(const Vector &x)
real_t dirichlet_velocity_xy_exponent(const Vector &x)
real_t dirichlet_velocity_xy_sinusoidal(const Vector &x)
real_t rhs_fun_xy_sinusoidal(const Vector &x)
real_t homogeneous(const Vector &x)
Boundary conditions - Dirichlet.
real_t traction_xy_exponent(const Vector &x)
Neumann condition for exponent based solution.
void normal_vector_1(const Vector &x, Vector &p)
real_t rhs_fun_circle(const Vector &x)
f for the Poisson problem (-nabla^2 u = f).
void normal_vector_2(const Vector &x, Vector &p)
Normal vector for level_set_type = 7. Circle centered at [0.5 , 0.6].
PrintLevel & FirstAndLast()