While carbon fibers and Kevlar fibers usually have consistent diameter with just a minor variation, the diameter within single batches of glass fibers varies significantly [1].
This case study presents ideas on how to numerically process and visualize fiber diameter distribution and randomly placed fibers in a unidirectional configuration. The diameters of a representative sample of 600 glass fibers are listed in the text file fiberDiameters.txt.
The simple numpy method for reading the data into a numpy array is:
import numpy as np
fibd=np.loadtxt('data/fiberDiameters.txt')
%matplotlib inline
def plotDistribution(d):
import matplotlib.pyplot as plt
fig,ax = plt.subplots(figsize=(8,6))
n,bins,patches=plt.hist(d, 20, density=True,facecolor='teal', alpha=0.6 )
ax.set_xlabel('Fiber diameter(um)')
ax.set_ylabel('Normalized number of fibers')
ax.set_title('Fiber diameter distribution')
ax.set_xlim(0,)
ax.grid(True)
plt.show()
plotDistribution(fibd)
print('Min:',np.amin(fibd))
print('Max:',np.amax(fibd))
print('Range:',np.ptp(fibd))
print('Mean:',np.mean(fibd))
print('Stdev:',np.std(fibd))
The basic idea of the following code is to simulate a cross section of UD composite with randomly placed fibers with varying diameters according to the previous distribution:
def plotRandomDistributionOfFibers(dx,dy,d,n):
import numpy as np
rx=dx*np.random.rand(n)
ry=dy*np.random.rand(n)
x, y = [], [] #lists of coordinates verified to fit
dm=[]
k=0 # counter: no. of fibers already added
for j in range(0,n): # all randomly generated coordinates
fits=True # initially assuming that the fiber fits
for p in range(0,k): # all previously verified coordinates
distance= ( (rx[j]-x[p])**2 + (ry[j]-y[p])**2 )**0.5 # vector length
if distance<(d[k]+d[p])/2: # does not fit if the distance is less than average diameter of the two
fits=False
if fits==True: # append only the ones that fit
x.append(rx[j])
y.append(ry[j])
dm.append(d[k])
k=k+1
print('Number of fibers:',k)
import matplotlib.pyplot as plt
fig,ax=plt.subplots(figsize=(10,10))
ax.set_xlim(0,dx)
ax.set_ylim(0,dy)
ax.set_axis_off()
for i in range(0,len(x)):
circle1 = plt.Circle( (x[i], y[i]), dm[i]/2, color='black',fc='silver')
ax.add_artist(circle1)
plotRandomDistributionOfFibers(dx=200,dy=200,d=fibd,n=20000)
Although the sample of fibers is the same, another random sample of positions will produce a different result, and likely a different number of fibers in the cross section:
plotRandomDistributionOfFibers(dx=200,dy=200,d=fibd,n=20000)
The same code for a sample of fibers having identical diameters:
d12=[12.025 for i in range(0,300)]
plotRandomDistributionOfFibers(dx=200,dy=200,d=d12,n=20000)
The function scipy.stats.norm()
creates a normal distribution based on the mean and the standard deviation which can be added to the plot:
def plotDistributionB(d):
import matplotlib.pyplot as plt
from scipy.stats import norm
x=np.linspace(min(d),max(d))
y=norm.pdf(x,np.mean(d),np.std(d))
fig,ax = plt.subplots(figsize=(8,6))
n,bins,patches=plt.hist(d, 20, density=True,facecolor='teal', alpha=0.6 )
ax.plot(x,y,color='black')
ax.set_xlabel('Fiber diameter(um)')
ax.set_ylabel('Normalized number of fibers')
ax.set_title('Fiber diameter distribution')
ax.set_xlim(0,)
ax.grid(True)
plt.show()
plotDistributionB(fibd)
Finally, creating a fictive distribution is simple. For example, natural fibers show typically diameters within a large range as in the following example:
def plotFakeDistribution(mean,std,n):
import matplotlib.pyplot as plt
from scipy.stats import norm
dis = np.random.normal(mean, std, n)
fig,ax = plt.subplots(figsize=(8,6))
n,bins,patches=plt.hist(dis, 15, density=True,facecolor='orange', alpha=0.6 )
x=np.linspace(min(dis),max(dis))
y=norm.pdf(x,mean,std)
ax.plot(x,y,color='black')
ax.set_xlabel('Fiber diameter(um)')
ax.set_ylabel('Normalized number of fibers')
ax.set_title('Fiber diameter distribution')
ax.set_xlim(0,)
ax.grid(True)
plt.show()
plotFakeDistribution(40,10,500)