Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
About
People
Contact/Get involved
Publications
Acknowledgements
Copyright
Picture show
Go
demo_drivers
poisson
two_d_poisson_flux_bc
two_d_poisson_flux_bc.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-2026 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 simple 2D Poisson problem with flux boundary conditions
27
28
//Generic routines
29
#include "generic.h"
30
31
// The Poisson equations
32
#include "poisson.h"
33
34
// The mesh
35
#include "meshes/simple_rectangular_quadmesh.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
//=====================================================================
44
namespace
TanhSolnForPoisson
45
{
46
47
/// Parameter for steepness of "step"
48
double
Alpha
=1.0;
49
50
/// Parameter for angle Phi of "step"
51
double
TanPhi
=0.0;
52
53
/// Exact solution as a Vector
54
void
get_exact_u
(
const
Vector<double>& x, Vector<double>& u)
55
{
56
u[0]=tanh(1.0-
Alpha
*(
TanPhi
*x[0]-x[1]));
57
}
58
59
/// Source function required to make the solution above an exact solution
60
void
source_function
(
const
Vector<double>& x,
double
& source)
61
{
62
source = 2.0*tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1]))*
63
(1.0-pow(tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1])),2.0))*
64
Alpha
*
Alpha
*
TanPhi
*
TanPhi
+2.0*tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1]))*
65
(1.0-pow(tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1])),2.0))*
Alpha
*
Alpha
;
66
}
67
68
/// Flux required by the exact solution on a boundary on which x is fixed
69
void
prescribed_flux_on_fixed_x_boundary
(
const
Vector<double>& x,
70
double
& flux)
71
{
72
//The outer unit normal to the boundary is (1,0)
73
double
N[2] = {1.0, 0.0};
74
//The flux in terms of the normal is
75
flux =
76
-(1.0-pow(tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1])),2.0))*
Alpha
*
TanPhi
*N[0]+(
77
1.0-pow(tanh(-1.0+
Alpha
*(
TanPhi
*x[0]-x[1])),2.0))*
Alpha
*N[1];
78
}
79
80
}
// end of namespace
81
82
83
84
85
86
//========= start_of_problem_class=====================================
87
/// 2D Poisson problem on rectangular domain, discretised with
88
/// 2D QPoisson elements. Flux boundary conditions are applied
89
/// along boundary 1 (the boundary where x=L). The specific type of
90
/// element is specified via the template parameter.
91
//====================================================================
92
template
<
class
ELEMENT>
93
class
FluxPoissonProblem
:
public
Problem
94
{
95
96
public
:
97
98
/// Constructor: Pass pointer to source function
99
FluxPoissonProblem
(PoissonEquations<2>::PoissonSourceFctPt source_fct_pt);
100
101
/// Destructor (empty)
102
~FluxPoissonProblem
(){}
103
104
/// Doc the solution. DocInfo object stores flags/labels for where the
105
/// output gets written to
106
void
doc_solution
(DocInfo& doc_info);
107
108
private
:
109
110
/// Update the problem specs before solve: Reset boundary conditions
111
/// to the values from the exact solution.
112
void
actions_before_newton_solve
();
113
114
/// Update the problem specs after solve (empty)
115
void
actions_after_newton_solve
(){}
116
117
/// Create Poisson flux elements on the b-th boundary of the
118
/// problem's mesh
119
void
create_flux_elements
(
const
unsigned
&b);
120
121
/// Number of Poisson "bulk" elements (We're attaching the flux
122
/// elements to the bulk mesh --> only the first Npoisson_elements elements
123
/// in the mesh are bulk elements!)
124
unsigned
Npoisson_elements
;
125
126
/// Pointer to source function
127
PoissonEquations<2>::PoissonSourceFctPt
Source_fct_pt
;
128
129
};
// end of problem class
130
131
132
133
//=======start_of_constructor=============================================
134
/// Constructor for Poisson problem: Pass pointer to source function.
135
//========================================================================
136
template
<
class
ELEMENT>
137
FluxPoissonProblem<ELEMENT>::
138
FluxPoissonProblem
(PoissonEquations<2>::PoissonSourceFctPt source_fct_pt)
139
: Source_fct_pt(source_fct_pt)
140
{
141
142
// Setup mesh
143
144
// # of elements in x-direction
145
unsigned
n_x=4;
146
147
// # of elements in y-direction
148
unsigned
n_y=4;
149
150
// Domain length in x-direction
151
double
l_x=1.0;
152
153
// Domain length in y-direction
154
double
l_y=2.0;
155
156
// Build and assign mesh
157
Problem::mesh_pt()=
new
SimpleRectangularQuadMesh<ELEMENT>(n_x,n_y,l_x,l_y);
158
159
// Store number of Poisson bulk elements (= number of elements so far).
160
Npoisson_elements
=mesh_pt()->nelement();
161
162
// Create prescribed-flux elements from all elements that are
163
// adjacent to boundary 1 and add them to the (single) global mesh
164
create_flux_elements
(1);
165
166
// Set the boundary conditions for this problem: All nodes are
167
// free by default -- just pin the ones that have Dirichlet conditions
168
// here.
169
unsigned
n_bound = mesh_pt()->nboundary();
170
for
(
unsigned
b=0;b<n_bound;b++)
171
{
172
//Leave nodes on boundary 1 free
173
if
(b!=1)
174
{
175
unsigned
n_node= mesh_pt()->nboundary_node(b);
176
for
(
unsigned
n=0;n<n_node;n++)
177
{
178
mesh_pt()->boundary_node_pt(b,n)->pin(0);
179
}
180
}
181
}
182
183
// Loop over the Poisson bulk elements to set up element-specific
184
// things that cannot be handled by constructor: Pass pointer to source
185
// function
186
for
(
unsigned
e=0;e<
Npoisson_elements
;e++)
187
{
188
// Upcast from GeneralisedElement to Poisson bulk element
189
ELEMENT *el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
190
191
//Set the source function pointer
192
el_pt->source_fct_pt() =
Source_fct_pt
;
193
}
194
195
// Total number of elements:
196
unsigned
n_element=mesh_pt()->nelement();
197
198
// Loop over the flux elements (located at the "end" of the
199
// mesh) to pass function pointer to prescribed-flux function.
200
for
(
unsigned
e=
Npoisson_elements
;e<n_element;e++)
201
{
202
// Upcast from GeneralisedElement to Poisson flux element
203
PoissonFluxElement<ELEMENT> *el_pt =
204
dynamic_cast<
PoissonFluxElement<ELEMENT>*
>
(mesh_pt()->element_pt(e));
205
206
// Set the pointer to the prescribed flux function
207
el_pt->flux_fct_pt() =
208
&
TanhSolnForPoisson::prescribed_flux_on_fixed_x_boundary
;
209
}
210
211
// Setup equation numbering scheme
212
cout <<
"Number of equations: "
<< assign_eqn_numbers() << std::endl;
213
214
}
// end of constructor
215
216
217
//============start_of_create_flux_elements==============================
218
/// Create Poisson Flux Elements on the b-th boundary of the Mesh
219
//=======================================================================
220
template
<
class
ELEMENT>
221
void
FluxPoissonProblem<ELEMENT>::create_flux_elements
(
const
unsigned
&b)
222
{
223
// How many bulk elements are adjacent to boundary b?
224
unsigned
n_element = mesh_pt()->nboundary_element(b);
225
226
// Loop over the bulk elements adjacent to boundary b?
227
for
(
unsigned
e=0;e<n_element;e++)
228
{
229
// Get pointer to the bulk element that is adjacent to boundary b
230
ELEMENT* bulk_elem_pt =
dynamic_cast<
ELEMENT*
>
(
231
mesh_pt()->boundary_element_pt(b,e));
232
233
// What is the index of the face of the bulk element at the boundary
234
int
face_index = mesh_pt()->face_index_at_boundary(b,e);
235
236
// Build the corresponding prescribed-flux element
237
PoissonFluxElement<ELEMENT>* flux_element_pt =
new
238
PoissonFluxElement<ELEMENT>(bulk_elem_pt,face_index);
239
240
//Add the prescribed-flux element to the mesh
241
mesh_pt()->add_element_pt(flux_element_pt);
242
243
}
//end of loop over bulk elements adjacent to boundary b
244
245
}
// end of create_flux_elements
246
247
248
249
//====================start_of_actions_before_newton_solve================
250
/// Update the problem specs before solve: Reset boundary conditions
251
/// to the values from the exact solution.
252
//========================================================================
253
template
<
class
ELEMENT>
254
void
FluxPoissonProblem<ELEMENT>::actions_before_newton_solve
()
255
{
256
// How many boundaries are there?
257
unsigned
n_bound = mesh_pt()->nboundary();
258
259
//Loop over the boundaries
260
for
(
unsigned
i=0;i<n_bound;i++)
261
{
262
// Only update Dirichlet nodes
263
if
(i!=1)
264
{
265
// How many nodes are there on this boundary?
266
unsigned
n_node = mesh_pt()->nboundary_node(i);
267
268
// Loop over the nodes on boundary
269
for
(
unsigned
n=0;n<n_node;n++)
270
{
271
// Get pointer to node
272
Node* nod_pt = mesh_pt()->boundary_node_pt(i,n);
273
274
// Extract nodal coordinates from node:
275
Vector<double> x(2);
276
x[0]=nod_pt->x(0);
277
x[1]=nod_pt->x(1);
278
279
// Compute the value of the exact solution at the nodal point
280
Vector<double> u(1);
281
TanhSolnForPoisson::get_exact_u
(x,u);
282
283
// Assign the value to the one (and only) nodal value at this node
284
nod_pt->set_value(0,u[0]);
285
}
286
}
287
}
288
}
// end of actions before solve
289
290
291
292
//=====================start_of_doc=======================================
293
/// Doc the solution: doc_info contains labels/output directory etc.
294
//========================================================================
295
template
<
class
ELEMENT>
296
void
FluxPoissonProblem<ELEMENT>::doc_solution
(DocInfo& doc_info)
297
{
298
299
ofstream some_file;
300
char
filename[100];
301
302
// Number of plot points
303
unsigned
npts;
304
npts=5;
305
306
// Output solution
307
//-----------------
308
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,doc_info.directory().c_str(),
309
doc_info.number());
310
some_file.open(filename);
311
mesh_pt()->output(some_file,npts);
312
some_file.close();
313
314
// Output exact solution
315
//----------------------
316
snprintf(filename,
sizeof
(filename),
"%s/exact_soln%i.dat"
,doc_info.directory().c_str(),
317
doc_info.number());
318
some_file.open(filename);
319
for
(
unsigned
e=0;e<Npoisson_elements;e++)
320
{
321
ELEMENT *el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
322
el_pt->output_fct(some_file,npts,
TanhSolnForPoisson::get_exact_u
);
323
}
324
some_file.close();
325
326
// Can't use black-box error computatation routines because
327
// the mesh contains two different types of elements.
328
// error function hasn't been implemented for the prescribed
329
// flux elements...
330
331
}
// end of doc
332
333
334
335
//==========start_of_main=================================================
336
/// Demonstrate how to solve 2D Poisson problem with flux boundary
337
/// conditions
338
//========================================================================
339
int
main
()
340
{
341
342
//Set up the problem
343
//------------------
344
345
//Set up the problem with 2D nine-node elements from the
346
//QPoissonElement family. Pass pointer to source function.
347
FluxPoissonProblem<QPoissonElement<2,3>
>
348
problem(&
TanhSolnForPoisson::source_function
);
349
350
351
// Create label for output
352
//------------------------
353
DocInfo doc_info;
354
355
// Set output directory
356
doc_info.set_directory(
"RESLT"
);
357
358
// Step number
359
doc_info.number()=0;
360
361
362
363
// Check that we're ready to go:
364
//----------------------------
365
cout <<
"\n\n\nProblem self-test "
;
366
if
(problem.self_test()==0)
367
{
368
cout <<
"passed: Problem can be solved."
<< std::endl;
369
}
370
else
371
{
372
throw
OomphLibError(
"Self test failed"
,
373
OOMPH_CURRENT_FUNCTION,
374
OOMPH_EXCEPTION_LOCATION);
375
}
376
377
378
// Set the orientation of the "step" to 45 degrees
379
TanhSolnForPoisson::TanPhi
=1.0;
380
381
// Initial value for the steepness of the "step"
382
TanhSolnForPoisson::Alpha
=1.0;
383
384
// Do a couple of solutions for different forcing functions
385
//---------------------------------------------------------
386
unsigned
nstep=4;
387
for
(
unsigned
istep=0;istep<nstep;istep++)
388
{
389
// Increase the steepness of the step:
390
TanhSolnForPoisson::Alpha
+=2.0;
391
392
cout <<
"\n\nSolving for TanhSolnForPoisson::Alpha="
393
<<
TanhSolnForPoisson::Alpha
<< std::endl << std::endl;
394
395
// Solve the problem
396
problem.newton_solve();
397
398
//Output solution
399
problem.
doc_solution
(doc_info);
400
401
//Increment counter for solutions
402
doc_info.number()++;
403
}
404
405
}
//end of main
406
407
408
409
410
411
412
413
414
FluxPoissonProblem
2D Poisson problem on rectangular domain, discretised with 2D QPoisson elements. Flux boundary condit...
Definition
two_d_poisson_flux_bc.cc:94
FluxPoissonProblem::FluxPoissonProblem
FluxPoissonProblem(PoissonEquations< 2 >::PoissonSourceFctPt source_fct_pt)
Constructor: Pass pointer to source function.
Definition
two_d_poisson_flux_bc.cc:138
FluxPoissonProblem::Npoisson_elements
unsigned Npoisson_elements
Number of Poisson "bulk" elements (We're attaching the flux elements to the bulk mesh --> only the fi...
Definition
two_d_poisson_flux_bc.cc:124
FluxPoissonProblem::create_flux_elements
void create_flux_elements(const unsigned &b)
Create Poisson flux elements on the b-th boundary of the problem's mesh.
Definition
two_d_poisson_flux_bc.cc:221
FluxPoissonProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update the problem specs after solve (empty)
Definition
two_d_poisson_flux_bc.cc:115
FluxPoissonProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve: Reset boundary conditions to the values from the exact solutio...
Definition
two_d_poisson_flux_bc.cc:254
FluxPoissonProblem::Source_fct_pt
PoissonEquations< 2 >::PoissonSourceFctPt Source_fct_pt
Pointer to source function.
Definition
two_d_poisson_flux_bc.cc:127
FluxPoissonProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to.
Definition
two_d_poisson_flux_bc.cc:296
FluxPoissonProblem::~FluxPoissonProblem
~FluxPoissonProblem()
Destructor (empty)
Definition
two_d_poisson_flux_bc.cc:102
TanhSolnForPoisson
Namespace for exact solution for Poisson equation with "sharp step".
Definition
two_d_poisson_flux_bc.cc:45
TanhSolnForPoisson::prescribed_flux_on_fixed_x_boundary
void prescribed_flux_on_fixed_x_boundary(const Vector< double > &x, double &flux)
Flux required by the exact solution on a boundary on which x is fixed.
Definition
two_d_poisson_flux_bc.cc:69
TanhSolnForPoisson::TanPhi
double TanPhi
Parameter for angle Phi of "step".
Definition
two_d_poisson_flux_bc.cc:51
TanhSolnForPoisson::source_function
void source_function(const Vector< double > &x, double &source)
Source function required to make the solution above an exact solution.
Definition
two_d_poisson_flux_bc.cc:60
TanhSolnForPoisson::Alpha
double Alpha
Parameter for steepness of "step".
Definition
two_d_poisson_flux_bc.cc:48
TanhSolnForPoisson::get_exact_u
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector.
Definition
two_d_poisson_flux_bc.cc:54
main
int main()
Demonstrate how to solve 2D Poisson problem with flux boundary conditions.
Definition
two_d_poisson_flux_bc.cc:339