From 2ecc1c82f00546248a36569c8df5e0c111262c3d Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 23 Apr 2002 16:05:00 +0000 Subject: [PATCH] Add some more docs. git-svn-id: https://svn.dealii.org/trunk@5717 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/examples/step-14/step-14.cc | 319 ++++++++++++++++++++++------ 1 file changed, 253 insertions(+), 66 deletions(-) diff --git a/deal.II/examples/step-14/step-14.cc b/deal.II/examples/step-14/step-14.cc index e3b5b5b4b7..fbeaa43fb7 100644 --- a/deal.II/examples/step-14/step-14.cc +++ b/deal.II/examples/step-14/step-14.cc @@ -354,7 +354,6 @@ namespace LaplaceSolver *boundary_values, boundary_value_map); - thread_manager.wait (); linear_system.hanging_node_constraints.condense (linear_system.matrix); @@ -680,78 +679,265 @@ namespace LaplaceSolver }; -template -class Solution : public Function + // @sect3{Equation data} + // + // In this example program, we work + // with the same data sets as in the + // previous one, but as it may so + // happen that someone wants to run + // the program with a different + // solution and right hand side + // function, we show a simple + // technique to do exactly that. For + // more clarity, we furthermore pack + // everything that has to do with + // equation data into a namespace of + // its own. + // + // Basically, the idea is as follows: + // let us have a structure for each + // set of data, in which we have two + // subclasses, one called + // ``Solution'' for the exact + // solution (and also used as right + // hand side), and one called + // ``RightHandSide''. Since the + // solution of the previous example + // program looked like curved ridges, + // we use this name here for the + // enclosing class. Note that the + // names of the two inner class have + // to be the same for all enclosing + // classes, and also that we have + // attached the dimension template + // argument to the enclosing class + // rather than to the inner ones, to + // make further processing simpler. + // (From a language viewpoint, a + // namespace would be better to + // encapsulate these inner classes, + // rather than a structure. However, + // namespaces cannot be given as + // template arguments, so we use a + // structure to allow a second object + // to select from within its given + // argument. The enclosing structure, + // of course, has no members apart + // from the classes it declares, and + // will never be instantiated.) + // + // The idea is then the following: we + // can generate objects for + // solution/boundary values and right + // hand side by simply giving the + // name of the outer class as a + // template argument to a class which + // we call here ``Data::SetUp'', and + // it then creates objects for the + // inner classes. In this case, to + // get all that characterizes the + // curved ridge solution, we would + // simply generate an instance of + // ``Data::SetUp'', + // and everything we need to know + // about the solution would be static + // member variables of that object. + // + // This approach might seem like + // overkill in this case, but will + // become very handy once a certain + // set up is not only characterized + // by a solution (or Dirichlet + // boundary values) and a right hand + // side function, but in addition by + // material properties, Neumann + // values, different boundary + // descriptors, etc. In that case, + // the ``SetUp'' class might consist + // of a dozen or more objects, and + // each descriptor class (like the + // ``CurvedRidges'' class below) + // would have to provide them. Then, + // you will be happy to be able to + // change from one set of data to + // another by only changing the + // template argument to the ``SetUp'' + // class at one place, rather than at + // many. + // + // With this framework for different + // test cases, we are almost + // finished, but one thing remains: + // by now we can select statically, + // by changing one template argument, + // which data set to choose. In order + // to be able to do that dynamically, + // i.e. at run time, we need a base + // class. This we provide in the + // obvious way, see below, with + // virtual abstract functions. It + // forces us to introduce a second + // template parameter ``dim'' which + // we need for the base class (which + // could be avoided using some + // template magic, but we omit that), + // but that's all. + // + // Adding new testcases is now + // simple, you don't have to touch + // the framework classes, only a + // structure like the + // ``CurvedRidges'' one is needed. +namespace Data { - public: - Solution () : Function () {}; - - virtual double value (const Point &p, - const unsigned int component) const; -}; + // @sect4{The SetUpBase and SetUp classes} + + // Based on the above description, + // the ``SetUpBase'' class then looks + // like this: + template + struct SetUpBase + { + virtual + const Function & get_solution () const = 0; + virtual + const Function & get_right_hand_side () const = 0; + }; -template -double -Solution::value (const Point &p, - const unsigned int /*component*/) const -{ -// double q = p(0); -// for (unsigned int i=1; i + struct SetUp : public SetUpBase + { + SetUp () {}; + virtual + const Function & get_solution () const; -template -class RightHandSide : public Function -{ - public: - RightHandSide () {}; - - virtual double value (const Point &p, - const unsigned int component) const; -}; + virtual + const Function & get_right_hand_side () const; + + private: + static const typename Traits::Solution solution; + static const typename Traits::RightHandSide right_hand_side; + }; + // We have to provide definitions + // for the static member variables + // of the above class: + template + const typename Traits::Solution SetUp::solution; + template + const typename Traits::RightHandSide SetUp::right_hand_side; + + // And definitions of the member + // functions: + template + const Function & + SetUp::get_solution () const + { + return solution; + }; -template -double -RightHandSide::value (const Point &p, - const unsigned int /*component*/) const -{ - double q = p(0); - for (unsigned int i=1; i + const Function & + SetUp::get_right_hand_side () const + { + return right_hand_side; + }; + + + // @sect4{The CurvedRidges class} + + // The class that is used to + // describe the solution and right + // hand side of the ``curved + // ridge'' problem is like so: + template + struct CurvedRidges + { + class Solution : public Function + { + public: + Solution () : Function () {}; + + virtual double value (const Point &p, + const unsigned int component) const; + }; + + + class RightHandSide : public Function + { + public: + RightHandSide () : Function () {}; + + virtual double value (const Point &p, + const unsigned int component) const; + }; + }; - return -u*(t1+t2+t3); -// double s = 1; -// for (unsigned int i=0; i + double + CurvedRidges::Solution::value (const Point &p, + const unsigned int /*component*/) const + { + double q = p(0); + for (unsigned int i=1; i + double + CurvedRidges::RightHandSide::value (const Point &p, + const unsigned int /*component*/) const + { + double q = p(0); + for (unsigned int i=1; i @@ -1232,7 +1418,7 @@ namespace LaplaceSolver data_out.attach_dof_handler (DualSolver::dof_handler); data_out.add_data_vector (xe, "e"); data_out.build_patches (); - data_out.write_gmv (x); + data_out.write_gnuplot (x); std::transform (error_indicators.begin(), error_indicators.end(), @@ -2065,16 +2251,17 @@ void solve_problem (const std::string &solver_name) std::cout << header << std::endl << std::string (header.size(), '-') << std::endl; - Triangulation triangulation; + Triangulation triangulation (Triangulation::maximum_smoothing); // create_triangulation (triangulation); GridGenerator::hyper_cube (triangulation, -1, 1); triangulation.refine_global (5); const FE_Q primal_fe(1); const FE_Q dual_fe(2); const QGauss4 quadrature; - const QGauss4 face_quadrature; - const RightHandSide rhs_function; - const Solution boundary_values; + const QGauss4 face_quadrature; + + const Data::SetUpBase *data = + new Data::SetUp,dim> (); const Point evaluation_point(0.5,0.5); const DualFunctional::PointValueEvaluation @@ -2086,8 +2273,8 @@ void solve_problem (const std::string &solver_name) dual_fe, quadrature, face_quadrature, - rhs_function, - boundary_values, + data->get_right_hand_side(), + data->get_solution(), dual_functional); TableHandler results_table; -- 2.39.5