40 using std::endl;
using std::cout;
using std::cerr;
41 using std::ends;
using std::cin;
46 using bgeot::scalar_type;
53 typedef gmm::row_matrix<sparse_vector_type> sparse_matrix_type;
54 typedef gmm::col_matrix<sparse_vector_type> col_sparse_matrix_type;
55 typedef std::vector<scalar_type> plain_vector;
61 base_small_vector sol_K;
63 scalar_type sol_u(
const base_node &x) {
return sin(gmm::vect_sp(sol_K, x)); }
65 scalar_type sol_f(
const base_node &x)
66 {
return gmm::vect_sp(sol_K, sol_K) * sin(gmm::vect_sp(sol_K, x)); }
68 base_small_vector sol_grad(
const base_node &x)
69 {
return sol_K * cos(gmm::vect_sp(sol_K, x)); }
74 struct laplacian_problem {
76 enum { DIRICHLET_BOUNDARY_NUM = 0, NEUMANN_BOUNDARY_NUM = 1};
87 sparse_matrix_type SM;
88 std::vector<scalar_type> U, B;
90 std::vector<scalar_type> Ud;
91 col_sparse_matrix_type NS;
94 std::string datafilename;
95 bgeot::md_param PARAM;
100 void compute_error();
101 laplacian_problem(
void) : mim(mesh), mf_u(mesh), mf_rhs(mesh),
108 void laplacian_problem::init(
void) {
110 std::string MESH_TYPE = PARAM.string_value(
"MESH_TYPE",
"Mesh type ");
111 std::string FEM_TYPE = PARAM.string_value(
"FEM_TYPE",
"FEM name");
112 std::string INTEGRATION = PARAM.string_value(
"INTEGRATION",
113 "Name of integration method");
115 cout <<
"MESH_TYPE=" << MESH_TYPE <<
"\n";
116 cout <<
"FEM_TYPE=" << FEM_TYPE <<
"\n";
117 cout <<
"INTEGRATION=" << INTEGRATION <<
"\n";
123 std::vector<size_type> nsubdiv(N);
124 std::fill(nsubdiv.begin(),nsubdiv.end(),
125 PARAM.int_value(
"NX",
"Nomber of space steps "));
127 PARAM.int_value(
"MESH_NOISED") != 0);
129 bgeot::base_matrix M(N,N);
131 static const char *t[] = {
"LX",
"LY",
"LZ"};
132 M(i,i) = (i<3) ? PARAM.real_value(t[i],t[i]) : 1.0;
134 if (N>1) { M(0,1) = PARAM.real_value(
"INCLINE") * PARAM.real_value(
"LY"); }
137 mesh.transformation(M);
139 datafilename = PARAM.string_value(
"ROOTFILENAME",
"Base name of data files.");
140 scalar_type FT = PARAM.real_value(
"FT",
"parameter for exact solution");
141 residual = PARAM.real_value(
"RESIDUAL");
142 if (residual == 0.) residual = 1e-10;
145 sol_K[j] = ((j & 1) == 0) ? FT : -FT;
151 mim.set_integration_method(mesh.convex_index(), ppi);
152 mf_u.set_finite_element(mesh.convex_index(), pf_u);
156 std::string data_fem_name = PARAM.string_value(
"DATA_FEM_TYPE");
157 if (data_fem_name.size() == 0) {
158 GMM_ASSERT1(pf_u->is_lagrange(),
"You are using a non-lagrange FEM. "
159 <<
"In that case you need to set "
160 <<
"DATA_FEM_TYPE in the .param file");
161 mf_rhs.set_finite_element(mesh.convex_index(), pf_u);
163 mf_rhs.set_finite_element(mesh.convex_index(),
170 mf_coef.set_finite_element(mesh.convex_index(),
175 gen_dirichlet = PARAM.int_value(
"GENERIC_DIRICHLET");
177 if (!pf_u->is_lagrange() && !gen_dirichlet)
178 GMM_WARNING2(
"With non lagrange fem prefer the generic "
179 "Dirichlet condition option");
181 cout <<
"Selecting Neumann and Dirichlet boundaries\n";
186 base_node un = mesh.normal_of_face_of_convex(i.cv(), i.f());
188 if (gmm::abs(un[N-1] - 1.0) < 1.0E-7) {
189 mesh.region(NEUMANN_BOUNDARY_NUM).add(i.cv(), i.f());
191 mesh.region(DIRICHLET_BOUNDARY_NUM).add(i.cv(), i.f());
196 void laplacian_problem::assembly(
void) {
204 cout <<
"Number of dof : " << nb_dof << endl;
205 cout <<
"Assembling stiffness matrix" << endl;
207 std::vector<scalar_type>(mf_coef.nb_dof(), 1.0));
209 cout <<
"Assembling source term" << endl;
210 std::vector<scalar_type> F(nb_dof_rhs);
214 cout <<
"Assembling Neumann condition" << endl;
218 NEUMANN_BOUNDARY_NUM);
220 cout <<
"take Dirichlet condition into account" << endl;
221 if (!gen_dirichlet) {
222 std::vector<scalar_type> D(nb_dof);
224 getfem::assembling_Dirichlet_condition(SM, B, mf_u,
225 DIRICHLET_BOUNDARY_NUM, D);
232 col_sparse_matrix_type H(nb_dof_rhs, nb_dof);
233 std::vector<scalar_type> R(nb_dof_rhs);
234 std::vector<scalar_type> RHaux(nb_dof);
238 mf_rhs, F, DIRICHLET_BOUNDARY_NUM);
240 gmm::clean(H, 1e-12);
247 gmm::mult(SM, Ud, gmm::scaled(B, -1.0), RHaux);
250 gmm::mult(gmm::transposed(NS), gmm::scaled(RHaux, -1.0), B);
251 sparse_matrix_type SMaux(nbcols, nb_dof);
252 gmm::mult(gmm::transposed(NS), SM, SMaux);
255 sparse_matrix_type NSaux(nb_dof, nbcols); gmm::copy(NS, NSaux);
256 gmm::mult(SMaux, NSaux, SM);
261 bool laplacian_problem::solve(
void) {
265 cout <<
"Compute preconditionner\n";
267 double time = gmm::uclock_sec();
277 cout <<
"Time to compute preconditionner : "
278 << gmm::uclock_sec() - time <<
" seconds\n";
284 gmm::gmres(SM, U, B, P, 50, iter);
287 gmm::SuperLU_solve(SM, U, B, rcond);
288 cout <<
"cond = " << 1/rcond <<
"\n";
291 cout <<
"Total time to solve : "
292 << gmm::uclock_sec() - time <<
" seconds\n";
295 std::vector<scalar_type> Uaux(mf_u.nb_dof());
296 gmm::mult(NS, U, Ud, Uaux);
301 return (iter.converged());
305 void laplacian_problem::compute_error() {
306 std::vector<scalar_type> V(mf_rhs.nb_basic_dof());
308 for (
size_type i = 0; i < mf_rhs.nb_basic_dof(); ++i)
309 V[i] -= sol_u(mf_rhs.point_of_basic_dof(i));
320 int main(
int argc,
char *argv[]) {
322 GETFEM_MPI_INIT(argc, argv);
323 GMM_SET_EXCEPTION_DEBUG;
328 p.PARAM.read_command_line(argc, argv);
330 p.mesh.write_to_file(p.datafilename +
".mesh");
332 if (!p.solve()) GMM_ASSERT1(
false,
"Solve procedure has failed");
335 GMM_STANDARD_CATCH_ERROR;