Vedo 3D-Gyroid structures STL export - python

I need to generate a double 3D gyroid structure. For this, I'm using vedo
from matplotlib import pyplot as plt
from scipy.constants import speed_of_light
from vedo import *
import numpy as np
# Paramters
a = 5
length = 100
width = 100
height = 10
pi = np.pi
x, y, z = np.mgrid[:length, :width, :height]
def gen_strut(start, stop):
'''Generate the strut parameter t for the gyroid surface. Create a linear gradient'''
strut_param = np.ones((length, 1))
strut_param = strut_param * np.linspace(start, stop, width)
t = np.repeat(strut_param[:, :, np.newaxis], height, axis=2)
return t
plt = Plotter(shape=(1, 1), interactive=False, axes=3)
scale=0.5
cox = cos(scale * pi * x / a)
siy = sin(scale * pi * y / a)
coy = cos(scale * pi * y / a)
siz = sin(scale * pi * z / a)
coz = cos(scale * pi * z / a)
six = sin(scale * pi * x / a)
U1 = ((six ** 2) * (coy ** 2) +
(siy ** 2) * (coz ** 2) +
(siz ** 2) * (cox ** 2) +
(2 * six * coy * siy * coz) +
(2 * six * coy * siz * cox) +
(2 * cox * siy * siz * coz)) - (gen_strut(0, 1.3) ** 2)
threshold = 0
iso1 = Volume(U1).isosurface(threshold).c('silver').alpha(1)
cube = TessellatedBox(n=(int(length-1), int(width-1), int(height-1)), spacing=(1, 1, 1))
iso_cut = cube.cutWithMesh(iso1).c('silver').alpha(1)
# Combine the two meshes into a single mesh
plt.at(0).show([cube, iso1], "Double Gyroid 1", resetcam=False)
plt.interactive().close()
The result looks quite good, but now I'm struggling with exporting the volume. Although vedo has over 300 examples, I did not find anything in the documentation to export this as a watertight volume for 3D-Printing. How can I achieve this?

I assume you mean that you want to extract a watertight mesh as an STL (?).
This is a non trivial problem because it is only well defined on a subset of the mesh regions where the in/out is not ambiguous, in those cases fill_holes() seems to do a decent job..
Other cases should be dealt "manually". Eg, you can access the boundaries with mesh.boundaries() and try to snap the vertices to a closest common vertex. This script is not a solution, but I hope can give some ideas on how to proceed.
from vedo import *
# Paramters
a = 5
length = 100
width = 100
height = 10
def gen_strut(start, stop):
strut_param = np.ones((length, 1))
strut_param = strut_param * np.linspace(start, stop, width)
t = np.repeat(strut_param[:, :, np.newaxis], height, axis=2)
return t
scale=0.5
pi = np.pi
x, y, z = np.mgrid[:length, :width, :height]
cox = cos(scale * pi * x / a)
siy = sin(scale * pi * y / a)
coy = cos(scale * pi * y / a)
siz = sin(scale * pi * z / a)
coz = cos(scale * pi * z / a)
six = sin(scale * pi * x / a)
U1 = ((six ** 2) * (coy ** 2) +
(siy ** 2) * (coz ** 2) +
(siz ** 2) * (cox ** 2) +
(2 * six * coy * siy * coz) +
(2 * six * coy * siz * cox) +
(2 * cox * siy * siz * coz)) - (gen_strut(0, 1.3) ** 2)
iso = Volume(U1).isosurface(0).c('silver').backcolor("p5").lw(1).flat()
cube = TessellatedBox(n=(length-1, width-1, height-1)).c('red5').alpha(1)
cube.triangulate().compute_normals()
cube.cut_with_mesh(iso).compute_normals()
print(iso.boundaries(return_point_ids=True))
print(cube.boundaries(return_point_ids=True))
print(iso.boundaries().join().lines())
show(iso, cube).close()
merge(iso, cube).clean().backcolor("p5").show().close()
iso.clone().fill_holes(15).backcolor("p5").show().close()

Related

Numpy refuses to display vectorized function

