5858#include "libmesh/perf_log.h"
5959#include "libmesh/string_to_enum.h"
6060#include "libmesh/enum_solver_package.h"
61+ #include "libmesh/dirichlet_boundaries.h"
62+ #include "libmesh/wrapped_function.h"
6163
6264// Bring in everything from the libMesh namespace
6365using namespace libMesh ;
@@ -71,6 +73,9 @@ using namespace libMesh;
7173void assemble_biharmonic (EquationSystems & es ,
7274 const std ::string & system_name );
7375
76+ // Global parameter, to be accessible to the above function
77+ bool penalty_dirichlet = true;
78+
7479
7580// Prototypes for calculation of the exact solution. Necessary
7681// for setting boundary conditions.
@@ -189,6 +194,7 @@ int main(int argc, char ** argv)
189194 const Real coarsen_percentage = input_file ("coarsen_percentage" , 0.5 );
190195 const unsigned int dim = input_file ("dimension" , 2 );
191196 const unsigned int max_linear_iterations = input_file ("max_linear_iterations" , 10000 );
197+ penalty_dirichlet = input_file ("penalty_dirichlet" , penalty_dirichlet );
192198
193199 // Skip higher-dimensional examples on a lower-dimensional libMesh build
194200 libmesh_example_requires (dim <= LIBMESH_DIM , "2D/3D support" );
@@ -217,10 +223,12 @@ int main(int argc, char ** argv)
217223 else
218224 output_file += "clough_" ;
219225
226+ output_file += approx_order_string ;
227+
220228 if (uniform_refine == 0 )
221- output_file += "adaptive " ;
229+ output_file += "_adaptive " ;
222230 else
223- output_file += "uniform " ;
231+ output_file += "_uniform " ;
224232
225233#ifdef LIBMESH_HAVE_EXODUS_API
226234 // If we have Exodus, use the same base output filename
@@ -303,6 +311,26 @@ int main(int argc, char ** argv)
303311 // function.
304312 system .attach_assemble_function (assemble_biharmonic );
305313
314+ // Give the system Dirichlet boundary conditions, if we want to
315+ // enforce those strongly.
316+ if (!penalty_dirichlet )
317+ {
318+ const std ::vector < unsigned int >
319+ all_vars (1 , system .variable_number ("u" ));
320+ std ::set < boundary_id_type > all_bdys ;
321+ for (unsigned int i = 0 ; i != dim ; ++ i )
322+ {
323+ all_bdys .insert (2 * i );
324+ all_bdys .insert (2 * i + 1 );
325+ }
326+
327+ WrappedFunction < Number > exact_val (system , exact_solution );
328+ WrappedFunction < Gradient > exact_grad (system , * exact_derivative );
329+ DirichletBoundary exact_bc (all_bdys , all_vars , exact_val ,
330+ exact_grad );
331+ system .get_dof_map ().add_dirichlet_boundary (exact_bc );
332+ }
333+
306334 // Initialize the data structures for the equation system.
307335 equation_systems .init ();
308336
@@ -377,6 +405,20 @@ int main(int argc, char ** argv)
377405 << exact_sol .h1_error ("Biharmonic" , "u" ) << " "
378406 << exact_sol .h2_error ("Biharmonic" , "u" ) << std ::endl ;
379407
408+ // Assert that we're not outright diverging here, for regression
409+ // testing. These bounds just come from eyeballing some graphs
410+ // and tacking on a huge tolerance.
411+ const dof_id_type n_dofs = system .n_dofs ();
412+
413+ if (exact_sol .l2_error ("Biharmonic" , "u" ) > 200 * std ::pow (n_dofs ,-4. /3. ))
414+ libmesh_error_msg ("Unacceptably high L2-error!" );
415+
416+ if (exact_sol .h1_error ("Biharmonic" , "u" ) > 200. /n_dofs )
417+ libmesh_error_msg ("Unacceptably high H1-error!" );
418+
419+ if (exact_sol .h2_error ("Biharmonic" , "u" ) > 400 * std ::pow (n_dofs ,-2. /3. ))
420+ libmesh_error_msg ("Unacceptably high H2-error!" );
421+
380422 // Possibly refine the mesh
381423 if (r_step + 1 != max_r_steps )
382424 {
@@ -836,12 +878,14 @@ void assemble_biharmonic(EquationSystems & es,
836878
837879
838880 // At this point the interior element integration has
839- // been completed. However, we have not yet addressed
840- // boundary conditions. For this example we will only
841- // consider simple Dirichlet boundary conditions imposed
881+ // been completed. However, we may have not yet addressed
882+ // boundary conditions, if we didn't add a DirichletBoundary to
883+ // our system earlier. In that case, we will demonstrate the
884+ // imposition of simple Dirichlet boundary conditions imposed
842885 // via the penalty method. Note that this is a fourth-order
843886 // problem: Dirichlet boundary conditions include *both*
844887 // boundary values and boundary normal fluxes.
888+ if (penalty_dirichlet )
845889 {
846890 // Start logging the boundary condition computation. We use a
847891 // macro to log everything in this scope.
0 commit comments