eighth_sphere_poisson.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 //LIC//
8 //LIC// This library is free software; you can redistribute it and/or
9 //LIC// modify it under the terms of the GNU Lesser General Public
10 //LIC// License as published by the Free Software Foundation; either
11 //LIC// version 2.1 of the License, or (at your option) any later version.
12 //LIC//
13 //LIC// This library is distributed in the hope that it will be useful,
14 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 //LIC// Lesser General Public License for more details.
17 //LIC//
18 //LIC// You should have received a copy of the GNU Lesser General Public
19 //LIC// License along with this library; if not, write to the Free Software
20 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 //LIC// 02110-1301 USA.
22 //LIC//
23 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 //LIC//
25 //LIC//====================================================================
26 //Driver for a 3D poisson problem
27 
28 //Generic routines
29 #include "generic.h"
30 
31 // The Poisson equations
32 #include "poisson.h"
33 
34 // The mesh
35 #include "meshes/eighth_sphere_mesh.h"
36 
37 using namespace std;
38 
39 using namespace oomph;
40 
41 //=============start_of_namespace=====================================
42 /// Namespace for exact solution for Poisson equation with sharp step
43 //====================================================================
45 {
46 
47  /// Parameter for steepness of step
48  double Alpha=1;
49 
50  /// Orientation (non-normalised x-component of unit vector in direction
51  /// of step plane)
52  double N_x=-1.0;
53 
54  /// Orientation (non-normalised y-component of unit vector in direction
55  /// of step plane)
56  double N_y=-1.0;
57 
58  /// Orientation (non-normalised z-component of unit vector in direction
59  /// of step plane)
60  double N_z=1.0;
61 
62 
63  /// Orientation (x-coordinate of step plane)
64  double X_0=0.0;
65 
66  /// Orientation (y-coordinate of step plane)
67  double Y_0=0.0;
68 
69  /// Orientation (z-coordinate of step plane)
70  double Z_0=0.0;
71 
72 
73  // Exact solution as a Vector
74  void get_exact_u(const Vector<double>& x, Vector<double>& u)
75  {
76  u[0] = tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-Y_0)*
77  N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*
78  N_z/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)));
79  }
80 
81  /// Exact solution as a scalar
82  void get_exact_u(const Vector<double>& x, double& u)
83  {
84  u = tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-Y_0)*
85  N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*
86  N_z/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)));
87  }
88 
89 
90  /// Source function to make it an exact solution
91  void get_source(const Vector<double>& x, double& source)
92  {
93 
94  double s1,s2,s3,s4;
95 
96  s1 = -2.0*tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
97 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
98 N_z)))*(1.0-pow(tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
99 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
100 N_z))),2.0))*Alpha*Alpha*N_x*N_x/(N_x*N_x+N_y*N_y+N_z*N_z);
101  s3 = -2.0*tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
102 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
103 N_z)))*(1.0-pow(tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
104 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
105 N_z))),2.0))*Alpha*Alpha*N_y*N_y/(N_x*N_x+N_y*N_y+N_z*N_z);
106  s4 = -2.0*tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
107 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
108 N_z)))*(1.0-pow(tanh(Alpha*((x[0]-X_0)*N_x/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[1]-
109 Y_0)*N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*N_z/sqrt(N_x*N_x+N_y*N_y+N_z*
110 N_z))),2.0))*Alpha*Alpha*N_z*N_z/(N_x*N_x+N_y*N_y+N_z*N_z);
111  s2 = s3+s4;
112  source = s1+s2;
113  }
114 
115 
116 } // end of namespace
117 
118 
119 
120 
121 /// /////////////////////////////////////////////////////////////////////
122 /// /////////////////////////////////////////////////////////////////////
123 /// /////////////////////////////////////////////////////////////////////
124 
125 
126 
127 //=======start_of_class_definition====================================
128 /// Poisson problem in refineable eighth of a sphere mesh.
129 //====================================================================
130 template<class ELEMENT>
131 class EighthSpherePoissonProblem : public Problem
132 {
133 
134 public:
135 
136  /// Constructor: Pass pointer to source function
138  PoissonEquations<3>::PoissonSourceFctPt source_fct_pt);
139 
140  /// Destructor: Empty
142 
143  /// Overload generic access function by one that returns
144  /// a pointer to the specific mesh
145  RefineableEighthSphereMesh<ELEMENT>* mesh_pt()
146  {
147  return dynamic_cast<RefineableEighthSphereMesh<ELEMENT>*>(Problem::mesh_pt());
148  }
149 
150  /// Update the problem specs after solve (empty)
152 
153  /// Update the problem specs before solve:
154  /// Set Dirchlet boundary conditions from exact solution.
156  {
157  //Loop over the boundaries
158  unsigned num_bound = mesh_pt()->nboundary();
159  for(unsigned ibound=0;ibound<num_bound;ibound++)
160  {
161  // Loop over the nodes on boundary
162  unsigned num_nod=mesh_pt()->nboundary_node(ibound);
163  for (unsigned inod=0;inod<num_nod;inod++)
164  {
165  Node* nod_pt=mesh_pt()->boundary_node_pt(ibound,inod);
166  double u;
167  Vector<double> x(3);
168  x[0]=nod_pt->x(0);
169  x[1]=nod_pt->x(1);
170  x[2]=nod_pt->x(2);
172  nod_pt->set_value(0,u);
173  }
174  }
175  }
176 
177  /// Doc the solution
178  void doc_solution(DocInfo& doc_info);
179 
180 private:
181 
182  /// Pointer to source function
183  PoissonEquations<3>::PoissonSourceFctPt Source_fct_pt;
184 
185 }; // end of class definition
186 
187 
188 
189 
190 
191 //====================start_of_constructor================================
192 /// Constructor for Poisson problem on eighth of a sphere mesh
193 //========================================================================
194 template<class ELEMENT>
196  PoissonEquations<3>::PoissonSourceFctPt source_fct_pt) :
197  Source_fct_pt(source_fct_pt)
198 {
199 
200  // Setup parameters for exact tanh solution
201  // Steepness of step
203 
204  /// Create mesh for sphere of radius 5
205  double radius=5.0;
206  Problem::mesh_pt() = new RefineableEighthSphereMesh<ELEMENT>(radius);
207 
208  // Set error estimator
209  Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
210  mesh_pt()->spatial_error_estimator_pt()=error_estimator_pt;
211 
212  // Adjust error targets for adaptive refinement
213  if (CommandLineArgs::Argc>1)
214  {
215  // Validation: Relax tolerance to get nonuniform refinement during
216  // first step
217  mesh_pt()->max_permitted_error()=0.7;
218  mesh_pt()->min_permitted_error()=0.5;
219  }
220  else
221  {
222  mesh_pt()->max_permitted_error()=0.01;
223  mesh_pt()->min_permitted_error()=0.001;
224  } // end adjustment
225 
226  //Doc the mesh boundaries
227  ofstream some_file;
228  some_file.open("boundaries.dat");
229  mesh_pt()->output_boundaries(some_file);
230  some_file.close();
231 
232  // Set the boundary conditions for this problem: All nodes are
233  // free by default -- just pin the ones that have Dirichlet conditions
234  // here (all the nodes on the boundary)
235  unsigned num_bound = mesh_pt()->nboundary();
236  for(unsigned ibound=0;ibound<num_bound;ibound++)
237  {
238  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
239  for (unsigned inod=0;inod<num_nod;inod++)
240  {
241  mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
242  }
243  } // end of pinning
244 
245 
246  //Find number of elements in mesh
247  unsigned n_element = mesh_pt()->nelement();
248 
249  // Loop over the elements to set up element-specific
250  // things that cannot be handled by constructor
251  for(unsigned i=0;i<n_element;i++)
252  {
253  // Upcast from FiniteElement to the present element
254  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
255 
256  //Set the source function pointer
257  el_pt->source_fct_pt() = Source_fct_pt;
258  }
259 
260  // Setup equation numbering
261  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
262 
263 } // end of constructor
264 
265 
266 
267 //========================start_of_doc====================================
268 /// Doc the solution
269 //========================================================================
270 template<class ELEMENT>
272 {
273  ofstream some_file;
274  char filename[100];
275 
276  // Number of plot points
277  unsigned npts;
278  npts=5;
279 
280 
281  // Output solution
282  //-----------------
283  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
284  doc_info.number());
285  some_file.open(filename);
286  mesh_pt()->output(some_file,npts);
287  some_file.close();
288 
289 
290  // Output exact solution
291  //----------------------
292  sprintf(filename,"%s/exact_soln%i.dat",doc_info.directory().c_str(),
293  doc_info.number());
294  some_file.open(filename);
295  mesh_pt()->output_fct(some_file,npts,TanhSolnForPoisson::get_exact_u);
296  some_file.close();
297 
298 
299  // Doc error
300  //----------
301  double error,norm;
302  sprintf(filename,"%s/error%i.dat",doc_info.directory().c_str(),
303  doc_info.number());
304  some_file.open(filename);
305  mesh_pt()->compute_error(some_file,TanhSolnForPoisson::get_exact_u,
306  error,norm);
307  some_file.close();
308  cout << "error: " << sqrt(error) << std::endl;
309  cout << "norm : " << sqrt(norm) << std::endl << std::endl;
310 
311 } // end of doc
312 
313 
314 /// /////////////////////////////////////////////////////////////////////
315 /// /////////////////////////////////////////////////////////////////////
316 /// /////////////////////////////////////////////////////////////////////
317 
318 
319 
320 //=========start_of_main=============================================
321 /// Driver for 3D Poisson problem in eighth of a sphere. Solution
322 /// has a sharp step. If there are
323 /// any command line arguments, we regard this as a validation run
324 /// and perform only a single adaptation.
325 //===================================================================
326 int main(int argc, char *argv[])
327 {
328 
329  // Store command line arguments
330  CommandLineArgs::setup(argc,argv);
331 
332  // Set up the problem with 27-node brick elements, pass pointer to
333  // source function
336 
337  // Setup labels for output
338  DocInfo doc_info;
339 
340  // Output directory
341  doc_info.set_directory("RESLT");
342 
343  // Step number
344  doc_info.number()=0;
345 
346  // Check if we're ready to go
347  cout << "Self test: " << problem.self_test() << std::endl;
348 
349  // Solve the problem
350  problem.newton_solve();
351 
352  //Output solution
353  problem.doc_solution(doc_info);
354 
355  //Increment counter for solutions
356  doc_info.number()++;
357 
358  // Now do (up to) three rounds of fully automatic adapation in response to
359  // error estimate
360  unsigned max_solve;
361  if (CommandLineArgs::Argc>1)
362  {
363  // Validation run: Just one adaptation
364  max_solve=1;
365  cout << "Only doing one adaptation for validation" << std::endl;
366  }
367  else
368  {
369  // Up to four adaptations
370  max_solve=4;
371  }
372 
373  for (unsigned isolve=0;isolve<max_solve;isolve++)
374  {
375  // Adapt problem/mesh
376  problem.adapt();
377 
378  // Re-solve the problem if the adaptation has changed anything
379  if ((problem.mesh_pt()->nrefined() !=0)||
380  (problem.mesh_pt()->nunrefined()!=0))
381  {
382  problem.newton_solve();
383  }
384  else
385  {
386  cout << "Mesh wasn't adapted --> we'll stop here" << std::endl;
387  break;
388  }
389 
390  //Output solution
391  problem.doc_solution(doc_info);
392 
393  //Increment counter for solutions
394  doc_info.number()++;
395  }
396 
397 // pause("done");
398 
399 } // end of main
400 
401 
402 
403 
404 
405 
406 
407 
408 
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
~EighthSpherePoissonProblem()
Destructor: Empty.
void actions_after_newton_solve()
Update the problem specs after solve (empty)
RefineableEighthSphereMesh< ELEMENT > * mesh_pt()
Overload generic access function by one that returns a pointer to the specific mesh.
void doc_solution(DocInfo &doc_info)
Doc the solution.
EighthSpherePoissonProblem(PoissonEquations< 3 >::PoissonSourceFctPt source_fct_pt)
Constructor: Pass pointer to source function.
PoissonEquations< 3 >::PoissonSourceFctPt Source_fct_pt
Pointer to source function.
void actions_before_newton_solve()
Update the problem specs before solve: Set Dirchlet boundary conditions from exact solution.
int main(int argc, char *argv[])
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Namespace for exact solution for Poisson equation with sharp step.
double N_y
Orientation (non-normalised y-component of unit vector in direction of step plane)
double Z_0
Orientation (z-coordinate of step plane)
double N_x
Orientation (non-normalised x-component of unit vector in direction of step plane)
double Y_0
Orientation (y-coordinate of step plane)
void get_source(const Vector< double > &x, double &source)
Source function to make it an exact solution.
double Alpha
Parameter for steepness of step.
double N_z
Orientation (non-normalised z-component of unit vector in direction of step plane)
void get_exact_u(const Vector< double > &x, double &u)
Exact solution as a scalar.
double X_0
Orientation (x-coordinate of step plane)
void get_exact_u(const Vector< double > &x, Vector< double > &u)