# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# +
# Erasmus+ ICCT project (2018-1-SI01-KA203-047081)

# Toggle cell visibility

from IPython.display import HTML
tag = HTML('''<script>
code_show=true; 
function code_toggle() {
    if (code_show){
        $('div.input').hide()
    } else {
        $('div.input').show()
    }
    code_show = !code_show
} 
$( document ).ready(code_toggle);
</script>
Toggle cell visibility <a href="javascript:code_toggle()">here</a>.''')
display(tag)

# Hide the code completely

# from IPython.display import HTML
# tag = HTML('''<style>
# div.input {
#     display:none;
# }
# </style>''')
# display(tag)

# +
continuous_update=False
# %matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint

from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets


# + [markdown] lang="it"
# ## Equazioni differenziali - sistemi lineari e non lineari
#
# Questo notebook copre vari sistemi definiti dalle seguenti equazioni differenziali:
#
# - vibrazioni non lineari: $\ddot{x}+0.25\dot{x}+5\sin{x}=F$,
# - vibrazioni lineari: $\ddot{x}+0.25\dot{x}+5x=F$,
# - sistema non lineare: $\ddot{x}+0.003\dot{x}x=F$,
# - sistema lineare dipendente dal tempo: $\ddot{x}-0.2{x}t^{\frac{1}{4}}=F$,
# - sistema non lineare dipendente dal tempo: $\ddot{x}+0.0001x^2t=F$, <br>
#
# dove $F$ denota l'input (funzione gradino), $t$ il tempo e $x$ la variabile dipendente.
#
# La figura a sinistra mostra le risposte temporali per diverse condizioni iniziali e diversi input. La curva blu spessa rappresenta la risposta temporale in base ai valori impostati tramite i cursori. Le altre curve rappresentano risposte temporali ottenute da multipli di 1) un valore della prima condizione iniziale (spostamento) $x(0)$, 2) un valore della seconda condizione iniziale (velocità) $\dot x(0)$, o 3) dell'input del sistema (a seconda della selezione *Cosa variare*). I multipli sono valori interi compresi tra -5 e +5.
# <br>
#
# *Esempio*:
# <br>
# $\text{input}=0.7$, $x(0)=2.0$ e $\dot x(0)=5.5$, opzione *input* selezionata.
# Output: la curva spessa si basa sui valori impostati sopra. Le altre curve si basano sugli stessi valori $x(0)$ e $\dot x(0)$, ma con le seguenti ampiezze del gradino:
#
# $0.7\begin{pmatrix}-5& -4& -3& -2& -1& 0& 1& 2& 3& 4& 5\end{pmatrix}=\begin{pmatrix}-3.5& -2.8& -2.1& -1.4& -0.7& 0& 0.7& 1.4& 2.1& 2.8& 3.5\end{pmatrix}$.
#
# La figura a destra mostra i valori di tutte le risposte temporali mostrate nella figura a sinistra nell'istante di tempo selezionato. Le etichette di graduazione dell'asse x indicano i valori interi compresi tra -5 e +5. Per un sistema lineare questo grafico è sempre una linea.
#
# ---
#
# ### Come usare questo notebook?
#
# Sposta i cursori per modificare le risposte temporali in funzione dell'ampiezza del gradino selezionato (*input*) o delle condizioni iniziali dei sistemi predefiniti introdotti sopra. È possibile passare da un sistema all'altro premendo il pulsante corrispondente.
#
# #### Legenda:
#
# - *input*: valore dell'ampiezza dell'ingresso (gradino).
# - *delay*: ritardo di inizio integrazione (per sistemi dipendenti dal tempo).
# - *istante di tempo*: istante in cui vengono mostrate le risposte nella figura a destra.
# - $x(0)$: valore della prima condizione iniziale (spostamento).
# - $\dot x(0)$: valore della seconda condizione iniziale (velocità).
# <br>

# +
# diferential equations:

def nonlinear_vibr(y,t, x): # y začetni pogoj, t čas, x krmilni vhod
    '''nonlinear vibration'''
    th, om = y
    b=0.25
    c=5.
    dydt = (om, x - b*om - c*np.sin(th))
    return dydt

def linear_vibr(y,t,x):
    '''linear vibration'''
    th, om = y
    b=0.25
    c=5.
    dydt = (om, x - b*om - c*th)
    return dydt

def nonlinear(y,t,x):
    '''nonlinear d.e.'''
    c, v = y
    dydt = (v, x - 0.003*c*v)
    return dydt

def time_dependent(y,t,x):
    '''time dependent d.e.'''
    c, v = y
    dydt = (v, x + .2*c*t**(1/4))
    return dydt

def first_order (y, t, x):
    '''first order nonlinear time dependent d.e.'''
    c, v = y
    dydt = (v, x - .0001*c*c*t)
    return dydt


# +
fig = plt.figure(figsize=(9.8, 4),num="Equazioni differenziali (ED)")

response = fig.add_subplot(1, 2, 1)

pnts_of_resp = fig.add_subplot(1, 2, 2)

y0 = np.array([0.,0.]) # init. conditions

t_end = 10

x=1
t_0=1
t_calc=1
y0_0=1
y0_1=1


