#Programação Não Linear - Terceiro Projeto Computacional
**Universidade Federal do Ceará**
Professor: RICARDO COELHO
Alunos: MARCIO BARROS OLIVEIRA DE SOUZA,
        PAULINO CARDIAL RABELO e
        PEDRO JORGE DE ABREU FIGUEREDO

#Introdução

Este trabalho consiste no desenvolvimento computacional de métodos de otimização não linear restrita. Dentre eles apresentamos o Método de Barreira e Penalidade. Primeiramente, apresentamos um pouco sobre o ambiente computacional usado. Em seguida, mostramos a implementação dos métodos em conjunto com um breve resumo de cada um deles. Nas seções "Modo de Usar" e "Parâmetros dos Métodos" mostramos como chamar os métodos e quais os parâmetros implementados. Por fim, fazemos um análise simples encima de um conjunto de dados disponibilizados para o desenvolvimento desta atividade.

#Instalação Ambiente

No desenvolvimento desta atividade íremos utilizar Julia como linguagem de implementação pelo seu facil uso e vasto conjunto de bibliotecas que oferecem suporte a otimização matemática. Para facilitar a distribuição fornecemos um notebook Jupyter que colocamos pode ser usado no Colab Google. Veja que facilmente podemos exportar o mesmo para o uso local.

Para podermos executar corretamente no ambiente Colab temos que executar a seguinte célula e reiniciar a aba do navegador aplicando "F5" quando a célula terminar de instalar o kernel Julia. No caso do uso local basta ter a aplicação Jupyter Notebook (,no Windows Anaconda) e uma distribuição Julia 1.4.2 ou mais recente.

```julia
# Installation cell
%%shell
if ! command -v julia 3>&1 > /dev/null
then
    wget 'https://julialang-s3.julialang.org/bin/linux/x64/1.4/julia-1.4.2-linux-x86_64.tar.gz' \
        -O /tmp/julia.tar.gz
    tar -x -f /tmp/julia.tar.gz -C /usr/local --strip-components 1
    rm /tmp/julia.tar.gz
fi
julia -e 'using Pkg; pkg"add IJulia; precompile;"'
echo 'Done'
```

    --2020-10-30 18:42:57--  https://julialang-s3.julialang.org/bin/linux/x64/1.4/julia-1.4.2-linux-x86_64.tar.gz
    Resolving julialang-s3.julialang.org (julialang-s3.julialang.org)... 151.101.2.49, 151.101.66.49, 151.101.130.49, ...
    Connecting to julialang-s3.julialang.org (julialang-s3.julialang.org)|151.101.2.49|:443... connected.
    HTTP request sent, awaiting response... 302 gce internal redirect trigger
    Location: https://storage.googleapis.com/julialang2/bin/linux/x64/1.4/julia-1.4.2-linux-x86_64.tar.gz [following]
    --2020-10-30 18:42:57--  https://storage.googleapis.com/julialang2/bin/linux/x64/1.4/julia-1.4.2-linux-x86_64.tar.gz
    Resolving storage.googleapis.com (storage.googleapis.com)... 142.250.73.208, 172.253.63.128, 142.250.31.128, ...
    Connecting to storage.googleapis.com (storage.googleapis.com)|142.250.73.208|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 99093958 (95M) [application/x-tar]
    Saving to: ‘/tmp/julia.tar.gz’

    /tmp/julia.tar.gz   100%[===================>]  94.50M   194MB/s    in 0.5s

    2020-10-30 18:42:58 (194 MB/s) - ‘/tmp/julia.tar.gz’ saved [99093958/99093958]

        Cloning default registries into `~/.julia`
        Cloning registry from "https://github.com/JuliaRegistries/General.git"
          Added registry `General` to `~/.julia/registries/General`
      Resolving package versions...
      Installed Artifacts ─────── v1.3.0
      Installed VersionParsing ── v1.2.0
      Installed MbedTLS_jll ───── v2.16.8+1
      Installed ZeroMQ_jll ────── v4.3.2+5
      Installed SoftGlobalScope ─ v1.1.0
      Installed Parsers ───────── v1.0.11
      Installed IJulia ────────── v1.22.0
      Installed JLLWrappers ───── v1.1.3
      Installed JSON ──────────── v0.21.1
      Installed Conda ─────────── v1.4.1
      Installed MbedTLS ───────── v1.0.3
      Installed ZMQ ───────────── v1.2.1
    Downloading artifact: MbedTLS
    ######################################################################## 100.0%
    Downloading artifact: ZeroMQ
    ######################################################################## 100.0%
       Updating `~/.julia/environments/v1.4/Project.toml`
      [7073ff75] + IJulia v1.22.0
       Updating `~/.julia/environments/v1.4/Manifest.toml`
      [56f22d72] + Artifacts v1.3.0
      [8f4d0f93] + Conda v1.4.1
      [7073ff75] + IJulia v1.22.0
      [692b3bcd] + JLLWrappers v1.1.3
      [682c06a0] + JSON v0.21.1
      [739be429] + MbedTLS v1.0.3
      [c8ffd9c3] + MbedTLS_jll v2.16.8+1
      [69de0a69] + Parsers v1.0.11
      [b85f4697] + SoftGlobalScope v1.1.0
      [81def892] + VersionParsing v1.2.0
      [c2297ded] + ZMQ v1.2.1
      [8f1865be] + ZeroMQ_jll v4.3.2+5
      [2a0f44e3] + Base64
      [ade2ca70] + Dates
      [8ba89e20] + Distributed
      [7b1f6079] + FileWatching
      [b77e0a4c] + InteractiveUtils
      [76f85450] + LibGit2
      [8f399da3] + Libdl
      [56ddb016] + Logging
      [d6f4376e] + Markdown
      [a63ad114] + Mmap
      [44cfe95a] + Pkg
      [de0858da] + Printf
      [3fa0cd96] + REPL
      [9a3f8284] + Random
      [ea8e919c] + SHA
      [9e88b42a] + Serialization
      [6462fe0b] + Sockets
      [8dfed614] + Test
      [cf7118a7] + UUIDs
      [4ec0a83e] + Unicode
       Building Conda ─→ `~/.julia/packages/Conda/3rPhK/deps/build.log`
       Building IJulia → `~/.julia/packages/IJulia/a1SNk/deps/build.log`
    Precompiling project...
    Done

#Dependências

As depências a seguir devem ser instaladas para permitir importar as bibliotecas que são usadas neste trabalho.

```julia
9#Julia 1.4 Environment
using Pkg
pkg"add ForwardDiff; precompile;"
pkg"add Plots; precompile;"
pkg"add PyPlot; precompile;"
```

       Updating registry at `~/.julia/registries/General`

       Updating git-repo `https://github.com/JuliaRegistries/General.git`

      Resolving package versions...
      Installed OpenSpecFun_jll ────────────── v0.5.3+4
      Installed CompilerSupportLibraries_jll ─ v0.3.4+0
      Installed DiffResults ────────────────── v1.0.2
      Installed NaNMath ────────────────────── v0.3.4
      Installed MacroTools ─────────────────── v0.5.6
      Installed DiffRules ──────────────────── v1.0.1
      Installed StaticArrays ───────────────── v0.12.5
      Installed ForwardDiff ────────────────── v0.10.12
      Installed SpecialFunctions ───────────── v0.10.3
      Installed CommonSubexpressions ───────── v0.3.0
    ######################################################################### 100.0%
    ######################################################################### 100.0%
       Updating `~/.julia/environments/v1.4/Project.toml`
      [f6369f11] + ForwardDiff v0.10.12
       Updating `~/.julia/environments/v1.4/Manifest.toml`
      [bbf7d656] + CommonSubexpressions v0.3.0
      [e66e0078] + CompilerSupportLibraries_jll v0.3.4+0
      [163ba53b] + DiffResults v1.0.2
      [b552c78f] + DiffRules v1.0.1
      [f6369f11] + ForwardDiff v0.10.12
      [1914dd2f] + MacroTools v0.5.6
      [77ba4419] + NaNMath v0.3.4
      [efe28fd5] + OpenSpecFun_jll v0.5.3+4
      [276daf66] + SpecialFunctions v0.10.3
      [90137ffa] + StaticArrays v0.12.5
      [37e2e46d] + LinearAlgebra
      [2f01184e] + SparseArrays
      [10745b16] + Statistics
    Precompiling project...
    ┌ Info: Precompiling ForwardDiff [f6369f11-7733-5829-9624-2563aa707210]
    └ @ Base loading.jl:1260
      Resolving package versions...
      Installed FFMPEG_jll ────────────────── v4.3.1+4
      Installed HTTP ──────────────────────── v0.8.19
      Installed LibVPX_jll ────────────────── v1.9.0+1
      Installed FreeType2_jll ─────────────── v2.10.1+5
      Installed DataAPI ───────────────────── v1.3.0
      Installed TableTraits ───────────────── v1.0.0
      Installed StructArrays ──────────────── v0.4.4
      Installed StatsBase ─────────────────── v0.33.2
      Installed Plots ─────────────────────── v1.6.12
      Installed Adapt ─────────────────────── v2.3.0
      Installed FFMPEG ────────────────────── v0.4.0
      Installed DataStructures ────────────── v0.18.8
      Installed IterTools ─────────────────── v1.3.0
      Installed Grisu ─────────────────────── v1.0.0
      Installed x264_jll ──────────────────── v2020.7.14+2
      Installed Contour ───────────────────── v0.5.5
      Installed OpenSSL_jll ───────────────── v1.1.1+6
      Installed Colors ────────────────────── v0.12.4
      Installed IniFile ───────────────────── v0.5.0
      Installed Bzip2_jll ─────────────────── v1.0.6+5
      Installed FriBidi_jll ───────────────── v1.0.5+6
      Installed Opus_jll ──────────────────── v1.3.1+3
      Installed SortingAlgorithms ─────────── v0.3.1
      Installed PlotThemes ────────────────── v2.0.0
      Installed IteratorInterfaceExtensions ─ v1.0.0
      Installed EarCut_jll ────────────────── v2.1.5+0
      Installed OrderedCollections ────────── v1.3.1
      Installed Latexify ──────────────────── v0.14.2
      Installed FixedPointNumbers ─────────── v0.8.4
      Installed Measures ──────────────────── v0.3.1
      Installed x265_jll ──────────────────── v3.0.0+3
      Installed Reexport ──────────────────── v0.2.0
      Installed GeometryBasics ────────────── v0.3.3
      Installed PlotUtils ─────────────────── v1.0.7
      Installed DataValueInterfaces ───────── v1.0.0
      Installed libfdk_aac_jll ────────────── v0.1.6+4
      Installed Tables ────────────────────── v1.1.0
      Installed Ogg_jll ───────────────────── v1.3.4+2
      Installed libvorbis_jll ─────────────── v1.3.6+6
      Installed LaTeXStrings ──────────────── v1.2.0
      Installed Zlib_jll ──────────────────── v1.2.11+18
      Installed Compat ────────────────────── v3.23.0
      Installed Missings ──────────────────── v0.4.4
      Installed Showoff ───────────────────── v0.3.2
      Installed LAME_jll ──────────────────── v3.100.0+3
      Installed Formatting ────────────────── v0.4.1
      Installed RecipesPipeline ───────────── v0.1.13
      Installed ColorTypes ────────────────── v0.10.9
      Installed RecipesBase ───────────────── v1.1.0
      Installed Requires ──────────────────── v1.1.0
      Installed GR ────────────────────────── v0.52.0
      Installed GeometryTypes ─────────────── v0.8.3
      Installed libass_jll ────────────────── v0.14.0+4
      Installed ColorSchemes ──────────────── v3.10.1
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
    ######################################################################### 100.0%
       Updating `~/.julia/environments/v1.4/Project.toml`
      [91a5bcdd] + Plots v1.6.12
       Updating `~/.julia/environments/v1.4/Manifest.toml`
      [79e6a3ab] + Adapt v2.3.0
      [6e34b625] + Bzip2_jll v1.0.6+5
      [35d6a980] + ColorSchemes v3.10.1
      [3da002f7] + ColorTypes v0.10.9
      [5ae59095] + Colors v0.12.4
      [34da2185] + Compat v3.23.0
      [d38c429a] + Contour v0.5.5
      [9a962f9c] + DataAPI v1.3.0
      [864edb3b] + DataStructures v0.18.8
      [e2d170a0] + DataValueInterfaces v1.0.0
      [5ae413db] + EarCut_jll v2.1.5+0
      [c87230d0] + FFMPEG v0.4.0
      [b22a6f82] + FFMPEG_jll v4.3.1+4
      [53c48c17] + FixedPointNumbers v0.8.4
      [59287772] + Formatting v0.4.1
      [d7e528f0] + FreeType2_jll v2.10.1+5
      [559328eb] + FriBidi_jll v1.0.5+6
      [28b8d3ca] + GR v0.52.0
      [5c1252a2] + GeometryBasics v0.3.3
      [4d00f742] + GeometryTypes v0.8.3
      [42e2da0e] + Grisu v1.0.0
      [cd3eb016] + HTTP v0.8.19
      [83e8ac13] + IniFile v0.5.0
      [c8e1da08] + IterTools v1.3.0
      [82899510] + IteratorInterfaceExtensions v1.0.0
      [c1c5ebd0] + LAME_jll v3.100.0+3
      [b964fa9f] + LaTeXStrings v1.2.0
      [23fbe1c1] + Latexify v0.14.2
      [dd192d2f] + LibVPX_jll v1.9.0+1
      [442fdcdd] + Measures v0.3.1
      [e1d29d7a] + Missings v0.4.4
      [e7412a2a] + Ogg_jll v1.3.4+2
      [458c3c95] + OpenSSL_jll v1.1.1+6
      [91d4177d] + Opus_jll v1.3.1+3
      [bac558e1] + OrderedCollections v1.3.1
      [ccf2f8ad] + PlotThemes v2.0.0
      [995b91a9] + PlotUtils v1.0.7
      [91a5bcdd] + Plots v1.6.12
      [3cdcf5f2] + RecipesBase v1.1.0
      [01d81517] + RecipesPipeline v0.1.13
      [189a3867] + Reexport v0.2.0
      [ae029012] + Requires v1.1.0
      [992d4aef] + Showoff v0.3.2
      [a2af1166] + SortingAlgorithms v0.3.1
      [2913bbd2] + StatsBase v0.33.2
      [09ab397b] + StructArrays v0.4.4
      [3783bdb8] + TableTraits v1.0.0
      [bd369af6] + Tables v1.1.0
      [83775a58] + Zlib_jll v1.2.11+18
      [0ac62f75] + libass_jll v0.14.0+4
      [f638f0a6] + libfdk_aac_jll v0.1.6+4
      [f27f6e37] + libvorbis_jll v1.3.6+6
      [1270edf5] + x264_jll v2020.7.14+2
      [dfaa095f] + x265_jll v3.0.0+3
      [8bb1440f] + DelimitedFiles
      [1a1011a3] + SharedArrays
       Building GR → `~/.julia/packages/GR/BwGt2/deps/build.log`
    Precompiling project...
    ┌ Info: Precompiling Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]
    └ @ Base loading.jl:1260
      Resolving package versions...
      Installed PyPlot ─ v2.9.0
      Installed PyCall ─ v1.92.1
       Updating `~/.julia/environments/v1.4/Project.toml`
      [d330b81b] + PyPlot v2.9.0
       Updating `~/.julia/environments/v1.4/Manifest.toml`
      [438e738f] + PyCall v1.92.1
      [d330b81b] + PyPlot v2.9.0
       Building PyCall → `~/.julia/packages/PyCall/BcTLp/deps/build.log`
    Precompiling project...
    ┌ Info: Precompiling PyPlot [d330b81b-6aea-500a-939a-2ce795aea3ee]
    └ @ Base loading.jl:1260

Funções Auxiliares