I've got a code that runs as follows:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import pyXSteam.XSteam
from pyXSteam.XSteam import XSteam
steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) # m/kg/sec/°C/bar/W
A = 3000 #define the heat exchange area
d_in = 20 #define the inner diameter of HE tubes
CF = 0.85 #define the cleanliness factor of SC.
w = 2.26 #define the water velocity within the tubes
Dk=np.arange(27.418,301.598,27.418) #define the range of steam loads
dk = (Dk * 1000 / (A * 3.600)) #calculate the relative steam load
Tcwin=20
def Cp():
return steamTable.CpL_t(Tcwin)
Gw = 13000 #define the flow of CW, t/hr
e = 2.718281828
f_velocity = w * 1.1 / (20 ** 0.25)
f_w=0.12 * CF * (1 + 0.15 * Tcwin)
Ф_в = f_velocity ** f_w
K = CF * 4070 * ((1.1 * w / (d_in ** 0.25)) ** (0.12 * CF * (1 + 0.15 * Tcwin))) * (1 - (((35 - Tcwin) ** 2) * (0.52 - 0.0072 * dk) * (CF ** 0.5)) / 1000)
n = (K * A) / (Cp() * Gw * 1000)
Tcwout_theor = Tcwin + (Dk * 2225 / (Cp() * Gw))
Subcooling_theor = (Tcwout_theor - Tcwin) / (e ** (K * A / (Cp() * (Gw * 1000 / 3600) * 1000)))
TR_theor = (Tcwout_theor - Tcwin)
Tsat_theor = (Tcwout_theor + Subcooling_theor)
def Ts():
return np.vectorize(Tsat_theor)
def Psat_theor():
return steamTable.psat_t(Tsat_theor)
print(Dk)
print(Tsat_theor)
print(Psat_theor)
While it does calculate Tsat_theor, it fails to print Psat_theor.
The output goes like this:
<function Psat_theor at 0x000002A7C29F0D30>
How can I obtain the actual value of Psat_theor?
You need to call mentioned function, change
print(Psat_theor)
to
print(Psat_theor())

Why does this function run slower with CUDA vs parallel?

Ive create a bilateral filter in python and added numba to(in theory) run it on the my GPU. Yet when I set the mode to CUDA its extremely slow and doesn't seem to use my graphics card at all while putting it into parallel makes it very fast. The best reason I have is that my function just isn't optimized to run on my GPU very well because it can't apply one function to all elements at once(because it requires the x and y coordinate to work). So my question is, why does this run slow with target set to CUDA?
#guvectorize([(float64[:,:], float64[:,:])],'(n,m)->(n,m)',target='cuda',nopython =True)
def apply_filter(img, filteredImage):
imh, imw = img.shape[:2]
radius = diameter // 2
hd = int((diameter - 1) / 2)
#print("starting work in cuda")
for h in prange(hd, imh - hd):
for w in prange(hd, imw - hd):
Wp = 0
filteredPixel = 0
startX = h
startY = w
for x in prange(0, diameter):
for y in prange(0, diameter):
currentX = startX - (radius - x)
cureentY = startY - (radius - y)
intensityDifferent = img[currentX][cureentY] - img[startX][startY]
intensity = (1.0 / (2 * math.pi * (sIntesity ** 2)) * math.exp(- (intensityDifferent ** 2) / (2 * sIntesity ** 2)))
distance = ((currentX-startX)**2 + (cureentY-startY)**2)**(1/2)
smoothing = (1.0 / (2 * math.pi * (sSpace ** 2))) * math.exp(- (distance ** 2) / (2 * sSpace ** 2))
weight = intensity * smoothing;
filteredPixel += img[currentX][cureentY] * weight
Wp += weight
filteredImage[h][w] = int(round(filteredPixel / Wp))
#print("done!")

Using functions to create Electric Field array for 2d Density Plot and 3d Surface Plot

