algebraic_free_boundary_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 solution of "free boundary" 2D Poisson equation in
27// fish-shaped domain with adaptivity
28
29
30// Generic oomph-lib headers
31#include "generic.h"
32
33// The Poisson equations
34#include "poisson.h"
35
36// The fish mesh
37#include "meshes/fish_mesh.h"
38
39// Circle as generalised element:
41
42using namespace std;
43
44using namespace oomph;
45
46///////////////////////////////////////////////////////////////////////
47///////////////////////////////////////////////////////////////////////
48///////////////////////////////////////////////////////////////////////
49
50
51
52//====================================================================
53/// Namespace for const source term in Poisson equation
54//====================================================================
56{
57 /// Strength of source function: default value 1.0
58 double Strength=1.0;
59
60/// Const source function
61 void get_source(const Vector<double>& x, double& source)
62 {
63 source = -Strength*(1.0+x[0]*x[1]);
64 }
65
66}
67
68
69////////////////////////////////////////////////////////////////////////
70////////////////////////////////////////////////////////////////////////
71////////////////////////////////////////////////////////////////////////
72
73
74
75//====================================================================
76/// Refineable Poisson problem in deformable fish-shaped domain.
77/// Template parameter identify the elements.
78//====================================================================
79template<class ELEMENT>
80class RefineableFishPoissonProblem : public Problem
81{
82
83public:
84
85 /// Constructor: Bool flag specifies if position of fish back is
86 /// prescribed or computed from the coupled problem. String specifies
87 /// output directory.
89 const bool& fix_position, const string& directory_name,
90 const unsigned& i_case);
91
92 /// Destructor
94
95 /// Update after Newton step: Update mesh in response to
96 /// possible changes in the wall shape
98 {
99 fish_mesh_pt()->node_update();
100 }
101
102 /// Update the problem specs after solve (empty)
104
105 /// Update the problem specs before solve: Update mesh
107 {
108 fish_mesh_pt()->node_update();
109 }
110
111 //Access function for the fish mesh
112 AlgebraicRefineableFishMesh<ELEMENT>* fish_mesh_pt()
113 {
114 return Fish_mesh_pt;
115 }
116
117 /// Return value of the "load" on the elastically supported ring
118 double& load()
119 {
120 return *Load_pt->value_pt(0);
121 }
122
123
124 /// Return value of the vertical displacement of the ring that
125 /// represents the fish's back
126 double& y_c()
127 {
128 return static_cast<ElasticallySupportedRingElement*>(fish_mesh_pt()->
129 fish_back_pt())->y_c();
130 }
131
132 /// Doc the solution
133 void doc_solution();
134
135 /// Access to DocInfo object
136 DocInfo& doc_info() {return Doc_info;}
137
138private:
139
140 /// Helper fct to set method for evaluation of shape derivs
142 {
143
144 bool done=false;
145
146 //Loop over elements and set pointers to source function
147 unsigned n_element = fish_mesh_pt()->nelement();
148 for(unsigned i=0;i<n_element;i++)
149 {
150 // Upcast from FiniteElement to the present element
151 ELEMENT *el_pt = dynamic_cast<ELEMENT*>(fish_mesh_pt()->element_pt(i));
152
153 // Direct FD
154 if (Case_id==0)
155 {
156 el_pt->evaluate_shape_derivs_by_direct_fd();
157 if (!done) std::cout << "\n\n [CR residuals] Direct FD" << std::endl;
158 }
159 // Chain rule with/without FD
160 else if ( (Case_id==1) || (Case_id==2) )
161 {
162 // It's broken but let's call it anyway to keep self-test alive
163 bool i_know_what_i_am_doing=true;
164 el_pt->evaluate_shape_derivs_by_chain_rule(i_know_what_i_am_doing);
165 if (Case_id==1)
166 {
167 el_pt->enable_always_evaluate_dresidual_dnodal_coordinates_by_fd();
168 if (!done) std::cout << "\n\n [CR residuals] Chain rule and FD"
169 << std::endl;
170 }
171 else
172 {
173 el_pt->disable_always_evaluate_dresidual_dnodal_coordinates_by_fd();
174 if (!done) std::cout << "\n\n [CR residuals] Chain rule and analytic"
175 << std::endl;
176 }
177 }
178 // Fastest with/without FD
179 else if ( (Case_id==3) || (Case_id==4) )
180 {
181 // It's broken but let's call it anyway to keep self-test alive
182 bool i_know_what_i_am_doing=true;
183 el_pt->evaluate_shape_derivs_by_fastest_method(i_know_what_i_am_doing);
184 if (Case_id==3)
185 {
186 el_pt->enable_always_evaluate_dresidual_dnodal_coordinates_by_fd();
187 if (!done) std::cout << "\n\n [CR residuals] Fastest and FD"
188 << std::endl;
189 }
190 else
191 {
192 el_pt->disable_always_evaluate_dresidual_dnodal_coordinates_by_fd();
193 if (!done) std::cout << "\n\n [CR residuals] Fastest and analytic"
194 << std::endl;
195
196 }
197 }
198 done=true;
199 }
200
201 }
202
203 /// Node at which the solution of the Poisson equation is documented
205
206 /// Trace file
207 ofstream Trace_file;
208
209 /// Pointer to fish mesh
210 AlgebraicRefineableFishMesh<ELEMENT>* Fish_mesh_pt;
211
212 /// Pointer to single-element mesh that stores the GeneralisedElement
213 /// that represents the fish back
215
216 /// Pointer to data item that stores the "load" on the fish back
217 Data* Load_pt;
218
219 /// Is the position of the fish back prescribed?
221
222 /// Doc info object
223 DocInfo Doc_info;
224
225 /// Case id
226 unsigned Case_id;
227
228};
229
230
231
232
233
234//========================================================================
235/// Constructor for adaptive Poisson problem in deformable fish-shaped
236/// domain. Pass flag if position of fish back is fixed, and the output
237/// directory.
238//========================================================================
239template<class ELEMENT>
241 const bool& fix_position, const string& directory_name,
242 const unsigned& i_case) : Fix_position(fix_position), Case_id(i_case)
243{
244
245
246 // Set output directory
247 Doc_info.set_directory(directory_name);
248
249 // Initialise step number
250 Doc_info.number()=0;
251
252 // Open trace file
253 char filename[100];
254 snprintf(filename, sizeof(filename), "%s/trace.dat",directory_name.c_str());
255 Trace_file.open(filename);
256
258 << "VARIABLES=\"load\",\"y<sub>circle</sub>\",\"u<sub>control</sub>\""
259 << std::endl;
260
261 // Set coordinates and radius for the circle that will become the fish back
262 double x_c=0.5;
263 double y_c=0.0;
264 double r_back=1.0;
265
266 // Build geometric element that will become the fish back
267 GeomObject* fish_back_pt=new ElasticallySupportedRingElement(x_c,y_c,r_back);
268
269 // Build fish mesh with geometric object that specifies the fish back
270 Fish_mesh_pt=new AlgebraicRefineableFishMesh<ELEMENT>(fish_back_pt);
271
272 // Add the fish mesh to the problem's collection of submeshes:
273 add_sub_mesh(Fish_mesh_pt);
274
275 // Build mesh that will store only the geometric wall element
276 Fish_back_mesh_pt=new Mesh;
277
278 // So far, the mesh is completely empty. Let's add the
279 // one (and only!) GeneralisedElement which represents the shape
280 // of the fish's back to it:
281 Fish_back_mesh_pt->add_element_pt(dynamic_cast<GeneralisedElement*>(
282 Fish_mesh_pt->fish_back_pt()));
283
284 // Add the fish back mesh to the problem's collection of submeshes:
285 add_sub_mesh(Fish_back_mesh_pt);
286
287 // Now build global mesh from the submeshes
288 build_global_mesh();
289
290
291 // Create/set error estimator
292 fish_mesh_pt()->spatial_error_estimator_pt()=new Z2ErrorEstimator;
293
294 // Choose a node at which the solution is documented: Choose
295 // the central node that is shared by all four elements in
296 // the base mesh because it exists at all refinement levels.
297
298 // How many nodes does element 0 have?
299 unsigned nnod=fish_mesh_pt()->finite_element_pt(0)->nnode();
300
301 // The central node is the last node in element 0:
302 Doc_node_pt=fish_mesh_pt()->finite_element_pt(0)->node_pt(nnod-1);
303
304 // Doc
305 cout << std::endl << "Control node is located at: "
306 << Doc_node_pt->x(0) << " " << Doc_node_pt->x(1)
307 << std::endl << std::endl;
308
309 // Position of fish back is prescribed
310 if (Fix_position)
311 {
312 // Create the load data object
313 Load_pt=new Data(1);
314
315 // Pin the prescribed load
316 Load_pt->pin(0);
317
318 // Pin the vertical displacement
319 dynamic_cast<ElasticallySupportedRingElement*>(
320 Fish_mesh_pt->fish_back_pt())->pin_yc();
321 }
322 // Coupled problem: The position of the fish back is determined
323 // via the solution of the Poisson equation: The solution at
324 // the control node acts as the load for the displacement of the
325 // fish back
326 else
327 {
328 // Use the solution (value 0) at the control node as the load
329 // that acts on the ring. [Note: Node == Data by inheritance]
331 }
332
333
334 // Set the pointer to the Data object that specifies the
335 // load on the fish's back
336 dynamic_cast<ElasticallySupportedRingElement*>(Fish_mesh_pt->fish_back_pt())->
337 set_load_pt(Load_pt);
338
339
340 // Set the boundary conditions for this problem: All nodes are
341 // free by default -- just pin the ones that have Dirichlet conditions
342 // here.
343 unsigned num_bound = fish_mesh_pt()->nboundary();
344 for(unsigned ibound=0;ibound<num_bound;ibound++)
345 {
346 unsigned num_nod= fish_mesh_pt()->nboundary_node(ibound);
347 for (unsigned inod=0;inod<num_nod;inod++)
348 {
349 fish_mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
350 }
351 }
352
353
354 // Set homogeneous boundary conditions on all boundaries
355 for(unsigned ibound=0;ibound<num_bound;ibound++)
356 {
357 // Loop over the nodes on boundary
358 unsigned num_nod=fish_mesh_pt()->nboundary_node(ibound);
359 for (unsigned inod=0;inod<num_nod;inod++)
360 {
361 fish_mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,0.0);
362 }
363 }
364
365 /// Loop over elements and set pointers to source function
366 unsigned n_element = fish_mesh_pt()->nelement();
367 for(unsigned i=0;i<n_element;i++)
368 {
369 // Upcast from FiniteElement to the present element
370 ELEMENT *el_pt = dynamic_cast<ELEMENT*>(fish_mesh_pt()->element_pt(i));
371
372 //Set the source function pointer
373 el_pt->source_fct_pt() = &ConstSourceForPoisson::get_source;
374 }
375
376 // Set shape derivative method
378
379 // Do equation numbering
380 cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
381
382}
383
384
385
386//========================================================================
387/// Destructor for Poisson problem in deformable fish-shaped domain.
388//========================================================================
389template<class ELEMENT>
391{
392 // Close trace file
393 Trace_file.close();
394
395}
396
397
398
399
400//========================================================================
401/// Doc the solution in tecplot format.
402//========================================================================
403template<class ELEMENT>
405{
406
407 ofstream some_file;
408 char filename[100];
409
410 // Number of plot points in each coordinate direction.
411 unsigned npts;
412 npts=5;
413
414
415 // Output solution
416 if (Case_id!=0)
417 {
418 snprintf(filename, sizeof(filename), "%s/soln_%i_%i.dat",Doc_info.directory().c_str(),
419 Case_id,Doc_info.number());
420 }
421 else
422 {
423 snprintf(filename, sizeof(filename), "%s/soln%i.dat",Doc_info.directory().c_str(),
424 Doc_info.number());
425 }
426 some_file.open(filename);
427 fish_mesh_pt()->output(some_file,npts);
428 some_file.close();
429
430 // Write "load", vertical position of the fish back, and solution at
431 // control node to trace file
432 Trace_file
433 << static_cast<ElasticallySupportedRingElement*>(fish_mesh_pt()->
434 fish_back_pt())->load()
435 << " "
436 << static_cast<ElasticallySupportedRingElement*>(fish_mesh_pt()->
437 fish_back_pt())->y_c()
438 << " " << Doc_node_pt->value(0) << std::endl;
439}
440
441
442
443
444
445
446
447////////////////////////////////////////////////////////////////////////
448////////////////////////////////////////////////////////////////////////
449////////////////////////////////////////////////////////////////////////
450
451
452
453
454
455//========================================================================
456/// Demonstrate how to solve 2D Poisson problem in deformable
457/// fish-shaped domain with mesh adaptation.
458//========================================================================
459template<class ELEMENT>
460void demo_fish_poisson(const string& directory_name)
461{
462
463 // Set up the problem with prescribed displacement of fish back
464 bool fix_position=true;
465 RefineableFishPoissonProblem<ELEMENT> problem(fix_position,directory_name,0);
466
467 // Doc refinement targets
468 problem.fish_mesh_pt()->doc_adaptivity_targets(cout);
469
470 // Do some uniform mesh refinement first
471 //--------------------------------------
472 problem.refine_uniformly();
473 problem.refine_uniformly();
474
475 // Initial value for the vertical displacement of the fish's back
476 problem.y_c()=-0.3;
477
478 // Loop for different fish shapes
479 //-------------------------------
480
481 // Number of steps
482 unsigned nstep=5;
483
484 // Increment in displacement
485 double dyc=0.6/double(nstep-1);
486
487 // Valiation: Just do one step
488 if (CommandLineArgs::Argc>1) nstep=1;
489
490 for (unsigned istep=0;istep<nstep;istep++)
491 {
492 // Solve/doc
493 unsigned max_solve=2;
494 problem.newton_solve(max_solve);
495 problem.doc_solution();
496
497 //Increment counter for solutions
498 problem.doc_info().number()++;
499
500 // Change vertical displacement
501 problem.y_c()+=dyc;
502 }
503}
504
505
506//========================================================================
507/// Demonstrate how to solve "elastic" 2D Poisson problem in deformable
508/// fish-shaped domain with mesh adaptation.
509//========================================================================
510template<class ELEMENT>
511void demo_elastic_fish_poisson(const string& directory_name)
512{
513
514 // Loop over all cases
515 for (unsigned i_case=0;i_case<5;i_case++)
516 //unsigned i_case=1;
517 {
518 std::cout << "[CR residuals] " << std::endl;
519 std::cout << "[CR residuals]=================================================="
520 << std::endl;
521 std::cout << "[CR residuals] " << std::endl;
522 //Set up the problem with "elastic" fish back
523 bool fix_position=false;
524 RefineableFishPoissonProblem<ELEMENT> problem(fix_position,
525 directory_name,
526 i_case);
527
528 // Doc refinement targets
529 problem.fish_mesh_pt()->doc_adaptivity_targets(cout);
530
531 // Do some uniform mesh refinement first
532 //--------------------------------------
533 problem.refine_uniformly();
534 problem.refine_uniformly();
535
536
537 // Initial value for load on fish back
538 problem.load()=0.0;
539
540 // Solve/doc
541 unsigned max_solve=2;
542 problem.newton_solve(max_solve);
543 problem.doc_solution();
544 }
545
546
547}
548
549
550
551
552
553//========================================================================
554/// Driver for "elastic" fish poisson solver with adaptation.
555/// If there are any command line arguments, we regard this as a
556/// validation run and perform only a single step.
557//========================================================================
558int main(int argc, char* argv[])
559{
560 // Store command line arguments
561 CommandLineArgs::setup(argc,argv);
562
563 // Shorthand for element type
564 typedef AlgebraicElement<RefineableQPoissonElement<2,3> > ELEMENT;
565
566 // Compute solution of Poisson equation in various domains
568
569 // Compute "elastic" coupled solution directly
570 demo_elastic_fish_poisson<ELEMENT>("RESLT_coupled");
571
572}
573
574
void demo_elastic_fish_poisson(const string &directory_name)
Demonstrate how to solve "elastic" 2D Poisson problem in deformable fish-shaped domain with mesh adap...
void demo_fish_poisson(const string &directory_name)
Demonstrate how to solve 2D Poisson problem in deformable fish-shaped domain with mesh adaptation.
int main()
Driver.
Definition circle.cc:40
Refineable Poisson problem in deformable fish-shaped domain. Template parameter identify the elements...
void set_shape_deriv_method()
Helper fct to set method for evaluation of shape derivs.
RefineableFishPoissonProblem(const bool &fix_position, const string &directory_name, const unsigned &i_case)
Constructor: Bool flag specifies if position of fish back is prescribed or computed from the coupled ...
double & load()
Return value of the "load" on the elastically supported ring.
double & y_c()
Return value of the vertical displacement of the ring that represents the fish's back.
bool Fix_position
Is the position of the fish back prescribed?
DocInfo & doc_info()
Access to DocInfo object.
void actions_before_newton_solve()
Update the problem specs before solve: Update mesh.
Node * Doc_node_pt
Node at which the solution of the Poisson equation is documented.
AlgebraicRefineableFishMesh< ELEMENT > * fish_mesh_pt()
void actions_after_newton_solve()
Update the problem specs after solve (empty)
void actions_before_newton_convergence_check()
Update after Newton step: Update mesh in response to possible changes in the wall shape.
Data * Load_pt
Pointer to data item that stores the "load" on the fish back.
Mesh * Fish_back_mesh_pt
Pointer to single-element mesh that stores the GeneralisedElement that represents the fish back.
AlgebraicRefineableFishMesh< ELEMENT > * Fish_mesh_pt
Pointer to fish mesh.
GeneralCircle "upgraded" to a GeneralisedElement: Circular ring whose position is given by.
Namespace for const source term in Poisson equation.
void get_source(const Vector< double > &x, double &source)
Const source function.
double Strength
Strength of source function: default value 1.0.
Definition circle.h:34