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-2025 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
37using namespace std;
38
39using 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]-
97Y_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*
98N_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]-
99Y_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*
100N_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]-
102Y_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*
103N_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]-
104Y_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*
105N_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]-
107Y_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*
108N_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]-
109Y_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*
110N_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//====================================================================
130template<class ELEMENT>
131class EighthSpherePoissonProblem : public Problem
132{
133
134public:
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
180private:
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//========================================================================
194template<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//========================================================================
270template<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 snprintf(filename, sizeof(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 snprintf(filename, sizeof(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 snprintf(filename, sizeof(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//===================================================================
326int 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
Poisson problem in refineable eighth of a sphere mesh.
~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[])
Driver for 3D Poisson problem in eighth of a sphere. Solution has a sharp step. If there are any comm...
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)
double X_0
Orientation (x-coordinate of step plane)
void get_exact_u(const Vector< double > &x, Vector< double > &u)