Below is my code, I'm supposed to use the electric field equation and the given variables to create a density plot and surface plot of the equation. I'm getting "invalid dimensions for image data" probably because the function E takes multiple variables and is trying to display them all as multiple dimensions. I know the issue is that I have to turn E into an array so that the density plot can be displayed, but I cannot figure out how to do so. Please help.
import numpy as np
from numpy import array,empty,linspace,exp,cos,sqrt,pi
import matplotlib.pyplot as plt
lam = 500 #Nanometers
x = linspace(-10*lam,10*lam,10)
z = linspace(-20*lam,20*lam,10)
w0 = lam
E0 = 5
def E(E0,w0,x,z,lam):
E = np.zeros((len(x),len(z)))
for i in z:
for j in x:
E = ((E0 * w0) / w(z,w0,zR(w0,lam)))
E = E * exp((-r(x)**2) / (w(z,w0,zR(w0,lam)))**2)
E = E * cos((2 * pi / lam) * (z + (r(x)**2 / (2 * Rz(z,zR,lam)))))
return E
def r(x):
r = sqrt(x**2)
return r
def w(z,w0,lam):
w = w0 * sqrt(1 + (z / zR(w0,lam))**2)
return w
def Rz(z,w0,lam):
Rz = z * (1 + (zR(w0,lam) / z)**2)
return Rz
def zR(w0,lam):
zR = pi * lam
return zR
p = E(E0,w0,x,z,lam)
plt.imshow(p)
It took me way too much time and thinking but I finally figured it out after searching for similar examples of codes for similar problems. The correct code looks like:
import numpy as np
from numpy import array,empty,linspace,exp,cos,sqrt,pi
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
lam = 500*10**-9 #Nanometers
x1 = linspace(-10*lam,10*lam,100)
z1 = linspace(-20*lam,20*lam,100)
[x,y] = np.meshgrid(x1,z1)
w0 = lam
E0 = 5
r = sqrt(x**2)
zR = pi * lam
w = w0 * sqrt(1 + (y / zR)**2)
Rz = y * (1 + (zR / y)**2)
E = (E0 * w0) / w
E = E * exp((-r**2 / w**2))
E = E * cos((2 * pi / lam) * (y + (r**2 / (2 * Rz))))
def field(x,y):
lam = 500*10**-9
k = (5 * lam) / lam * sqrt(1 + (y / (pi*lam))**2)
k *= exp(((-sqrt(x**2)**2 / (lam * sqrt(1 + (y / pi * lam)**2))**2)))
k *= cos((2 / lam) * (y + ((sqrt(x**2)**2 / (2 * y * (1 + (pi * lam / y)**2))))))
return k
#Density Plot
f = field(x,y)
plt.imshow(f)
plt.show()
#Surface Plot
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x,y,E,rstride=1,cstride=1)
plt.show

Plot a ball rolling down a curve

I want to "animate" a circle rolling over the sin graph, I made a code where the circle moves rapidly down a straight line, now I want the same but the acceleration will be changing.
My previous code:
import numpy as np
import matplotlib.pyplot as plt
theta = np.arange(0, np.pi * 2, (0.01 * np.pi))
x = np.arange(-50, 1, 1)
y = x - 7
plt.figure()
for t in np.arange(0, 4, 0.1):
plt.plot(x, y)
xc = ((-9.81 * t**2 * np.sin(np.pi / 2)) / 3) + (5 * np.cos(theta))
yc = ((-9.81 * t**2 * np.sin(np.pi / 2)) / 3) + (5 * np.sin(theta))
plt.plot(xc, yc, 'r')
xp = ((-9.81 * t**2 * np.sin(np.pi / 2)) / 3) + (5 * np.cos(np.pi * t))
yp = ((-9.81 * t**2 * np.sin(np.pi / 2)) / 3) + (5 * np.sin(np.pi * t))
plt.plot(xp, yp, 'bo')
plt.pause(0.01)
plt.cla()
plt.show()
You can do this by numerically integrating:
dt = 0.01
lst_x = []
lst_y = []
t = 0
while t < 10: #for instance
t += dt
a = get_acceleration(function, x)
x += v * dt + 0.5 * a * dt * dt
v += a * dt
y = get_position(fuction, x)
lst_x.append(x)
lst_y.append(y)
This is assuming the ball never leaves your slope! If it does, you'll also have to integrate in y in a similar way as done in x!!
Where your acceleration is going to be equal to g * cos(slope).

How do i use python to plot fouries series graph?

I have no idea about how to plot fourier series graph from equation like this
I try to use matplotlib to plot this but there are so many values. Here are code that I used. Not sure about algorithm.
import numpy as np
import matplotlib.pyplot as plt
x_ = np.linspace(0, 30, 10000)
a0 = 3/5
##an = 1/n * np.pi * (np.sin(0.4 * n * np.pi) + np.sin(0.8 * n * np.pi))
##bn = 1/n * np.pi * (2 - np.cos(0.4 * n * np.pi) - np.cos(0.8 * n * np.pi))
f0 = 5
def a(n):
return 1/n * np.pi * (np.sin(0.4 * n * np.pi) + np.sin(0.8 * n * np.pi))
def b(n):
return 1/n * np.pi * (2 - np.cos(0.4 * n * np.pi) - np.cos(0.8 * n * np.pi))
def s(t, n):
temp = 0
for i in range (1, n + 1):
temp = temp + (a(i) * np.cos(2 * np.pi * i * f0 * t) \
+ b(i) * np.sin(2 * np.pi * n * f0 * t))
temp += a0
return temp
st = []
for i in range (1, 6):
st.append(s(1, 6))
plt.title("Test")
plt.plot(x_, st, color="red")
plt.show()
Tried this then got this error
ValueError: x and y must have same first dimension, but have shapes (10000,) and (5,)
thanks for any help

Categories