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