def kinetic_local(omega_par, disp_vector, passive_el, ind_passive, coord, connect, E, v, rho, const_func): """ Calculates the local kinetic energy function. Args: omega_par (:obj:`float`): 2 * pi * frequency. disp_vector (:obj:`numpy.array`): Displacement. passive_el (:obj:`numpy.array`, optional): Passive element nodes. ind_passive (:obj:`numpy.array`, optional): Index of passive elements. coord (:obj:`numpy.array`, optional): Coordinates of the element. connect (:obj:`numpy.array`, optional): Element connectivity. E (:obj:`float`, optional): Elastic modulus. v (:obj:`float`, optional): Poisson's ratio. rho (:obj:`float`, optional): Density. Returns: Local kinetic energy on the logarithmic scale and the non-logarithmic local kinetic energy. """ ki = 0 for i, ind_el in enumerate(ind_passive): _, Me = fc.matricesQ4(passive_el[i], coord, connect, E, v, rho) aux = disp_vector[ind_el].conj().reshape(1, -1)@Me@disp_vector[ind_el] ki+=aux fvirg = ((omega_par**2)/4) * ki[0].real #Log Scale f = const_func + 10 * np.log10(fvirg) return f, fvirg
def elastic_potential_local(disp_vector, passive_el, ind_passive, coord, connect, E, v, rho, const_func): """ Calculates the local elastic potential energy function. Args: disp_vector (:obj:`numpy.array`): Displacement. passive_el (:obj:`numpy.array`, optional): Passive element nodes. ind_passive (:obj:`numpy.array`, optional): Index of passive elements. coord (:obj:`numpy.array`, optional): Coordinates of the element. connect (:obj:`numpy.array`, optional): Element connectivity. E (:obj:`float`, optional): Elastic modulus. v (:obj:`float`, optional): Poisson's ratio. rho (:obj:`float`, optional): Density. Returns: Local elastic potential energy on the logarithmic scale and the non-logarithmic local elastic potential energy. """ ep2 = 0 for i, ind_el in enumerate(ind_passive): Ke, _ = fc.matricesQ4(passive_el[i], coord, connect, E, v, rho) aux = disp_vector[ind_el].reshape(1, -1).conjugate()@Ke@disp_vector[ind_el] ep2+=aux fvirg = (1/4) * ep2[0].real #Log Scale f = const_func + 10 * np.log10(fvirg) return f, fvirg
def lambda_local_ep(ngl, ind_passive, passive_el, disp_vector, dyna_stif, coord, connect, E, v, rho): """ Calculates the lambda parameter of the local elastic potential energy function. Args: ngl (:obj:`int`): Degrees of freedom. ind_passive (:obj:`numpy.array`): Index of passive elements. passive_el (:obj:`numpy.array`): Passive element nodes. disp_vector (:obj:`numpy.array`): Displacement vector. dyna_stif (:obj:`numpy.array`): Dynamic stiffness matrix. omega_par (:obj:`float`): 2 * pi * frequency. coord (:obj:`numpy.array`): Coordinates of the element. connect (:obj:`numpy.array`): Element connectivity. E (:obj:`float`): Elastic modulus. v (:obj:`float`): Poisson's ratio. rho (:obj:`float`): Density. Returns: Lambda parameter solution. """ aux1 = np.zeros(ngl, dtype=complex) fadj = 0 for i, el in enumerate(passive_el): Ke, _ = fc.matricesQ4(el, coord, connect, E, v, rho) aux1[ind_passive[i]] = Ke @ disp_vector[ind_passive[i]].conjugate() fadj += aux1 aux1[:] = 0 fadj *= -1 / 2 lam = spsolve(dyna_stif, fadj) return lam
def derivative_local_ep(passive_el, lam, ind_dofs, xval, disp_vector, connect, coord, E, v, rho, x_min_k, x_min_m, omega_par, alpha, beta, p_par, q_par): """ Calculates the derivative of the local elastic potential energy function. Args: passive_el (:obj:`numpy.array`): Passive element nodes. lam (:obj:`float`): Lambda parameter. ind_dofs (:obj:`numpy.array`, optional): TODO xval (:obj:`numpy.array`): Indicates where there is mass. disp_vector (:obj:`numpy.array`): Displacement vector. connect (:obj:`numpy.array`): Element connectivity. coord (:obj:`numpy.array`): Coordinates of the element. E (:obj:`float`): Elastic modulus. v (:obj:`float`): Poisson's ratio. rho (:obj:`float`): Density. x_min_m (:obj:`float`): Minimum relative densities to mass. x_min_k (:obj:`float`): Minimum relative densities to stiffness. omega_par (:obj:`float`): 2 * pi * frequency. alpha (:obj:`float`): Damping coefficient proportional to mass. beta (:obj:`float`): Damping coefficient proportional to stiffness. p_par (:obj:`int`): Penalization power to stiffness. q_par (:obj:`int`): Penalization power to mass. Returns: Derivative of the local elastic potential energy function. """ deriv_f = np.empty((len(connect), 1), dtype=complex) for el in range(len(connect)): Ke, Me = fc.matricesQ4(el, coord, connect, E, v, rho) ind = ind_dofs[el, :] dKe = p_par * (xval[el]**(p_par - 1)) * (1 - x_min_k) * Ke dCe = alpha * Me + beta * dKe if xval[el] > 0.1: dMe = q_par * (xval[el]**(q_par - 1)) * (1 - x_min_m) * Me else: dMe = ((9 * 3.512e7 * xval[el]**8 - 10 * 2.081e8 * xval[el]**9) * (1 - x_min_m)) * Me dKed = dKe + omega_par * 1j * dCe - (omega_par**2) * dMe if el in passive_el: deriv_f[el, 0] = (1 / 4) * ( (disp_vector[ind].reshape(1, -1).conjugate() @ dKe @ disp_vector[ind]) + (lam[ind].reshape(1, -1) @ dKed @ disp_vector[ind]).real)[0] else: deriv_f[el, 0] = (( lam[ind].reshape(1, -1) @ dKed @ disp_vector[ind]).real)[0] return deriv_f
def derivative_R(coord, connect, E, v, rho, alpha, beta, omega_par, p_par, q_par, x_min_m, x_min_k, xval, disp_vector, lam, fvirg, kinetic_e): """ Calculates the derivative of the strain-to-kinetic function. Args: coord (:obj:`numpy.array`): Coordinates of the element. connect (:obj:`numpy.array`): Element connectivity. E (:obj:`float`): Elastic modulus. v (:obj:`float`): Poisson's ratio. rho (:obj:`float`): Density. alpha (:obj:`float`): Damping coefficient proportional to mass. beta (:obj:`float`): Damping coefficient proportional to stiffness. omega_par (:obj:`float`): 2 * pi * frequency p_par (:obj:`float`): Penalization power to stiffness. q_par (:obj:`float`): Penalization power to mass. x_min_m (:obj:`float`): Minimum relative densities to mass. x_min_k (:obj:`float`): Minimum relative densities to stiffness. xval (:obj:`numpy.array`): Indicates where there is mass. disp_vector (:obj:`numpy.array`): Displacement vector. lam (:obj:`float`): Lambda parameter. fvirg (:obj:`float`): Strain-to-kinetic function. kinetic_e (:obj:`float`): Kinetic energy function. Returns: Derivative of the strain-to-kinetic function function. """ deriv_R = np.empty((len(connect), 1), dtype=complex) dofs = 2 ind_dofs = (np.array([ dofs * connect[:, 1] - 1, dofs * connect[:, 1], dofs * connect[:, 2] - 1, dofs * connect[:, 2], dofs * connect[:, 3] - 1, dofs * connect[:, 3], dofs * connect[:, 4] - 1, dofs * connect[:, 4] ], dtype=int) - 1).T for el in range(len(connect)): Ke, Me = fc.matricesQ4(el, coord, connect, E, v, rho) ind = ind_dofs[el, :] dKe = p_par * (xval[el]**(p_par - 1)) * (1 - x_min_k) * Ke dCe = alpha * Me + beta * dKe if xval[el] > 0.1: dMe = q_par * (xval[el]**(q_par - 1)) * (1 - x_min_m) * Me else: dMe = ((9 * 3.512e7 * xval[el]**8 - 10 * 2.081e8 * xval[el]**9) * (1 - x_min_m)) * Me dKed = dKe + omega_par * 1j * dCe - (omega_par**2) * dMe deriv_R[el, 0] = 1/(4*kinetic_e) * (disp_vector[ind].conjugate()@(dKe - (omega_par**2)*fvirg*dMe)@disp_vector[ind]).real + \ (lam[ind]@dKed@disp_vector[ind]).real return deriv_R
def derivative_input_power(coord, connect, E, v, rho, alpha, beta, omega_par, p_par, q_par, x_min_m, x_min_k, xval, disp_vector): """ Calculates the derivative of the input power function. Args: coord (:obj:`numpy.array`): Coordinates of the element. connect (:obj:`numpy.array`): Element connectivity. E (:obj:`float`): Elastic modulus. v (:obj:`float`): Poisson's ratio. rho (:obj:`float`): Density. alpha (:obj:`float`): Damping coefficient proportional to mass. beta (:obj:`float`): Damping coefficient proportional to stiffness. omega_par (:obj:`float`): 2 * pi * frequency p_par (:obj:`float`): Penalization power to stiffness. q_par (:obj:`float`): Penalization power to mass. x_min_m (:obj:`float`): Minimum relative densities to mass. x_min_k (:obj:`float`): Minimum relative densities to stiffness. xval (:obj:`numpy.array`): Indicates where there is mass. disp_vector (:obj:`numpy.array`): Displacement vector. Returns: Derivative of the input power function. """ deriv_f = np.empty((len(connect), 1)) dofs = 2 ind_dofs = (np.array([ dofs * connect[:, 1] - 1, dofs * connect[:, 1], dofs * connect[:, 2] - 1, dofs * connect[:, 2], dofs * connect[:, 3] - 1, dofs * connect[:, 3], dofs * connect[:, 4] - 1, dofs * connect[:, 4] ], dtype=int) - 1).T for el in range(len(connect)): Ke, Me = fc.matricesQ4(el, coord, connect, E, v, rho) ind = ind_dofs[el, :] dKe = p_par * (xval[el]**(p_par - 1)) * (1 - x_min_k) * Ke dCe = alpha * Me + beta * dKe if xval[el] > 0.1: dMe = q_par * (xval[el]**(q_par - 1)) * (1 - x_min_m) * Me else: dMe = ((9 * 3.512e7 * xval[el]**8 - 10 * 2.081e8 * xval[el]**9) * (1 - x_min_m)) * Me dKed = dKe + omega_par * 1j * dCe - (omega_par**2) * dMe a = 1j * (disp_vector[ind].reshape(1, 8) @ dKed @ disp_vector[ind].reshape(8, 1))[0, 0] deriv_f[el, 0] = -0.5 * omega_par * a.real return deriv_f