17 #include "../include/bem_problem.h"
18 #include "../include/laplace_kernel.h"
52 comp_dom(comp_dom), fma(fma)
58 const unsigned int n_dofs = comp_dom.dh.n_dofs();
60 neumann_matrix.reinit(n_dofs, n_dofs);
61 dirichlet_matrix.reinit(n_dofs, n_dofs);
62 system_rhs.reinit(n_dofs);
65 serv_phi.reinit(n_dofs);
66 serv_dphi_dn.reinit(n_dofs);
67 serv_tmp_rhs.reinit(n_dofs);
68 preconditioner_band = 100;
69 preconditioner_sparsity_pattern.reinit (n_dofs,n_dofs,preconditioner_band);
70 is_preconditioner_initialized =
false;
96 solver_control.parse_parameters(prm);
99 solution_method = prm.
get(
"Solution method");
109 std::cout<<
"(Directly) Assembling system matrices"<<std::endl;
112 dirichlet_matrix = 0;
116 std::vector<QGaussOneOverR<2> > sing_quadratures_3d;
117 for (
unsigned int i=0; i<comp_dom.fe.dofs_per_cell; ++i)
118 sing_quadratures_3d.push_back
120 comp_dom.fe.get_unit_support_points()[i],
true));
133 FEValues<dim-1,dim> fe_v(*comp_dom.mapping,comp_dom.fe, *comp_dom.quadrature,
135 update_cell_normal_vectors |
136 update_quadrature_points |
139 const unsigned int n_q_points = fe_v.n_quadrature_points;
141 std::vector<unsigned int> local_dof_indices(comp_dom.fe.dofs_per_cell);
159 Vector<double> local_neumann_matrix_row_i(comp_dom.fe.dofs_per_cell);
160 Vector<double> local_dirichlet_matrix_row_i(comp_dom.fe.dofs_per_cell);
168 std::vector<Point<dim> > support_points(comp_dom.dh.n_dofs());
184 cell = comp_dom.dh.begin_active(),
185 endc = comp_dom.dh.end();
190 for (cell = comp_dom.dh.begin_active(); cell != endc; ++cell)
193 cell->get_dof_indices(local_dof_indices);
195 const std::vector<Point<dim> > &q_points = fe_v.get_quadrature_points();
196 const std::vector<Point<dim> > &normals = fe_v.get_normal_vectors();
214 for (
unsigned int i=0; i<comp_dom.dh.n_dofs() ; ++i)
217 local_neumann_matrix_row_i = 0;
218 local_dirichlet_matrix_row_i = 0;
220 bool is_singular =
false;
223 for (
unsigned int j=0; j<comp_dom.fe.dofs_per_cell; ++j)
225 if (comp_dom.double_nodes_set[i].count(local_dof_indices[j]) > 0)
241 if (is_singular ==
false)
243 for (
unsigned int q=0; q<n_q_points; ++q)
245 const Point<dim> R = q_points[q] + -1.0*support_points[i];
248 for (
unsigned int j=0; j<comp_dom.fe.dofs_per_cell; ++j)
250 local_neumann_matrix_row_i(j) += ( ( D *
252 fe_v.shape_value(j,q) *
254 local_dirichlet_matrix_row_i(j) += ( s *
255 fe_v.shape_value(j,q) *
485 1./cell->measure(),
true))
490 &sing_quadratures_3d[singular_index])
495 FEValues<dim-1,dim> fe_v_singular (*comp_dom.mapping, comp_dom.fe, *singular_quadrature,
498 update_cell_normal_vectors |
499 update_quadrature_points );
501 fe_v_singular.reinit(cell);
503 const std::vector<Point<dim> > &singular_normals = fe_v_singular.get_normal_vectors();
504 const std::vector<Point<dim> > &singular_q_points = fe_v_singular.get_quadrature_points();
506 for (
unsigned int q=0; q<singular_quadrature->size(); ++q)
508 const Point<dim> R = singular_q_points[q] + -1.0*support_points[i];
511 for (
unsigned int j=0; j<comp_dom.fe.dofs_per_cell; ++j)
513 local_neumann_matrix_row_i(j) += (( D *
514 singular_normals[q]) *
515 fe_v_singular.shape_value(j,q) *
516 fe_v_singular.JxW(q) );
518 local_dirichlet_matrix_row_i(j) += ( s *
519 fe_v_singular.shape_value(j,q) *
520 fe_v_singular.JxW(q) );
524 delete singular_quadrature;
531 for (
unsigned int j=0; j<comp_dom.fe.dofs_per_cell; ++j)
533 neumann_matrix(i,local_dof_indices[j])
534 += local_neumann_matrix_row_i(j);
535 dirichlet_matrix(i,local_dof_indices[j])
536 += local_dirichlet_matrix_row_i(j);
589 std::cout<<
"done assembling system matrices"<<std::endl;
598 if (ones.
size() != comp_dom.dh.n_dofs())
600 ones.
reinit(comp_dom.dh.n_dofs());
602 zeros.
reinit(comp_dom.dh.n_dofs());
603 dummy.
reinit(comp_dom.dh.n_dofs());
607 if (solution_method ==
"Direct")
609 neumann_matrix.vmult(alpha, ones);
613 fma.generate_multipole_expansions(ones,zeros);
614 fma.multipole_matr_vect_products(ones,zeros,alpha,dummy);
634 if (phi.size() != src.
size())
637 dphi_dn.reinit(src.
size());
643 phi.
scale(comp_dom.other_nodes);
644 dphi_dn.scale(comp_dom.surface_nodes);
646 if (solution_method ==
"Direct")
648 dirichlet_matrix.vmult(dst, dphi_dn);
650 neumann_matrix.vmult_add(dst, phi);
657 fma.generate_multipole_expansions(phi,dphi_dn);
658 fma.multipole_matr_vect_products(phi,dphi_dn,matrVectProdN,matrVectProdD);
660 dst += matrVectProdD;
662 dst += matrVectProdN;
667 if (comp_dom.surface_nodes.linfty_norm() < 1e-10)
683 if (phi.size() != src.
size())
686 dphi_dn.reinit(src.
size());
694 phi.
scale(comp_dom.surface_nodes);
695 dphi_dn.scale(comp_dom.other_nodes);
700 if (solution_method ==
"Direct")
702 neumann_matrix.vmult(dst, phi);
706 dirichlet_matrix.vmult_add(dst, dphi_dn);
710 fma.generate_multipole_expansions(phi,dphi_dn);
711 fma.multipole_matr_vect_products(phi,dphi_dn,matrVectProdN,matrVectProdD);
713 dst += matrVectProdN;
716 dst += matrVectProdD;
839 compute_rhs(system_rhs, tmp_rhs);
841 compute_constraints(constraints, tmp_rhs);
843 cc(*
this, constraints);
847 if (solution_method ==
"Direct")
851 assemble_preconditioner();
853 solver.
solve (cc, sol, system_rhs, preconditioner);
858 solver.
solve (*
this, sol, system_rhs, inv);
869 for (
unsigned int i=0; i <comp_dom.surface_nodes.size(); i++)
871 if (comp_dom.surface_nodes(i) == 0)
912 serv_dphi_dn = dphi_dn;
917 serv_dphi_dn.scale(comp_dom.other_nodes);
918 serv_phi.scale(comp_dom.surface_nodes);
919 serv_tmp_rhs.add(serv_dphi_dn);
920 serv_tmp_rhs.add(serv_phi);
926 compute_rhs(rrhs, serv_tmp_rhs);
929 compute_constraints(constraints, serv_tmp_rhs);
931 cc(*
this, constraints);
943 serv_dphi_dn = dphi_dn;
944 serv_dphi_dn.
scale(comp_dom.surface_nodes);
945 serv_phi.scale(comp_dom.other_nodes);
946 sol.add(serv_dphi_dn);
949 if (solution_method ==
"Direct")
974 if (solution_method ==
"Direct")
980 comp_dom.generate_octree_blocking();
981 fma.direct_integrals();
982 fma.multipole_integrals();
985 solve_system(phi,dphi_dn,tmp_rhs);
996 comp_dom.compute_normals();
997 compute_surface_gradients(tmp_rhs);
1012 for (
unsigned int i=0; i <tmp_rhs.
size(); i++)
1018 std::set<unsigned int> doubles = comp_dom.double_nodes_set[i];
1019 unsigned int firstOfDoubles = *doubles.begin();
1020 for (std::set<unsigned int>::iterator it = doubles.begin() ; it != doubles.end(); it++ )
1022 if (comp_dom.surface_nodes(*it) == 1)
1024 firstOfDoubles = *it;
1031 if (i == firstOfDoubles)
1040 if (comp_dom.surface_nodes(i) == 1)
1042 for (std::set<unsigned int>::iterator it = doubles.begin() ; it != doubles.end(); it++ )
1044 if (comp_dom.surface_nodes(*it) == 1)
1048 if ( comp_dom.nodes_normals[*it].distance(comp_dom.nodes_normals[i]) < 1e-4 )
1058 double this_normal_gradient = (1.0/(1.0-pow(comp_dom.nodes_normals[i]*comp_dom.nodes_normals[*it],2))) *
1059 (node_surface_gradients[*it]*comp_dom.nodes_normals[i]+
1060 (node_surface_gradients[i]*comp_dom.nodes_normals[*it])*(comp_dom.nodes_normals[i]*comp_dom.nodes_normals[*it]));
1061 double other_normal_gradient = (1.0/(1.0-pow(comp_dom.nodes_normals[*it]*comp_dom.nodes_normals[i],2))) *
1062 (node_surface_gradients[i]*comp_dom.nodes_normals[*it]+
1063 (node_surface_gradients[*it]*comp_dom.nodes_normals[i])*(comp_dom.nodes_normals[*it]*comp_dom.nodes_normals[i]));
1090 if (comp_dom.surface_nodes(i) == 0)
1092 for (std::set<unsigned int>::iterator it = doubles.begin() ; it != doubles.end(); it++ )
1114 if (is_preconditioner_initialized ==
false)
1116 for (
int i=0; (
unsigned int) i<comp_dom.dh.n_dofs(); ++i)
1117 for (
int j=std::max(i-preconditioner_band/2,0); j<std::min(i+preconditioner_band/2,(
int)comp_dom.dh.n_dofs()); ++j)
1118 preconditioner_sparsity_pattern.
add((
unsigned int) j,(
unsigned int) i);
1119 preconditioner_sparsity_pattern.compress();
1120 band_system.
reinit(preconditioner_sparsity_pattern);
1121 is_preconditioner_initialized =
true;
1126 for (
int i=0; (
unsigned int) i<comp_dom.dh.n_dofs(); ++i)
1128 if (constraints.is_constrained(i))
1129 band_system.
set((
unsigned int)i,(
unsigned int) i, 1);
1130 for (
int j=std::max(i-preconditioner_band/2,0); j<std::min(i+preconditioner_band/2,(
int)comp_dom.dh.n_dofs()); ++j)
1132 if (constraints.is_constrained(j) ==
false)
1134 if (comp_dom.surface_nodes(i) == 0)
1137 band_system.
set(j,i,neumann_matrix(j,i));
1139 band_system.
add((
unsigned int) j,(
unsigned int) i, alpha(i));
1142 band_system.
set(j,i,-dirichlet_matrix(j,i));
1147 preconditioner.initialize(band_system);
1158 phi.
scale(comp_dom.surface_nodes);
1164 gradients_sparsity_pattern.
reinit(comp_dom.vector_dh.n_dofs(),
1165 comp_dom.vector_dh.n_dofs(),
1166 comp_dom.vector_dh.max_couplings_between_dofs());
1168 vector_constraints.
clear();
1170 vector_constraints.
close();
1172 gradients_sparsity_pattern.
compress();
1178 vector_gradients_matrix.
reinit (gradients_sparsity_pattern);
1179 vector_gradients_rhs.
reinit(comp_dom.vector_dh.n_dofs());
1180 Vector<double> vector_gradients_solution(comp_dom.vector_dh.n_dofs());
1183 FEValues<dim-1,dim> vector_fe_v(*comp_dom.mapping, comp_dom.vector_fe, *comp_dom.quadrature,
1184 update_values | update_gradients |
1185 update_cell_normal_vectors |
1186 update_quadrature_points |
1189 FEValues<dim-1,dim> fe_v(*comp_dom.mapping, comp_dom.fe, *comp_dom.quadrature,
1190 update_values | update_gradients |
1191 update_cell_normal_vectors |
1192 update_quadrature_points |
1195 const unsigned int vector_n_q_points = vector_fe_v.n_quadrature_points;
1196 const unsigned int vector_dofs_per_cell = comp_dom.vector_fe.dofs_per_cell;
1197 std::vector<unsigned int> vector_local_dof_indices (vector_dofs_per_cell);
1199 std::vector< Tensor<1,dim> > phi_surf_grads(vector_n_q_points);
1200 std::vector<double> phi_norm_grads(vector_n_q_points);
1201 std::vector<Vector<double> > q_vector_normals_solution(vector_n_q_points,
1204 FullMatrix<double> local_gradients_matrix (vector_dofs_per_cell, vector_dofs_per_cell);
1209 vector_cell = comp_dom.vector_dh.begin_active(),
1210 vector_endc = comp_dom.vector_dh.end();
1213 cell = comp_dom.dh.begin_active(),
1214 endc = comp_dom.dh.end();
1216 std::vector<Point<dim> > support_points(comp_dom.dh.n_dofs());
1218 std::vector<unsigned int> face_dofs(comp_dom.fe.dofs_per_face);
1220 Quadrature <dim-1> dummy_quadrature(comp_dom.fe.get_unit_support_points());
1221 FEValues<dim-1,dim> dummy_fe_v(*comp_dom.mapping, comp_dom.fe, dummy_quadrature,
1222 update_values | update_gradients |
1223 update_cell_normal_vectors |
1224 update_quadrature_points);
1226 const unsigned int dofs_per_cell = comp_dom.fe.dofs_per_cell;
1227 std::vector<unsigned int> local_dof_indices (dofs_per_cell);
1228 const unsigned int n_q_points = dummy_fe_v.n_quadrature_points;
1229 std::vector< Tensor<1,dim> > dummy_phi_surf_grads(n_q_points);
1232 for (; cell!=endc,vector_cell!=vector_endc; ++cell,++vector_cell)
1237 vector_fe_v.
reinit (vector_cell);
1238 local_gradients_matrix = 0;
1239 local_gradients_rhs = 0;
1240 const std::vector<Point<dim> > &vector_node_normals = vector_fe_v.get_normal_vectors();
1241 fe_v.get_function_gradients(phi, phi_surf_grads);
1242 unsigned int comp_i, comp_j;
1247 for (
unsigned int q=0; q<vector_n_q_points; ++q)
1249 Point<dim> gradient(phi_surf_grads[q][0],phi_surf_grads[q][1],phi_surf_grads[q][2]);
1250 for (
unsigned int i=0; i<vector_dofs_per_cell; ++i)
1252 comp_i = comp_dom.vector_fe.system_to_component_index(i).first;
1253 for (
unsigned int j=0; j<vector_dofs_per_cell; ++j)
1255 comp_j = comp_dom.vector_fe.system_to_component_index(j).first;
1256 if (comp_i == comp_j)
1258 local_gradients_matrix(i,j) += vector_fe_v.shape_value(i,q)*
1259 vector_fe_v.shape_value(j,q)*
1263 local_gradients_rhs(i) += (vector_fe_v.shape_value(i, q)) *
1264 gradient(comp_i) * vector_fe_v.JxW(q);
1267 vector_cell->get_dof_indices (vector_local_dof_indices);
1270 (local_gradients_matrix,
1271 local_gradients_rhs,
1272 vector_local_dof_indices,
1273 vector_gradients_matrix,
1274 vector_gradients_rhs);
1278 gradients_inverse.
initialize(vector_gradients_matrix);
1279 gradients_inverse.
vmult(vector_gradients_solution, vector_gradients_rhs);
1280 vector_constraints.
distribute(vector_gradients_solution);
1283 node_surface_gradients.resize(comp_dom.dh.n_dofs());
1285 for (
unsigned int i=0; i<comp_dom.vector_dh.n_dofs()/dim; ++i)
1287 for (
unsigned int d=0; d<dim; d++)
1288 node_surface_gradients[i](d) = vector_gradients_solution(3*i+d);
static const unsigned int invalid_unsigned_int
real_type l2_norm() const
void kernels(const Point< dim > &R, Point< dim > &D, double &d)
void set(const size_type i, const size_type j, const number value)
static void declare_parameters(ParameterHandler ¶m)
void distribute(VectorType &vec) const
void residual(Vector< double > &res, const Vector< double > &phi, const Vector< double > &dphi_dn)
virtual void reinit(const SparsityPattern &sparsity)
std::string get(const std::string &entry_string) const
DoFHandler< dim-1, dim >::active_cell_iterator cell_it
void enter_subsection(const std::string &subsection)
void add_line(const size_type line)
void add(const std::vector< size_type > &indices, const std::vector< OtherNumber > &values)
void make_hanging_node_constraints(const DoFHandlerType &dof_handler, ConstraintMatrix &constraints)
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
void distribute_rhs(VEC &rhs) const
void scale(const Vector< double > &scaling_factors)
void add_entry(const size_type line, const size_type column, const double value)
#define Assert(cond, exc)
void compute_constraints(ConstraintMatrix &constraints, const Vector< double > &tmp_rhs)
void assemble_preconditioner()
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &precondition)
void compute_rhs(Vector< double > &dst, const Vector< double > &src) const
void vmult(Vector< double > &dst, const Vector< double > &src) const
void vmult(VEC &dst, const VEC &src) const
void parse_parameters(ParameterHandler &prm)
void add(const size_type i, const size_type j, const number value)
void solve_system(Vector< double > &phi, Vector< double > &dphi_dn, const Vector< double > &tmp_rhs)
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
BEMProblem(ComputationalDomain< dim > &comp_dom, BEMFMA< dim > &fma)
void make_sparsity_pattern(const DoFHandlerType &dof_handler, SparsityPatternType &sparsity_pattern, const ConstraintMatrix &constraints=ConstraintMatrix(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void initialize(const SparsityPattern &sparsity_pattern)
void declare_parameters(ParameterHandler &prm)
void solve(Vector< double > &phi, Vector< double > &dphi_dn, const Vector< double > &tmp_rhs)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
void compute_surface_gradients(const Vector< double > &tmp_rhs)
void set_inhomogeneity(const size_type line, const double value)
void vmult(Vector< double > &dst, const Vector< double > &src) const
static::ExceptionBase & ExcInternalError()