mesh_from_tetgen_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 function for a simple test poisson problem using a mesh
27 // generated from an input file generated by the tetrahedra mesh generator.
28 // the files .node, .ele and .face should be specified in this order
29 
30 //Generic routines
31 #include "generic.h"
32 
33 // Poisson equations
34 #include "poisson.h"
35 
36 // Get the mesh
37 #include "meshes/tetgen_mesh.h"
38 
39 using namespace std;
40 
41 using namespace oomph;
42 
43 //=============start_of_namespace=====================================
44 /// Namespace for exact solution for Poisson equation with sharp step
45 //====================================================================
47 {
48 
49  /// Parameter for steepness of step
50  double Alpha=3;
51 
52  /// Orientation (non-normalised x-component of unit vector in direction
53  /// of step plane)
54  double N_x=-1.0;
55 
56  /// Orientation (non-normalised y-component of unit vector in direction
57  /// of step plane)
58  double N_y=-1.0;
59 
60  /// Orientation (non-normalised z-component of unit vector in direction
61  /// of step plane)
62  double N_z=1.0;
63 
64 
65  /// Orientation (x-coordinate of step plane)
66  double X_0=0.0;
67 
68  /// Orientation (y-coordinate of step plane)
69  double Y_0=0.0;
70 
71  /// Orientation (z-coordinate of step plane)
72  double Z_0=0.0;
73 
74 
75  // Exact solution as a Vector
76  void get_exact_u(const Vector<double>& x, Vector<double>& u)
77  {
78  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)*
79  N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*
80  N_z/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)));
81  }
82 
83  /// Exact solution as a scalar
84  void get_exact_u(const Vector<double>& x, double& u)
85  {
86  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)*
87  N_y/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)+(x[2]-Z_0)*
88  N_z/sqrt(N_x*N_x+N_y*N_y+N_z*N_z)));
89  }
90 
91 
92  /// Source function to make it an exact solution
93  void get_source(const Vector<double>& x, double& source)
94  {
95 
96  double s1,s2,s3,s4;
97 
98  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]-
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)))*(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]-
101  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*
102  N_z))),2.0))*Alpha*Alpha*N_x*N_x/(N_x*N_x+N_y*N_y+N_z*N_z);
103  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]-
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)))*(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]-
106  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*
107  N_z))),2.0))*Alpha*Alpha*N_y*N_y/(N_x*N_x+N_y*N_y+N_z*N_z);
108  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]-
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)))*(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]-
111  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*
112  N_z))),2.0))*Alpha*Alpha*N_z*N_z/(N_x*N_x+N_y*N_y+N_z*N_z);
113  s2 = s3+s4;
114  source = s1+s2;
115  }
116 
117 
118 } // end of namespace
119 
120 
121 
122 
123 
124 //====================================================================
125 /// Micky mouse Poisson problem.
126 //====================================================================
127 template<class ELEMENT>
128 class PoissonProblem : public Problem
129 {
130 
131 public:
132 
133 
134  /// Constructor
135  PoissonProblem(PoissonEquations<3>::PoissonSourceFctPt source_fct_pt,
136  const string& node_file_name,
137  const string& element_file_name,
138  const string& face_file_name);
139 
140  /// Destructor (empty)
142 
143 
144  /// Update the problem specs before solve: (Re)set boundary conditions
146  {
147  //Loop over the boundaries
148  unsigned num_bound = mesh_pt()->nboundary();
149  for(unsigned ibound=0;ibound<num_bound;ibound++)
150  {
151  // Loop over the nodes on boundary
152  unsigned num_nod=mesh_pt()->nboundary_node(ibound);
153  for (unsigned inod=0;inod<num_nod;inod++)
154  {
155  Node* nod_pt=mesh_pt()->boundary_node_pt(ibound,inod);
156  double u;
157  Vector<double> x(3);
158  x[0]=nod_pt->x(0);
159  x[1]=nod_pt->x(1);
160  x[2]=nod_pt->x(2);
162  nod_pt->set_value(0,u);
163  }
164  }
165  }
166 
167  /// Update the problem specs before solve (empty)
169 
170 
171  //Access function for the specific mesh
173  {
174  return dynamic_cast<TetgenMesh<ELEMENT>*>(Problem::mesh_pt());
175  }
176 
177  /// Doc the solution
178  void doc_solution(const unsigned& nplot, DocInfo& doc_info);
179 
180 private:
181 
182  /// Pointer to source function
183  PoissonEquations<3>::PoissonSourceFctPt Source_fct_pt;
184 
185 };
186 
187 
188 
189 //========================================================================
190 /// Constructor for Poisson problem
191 //========================================================================
192 template<class ELEMENT>
194  PoissonProblem(PoissonEquations<3>::PoissonSourceFctPt source_fct_pt,
195  const string& node_file_name,
196  const string& element_file_name,
197  const string& face_file_name)
198  : Source_fct_pt(source_fct_pt)
199 {
200 
201  // Setup parameters for exact tanh solution
202 
203  // Steepness of step
205 
206 
207  //Create mesh
208  Problem::mesh_pt() = new TetgenMesh<ELEMENT>(node_file_name,
209  element_file_name,
210  face_file_name);
211 
212  // Set the boundary conditions for this problem: All nodes are
213  // free by default -- just pin the ones that have Dirichlet conditions
214  // here.
215  unsigned num_bound = mesh_pt()->nboundary();
216  for(unsigned ibound=0;ibound<num_bound;ibound++)
217  {
218  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
219  for (unsigned inod=0;inod<num_nod;inod++)
220  {
221  mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
222  }
223  }
224 
225  // Complete the build of all elements so they are fully functional
226 
227  //Find number of elements in mesh
228  unsigned n_element = mesh_pt()->nelement();
229 
230  // Loop over the elements to set up element-specific
231  // things that cannot be handled by constructor
232  for(unsigned i=0;i<n_element;i++)
233  {
234  // Upcast from GeneralElement to the present element
235  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
236 
237  //Set the source function pointer
238  el_pt->source_fct_pt() = Source_fct_pt;
239  }
240 
241  // Setup equation numbering scheme
242  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
243 
244 }
245 
246 
247 
248 //========================================================================
249 /// Doc the solution
250 //========================================================================
251 template<class ELEMENT>
252 void PoissonProblem<ELEMENT>::doc_solution(const unsigned& nplot,
253  DocInfo& doc_info)
254 {
255 
256  ofstream some_file;
257  char filename[100];
258 
259 
260  // Doc local node numbering
261  //-------------------------
262  sprintf(filename,"%s/node_numbering%i.dat",doc_info.directory().c_str(),
263  doc_info.number());
264  some_file.open(filename);
265  FiniteElement* el_pt=mesh_pt()->finite_element_pt(0);
266  unsigned nnode=el_pt->nnode();
267  unsigned ndim=el_pt->node_pt(0)->ndim();
268  for (unsigned j=0;j<nnode;j++)
269  {
270  for (unsigned i=0;i<ndim;i++)
271  {
272  some_file << el_pt->node_pt(j)->x(i) << " " ;
273  }
274  some_file << j << std::endl;
275  }
276  some_file.close();
277 
278  // Output boundaries
279  //------------------
280  sprintf(filename,"%s/boundaries%i.dat",doc_info.directory().c_str(),
281  doc_info.number());
282  some_file.open(filename);
283  mesh_pt()->output_boundaries(some_file);
284  some_file.close();
285 
286 
287  // Output solution
288  //----------------
289  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
290  doc_info.number());
291  some_file.open(filename);
292  mesh_pt()->output(some_file,nplot);
293  some_file.close();
294 
295 
296  // Output exact solution
297  //----------------------
298  sprintf(filename,"%s/exact_soln%i.dat",doc_info.directory().c_str(),
299  doc_info.number());
300  some_file.open(filename);
301  mesh_pt()->output_fct(some_file,nplot,TanhSolnForPoisson::get_exact_u);
302  some_file.close();
303 
304  // Doc error
305  //----------
306  double error,norm;
307  sprintf(filename,"%s/error%i.dat",doc_info.directory().c_str(),
308  doc_info.number());
309  some_file.open(filename);
310  mesh_pt()->compute_error(some_file,TanhSolnForPoisson::get_exact_u,
311  error,norm);
312  some_file.close();
313  cout << "error: " << sqrt(error) << std::endl;
314  cout << "norm : " << sqrt(norm) << std::endl << std::endl;
315 
316 } // end of doc
317 
318 
319 
320 
321 //========================================================================
322 /// Demonstrate how to solve Poisson problem
323 //========================================================================
324 int main(int argc, char* argv[])
325 {
326 
327 // Store command line arguments
328  CommandLineArgs::setup(argc,argv);
329 
330  // Check number of command line arguments: Need exactly three.
331  if (argc!=4)
332  {
333  std::string error_message =
334  "Wrong number of command line arguments.\n";
335  error_message +=
336  "Must specify the following file names \n";
337  error_message +=
338  "filename.node then filename.ele then filename.face\n";
339 
340  throw OomphLibError(error_message,
341  OOMPH_CURRENT_FUNCTION,
342  OOMPH_EXCEPTION_LOCATION);
343  }
344 
345  // Convert arguments to strings that specify the input file names
346  string node_file_name(argv[1]);
347  string element_file_name(argv[2]);
348  string face_file_name(argv[3]);
349 
350 
351  // Label for output
352  DocInfo doc_info;
353 
354  // Output directory
355  doc_info.set_directory("RESLT");
356 
357  // Number of output points per edge
358  unsigned nplot=2;
359 
360  // Do the problem with linear elements
361  //------------------------------------
362  {
365  node_file_name,element_file_name,face_file_name);
366 
367  // Solve the problem
368  problem.newton_solve();
369 
370  //Output solution with 2 points per edge
371  nplot=2;
372  problem.doc_solution(nplot,doc_info);
373 
374  //Increment counter for solutions
375  doc_info.number()++;
376 
377  //Output solution with 5 points per edge
378  nplot=5;
379  problem.doc_solution(nplot,doc_info);
380 
381  //Increment counter for solutions
382  doc_info.number()++;
383 
384 
385  }
386 
387 
388 
389  // Do the problem with quadratic elements
390  //---------------------------------------
391  {
394  node_file_name,element_file_name,face_file_name);
395 
396  // Solve the problem
397  problem.newton_solve();
398 
399  //Output solution with 2 points per edge
400  nplot=2;
401  problem.doc_solution(nplot,doc_info);
402 
403  //Increment counter for solutions
404  doc_info.number()++;
405 
406  //Output solution with 5 points per edge
407  nplot=5;
408  problem.doc_solution(nplot,doc_info);
409 
410  //Increment counter for solutions
411  doc_info.number()++;
412 
413  }
414 
415 
416 }
417 
418 
419 
Micky mouse Poisson problem.
void actions_before_newton_solve()
Update the problem specs before solve: (Re)set boundary conditions.
void actions_after_newton_solve()
Update the problem specs before solve (empty)
void doc_solution(const unsigned &nplot, DocInfo &doc_info)
Doc the solution.
TetgenMesh< ELEMENT > * mesh_pt()
~PoissonProblem()
Destructor (empty)
PoissonEquations< 3 >::PoissonSourceFctPt Source_fct_pt
Pointer to source function.
PoissonProblem(PoissonEquations< 3 >::PoissonSourceFctPt source_fct_pt, const string &node_file_name, const string &element_file_name, const string &face_file_name)
Constructor.
Unstructured tet mesh based on output from Tetgen: http://wias-berlin.de/software/tetgen/.
int main(int argc, char *argv[])
Demonstrate how to solve Poisson problem.
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)
////////////////////////////////////////////////////////////////////// //////////////////////////////...