I have the working function below. I have a function from which I calculate the first and second derivative. I then need to find the value of theta where the first derivative is zero and second one is negative. I have to compute this for a large number of points. The number of points is equal to the length of K1 and K2. Using sympy I calculate the first and second derivative. I currently iterate over all the derivatives and solve the equations for each. Is there a faster way to do this, once the lengths of K1 and K2 increase > 1000 , this takes much to long for my application.
import numpy as np
import sympy as sp
from scipy.optimize import fsolve
from sympy.utilities.lambdify import lambdify
def get_cpd(K1, K2):
'''
*args:
K1, 1D numpy array: mode I stress intensity factors
K2, 1D numpy array: mode II stress intensity factor
*Note:
K1 and K2 should have the same length
'''
# Define symbols
r, theta = sp.symbols("r theta")
# Shear stress intensity
sif_shear = 1/2*sp.cos(theta/2)*(K1*sp.sin(theta)+K2*(3*sp.cos(theta)-1))
# Determine the first and second derivative w.r.t. theta
first_derivative = sp.diff(sif_shear, theta)
second_derivative = sp.diff(first_derivative, theta)
cpd_lst = []
for first, second in zip(first_derivative, second_derivative):
# Lambdify function such that it can evaluate an array of points
func1 = sp.lambdify(theta, first, "numpy")
func2 = sp.lambdify(theta, second, "numpy")
# initialize array from -π/2 to π/2, this is used for the initial guesses of the solver
x = np.linspace(-np.pi/2, np.pi/2, num=50)
# Solve the first derivative for all initial guesses to find possible propagation angles
y1 = fsolve(func1, x)
# Evaluate the second derivative in the roots of the first derivative
y2 = func2(y1)
# Get roots of first derivative between -π/2 to π/2
# and where second derivative is negative
y1 = np.round(y1, 4)
y1 = y1[(y1 > -np.pi/2) & (y1 < np.pi/2) & (y2 < 0)]
# get unique roots
cpd = np.unique(y1)
cpd_lst.append(cpd)
return cpd_lst
Input example:
K1 = np.random.rand(10000,)
K2 = np.random.rand(10000,)
get_cpd(K1, K2)