acoustic_fsi.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 Helmholtz/TimeHarmonicTimeHarmonicLinElast coupling
27
28#include <cassert>
29
30//Oomph-lib includes
31#include "generic.h"
32#include "helmholtz.h"
33#include "time_harmonic_linear_elasticity.h"
34#include "multi_physics.h"
35
36//The mesh
37#include "meshes/annular_mesh.h"
38
39using namespace std;
40using namespace oomph;
41
42//////////////////////////////////////////////////////////////////////
43//////////////////////////////////////////////////////////////////////
44//////////////////////////////////////////////////////////////////////
45
46
47//=======start_namespace==========================================
48/// Global variables
49//================================================================
51{
52
53 /// Square of wavenumber for the Helmholtz equation
54 double K_squared=10.0;
55
56 /// Radius of outer boundary of Helmholtz domain
57 double Outer_radius=4.0;
58
59 /// FSI parameter
60 double Q=0.0;
61
62 /// Non-dim thickness of elastic coating
63 double H_coating=0.3;
64
65 /// Poisson's ratio
66 double Nu = 0.3;
67
68 /// The elasticity tensor for the solid
69 TimeHarmonicIsotropicElasticityTensor E(Nu);
70
71 /// Density ratio: solid to fluid
72 double Density_ratio=0.0;
73
74 /// Non-dim square of frequency for solid -- dependent variable!
75 double Omega_sq=0.0;
76
77 /// Function to update dependent parameter values
82
83 /// Azimuthal wavenumber for imposed displacement of coating
84 /// on inner boundary
85 unsigned N=0;
86
87 /// Displacement field on inner boundary of solid
88 void solid_boundary_displacement(const Vector<double>& x,
89 Vector<std::complex<double> >& u)
90 {
91 Vector<double> normal(2);
92 double norm=sqrt(x[0]*x[0]+x[1]*x[1]);
93 double phi=atan2(x[1],x[0]);
94 normal[0]=x[0]/norm;
95 normal[1]=x[1]/norm;
96
97 u[0]=complex<double>(normal[0]*cos(double(N)*phi),0.0);
98 u[1]=complex<double>(normal[1]*cos(double(N)*phi),0.0);
99 }
100
101
102 /// Output directory
103 string Directory="RESLT";
104
105 /// Multiplier for number of elements
106 unsigned El_multiplier=1;
107
108 /// Interface to Hankel function in maple style
109 std::complex<double> HankelH1(const double& k, const double& x)
110 {
111 Vector<std::complex<double> > h(2);
112 Vector<std::complex<double> > hp(2);
113 Hankel_functions_for_helmholtz_problem::Hankel_first(2,x,h,hp);
114
115 if (k==0.0)
116 {
117 return h[0];
118 }
119 else if (k==1.0)
120 {
121 return h[1];
122 }
123 else
124 {
125 cout << "Never get here. k=" << k << std::endl;
126 assert(false);
127 // Dummy return
128 return std::complex<double>(1.0,1.0);
129 }
130 }
131
132
133 /// Coefficient in front of Hankel function for axisymmetric solution
134 /// of Helmholtz potential
135 std::complex<double> axisym_coefficient()
136 {
137 std::complex<double> MapleGenVar1;
138 std::complex<double> MapleGenVar2;
139 std::complex<double> MapleGenVar3;
140 std::complex<double> MapleGenVar4;
141 std::complex<double> MapleGenVar5;
142 std::complex<double> MapleGenVar6;
143 std::complex<double> MapleGenVar7;
144 std::complex<double> MapleGenVar8;
145 std::complex<double> t0;
146
147
148 MapleGenVar3 = (-2.0/(2.0+2.0*Nu)*1.0+2.0/(2.0+2.0*Nu)*1.0*
149H_coating)/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*
150H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0;
151 MapleGenVar5 = -1/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0
152*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)*Q/2.0;
153 MapleGenVar6 = HankelH1(0.0,sqrt(K_squared))*(-(-2.0/(2.0+2.0*Nu)*1.0
154+2.0/(2.0+2.0*Nu)*1.0*H_coating)/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)
155-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0+(2.0/(2.0+
1562.0*Nu)*1.0-2.0/(2.0+2.0*Nu)*1.0*H_coating+2.0*1.0*Nu/(1.0+Nu)/(1.0
157-2.0*Nu)-2.0*1.0*H_coating*Nu/(1.0+Nu)/(1.0-2.0*Nu))/(Nu/(1.0+Nu)/(1.0-2.0*
158Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*
159H_coating)/2.0)/(HankelH1(1.0,sqrt(K_squared))*sqrt(K_squared)-Q*HankelH1(0.0,
160sqrt(K_squared))/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*
161H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0+Q*HankelH1(0.0,sqrt(K_squared
162))*(1.0-2.0*H_coating+H_coating*H_coating)/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+
1632.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0);
164 MapleGenVar4 = MapleGenVar5*MapleGenVar6;
165 MapleGenVar2 = MapleGenVar3+MapleGenVar4;
166 MapleGenVar3 = MapleGenVar2;
167 MapleGenVar5 = -(2.0/(2.0+2.0*Nu)*1.0-2.0/(2.0+2.0*Nu)*1.0*
168H_coating+2.0*1.0*Nu/(1.0+Nu)/(1.0-2.0*Nu)-2.0*1.0*H_coating*Nu/(1.0+Nu
169)/(1.0-2.0*Nu))/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*
170H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0;
171 MapleGenVar7 = (1.0-2.0*H_coating+H_coating*H_coating)/(Nu/(1.0+Nu)/(1.0
172-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*
173H_coating)/2.0;
174 MapleGenVar8 = Q*HankelH1(0.0,sqrt(K_squared))*(-(-2.0/(2.0+2.0*Nu)*
1751.0+2.0/(2.0+2.0*Nu)*1.0*H_coating)/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+
1762.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0+(2.0
177/(2.0+2.0*Nu)*1.0-2.0/(2.0+2.0*Nu)*1.0*H_coating+2.0*1.0*Nu/(1.0+Nu
178)/(1.0-2.0*Nu)-2.0*1.0*H_coating*Nu/(1.0+Nu)/(1.0-2.0*Nu))/(Nu/(1.0+Nu)/(
1791.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*
180H_coating*H_coating)/2.0)/(HankelH1(1.0,sqrt(K_squared))*sqrt(K_squared)-Q*
181HankelH1(0.0,sqrt(K_squared))/(Nu/(1.0+Nu)/(1.0-2.0*Nu)+2.0/(2.0+2.0*Nu)-2.0/(
1822.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*H_coating)/2.0+Q*HankelH1(0.0,
183sqrt(K_squared))*(1.0-2.0*H_coating+H_coating*H_coating)/(Nu/(1.0+Nu)/(1.0-2.0*
184Nu)+2.0/(2.0+2.0*Nu)-2.0/(2.0+2.0*Nu)*H_coating+1/(2.0+2.0*Nu)*H_coating*
185H_coating)/2.0);
186 MapleGenVar6 = MapleGenVar7*MapleGenVar8;
187 MapleGenVar4 = MapleGenVar5+MapleGenVar6;
188 MapleGenVar1 = MapleGenVar3+MapleGenVar4;
189 MapleGenVar2 = 1.0/HankelH1(1.0,sqrt(K_squared))/sqrt(K_squared);
190 t0 = MapleGenVar1*MapleGenVar2;
191
192 return t0;
193 }
194
195
196 /// Exact solution for Helmholtz potential for axisymmetric solution
197 void exact_axisym_potential(const Vector<double>& x,
198 Vector<double>& soln)
199 {
200 std::complex<double> C=axisym_coefficient();
201 double r=sqrt(x[0]*x[0]+x[1]*x[1]);
202 soln[0]=real(HankelH1(0,sqrt(K_squared)*r)*C);
203 soln[1]=imag(HankelH1(0,sqrt(K_squared)*r)*C);
204 }
205
206 /// Exact radiated power for axisymmetric solution
208 {
209 // Solution is independent of where it's evaluated (have checked!)
210 double r=1.0;
211
212 // Get the coefficient for the axisymmetric potential
213 std::complex<double> C=axisym_coefficient();
214
215 // Argument for Bessel/Hankel functions
216 double rr=sqrt(K_squared)*r;
217
218 // Evaluate Hankel functions -- only need zero-th term
219 Vector<std::complex<double> > h(2),hp(2);
220 Hankel_functions_for_helmholtz_problem::Hankel_first(1,rr,h,hp);
221
222 // Compute time-average radiated power
223 double power=sqrt(K_squared)*0.5*r*2.0*MathematicalConstants::Pi*
224 (imag(C*hp[0])*real(C*h[0])-real(C*hp[0])*imag(C*h[0]));
225
226 return power;
227 }
228
229} //end namespace
230
231
232
233//=============begin_problem============================================
234/// Coated disk FSI
235//======================================================================
236template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
237class CoatedDiskProblem : public Problem
238{
239
240public:
241
242 /// Constructor:
244
245 /// Update function (empty)
247
248 /// Update function (empty)
250
251 /// Recompute gamma integral before checking Newton residuals
256
257 /// Actions before adapt: Wipe the mesh of traction elements
259
260 /// Actions after adapt: Rebuild the mesh of traction elements
261 void actions_after_adapt();
262
263 /// Doc the solution
264 void doc_solution();
265
266private:
267
268 /// Create FSI traction elements
270
271 /// Create Helmholtz FSI flux elements
273
274 /// Delete (face) elements in specified mesh
275 void delete_face_elements(Mesh* const & boundary_mesh_pt);
276
277 /// Create DtN face elements
279
280 /// Setup interaction
281 void setup_interaction();
282
283 /// Pointer to solid mesh
284 TreeBasedRefineableMeshBase* Solid_mesh_pt;
285
286 /// Pointer to mesh of FSI traction elements
288
289 /// Pointer to Helmholtz mesh
290 TreeBasedRefineableMeshBase* Helmholtz_mesh_pt;
291
292 /// Pointer to mesh of Helmholtz FSI flux elements
294
295 /// Pointer to mesh containing the DtN elements
296 HelmholtzDtNMesh<HELMHOLTZ_ELEMENT>* Helmholtz_outer_boundary_mesh_pt;
297
298 /// DocInfo object for output
299 DocInfo Doc_info;
300
301 /// Trace file
302 ofstream Trace_file;
303
304};
305
306
307//===========start_of_constructor=======================================
308/// Constructor
309//======================================================================
310template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
312{
313
314 // The coating mesh is periodic
315 bool periodic=true;
316 double azimuthal_fraction_of_coating=1.0;
317
318 // Solid mesh
319 //-----------
320 // Number of elements in azimuthal direction
321 unsigned ntheta_solid=10*Global_Parameters::El_multiplier;
322
323 // Number of elements in radial direction
324 unsigned nr_solid=3*Global_Parameters::El_multiplier;
325
326 // Innermost radius for solid mesh
327 double a=1.0-Global_Parameters::H_coating;
328
329 // Build solid mesh
330 Solid_mesh_pt = new
331 RefineableTwoDAnnularMesh<ELASTICITY_ELEMENT>
332 (periodic,azimuthal_fraction_of_coating,
333 ntheta_solid,nr_solid,a,Global_Parameters::H_coating);
334
335
336 // Helmholtz mesh
337 //---------------
338
339 // Number of elements in azimuthal direction in Helmholtz mesh
340 unsigned ntheta_helmholtz=11*Global_Parameters::El_multiplier;
341
342 // Number of elements in radial direction in Helmholtz mesh
343 unsigned nr_helmholtz=3*Global_Parameters::El_multiplier;
344
345 // Innermost radius of Helmholtz mesh
346 a=1.0;
347
348 // Thickness of Helmholtz mesh
349 double h_thick_helmholtz=Global_Parameters::Outer_radius-a;
350
351 // Build mesh
352 Helmholtz_mesh_pt = new
353 RefineableTwoDAnnularMesh<HELMHOLTZ_ELEMENT>
354 (periodic,azimuthal_fraction_of_coating,
355 ntheta_helmholtz,nr_helmholtz,a,h_thick_helmholtz);
356
357
358 // Set error estimators
359 Solid_mesh_pt->spatial_error_estimator_pt()=new Z2ErrorEstimator;
360 Helmholtz_mesh_pt->spatial_error_estimator_pt()=new Z2ErrorEstimator;
361
362
363 // Mesh containing the Helmholtz DtN
364 // elements. Specify outer radius and number of Fourier terms to be
365 // used in gamma integral
366 unsigned nfourier=20;
367 Helmholtz_outer_boundary_mesh_pt =
368 new HelmholtzDtNMesh<HELMHOLTZ_ELEMENT>(Global_Parameters::Outer_radius,
369 nfourier);
370
371 //Assign the physical properties to the elements before any refinement
372 //Loop over the elements in the solid mesh
373 unsigned n_element=Solid_mesh_pt->nelement();
374 for(unsigned i=0;i<n_element;i++)
375 {
376 //Cast to a solid element
377 ELASTICITY_ELEMENT *el_pt =
378 dynamic_cast<ELASTICITY_ELEMENT*>(Solid_mesh_pt->element_pt(i));
379
380 // Set the constitutive law
381 el_pt->elasticity_tensor_pt() = &Global_Parameters::E;
382
383 // Square of non-dim frequency
384 el_pt->omega_sq_pt()= &Global_Parameters::Omega_sq;
385 }
386
387
388 // Same for Helmholtz mesh
389 n_element =Helmholtz_mesh_pt->nelement();
390 for(unsigned i=0;i<n_element;i++)
391 {
392 //Cast to a solid element
393 HELMHOLTZ_ELEMENT *el_pt =
394 dynamic_cast<HELMHOLTZ_ELEMENT*>(Helmholtz_mesh_pt->element_pt(i));
395
396 //Set the pointer to square of Helmholtz wavenumber
397 el_pt->k_squared_pt() = &Global_Parameters::K_squared;
398 }
399
400
401 // Output meshes and their boundaries so far so we can double
402 // check the boundary enumeration
403 Solid_mesh_pt->output("solid_mesh.dat");
404 Helmholtz_mesh_pt->output("helmholtz_mesh.dat");
405 Solid_mesh_pt->output_boundaries("solid_mesh_boundary.dat");
406 Helmholtz_mesh_pt->output_boundaries("helmholtz_mesh_boundary.dat");
407
408
409 // Create FaceElement meshes for boundary conditions
410 //---------------------------------------------------
411
412 // Construct the fsi traction element mesh
413 FSI_traction_mesh_pt=new Mesh;
414 create_fsi_traction_elements();
415
416 // Construct the Helmholtz fsi flux element mesh
417 Helmholtz_fsi_flux_mesh_pt=new Mesh;
418 create_helmholtz_fsi_flux_elements();
419
420 // Create DtN elements on outer boundary of Helmholtz mesh
421 create_helmholtz_DtN_elements();
422
423
424 // Combine sub meshes
425 //-------------------
426
427 // Solid mesh is first sub-mesh
428 add_sub_mesh(Solid_mesh_pt);
429
430 // Add traction sub-mesh
431 add_sub_mesh(FSI_traction_mesh_pt);
432
433 // Add Helmholtz mesh
434 add_sub_mesh(Helmholtz_mesh_pt);
435
436 // Add Helmholtz FSI flux mesh
437 add_sub_mesh(Helmholtz_fsi_flux_mesh_pt);
438
439 // Add Helmholtz DtN mesh
440 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
441
442 // Build combined "global" mesh
443 build_global_mesh();
444
445
446 // Solid boundary conditions:
447 //---------------------------
448 // Pin displacements on innermost boundary (boundary 0) of solid mesh
449 unsigned n_node = Solid_mesh_pt->nboundary_node(0);
450 Vector<std::complex<double> > u(2);
451 Vector<double> x(2);
452 for(unsigned i=0;i<n_node;i++)
453 {
454 Node* nod_pt=Solid_mesh_pt->boundary_node_pt(0,i);
455 nod_pt->pin(0);
456 nod_pt->pin(1);
457 nod_pt->pin(2);
458 nod_pt->pin(3);
459
460 // Assign displacements
461 x[0]=nod_pt->x(0);
462 x[1]=nod_pt->x(1);
464
465 // Real part of x-displacement
466 nod_pt->set_value(0,u[0].real());
467
468 // Imag part of x-displacement
469 nod_pt->set_value(1,u[1].real());
470
471 // Real part of y-displacement
472 nod_pt->set_value(2,u[0].imag());
473
474 //Imag part of y-displacement
475 nod_pt->set_value(3,u[1].imag());
476 }
477
478
479 // Setup fluid-structure interaction
480 //----------------------------------
481 setup_interaction();
482
483 // Assign equation numbers
484 oomph_info << "Number of unknowns: " << assign_eqn_numbers() << std::endl;
485
486 // Set output directory
487 Doc_info.set_directory(Global_Parameters::Directory);
488
489 // Open trace file
490 char filename[100];
491 snprintf(filename, sizeof(filename), "%s/trace.dat",Doc_info.directory().c_str());
492 Trace_file.open(filename);
493
494
495} //end of constructor
496
497
498//=====================start_of_actions_before_adapt======================
499/// Actions before adapt: Wipe the meshes face elements
500//========================================================================
501template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
504{
505 // Kill the fsi traction elements and wipe surface mesh
506 delete_face_elements(FSI_traction_mesh_pt);
507
508 // Kill Helmholtz FSI flux elements
509 delete_face_elements(Helmholtz_fsi_flux_mesh_pt);
510
511 // Kill Helmholtz BC elements
512 delete_face_elements(Helmholtz_outer_boundary_mesh_pt);
513
514 // Rebuild the Problem's global mesh from its various sub-meshes
515 rebuild_global_mesh();
516
517}// end of actions_before_adapt
518
519
520
521//=====================start_of_actions_after_adapt=======================
522/// Actions after adapt: Rebuild the meshes of face elements
523//========================================================================
524template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
527{
528 // Create fsi traction elements from all elements that are
529 // adjacent to FSI boundaries and add them to surface meshes
530 create_fsi_traction_elements();
531
532 // Create Helmholtz fsi flux elements
533 create_helmholtz_fsi_flux_elements();
534
535 // Create DtN elements from all elements that are
536 // adjacent to the outer boundary of Helmholtz mesh
537 create_helmholtz_DtN_elements();
538
539 // Setup interaction
540 setup_interaction();
541
542 // Rebuild the Problem's global mesh from its various sub-meshes
543 rebuild_global_mesh();
544
545}// end of actions_after_adapt
546
547
548//============start_of_delete_face_elements================
549/// Delete face elements and wipe the mesh
550//==========================================================
551template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
553delete_face_elements(Mesh* const & boundary_mesh_pt)
554{
555 // How many surface elements are in the surface mesh
556 unsigned n_element = boundary_mesh_pt->nelement();
557
558 // Loop over the surface elements
559 for(unsigned e=0;e<n_element;e++)
560 {
561 // Kill surface element
562 delete boundary_mesh_pt->element_pt(e);
563 }
564
565 // Wipe the mesh
566 boundary_mesh_pt->flush_element_and_node_storage();
567
568} // end of delete_face_elements
569
570
571
572//============start_of_create_fsi_traction_elements======================
573/// Create fsi traction elements
574//=======================================================================
575template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
578{
579 // We're on boundary 2 of the solid mesh
580 unsigned b=2;
581
582 // How many bulk elements are adjacent to boundary b?
583 unsigned n_element = Solid_mesh_pt->nboundary_element(b);
584
585 // Loop over the bulk elements adjacent to boundary b
586 for(unsigned e=0;e<n_element;e++)
587 {
588 // Get pointer to the bulk element that is adjacent to boundary b
589 ELASTICITY_ELEMENT* bulk_elem_pt = dynamic_cast<ELASTICITY_ELEMENT*>(
590 Solid_mesh_pt->boundary_element_pt(b,e));
591
592 //Find the index of the face of element e along boundary b
593 int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
594
595 // Create element
596 TimeHarmonicLinElastLoadedByHelmholtzPressureBCElement
597 <ELASTICITY_ELEMENT,HELMHOLTZ_ELEMENT>* el_pt=
598 new TimeHarmonicLinElastLoadedByHelmholtzPressureBCElement
599 <ELASTICITY_ELEMENT,HELMHOLTZ_ELEMENT>(bulk_elem_pt,
600 face_index);
601 // Add to mesh
602 FSI_traction_mesh_pt->add_element_pt(el_pt);
603
604 // Associate element with bulk boundary (to allow it to access
605 // the boundary coordinates in the bulk mesh)
606 el_pt->set_boundary_number_in_bulk_mesh(b);
607
608 // Set FSI parameter
609 el_pt->q_pt()=&Global_Parameters::Q;
610 }
611
612} // end of create_traction_elements
613
614
615
616
617
618//============start_of_create_helmholtz_fsi_flux_elements================
619/// Create Helmholtz fsii flux elements
620//=======================================================================
621template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
624{
625
626 // Attach to inner boundary of Helmholtz mesh (0)
627 unsigned b=0;
628
629 // How many bulk elements are adjacent to boundary b?
630 unsigned n_element = Helmholtz_mesh_pt->nboundary_element(b);
631
632 // Loop over the bulk elements adjacent to boundary b
633 for(unsigned e=0;e<n_element;e++)
634 {
635 // Get pointer to the bulk element that is adjacent to boundary b
636 HELMHOLTZ_ELEMENT* bulk_elem_pt = dynamic_cast<HELMHOLTZ_ELEMENT*>(
637 Helmholtz_mesh_pt->boundary_element_pt(b,e));
638
639 //Find the index of the face of element e along boundary b
640 int face_index = Helmholtz_mesh_pt->face_index_at_boundary(b,e);
641
642 // Create element
643 HelmholtzFluxFromNormalDisplacementBCElement
644 <HELMHOLTZ_ELEMENT,ELASTICITY_ELEMENT>* el_pt=
645 new HelmholtzFluxFromNormalDisplacementBCElement
646 <HELMHOLTZ_ELEMENT,ELASTICITY_ELEMENT>(bulk_elem_pt,
647 face_index);
648
649 // Add to mesh
650 Helmholtz_fsi_flux_mesh_pt->add_element_pt(el_pt);
651
652 // Associate element with bulk boundary (to allow it to access
653 // the boundary coordinates in the bulk mesh)
654 el_pt->set_boundary_number_in_bulk_mesh(b);
655 }
656
657} // end of create_helmholtz_flux_elements
658
659
660
661//============start_of_create_DtN_elements==============================
662/// Create DtN elements on the outer boundary of
663/// the Helmholtz mesh
664//===========================================================================
665template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
668{
669 // We're on boundary 2 of the Helmholtz mesh
670 unsigned b=2;
671
672 // How many bulk elements are adjacent to boundary b?
673 unsigned n_element = Helmholtz_mesh_pt->nboundary_element(b);
674
675 // Loop over the bulk elements adjacent to boundary b?
676 for(unsigned e=0;e<n_element;e++)
677 {
678 // Get pointer to the bulk element that is adjacent to boundary b
679 HELMHOLTZ_ELEMENT* bulk_elem_pt = dynamic_cast<HELMHOLTZ_ELEMENT*>(
680 Helmholtz_mesh_pt->boundary_element_pt(b,e));
681
682 //Find the index of the face of element e along boundary b
683 int face_index = Helmholtz_mesh_pt->face_index_at_boundary(b,e);
684
685 // Build the corresponding DtN element
686 HelmholtzDtNBoundaryElement<HELMHOLTZ_ELEMENT>* flux_element_pt = new
687 HelmholtzDtNBoundaryElement<HELMHOLTZ_ELEMENT>(bulk_elem_pt,face_index);
688
689 // Set pointer to the mesh that contains all the boundary condition
690 // elements on this boundary
691 flux_element_pt->set_outer_boundary_mesh_pt(
692 Helmholtz_outer_boundary_mesh_pt);
693
694 //Add the DtN element to the mesh
695 Helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
696
697 }
698
699} // end of create_helmholtz_DtN_elements
700
701
702
703//=====================start_of_setup_interaction======================
704/// Setup interaction between two fields
705//========================================================================
706template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
709{
710 // Setup Helmholtz "pressure" load on traction elements
711 unsigned boundary_in_helmholtz_mesh=0;
712 Multi_domain_functions::setup_bulk_elements_adjacent_to_face_mesh
713 <HELMHOLTZ_ELEMENT,2>
714 (this,boundary_in_helmholtz_mesh,Helmholtz_mesh_pt,FSI_traction_mesh_pt);
715
716 // Setup Helmholtz flux from normal displacement interaction
717 unsigned boundary_in_solid_mesh=2;
718 Multi_domain_functions::setup_bulk_elements_adjacent_to_face_mesh
719 <ELASTICITY_ELEMENT,2>(
720 this,boundary_in_solid_mesh,Solid_mesh_pt,Helmholtz_fsi_flux_mesh_pt);
721}
722
723
724
725//==============start_doc===========================================
726/// Doc the solution
727//==================================================================
728template<class ELASTICITY_ELEMENT, class HELMHOLTZ_ELEMENT>
730{
731
732 ofstream some_file,some_file2;
733 char filename[100];
734
735 // Number of plot points
736 unsigned n_plot=5;
737
738 // Compute/output the radiated power
739 //----------------------------------
740 snprintf(filename, sizeof(filename), "%s/power%i.dat",Doc_info.directory().c_str(),
741 Doc_info.number());
742 some_file.open(filename);
743
744 // Accumulate contribution from elements
745 double power=0.0;
746 unsigned nn_element=Helmholtz_outer_boundary_mesh_pt->nelement();
747 for(unsigned e=0;e<nn_element;e++)
748 {
749 HelmholtzBCElementBase<HELMHOLTZ_ELEMENT> *el_pt =
750 dynamic_cast<HelmholtzBCElementBase<HELMHOLTZ_ELEMENT>*>(
751 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
752 power += el_pt->global_power_contribution(some_file);
753 }
754 some_file.close();
755 oomph_info << "Step: " << Doc_info.number()
756 << ": Q=" << Global_Parameters::Q << "\n"
757 << " k_squared=" << Global_Parameters::K_squared << "\n"
758 << " density ratio=" << Global_Parameters::Density_ratio << "\n"
759 << " omega_sq=" << Global_Parameters::Omega_sq << "\n"
760 << " Total radiated power " << power << "\n"
761 << " Axisymmetric radiated power " << "\n"
763 << std::endl;
764
765
766 // Write trace file
767 Trace_file << Global_Parameters::Q << " "
771 << power << " "
773 << std::endl;
774
775 std::ostringstream case_string;
776 case_string << "TEXT X=10,Y=90, T=\"Q="
778 << ", k<sup>2</sup>="
780 << ", density ratio="
782 << ", omega_sq="
784 << "\"\n";
785
786
787 // Output displacement field
788 //--------------------------
789 snprintf(filename, sizeof(filename), "%s/elast_soln%i.dat",Doc_info.directory().c_str(),
790 Doc_info.number());
791 some_file.open(filename);
792 Solid_mesh_pt->output(some_file,n_plot);
793 some_file.close();
794
795
796 // Output fsi traction elements
797 //-----------------------------
798 snprintf(filename, sizeof(filename), "%s/traction_soln%i.dat",Doc_info.directory().c_str(),
799 Doc_info.number());
800 some_file.open(filename);
801 FSI_traction_mesh_pt->output(some_file,n_plot);
802 some_file.close();
803
804
805 // Output Helmholtz fsi flux elements
806 //-----------------------------------
807 snprintf(filename, sizeof(filename), "%s/flux_bc_soln%i.dat",Doc_info.directory().c_str(),
808 Doc_info.number());
809 some_file.open(filename);
810 Helmholtz_fsi_flux_mesh_pt->output(some_file,n_plot);
811 some_file.close();
812
813
814 // Output Helmholtz
815 //-----------------
816 snprintf(filename, sizeof(filename), "%s/helmholtz_soln%i.dat",Doc_info.directory().c_str(),
817 Doc_info.number());
818 some_file.open(filename);
819 Helmholtz_mesh_pt->output(some_file,n_plot);
820 some_file << case_string.str();
821 some_file.close();
822
823
824 // Output exact solution for Helmholtz
825 //------------------------------------
826 snprintf(filename, sizeof(filename), "%s/exact_helmholtz_soln%i.dat",Doc_info.directory().c_str(),
827 Doc_info.number());
828 some_file.open(filename);
829 Helmholtz_mesh_pt->output_fct(some_file,n_plot,
831 some_file.close();
832
833
834 cout << "Doced for Q=" << Global_Parameters::Q << " (step "
835 << Doc_info.number() << ")\n";
836
837 // Increment label for output files
838 Doc_info.number()++;
839
840} //end doc
841
842
843
844//=======start_of_main==================================================
845/// Driver for acoustic fsi problem
846//======================================================================
847int main(int argc, char **argv)
848{
849
850 // Store command line arguments
851 CommandLineArgs::setup(argc,argv);
852
853 // Define possible command line arguments and parse the ones that
854 // were actually specified
855
856 // Output directory
857 CommandLineArgs::specify_command_line_flag("--dir",
859
860 // Azimuthal wavenumber of forcing
861 CommandLineArgs::specify_command_line_flag("--n",&Global_Parameters::N);
862
863 // Minimum refinement level
864 CommandLineArgs::specify_command_line_flag("--el_multiplier",
866
867 // Outer radius of Helmholtz domain
868 CommandLineArgs::specify_command_line_flag("--outer_radius",
870
871 // Number of steps in parameter study
872 unsigned nstep=2;
873 CommandLineArgs::specify_command_line_flag("--nstep",&nstep);
874
875 // Increment in FSI parameter in parameter study
876 double q_increment=5.0;
877 CommandLineArgs::specify_command_line_flag("--q_increment",&q_increment);
878
879 // Max. number of adaptations
880 unsigned max_adapt=3;
881 CommandLineArgs::specify_command_line_flag("--max_adapt",&max_adapt);
882
883 // Parse command line
884 CommandLineArgs::parse_and_assign();
885
886 // Doc what has actually been specified on the command line
887 CommandLineArgs::doc_specified_flags();
888
889 //Set up the problem
891 RefineableQHelmholtzElement<2,3> > problem;
892
893
894 // Initial values for parameter values
897
898 //Parameter incrementation
899 for(unsigned i=0;i<nstep;i++)
900 {
901 // Solve the problem with Newton's method, allowing
902 // up to max_adapt mesh adaptations after every solve.
903 problem.newton_solve(max_adapt);
904
905 // Doc solution
906 problem.doc_solution();
907
908 // Increment FSI parameter
909 Global_Parameters::Q+=q_increment;
911 }
912
913} //end of main
914
915
916
917
918
919
920
921
int main(int argc, char **argv)
Driver for acoustic fsi problem.
Coated disk FSI.
HelmholtzDtNMesh< HELMHOLTZ_ELEMENT > * Helmholtz_outer_boundary_mesh_pt
Pointer to mesh containing the DtN elements.
void create_fsi_traction_elements()
Create FSI traction elements.
Mesh * Helmholtz_fsi_flux_mesh_pt
Pointer to mesh of Helmholtz FSI flux elements.
void create_helmholtz_DtN_elements()
Create DtN face elements.
void create_helmholtz_fsi_flux_elements()
Create Helmholtz FSI flux elements.
void actions_before_newton_solve()
Update function (empty)
void delete_face_elements(Mesh *const &boundary_mesh_pt)
Delete (face) elements in specified mesh.
ofstream Trace_file
Trace file.
void actions_before_adapt()
Actions before adapt: Wipe the mesh of traction elements.
void actions_before_newton_convergence_check()
Recompute gamma integral before checking Newton residuals.
void actions_after_adapt()
Actions after adapt: Rebuild the mesh of traction elements.
CoatedDiskProblem()
Constructor:
void actions_after_newton_solve()
Update function (empty)
TreeBasedRefineableMeshBase * Solid_mesh_pt
Pointer to solid mesh.
DocInfo Doc_info
DocInfo object for output.
void setup_interaction()
Setup interaction.
TreeBasedRefineableMeshBase * Helmholtz_mesh_pt
Pointer to Helmholtz mesh.
Mesh * FSI_traction_mesh_pt
Pointer to mesh of FSI traction elements.
void doc_solution()
Doc the solution.
Global variables.
double Nu
Poisson's ratio.
string Directory
Output directory.
std::complex< double > axisym_coefficient()
Coefficient in front of Hankel function for axisymmetric solution of Helmholtz potential.
unsigned El_multiplier
Multiplier for number of elements.
double Density_ratio
Density ratio: solid to fluid.
double Q
FSI parameter.
double exact_axisym_radiated_power()
Exact radiated power for axisymmetric solution.
double Outer_radius
Radius of outer boundary of Helmholtz domain.
double K_squared
Square of wavenumber for the Helmholtz equation.
void solid_boundary_displacement(const Vector< double > &x, Vector< std::complex< double > > &u)
Displacement field on inner boundary of solid.
std::complex< double > HankelH1(const double &k, const double &x)
Interface to Hankel function in maple style.
void update_parameter_values()
Function to update dependent parameter values.
double H_coating
Non-dim thickness of elastic coating.
TimeHarmonicIsotropicElasticityTensor E(Nu)
The elasticity tensor for the solid.
void exact_axisym_potential(const Vector< double > &x, Vector< double > &soln)
Exact solution for Helmholtz potential for axisymmetric solution.
double Omega_sq
Non-dim square of frequency for solid – dependent variable!
unsigned N
Azimuthal wavenumber for imposed displacement of coating on inner boundary.