Durante a implementação usamos uma biblioteca para calcular derivadas e gradientes através da técnica  de "Automatic Differentiation". Essa permite calcular com precisão e agilidade os métodos aqui utilizados. Além disso, usamos o framework Plots em conjunto com a engine PyPlot para gerar gráficos das funções testadas.

```julia
import ForwardDiff  # calcula derivadas usando automatic differentiation in forward mode
using LinearAlgebra #adiciona operações de algebra linear
using Plots

pyplot()#usa PyPlot como backend engine
∇ = (h,x)->ForwardDiff.gradient(h,x) #gradiente de h(x)
Hessian = (h,x)->ForwardDiff.hessian(h,x) # hessian de h(x)
Df = (h,x)->ForwardDiff.derivative(h,x);  # primeira derivada de h'(x)
D_2f = (h,x)->ForwardDiff.derivative(z->ForwardDiff.derivative(h,z),x) # segunda derivada h"(x)
```

    #198 (generic function with 1 method)

```julia
#função de busca linear
function linear_search(f::Function,x::Vector,d::Vector,method::Function)
    ϕ = t->f(x+t*d)
    α = method(f,x,d)
    return (ϕ(α),x+α*d)
end

function viable_step(x::Vector,d::Vector,α,inequalities::Vector)
    while(length(filter(x->x==true,[g(x+α*d)>0 for g in inequalities]))!=0)
          α = 0.8*α
    end
    return α;
end

function secao_aurea(f::Function,x::Vector,d::Vector;φ::Function = t->f(x+t*d),ρ = 1/2,ϵ = 1e-9)::Float64
    θ_1 = (3 - sqrt(5))/2.0
    θ_2 = (sqrt(5) - 1)/2.0
    #Obtenção intervalo
    a=0
    b=2*ρ
    s = b / 2
    while(φ(b)<φ(s))
        a = s
        s = b
        b *= 2
    end
    #Obtenção de t
    u = a + θ_1*(b - a)
    v = a + θ_2*(b - a)
    while(b - a > ϵ)
        if(φ(u)<φ(v))
            b = v
            v = u
            u = a + θ_1*(b - a)
        else
            a = u
            u = v
            v = a + θ_2*(b - a)
        end
    end
    return (u+v)/2
end

function secao_aurea(f::Function,x::Vector,d::Vector,(a,b)::Tuple{Float64,Float64};φ::Function = t->f(x+t*d),ϵ = 1e-9,n_iter=100)::Float64
    θ_1 = (3 - sqrt(5))/2.0
    θ_2 = (sqrt(5) - 1)/2.0
    #Obtenção de t
    u = a + θ_1*(b - a)
    v = a + θ_2*(b - a)
    iter = 0
    while(b - a > ϵ&&iter<n_iter)
        if(φ(u)< φ(v))
            b = v
            v = u
            u = a + θ_1*(b - a)
        else
            a = u
            u = v
            v = a + θ_2*(b - a)
        end
        iter = iter + 1
    end
    return (u+v)/2
end

function newton(f::Function,x::Vector,d::Vector;φ::Function = y->f(x+y*d),t::Float64=1.0,ϵ = 1e-4,n_iter=100)::Float64
   iter = 0
   while (abs(Df(φ,t)) > ϵ && iter < n_iter)
         t_next = t - (Df(φ,t)/D_2f(φ,t))
         if(t_next>=0.0)
            t = t_next
         else
            return t
         end
         iter = iter + 1
   end
   return t
end

function armijo(f::Function,x::Vector,d::Vector;φ::Function = y->f(x+y*d),t::Float64= 1.0,η::Float64 = 0.25)
    # f(x + td) > f(x) +t(∇f(x)⋅ d)
    while (φ(t)>φ(0)+ η*t*(∇(f,x)⋅d)&&t>1e-12)
      t *=0.8
    end
    return t
end

function gradient_descent(f::Function,x::Vector,linear_method::Function;ϵ=1e-4,n_iter=100)
     iter = 0
    while(norm(∇(f,x))> ϵ && iter < n_iter)
      d = -∇(f,x)
      x = linear_search(f,x,d,linear_method)[2]
      iter = iter + 1
    end

    return (f(x),x)
end

function newton_search(f::Function,x::Vector,linear_method::Function;ϵ=1e-4,n_iter=100)
     iter = 0
    while(norm(∇(f,x))> ϵ && iter < n_iter)
        d = -inv(Hessian(f,x))*∇(f,x)
        x = linear_search(f,x,d,linear_method)[2]
         iter = iter + 1
    end
    return (f(x),x)
end

function quasi_newton_BFGS(f::Function,x::Vector,linear_method::Function;ϵ=1e-4,n_iter=100)
    H = I
     flag = true
    g_new=∇(f,x)
     iter = 0
    while(norm(g_new)> ϵ&& iter < n_iter)
       d = -H*g_new
       x_old=x
       g_old = g_new
      x=linear_search(f,x,d,linear_method)[2]
      if(-x_old[1]+x[1]==0.0)
          return (f(x),x)
      end
      p = x - x_old
      g_new = ∇(f,x)
      q = g_new - g_old
      qT = transpose(q)
      pT = transpose(p)
       if(flag)
          H = ((qT*p)/(qT*q))*I #scaling of I
          flag =false
      end
      H = H+ (1+ ((qT*H*q)/(pT*q)))*((p*pT)/(pT*q)) - ((p*qT*H + H*q*pT)/(pT*q))
      iter = iter +1
    end
    return (f(x),x)
end

function gradient_conjugate_PR(f::Function,x::Vector,linear_method::Function;ϵ=1e-4,n_iter=100)
    k = 0
    n = length(x)
    g_new=∇(f,x)
    d = -g_new
    while(norm(g_new)> ϵ&&k<n_iter)
        x_old = x
        g_old = g_new
        x=linear_search(f,x,d,linear_method)[2]
        g_new  = ∇(f,x)
        β = max((transpose(g_new)*(g_new - g_old))/(transpose(g_old)*g_old),0)
        d = -g_new + β*d
        k = k + 1
    end
    return (f(x),x)
end
```

    gradient_conjugate_PR (generic function with 1 method)

#Método da Barreira

O objetivo do método é transformar um problema restrito em um problema irrestrito. Para isso usamos um parâmetro que ajuda a transformar o problema restrito em um problema irrestrito, onde tal parâmetro deve tender a zero para obtermos a convergência para solução do problema original. A ideia é obter uma nova função para o problema irrestrito, de tal maneira que ela tenha uma "barreira" em torno do conjunto viável, e com isso vamos gerar uma sequência {$x_{k}$} de pontos viáveis a partir de um $x_{0}$ viável.

\

Definição \\
Uma função $\psi :D^{0}\rightarrow\mathbb{R}_{+}$ chama-se barreira para o conjunto $D$ definido por uma função objetivo sujeito a um conjunto de restrições de desigualdades, se ela e contínua $D^{0}$, e para a sequência {$x_{k}$}$\subset D^{0}$ tal que $g_{i}(x_{k})\rightarrow 0$ para algum $i\in${$1,..,m$}, tem-se que $\psi (x_{k})\rightarrow+\infty$ $(k\rightarrow+\infty)$.

\

Com $min$ $f(x)$ sujeito a $x\in D=\left\{x\in \mathbb{R}^{n}|g(x)\leq 0\right\}$, sendo $f:\mathbb{R}^{n}\rightarrow\mathbb{R}$ e $g:\mathbb{R}^{n}\rightarrow\mathbb{R}^{m}$, sendo o problema a ser resolvido. \\
Essa definição nos diz que barreira é uma função na qual se nos aproximarmos da fronteira do conjunto viável, a função de barreira vai tender para infinito. Portanto vale ressaltar que $\psi$, a função de barreira, trabalha no conjunto interior do conjunto viável, pois nas igualdades, teriamos indeterminações, porem mesmo assim teriamos a mesma solução, pois.

\

\begin{equation}
inf_{x\in D^{0}}f(x)=inf_{x\in D}f(x)=v>-\infty
\end{equation}

\

Com isso podemos definir algumas funções de barreira como a logarítmica,

\

\begin{equation}
\psi(x)=-\sum^{m}_{i=1}log(-g_{i}(x))
\end{equation}
com $x\in D^{0}$

\

Pode-se perceber que se $x$ pertencer a fronteira de $D$, então vamos ter uma indeterminação pois para algum $i\in${$1,...,m$}, vamos ter $log(-g_{i}(x)=0)$ que é uma indeterminação. Uma observação é que o sinal negativo de $g_{i}(x)$ no logaritmo vem da sua desigualdade $\leq$, pois para $x\in D^{0}$ temos que $log(g_{i}(x)<0)$, como $log$ não é definido para números negativos, portanto multiplicamos por $(-1)$, e ficamos com $log(-g_{i}(x)>0)$. \\
Tambem temos a barreira inversa, definida por.

\

\begin{equation}
\psi(x)=-\sum^{m}_{i=1}\frac{1}{g_{i}(x)}
\end{equation}
com $x\in D^{0}$

\

análogo a barreira logarítmica, teremos uma indeterminação se $x$ pertencer a fronteira de conjunto viável.

\

Agora podemos definir a função objetivo do problema irrestrito como,

\

\begin{equation}
\phi (x;t)=f(x)+t\psi (x)
\end{equation}

\

sendo $t>0$ o parâmetro penalizador. Portanto vamos ficar com o problema de $min$ $f(x)+t\psi(x)$ sujeito a $x\in \mathbb{R}^{n}$, com $\phi:D^{0}\rightarrow\mathbb{R}_{+}$

\

Proposição \\
Suponhamos que o conjunto viável $D$ satisfaça o fato de ser interior e que o ínfimo de $f$ seja o valor ótimo desse problema. Seja {$x_{k}$} uma sequência gerada pelo algoritmo do método de barreira, onde $x_{k}$ é um solução global do problema transformado com $t=t_{k}$. Então $\forall k$, tem-se que

\

\begin{equation}
\phi (x_{k+1};t_{k+1})\leq \phi (x_{k};t)
\end{equation}
\begin{equation}
\psi (x_{k+1})\geq \psi (x_{k})
\end{equation}
\begin{equation}
f(x_{k+1})\leq f(x_{k})
\end{equation}

\

Teorema (Convergência do Métodos de Barreira) \\
Sejam $f:\mathbb{R}^{n}\rightarrow\mathbb{R}$ e $g:\mathbb{R}^{n}\rightarrow\mathbb{R}^{m}$ funções contínuas em $\mathbb{R}^{n}$. Suponhamos que o conjunto viável $D$ satisfaça o fato de ser interior e que o ínfimo de $f$ seja o valor ótimo desse problema. Então todo ponto de acumulação da sequência {$x_{k}$} gerada pelo algoritmo do método de barreira, onde $x_{k}$ é uma solução global do problema transformado com $t=t_{k}$ e $t\rightarrow 0$$(k\rightarrow \infty)$, é uma solução global do problema de otimização original.

```julia
function barrier_method(f::Function,x::Vector,inequalities::Vector,unc_opt_method::Function,linear_method::Function;t=10.0,β=0.5,tol=1e-4)
    function ψ(x)
        if(length(filter(x->x>=0,[g(x) for g in inequalities]))!=0)
            return Inf
        end
        return -sum([(1.0/g(x)) for g in inequalities])
    end
    φ = (y,h)-> f(y) + h*ψ(y)
    #L = (y,μ)-> -∇(f,x) + sum(μ.*[∇(g,x) for g in inequalities]))
    x = unc_opt_method(y->φ(y,t),x,(f,x,d)->viable_step(x,d,linear_method(f,x,d),inequalities))[2]
    while(t*ψ(x)>=tol)
       t = β*t
       x = unc_opt_method(y->φ(y,t),x,(f,x,d)->viable_step(x,d,linear_method(f,x,d),inequalities))[2]
       #println("--------barrier step---------")
       #println([x,f(x),t,ψ(x)])
       #println("-----------------------------")
    end
    return (f(x),x)
end

```

    barrier_method (generic function with 1 method)

```julia
barrier_method(x->(x[1]-2)^2+(x[2]-1)^2,[0.5,0.5],[x->x[1]+x[2]-2,x->x[1]^2-x[2]],gradient_descent,armijo)
```

    (1.0000787953324752, [0.999960603303814, 0.9999803021930853])

#Método de Penalidade

O objetivo é transformar um problema restrito em irrestrito, onde vamos gerar um sequência {$x_{k}$} de pontos inviáveis, onde espera-se que quando $x_{k}$ torne-se viável, vamos ter a solução do problema original. E para a convergência à solução do problema original, é necessário que o parâmetro que nos auxilia nessa transformação vá para o infinito. \\
Assim vamos querer uma função $\psi :\mathbb{R}^{n}\rightarrow \mathbb{R}_{+}$ contínua em $\mathbb{R}^{n}$, tal que.

\

\begin{equation}
\psi (x)=\left\{\begin{matrix}
 =0& \forall x\in D \\
 >0& \forall x\in \mathbb{R}^{n}-D
\end{matrix}\right.
\end{equation}

\

Perceba que quando $x\rightarrow D$, então $\psi \rightarrow 0$. \\
Para definir $\psi$ tome $\phi :\mathbb{R}^{n}\rightarrow \mathbb{R}^{l}\times\mathbb{R}^{m}$ como,

\

\begin{equation}
\phi (x)=(h(x), max\left\{0,g_{1}(x)\right\},...,max\left\{0,g_{m}(x)\right\})
\end{equation}

\

Veja que se para algum $x^{*}$ houver um $i\in${$1,...,m$}, tal que, $g_{i}(x^{*})<0$, então, $\phi (x^{*})=(h(x^{*}),...,max\left\{0,g_{i-1}(x)\right\},0,max\left\{0,g_{i+1}(x)\right\},...,max\left\{0,g_{m}(x)\right\})$, e como $\forall x\in D$ temos que $h(x)=0$ e $g_{i}(x)\leq 0$ $\forall i\in \left\{1,...,m\right\}$, portanto concluímos que $\phi (x)=(0,...,0)$. Agora podemos definir nossa $\psi$ como,

\

\begin{equation}
\psi (x)=||\phi (x)||^{p}
\end{equation}
Com $x\in \mathbb{R}^{n}$ e $p>0$

\

Que satisfaz as propriedades pois, pra $x\in D$ tem que $\psi =0$ pois $||0||^{p}=0$ e definida positiva. Para $h(x)$ e $g(x)$ diferenciáveis, temos que para a norna Euclidiana $\psi (x)$ é diferenciável para $p>1$, e não diferenciável caso contrário.

\

Agora podemos definir nosso problema irrestrito como,

\

\begin{equation}
min \varphi(x;t)=f(x)+c\psi(x)
\end{equation}
$\hspace{3cm}$Sujeito $x\in \mathbb{R}^{n}$

\
Note que quando $c$ tende ao infinito, os valores de $\psi$ fora de $D$ crescem muito, assim a sequência {$x_{k}$} se aproxima do conjunto viável $D$.

\

Teorema (Convergência Global do Método de Penalização Externa) \\
Seja {$x_{k}$} uma sequência gerada pelo algoritmo de penalização, onde $x_{k}$ é uma solução global do problema irrestrito transformado com $c=c_{k}$. Então $x_{k}\in D$ se, somente se, $x_{k}$ for uma solução global do problema original. Sejam $f:\mathbb{R}^{n}\rightarrow\mathbb{R}$ e $\psi:\mathbb{R}^{n}\rightarrow\mathbb{R}_{+}$ funções contínuas em $\mathbb{R}^{n}$ e seja $v>-\infty$ o valor ótimo do problema original. Se $c_{k}\rightarrow\infty$$(k\rightarrow\infty)$, então todo ponto de acumulação da sequência {$x_{k}$} é uma solução global do problema original.

```julia
function penality_method(f::Function,x::Vector,equalities::Vector,inequalities::Vector,unc_opt_method::Function,linear_method::Function;c=0.1,β=10,tol=1e-4,p=2)
    ϕ = y-> append!([h(y) for h in equalities],[max(0,g(y)) for g in inequalities])
    ψ= y -> norm(ϕ(y))^p
    φ = (y,t)-> f(y) + c*ψ(y)
    #L = (y,μ)-> -∇(f,x) + sum(μ.*[∇(g,x) for g in inequalities]))
    x = unc_opt_method(y->φ(y,c),x,linear_method)[2]
    while(c*ψ(x)>=tol)
       c = β*c
       x = unc_opt_method(y->φ(y,c),x,linear_method)[2]
    end
    return (f(x),x)
end
```

    penality_method (generic function with 1 method)

```julia
penality_method(x->(x[1]-2)^2+(x[2]-1)^2,[0.5,0.5],[],[x->x[1]+x[2]-2,x->x[1]^2-x[2]],newton_search,newton)
```

    (0.9999555583948376, [1.0000222211111889, 1.0000111102469702])

# Modo de Usar

   Sejam os dados de entrada $x \in \mathcal{R}^n , f: \mathcal{R}^n \to \mathcal{R},g= \{g_i:\mathcal{R}^n \to \mathcal{R}|0\leq i \leq m,i\in \mathbb{N}\}$ e $h= \{h_j: \mathcal{R}^n \to \mathcal{R}|0\leq j \leq l,j\in \mathbb{N}\}$. Onde $x$ representa as variáveis de decisão , $f$ a função objetivo,$g$ conjunto de todas as desigualdades válidas($g_i(x)\leq0$) e $h$ conjunto de todas as equações válidas($h_i(x)=0$), no caso somente para o método de penalidade). Vamos mostrar como chamar os métodos de otimização restrita(no caso temos as funções: barrier_method e penality_method) para resolver o problema de encontrar um ponto ótimo e  valor da função neste ponto.

   Considere o seguinte exemplo, seja $f(x_1,x_2)= (x_1-2)^2+(x_2-1)^2,g_1 = x_1+x_2-2,g_2=x_1^2-x_2$ e $x = \begin{pmatrix}0.5 \\0.5\end{pmatrix}$ . Esses podem ser passados para um método da seguinte forma:

