37 using std::endl;
using std::cout;
using std::cerr;
38 using std::ends;
using std::cin;
43 using bgeot::scalar_type;
44 using bgeot::complex_type;
47 using bgeot::base_matrix;
52 typedef getfem::modeling_standard_complex_sparse_matrix sparse_matrix;
53 typedef getfem::modeling_standard_complex_plain_vector plain_vector;
58 struct Helmholtz_problem {
60 enum { DIRICHLET_BOUNDARY_NUM = 0, ROBIN_BOUNDARY_NUM = 1};
65 complex_type wave_number;
70 std::string datafilename;
71 bgeot::md_param PARAM;
73 bool solve(plain_vector &U);
75 void compute_error(plain_vector &U);
76 Helmholtz_problem(
void) : mim(mesh), mf_u(mesh), mf_rhs(mesh) {}
79 complex_type __wave_number;
81 complex_type incoming_field(
const base_node &P) {
82 return complex_type(cos(__wave_number.real()*P[1]+.2),
83 sin(__wave_number.real()*P[1]+.2));
94 void Helmholtz_problem::init(
void) {
95 std::string FEM_TYPE = PARAM.string_value(
"FEM_TYPE",
"FEM name");
96 std::string INTEGRATION = PARAM.string_value(
"INTEGRATION",
97 "Name of integration method");
98 cout <<
"FEM_TYPE=" << FEM_TYPE <<
"\n";
99 cout <<
"INTEGRATION=" << INTEGRATION <<
"\n";
102 size_type Nt = PARAM.int_value(
"NTHETA",
"Nomber of space steps "),
103 Nr=PARAM.int_value(
"NR",
"Nomber of space steps ");
104 size_type gt_order = PARAM.int_value(
"GTDEGREE",
105 "polynomial degree of geometric transformation");
106 scalar_type dtheta=2*M_PI*1./scalar_type(Nt);
107 scalar_type R0 = PARAM.real_value(
"R0",
"R0");
108 scalar_type R1 = PARAM.real_value(
"R1",
"R1");
109 scalar_type dR = (R1-R0)/scalar_type(Nr-1);
111 pgt = bgeot::parallelepiped_geotrans(2,
short_type(gt_order));
114 std::vector<size_type> ipts; ipts.reserve(gmm::sqr(gt_order+1));
115 for (
size_type ii=0; ii <= gt_order; ++ii) {
116 for (
size_type jj=0; jj <= gt_order; ++jj) {
117 scalar_type r = R0 + scalar_type(j)*dR
118 + scalar_type(jj)*(dR/scalar_type(gt_order));
119 scalar_type t = scalar_type(i)*dtheta
120 + scalar_type(ii)*dtheta/scalar_type(gt_order);
121 ipts.push_back(mesh.add_point(base_node(r*cos(t),r*sin(t))));
124 mesh.add_convex(pgt, ipts.begin());
128 datafilename = PARAM.string_value(
"ROOTFILENAME",
"Base name of data files.");
129 residual = PARAM.real_value(
"RESIDUAL");
if (residual == 0.) residual = 1e-10;
131 __wave_number = wave_number = complex_type
132 (PARAM.real_value(
"WAVENUM_R",
"Real part of the wave number"),
133 PARAM.real_value(
"WAVENUM_I",
"Imaginary part of the wave number"));
135 with_mult = int(PARAM.int_value(
"DIRICHLET_VERSION",
136 "Dirichlet condition version"));
141 getfem::pintegration_method ppi =
144 mim.set_integration_method(ppi);
145 mf_u.set_finite_element(pf_u);
149 std::string data_fem_name = PARAM.string_value(
"DATA_FEM_TYPE");
150 if (data_fem_name.size() == 0) {
151 GMM_ASSERT1(pf_u->is_lagrange(),
"You are using a non-lagrange FEM. "
152 <<
"In that case you need to set "
153 <<
"DATA_FEM_TYPE in the .param file");
154 mf_rhs.set_finite_element(pf_u);
161 cout <<
"Selecting Robin and Dirichlet boundaries\n";
166 if (gmm::vect_norm2(mesh.points_of_face_of_convex(i.cv(),
168 mesh.region(ROBIN_BOUNDARY_NUM).add(i.cv(),i.f());
169 }
else mesh.region(DIRICHLET_BOUNDARY_NUM).add(i.cv(),i.f());
178 bool Helmholtz_problem::solve(plain_vector &U) {
184 Helmholtz_model.add_fem_variable(
"u", mf_u);
187 plain_vector K(1); K[0] = wave_number;
188 Helmholtz_model.add_initialized_fixed_size_data(
"k", K);
192 plain_vector Q(1); Q[0] = wave_number * complex_type(0,1.);
193 Helmholtz_model.add_initialized_fixed_size_data(
"Q", Q);
197 plain_vector F(mf_rhs.nb_dof());
199 Helmholtz_model.add_initialized_fem_data(
"DirichletData", mf_rhs, F);
201 (Helmholtz_model, mim,
"u", mf_u,
202 DIRICHLET_BOUNDARY_NUM,
"DirichletData");
210 gmm::copy(Helmholtz_model.complex_variable(
"u"), U);
214 return (iter.converged());
221 int main(
int argc,
char *argv[]) {
223 GETFEM_MPI_INIT(argc, argv);
224 GMM_SET_EXCEPTION_DEBUG;
228 p.PARAM.read_command_line(argc, argv);
230 plain_vector U(p.mf_u.nb_dof());
231 if (!p.solve(U)) GMM_ASSERT1(
false,
"Solve has failed");
233 if (p.PARAM.int_value(
"VTK_EXPORT")) {
234 cout <<
"export to " << p.datafilename +
".vtk" <<
"..\n";
236 p.PARAM.int_value(
"VTK_EXPORT")==1,
true);
237 cout <<
"export to " << p.datafilename +
".vtu" <<
"..\n";
238 getfem::vtu_export vtu_exp(p.datafilename +
".vtu");
240 vtk_exp.exporting(sl);
241 vtk_exp.write_point_data(p.mf_u, gmm::real_part(U),
"helmholtz_rfield");
242 vtk_exp.write_point_data(p.mf_u, gmm::imag_part(U),
"helmholtz_ifield");
243 vtu_exp.exporting(sl);
244 vtu_exp.write_point_data(p.mf_u, gmm::real_part(U),
"helmholtz_rfield");
245 vtu_exp.write_point_data(p.mf_u, gmm::imag_part(U),
"helmholtz_ifield");
246 cout <<
"export done, you can view the data file with (for example)\n"
247 "mayavi2 -d helmholtz.vtk -f WarpScalar -m Surface -m Outline"