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-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 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 
42 using namespace std;
43 
44 using 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 //====================================================================
79 template<class ELEMENT>
80 class RefineableFishPoissonProblem : public Problem
81 {
82 
83 public:
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 
138 private:
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
204  Node* Doc_node_pt;
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 //========================================================================
239 template<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  sprintf(filename,"%s/trace.dat",directory_name.c_str());
255  Trace_file.open(filename);
256 
257  Trace_file
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 //========================================================================
389 template<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 //========================================================================
403 template<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  sprintf(filename,"%s/soln_%i_%i.dat",Doc_info.directory().c_str(),
419  Case_id,Doc_info.number());
420  }
421  else
422  {
423  sprintf(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 //========================================================================
459 template<class ELEMENT>
460 void 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 //========================================================================
510 template<class ELEMENT>
511 void 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 //========================================================================
558 int 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
567  demo_fish_poisson<ELEMENT>("RESLT");
568 
569  // Compute "elastic" coupled solution directly
570  demo_elastic_fish_poisson<ELEMENT>("RESLT_coupled");
571 
572 }
573 
574 
int main(int argc, char *argv[])
Driver for "elastic" fish poisson solver with adaptation. If there are any command line arguments,...
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)
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
DocInfo & doc_info()
Access to DocInfo object.
void set_shape_deriv_method()
Helper fct to set method for evaluation of shape derivs.
double & y_c()
Return value of the vertical displacement of the ring that represents the fish's back.
double & load()
Return value of the "load" on the elastically supported ring.
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 ...
bool Fix_position
Is the position of the fish back prescribed?
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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
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