39 #include "fourier_decomposed_helmholtz.h" 42 #include "meshes/triangle_mesh.h" 45 #include "oomph_crbond_bessel.h" 47 using namespace oomph;
67 double K=3.0*MathematicalConstants::Pi;
70 std::complex<double>
I(0.0,1.0);
73 void get_exact_u(
const Vector<double>& x, Vector<double>& u)
76 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
79 theta=atan2(x[0],x[1]);
85 double bessel_offset=0.5;
88 Vector<double> jv(N_terms);
89 Vector<double> yv(N_terms);
90 Vector<double> djv(N_terms);
91 Vector<double> dyv(N_terms);
92 double order_max_in=double(N_terms-1)+bessel_offset;
93 double order_max_out=0;
104 CRBond_Bessel::bessjyv(order_max_in,
113 complex<double> u_ex(0.0,0.0);
114 for(
unsigned i=0;i<
N_terms;i++)
117 double p=Legendre_functions_helper::plgndr2(i,0,cos(theta));
120 u_ex+=(2.0*i+1.0)*pow(
I,i)*
121 sqrt(MathematicalConstants::Pi/(2.0*kr))*jv[i]*p;
138 ofstream some_file(
"planar_wave.dat");
140 for (
unsigned i_t=0;i_t<nt;i_t++)
142 double t=2.0*MathematicalConstants::Pi*double(i_t)/double(nt-1);
144 some_file <<
"ZONE I="<< nz <<
", J="<< nr << std::endl;
148 for (
unsigned i=0;i<nr;i++)
150 x[0]=0.001+double(i)/double(nr-1);
151 for (
unsigned j=0;j<nz;j++)
153 x[1]=double(j)/double(nz-1);
155 complex<double> uu=complex<double>(u[0],u[1])*exp(-
I*t);
156 some_file << x[0] <<
" " << x[1] <<
" " 157 << uu.real() <<
" " << uu.imag() <<
"\n";
189 Vector<double>
Coeff(N_terms,1.0);
192 std::complex<double>
I(0.0,1.0);
195 void get_exact_u(
const Vector<double>& x, Vector<double>& u)
198 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
201 theta=atan2(x[0],x[1]);
204 double kr = sqrt(K_squared)*R;
207 double bessel_offset=0.5;
210 Vector<double> jv(N_terms);
211 Vector<double> yv(N_terms);
212 Vector<double> djv(N_terms);
213 Vector<double> dyv(N_terms);
214 double order_max_in=double(N_terms-1)+bessel_offset;
215 double order_max_out=0;
226 CRBond_Bessel::bessjyv(order_max_in,
235 complex<double> u_ex(0.0,0.0);
236 for(
unsigned i=N_fourier;i<
N_terms;i++)
239 double p=Legendre_functions_helper::plgndr2(i,N_fourier,
242 u_ex+=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*(jv[i]+
I*yv[i])*p;
257 flux=std::complex<double>(0.0,0.0);
260 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
263 theta=atan2(x[0],x[1]);
266 double kr=sqrt(K_squared)*R;
269 double k=sqrt(K_squared);
272 double bessel_offset=0.5;
275 Vector<double> jv(N_terms);
276 Vector<double> yv(N_terms);
277 Vector<double> djv(N_terms);
278 Vector<double> dyv(N_terms);
279 double order_max_in=double(N_terms-1)+bessel_offset;
280 double order_max_out=0;
291 CRBond_Bessel::bessjyv(order_max_in,
300 complex<double> u_ex(0.0,0.0);
301 for(
unsigned i=N_fourier;i<
N_terms;i++)
304 double p=Legendre_functions_helper::plgndr2(i,N_fourier,
307 flux-=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*p*
308 ( k*(djv[i]+
I*dyv[i]) - (0.5*(jv[i]+
I*yv[i])/R) );
327 template<
class ELEMENT>
347 void doc_solution(DocInfo& doc_info);
352 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
354 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
359 void actions_before_adapt();
362 void actions_after_adapt();
365 void check_gamma(DocInfo& doc_info);
370 void create_outer_bc_elements();
373 void create_flux_elements_on_inner_boundary();
380 unsigned n_element = boundary_mesh_pt->nelement();
381 for(
unsigned e=0;e<n_element;e++)
384 delete boundary_mesh_pt->element_pt(e);
388 boundary_mesh_pt->flush_element_and_node_storage();
406 FourierDecomposedHelmholtzDtNMesh<ELEMENT>* Helmholtz_outer_boundary_mesh_pt;
409 Mesh* Helmholtz_inner_boundary_mesh_pt;
421 template<
class ELEMENT>
425 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
427 delete_face_elements(Helmholtz_outer_boundary_mesh_pt);
429 delete_face_elements(Helmholtz_inner_boundary_mesh_pt);
432 rebuild_global_mesh();
440 template<
class ELEMENT>
450 unsigned n_element = Bulk_mesh_pt->nelement();
451 for(
unsigned e=0;e<n_element;e++)
454 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
466 create_flux_elements_on_inner_boundary();
467 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
469 create_outer_bc_elements();
473 rebuild_global_mesh();
481 template<
class ELEMENT>
487 Trace_file.open(
"RESLT/trace.dat");
494 Circle* inner_circle_pt=
new Circle(x_c,y_c,r_min);
495 Circle* outer_circle_pt=
new Circle(x_c,y_c,r_max);
499 Vector<TriangleMeshCurveSection*> outer_boundary_line_pt(4);
502 unsigned n_segments = 20;
505 Vector<Vector<double> > boundary_vertices(2);
510 boundary_vertices[0].resize(2);
511 boundary_vertices[0][0]=0.0;
512 boundary_vertices[0][1]=-r_min;
513 boundary_vertices[1].resize(2);
514 boundary_vertices[1][0]=0.0;
515 boundary_vertices[1][1]=-r_max;
517 unsigned boundary_id=0;
518 outer_boundary_line_pt[0]=
519 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
522 if (CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
527 Vector<Vector<double> > boundary_vertices(4);
528 boundary_vertices[0].resize(2);
529 boundary_vertices[0][0]=0.0;
530 boundary_vertices[0][1]=-r_max;
531 boundary_vertices[1].resize(2);
532 boundary_vertices[1][0]=r_max;
533 boundary_vertices[1][1]=-r_max;
534 boundary_vertices[2].resize(2);
535 boundary_vertices[2][0]=r_max;
536 boundary_vertices[2][1]=r_max;
537 boundary_vertices[3].resize(2);
538 boundary_vertices[3][0]=0.0;
539 boundary_vertices[3][1]=r_max;
542 outer_boundary_line_pt[1]=
543 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
550 double s_start = -0.5*MathematicalConstants::Pi;
551 double s_end = 0.5*MathematicalConstants::Pi;
554 outer_boundary_line_pt[1]=
555 new TriangleMeshCurviLine(outer_circle_pt,
565 boundary_vertices[0][0]=0.0;
566 boundary_vertices[0][1]=r_max;
567 boundary_vertices[1][0]=0.0;
568 boundary_vertices[1][1]=r_min;
571 outer_boundary_line_pt[2]=
572 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
579 double s_start = 0.5*MathematicalConstants::Pi;
580 double s_end = -0.5*MathematicalConstants::Pi;
583 outer_boundary_line_pt[3]=
584 new TriangleMeshCurviLine(inner_circle_pt,
593 TriangleMeshClosedCurve *outer_boundary_pt =
594 new TriangleMeshClosedCurve(outer_boundary_line_pt);
600 TriangleMeshParameters triangle_mesh_parameters(outer_boundary_pt);
603 double element_area = 0.1;
604 triangle_mesh_parameters.element_area() = element_area;
609 Bulk_mesh_pt=
new RefineableTriangleMesh<ELEMENT>(triangle_mesh_parameters);
612 Bulk_mesh_pt->spatial_error_estimator_pt()=
new Z2ErrorEstimator;
615 Bulk_mesh_pt->min_permitted_error()=0.00004;
616 Bulk_mesh_pt->max_permitted_error()=0.0001;
621 Bulk_mesh_pt=
new TriangleMesh<ELEMENT>(triangle_mesh_parameters);
626 Bulk_mesh_pt->output(
"mesh.dat");
627 Bulk_mesh_pt->output_boundaries(
"boundaries.dat");
630 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
633 Helmholtz_outer_boundary_mesh_pt=
634 new FourierDecomposedHelmholtzDtNMesh<ELEMENT>(
638 create_outer_bc_elements();
642 Helmholtz_inner_boundary_mesh_pt=
new Mesh;
643 create_flux_elements_on_inner_boundary();
646 add_sub_mesh(Bulk_mesh_pt);
647 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
648 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
650 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
657 unsigned n_element = Bulk_mesh_pt->nelement();
658 for(
unsigned i=0;i<n_element;i++)
661 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(i));
671 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
680 template<
class ELEMENT>
685 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
690 sprintf(filename,
"%s/gamma_test%i.dat",doc_info.directory().c_str(),
692 some_file.open(filename);
695 unsigned nel=Helmholtz_outer_boundary_mesh_pt->nelement();
696 for (
unsigned e=0;e<nel;e++)
699 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* el_pt=
700 dynamic_cast<FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>*
> 701 (Helmholtz_outer_boundary_mesh_pt->element_pt(e));
704 const unsigned n_intpt =el_pt->integral_pt()->nweight();
707 Vector<std::complex<double> > gamma(
708 Helmholtz_outer_boundary_mesh_pt->gamma_at_gauss_point(el_pt));
711 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
714 Vector<double> x(el_pt->dim()+1,0.0);
717 unsigned n=el_pt->dim();
718 Vector<double> s(n,0.0);
719 for(
unsigned i=0;i<n;i++)
721 s[i]=el_pt->integral_pt()->knot(ipt,i);
725 el_pt->interpolated_x(s,x);
727 complex<double> flux;
729 some_file << atan2(x[0],x[1]) <<
" " 730 << gamma[ipt].real() <<
" " 731 << gamma[ipt].imag() <<
" " 732 << flux.real() <<
" " 733 << flux.imag() <<
" " 748 template<
class ELEMENT>
760 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
762 some_file.open(filename);
763 Bulk_mesh_pt->output(some_file,npts);
769 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
771 some_file.open(filename);
779 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
781 some_file.open(filename);
787 cout <<
"\nNorm of error : " << sqrt(error) << std::endl;
788 cout <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
792 Bulk_mesh_pt->compute_norm(norm);
793 Trace_file << norm << std::endl;
796 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
799 check_gamma(doc_info);
809 template<
class ELEMENT>
817 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
818 for(
unsigned e=0;e<n_element;e++)
821 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
822 Bulk_mesh_pt->boundary_element_pt(b,e));
825 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
828 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new 829 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,
833 Helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
838 set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
848 template<
class ELEMENT>
856 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
857 for(
unsigned e=0;e<n_element;e++)
860 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
861 Bulk_mesh_pt->boundary_element_pt(b,e));
864 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
867 FourierDecomposedHelmholtzFluxElement<ELEMENT>* flux_element_pt =
new 868 FourierDecomposedHelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
871 Helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
885 int main(
int argc,
char **argv)
888 CommandLineArgs::setup(argc,argv);
894 CommandLineArgs::specify_command_line_flag(
"--square_domain");
897 CommandLineArgs::parse_and_assign();
900 CommandLineArgs::doc_specified_flags();
913 double bessel_offset=0.5;
915 ofstream bessely_file(
"besselY.dat");
916 ofstream bessely_deriv_file(
"dbesselY.dat");
918 ofstream besselj_file(
"besselJ.dat");
919 ofstream besselj_deriv_file(
"dbesselJ.dat");
922 Vector<double> jv(n+1);
923 Vector<double> yv(n+1);
924 Vector<double> djv(n+1);
925 Vector<double> dyv(n+1);
929 for (
unsigned i=0;i<nplot;i++)
931 double x=x_min+(x_max-x_min)*
double(i)/double(nplot-1);
932 double order_max_in=double(n)+bessel_offset;
933 double order_max_out=0;
944 CRBond_Bessel::bessjyv(order_max_in,x,
948 bessely_file << x <<
" ";
949 for (
unsigned j=0;j<=n;j++)
951 bessely_file << yv[j] <<
" ";
953 bessely_file << std::endl;
955 besselj_file << x <<
" ";
956 for (
unsigned j=0;j<=n;j++)
958 besselj_file << jv[j] <<
" ";
960 besselj_file << std::endl;
962 bessely_deriv_file << x <<
" ";
963 for (
unsigned j=0;j<=n;j++)
965 bessely_deriv_file << dyv[j] <<
" ";
967 bessely_deriv_file << std::endl;
969 besselj_deriv_file << x <<
" ";
970 for (
unsigned j=0;j<=n;j++)
972 besselj_deriv_file << djv[j] <<
" ";
974 besselj_deriv_file << std::endl;
977 bessely_file.close();
978 besselj_file.close();
979 bessely_deriv_file.close();
980 besselj_deriv_file.close();
990 ofstream some_file(
"legendre3.dat");
992 for (
unsigned i=0;i<nplot;i++)
994 double x=double(i)/double(nplot-1);
996 some_file << x <<
" ";
997 for (
unsigned j=0;j<=n;j++)
999 some_file << Legendre_functions_helper::plgndr2(n,j,x) <<
" ";
1001 some_file << std::endl;
1012 TFourierDecomposedHelmholtzElement<3> > > problem;
1027 doc_info.set_directory(
"RESLT");
1041 unsigned max_adapt=1;
1045 problem.newton_solve(max_adapt);
1050 problem.newton_solve();
Namespace for the Fourier decomposed Helmholtz problem parameters.
RefineableTriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
~FourierDecomposedHelmholtzProblem()
Destructor (empty)
Vector< double > Coeff(N_terms, 1.0)
Coefficients in the exact solution.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector of size 2, containing real and imag parts.
void check_gamma(DocInfo &doc_info)
Check gamma computation.
FourierDecomposedHelmholtzProblem()
Constructor.
void actions_after_newton_solve()
Update the problem after solve (empty)
int main(int argc, char **argv)
Driver code for Fourier decomposed Helmholtz problem.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector of size 2, containing real and imag parts.
void create_flux_elements_on_inner_boundary()
Create flux elements on inner boundary.
double K_squared
Square of the wavenumber.
std::complex< double > I(0.0, 1.0)
Imaginary unit.
void actions_before_adapt()
Actions before adapt: Wipe the mesh of prescribed flux elements.
int N_fourier
Fourier wave number.
unsigned Nterms_for_DtN
Number of terms in computation of DtN boundary condition.
void actions_after_adapt()
Actions after adapt: Rebuild the mesh of prescribed flux elements.
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to...
void actions_before_newton_convergence_check()
Recompute gamma integral before checking Newton residuals.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
ofstream Trace_file
Trace file.
void exact_minus_dudr(const Vector< double > &x, std::complex< double > &flux)
Get -du/dr (spherical r) for exact solution. Equal to prescribed flux on inner boundary.
void create_outer_bc_elements()
Create BC elements on outer boundary.
void delete_face_elements(Mesh *const &boundary_mesh_pt)
Delete boundary face elements and wipe the surface mesh.
TriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
unsigned N_terms
Number of terms in series.