def func():
    global y0, x, t_0, t_calc, y0_0, y0_1
    y0[0] = y0_0
    y0[1] = y0_1
    t = np.linspace(0,t_end,t_end*10+1) #time points, where response (solution) is calculated
    linearity = [] # point to look, if d.e. is linear on not
    
    t = t+ t_0
    
    plus_minus = 5.
    input_amp = np.round(np.linspace(-plus_minus,plus_minus,2*int(plus_minus)+1))

    response.clear()
    pnts_of_resp.clear()
    
    current_button = buttons.index
    for amp in input_amp:
        if radio_buttons.index == 0:
            i=amp*x
            input_pack = [i, y0]
        if radio_buttons.index == 1:
            i=amp*float(y0[0])
            input_pack = [x, [i, y0[1]]]
        if radio_buttons.index == 2:
            i=amp*float(y0[1])
            input_pack = [x, [y0[0], i]]

        if current_button == 0:
            solution = odeint(nonlinear_vibr, input_pack[1], t, args=(input_pack[0],))
        if current_button == 1:
            solution = odeint(linear_vibr, input_pack[1], t, args=(input_pack[0],))
        if current_button == 2:
            solution = odeint(nonlinear, input_pack[1], t, args=(input_pack[0],))
        if current_button == 3:
            solution = odeint(time_dependent, input_pack[1], t, args=(input_pack[0],))
        if current_button == 4:
            solution = odeint(first_order, input_pack[1], t, args=(input_pack[0],))
            
        solution = solution[:,0]
        linearity.append(solution[int(t_calc*10)])
        
        if amp == 1:
            response.plot(t, solution, 'b', lw=2, label='risposta')
        else:
            response.plot(t, solution, lw=.7)
        
    response.grid()
    response.set_xlabel('$t$ [s]')
    response.set_ylabel('risposta')
    response.set_title('Soluzioni della ED')
    response.legend()

    pnts_of_resp.plot(input_amp, linearity, label='linearità')
    pnts_of_resp.grid()
    pnts_of_resp.legend()
    pnts_of_resp.set_xlabel('Input o condizioni iniziali')
    pnts_of_resp.set_ylabel('risposta nell\'istante %.1d' %t_calc)
    pnts_of_resp.set_title('Linearità della ED')
    
    
    
style = {'description_width': 'initial'}
x_widget = widgets.FloatSlider(value=0.5,min=0,max=1,step=.1,description='input',
    disabled=False,continuous_update=True,orientation='horizontal',readout=True,readout_format='.1f')
t_0_widget = widgets.IntSlider(value=0,min=0,max=10,step=1,description='delay [s]',
    disabled=False,continuous_update=True,orientation='horizontal',readout=True,readout_format='.1d')
t_calc_widget = widgets.IntSlider(value=1,min=1,max=10,step=1,description='istante di tempo [s]',
    disabled=False,continuous_update=True,orientation='horizontal',readout=True,readout_format='.1d',style=style)
y0_0_widget = widgets.FloatSlider(value=0.,min=0,max=10,step=.1,description='$x(0)$',
    disabled=False,continuous_update=True,orientation='horizontal',readout=True,readout_format='.1f')
y0_1_widget = widgets.FloatSlider(value=0.,min=0,max=10,step=.1,description='$\dot x(0)$',
    disabled=False,continuous_update=True,orientation='horizontal',readout=True,readout_format='.1f')

style = {'description_width': 'initial','button_width':'180px'}

buttons = widgets.ToggleButtons(options=['vibrazioni non lineari', 'vibrazioni lineari', 'non lineare', 'lineare tempo variante', 'non lineare tempo variante'],
    description='Seleziona un sistema:',value = 'vibrazioni non lineari',disabled=False,style=style)

display(buttons)

i=0
def buttons_clicked(event):
    global i
    i+=1
    if i%5==0: # for more efficient program
        i=0
        func()   

buttons.observe(buttons_clicked)

radio_buttons = widgets.RadioButtons(options=['input', 'x(0)', u'\u1E8B''(0)'],
    value='input',description='Cosa variare:',disabled=False,style=style)

j=0
def radio_buttons_clicked(event):
    global j
    j+=1
    if j%5==0:
        if radio_buttons.index==0:
            x_widget.min=.1
            y0_0_widget.min=0
            y0_1_widget.min=0
        if radio_buttons.index==1:
            x_widget.min=0
            y0_0_widget.min=.1
            y0_1_widget.min=0
        if radio_buttons.index==2:
            x_widget.min=0
            y0_0_widget.min=0
            y0_1_widget.min=.1
        
        j=0
        func()   

radio_buttons.observe(radio_buttons_clicked)


vbox = widgets.VBox([x_widget, t_0_widget, t_calc_widget, y0_0_widget, y0_1_widget])
hbox = widgets.HBox([vbox, radio_buttons])

#buttons.observe(buttons_clicked)
display(hbox)


k=0
def set_values(event):
    global k, x, t_0, t_calc, y0_0, y0_1
    k+=1
    if k%3==0: # every three times is because .observe sends 3 events
        k=0
        x=x_widget.value
        t_0=t_0_widget.value
        t_calc=t_calc_widget.value
        y0_0=y0_0_widget.value
        y0_1=y0_1_widget.value
        func()

x_widget.observe(set_values)
t_0_widget.observe(set_values)
t_calc_widget.observe(set_values)
y0_0_widget.observe(set_values)
y0_1_widget.observe(set_values)

#initialize:
def initialize():
    set_values(0)
    set_values(0)
    set_values(0)
    x_widget.min = .1
initialize()

StarcoderdataJupyterScriptsDedupFiltered