```julia
penality_method(x->(x[1]-2)^2+(x[2]-1)^2,[0.5,0.5],[],[x->x[1]+x[2]-2,x->x[1]^2-x[2]],gradient_descent,newton)
```

    (1.01059485367582, [0.9947711703997256, 0.9895188828705027])

   Onde o primeiro campo da função implementa uma função anônima para representar $f(x)$, com formato (vetores)$\to$ (função expressa). Devemos utilizar de operações aritméticas padrões sobre um vetor[$i$], que refere-se a coordenada $i$ do vetor(em julia começa de 1 até n), para expressar $f(x)$, usamos esse mesmo modo para especificar $g$ (Atenção para o sinal da desigualdade, multiplique por -1 caso $g_i\geq 0$, fazendo $g_i=-g_i$) e $h$. O campo seguinte do método faz referência à $x$ implementado como um Array'([$x_1$,$x_2$]. Os dois campos seguintes usam Array's para implementar o conjunto g e h , aonde seus elementos são funções anônimas.

  No penúltimo campo temos uma função referenciando o método de busca irrestrita(no caso método da gradiente) usado, temos quatro referências implementadas gradient_descent,newton_search,quasi_newton_BFGS,gradient_conjugate_PR. Elas podem ser chamadas da forma que foi definida no [Projeto 2](https://colab.research.google.com/drive/1M7-OvZIy7IrNnfRISIJWpaCJilva6jUA#scrollTo=69BxyOziMVFf).

  No último campo temos uma função referenciando o método de busca linear(no caso newton) usado, temos três referências implementadas secao_aurea, armijo e newton. Elas podem ser chamadas da mesma forma que foi definida no [Projeto 1](https://colab.research.google.com/drive/1Nt6ffNGr-3ej0gCgIW2sG5DYSnJ7Pywh?usp=sharing).

```julia
penality_method(x->(x[1]-2)^2+(x[2]-1)^2,[0.5,0.5],[],[x->x[1]+x[2]-2,x->x[1]^2-x[2]],gradient_descent,newton)
```

    (1.01059485367582, [0.9947711703997256, 0.9895188828705027])

 Na proxima seção discutimos os parâmetros para cada método. A saída do método  retorna uma tupla da forma ($f(x^*),x^*$), ou seja, o valor da função objetivo no melhor ponto encontrado e o ponto. Veja que um novo parametro limitando o número de iterações foi usado para controlar melhor o método de barreira em pontos inviáveis.

# Parâmetros dos Métodos

   Aqui colocaremos as funções dos métodos implementados e a descrição sobre seus parâmetros. Parametros depois do caracter ";" são chamados de argumentos palavra-chave. Esses devem vir depois dos argumentos posicionais e da forma (palavra-chave) = valor. Algumas palavras-chave estão em unicode para acessar estas no julia basta escrever da mesma forma que em latex(ex. \epsilon) e pressionar a tecla 'tab', ou seja , $\epsilon$ = \epsilona + tab. No ambiente Colab para inserir os caracteres basta copiar das funções, pois o mesmo não possui suporte para inserir caracteres unicode.

barrier_method(f::Function,x::Vector,inequalities::Vector,unc_opt_method::Function,linear_method::Function;t=10.0,β=0.5,tol=1e-4)

>  Algoritmo usando função de barreira inversa. O ponto inicial precisa ser viável. Possui problemas com pontos inviáveis, foram feitas configurações de passo e métodos para lidar com eles.

* t -  Multiplicador Inicial da função de Barreira Inversa.
* β -  Fator de escalonamento do fator c.
* n_iter -  Número de iterações máxima usada pelo método.
* tol - Tolerância utilizada para verificar convergencia. Com menor precisão mais rápido converge.

---
 penality_method(f::Function,x::Vector,equalities::Vector,inequalities::Vector,unc_opt_method::Function,linear_method::Function;c=0.1,β=10,tol=1e-9,n_iter=100,p=2)

> Método de penalidade clássico. Não possui problema com pontos inviáveis.
* c -  Multiplicador Inicial da função de Penalidade.
* β -  Fator de escalonamento do fator c.
* n_iter -  Número de iterações máxima usada pelo método.
* tol - Tolerância utilizada para verificar convergencia. Com menor precisão mais rápido converge.
* p - Fator de exponenciação norma euclidiana.

---

Todos os métodos retornam a função objetivo e o melhor ponto encontrado. Vale ressaltar que podemos passar em linear_method uma função de passo constante ou funções com passos customizados aos métodos.

#Testes

Nesta seção definimos as instâncias de testes que usamos e quais os resultados os métodos encontraram.

Instâncias

   As instâncias dadas são definidas em termo de função objetivo, valor inicial de $x$, desigualdades $g$ e igualdades $h$. Apresentamos abaixo as instâncias em código separadas por parametros que seram usados pelos métodos.

```julia
#instancia 1
f1 = x->100*(x[2]-x[1]^2)^2 + (1-x[1])^2
g1 = [(x->x[1]-x[2]^2),(x->x[2]-x[1]^2)]
x1 = [-2,1]

#instancia 2
f2 = x->x[1]^2 + 0.5*x[2]^2+ x[3]^2 + 0.5*x[4]^2 -x[1]*x[3] +x[3]*x[4] - x[1] - 3*x[2] + x[3] - x[4]
g2 = [(x->x[1] + 2*x[2] + x[3]+x[4]-5),(x->3*x[1]+x[2]+2*x[3]-x[4]-4),(x->1.5-4*x[3] - x[2]),(x->(-x[1])),(x->(-x[2])),(x->(-x[3])),(x->(-x[4]))]
x2 = [0.5,0.5,0.5,0.5]

#instancia 3
f3 = x->(x[1]-10)^3 +(x[2]-20)^3
g3 = [(x->-(x[1]-5)^2 - (x[2]-5)^2 + 100),(x->-(x[1]-6)^2 - (x[2]-5)^2),(x->(x[1]-6)^2 + (x[2]-5)^2 - 82.81)]
x3 = [14.115,0.885]

#instancia 4
f4 = x->0.01*(x[1]-1)^2+(x[2]-x[1]^2)^2
h4 = [(x->x[1]+x[3]^2+1)]
x4 = [2,2,2]

#instancia 5
f5 = x->(x[1]-x[2])^2+(x[2]+x[3]-2)^2+(x[4]-1)^2+(x[5]-1)^2
h5 = [(x->x[1]+3*x[2]-4),(x->x[3]+x[4]-2*x[5]),(x->x[2]-x[5])]
x5 = [2.5,0.5,2,-1,0.5]

#instancia 6
f6 = x->(x[1]-x[2])^2 +(x[2] -1)^2
h6 = [(x->x[1]-2*x[2] +1)]
g6 = [(x->0.25*x[1]^2+x[2]^2 - 1)]
x6 = [2,2]

#instancia 7
f7 = x->x[1]*x[4]*(x[1]+x[2]+x[3])+x[3]
g7 = [(x->-x[1]*x[2]*x[3]*x[4] + 25),(x-> -(x[1]^2)-(x[2]^2)-(x[3]^2)-(x[4]^2)+40),(x-> -x[1]+1),(x-> -x[2]+1),(x-> -x[3]+1),(x-> -x[4]+1),(x-> x[1]-5),(x-> x[2]-5),(x-> x[3]-5),(x-> x[4]-5)]
x7 = [3,4,4,3]

#instancia 8
f8 = x->x[1]-x[2]-x[3]-x[1]*x[3]+x[1]*x[4]+x[2]*x[3]-x[2]*x[4]
g8 = [(x->x[1]+2*x[2]-8),(x->4*x[1]+x[2]-12),(x->3*x[1]+4*x[2]-12),(x->2*x[3]+x[4]-8),(x->x[3]+2*x[4]-8),(x->x[3]+x[4]-5),(x->(-x[1])),(x->(-x[2])),(x->(-x[3])),(x->(-x[4]))]
x8 = [1,1,1,1]

#instancia 9
f9 = x->(x[1]-10)^2+5*(x[2]-12)^2 + x[3]^4 + 3*(x[4]-11)^2 + 10*x[5]^6+7*x[6]^2+x[7]^4-4*x[6]*x[7]- 10*x[6] - 8*x[7]
g9 = [(x->x[1]^2+3*x[2]^4+x[3]+4*x[4]^2+5*x[5]-127),(x->7*x[1]+3*x[2]+10*x[3]^2+x[4]-x[5]-282),(x->23*x[1]^2+x[2]^2+6*x[6]^2-8*x[7]-196),(x->4*x[1]^2+x[2]^2-3*x[1]*x[2]+2*x[3]^2+5*x[6]-11*x[7])]
x9 = [1,2,0,4,0,1,1]

```

    7-element Array{Int64,1}:
     1
     2
     0
     4
     0
     1
     1

## Instâncias Método da Barreira

1.

```julia
barrier_method(f1,x1,g1,(f,x,linear)->gradient_descent(f,x,linear,n_iter=500),newton,t=300)
```

    (3.5066395743146755e-5, [1.002079492666194, 1.0036088539792365])

2.

```julia
barrier_method(f2,x2,g2,newton_search,armijo)
```

    (-4.68172223408539, [0.2727374658945035, 2.090876384025888, 3.67142487771465e-5, 0.5454014832968413])

3.

```julia
barrier_method(f3,x3,g3,newton_search,newton)
```

    (-6961.813802875752, [14.095000031299115, 0.8429608538216018])

## Instâncias Método da Penalidade

1.

```julia
penality_method(f4,x4,h4,[],newton_search,armijo)
```

    (0.039920119840199754, [-0.998001998001998, 0.99600798801598, 2.4314586365084114e-24])

2.

```julia
penality_method(f5,x5,h5,[],quasi_newton_BFGS,newton)
```

    (3.4512664603419266e-31, [0.9999999999999998, 1.0, 0.9999999999999997, 1.0000000000000002, 1.0000000000000002])

3.

```julia
penality_method(f6,x6,h6,g6,quasi_newton_BFGS,secao_aurea)
```

    (0.015524335384016067, [0.8237947044538988, 0.9115954459735927])

## Ambos os Métodos

1.

```julia
barrier_method(f7,x7,g7,quasi_newton_BFGS,newton)
```

    (16.000099265018427, [1.0000174453450508, 4.999976082241852, 4.999818012764078, 1.0000252560280707])

```julia
penality_method(f7,x7,[],g7,quasi_newton_BFGS,armijo,p=4)
```

    (15.99973856766942, [0.9999022126381514, 5.000117340918883, 5.000019553691205, 1.0000686947946014])

2.

```julia
barrier_method(f8,x8,g8,gradient_descent,armijo)
```

    (-14.999913487178183, [4.0780811140272565e-6, 2.9999942440262277, 6.448085102265769e-6, 3.9999918511597574])

```julia
penality_method(f8,x8,[],g8,gradient_descent,armijo,tol=1e-9,p=3)
```

    (-15.000000001723823, [-1.62829122674867e-10, 3.0000000001279696, -6.513106214271318e-11, 4.000000000046522])

3.

```julia
barrier_method(f9,x9,g9,(f,x,linear)->gradient_descent(f,x,linear,n_iter=1000),armijo)
```

    (674.1390295538063, [2.465679335714826, 1.9753209346719036, -0.3282248111825475, 4.435084763984302, -0.621121046567633, 0.9520938424796459, 1.6895143166051672])

```julia
penality_method(f9,x9,[],g9,(f,x,linear)->gradient_descent(f,x,linear,n_iter=1000),armijo)
```

    (674.1400600069386, [2.475421589145944, 1.9734934461136917, -0.34341888707112844, 4.438967626657365, -0.6214968094293873, 0.9465688823024578, 1.701683835261642])

#Referências
 $[1]$ **Ademir A.R.** e **Elizabeth W.K.** (2011). *Um Curso De Otimização. Curitiba.*


# Matrix product
> ### $ A_{ij} B_{jk} = (AB)_{ik}$
> ### dummy index
>> ### 모든 term에서 인덱스 치환이 동시에 일어난다, 한 term에서 인덱스변수가 반드시 두번 등장한다.
> ### free index
>> ### 한 term에서 한번만 존재하는 인덱스 변수 이다.

# KroneckerDelta tensor(Unit tensor)
> ## Indentity of tensor
>> ## $\begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}$
>> ### $\delta_{ij} \begin{cases}
1 & i = j \\
0 & i \neq j \\
\end{cases} $
>> ### $ \delta_{ij} = \delta_{ji} $
>> ### $ \delta_{jj} = \sum_{j=1}^{n=3}\delta_{jj} = \delta_{11} + \delta_{22} + \delta_{33} = 3$
>> ### $ \delta_{ij}\delta_{jk}
= \sum_{j=1}^{n=3}\delta_{ij}\delta_{jk}
= \delta_{i1}\delta_{1k} + \delta_{i2}\delta_{2k} + \delta_{i3}\delta_{3k}
= \delta_{ik}$
>> ### $
\delta_{ij}v_{j} = \sum_{j=1}^{n=3}\delta_{ij}v_{j} = \delta_{i1}v_{1} + \delta_{i2}v_{2} + \delta_{i3}v_{3}\\
\begin{cases}
i =  1 & \delta_{11}v_{1} + \delta_{12}v_{2} + \delta_{13}v_{3}  = v_{1} \\
i =  2 & \delta_{21}v_{1} + \delta_{22}v_{2} + \delta_{23}v_{3}  = v_{2} \\
i =  3 & \delta_{31}v_{1} + \delta_{32}v_{2} + \delta_{33}v_{3}  = v_{3} \\
\therefore v_{i}
\end{cases}$

>> ### $
\delta_{ij}M_{jk} = \sum_{j=1}^{n=3}\delta_{ij}M_{jk} = \delta_{i1}M_{1k} + \delta_{i2}M_{2k} + \delta_{i3}M_{3k}\\
\begin{cases}
i =  1 & \delta_{11}M_{1k} + \delta_{12}M_{2k} + \delta_{13}M_{3k}  = M_{1k} \\
i =  2 & \delta_{21}M_{1k} + \delta_{22}M_{2k} + \delta_{23}M_{3k}  = M_{2k} \\
i =  3 & \delta_{31}M_{1k} + \delta_{32}M_{2k} + \delta_{33}M_{3k}  = M_{3k} \\
\therefore M_{ik}
\end{cases}$

---
> # $$\vec{a} \cdot  \vec{b}
= \sum_{i=1}^{3}\sum_{j=1}^{3}\delta_{ij}A^{i}B^{j}
= \delta_{ij}A^{i}B^{j}
$$

```python
# KroneckerDelta tensor = unit tensor
import sympy as sm
import sympy.vector
sm.KroneckerDelta(i,i+1)
sm.KroneckerDelta(i,i)
B = sm.vector.CoordSys3D('B')
a = 2*B.i + 3*B.j + B.k
A = a.to_matrix(B)
b = B.i + 2*B.j + 3*B.k
B= b.to_matrix(B)
sm.Sum(sm.IndexedBase('a')[sm.symbols('i',cls=sm.Idx)],(i,1,2))
```

$\displaystyle \sum_{Idx\left(i\right)=1}^{2} {a}_{Idx\left(i\right)}$

# LeviCiviata tensor (permutaion symbol tensor)
> ### epsilon tensor
> ### altenative tensor
> ### $ \epsilon_{ijk} \begin{cases}
0 & i = j \text{ or } j=k \text{ or } k=j \\
1 & (i,j,k) = (1,2,3),(2,3,1),(3,1,2) \\
-1 & (i,j,k) = (1,3,2),(2,1,3),(3,2,1) \\
\end{cases}$
> ### $
(\vec{a} \times \vec{b})_{i} = \epsilon_{ijk}a_{j}b_{k}
$
> ### determinent
>> ### $
\begin{align}
\begin{vmatrix}
a_1 & a_2 & a_3 \\
b_1 & b_2 & b_3 \\
c_1 & c_2 & c_3 \\
\end{vmatrix}
&= a_1b_2c_3 + a_2b_3c_1 + a_3b_1c_2 - a_1b_3c_2 - a_2b_1c_3 - a_3b_2c_1
= \sum_{i=1}^{3}\sum_{j=1}^{3}\sum_{k=1}^{3}\epsilon_{ijk}a_{i}b_{j}c_{k}
\end{align}
$
> ### cross product
>> ### $
\begin{align}
\begin{vmatrix}
e_{1} & e_{2} & e_{3} \\
A_{x_1} & A_{x_2} & A_{x_3} \\
B_{x_1} & B_{x_2} & B_{x_3} \\
\end{vmatrix}
&= e_1A_{x_2}B_{x_3} + e_2A_{x_3}B_{x_1} + e_3A_{x_1}B_{x_2} - e_1A_{x_3}B_{x_2} - e_2A_{x_1}B_{x_3} - e_3A_{x_2}B_{x_1}
= \sum_{i=1}^{3}\sum_{j=1}^{3}\sum_{k=1}^{3}\epsilon_{ijk}e_{i}A_{x_{j}}B_{x_{k}}
\end{align}
$

---
> $$
\begin{align}
\vec{A} \times \vec{B} =
\begin{vmatrix}
e_{1} & e_{2} & e_{3} \\
A^1 & A^2 & A^3 \\
B^1 & B^2 & B^3 \\
\end{vmatrix}
&=
\begin{vmatrix}
A^1 & A^2 & A^3 \\
B^1 & B^2 & B^3 \\
e_{1} & e_{2} & e_{3} \\
\end{vmatrix}
= -
\begin{vmatrix}
A^1 & A^2 & A^3 \\
e_{1} & e_{2} & e_{3} \\
B^1 & B^2 & B^3 \\
\end{vmatrix} \\
&= e_1 A^2 B^3 + e_2 A^3 B^1 + e_3 A^1 B^2 - e_1 A^3 B^2 - e_2 A^1 B^3 - e_3 A^2 B^1
\\ &= \sum_{i=1}^{3} \sum_{j=1}^{3} \sum_{k=1}^{3} \epsilon_{ijk} e_{i} A^{j} B^{k}
\\ &= \epsilon_{ijk} e_{i} A^{j} B^{k}
\\ &= \epsilon_{ijk} A^{i} B^{j} e_{k}
\end{align}
$$

---
> ## $
\begin{align}
\big(\vec{a} \times \vec{b}\big) \cdot \vec{c}
&= \epsilon_{ijk} e_{i} A^{j} B^{k} \cdot \vec{C}
\\ &= \epsilon_{ijk} A^{i} B^{j} e_{k} \cdot \vec{C}
\\ &= \epsilon_{ijk} A^{i} B^{j} (e_{k} \cdot C^{l}e_{l})
\\ &= \epsilon_{ijk} A^{i} B^{j} (e_{k} \cdot e_{l})C^{l}
\\ &= \epsilon_{ijk} A^{i} B^{j} \delta_{kl}C^{l}
\\ &= \epsilon_{ijk} A^{i} B^{j} C^{k}
\\ \therefore & \text{ det}\begin{bmatrix}A^i \\ B^i \\ C^i \end{bmatrix}
\\ \therefore & \text{ The volumn of } \vec{a},\vec{b},\vec{c}
\end{align}
$

```python
# LeviCivita
sm.LeviCivita(i,j,k)
sm.LeviCivita(i,j,j)
sm.LeviCivita(j,i,k)
sm.Eijk(i,j,k)
```

$\displaystyle \varepsilon_{i j k}$

```python
# DirecDelta
sm.DiracDelta(1)
sm.DiracDelta(-1)
sm.DiracDelta(0)
sm.diff(sm.DiracDelta(x))
sm.DiracDelta(x)
```

$\displaystyle \delta\left(x\right)$

```python
# Heaviside

sm.Heaviside(-1)
sm.Heaviside(1)
sm.Heaviside(0)
sm.diff(sm.Heaviside(x))
sm.Heaviside(x)
```

$\displaystyle \theta\left(x\right)$

```python

```


###### Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c) 2019 Daniel Koehn, based on (c)2018 L.A. Barba, G.F. Forsyth [CFD Python](https://github.com/barbagroup/CFDPython#cfd-python), (c)2014 L.A. Barba, I. Hawke, B. Knaepen [Practical Numerical Methods with Python](https://github.com/numerical-mooc/numerical-mooc#practical-numerical-methods-with-python), also under CC-BY.

```python
from IPython.core.display import HTML
css_file = '../style/custom.css'
HTML(open(css_file, 'r').read())
```

<link href="https://fonts.googleapis.com/css?family=Merriweather:300,300i,400,400i,700,700i,900,900i" rel='stylesheet' >
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i,700,700i" rel='stylesheet' >
<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:300,400' rel='stylesheet' >
<style>

@font-face {
    font-family: "Computer Modern";
    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');
}

#notebook_panel { /* main background */
    background: rgb(245,245,245);
}

div.cell { /* set cell width */
    width: 800px;
}

div #notebook { /* centre the content */
    background: #fff; /* white background for content */
    width: 1000px;
    margin: auto;
    padding-left: 0em;
}

