one_d_poisson.cc
Go to the documentation of this file.
1 //kruemelmonster
2 //LIC// ====================================================================
3 //LIC// This file forms part of oomph-lib, the object-oriented,
4 //LIC// multi-physics finite-element library, available
5 //LIC// at http://www.oomph-lib.org.
6 //LIC//
7 //LIC// Version 1.0; svn revision $LastChangedRevision$
8 //LIC//
9 //LIC// $LastChangedDate$
10 //LIC//
11 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
12 //LIC//
13 //LIC// This library is free software; you can redistribute it and/or
14 //LIC// modify it under the terms of the GNU Lesser General Public
15 //LIC// License as published by the Free Software Foundation; either
16 //LIC// version 2.1 of the License, or (at your option) any later version.
17 //LIC//
18 //LIC// This library is distributed in the hope that it will be useful,
19 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
20 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 //LIC// Lesser General Public License for more details.
22 //LIC//
23 //LIC// You should have received a copy of the GNU Lesser General Public
24 //LIC// License along with this library; if not, write to the Free Software
25 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 //LIC// 02110-1301 USA.
27 //LIC//
28 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
29 //LIC//
30 //LIC//====================================================================
31 //Driver for a simple 1D poisson problem
32 
33 // Generic oomph-lib routines
34 #include "generic.h"
35 
36 // Include Poisson elements/equations
37 #include "poisson.h"
38 
39 // Include the mesh
40 #include "meshes/one_d_mesh.h"
41 
42 using namespace std;
43 
44 using namespace oomph;
45 
46 //==start_of_namespace================================================
47 /// Namespace for fish-shaped solution of 1D Poisson equation
48 //====================================================================
50 {
51 
52  /// \short Sign of the source function
53  /// (- gives the upper half of the fish, + the lower half)
54  int Sign=-1;
55 
56 
57  /// Exact, fish-shaped solution as a 1D vector
58  void get_exact_u(const Vector<double>& x, Vector<double>& u)
59  {
60  u[0] = double(Sign)*((sin(sqrt(30.0))-1.0)*x[0]-sin(sqrt(30.0)*x[0]));
61  }
62 
63 
64  /// Source function required to make the fish shape an exact solution
65  void source_function(const Vector<double>& x, double& source)
66  {
67  source = double(Sign)*30.0*sin(sqrt(30.0)*x[0]);
68  }
69 
70 } // end of namespace
71 
72 
73 
74 
75 
76 
77 
78 //==start_of_problem_class============================================
79 /// 1D Poisson problem in unit interval.
80 //====================================================================
81 template<class ELEMENT>
82 class OneDPoissonProblem : public Problem
83 {
84 
85 public:
86 
87  /// Constructor: Pass number of elements and pointer to source function
88  OneDPoissonProblem(const unsigned& n_element,
89  PoissonEquations<1>::PoissonSourceFctPt source_fct_pt);
90 
91  /// Destructor (empty)
93  {
94  delete mesh_pt();
95  }
96 
97  /// Update the problem specs before solve: (Re)set boundary conditions
98  void actions_before_newton_solve();
99 
100  /// Update the problem specs after solve (empty)
102 
103  /// \short Doc the solution, pass the number of the case considered,
104  /// so that output files can be distinguished.
105  void doc_solution(const unsigned& label);
106 
107 private:
108 
109  /// Pointer to source function
110  PoissonEquations<1>::PoissonSourceFctPt Source_fct_pt;
111 
112 }; // end of problem class
113 
114 
115 
116 
117 
118 //=====start_of_constructor===============================================
119 /// \short Constructor for 1D Poisson problem in unit interval.
120 /// Discretise the 1D domain with n_element elements of type ELEMENT.
121 /// Specify function pointer to source function.
122 //========================================================================
123 template<class ELEMENT>
125  PoissonEquations<1>::PoissonSourceFctPt source_fct_pt) :
126  Source_fct_pt(source_fct_pt)
127 {
128  Problem::Sparse_assembly_method = Perform_assembly_using_two_arrays;
129 
130 // Problem::Problem_is_nonlinear = false;
131  // Set domain length
132  double L=1.0;
133 
134  // Build mesh and store pointer in Problem
135  Problem::mesh_pt() = new OneDMesh<ELEMENT>(n_element,L);
136 
137  // Set the boundary conditions for this problem: By default, all nodal
138  // values are free -- we only need to pin the ones that have
139  // Dirichlet conditions.
140 
141  // Pin the single nodal value at the single node on mesh
142  // boundary 0 (= the left domain boundary at x=0)
143  mesh_pt()->boundary_node_pt(0,0)->pin(0);
144 
145  // Pin the single nodal value at the single node on mesh
146  // boundary 1 (= the right domain boundary at x=1)
147  mesh_pt()->boundary_node_pt(1,0)->pin(0);
148 
149  // Complete the setup of the 1D Poisson problem:
150 
151  // Loop over elements and set pointers to source function
152  for(unsigned i=0;i<n_element;i++)
153  {
154  // Upcast from GeneralisedElement to the present element
155  ELEMENT *elem_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
156 
157  //Set the source function pointer
158  elem_pt->source_fct_pt() = Source_fct_pt;
159  }
160 
161  // Setup equation numbering scheme
162  assign_eqn_numbers();
163 
164 } // end of constructor
165 
166 
167 
168 
169 //===start_of_actions_before_newton_solve========================================
170 /// \short Update the problem specs before solve: (Re)set boundary values
171 /// from the exact solution.
172 //========================================================================
173 template<class ELEMENT>
175 {
176 
177  // Assign boundary values for this problem by reading them out
178  // from the exact solution.
179 
180  // Left boundary is node 0 in the mesh:
181  Node* left_node_pt=mesh_pt()->node_pt(0);
182 
183  // Determine the position of the boundary node (the exact solution
184  // requires the coordinate in a 1D vector!)
185  Vector<double> x(1);
186  x[0]=left_node_pt->x(0);
187 
188  // Boundary value (read in from exact solution which returns
189  // the solution in a 1D vector)
190  Vector<double> u(1);
192 
193  // Assign the boundary condition to one (and only) nodal value
194  left_node_pt->set_value(0,u[0]);
195 
196 
197  // Right boundary is last node in the mesh:
198  unsigned last_node=mesh_pt()->nnode()-1;
199  Node* right_node_pt=mesh_pt()->node_pt(last_node);
200 
201  // Determine the position of the boundary node
202  x[0]=right_node_pt->x(0);
203 
204  // Boundary value (read in from exact solution which returns
205  // the solution in a 1D vector)
207 
208  // Assign the boundary condition to one (and only) nodal value
209  right_node_pt->set_value(0,u[0]);
210 
211 
212 } // end of actions before solve
213 
214 
215 
216 //===start_of_doc=========================================================
217 /// Doc the solution in tecplot format. Label files with label.
218 //========================================================================
219 template<class ELEMENT>
220 void OneDPoissonProblem<ELEMENT>::doc_solution(const unsigned& label)
221 {
222  using namespace StringConversion;
223 
224  // Number of plot points
225  unsigned npts;
226  npts=5;
227 
228  // Output solution with specified number of plot points per element
229  ofstream solution_file(("soln" + to_string(label) + ".dat").c_str());
230  mesh_pt()->output(solution_file,npts);
231  solution_file.close();
232 
233  // Output exact solution at much higher resolution (so we can
234  // see how well the solutions agree between nodal points)
235  ofstream exact_file(("exact_soln" + to_string(label) + ".dat").c_str());
236  mesh_pt()->output_fct(exact_file,20*npts,FishSolnOneDPoisson::get_exact_u);
237  exact_file.close();
238 
239  // Doc pointwise error and compute norm of error and of the solution
240  double error,norm;
241  ofstream error_file(("error" + to_string(label) + ".dat").c_str());
242  mesh_pt()->compute_error(error_file,FishSolnOneDPoisson::get_exact_u,
243  error,norm);
244  error_file.close();
245 
246  // Doc error norm:
247  cout << "\nNorm of error : " << sqrt(error) << std::endl;
248  cout << "Norm of solution : " << sqrt(norm) << std::endl << std::endl;
249  cout << std::endl;
250 
251 } // end of doc
252 
253 
254 
255 ////////////////////////////////////////////////////////////////////////
256 ////////////////////////////////////////////////////////////////////////
257 ////////////////////////////////////////////////////////////////////////
258 
259 
260 //======start_of_main==================================================
261 /// Driver for 1D Poisson problem
262 //=====================================================================
263 int main()
264 {
265 
266  // Set up the problem:
267  // Solve a 1D Poisson problem using a source function that generates
268  // a fish shaped exact solution
269  unsigned n_element=40; //Number of elements
270  OneDPoissonProblem<QPoissonElement<1,4> > //Element type as template parameter
271  problem(n_element,FishSolnOneDPoisson::source_function);
272 
273  // Check whether the problem can be solved
274  cout << "\n\n\nProblem self-test ";
275  if (problem.self_test()==0)
276  {
277  cout << "passed: Problem can be solved." << std::endl;
278  }
279  else
280  {
281  throw OomphLibError("failed!",
282  OOMPH_CURRENT_FUNCTION,OOMPH_EXCEPTION_LOCATION);
283  }
284 
285  // Set the sign of the source function:
286  cout << "\n\n\nSolving with negative sign:\n" << std::endl;
288 
289  // Solve the problem with this Sign
290  problem.newton_solve();
291 
292  //Output solution for this case (label output files with "0")
293  problem.doc_solution(0);
294 
295 
296  // Change the sign of the source function:
297  cout << "\n\n\nSolving with positive sign:\n" << std::endl;
299 
300  // Re-solve the problem with this Sign (boundary conditions get
301  // updated automatically when Problem::actions_before_newton_solve() is
302  // called.
303  problem.newton_solve();
304 
305  //Output solution for this case (label output files with "1")
306  problem.doc_solution(1);
307 
308 } // end of main
309 
310 
311 
312 
313 
314 
315 
316 
317 
Namespace for fish-shaped solution of 1D Poisson equation.
1D Poisson problem in unit interval.
int main()
Driver for 1D Poisson problem.
void actions_before_newton_solve()
Update the problem specs before solve: (Re)set boundary conditions.
void source_function(const Vector< double > &x, double &source)
Source function required to make the fish shape an exact solution.
int Sign
Sign of the source function (- gives the upper half of the fish, + the lower half) ...
void doc_solution(const unsigned &label)
Doc the solution, pass the number of the case considered, so that output files can be distinguished...
PoissonEquations< 1 >::PoissonSourceFctPt Source_fct_pt
Pointer to source function.
~OneDPoissonProblem()
Destructor (empty)
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact, fish-shaped solution as a 1D vector.
OneDPoissonProblem(const unsigned &n_element, PoissonEquations< 1 >::PoissonSourceFctPt source_fct_pt)
Constructor: Pass number of elements and pointer to source function.
void actions_after_newton_solve()
Update the problem specs after solve (empty)