def _compute_damping_forces(self): # Internal damping forces. elemental_velocities = 0.5 * (self.velocity_collection[..., :-1] + self.velocity_collection[..., 1:]) elemental_damping_forces = (self.dissipation_constant_for_forces * elemental_velocities * self.lengths) self.damping_forces = quadrature_kernel(elemental_damping_forces)
def _compute_damping_forces(self): """ This method computes internal damping forces acting on the elements. Returns ------- """ # Internal damping forces. elemental_velocities = 0.5 * ( self.velocity_collection[..., :-1] + self.velocity_collection[..., 1:] ) elemental_damping_forces = self.nu * elemental_velocities * self.lengths nodal_damping_forces = quadrature_kernel(elemental_damping_forces) return nodal_damping_forces
def _compute_internal_torques(self): # Compute \tau_l and cache it using internal_couple # Be careful about usage though self._compute_internal_bending_twist_stresses_from_model() # Compute dilatation rate when needed, dilatation itself is done before # in internal_stresses self._compute_dilatation_rate() # FIXME: change memory overload instead for the below calls! voronoi_dilatation_inv_cube_cached = 1.0 / self.voronoi_dilatation**3 # Delta(\tau_L / \Epsilon^3) bend_twist_couple_2D = difference_kernel( self.internal_couple * voronoi_dilatation_inv_cube_cached) # \mathcal{A}[ (\kappa x \tau_L ) * \hat{D} / \Epsilon^3 ] bend_twist_couple_3D = quadrature_kernel( _batch_cross(self.kappa, self.internal_couple) * self.rest_voronoi_lengths * voronoi_dilatation_inv_cube_cached) # (Qt x n_L) * \hat{l} shear_stretch_couple = (_batch_cross( _batch_matvec(self.director_collection, self.tangents), self.internal_stress, ) * self.rest_lengths) # I apply common sub expression elimination here, as J w / e is used in both the lagrangian and dilatation # terms # TODO : the _batch_matvec kernel needs to depend on the representation of J, and should be coded as such J_omega_upon_e = (_batch_matvec(self.mass_second_moment_of_inertia, self.omega_collection) / self.dilatation) # (J \omega_L / e) x \omega_L # Warning : Do not do micro-optimization here : you can ignore dividing by dilatation as we later multiply by it # but this causes confusion and violates SRP lagrangian_transport = _batch_cross(J_omega_upon_e, self.omega_collection) # Note : in the computation of dilatation_rate, there is an optimization opportunity as dilatation rate has # a dilatation-like term in the numerator, which we cancel here # (J \omega_L / e^2) . (de/dt) unsteady_dilatation = J_omega_upon_e * self.dilatation_rate / self.dilatation # Compute damping torques self._compute_damping_torques() return (bend_twist_couple_2D + bend_twist_couple_3D + shear_stretch_couple + lagrangian_transport + unsteady_dilatation - self.damping_torques)
def _compute_damping_forces(damping_forces, velocity_collection, dissipation_constant_for_forces, lengths): # Internal damping foces. elemental_velocities = node_to_element_pos_or_vel(velocity_collection) blocksize = elemental_velocities.shape[1] elemental_damping_forces = np.zeros((3, blocksize)) for i in range(3): for k in range(blocksize): elemental_damping_forces[i, k] = (dissipation_constant_for_forces[k] * elemental_velocities[i, k] * lengths[k]) damping_forces[:] = quadrature_kernel(elemental_damping_forces)
def _compute_internal_torques( position_collection, velocity_collection, tangents, lengths, rest_lengths, director_collection, rest_voronoi_lengths, bend_matrix, rest_kappa, kappa, voronoi_dilatation, mass_second_moment_of_inertia, omega_collection, internal_stress, internal_couple, dilatation, dilatation_rate, dissipation_constant_for_torques, damping_torques, internal_torques, ): # Compute \tau_l and cache it using internal_couple # Be careful about usage though _compute_internal_bending_twist_stresses_from_model( director_collection, rest_voronoi_lengths, internal_couple, bend_matrix, kappa, rest_kappa, ) # Compute dilatation rate when needed, dilatation itself is done before # in internal_stresses _compute_dilatation_rate(position_collection, velocity_collection, lengths, rest_lengths, dilatation_rate) # FIXME: change memory overload instead for the below calls! voronoi_dilatation_inv_cube_cached = 1.0 / voronoi_dilatation**3 # Delta(\tau_L / \Epsilon^3) bend_twist_couple_2D = difference_kernel( internal_couple * voronoi_dilatation_inv_cube_cached) # \mathcal{A}[ (\kappa x \tau_L ) * \hat{D} / \Epsilon^3 ] bend_twist_couple_3D = quadrature_kernel( _batch_cross(kappa, internal_couple) * rest_voronoi_lengths * voronoi_dilatation_inv_cube_cached) # (Qt x n_L) * \hat{l} shear_stretch_couple = (_batch_cross( _batch_matvec(director_collection, tangents), internal_stress) * rest_lengths) # I apply common sub expression elimination here, as J w / e is used in both the lagrangian and dilatation # terms # TODO : the _batch_matvec kernel needs to depend on the representation of J, and should be coded as such J_omega_upon_e = ( _batch_matvec(mass_second_moment_of_inertia, omega_collection) / dilatation) # (J \omega_L / e) x \omega_L # Warning : Do not do micro-optimization here : you can ignore dividing by dilatation as we later multiply by it # but this causes confusion and violates SRP lagrangian_transport = _batch_cross(J_omega_upon_e, omega_collection) # Note : in the computation of dilatation_rate, there is an optimization opportunity as dilatation rate has # a dilatation-like term in the numerator, which we cancel here # (J \omega_L / e^2) . (de/dt) unsteady_dilatation = J_omega_upon_e * dilatation_rate / dilatation _compute_damping_torques(damping_torques, omega_collection, dissipation_constant_for_torques, lengths) blocksize = internal_torques.shape[1] for i in range(3): for k in range(blocksize): internal_torques[i, k] = (bend_twist_couple_2D[i, k] + bend_twist_couple_3D[i, k] + shear_stretch_couple[i, k] + lagrangian_transport[i, k] + unsteady_dilatation[i, k] - damping_torques[i, k])