#notebook li { /* More space between bullet points */
margin-top:0.5em;
}

/* draw border around running cells */
div.cell.border-box-sizing.code_cell.running {
    border: 1px solid #111;
}

/* Put a solid color box around each cell and its output, visually linking them*/
div.cell.code_cell {
    background-color: rgb(256,256,256);
    border-radius: 0px;
    padding: 0.5em;
    margin-left:1em;
    margin-top: 1em;
}

div.text_cell_render{
    font-family: 'Source Sans Pro', sans-serif;
    line-height: 140%;
    font-size: 110%;
    width:680px;
    margin-left:auto;
    margin-right:auto;
}

/* Formatting for header cells */
.text_cell_render h1 {
    font-family: 'Merriweather', serif;
    font-style:regular;
    font-weight: bold;
    font-size: 250%;
    line-height: 100%;
    color: #004065;
    margin-bottom: 1em;
    margin-top: 0.5em;
    display: block;
}
.text_cell_render h2 {
    font-family: 'Merriweather', serif;
    font-weight: bold;
    font-size: 180%;
    line-height: 100%;
    color: #0096d6;
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}

.text_cell_render h3 {
    font-family: 'Merriweather', serif;
	font-size: 150%;
    margin-top:12px;
    margin-bottom: 3px;
    font-style: regular;
    color: #008367;
}

.text_cell_render h4 {    /*Use this for captions*/
    font-family: 'Merriweather', serif;
    font-weight: 300;
    font-size: 100%;
    line-height: 120%;
    text-align: left;
    width:500px;
    margin-top: 1em;
    margin-bottom: 2em;
    margin-left: 80pt;
    font-style: regular;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-family: 'Source Sans Pro', sans-serif;
    font-weight: regular;
    font-size: 130%;
    color: #e31937;
    font-style: italic;
    margin-bottom: .5em;
    margin-top: 1em;
    display: block;
}

.text_cell_render h6 { /*use this for copyright note*/
    font-family: 'Source Code Pro', sans-serif;
    font-weight: 300;
    font-size: 9pt;
    line-height: 100%;
    color: grey;
    margin-bottom: 1px;
    margin-top: 1px;
}

    .CodeMirror{
            font-family: "Source Code Pro";
			font-size: 90%;
    }
/*    .prompt{
        display: None;
    }*/

    .warning{
        color: rgb( 240, 20, 20 )
        }
</style>

# 2D Navier–Stokes: Cavity Flow

In this lecture, we discuss the basics of solving the 2D Navier-Stokes equations for numerical fluid flow modelling. After covering the basic governing equations and finite-difference based solvers, a simple cavity flow problem is solved.

## Governing Equations

The governing equations for fluid flow in an incompressible medium consist of the **conservation of mass (continuity)** equation

$$\vec{\nabla} \cdot  \vec{v} = 0$$

and the **conservation of momentum equation** in vector form for a velocity field $\vec{v}$

$$\frac{\partial \vec{v}}{\partial t}+(\vec{v}\cdot\nabla)\vec{v}=-\frac{1}{\rho}\nabla p + \nu \nabla^2\vec{v}$$

This represents three scalar equations, one for each velocity component $(u,v,w)$. But we will solve it only in two dimensions, so there will be two scalar equations.

In order to solve these equations, a relation between the pressure and velocity field is required. This can be derived by assuming that the continuity equation acts as constraint to the velocity fields computed by the momentum equation.

Writing the equations in component form leads to

\begin{equation}
\frac{\partial u}{\partial x} + \frac{\partial v}{\partial y} = 0 \tag{1}
\end{equation}

\begin{equation}
\frac{\partial u}{\partial t}+u\frac{\partial u}{\partial x}+v\frac{\partial u}{\partial y} = -\frac{1}{\rho}\frac{\partial p}{\partial x}+\nu \left(\frac{\partial^2 u}{\partial x^2}+\frac{\partial^2 u}{\partial y^2} \right) \tag{2}
\end{equation}

\begin{equation}
\frac{\partial v}{\partial t}+u\frac{\partial v}{\partial x}+v\frac{\partial v}{\partial y} = -\frac{1}{\rho}\frac{\partial p}{\partial y}+\nu\left(\frac{\partial^2 v}{\partial x^2}+\frac{\partial^2 v}{\partial y^2}\right) \tag{3}
\end{equation}

By apply $\frac{\partial}{\partial x}$ to eq. (2) and $\frac{\partial}{\partial y}$ to eq. (3), adding the resulting equations and using the continuity eq. (1) leads to a **2D Poisson equation for the pressure field**

\begin{equation}
\frac{\partial^2 p}{\partial x^2}+\frac{\partial^2 p}{\partial y^2} = -\rho\left(\frac{\partial u}{\partial x}\frac{\partial u}{\partial x}+2\frac{\partial u}{\partial y}\frac{\partial v}{\partial x}+\frac{\partial v}{\partial y}\frac{\partial v}{\partial y} \right) \tag{4}
\end{equation}

A step-by-step derivation is shown in **Video Lesson 11** of the **Computational Fluid Dynamics Course** by Prof. Lorena Barba:

```python
from IPython.display import YouTubeVideo
YouTubeVideo('ZjfxA3qq2Lg')
```

## Cavity Flow with Navier–Stokes

Here is the system of differential equations: two equations for the velocity components $u,v$ and one equation for pressure:

$$\frac{\partial u}{\partial t}+u\frac{\partial u}{\partial x}+v\frac{\partial u}{\partial y} = -\frac{1}{\rho}\frac{\partial p}{\partial x}+\nu \left(\frac{\partial^2 u}{\partial x^2}+\frac{\partial^2 u}{\partial y^2} \right) $$

$$\frac{\partial v}{\partial t}+u\frac{\partial v}{\partial x}+v\frac{\partial v}{\partial y} = -\frac{1}{\rho}\frac{\partial p}{\partial y}+\nu\left(\frac{\partial^2 v}{\partial x^2}+\frac{\partial^2 v}{\partial y^2}\right) $$

$$\frac{\partial^2 p}{\partial x^2}+\frac{\partial^2 p}{\partial y^2} = -\rho\left(\frac{\partial u}{\partial x}\frac{\partial u}{\partial x}+2\frac{\partial u}{\partial y}\frac{\partial v}{\partial x}+\frac{\partial v}{\partial y}\frac{\partial v}{\partial y} \right)$$

By looking more closely, we see that the governing equation consists of multiple smaller problems, which we already covered in previous notebooks.

