37 using std::endl;
using std::cout;
using std::cerr;
38 using std::ends;
using std::cin;
43 using bgeot::scalar_type;
45 using bgeot::dim_type;
46 using bgeot::base_matrix;
52 typedef getfem::modeling_standard_sparse_matrix sparse_matrix;
53 typedef getfem::modeling_standard_plain_vector plain_vector;
58 struct plate_problem {
60 enum { SIMPLY_FIXED_BOUNDARY_NUM = 0 };
68 scalar_type lambda, mu;
83 base_matrix theta1_Four, theta2_Four, u3_Four ;
89 std::string datafilename;
90 bgeot::md_param PARAM;
92 base_small_vector theta_exact(base_node P);
93 scalar_type u3_exact(base_node P);
95 bool solve(plain_vector &Ut, plain_vector &U3, plain_vector &THETA);
97 void compute_error(plain_vector &Ut, plain_vector &U3, plain_vector &THETA);
98 plate_problem(
void) : mim(mesh), mim_subint(mesh), mf_ut(mesh), mf_u3(mesh),
99 mf_theta(mesh), mf_rhs(mesh), mf_coef(mesh) {}
105 void plate_problem::init(
void) {
106 std::string MESH_FILE = PARAM.string_value(
"MESH_FILE");
107 std::string MESH_TYPE = PARAM.string_value(
"MESH_TYPE",
"Mesh type ");
108 std::string FEM_TYPE_UT = PARAM.string_value(
"FEM_TYPE_UT",
"FEM name");
109 std::string FEM_TYPE_U3 = PARAM.string_value(
"FEM_TYPE_U3",
"FEM name");
110 std::string FEM_TYPE_THETA = PARAM.string_value(
"FEM_TYPE_THETA",
"FEM name");
111 std::string INTEGRATION = PARAM.string_value(
"INTEGRATION",
112 "Name of integration method");
113 std::string INTEGRATION_CT = PARAM.string_value(
"INTEGRATION_CT",
114 "Name of integration method");
115 cout <<
"MESH_TYPE=" << MESH_TYPE <<
"\n";
116 cout <<
"FEM_TYPE_UT=" << FEM_TYPE_UT <<
"\n";
117 cout <<
"INTEGRATION=" << INTEGRATION <<
"\n";
118 cout <<
"INTEGRATION_CT=" << INTEGRATION_CT <<
"\n";
124 if (!MESH_FILE.empty()) {
125 cout <<
"MESH_FILE=" << MESH_FILE <<
"\n";
126 mesh.read_from_file(MESH_FILE);
128 (mesh.trans_of_convex(mesh.convex_index().first_true()));
129 cout <<
"MESH_TYPE=" << MESH_TYPE <<
"\n";
133 GMM_ASSERT1(N == 2,
"For a plate problem, N should be 2");
134 std::vector<size_type> nsubdiv(N);
135 std::fill(nsubdiv.begin(),nsubdiv.end(),
136 PARAM.int_value(
"NX",
"Number of space steps "));
138 PARAM.int_value(
"MESH_NOISED") != 0);
141 datafilename = PARAM.string_value(
"ROOTFILENAME",
"Base name of data files.");
142 residual = PARAM.real_value(
"RESIDUAL");
if (residual == 0.) residual = 1e-10;
143 mitc = (PARAM.int_value(
"MITC",
"Mitc version ?") != 0);
147 if (mitc) cout <<
"true \n" ;
else cout <<
"false \n" ;
148 sol_ref = int(PARAM.int_value(
"SOL_REF") ) ;
149 study_flag = int(PARAM.int_value(
"STUDY_FLAG") ) ;
150 eta = (PARAM.real_value(
"ETA") );
151 N_Four = (PARAM.int_value(
"N_Four") ) ;
154 LX = PARAM.real_value(
"LX");
155 LY = PARAM.real_value(
"LY");
156 mu = PARAM.real_value(
"MU",
"Lamé coefficient mu");
157 lambda = PARAM.real_value(
"LAMBDA",
"Lamé coefficient lambda");
158 epsilon = PARAM.real_value(
"EPSILON",
"thickness of the plate");
159 pressure = PARAM.real_value(
"PRESSURE",
160 "pressure on the top surface of the plate.");
163 cout <<
"SOL_REF = " ;
164 if (sol_ref==0) cout <<
"appui simple aux 2 bords verticaux\n" ;
165 if (sol_ref==1) cout <<
"encastrement aux 2 bords verticaux\n" ;
167 cout <<
"encastrement aux 4 bords verticaux, solution en sin(x)^2*sin(y)^2\n" ;
168 cout <<
"eta = " << eta <<
"\n";
171 cout <<
"bord en appuis simple\n" ;
172 cout <<
"nombre de terme pour calcul sol exacte : " << N_Four <<
" \n" ;
178 base_matrix Jmn(3, 3) ;
179 base_small_vector Bmn(3), Xmn(3) ;
180 scalar_type A, B, e2, Pmn ;
181 E = 4.*mu*(mu+lambda) / (2. * mu + lambda);
182 nu = lambda / (2. * mu + lambda);
183 e2 = epsilon * epsilon / 4. ;
184 for(
size_type i = 0 ; i < N_Four ; i++) {
185 for(
size_type j = 0 ; j < N_Four ; j++) {
186 A = scalar_type(j + 1) * M_PI / LX ;
187 B = scalar_type(i + 1) * M_PI / LY ;
188 Jmn(0, 0) = 2. * A * A / (1. - nu) + B * B + 3. / e2 ;
189 Jmn(0, 1) = A * B * (1. +nu) / (1. - nu) ;
190 Jmn(0, 2) = A * 3. / e2 ;
191 Jmn(1, 0) = A * B * (1. +nu) / (1. - nu) ;
192 Jmn(1, 1) = 2. * B * B / (1. - nu) + A * A + 3. / e2 ;
193 Jmn(1, 2) = B * 3. / e2 ;
196 Jmn(2, 2) = A * A + B * B ;
197 gmm::scale(Jmn, - E*(epsilon/2.) / (1. + nu) ) ;
200 if ( ( (i + 1) % 2 == 1 ) && ( (j + 1) % 2 == 1) ) {
201 Pmn = 16. * pressure / ( scalar_type(i + 1) * scalar_type(j + 1) * M_PI * M_PI) ; }
207 gmm::lu_solve(Jmn, Xmn, Bmn) ;
208 theta1_Four(i, j) = Xmn[0] ;
209 theta1_Four(i, j) = Xmn[1] ;
210 u3_Four(i, j) = Xmn[2] ;
215 mf_ut.set_qdim(dim_type(N));
216 mf_theta.set_qdim(dim_type(N));
223 getfem::pintegration_method ppi =
225 getfem::pintegration_method ppi_ct =
228 mim.set_integration_method(mesh.convex_index(), ppi);
229 mim_subint.set_integration_method(mesh.convex_index(), ppi_ct);
230 mf_ut.set_finite_element(mesh.convex_index(), pf_ut);
231 mf_u3.set_finite_element(mesh.convex_index(), pf_u3);
232 mf_theta.set_finite_element(mesh.convex_index(), pf_theta);
236 std::string data_fem_name = PARAM.string_value(
"DATA_FEM_TYPE");
237 if (data_fem_name.size() == 0) {
238 GMM_ASSERT1(pf_ut->is_lagrange(),
"You are using a non-lagrange FEM. " 239 <<
"In that case you need to set " 240 <<
"DATA_FEM_TYPE in the .param file");
241 mf_rhs.set_finite_element(mesh.convex_index(), pf_ut);
243 mf_rhs.set_finite_element(mesh.convex_index(),
250 mf_coef.set_finite_element(mesh.convex_index(),
255 cout <<
"Selecting Neumann and Dirichlet boundaries\n";
260 base_node un = mesh.normal_of_face_of_convex(i.cv(), i.f());
264 if (gmm::abs(un[1]) <= 1.0E-7)
265 mesh.region(SIMPLY_FIXED_BOUNDARY_NUM).add(i.cv(), i.f());
268 if (gmm::abs(un[1]) <= 1.0E-7)
269 mesh.region(SIMPLY_FIXED_BOUNDARY_NUM).add(i.cv(), i.f());
272 if ( (gmm::abs(un[0]) <= 1.0E-7) || (gmm::abs(un[1]) <= 1.0E-7) )
273 mesh.region(SIMPLY_FIXED_BOUNDARY_NUM).add(i.cv(), i.f());
276 if (un[0] <= (- 1. + 1.0E-7))
277 mesh.region(SIMPLY_FIXED_BOUNDARY_NUM).add(i.cv(), i.f());
280 if ( (gmm::abs(un[0]) <= 1.0E-7) || (gmm::abs(un[1]) <= 1.0E-7) )
281 mesh.region(SIMPLY_FIXED_BOUNDARY_NUM).add(i.cv(), i.f());
284 GMM_ASSERT1(
false,
"SOL_REF parameter is undefined");
290 base_small_vector plate_problem::theta_exact(base_node P) {
291 base_small_vector theta(2);
293 theta[0] = - (-pressure / (32. * mu * epsilon * epsilon * epsilon / 8.))
294 * (4. * pow(P[0] - .5, 3.) - 3 * (P[0] - .5));
298 theta[0] = - (-pressure / (16. * mu * epsilon * epsilon * epsilon / 8.))
299 * P[0] * ( 2.*P[0]*P[0] - 3.* P[0] + 1. ) ;
303 theta[0] = (1. + eta) * M_PI * sin(2.*M_PI*P[0]) * sin(M_PI*P[1])* sin(M_PI*P[1]) ;
304 theta[1] = (1. + eta) * M_PI * sin(2.*M_PI*P[1]) * sin(M_PI*P[0])* sin(M_PI*P[0]) ;
307 theta[0] = - (- 3. * pressure / (8. * mu * epsilon * epsilon * epsilon / 8.))
308 * P[0] * ( 0.25 * P[0] * P[0] - P[0] + 1. ) ;
314 for(
size_type i = 0 ; i < N_Four ; i ++) {
315 for(
size_type j = 0 ; j < N_Four ; j ++) {
316 theta[0] -= theta1_Four(i, j) * cos( scalar_type(j + 1) * M_PI * P[0] / LX ) * sin( scalar_type(i + 1) * M_PI * P[1] / LY ) ;
317 theta[0] -= theta2_Four(i, j) * sin( scalar_type(j + 1) * M_PI * P[0] / LX ) * cos( scalar_type(i + 1) * M_PI * P[1] / LY ) ;
324 scalar_type plate_problem::u3_exact(base_node P) {
326 case 0 :
return (pressure / (32. * mu * epsilon * epsilon * epsilon / 8.))
328 * (gmm::sqr(P[0] - .5) -1.25-(8.* epsilon*epsilon / 4.));
330 case 1 :
return (pressure /(32.* mu * epsilon * epsilon * epsilon / 8.))
332 * ( P[0] * P[0] - P[0] - 8. * epsilon *epsilon / 4.) ;
334 case 2 :
return gmm::sqr(sin(M_PI*P[0])) * gmm::sqr(sin(M_PI*P[1]));
336 case 3 :
return (3. * pressure / (4. * mu * epsilon * epsilon * epsilon / 8. ))
337 * P[0] * ( P[0] * P[0] * P[0] / 24. - P[0] * P[0] / 6. + P[0] / 4.
338 - (epsilon * epsilon / 4.) * P[0] / 3.
339 + 2. * (epsilon * epsilon / 4.) / 3.) ;
342 scalar_type u3_local ;
344 for(
size_type i = 0 ; i < N_Four ; i ++) {
346 u3_local += u3_Four(i, j) * sin( scalar_type(j + 1) * M_PI * P[0] / LX ) * sin( scalar_type(i + 1) * M_PI * P[1] / LY ) ;
350 default : GMM_ASSERT1(
false,
"indice de solution de référence incorrect");
356 void plate_problem::compute_error(plain_vector &Ut, plain_vector &U3, plain_vector &THETA) {
358 if (PARAM.int_value(
"SOL_EXACTE") == 1) {
362 std::vector<scalar_type> V(mf_rhs.nb_dof()*2);
370 cout <<
"L2 error = " << sqrt(l2) << endl
371 <<
"H1 error = " << sqrt(h1) << endl
372 <<
"Linfty error = " << linf << endl;
375 GMM_ASSERT1(!mf_rhs.is_reduced(),
376 "To be adapted, use interpolation_function");
377 for (
size_type i = 0; i < mf_rhs.nb_dof(); ++i) {
378 gmm::add(gmm::scaled(theta_exact(mf_rhs.point_of_basic_dof(i)), -1.0),
379 gmm::sub_vector(V, gmm::sub_interval(i*2, 2)));
384 linf = std::max(linf, gmm::vect_norminf(V));
386 cout <<
"L2 error theta:" << sqrt(l2) << endl
387 <<
"H1 error theta:" << sqrt(h1) << endl
388 <<
"Linfty error = " << linf << endl;
393 for (
size_type i = 0; i < mf_rhs.nb_dof(); ++i)
394 V[i] -= u3_exact(mf_rhs.point_of_basic_dof(i));
398 linf = std::max(linf, gmm::vect_norminf(V));
401 cout <<
"L2 error u3:" << sqrt(l2) << endl
402 <<
"H1 error u3:" << sqrt(h1) << endl
403 <<
"Linfty error = " << linf << endl;
406 if (PARAM.int_value(
"SAUV")){
407 std::ofstream f_out(
"errH1.don");
408 if (!f_out)
throw std :: runtime_error(
"Impossible to open file") ;
409 f_out << sqrt(h1) <<
"\n" ;
419 bool plate_problem::solve(plain_vector &Ut, plain_vector &U3, plain_vector &THETA) {
422 cout <<
"Number of dof for ut: " << mf_ut.nb_dof() << endl;
423 cout <<
"Number of dof for u3: " << mf_u3.nb_dof() << endl;
424 cout <<
"Number of dof for theta: " << mf_theta.nb_dof() << endl;
426 E = 4.*mu*(mu+lambda) / (2. * mu + lambda);
427 nu = lambda / (2. * mu + lambda);
428 scalar_type kappa = 5./6.;
443 "E",
"nu",
"epsilon",
"kappa",
448 if (study_flag == 1 ){
449 cout <<
"Attention : l'intensité de la pression verticale " ;
450 cout <<
"a été choisie pour que le déplacement maximal soit unitaire." ;
451 cout <<
"Pour annuler cette option, faire STUDY_FLAG = 0\n" ;
454 pressure = 128. * mu * epsilon * epsilon * epsilon / 8. ;
455 pressure /= 1.25 + 8. * epsilon * epsilon / 4. ;
458 pressure = 128. * mu * epsilon * epsilon * epsilon / 8. ;
459 pressure /= 0.25 + 8. * epsilon * epsilon / 4. ;
462 pressure = 32. * mu * epsilon * epsilon * epsilon / 8.;
463 pressure /= 3. + 8. * epsilon * epsilon / 4.;
468 plain_vector F(nb_dof_rhs);
469 plain_vector M(nb_dof_rhs * 2);
471 base_small_vector P(2) ;
472 scalar_type sx, sy, cx, cy, s2x, s2y, c2x, c2y ;
473 E = 4.*mu*(mu+lambda) / (2. * mu + lambda);
474 nu = lambda / (2. * mu + lambda);
475 for (
size_type i = 0; i < nb_dof_rhs; ++i) {
476 P = mf_rhs.point_of_basic_dof(i);
477 sx = sin(M_PI*P[0]) ;
478 cx = cos(M_PI*P[0]) ;
479 sy = sin(M_PI*P[1]) ;
480 cy = cos(M_PI*P[1]) ;
481 c2x = cos(2.*M_PI*P[0]) ;
482 c2y = cos(2.*M_PI*P[1]) ;
483 s2x = sin(2.*M_PI*P[0]) ;
484 s2y = sin(2.*M_PI*P[1]) ;
485 F[i] = 2. * (epsilon / 2.) * E * M_PI * M_PI * eta *
486 ( sy * sy * c2x + sx * sx * c2y ) / ( 1. + nu ) ;
487 M[2*i] = -((epsilon * epsilon * epsilon / 8.) * E * M_PI * s2x / 3. / (1. + nu))
488 * ( (4. * M_PI * M_PI * (1. + eta) * (2. * c2y - 1.) / (1.- nu))
489 - 3. * eta * sy * sy / (epsilon/2.) / (epsilon/2.) ) ;
490 M[2*i+1] = -((epsilon * epsilon * epsilon/8.) * E * M_PI * s2y / 3. / (1. + nu))
491 * ( (4. * M_PI * M_PI * (1. + eta) * (2. * c2x - 1.) / (1.- nu))
492 - 3. * eta * sx * sx / (epsilon/2.) / (epsilon/2.) ) ;
496 for (
size_type i = 0; i < nb_dof_rhs; ++i) {
506 (md, mim,
"u3", mf_u3, SIMPLY_FIXED_BOUNDARY_NUM);
508 (md, mim,
"ut", mf_ut, SIMPLY_FIXED_BOUNDARY_NUM);
510 if (sol_ref == 1 || sol_ref == 2 || sol_ref == 3)
512 (md, mim,
"theta", mf_ut, SIMPLY_FIXED_BOUNDARY_NUM);
527 if (PARAM.int_value(
"VTK_EXPORT")) {
528 cout <<
"export to " << datafilename +
".vtk" <<
"..\n";
530 PARAM.int_value(
"VTK_EXPORT")==1);
532 exp.write_point_data(mf_u3, U3,
"plate_normal_displacement");
533 cout <<
"export done, you can view the data file with (for example)\n" 534 "mayavi2 -d " << datafilename <<
".vtk -f " 535 "WarpScalar -m Surface -m Outline\n";
540 if (PARAM.int_value(
"DX_EXPORT")) {
541 cout <<
"export to " << datafilename +
".dx" <<
".\n";
543 PARAM.int_value(
"DX_EXPORT")==1);
544 exp.exporting(mf_u3);
545 exp.write_point_data(mf_u3, U3,
"plate_normal_displacement");
549 return (iter.converged());
556 int main(
int argc,
char *argv[]) {
558 GMM_SET_EXCEPTION_DEBUG;
563 p.PARAM.read_command_line(argc, argv);
565 if ((p.study_flag != 1)&&((p.sol_ref == 0) || (p.sol_ref ==1)))
566 p.pressure *= p.epsilon * p.epsilon * p.epsilon / 8.;
567 p.mesh.write_to_file(p.datafilename +
".mesh");
568 plain_vector Ut, U3, THETA;
569 bool ok = p.solve(Ut, U3, THETA);
570 p.compute_error(Ut, U3, THETA);
571 GMM_ASSERT1(ok,
"Solve has failed");
574 GMM_STANDARD_CATCH_ERROR;
structure used to hold a set of convexes and/or convex faces.
Export solutions to various formats.
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
The Iteration object calculates whether the solution has reached the desired accuracy, or whether the maximum number of iterations has been reached.
size_type APIDECL add_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1), const std::string &directdataname=std::string())
Add a source term on the variable varname.
size_type APIDECL add_isotropic_linearized_elasticity_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname_lambda, const std::string &dataname_mu, size_type region=size_type(-1), const std::string &dataname_preconstraint=std::string())
Linear elasticity brick ( ).
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.
Describe a mesh (collection of convexes (elements) and points).
void standard_solve(model &md, gmm::iteration &iter, rmodel_plsolver_type lsolver, abstract_newton_line_search &ls)
A default solver for the model brick system.
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .
Describe an integration method linked to a mesh.
void exporting(const mesh &m)
should be called before write_*_data
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
``Model'' variables store the variables, the data and the description of a model. ...
size_t size_type
used as the common size type in the library
void add_initialized_scalar_data(const std::string &name, T e)
Add a scalar data (i.e.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norminf(const V &v)
Infinity norm of a vector.
Standard solvers for model bricks.
Reissner-Mindlin plate model brick.
"iterator" class for regions.
A (quite large) class for exportation of data to IBM OpenDX.
sparse vector built upon std::vector.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Describe a finite element method linked to a mesh.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
size_type add_Mindlin_Reissner_plate_brick(model &md, const mesh_im &mim, const mesh_im &mim_reduced, const std::string &u3, const std::string &Theta, const std::string ¶m_E, const std::string ¶m_nu, const std::string ¶m_epsilon, const std::string ¶m_kappa, size_type variant=size_type(2), size_type region=size_type(-1))
Add a term corresponding to the classical Reissner-Mindlin plate model for which u3 is the transverse...
void add_initialized_fem_data(const std::string &name, const mesh_fem &mf, const VECT &v)
Add an initialized fixed size data to the model, assumed to be a vector field if the size of the vect...
pfem classical_fem(bgeot::pgeometric_trans pgt, short_type k, bool complete=false)
Give a pointer on the structures describing the classical polynomial fem of degree k on a given conve...
scalar_type asm_L2_norm(const mesh_im &mim, const mesh_fem &mf, const VEC &U, const mesh_region &rg=mesh_region::all_convexes())
compute , U might be real or complex
void add_fem_variable(const std::string &name, const mesh_fem &mf, size_type niter=1)
Add a variable being the dofs of a finite element method to the model.
const model_real_plain_vector & real_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
scalar_type asm_H1_norm(const mesh_im &mim, const mesh_fem &mf, const VEC &U, const mesh_region &rg=mesh_region::all_convexes())
compute the H1 norm of U.
Include common gmm files.
Miscelleanous assembly routines for common terms. Use the low-level generic assembly. Prefer the high-level one.
void resize(M &v, size_type m, size_type n)
*/
void regular_unit_mesh(mesh &m, std::vector< size_type > nsubdiv, bgeot::pgeometric_trans pgt, bool noised=false)
Build a regular mesh of the unit square/cube/, etc.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type APIDECL add_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
scalar_type asm_H1_semi_norm(const mesh_im &mim, const mesh_fem &mf, const VEC &U, const mesh_region &rg=mesh_region::all_convexes())
compute , U might be real or complex
void APIDECL outer_faces_of_mesh(const mesh &m, const dal::bit_vector &cvlst, convex_face_ct &flist)
returns a list of "exterior" faces of a mesh (i.e.