def phi_inv(C): arg = s_inv(C)/v_inv(C)*fe.sqrt(1./v_inv(C)) # numerical issues if arg~0 # https://fenicsproject.org/qa/12299 # /nan-values-when-computing-arccos-1-0-bug/ arg_cond = fe.conditional( fe.ge(arg, 1-fe.DOLFIN_EPS), 1-fe.DOLFIN_EPS,fe.conditional( fe.le(arg, -1+fe.DOLFIN_EPS), -1+fe.DOLFIN_EPS, arg )) return fe.acos(arg_cond)/3.
def inverse_ratio_function_ufl(ratio, map_type): if map_type == 'linear': return fe.conditional( fe.lt(ratio, -1. / 4.), 2. / 3. * ratio - 1. / 3., fe.conditional(fe.gt(ratio, 1. / 4.), 2. / 3. * ratio + 1. / 3., 2. * ratio)) elif map_type == 'power': return ratio**(0.5) elif map_type == 'identity': return ratio else: raise NotImplementedError("To be implemented")
def psi_minus_linear_elasticity_model_C(epsilon, lamda, mu): sqrt_delta = fe.conditional( fe.gt(fe.tr(epsilon)**2 - 4 * fe.det(epsilon), 0), fe.sqrt(fe.tr(epsilon)**2 - 4 * fe.det(epsilon)), 0) eigen_value_1 = (fe.tr(epsilon) + sqrt_delta) / 2 eigen_value_2 = (fe.tr(epsilon) - sqrt_delta) / 2 tr_epsilon_minus = fe.conditional(fe.lt(fe.tr(epsilon), 0.), fe.tr(epsilon), 0.) eigen_value_1_minus = fe.conditional(fe.lt(eigen_value_1, 0.), eigen_value_1, 0.) eigen_value_2_minus = fe.conditional(fe.lt(eigen_value_2, 0.), eigen_value_2, 0.) return lamda / 2 * tr_epsilon_minus**2 + mu * (eigen_value_1_minus**2 + eigen_value_2_minus**2)
def ratio_function_ufl(ratio, map_type): if map_type == 'linear': return fe.conditional( fe.lt(ratio, -1. / 2.), 3. / 2. * ratio + 1. / 2., fe.conditional(fe.gt(ratio, 1. / 2.), 3. / 2. * ratio - 1. / 2., 1. / 2. * ratio)) elif map_type == 'power': return ratio**(2.) elif map_type == 'identity': return ratio elif map_type == 'smooth': return fe.conditional(fe.lt(ratio, -1./2.), -6*ratio**3 - 14*ratio**2 - 9*ratio - 2, \ fe.conditional(fe.gt(ratio, 1./2.), -6*ratio**3 + 14*ratio**2 - 9*ratio + 2, 1./2.* ratio)) else: raise NotImplementedError("To be implemented")
def distance_function_segments_ufl(P, control_points, impact_radii): if len(control_points) == 1: return distance_function_point_ufl(P, control_points[0]), impact_radii[0] else: rho1 = impact_radii[0] rho2 = impact_radii[1] df, xi = distance_function_line_segement_ufl(P, control_points[0], control_points[1]) for i in range(len(control_points) - 1): tmp_df, tmp_xi = distance_function_line_segement_ufl( P, control_points[i], control_points[i + 1]) xi = fe.conditional(fe.lt(tmp_df, df), tmp_xi, xi) rho1 = fe.conditional(fe.lt(tmp_df, df), impact_radii[i], rho1) rho2 = fe.conditional(fe.lt(tmp_df, df), impact_radii[i + 1], rho2) df = ufl.Min(tmp_df, df) return df, (1 - xi) * rho1 + xi * rho2
def inverse_map_function_ufl(x, control_points, impact_radii, map_type): if len(control_points) == 0: return x x = fe.variable(x) df, rho = distance_function_segments_ufl(x, control_points, impact_radii) grad_x = fe.diff(df, x) delta_x = fe.conditional( fe.gt(df, rho), fe.Constant((0., 0.)), grad_x * (rho * inverse_ratio_function_ufl(df / rho, map_type) - df)) return delta_x + x
def compute_analytical_solutions_fully_broken(self, x): x1 = x[0] x2 = x[1] u1 = fe.Constant(0.) u2 = fe.conditional(fe.gt(x2, self.height / 2.), self.fix_load, fe.Constant(0.)) u_exact = fe.as_vector([u1, u2]) distance_field, _ = distance_function_segments_ufl( x, self.control_points, self.impact_radii) d_exact = fe.exp(-distance_field / (self.l0)) return u_exact, d_exact
def distance_function_line_segement_ufl(P, A=[-1, 0], B=[1, 0]): AB = [None, None] AB[0] = B[0] - A[0] AB[1] = B[1] - A[1] BP = [None, None] BP[0] = P[0] - B[0] BP[1] = P[1] - B[1] AP = [None, None] AP[0] = P[0] - A[0] AP[1] = P[1] - A[1] AB_BP = AB[0] * BP[0] + AB[1] * BP[1] AB_AP = AB[0] * AP[0] + AB[1] * AP[1] y = P[1] - B[1] x = P[0] - B[0] df1 = fe.sqrt(x**2 + y**2) xi1 = 1 y = P[1] - A[1] x = P[0] - A[0] df2 = fe.sqrt(x**2 + y**2) xi2 = 0 x1 = AB[0] y1 = AB[1] x2 = AP[0] y2 = AP[1] mod = fe.sqrt(x1**2 + y1**2) df3 = np.absolute(x1 * y2 - y1 * x2) / mod xi3 = fe.conditional(fe.gt(x2**2 + y2**2 - df3**2, 0), fe.sqrt(x2**2 + y2**2 - df3**2) / mod, 0) df = fe.conditional(fe.gt(AB_BP, 0), df1, fe.conditional(fe.lt(AB_AP, 0), df2, df3)) xi = fe.conditional(fe.gt(AB_BP, 0), xi1, fe.conditional(fe.lt(AB_AP, 0), xi2, xi3)) return df, xi
def update_map(self): d_clipped = fe.conditional(fe.gt(self.d_new, 0.5), self.d_new, 0.) d_int_full = fe.assemble(self.d_new * fe.det(self.grad_gamma) * fe.dx) d_int = fe.assemble(d_clipped * fe.det(self.grad_gamma) * fe.dx) print("d_int_clipped {}".format(float(d_int))) print("d_int_full {}".format(float(d_int_full))) update_flag = False if d_int - self.d_integrals[-1] > self.d_integral_interval: update_flag = True if update_flag and not self.finish_flag: print('\n') print( '=================================================================================' ) print('>> Updating map...') print( '=================================================================================' ) new_tip_point = self.identify_crack_tip() if self.inside_domain(new_tip_point): if len(self.control_points) > 1: v1 = self.control_points[-1] - self.control_points[-2] v2 = new_tip_point - self.control_points[-1] v1 = v1 / np.linalg.norm(v1) v2 = v2 / np.linalg.norm(v2) print("new_tip_point is {}".format(new_tip_point)) print("v1 is {}".format(v1)) print("v2 is {}".format(v2)) print("control points are \n{}".format( self.control_points)) print("impact_radii are {}".format(self.impact_radii)) assert np.dot( v1, v2 ) > np.sqrt(2) / 2, "Crack propogration angle not good" self.compute_impact_radii(new_tip_point) self.interpolate_H() self.d_integrals.append(d_int) print( '=================================================================================' ) else: self.finish_flag = True self.update_weak_form = True else: print("Do not modify map") print("d_integrals {}".format(self.d_integrals))
def obj(x): p = fe.Constant(x) x_coo = fe.SpatialCoordinate(self.mesh) control_points = list(self.control_points) control_points.append(p) pseudo_radii = np.zeros(len(control_points)) distance_field, _ = distance_function_segments_ufl( x_coo, control_points, pseudo_radii) d_artificial = fe.exp(-distance_field / self.l0) d_clipped = fe.conditional(fe.gt(self.d_new, 0.5), self.d_new, 0.) L_tape = fe.assemble((d_clipped - d_artificial)**2 * fe.det(self.grad_gamma) * fe.dx) # L_tape = fe.assemble((self.d_new - d_artificial)**2 * fe.det(self.grad_gamma) * fe.dx) L = float(L_tape) return L
def map_function_ufl(x_hat, control_points, impact_radii, map_type, boundary_info=None): if len(control_points) == 0: return x_hat x_hat = fe.variable(x_hat) df, rho = distance_function_segments_ufl(x_hat, control_points, impact_radii) grad_x_hat = fe.diff(df, x_hat) delta_x_hat = fe.conditional( fe.gt(df, rho), fe.Constant((0., 0.)), grad_x_hat * (rho * ratio_function_ufl(df / rho, map_type) - df)) if boundary_info is None: return delta_x_hat + x_hat else: last_control_point = control_points[-1] points, directions, rho_default = boundary_info mid_point, mid_point1, mid_point2 = points direct_vec, rotated_vec = directions aux_control_point1 = last_control_point + rho_default * rotated_vec aux_control_point2 = last_control_point - rho_default * rotated_vec w1 = np.linalg.norm(mid_point1 - aux_control_point1) w2 = np.linalg.norm(mid_point2 - aux_control_point2) w0 = np.linalg.norm(mid_point - last_control_point) assert np.absolute(2 * w0 - w1 - w2) < 1e-5 AB = mid_point - last_control_point AP = x_hat - last_control_point x1 = AB[0] y1 = AB[1] x2 = AP[0] y2 = AP[1] mod = fe.sqrt(x1**2 + y1**2) df_to_direct = (x1 * y2 - y1 * x2) / mod # AB x AP df_to_rotated = (x1 * x2 + y1 * y2) / mod k1 = rho_default * (w1 + w2) / (rho_default * (w1 + w2) + df_to_direct * (w1 - w2)) new_df_to_direct = rho_default * ratio_function_ufl( df_to_direct / rho_default, map_type) k2 = rho_default * (w1 + w2) / (rho_default * (w1 + w2) + new_df_to_direct * (w1 - w2)) new_df_to_rotated = df_to_rotated * k1 / k2 x = fe.as_vector(last_control_point + direct_vec * new_df_to_rotated + rotated_vec * new_df_to_direct) return fe.conditional( fe.gt(df_to_rotated, 0), fe.conditional(fe.gt(np.absolute(df_to_direct), rho), x_hat, x), delta_x_hat + x_hat)
def history(H_old, psi_new, psi_cr): history_max_tmp = fe.conditional(fe.gt(psi_new - psi_cr, 0), psi_new - psi_cr, 0) history_max = fe.conditional(fe.gt(history_max_tmp, H_old), history_max_tmp, H_old) return history_max
def psi_minus_Borden(F, mu, kappa): J = fe.det(F) U, Wbar = psi_aux_Borden(F, mu, kappa) return fe.conditional(fe.lt(J, 1), U, 0)
def d3(grad_u): norm = fe.sqrt(fe.inner(grad_u, grad_u)) return fe.conditional(fe.gt(norm, 1), 1 - 1 / norm, 1 - (2 - norm))