Rossler Attractor

Rossler Attractor

The Chaotic Attractor Project

This was assembled as a project for my computer science and physics courses sophomore year of undergraduate. I was studying chaos theory and decided for a final project I would incorporate this into my vfx background. So I developed my own Python script using the SDK available in Cinema 4D.

The result was a versatile piece of concise programming that could generate from a list several different chaotic attractors. I will include the source code below.

import c4d, math, datetime
from c4d import gui
from datetime import datetime
#Welcome to EquSim
def f(xvec):
a, b = (-8/7), (-5/7) #Chua's Circuit function constants
if xvec >= 1:
return b*xvec + a - b
elif -1 <= xvec <= 1:
return a*xvec
elif xvec <= -1:
return b*xvec - a + b
def main():
t = str(datetime.now()) #Gets the current local time
print("Trial: ", t) #prints to console the current local time
fps = doc.GetFps() #Gets the frames per second setting
startframe = doc.GetMinTime().GetFrame(fps) #set min time
endframe = doc.GetMaxTime().GetFrame(fps) #set max time
doc.SetTime(c4d.BaseTime(startframe, fps)) #sets time slider to frame 0
obj = c4d.BaseObject(5160) #assigns sphere base object to variable obj
obj[c4d.PRIM_SPHERE_RAD] = .25 #sets radius of sphere
doc.InsertObject(obj) #inserts object into doc
obj.SetBit(c4d.BIT_ACTIVE) #selects obj
xvec = 0.1 #init x vector
yvec = 0.1 #init y vector
zvec = 0.1 #init z vector
rate = 5 #init how many time steps per frame
L_a, L_b, L_c = 10, 28, (8/3) #init Lorenz constants
R_a, R_b, R_c = 0.2, 0.2, 7 #init Rossler constants
u = 5 #init Van der Pol constant
T_a, T_b, T_c, T_d = 0.9, 0.6013, 2, 0.5 #init Tinkerbell constants
alpha, gamma = 0.14, 0.1 #init Rabinovich-Fabrikant constants
C_alpha, C_beta = 9, (100/7) #Chua's Circuit constants
I_u = 0.918 #Ikeda constant
eq_list = ['lorenz', 'rossler', 'vanderpol', 'tinkerbell', 'rabinovichfabrikant',
'chua', 'ikeda']
eq_choice = eq_list[0] #change this option to change which equation the script is simulating
print(eq_choice) #posts this to the console for the user to check
#the main meat of the code is in this subsequent ‘for’ loop
for i in range(endframe + 1):
obj[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = xvec
obj[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = yvec
obj[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Z] = zvec
c4d.CallCommand(12410) #rec keyframe
if eq_choice == eq_list[0]:
for r in range(rate): #Lorenz Attractor
N_xvec = xvec + (L_a*(yvec - xvec))*.01 #previous x + dx/dt
N_yvec = yvec + (L_b*xvec - yvec - xvec*zvec)*.01 #previous y + dy/dt
N_zvec = zvec + (xvec*yvec - (L_c)*zvec)*.01 #previous z + dz/dt
xvec, yvec, zvec = N_xvec, N_yvec, N_zvec
elif eq_choice == eq_list[1]: #Rossler Attractor
for r in range(rate):
N_xvec = xvec + (-yvec - zvec)*.01 #dx/dt
N_yvec = yvec + (xvec + R_a*yvec)*.01 #dy/dt
N_zvec = zvec + (R_b + zvec*(xvec - R_c))*.01 #dz/dt
xvec, yvec, zvec = N_xvec, N_yvec, N_zvec
elif eq_choice == eq_list[2]: #Van der Pol Oscillator
for r in range(rate):
N_xvec = xvec + yvec*.01
N_yvec = yvec + (u*(1-(xvec*xvec))*yvec - xvec)*.01
xvec, yvec = N_xvec, N_yvec
elif eq_choice == eq_list[3]: #Tinkerbell Map (not fully working)
for r in range(rate):
N_xvec = xvec + ((xvec*xvec) - (yvec*yvec) + T_a*(xvec) + T_b*(yvec))*.01
N_yvec = yvec + (2*xvec*yvec + T_c*xvec + T_d*yvec)*.01
xvec, yvec = N_xvec, N_yvec
elif eq_choice == eq_list[4]: #Rabinovich-Fabrikant equations
for r in range(rate):
N_xvec = xvec + (yvec*(zvec - 1 + (xvec*xvec)) + gamma*xvec)*.01
N_yvec = yvec + (xvec*(3*zvec + 1 - (xvec*xvec)) + gamma*yvec)*.01
N_zvec = zvec + (-2*zvec*(alpha + xvec*yvec))*.01
xvec, yvec, zvec = N_xvec, N_yvec, N_zvec
elif eq_choice == eq_list[5]: #Chua's Circuit (not fully working)
for r in range(rate):
N_xvec = xvec + (C_alpha*(yvec - xvec - f(xvec)))*.01
N_yvec = yvec + (xvec - yvec + zvec)*.01
N_zvec = zvec + (-1*C_beta*yvec)*.01
xvec, yvec, zvec = N_xvec, N_yvec, N_zvec
elif eq_choice == eq_list[6]: #Ikeda map (not fully working)
for r in range(rate):
I_t = 0.4 - (6/(1+(xvec*xvec)+(yvec*yvec)))
N_xvec = xvec + (1 + I_u*(xvec*math.cos(I_t) - yvec*math.sin(I_t)))*.01
N_yvec = yvec + (I_u*(xvec*math.sin(I_t) + yvec*math.cos(I_t)))*.01
xvec, yvec = N_xvec, N_yvec
print(xvec, yvec, zvec)
doc.SetTime(c4d.BaseTime(i + 1, fps)) #move forward 1 frame
doc.SetTime(c4d.BaseTime(startframe, fps))
null = c4d.BaseObject(5140) #creates null
doc.InsertObject(null)
null.InsertUnder(obj) #makes the obj the null's parent
tracer = c4d.BaseObject(1018655) #creates tracer
tracer[c4d.SPLINEOBJECT_TYPE] = 4
tracer[c4d.SPLINEOBJECT_INTERPOLATION] = 4
doc.InsertObject(tracer)
t_link = tracer[c4d.MGTRACEROBJECT_OBJECTLIST] #creates list variable from tracer link
t_link.InsertObject(null, 0) #adds null to t_link
tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = t_link #update tracer attribute with new list
circle = c4d.BaseObject(5181)
doc.InsertObject(circle)
t_width = .05 #init width of tracer
circle[c4d.PRIM_CIRCLE_RADIUS] = t_width
circle[c4d.PRIM_PLANE] = 0
sweep = c4d.BaseObject(5118)
doc.InsertObject(sweep)
tracer.InsertUnder(sweep)
circle.InsertUnder(sweep)
c4d.EventAdd() #updates C4D’s viewport and windows to represent completion
if __name__==‘__main__': #this runs the main() function once the script is executed
main()