- 2D non-linear advection problems discussed in the linear form in [this notebook](https://nbviewer.jupyter.org/github/daniel-koehn/Differential-equations-earth-system/blob/master/08_Convection_2D/02_2D_Linear_Advection.ipynb)

$$\frac{\partial u}{\partial t}+u\frac{\partial u}{\partial x}+v\frac{\partial u}{\partial y} = 0 $$

$$\frac{\partial v}{\partial t}+u\frac{\partial v}{\partial x}+v\frac{\partial v}{\partial y} = 0 $$

- 2D diffusion-type problems discussed in [this lecture](https://github.com/daniel-koehn/Differential-equations-earth-system/tree/master/06_Heat_2D#differential-equations-in-earth-sciences-2d-heat-equation)

$$\frac{\partial u}{\partial t} = \nu \left(\frac{\partial^2 u}{\partial x^2}+\frac{\partial^2 u}{\partial y^2} \right) $$

$$\frac{\partial v}{\partial t} = \nu\left(\frac{\partial^2 v}{\partial x^2}+\frac{\partial^2 v}{\partial y^2}\right) $$

- 2D Poisson problem discussed in [this lecture](https://github.com/daniel-koehn/Differential-equations-earth-system/tree/master/07_BVP_2D#differential-equations-in-earth-sciences-2d-boundary-value-problems)

$$\frac{\partial^2 p}{\partial x^2}+\frac{\partial^2 p}{\partial y^2} = -\rho\left(\frac{\partial u}{\partial x}\frac{\partial u}{\partial x}+2\frac{\partial u}{\partial y}\frac{\partial v}{\partial x}+\frac{\partial v}{\partial y}\frac{\partial v}{\partial y} \right)$$

Additionally, we have pressure gradient terms in the momentum equations $-\frac{1}{\rho}\frac{\partial p}{\partial x}$ and $-\frac{1}{\rho}\frac{\partial p}{\partial y}$.

So, while the whole problem seems to be quite complex at first glimpse, it consists of multiple smaller, well known sub-problems. In the next step, we have to discretize these equations using the finite-difference approach.

### Discretized equations

We try to keep the codes simple, by using forward operators for the time-derivatives, central operators for the spatial derivatives, except for the advection terms, where backward operators are applied [(see this notebook)](https://nbviewer.jupyter.org/github/daniel-koehn/Differential-equations-earth-system/blob/master/04_Advection_1D/03_Numerical_Diffusion.ipynb)

First, let's discretize the $u$-momentum equation, as follows:

$$
\begin{split}
& \frac{u_{i,j}^{n+1}-u_{i,j}^{n}}{\Delta t}+u_{i,j}^{n}\frac{u_{i,j}^{n}-u_{i-1,j}^{n}}{\Delta x}+v_{i,j}^{n}\frac{u_{i,j}^{n}-u_{i,j-1}^{n}}{\Delta y} = \\
& \qquad -\frac{1}{\rho}\frac{p_{i+1,j}^{n}-p_{i-1,j}^{n}}{2\Delta x}+\nu\left(\frac{u_{i+1,j}^{n}-2u_{i,j}^{n}+u_{i-1,j}^{n}}{\Delta x^2}+\frac{u_{i,j+1}^{n}-2u_{i,j}^{n}+u_{i,j-1}^{n}}{\Delta y^2}\right)
\end{split}
$$

Similarly for the $v$-momentum equation:

$$
\begin{split}
&\frac{v_{i,j}^{n+1}-v_{i,j}^{n}}{\Delta t}+u_{i,j}^{n}\frac{v_{i,j}^{n}-v_{i-1,j}^{n}}{\Delta x}+v_{i,j}^{n}\frac{v_{i,j}^{n}-v_{i,j-1}^{n}}{\Delta y} = \\
& \qquad -\frac{1}{\rho}\frac{p_{i,j+1}^{n}-p_{i,j-1}^{n}}{2\Delta y}
+\nu\left(\frac{v_{i+1,j}^{n}-2v_{i,j}^{n}+v_{i-1,j}^{n}}{\Delta x^2}+\frac{v_{i,j+1}^{n}-2v_{i,j}^{n}+v_{i,j-1}^{n}}{\Delta y^2}\right)
\end{split}
$$

Finally, the discretized pressure-Poisson equation can be written thus:

$$
\begin{split}
& \frac{p_{i+1,j}^{n}-2p_{i,j}^{n}+p_{i-1,j}^{n}}{\Delta x^2}+\frac{p_{i,j+1}^{n}-2p_{i,j}^{n}+p_{i,j-1}^{n}}{\Delta y^2} = \\
& \qquad \rho \left[ \frac{1}{\Delta t}\left(\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x}+\frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\right) -\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x}\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x} - 2\frac{u_{i,j+1}-u_{i,j-1}}{2\Delta y}\frac{v_{i+1,j}-v_{i-1,j}}{2\Delta x} - \frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\right]
\end{split}
$$

You should write these equations down on your own notes, by hand, following each term mentally as you write it.

As before, let's rearrange the equations in the way that the iterations need to proceed in the code. First, the momentum equations for the velocity at the next time step.

The momentum equation in the $u$ direction:

$$
\begin{split}
u_{i,j}^{n+1} = u_{i,j}^{n} & - u_{i,j}^{n} \frac{\Delta t}{\Delta x} \left(u_{i,j}^{n}-u_{i-1,j}^{n}\right) - v_{i,j}^{n} \frac{\Delta t}{\Delta y} \left(u_{i,j}^{n}-u_{i,j-1}^{n}\right) \\
& - \frac{\Delta t}{\rho 2\Delta x} \left(p_{i+1,j}^{n}-p_{i-1,j}^{n}\right) \\
& + \nu \left(\frac{\Delta t}{\Delta x^2} \left(u_{i+1,j}^{n}-2u_{i,j}^{n}+u_{i-1,j}^{n}\right) + \frac{\Delta t}{\Delta y^2} \left(u_{i,j+1}^{n}-2u_{i,j}^{n}+u_{i,j-1}^{n}\right)\right)
\end{split}
$$

The momentum equation in the $v$ direction:

$$
\begin{split}
v_{i,j}^{n+1} = v_{i,j}^{n} & - u_{i,j}^{n} \frac{\Delta t}{\Delta x} \left(v_{i,j}^{n}-v_{i-1,j}^{n}\right) - v_{i,j}^{n} \frac{\Delta t}{\Delta y} \left(v_{i,j}^{n}-v_{i,j-1}^{n})\right) \\
& - \frac{\Delta t}{\rho 2\Delta y} \left(p_{i,j+1}^{n}-p_{i,j-1}^{n}\right) \\
& + \nu \left(\frac{\Delta t}{\Delta x^2} \left(v_{i+1,j}^{n}-2v_{i,j}^{n}+v_{i-1,j}^{n}\right) + \frac{\Delta t}{\Delta y^2} \left(v_{i,j+1}^{n}-2v_{i,j}^{n}+v_{i,j-1}^{n}\right)\right)
\end{split}
$$

Almost there! Now, we rearrange the pressure-Poisson equation:

$$
\begin{split}
p_{i,j}^{n} = & \frac{\left(p_{i+1,j}^{n}+p_{i-1,j}^{n}\right) \Delta y^2 + \left(p_{i,j+1}^{n}+p_{i,j-1}^{n}\right) \Delta x^2}{2\left(\Delta x^2+\Delta y^2\right)} \\
& -\frac{\rho\Delta x^2\Delta y^2}{2\left(\Delta x^2+\Delta y^2\right)} \\
& \times \left[\frac{1}{\Delta t}\left(\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x}+\frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\right)-\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x}\frac{u_{i+1,j}-u_{i-1,j}}{2\Delta x} -2\frac{u_{i,j+1}-u_{i,j-1}}{2\Delta y}\frac{v_{i+1,j}-v_{i-1,j}}{2\Delta x}-\frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\frac{v_{i,j+1}-v_{i,j-1}}{2\Delta y}\right]
\end{split}
$$

In order to test the 2D Navier-Stokes FD code, we want to solve a common benchmark problem for numerical fluid dynamics problems, the **lid-driven cavity problem**

governed by the following initial and boundary conditions.

The initial condition is $u, v, p = 0$ everywhere, and the boundary conditions are:

$u=1$ at $y=2$ (the "lid");

$u, v=0$ on the other boundaries;

$\frac{\partial p}{\partial y}=0$ at $y=0$;

$p=0$ at $y=2$

$\frac{\partial p}{\partial x}=0$ at $x=0,2$

Implementing Cavity Flow
----

```python
import numpy
from matplotlib import pyplot, cm
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

# import JIT from Numba
from numba import jit
```

```python
nx = 81
ny = 81
nt = 500
nit = 50
c = 1
dx = 2 / (nx - 1)
dy = 2 / (ny - 1)
x = numpy.linspace(0, 2, nx)
y = numpy.linspace(0, 2, ny)
X, Y = numpy.meshgrid(x, y)

rho = 1
nu = .1
dt = .001

u = numpy.zeros((ny, nx))
v = numpy.zeros((ny, nx))
p = numpy.zeros((ny, nx))
b = numpy.zeros((ny, nx))
```

The pressure Poisson equation that's written above can be hard to write out without typos.  The function `build_up_b` below represents the contents of the square brackets, so that the entirety of the Pressure Poisson Equation (PPE) is slightly more manageable.

```python
@jit(nopython=True) # use Just-In-Time (JIT) Compilation for C-performance
def build_up_b(b, rho, dt, u, v, dx, dy):

    ny, nx = b.shape

    # loop over spatial grid
    for i in range(1,nx-1):
        for j in range(1,ny-1):

            b[j, i] = (rho * (1 / dt *
                    ((u[j, i+1] - u[j, i-1]) /
                     (2 * dx) + (v[j+1, i] - v[j-1, i]) / (2 * dy)) -
                    ((u[j, i+1] - u[j, i-1]) / (2 * dx))**2 -
                      2 * ((u[j+1, i] - u[j-1, i]) / (2 * dy) *
                           (v[j, i+1] - v[j, i-1]) / (2 * dx))-
                          ((v[j+1, i] - v[j-1, i]) / (2 * dy))**2))

    return b
```

The function `pressure_poisson` is also defined to help segregate the different rounds of calculations.  Note the presence of the pseudo-time variable `nit`.  This sub-iteration in the Poisson calculation helps ensure a divergence-free field.

```python
@jit(nopython=True) # use Just-In-Time (JIT) Compilation for C-performance
def pressure_poisson(p, dx, dy, b):

    # Solve Pressure Poisson Equation using Gauss-Seidel method
    for q in range(nit):

        # loop over spatial grid
        for i in range(1,nx-1):
            for j in range(1,ny-1):

                p[j, i] = (((p[j, i+1] + p[j, i-1]) * dy**2 +
                            (p[j+1, i] + p[j-1, i]) * dx**2) /
                            (2 * (dx**2 + dy**2)) -
                            dx**2 * dy**2 / (2 * (dx**2 + dy**2)) *
                            b[j,i])

        # Boundary conditions
        p[:, -1] = p[:, -2] # dp/dx = 0 at x = 2
        p[0, :] = p[1, :]   # dp/dy = 0 at y = 0
        p[:, 0] = p[:, 1]   # dp/dx = 0 at x = 0
        p[-1, :] = 0        # p = 0 at y = 2

    return p
```

Finally, the rest of the cavity flow equations are wrapped inside the function `cavity_flow`, allowing us to easily plot the results of the cavity flow solver for different lengths of time.

```python
@jit(nopython=True) # use Just-In-Time (JIT) Compilation for C-performance
def cavity_flow(nt, u, v, dt, dx, dy, p, rho, nu):

    un = numpy.empty_like(u)
    vn = numpy.empty_like(v)
    b = numpy.zeros((ny, nx))

    for n in range(nt):

        un = u.copy()
        vn = v.copy()

        # solve Poisson equation to update pressure field
        b = build_up_b(b, rho, dt, u, v, dx, dy)
        p = pressure_poisson(p, dx, dy, b)

        # update velocity components
        for i in range(1,nx-1):
            for j in range(1,ny-1):

                u[j, i] = (un[j, i]-
                                 un[j, i] * dt / dx *
                                (un[j, i] - un[j, i-1]) -
                                 vn[j, i] * dt / dy *
                                (un[j, i] - un[j-1, i]) -
                                 dt / (2 * rho * dx) * (p[j, i+1] - p[j, i-1]) +
                                 nu * (dt / dx**2 *
                                (un[j, i+1] - 2 * un[j, i] + un[j, i-1]) +
                                 dt / dy**2 *
                                (un[j+1, i] - 2 * un[j, i] + un[j-1, i])))

                v[j, i] = (vn[j, i] -
                                un[j, i] * dt / dx *
                               (vn[j, i] - vn[j, i-1]) -
                                vn[j, i] * dt / dy *
                               (vn[j, i] - vn[j-1, i]) -
                                dt / (2 * rho * dy) * (p[j+1, i] - p[j-1, i]) +
                                nu * (dt / dx**2 *
                               (vn[j, i+1] - 2 * vn[j, i] + vn[j, i-1]) +
                                dt / dy**2 *
                               (vn[j+1, i] - 2 * vn[j, i] + vn[j-1, i])))

        # apply boundary conditions
        u[0, :]  = 0
        u[:, 0]  = 0
        u[:, -1] = 0
        u[-1, :] = 1    # set velocity on cavity lid equal to 1
        v[0, :]  = 0
        v[-1, :] = 0
        v[:, 0]  = 0
        v[:, -1] = 0

    return u, v, p
```

Let's start with `nt = 100` and see what the solver gives us:

```python
u = numpy.zeros((ny, nx))
v = numpy.zeros((ny, nx))
p = numpy.zeros((ny, nx))
b = numpy.zeros((ny, nx))
nt = 100
u, v, p = cavity_flow(nt, u, v, dt, dx, dy, p, rho, nu)
```

```python
fig = pyplot.figure(figsize=(11,7), dpi=100)

extent = [numpy.min(X), numpy.max(X),numpy.min(Y), numpy.max(Y)]
cmap = 'seismic'
im = pyplot.imshow(numpy.flipud(p), extent=extent, interpolation='spline36', cmap=cmap, vmin=-2, vmax=2)
cbar = pyplot.colorbar(im)
cbar.set_label('Pressure [Pa]')

# plotting velocity field
pyplot.quiver(X[::2, ::2], Y[::2, ::2], u[::2, ::2], v[::2, ::2])
pyplot.xlabel('X')
pyplot.ylabel('Y');
```

You can see that two distinct pressure zones are forming and that the spiral pattern expected from lid-driven cavity flow is beginning to form.  Experiment with different values of `nt` to see how long the system takes to stabilize.

```python
u = numpy.zeros((ny, nx))
v = numpy.zeros((ny, nx))
p = numpy.zeros((ny, nx))
b = numpy.zeros((ny, nx))
nt = 700
u, v, p = cavity_flow(nt, u, v, dt, dx, dy, p, rho, nu)
```

```python
fig = pyplot.figure(figsize=(11,7), dpi=100)

extent = [numpy.min(X), numpy.max(X),numpy.min(Y), numpy.max(Y)]
cmap = 'seismic'
im = pyplot.imshow(numpy.flipud(p), extent=extent, interpolation='spline36', cmap=cmap, vmin=-2, vmax=2)
cbar = pyplot.colorbar(im)
cbar.set_label('Pressure [Pa]')

# plotting velocity field
pyplot.quiver(X[::2, ::2], Y[::2, ::2], u[::2, ::2], v[::2, ::2])
pyplot.xlabel('X')
pyplot.ylabel('Y');
```

The quiver plot shows the magnitude of the velocity at the discrete points in the mesh grid we created.
(We're actually only showing half of the points because otherwise it's a bit of a mess.  The `X[::2, ::2]` syntax above is a convenient way to ask for every other point.)

Another way to visualize the flow in the cavity is to use a `streamplot`:

```python
fig = pyplot.figure(figsize=(11, 7), dpi=100)

extent = [numpy.min(X), numpy.max(X),numpy.min(Y), numpy.max(Y)]
cmap = 'seismic'
im = pyplot.imshow(numpy.flipud(p), extent=extent, interpolation='spline36', cmap=cmap, vmin=-2, vmax=2)
cbar = pyplot.colorbar(im)
cbar.set_label('Pressure [Pa]')

pyplot.streamplot(X, Y, u, v, linewidth=1, color='k')
pyplot.xlabel('X')
pyplot.ylabel('Y');
```

## Learn More

