GetFEM  5.5
getfem_crack_sif.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2007-2026 Yves Renard, Julien Pommier
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program. If not, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /**@file getfem_crack_sif.h
32  @author Julien Pommier
33  @date July 2007
34  @brief crack support functions for computation of SIF
35  (stress intensity factors)
36 */
37 
38 #ifndef GETFEM_CRACK_SIF_H
39 #define GETFEM_CRACK_SIF_H
40 
41 #include "getfem/getfem_mesh.h"
45 
46 namespace getfem {
47  /* build a "ring" of convexes of given center and radius */
48  inline dal::bit_vector
49  build_sif_ring_from_mesh(const mesh &m,
50  base_node center, scalar_type r) {
51  dal::bit_vector bv;
52  scalar_type r2 = r - 1e-4;
53  unsigned in = 0;
54  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
55  unsigned in1=0, out1=0;
56  unsigned in2=0, out2=0;
57  for (unsigned i=0; i < m.nb_points_of_convex(cv); ++i) {
58  base_node P = m.points_of_convex(cv)[i];
59  if (gmm::vect_dist2(P, center) < r) ++in1; else ++out1;
60  if (gmm::vect_dist2(P, center) < r2) ++in2; else ++out2;
61  }
62  if ((in1 && out1) || (in2 && out2)) bv.add(cv);
63  in += in1;
64  }
65  if (in < 3) GMM_WARNING1("looks like the radius is too small...");
66  return bv;
67  }
68 
69  /* return the crack tip in P,
70  and the outgoing tangent of the crack in T,
71  and the normal in N */
72  inline void get_crack_tip_and_orientation(const level_set &/* ls */,
73  base_node &P,
74  base_small_vector &T, base_small_vector &N) {
75  cerr << GMM_PRETTY_FUNCTION << " IS TO BE DONE\n";
76  /* too lazy to do it now */
77  P.resize(2); P[0] = .5; P[1] = 0;
78  T.resize(2); T[0] = 1; T[1] = 0;
79  N.resize(2); N[0] = 0; N[1] = 1;
80  }
81 
82 
83  /* compute with great precision the stress intensity factors using
84  integral computed on a ring around the crack tip */
85  template <typename VECT>
86  void compute_crack_stress_intensity_factors(const level_set &ls,
87  const mesh_im &mim,
88  const mesh_fem &mf,
89  const VECT &U,
90  scalar_type ring_radius,
91  scalar_type lambda, scalar_type mu,
92  scalar_type young_modulus,
93  scalar_type &KI, scalar_type &KII) {
94  const mesh &mring = mim.linked_mesh();
95  mesh_fem_global_function mf_mode(mring, 1);
96  mesh_fem mf_q(mring,1);
97 
98  std::vector<pglobal_function> cfun(4);
99  for (unsigned j=0; j < 4; ++j) {
100  auto s = std::make_shared<crack_singular_xy_function>(j);
101  cfun[j] = global_function_on_level_set(ls, s);
102  }
103  mf_mode.set_functions(cfun);
104  mf_mode.set_qdim(2);
105 
106  mf_q.set_classical_finite_element(1);
107 
108  base_node crack_tip;
109  base_small_vector T, N;
110  get_crack_tip_and_orientation(ls, crack_tip, T, N);
111 
112  dal::bit_vector cvring = build_sif_ring_from_mesh(mring, crack_tip,
113  ring_radius);
114 
115  /* fill the "q" ring field with a approximately linear field, equal to
116  1 on the inner boundary, and equal to zero on the outer boundary */
117  std::vector<scalar_type> q(mf_q.nb_basic_dof());
118  for (unsigned d = 0; d < mf_q.nb_basic_dof(); ++d) {
119  base_node P = mf_q.point_of_basic_dof(d);
120  q[d] = (gmm::vect_dist2(P, crack_tip) > ring_radius) ? 0 : 1;
121  }
122 
123  base_vector U_mode(mf_mode.nb_dof()); assert(U_mode.size() == 8);
124 
125  /* expression for SIF computation taken from "a finite element
126  method for crack growth without remeshing", moes, dolbow &
127  belytschko */
128 
129  generic_assembly
130  assem("lambda=data$1(1); mu=data$2(1); x1=data$3(mdim(#1)); "
131  "U1=data$4(#1); U2=data$5(#2); q=data$6(#3);"
132  "t=U1(i).U2(j).q(k).comp(vGrad(#1).vGrad(#2).Grad(#3))(i,:,:,j,:,:,k,:);"
133  "e1=(t{1,2,:,:,:}+t{2,1,:,:,:})/2;"
134  "e2=(t{:,:,3,4,:}+t{:,:,4,3,:})/2;"
135  "e12=(e1{:,:,3,4,:}+e1{:,:,4,3,:})/2;"
136  "V()+=2*mu(p).e1(i,j,i,k,j).x1(k) + lambda(p).e1(i,i,j,k,j).x1(k);"
137  "V()+=2*mu(p).e2(i,k,i,j,j).x1(k) + lambda(p).e2(j,k,i,i,j).x1(k);"
138  "V()+=-2*mu(p).e12(i,j,i,j,k).x1(k) - lambda(p).e12(i,i,j,j,k).x1(k);");
139  assem.push_mf(mf);
140  assem.push_mf(mf_mode);
141  assem.push_mf(mf_q);
142  assem.push_mi(mim);
143  base_vector vlambda(1); vlambda[0] = lambda;
144  base_vector vmu(1); vmu[0] = mu;
145  assem.push_data(vlambda);
146  assem.push_data(vmu);
147  assem.push_data(T); // outgoing tangent of the crack
148  assem.push_data(U);
149  assem.push_data(U_mode);
150  assem.push_data(q);
151  base_vector V(1);
152  assem.push_vec(V);
153 
154  /* fill with the crack opening mode I or mode II */
155  for (unsigned mode = 1; mode <= 2; ++mode) {
156  base_vector::iterator it = U_mode.begin();
157  scalar_type coeff=0.;
158  switch(mode) {
159  case 1: {
160  scalar_type A=2+2*mu/(lambda+2*mu), B=-2*(lambda+mu)/(lambda+2*mu);
161  /* "colonne" 1: ux, colonne 2: uy */
162  *it++ = 0; *it++ = A-B; /* sin(theta/2) */
163  *it++ = A+B; *it++ = 0; /* cos(theta/2) */
164  *it++ = -B; *it++ = 0; /* sin(theta/2)*sin(theta) */
165  *it++ = 0; *it++ = B; /* cos(theta/2)*cos(theta) */
166  coeff = 1/sqrt(2*M_PI);
167  } break;
168  case 2: {
169  scalar_type C1 = (lambda+3*mu)/(lambda+mu);
170  *it++ = C1+2-1; *it++ = 0;
171  *it++ = 0; *it++ = -(C1-2+1);
172  *it++ = 0; *it++ = 1;
173  *it++ = 1; *it++ = 0;
174  coeff = 2*(mu+lambda)/(lambda+2*mu)/sqrt(2*M_PI);
175  } break;
176  }
177  gmm::scale(U_mode, coeff/young_modulus);
178  V[0] = 0.;
179  cout << "assemblig SIFs ..." << std::flush;
180  double time = gmm::uclock_sec();
181  assem.assembly(cvring);
182  cout << "done (" << gmm::uclock_sec()-time << " sec)\n";
183  V[0] *= young_modulus/2; /* plane stress only, should be E/(2*(1-nu)) for plane strain */
184  if (mode == 1) KI = V[0]; else KII = V[0];
185  }
186  }
187 
188  /* return a (very rough) estimate of the stress intensity factors using
189  the local displacement near the crack tip */
190  template <typename VECT>
191  void estimate_crack_stress_intensity_factors(const level_set &ls,
192  const mesh_fem &mf, const VECT &U,
193  scalar_type young_modulus,
194  scalar_type &KI,
195  scalar_type &KII, double EPS=1e-2) {
196  base_node P(2);
197  base_small_vector T(2),N(2);
198  get_crack_tip_and_orientation(ls, P, T, N);
199  base_node P1 = P - EPS*T + EPS/100.*N;
200  base_node P2 = P - EPS*T - EPS/100.*N;
201  std::vector<double> V(4);
202  getfem::mesh_trans_inv mti(mf.linked_mesh());
203  mti.add_point(P1);
204  mti.add_point(P2);
205  cout << "P1 = " << P1 << ", P2=" << P2 << "\n";
206  base_matrix M;
207  getfem::interpolation(mf, mti, U, V, false);
208  KI = (V[1] - V[3])/sqrt(EPS/(2*M_PI)) * young_modulus / 8.0;
209  KII = (V[0] - V[2])/sqrt(EPS/(2*M_PI)) * young_modulus / 8.0;
210  }
211 }
212 
213 #endif // GETFEM_CRACK_SIF_H
Generic assembly implementation.
Define level-sets.
Define a getfem::getfem_mesh object.
Define a mesh_fem with base functions which are global functions given by the user.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
Definition: gmm_blas.h:596
GEneric Tool for Finite Element Methods.
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.