The interactive module [**12 steps to Navier–Stokes**](https://github.com/barbagroup/CFDPython) is one of several components of the [Computational Fluid Dynamics class taught by Prof. Lorena A. Barba](https://www.youtube.com/playlist?list=PL30F4C5ABCE62CB61) in Boston University between 2009 and 2013.

For a sample of what the other components of this class are, you can explore the **Resources** section of the Spring 2013 version of [the course's Piazza site](https://piazza.com/bu/spring2013/me702/resources).

***


```python
from typing import List, Dict
from sympy import Point, Point2D, Segment
import matplotlib.pyplot as plt
from collections import defaultdict
from itertools import combinations
import numpy as np
# Load data
txt_lines = open("input.txt").read().splitlines()
```

# Visualization
Horizontal and vertical lines:

```python
def str_to_point(p_str) -> Point:
    parts = p_str.split(",")
    return Point(int(parts[0]), int(parts[1]))
lines = [Segment(str_to_point(l.split(" -> ")[0]), str_to_point(l.split(" -> ")[1])) for l in txt_lines]

for l in [l for l in lines if l.p1.x == l.p2.x or l.p1.y == l.p2.y]:
    plt.plot([p.x for p in l.points], [p.y for p in l.points])
plt.xticks(range(0,1000,100))
plt.yticks(range(0,1000,100))
plt.grid()

```

```python
for l in [l for l in lines]:
    plt.plot([p.x for p in l.points], [p.y for p in l.points])
plt.xticks(range(0,1000,100))
plt.yticks(range(0,1000,100))
plt.grid()
```

All lines:

## Part 1 (slow)
> Consider only horizontal and vertical lines. At how many points do at least two lines overlap?
**Attention: Incredible slow!**

```python
intersections: Dict[Point2D, int] = defaultdict(int)
filtered_lines = [l for l in lines if l.p1.x == l.p2.x or l.p1.y == l.p2.y]
combs = list(combinations(filtered_lines, r=2))
i = 0
for l_pair in combs:
    i += 1
    if i % int(len(combs) / 20) == 0:
        print (f"{(i/(len(combs) / 100))} %")
    p = next(iter(l_pair[0].intersection(l_pair[1])), None)
    if p:
        if issubclass(type(p), Point):
                intersections[p] += 1
        elif issubclass(type(p), Segment):
            if p.p1.x == p.p2.x:
                for y in range(min(p.p1.y, p.p2.y), max(p.p1.y, p.p2.y)+1, 1):
                    intersections[Point(p.p1.x, y)] += 1
            else:
                for x in range(min(p.p1.x, p.p2.x), max(p.p1.x, p.p2.x)+1, 1):
                    intersections[Point(x, p.p1.y)] += 1

result = len(intersections)
print(result)
```

    4.999454009391038 %
    9.998908018782076 %
    14.998362028173114 %
    19.997816037564153 %
    24.99727004695519 %
    29.996724056346228 %
    34.99617806573727 %
    39.995632075128306 %
    44.99508608451934 %
    49.99454009391038 %
    54.99399410330142 %
    59.993448112692455 %
    64.99290212208349 %
    69.99235613147454 %
    74.99181014086557 %
    79.99126415025661 %
    84.99071815964764 %
    89.99017216903869 %
    94.98962617842973 %
    99.98908018782076 %
    4421

## Part 1 & 2 (fast)
> Consider only horizontal and vertical lines. At how many points do at least two lines overlap?

```python
lines = [[int(z) for z in x.replace(" -> ", ",").split(",")] for x in txt_lines]
mat_1 = np.zeros((1000,1000))
mat_2 = np.zeros((1000,1000))

for x1, y1, x2, y2 in lines:
    if x1 == x2:
        mat_1[min(y1,y2):max(y1,y2)+1,x1] += 1
    elif y1 == y2:
        mat_1[y1,min(x1,x2):max(x1,x2)+1] += 1
    else:
        l = [x1,y1,x2,y2] if x1 < x2 else [x2,y2,x1,y1]
        modi = 1 if l[1] < l[3] else -1
        for x in range(l[0],l[2]+1):
            y = modi * (x-l[0]) + l[1]
            mat_2[y,x] += 1

result_1 = np.count_nonzero(mat_1 > 1)
result_2 = np.count_nonzero(mat_1+mat_2 > 1)
print(f"Part 1: {result_1}, Part 2: {result_2}")
```

    Part 1: 4421, Part 2: 18674


```python
import sympy as sp
from sympy import *
from sympy.abc import *
```

```python
datapath= "C:\\Users\\i053131\\AnacondaProjects\\SAT illustrations\\"
```

```python
def symbol_init(x, count=0):
    def new_symbol ():
        nonlocal count
        count += 1
        return var(str(x) + str(count)) #var add the new symbol in the name space
    return new_symbol
```

```python
def read_literal(literal, name="x"):
    lit = str(literal)
    if lit == '':
        "error literal string cannot be null"
    elif lit[0] == "-":
        return Not(var(str(name) + str(lit[1:])))
    elif lit=='0':
        return false
    else:
        return var(str(name) + str(lit))

```

```python
def read_cnf(file):
    #read CNF in dima
    cnf = And()
    separator = ' '
    for line in open(file):
        clause_args = []
        line = line.split(separator)
        if (len(line) == 1 and line[0]=='\n'): #would be an empry line
            continue
        for i in line:
            if i != '/n':
              literal = read_literal(i.strip())
              clause_args.append(literal) #add literal  in clause
        if clause_args != []:
            cnf = And(cnf, eval("Or" + str(tuple(clause_args))))
    return cnf

```

```python
c1 =read_cnf(datapath + "cnf1.txt")
c1
```

    (x1 | x4) & (x10 | x8) & (x6 | x7) & (x1 | ~x6) & (x1 | ~x7) & (x10 | ~x6) & (x4 | ~x1) & (x6 | ~x3) & (x10 | x4 | x8) & (x4 | x7 | x8) & (~x4 | ~x5) & (x1 | x5 | ~x8) & (x10 | x2 | ~x1) & (x10 | x4 | ~x10) & (x10 | x7 | ~x9) & (x2 | x3 | ~x3) & (x2 | x6 | ~x9) & (x2 | x8 | ~x8) & (x3 | x8 | ~x8) & (x4 | x5 | ~x2) & (x5 | x6 | ~x6) & (x6 | x7 | ~x10) & (x6 | x7 | ~x7) & (x6 | x8 | ~x9) & (x6 | x9 | ~x7) & (x7 | x8 | ~x9) & (x10 | x2 | x7 | x9) & (x10 | ~x10 | ~x2) & (x10 | ~x10 | ~x8) & (x2 | ~x1 | ~x2) & (x3 | ~x10 | ~x7) & (x5 | ~x3 | ~x8) & (x5 | ~x5 | ~x6) & (x7 | ~x1 | ~x10) & (x7 | ~x2 | ~x8) & (x8 | ~x1 | ~x3) & (~x1 | ~x10 | ~x5) & (~x10 | ~x6 | ~x8) & (~x2 | ~x4 | ~x7) & (~x5 | ~x7 | ~x8)

```python
def first_var(cnf):
    if (cnf):
        return cnf
    else:
        clause = cnf.args[0]
        if clause.func == sp.Not:
            return clause.args[0]
        elif clause.func == sp.Symbol:
            return clause
        elif clause.args[0].func == sp.Symbol:
            return clause.args[0]
        elif clause.args[0].func == sp.Not:
            return clause.args[0].args[0]
        else:
            print("badly constructed cnf")

```

```python
first_var(c1)
```

    (x1 | x4) & (x10 | x8) & (x6 | x7) & (x1 | ~x6) & (x1 | ~x7) & (x10 | ~x6) & (x4 | ~x1) & (x6 | ~x3) & (x10 | x4 | x8) & (x4 | x7 | x8) & (~x4 | ~x5) & (x1 | x5 | ~x8) & (x10 | x2 | ~x1) & (x10 | x4 | ~x10) & (x10 | x7 | ~x9) & (x2 | x3 | ~x3) & (x2 | x6 | ~x9) & (x2 | x8 | ~x8) & (x3 | x8 | ~x8) & (x4 | x5 | ~x2) & (x5 | x6 | ~x6) & (x6 | x7 | ~x10) & (x6 | x7 | ~x7) & (x6 | x8 | ~x9) & (x6 | x9 | ~x7) & (x7 | x8 | ~x9) & (x10 | x2 | x7 | x9) & (x10 | ~x10 | ~x2) & (x10 | ~x10 | ~x8) & (x2 | ~x1 | ~x2) & (x3 | ~x10 | ~x7) & (x5 | ~x3 | ~x8) & (x5 | ~x5 | ~x6) & (x7 | ~x1 | ~x10) & (x7 | ~x2 | ~x8) & (x8 | ~x1 | ~x3) & (~x1 | ~x10 | ~x5) & (~x10 | ~x6 | ~x8) & (~x2 | ~x4 | ~x7) & (~x5 | ~x7 | ~x8)

```python
c1
```

    (x1 | x4) & (x10 | x8) & (x6 | x7) & (x1 | ~x6) & (x1 | ~x7) & (x10 | ~x6) & (x4 | ~x1) & (x6 | ~x3) & (x10 | x4 | x8) & (x4 | x7 | x8) & (~x4 | ~x5) & (x1 | x5 | ~x8) & (x10 | x2 | ~x1) & (x10 | x4 | ~x10) & (x10 | x7 | ~x9) & (x2 | x3 | ~x3) & (x2 | x6 | ~x9) & (x2 | x8 | ~x8) & (x3 | x8 | ~x8) & (x4 | x5 | ~x2) & (x5 | x6 | ~x6) & (x6 | x7 | ~x10) & (x6 | x7 | ~x7) & (x6 | x8 | ~x9) & (x6 | x9 | ~x7) & (x7 | x8 | ~x9) & (x10 | x2 | x7 | x9) & (x10 | ~x10 | ~x2) & (x10 | ~x10 | ~x8) & (x2 | ~x1 | ~x2) & (x3 | ~x10 | ~x7) & (x5 | ~x3 | ~x8) & (x5 | ~x5 | ~x6) & (x7 | ~x1 | ~x10) & (x7 | ~x2 | ~x8) & (x8 | ~x1 | ~x3) & (~x1 | ~x10 | ~x5) & (~x10 | ~x6 | ~x8) & (~x2 | ~x4 | ~x7) & (~x5 | ~x7 | ~x8)

```python
def naif(cnf, assigment):
    x = first_var(cnf)
    save_assignement = assignement.copy()
    assignement[x] = True
    tmp = naif(cnf.subs(x, True), assignement)

```

```python
c1.subs(x1, true, x2, false)
```

```python
d= {"a":1, "b": 2}
for i in {"a":1, "b": 2}:
    print(i, d[i])
```

    a 1
    b 2

```python
And(A, B) | C
```

    C | (A & B)

```python
(D+ C)*(A + B)
```

    (A + B)*(C + D)

```python

```


```python
from sympy import symbols
from sympy.plotting import plot
x=symbols('x')
p1=plot(x*x)
p2=plot(x)
p1.append(p2[0])
p1
```

```python
x=symbols('x')
p1=plot(x*x)
p2=plot(x)
p1.extend(p2)
p1
```

```python
plot(x, x**2, x**3, (x, -5, 5))
```

```python
from sympy.geometry import *
t = RegularPolygon(Point(0,0), 1, 5)
```

```python
from sympy.plotting.plot import Plot
p=Plot(axes='label_axes=True')
for i in range(len(t.sides)):
    p[i]=t.sides[i]
p.show
```

    <bound method Plot.show of <sympy.plotting.plot.Plot object at 0x000002270C9A2FD0>>

```python

```


# Reprodução dos resultados do artigo da PHYSICAL REVIEW E 73, 036205 (2006)

```python
from sympy import *
```

```python
x, xn_mais_1, xn_menos_1, dx, ddx, omega2, nu, a, D, delta, epsilon = symbols('x_n, x_{n+1}, x_{n-1}, \dot{x}_n, \ddot{x}_n, omega_n^2, nu, a, D, delta_n, epsilon')
```

Equação (6):

```python
eq = Eq(ddx + omega2*x - nu*(1-x**2)*dx + a*x**3 - D*(x-1/2*(xn_mais_1 + xn_menos_1)), 0)
eq
```

$\displaystyle - D \left(x_{n} - 0.5 x_{n+1} - 0.5 x_{n-1}\right) + \ddot{x}_n - \dot{x}_n \nu \left(1 - x_{n}^{2}\right) + a x_{n}^{3} + \omega^{2}_{n} x_{n} = 0$

Introduzindo parâmetros pequenos escalados por $\epsilon$

```python
eq1 = eq.subs([(omega2, 1 + epsilon*delta),
               (nu, epsilon*nu),
               (a, epsilon*a),
               (D, epsilon*D)
               ])
eq1
```

$\displaystyle - D \epsilon \left(x_{n} - 0.5 x_{n+1} - 0.5 x_{n-1}\right) + \ddot{x}_n - \dot{x}_n \epsilon \nu \left(1 - x_{n}^{2}\right) + a \epsilon x_{n}^{3} + x_{n} \left(\delta_{n} \epsilon + 1\right) = 0$

Soluções perturbativas para $x_n(t)$

```python
x1, x1n_mais_1, x1n_menos_1, dx1, ddx1, t = symbols("x_n^{(1)}, x_{n+1}^{(1)}, x_{n-1}^{(1)}, \dot{x}_n^{(1)}, \ddot{x}_n^{(1)}, t")
```

```python
A, An_mais_1, An_menos_1, Al, A2l, cc = symbols("A_n, A_{n+1}, A_{n-1}, A_n^', A_n^{''}, c.c.")
```

```python
#eq2 = eq1.subs([(x, A*exp(I*t)+cc+epsilon*x1),
#               (xn_mais_1, An_mais_1*exp(I*t)+cc+epsilon*x1n_mais_1),
#               (xn_menos_1, An_menos_1*exp(I*t)+cc+epsilon*x1n_menos_1),
#               (dx, (I*A+epsilon*Al)*exp(I*t)+cc+epsilon*dx1),
#               (ddx, (-A+2*I*epsilon*Al+epsilon**2*A2l)*exp(I*t)+cc+epsilon*ddx1)
#               ])
#eq2
```

```python
eq2 = eq1.subs([(x, A*exp(I*t)+epsilon*x1),
               (xn_mais_1, An_mais_1*exp(I*t)+epsilon*x1n_mais_1),
               (xn_menos_1, An_menos_1*exp(I*t)+epsilon*x1n_menos_1),
               (dx, (I*A+epsilon*Al)*exp(I*t)+epsilon*dx1),
               (ddx, (-A+2*I*epsilon*Al+epsilon**2*A2l)*exp(I*t)+epsilon*ddx1)
               ])
eq2
```

$\displaystyle - D \epsilon \left(A_{n} e^{i t} - 0.5 A_{n+1} e^{i t} - 0.5 A_{n-1} e^{i t} + \epsilon x_n^{(1)} - 0.5 \epsilon x_{n+1}^{(1)} - 0.5 \epsilon x_{n-1}^{(1)}\right) + \ddot{x}_n^{(1)} \epsilon + a \epsilon \left(A_{n} e^{i t} + \epsilon x_n^{(1)}\right)^{3} - \epsilon \nu \left(1 - \left(A_{n} e^{i t} + \epsilon x_n^{(1)}\right)^{2}\right) \left(\dot{x}_n^{(1)} \epsilon + \left(i A_{n} + A^{'}_{n} \epsilon\right) e^{i t}\right) + \left(A_{n} e^{i t} + \epsilon x_n^{(1)}\right) \left(\delta_{n} \epsilon + 1\right) + \left(- A_{n} + 2 i A^{'}_{n} \epsilon + A_n^{''} \epsilon^{2}\right) e^{i t} = 0$

```python
eq3 = eq2.expand()
eq3
```

$\displaystyle A_{n}^{3} a \epsilon e^{3 i t} + i A_{n}^{3} \epsilon \nu e^{3 i t} + A_{n}^{2} A^{'}_{n} \epsilon^{2} \nu e^{3 i t} + A_{n}^{2} \dot{x}_n^{(1)} \epsilon^{2} \nu e^{2 i t} + 3 A_{n}^{2} a \epsilon^{2} x_n^{(1)} e^{2 i t} + 2 i A_{n}^{2} \epsilon^{2} \nu x_n^{(1)} e^{2 i t} + 2 A_{n} A^{'}_{n} \epsilon^{3} \nu x_n^{(1)} e^{2 i t} - A_{n} D \epsilon e^{i t} + 2 A_{n} \dot{x}_n^{(1)} \epsilon^{3} \nu x_n^{(1)} e^{i t} + 3 A_{n} a \epsilon^{3} \left(x_n^{(1)}\right)^{2} e^{i t} + A_{n} \delta_{n} \epsilon e^{i t} + i A_{n} \epsilon^{3} \nu \left(x_n^{(1)}\right)^{2} e^{i t} - i A_{n} \epsilon \nu e^{i t} + A^{'}_{n} \epsilon^{4} \nu \left(x_n^{(1)}\right)^{2} e^{i t} - A^{'}_{n} \epsilon^{2} \nu e^{i t} + 2 i A^{'}_{n} \epsilon e^{i t} + A_n^{''} \epsilon^{2} e^{i t} + 0.5 A_{n+1} D \epsilon e^{i t} + 0.5 A_{n-1} D \epsilon e^{i t} - D \epsilon^{2} x_n^{(1)} + 0.5 D \epsilon^{2} x_{n+1}^{(1)} + 0.5 D \epsilon^{2} x_{n-1}^{(1)} + \ddot{x}_n^{(1)} \epsilon + \dot{x}_n^{(1)} \epsilon^{4} \nu \left(x_n^{(1)}\right)^{2} - \dot{x}_n^{(1)} \epsilon^{2} \nu + a \epsilon^{4} \left(x_n^{(1)}\right)^{3} + \delta_{n} \epsilon^{2} x_n^{(1)} + \epsilon x_n^{(1)} = 0$

```python
expr = eq3.lhs
expr
```

$\displaystyle A_{n}^{3} a \epsilon e^{3 i t} + i A_{n}^{3} \epsilon \nu e^{3 i t} + A_{n}^{2} A^{'}_{n} \epsilon^{2} \nu e^{3 i t} + A_{n}^{2} \dot{x}_n^{(1)} \epsilon^{2} \nu e^{2 i t} + 3 A_{n}^{2} a \epsilon^{2} x_n^{(1)} e^{2 i t} + 2 i A_{n}^{2} \epsilon^{2} \nu x_n^{(1)} e^{2 i t} + 2 A_{n} A^{'}_{n} \epsilon^{3} \nu x_n^{(1)} e^{2 i t} - A_{n} D \epsilon e^{i t} + 2 A_{n} \dot{x}_n^{(1)} \epsilon^{3} \nu x_n^{(1)} e^{i t} + 3 A_{n} a \epsilon^{3} \left(x_n^{(1)}\right)^{2} e^{i t} + A_{n} \delta_{n} \epsilon e^{i t} + i A_{n} \epsilon^{3} \nu \left(x_n^{(1)}\right)^{2} e^{i t} - i A_{n} \epsilon \nu e^{i t} + A^{'}_{n} \epsilon^{4} \nu \left(x_n^{(1)}\right)^{2} e^{i t} - A^{'}_{n} \epsilon^{2} \nu e^{i t} + 2 i A^{'}_{n} \epsilon e^{i t} + A_n^{''} \epsilon^{2} e^{i t} + 0.5 A_{n+1} D \epsilon e^{i t} + 0.5 A_{n-1} D \epsilon e^{i t} - D \epsilon^{2} x_n^{(1)} + 0.5 D \epsilon^{2} x_{n+1}^{(1)} + 0.5 D \epsilon^{2} x_{n-1}^{(1)} + \ddot{x}_n^{(1)} \epsilon + \dot{x}_n^{(1)} \epsilon^{4} \nu \left(x_n^{(1)}\right)^{2} - \dot{x}_n^{(1)} \epsilon^{2} \nu + a \epsilon^{4} \left(x_n^{(1)}\right)^{3} + \delta_{n} \epsilon^{2} x_n^{(1)} + \epsilon x_n^{(1)}$

```python
collected_expr = collect(expr, epsilon)
collected_expr
```

$\displaystyle \epsilon^{4} \left(A^{'}_{n} \nu \left(x_n^{(1)}\right)^{2} e^{i t} + \dot{x}_n^{(1)} \nu \left(x_n^{(1)}\right)^{2} + a \left(x_n^{(1)}\right)^{3}\right) + \epsilon^{3} \left(2 A_{n} A^{'}_{n} \nu x_n^{(1)} e^{2 i t} + 2 A_{n} \dot{x}_n^{(1)} \nu x_n^{(1)} e^{i t} + 3 A_{n} a \left(x_n^{(1)}\right)^{2} e^{i t} + i A_{n} \nu \left(x_n^{(1)}\right)^{2} e^{i t}\right) + \epsilon^{2} \left(A_{n}^{2} A^{'}_{n} \nu e^{3 i t} + A_{n}^{2} \dot{x}_n^{(1)} \nu e^{2 i t} + 3 A_{n}^{2} a x_n^{(1)} e^{2 i t} + 2 i A_{n}^{2} \nu x_n^{(1)} e^{2 i t} - A^{'}_{n} \nu e^{i t} + A_n^{''} e^{i t} - D x_n^{(1)} + 0.5 D x_{n+1}^{(1)} + 0.5 D x_{n-1}^{(1)} - \dot{x}_n^{(1)} \nu + \delta_{n} x_n^{(1)}\right) + \epsilon \left(A_{n}^{3} a e^{3 i t} + i A_{n}^{3} \nu e^{3 i t} - A_{n} D e^{i t} + A_{n} \delta_{n} e^{i t} - i A_{n} \nu e^{i t} + 2 i A^{'}_{n} e^{i t} + 0.5 A_{n+1} D e^{i t} + 0.5 A_{n-1} D e^{i t} + \ddot{x}_n^{(1)} + x_n^{(1)}\right)$

```python
eq4 = collected_expr.coeff(epsilon,1)
eq4
```

$\displaystyle A_{n}^{3} a e^{3 i t} + i A_{n}^{3} \nu e^{3 i t} - A_{n} D e^{i t} + A_{n} \delta_{n} e^{i t} - i A_{n} \nu e^{i t} + 2 i A^{'}_{n} e^{i t} + 0.5 A_{n+1} D e^{i t} + 0.5 A_{n-1} D e^{i t} + \ddot{x}_n^{(1)} + x_n^{(1)}$

Equação (12) do artigo do Cross (2006):

```python
eq5 = eq4.subs(A**3*exp(3*I*t), Abs(A)**2*A*exp(I*t))
eq5
```

$\displaystyle - A_{n} D e^{i t} + A_{n} a e^{i t} \left|{A_{n}}\right|^{2} + A_{n} \delta_{n} e^{i t} + i A_{n} \nu e^{i t} \left|{A_{n}}\right|^{2} - i A_{n} \nu e^{i t} + 2 i A^{'}_{n} e^{i t} + 0.5 A_{n+1} D e^{i t} + 0.5 A_{n-1} D e^{i t} + \ddot{x}_n^{(1)} + x_n^{(1)}$

```python
eq5.coeff(exp(I*t),1)
```

$\displaystyle - A_{n} D + A_{n} a \left|{A_{n}}\right|^{2} + A_{n} \delta_{n} + i A_{n} \nu \left|{A_{n}}\right|^{2} - i A_{n} \nu + 2 i A^{'}_{n} + 0.5 A_{n+1} D + 0.5 A_{n-1} D$

# Aplicação do método perturbativo na equação da cadeia de suprimentos não linear

```python
q, qn_mais_1, dq, dqn_mais_1, ddq, nu, mu, alpha, beta = symbols("q_n, q_{n+1}, \dot{q}_n, \dot{q}_{n+1}, \ddot{q}_n, nu, mu, alpha, beta", real=True)
```

```python
eq = Eq(ddq - (nu-beta-3*mu*q**2)*dq + alpha*q - alpha*qn_mais_1 - beta*dqn_mais_1, 0)
eq
```

$\displaystyle \ddot{q}_n - \dot{q}_n \left(- \beta - 3 \mu q_{n}^{2} + \nu\right) - \dot{q}_{n+1} \beta + \alpha q_{n} - \alpha q_{n+1} = 0$

Introduzindo parâmetros pequenos escalados por $\epsilon$

```python
eq1 = eq.subs([(beta, epsilon*beta),
               (nu, epsilon*nu),
               (alpha, epsilon*alpha),
               (mu, epsilon*mu)
               ])
eq1
```

$\displaystyle \ddot{q}_n - \dot{q}_n \left(- \beta \epsilon - 3 \epsilon \mu q_{n}^{2} + \epsilon \nu\right) - \dot{q}_{n+1} \beta \epsilon + \alpha \epsilon q_{n} - \alpha \epsilon q_{n+1} = 0$

Soluções perturbativas para $q_i(t)$

```python
q1, q1n_mais_1, dq1n_mais_1, dq1, ddq1, t = symbols("q_n^{(1)}, q_{n+1}^{(1)}, \dot{q}_{n+1}^{(1)}, \dot{q}_n^{(1)}, \ddot{q}_n^{(1)}, t")
```

```python
A, An_mais_1, Al, Aln_mais_1, A2l, cc = symbols("A_n, A_{n+1}, A_n^{'}, A_{n+1}^{'}, A_n^{''}, c.c.", complex=True)
```

```python
eq2 = eq1.subs([(q, A*exp(I*t)+epsilon*q1),
               (qn_mais_1, An_mais_1*exp(I*t)+epsilon*q1n_mais_1),
               (dq, (I*A+epsilon*Al)*exp(I*t)+epsilon*dq1),
               (dqn_mais_1, (I*An_mais_1+epsilon*Aln_mais_1)*exp(I*t)+epsilon*dq1n_mais_1),
               (ddq, (-A+2*I*epsilon*Al+epsilon**2*A2l)*exp(I*t)+epsilon*ddq1)
               ])
eq2
```

$\displaystyle \ddot{q}_n^{(1)} \epsilon + \alpha \epsilon \left(A_{n} e^{i t} + \epsilon q_n^{(1)}\right) - \alpha \epsilon \left(A_{n+1} e^{i t} + \epsilon q_{n+1}^{(1)}\right) - \beta \epsilon \left(\dot{q}_{n+1}^{(1)} \epsilon + \left(i A_{n+1} + A_{n+1}^{'} \epsilon\right) e^{i t}\right) - \left(\dot{q}_n^{(1)} \epsilon + \left(i A_{n} + A_n^{'} \epsilon\right) e^{i t}\right) \left(- \beta \epsilon - 3 \epsilon \mu \left(A_{n} e^{i t} + \epsilon q_n^{(1)}\right)^{2} + \epsilon \nu\right) + \left(- A_{n} + A_n^{''} \epsilon^{2} + 2 i A_n^{'} \epsilon\right) e^{i t} = 0$

```python
eq3 = eq2.expand()
eq3
```

$\displaystyle 3 i A_{n}^{3} \epsilon \mu e^{3 i t} + 3 A_{n}^{2} A_n^{'} \epsilon^{2} \mu e^{3 i t} + 3 A_{n}^{2} \dot{q}_n^{(1)} \epsilon^{2} \mu e^{2 i t} + 6 i A_{n}^{2} \epsilon^{2} \mu q_n^{(1)} e^{2 i t} + 6 A_{n} A_n^{'} \epsilon^{3} \mu q_n^{(1)} e^{2 i t} + 6 A_{n} \dot{q}_n^{(1)} \epsilon^{3} \mu q_n^{(1)} e^{i t} + A_{n} \alpha \epsilon e^{i t} + i A_{n} \beta \epsilon e^{i t} + 3 i A_{n} \epsilon^{3} \mu \left(q_n^{(1)}\right)^{2} e^{i t} - i A_{n} \epsilon \nu e^{i t} - A_{n} e^{i t} + A_n^{''} \epsilon^{2} e^{i t} + A_n^{'} \beta \epsilon^{2} e^{i t} + 3 A_n^{'} \epsilon^{4} \mu \left(q_n^{(1)}\right)^{2} e^{i t} - A_n^{'} \epsilon^{2} \nu e^{i t} + 2 i A_n^{'} \epsilon e^{i t} - A_{n+1} \alpha \epsilon e^{i t} - i A_{n+1} \beta \epsilon e^{i t} - A_{n+1}^{'} \beta \epsilon^{2} e^{i t} + \ddot{q}_n^{(1)} \epsilon + \dot{q}_n^{(1)} \beta \epsilon^{2} + 3 \dot{q}_n^{(1)} \epsilon^{4} \mu \left(q_n^{(1)}\right)^{2} - \dot{q}_n^{(1)} \epsilon^{2} \nu - \dot{q}_{n+1}^{(1)} \beta \epsilon^{2} + \alpha \epsilon^{2} q_n^{(1)} - \alpha \epsilon^{2} q_{n+1}^{(1)} = 0$

```python
expr = eq3.lhs
expr
```

$\displaystyle 3 i A_{n}^{3} \epsilon \mu e^{3 i t} + 3 A_{n}^{2} A_n^{'} \epsilon^{2} \mu e^{3 i t} + 3 A_{n}^{2} \dot{q}_n^{(1)} \epsilon^{2} \mu e^{2 i t} + 6 i A_{n}^{2} \epsilon^{2} \mu q_n^{(1)} e^{2 i t} + 6 A_{n} A_n^{'} \epsilon^{3} \mu q_n^{(1)} e^{2 i t} + 6 A_{n} \dot{q}_n^{(1)} \epsilon^{3} \mu q_n^{(1)} e^{i t} + A_{n} \alpha \epsilon e^{i t} + i A_{n} \beta \epsilon e^{i t} + 3 i A_{n} \epsilon^{3} \mu \left(q_n^{(1)}\right)^{2} e^{i t} - i A_{n} \epsilon \nu e^{i t} - A_{n} e^{i t} + A_n^{''} \epsilon^{2} e^{i t} + A_n^{'} \beta \epsilon^{2} e^{i t} + 3 A_n^{'} \epsilon^{4} \mu \left(q_n^{(1)}\right)^{2} e^{i t} - A_n^{'} \epsilon^{2} \nu e^{i t} + 2 i A_n^{'} \epsilon e^{i t} - A_{n+1} \alpha \epsilon e^{i t} - i A_{n+1} \beta \epsilon e^{i t} - A_{n+1}^{'} \beta \epsilon^{2} e^{i t} + \ddot{q}_n^{(1)} \epsilon + \dot{q}_n^{(1)} \beta \epsilon^{2} + 3 \dot{q}_n^{(1)} \epsilon^{4} \mu \left(q_n^{(1)}\right)^{2} - \dot{q}_n^{(1)} \epsilon^{2} \nu - \dot{q}_{n+1}^{(1)} \beta \epsilon^{2} + \alpha \epsilon^{2} q_n^{(1)} - \alpha \epsilon^{2} q_{n+1}^{(1)}$

```python
collected_expr = collect(expr, epsilon)
collected_expr
```

$\displaystyle - A_{n} e^{i t} + \epsilon^{4} \left(3 A_n^{'} \mu \left(q_n^{(1)}\right)^{2} e^{i t} + 3 \dot{q}_n^{(1)} \mu \left(q_n^{(1)}\right)^{2}\right) + \epsilon^{3} \left(6 A_{n} A_n^{'} \mu q_n^{(1)} e^{2 i t} + 6 A_{n} \dot{q}_n^{(1)} \mu q_n^{(1)} e^{i t} + 3 i A_{n} \mu \left(q_n^{(1)}\right)^{2} e^{i t}\right) + \epsilon^{2} \left(3 A_{n}^{2} A_n^{'} \mu e^{3 i t} + 3 A_{n}^{2} \dot{q}_n^{(1)} \mu e^{2 i t} + 6 i A_{n}^{2} \mu q_n^{(1)} e^{2 i t} + A_n^{''} e^{i t} + A_n^{'} \beta e^{i t} - A_n^{'} \nu e^{i t} - A_{n+1}^{'} \beta e^{i t} + \dot{q}_n^{(1)} \beta - \dot{q}_n^{(1)} \nu - \dot{q}_{n+1}^{(1)} \beta + \alpha q_n^{(1)} - \alpha q_{n+1}^{(1)}\right) + \epsilon \left(3 i A_{n}^{3} \mu e^{3 i t} + A_{n} \alpha e^{i t} + i A_{n} \beta e^{i t} - i A_{n} \nu e^{i t} + 2 i A_n^{'} e^{i t} - A_{n+1} \alpha e^{i t} - i A_{n+1} \beta e^{i t} + \ddot{q}_n^{(1)}\right)$

```python
eq4 = collected_expr.coeff(epsilon,1)
eq4
```

$\displaystyle 3 i A_{n}^{3} \mu e^{3 i t} + A_{n} \alpha e^{i t} + i A_{n} \beta e^{i t} - i A_{n} \nu e^{i t} + 2 i A_n^{'} e^{i t} - A_{n+1} \alpha e^{i t} - i A_{n+1} \beta e^{i t} + \ddot{q}_n^{(1)}$

Infelizmente a equação acima não tem o termo $\dot{q}_n^{(1)}$ e não podemos fazer a mesma consideração dos termos proporcionais às exponenciais imaginárias atuarem como uma força externa que deve ser nula para não divergir a solução perturbativa.

```python

```

# Alternativa: Método Krylov-Bogoliubov (KB) para escrever equações de fase

```python
eq
```

$\displaystyle \ddot{q}_n - \dot{q}_n \left(- \beta - 3 \mu q_{n}^{2} + \nu\right) - \dot{q}_{n+1} \beta + \alpha q_{n} - \alpha q_{n+1} = 0$

```python
alphas, phi, dphi, phin_mais_1, an, anast, an_mais_1, an_mais_1ast, dan = symbols('alpha_s, phi_n, \dot{\phi}_n, \phi_{n+1}, a_n, a_n^*, a_{n+1}, a_{n+1}^*, \dot{a}_n', real=True)
```

```python
eq1 = eq.subs([(ddq, I*alphas*dan*exp(I*alphas*t)-alphas**2/2*(an*exp(I*alphas*t)+anast*exp(-I*alphas*t)) ),
               (dq, I*alphas/2*(an*exp(I*alphas*t)-anast*exp(-I*alphas*t)) ),
               (dqn_mais_1, I*alphas/2*(an_mais_1*exp(I*alphas*t)-an_mais_1ast*exp(-I*alphas*t)) ),
               (q, 1/2*(an*exp(I*alphas*t)+anast*exp(-I*alphas*t)) ),
               (qn_mais_1, 1/2*(an_mais_1*exp(I*alphas*t)+an_mais_1ast*exp(-I*alphas*t)) )
               ])
eq1
```

$\displaystyle i \dot{a}_n \alpha_{s} e^{i \alpha_{s} t} + \alpha \left(0.5 a_{n} e^{i \alpha_{s} t} + 0.5 a^{*}_{n} e^{- i \alpha_{s} t}\right) - \alpha \left(0.5 a_{n+1} e^{i \alpha_{s} t} + 0.5 a_{n+1}^* e^{- i \alpha_{s} t}\right) - \frac{\alpha_{s}^{2} \left(a_{n} e^{i \alpha_{s} t} + a^{*}_{n} e^{- i \alpha_{s} t}\right)}{2} - \frac{i \alpha_{s} \beta \left(a_{n+1} e^{i \alpha_{s} t} - a_{n+1}^* e^{- i \alpha_{s} t}\right)}{2} - \frac{i \alpha_{s} \left(a_{n} e^{i \alpha_{s} t} - a^{*}_{n} e^{- i \alpha_{s} t}\right) \left(- \beta - 0.75 \mu \left(a_{n} e^{i \alpha_{s} t} + a^{*}_{n} e^{- i \alpha_{s} t}\right)^{2} + \nu\right)}{2} = 0$

```python
eq2 = eq1.lhs*(exp(-I*alphas*t))/(I*alphas)
eq2
```

$\displaystyle - \frac{i \left(i \dot{a}_n \alpha_{s} e^{i \alpha_{s} t} + \alpha \left(0.5 a_{n} e^{i \alpha_{s} t} + 0.5 a^{*}_{n} e^{- i \alpha_{s} t}\right) - \alpha \left(0.5 a_{n+1} e^{i \alpha_{s} t} + 0.5 a_{n+1}^* e^{- i \alpha_{s} t}\right) - \frac{\alpha_{s}^{2} \left(a_{n} e^{i \alpha_{s} t} + a^{*}_{n} e^{- i \alpha_{s} t}\right)}{2} - \frac{i \alpha_{s} \beta \left(a_{n+1} e^{i \alpha_{s} t} - a_{n+1}^* e^{- i \alpha_{s} t}\right)}{2} - \frac{i \alpha_{s} \left(a_{n} e^{i \alpha_{s} t} - a^{*}_{n} e^{- i \alpha_{s} t}\right) \left(- \beta - 0.75 \mu \left(a_{n} e^{i \alpha_{s} t} + a^{*}_{n} e^{- i \alpha_{s} t}\right)^{2} + \nu\right)}{2}\right) e^{- i \alpha_{s} t}}{\alpha_{s}}$

```python
eq3 = eq2.expand()
eq3
```

$\displaystyle \dot{a}_n + 0.375 a_{n}^{3} \mu e^{2 i \alpha_{s} t} + 0.375 a_{n}^{2} a^{*}_{n} \mu - 0.375 a_{n} \left(a^{*}_{n}\right)^{2} \mu e^{- 2 i \alpha_{s} t} - \frac{0.5 i a_{n} \alpha}{\alpha_{s}} + \frac{i a_{n} \alpha_{s}}{2} + \frac{a_{n} \beta}{2} - \frac{a_{n} \nu}{2} - 0.375 \left(a^{*}_{n}\right)^{3} \mu e^{- 4 i \alpha_{s} t} - \frac{0.5 i a^{*}_{n} \alpha e^{- 2 i \alpha_{s} t}}{\alpha_{s}} + \frac{i a^{*}_{n} \alpha_{s} e^{- 2 i \alpha_{s} t}}{2} - \frac{a^{*}_{n} \beta e^{- 2 i \alpha_{s} t}}{2} + \frac{a^{*}_{n} \nu e^{- 2 i \alpha_{s} t}}{2} + \frac{0.5 i a_{n+1} \alpha}{\alpha_{s}} - \frac{a_{n+1} \beta}{2} + \frac{0.5 i a_{n+1}^* \alpha e^{- 2 i \alpha_{s} t}}{\alpha_{s}} + \frac{a_{n+1}^* \beta e^{- 2 i \alpha_{s} t}}{2}$

```python
eq3.coeff(exp(I*alphas*t),-2)
```

$\displaystyle - 0.375 a_{n} \left(a^{*}_{n}\right)^{2} \mu - \frac{0.5 i a^{*}_{n} \alpha}{\alpha_{s}} + \frac{i a^{*}_{n} \alpha_{s}}{2} - \frac{a^{*}_{n} \beta}{2} + \frac{a^{*}_{n} \nu}{2} + \frac{0.5 i a_{n+1}^* \alpha}{\alpha_{s}} + \frac{a_{n+1}^* \beta}{2}$

```python
eq3.coeff(exp(I*alphas*t),2)
```

$\displaystyle 0.375 a_{n}^{3} \mu$

```python
eq3.coeff(exp(I*alphas*t),-4)
```

$\displaystyle - 0.375 \left(a^{*}_{n}\right)^{3} \mu$

```python
eq4 = (eq3 - eq3.coeff(exp(I*alphas*t),-2)*exp(-2*I*alphas*t) - eq3.coeff(exp(I*alphas*t),2)*exp(2*I*alphas*t) - eq3.coeff(exp(I*alphas*t),-4)*exp(-4*I*alphas*t)).expand()
eq4
```

$\displaystyle \dot{a}_n + 0.375 a_{n}^{2} a^{*}_{n} \mu - \frac{0.5 i a_{n} \alpha}{\alpha_{s}} + \frac{i a_{n} \alpha_{s}}{2} + \frac{a_{n} \beta}{2} - \frac{a_{n} \nu}{2} + \frac{0.5 i a_{n+1} \alpha}{\alpha_{s}} - \frac{a_{n+1} \beta}{2}$

```python
A, An_mais_1, Al = symbols("A_n, A_{n+1}, \dot{A}_n", real=True)
```

```python
eq5 = eq4.subs([(anast*an**2, A**3*exp(I*phi) ),
                (dan, Al*exp(I*phi)+ I*dphi*A*exp(I*phi) ),
                (an, A*exp(I*phi) ),
                (an_mais_1, An_mais_1*exp(I*phin_mais_1) )
                ])
eq5
```

$\displaystyle 0.375 A_{n}^{3} \mu e^{i \phi_{n}} + i A_{n} \dot{\phi}_n e^{i \phi_{n}} - \frac{0.5 i A_{n} \alpha e^{i \phi_{n}}}{\alpha_{s}} + \frac{i A_{n} \alpha_{s} e^{i \phi_{n}}}{2} + \frac{A_{n} \beta e^{i \phi_{n}}}{2} - \frac{A_{n} \nu e^{i \phi_{n}}}{2} + \frac{0.5 i A_{n+1} \alpha e^{i \phi_{n+1}}}{\alpha_{s}} - \frac{A_{n+1} \beta e^{i \phi_{n+1}}}{2} + \dot{A}_n e^{i \phi_{n}}$

```python
eq6 = (eq5*exp(-I*phi)).expand().simplify()
eq6
```

$\displaystyle 0.375 A_{n}^{3} \mu + i A_{n} \dot{\phi}_n - \frac{0.5 i A_{n} \alpha}{\alpha_{s}} + \frac{i A_{n} \alpha_{s}}{2} + \frac{A_{n} \beta}{2} - \frac{A_{n} \nu}{2} + \frac{i A_{n+1} \alpha e^{i \phi_{n+1} - i \phi_{n}}}{2 \alpha_{s}} - \frac{A_{n+1} \beta e^{i \phi_{n+1} - i \phi_{n}}}{2} + \dot{A}_n$

```python
eq7 = eq6.rewrite(cos).trigsimp()
eq7
```

$\displaystyle 0.375 A_{n}^{3} \mu + i A_{n} \dot{\phi}_n - \frac{0.5 i A_{n} \alpha}{\alpha_{s}} + \frac{i A_{n} \alpha_{s}}{2} + \frac{A_{n} \beta}{2} - \frac{A_{n} \nu}{2} + \frac{i A_{n+1} \alpha \left(i \sin{\left(\phi_{n+1} - \phi_{n} \right)} + \cos{\left(\phi_{n+1} - \phi_{n} \right)}\right)}{2 \alpha_{s}} - \frac{A_{n+1} \beta \left(i \sin{\left(\phi_{n+1} - \phi_{n} \right)} + \cos{\left(\phi_{n+1} - \phi_{n} \right)}\right)}{2} + \dot{A}_n$

```python
im(eq7)
```

$\displaystyle A_{n} \dot{\phi}_n - \frac{0.5 A_{n} \alpha}{\alpha_{s}} + \frac{A_{n} \alpha_{s}}{2} + \frac{A_{n+1} \alpha \cos{\left(\phi_{n+1} - \phi_{n} \right)}}{2 \alpha_{s}} - \frac{A_{n+1} \beta \sin{\left(\phi_{n+1} - \phi_{n} \right)}}{2}$

Equação da dinâmica da fase:

```python
eq8 = (im(eq7)/A).expand()
eq8
```

$\displaystyle \dot{\phi}_n - \frac{0.5 \alpha}{\alpha_{s}} + \frac{\alpha_{s}}{2} + \frac{A_{n+1} \alpha \cos{\left(\phi_{n+1} - \phi_{n} \right)}}{2 A_{n} \alpha_{s}} - \frac{A_{n+1} \beta \sin{\left(\phi_{n+1} - \phi_{n} \right)}}{2 A_{n}}$

Equação da dinâmica da amplitude:

```python
eq9 = re(eq7)
eq9
```

$\displaystyle 0.375 A_{n}^{3} \mu + \frac{A_{n} \beta}{2} - \frac{A_{n} \nu}{2} - \frac{A_{n+1} \alpha \sin{\left(\phi_{n+1} - \phi_{n} \right)}}{2 \alpha_{s}} - \frac{A_{n+1} \beta \cos{\left(\phi_{n+1} - \phi_{n} \right)}}{2} + \dot{A}_n$

# Estudo numérico da equação de fase

```python
# pacote para integração de equações diferenciais estocásticas
!pip install sdeint
```

    Collecting sdeint
      Downloading sdeint-0.2.2.tar.gz (41 kB)
         |████████████████████████████████| 41 kB 516 kB/s
    Requirement already satisfied: numpy>=1.6 in /usr/local/lib/python3.7/dist-packages (from sdeint) (1.19.5)
    Building wheels for collected packages: sdeint
      Building wheel for sdeint (setup.py) ... done
      Created wheel for sdeint: filename=sdeint-0.2.2-py3-none-any.whl size=27832 sha256=2288e6e44ea3299d832568bfa4330024b46b5271a16ab3cb2c773aa21560cefc
      Stored in directory: /root/.cache/pip/wheels/f3/1d/ed/ec3ca11c90feaa579fe504b5da5c6ae00a499303764788d653
    Successfully built sdeint
    Installing collected packages: sdeint
    Successfully installed sdeint-0.2.2

```python
# importação de bibliotecas necessárias
import numpy as np
import sdeint
import matplotlib.pyplot as plt
%matplotlib inline
```

```python
# definição de parâmetros
N = 5 # número de osciladores
alpha = 5
alphas = 2
beta = 6
nu = 7
mu = 1
tf = 20 # tempo final de simulação
delta_t=0.01 # intervalo entre pontos de tempo de simulação
nt=int(tf/delta_t) # nº de pontos de tempo de simulação
t = np.linspace(0, tf, nt) # vetor de tempo de simulação
```

```python
# condições iniciais
phi0 = np.random.uniform(0,2*np.pi,N) # condição inicial para as fases dos osciladores
A0 = np.random.uniform(0,1,N) # condição inicial para as amplitudes

R=np.concatenate((np.zeros(N-1),np.array([1.0]),np.zeros(N-1),np.array([1.0]))).reshape(2*N,1)
R
```

    array([[0.],
           [0.],
           [0.],
           [0.],
           [1.],
           [0.],
           [0.],
           [0.],
           [0.],
           [1.]])

```python
eq8
```

$\displaystyle \dot{\phi}_n - \frac{0.5 \alpha}{\alpha_{s}} + \frac{\alpha_{s}}{2} + \frac{A_{n+1} \alpha \cos{\left(\phi_{n+1} - \phi_{n} \right)}}{2 A_{n} \alpha_{s}} - \frac{A_{n+1} \beta \sin{\left(\phi_{n+1} - \phi_{n} \right)}}{2 A_{n}}$

```python
eq9
```

$\displaystyle 0.375 A_{n}^{3} \mu + \frac{A_{n} \beta}{2} - \frac{A_{n} \nu}{2} - \frac{A_{n+1} \alpha \sin{\left(\phi_{n+1} - \phi_{n} \right)}}{2 \alpha_{s}} - \frac{A_{n+1} \beta \cos{\left(\phi_{n+1} - \phi_{n} \right)}}{2} + \dot{A}_n$

```python
# funções que definem o sistema de equações diferenciais
def f(x,t):
  phi = x[:N]
  A = x[N:]
  dphidt = np.zeros(N,float)
  dAdt = np.zeros(N,float)
  for n in range(0,N-1):
    dphidt[n] = 0.5*alpha/alphas - alphas/2 - A[n+1]*alpha*cos(phi[n+1]-phi[n])/(2*A[n]*alphas) + A[n+1]*beta*sin(phi[n+1]-phi[n])/(2*A[n])
    dAdt[n] = A[n]/2*(nu-beta) - 0.375*A[n]**3*mu + A[n+1]*alpha*sin(phi[n+1]-phi[n])/(2*alphas) + A[n+1]*beta*cos(phi[n+1]-phi[n])/2
  dphidt[N-1] = 0.5*alpha/alphas - alphas/2
  dAdt[N-1] = A[N-1]/2*(nu-beta) - 0.375*A[N-1]**3*mu
  return np.concatenate((dphidt, dAdt))

def g(x,t):
  Amp_ruido = 0.5
  ruido = R*Amp_ruido
  return ruido
```

```python
# integração do sistema de equações
yinit = np.concatenate((phi0,A0))
res = sdeint.itoint(f,g,yinit,t)
res.shape
```

    (2000, 10)

```python
# plot das fases no tempo
plt.figure(figsize=(16,10))
plt.plot(t, res[:,:N]);
```

```python
# plot das diferenças de fases no tempo
plt.figure(figsize=(16,10))
plt.plot(t, (res[:,1:N]-res[:,:N-1]));
```

```python
# plot das amplitudes no tempo
plt.figure(figsize=(16,10))
plt.plot(t, res[:,N:]);
```

```python
# plot das diferenças de fases no tempo
plt.figure(figsize=(16,10))
plt.plot(t, (res[:,4:5]-res[:,3:4]) );
plt.plot(t, (res[:,3:4]-res[:,2:3]) );
plt.plot(t, (res[:,2:3]-res[:,1:2]) );
plt.plot(t, (res[:,1:2]-res[:,:1]) );

```

```python

```