# Testing numerical methods

```python
from IPython.core.display import HTML
css_file = 'https://raw.githubusercontent.com/ngcm/training-public/master/ipython_notebook_styles/ngcmstyle.css'
HTML(url=css_file)
```

<link href='http://fonts.googleapis.com/css?family=Open+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>
<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: 1000px;
}

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

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

/* 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: 'Open Sans' sans-serif;
    line-height: 140%;
    font-size: 125%;
    font-weight: 400;
    width:900px;
    margin-left:auto;
    margin-right:auto;
}

/* Formatting for header cells */
.text_cell_render h1 {
    font-family: 'Arvo', serif;
    font-style:regular;
    font-weight: 400;
    font-size: 45pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}
.text_cell_render h2 {
    font-family: 'Arvo', serif;
    font-weight: 400;
    font-size: 30pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    display: block;
}

.text_cell_render h3 {
    font-family: 'Arvo', serif;
    margin-top:16px;
	font-size: 22pt;
    font-weight: 600;
    margin-bottom: 3px;
    font-style: regular;
    color: rgb(102,102,0);
}

.text_cell_render h4 {    /*Use this for captions*/
    font-family: 'Arvo', serif;
    font-size: 14pt;
    text-align: center;
    margin-top: 0em;
    margin-bottom: 2em;
    font-style: regular;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-family: 'Arvo', sans-serif;
    font-weight: 400;
    font-size: 16pt;
    color: rgb(163,0,0);
    font-style: italic;
    margin-bottom: .1em;
    margin-top: 0.8em;
    display: block;
}

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

.CodeMirror{
        font-family: "PT Mono";
        font-size: 90%;
}

</style>

Back in October, Greg Wilson [blogged about testing scientific software](http://software-carpentry.org/blog/2014/10/why-we-dont-teach-testing.html). He specifically points to [a lesson introducing the Euler method](http://nbviewer.ipython.org/github/numerical-mooc/numerical-mooc/blob/master/lessons/01_phugoid/01_03_PhugoidFullModel.ipynb) as part of the [Practical Numerical Methods with Python MOOC](http://openedx.seas.gwu.edu/courses/GW/MAE6286/2014_fall/about), and asks why a certain number (the measured convergence rate) is *close enough* to the expected value.

The big question of testing in scientific software, how this should be done, and how it is being done, has led to the [*Close Enough for Scientific Work*](https://github.com/swcarpentry/close-enough-for-scientific-work) project, as launched and explained by Greg Wilson in [this blog post](http://software-carpentry.org/blog/2014/11/close-enough-for-scientific-work.html). If you're reading this, you should be following that project! As I've helped out on the MOOC, which is led by [Lorena Barba](http://lorenabarba.com/), I've been (over)thinking what sort of answer we could, or should, give. Well aware that we're heading for the [academic version of the balloon joke](https://www2.bc.edu/~radinr/Management_Humor/jokes.htm) (an answer that is correct, of little use, and took a long time to arrive), let's begin...

## Background

$$
\newcommand{\dt}{\Delta t}
\newcommand{\udt}[1]{u^{({#1})}(T)}
$$

We have a system of differential equations to solve: the solution will be $u(t)$. The numerical solution we get will depend on one parameter, the timestep $\dt$. The resulting numerical approximation, at the point $t=T$, will be $\udt{\dt}$: the exact solution is $u(T)$.

The method used is Euler's method, also [introduced in an earlier lesson in the MOOC](http://nbviewer.ipython.org/github/numerical-mooc/numerical-mooc/blob/master/lessons/01_phugoid/01_02_Phugoid_Oscillation.ipynb), and [explained in detail by Lorena in this screencast](https://www.youtube.com/watch?v=6i6qhqDCViA). The key result derived there is that Euler's method is *first order*, so that

$$
\begin{equation}
  u(T) - \udt{\dt} = c_1 \dt + c_2 \dt^2 + {\cal O}(\dt^3) \simeq c_1 \dt.
\end{equation}
$$

For sufficiently small $\dt$ the error is proportional to $\dt$.

As we can't (usually) know the exact solution $u(T)$ ahead of time, a standard check is *grid convergence*: compute three solutions with different timesteps (eg, $\dt, 2\dt, 4\dt$) and compare them. The comparison to use is

$$
\begin{equation}
  s_m = \log_2 \left( \frac{\udt{4\dt} - \udt{2\dt}}{\udt{2\dt} - \udt{\dt}} \right) \simeq 1.
\end{equation}
$$

The symbol $s_m$ is used as it's the *(measured) slope* of the best fit line through the errors, as shown on the [original lesson](http://nbviewer.ipython.org/github/numerical-mooc/numerical-mooc/blob/master/lessons/01_phugoid/01_03_PhugoidFullModel.ipynb):

####Figure 1. Convergence test plot taken from the original lesson.

The [original lesson](http://nbviewer.ipython.org/github/numerical-mooc/numerical-mooc/blob/master/lessons/01_phugoid/01_03_PhugoidFullModel.ipynb) does precisely this comparison (using the phugoid model, with specific parameter values, and $\dt = 0.001$), finding a measured slope $s_m = 1.014$. Is this *close enough* to 1?

## TL;DR: Answer

Answer**s**

1. [*I don't care about the algorithm: I just want the answer to be right*](http://nbviewer.ipython.org/github/IanHawke/close-enough-balloons/blob/master/01-Close-Enough-Errorbars.ipynb): $0.585 \lesssim s_m \lesssim 1.585$ is close enough for Euler's method.
2. [*I don't care about the answer: I just want the algorithm behaviour to be right*](http://nbviewer.ipython.org/github/IanHawke/close-enough-balloons/blob/master/02-Close-Enough-Slopes.ipynb): $s_m=1.014$ with $\dt=0.001$ is close enough if $1 \le s_m \le 1.0093$ with $\dt=0.0005$.
3. [*I don't care about the behaviour: I just want to know I've implemented Euler's method*](http://nbviewer.ipython.org/github/IanHawke/close-enough-balloons/blob/master/03-Close-Enough-Just-Euler.ipynb): measure the local truncation error instead, and check *both* the convergence rate *and* the leading order constant. $s_m$ by itself is useless.


## Manningの粗度係数を再考する

### Manningの公式の概要

Manningの公式は、Robert Manningによって提案された横断面内で平均化された流速$V$を示す実験公式であり、次式のように示される。

$$
\begin{align}
 V = \dfrac{1}{n}i_e^{1/2}R^{2/3}
\end{align}
$$
ここで、$n$：Manningの粗度係数（$m^{-1/3} \cdot s$）、$i_e$：エネルギー勾配、$R$：径深（m）である。

本式は現在世界で最も使われている平均流速公式である。

上式の実験定数はManningの粗度係数のみであるが次元を有しており定数として適切でない。
それにもかかわらず、式形が非常に単純なため、実験水路から実河川まで様々な条件下での豊富な観測資料を元にManningの粗度係数は整理されている。そのため、容易に概略値を把握することが可能である。

例えば、Chowの「OPEN-CHANNEL HYDRAULICS」では水路条件を100種類以上に分類し、Manningの粗度係数を一般値を示している。[^1]

日本では「水理公式集(平成11年版)」[^2]や「河川砂防技術基準(案)同解説調査編」[^3]に次表のようにまとめられている。

[^1]: Chow,V.,T.: Open-channel hydraulics, pp.110-113, McGraw-Hill, 1959.

[^2]: 土木学会水理委員会水理公式集改訂小委員会 : 水理公式集, p.89, 土木学会, 1999.

[^3]: 建設省河川局,日本河川協会 : 建設省河川砂防技術基準(案)同解説調査編, p.133, 技報堂出版, 1997.

 - 「水理公式集(平成11年版)」

 - 「河川砂防技術基準(案)同解説調査編」

### Manningの公式への水理学的な意味付け

流速係数$\phi=V/u_*$をManningの公式を用いて整理すると次式となる。
$$
\begin{align}
\phi &= \frac{V}{u_*} = \frac{k_s^{1/6}}{n \sqrt{g}} \left(\frac{R}{k_s} \right)^{1/6} \nonumber
\end{align}
$$
ここに$k_s$：相当粗度(m)である。
一方開水路完全粗面の対数則による流速係数は次式となる。

$$
\begin{align}
\phi &= \frac{1}{\kappa}\log_e{\frac{h}{k}} - \frac{1}{\kappa} + C
\end{align}
$$

両式より、$\phi$と$k_s^{1/6}/(n \sqrt{g})$の関係を整理したものが次図の点線である。

図　Manning・Stricklerの式と粗面対数則との比較[^4]

管路や開水路では流速係数$\phi$は8～25程度であるため、$k_s^{1/6}/(n \sqrt{g})$は図中直線の一定値に近似できる。
これより、流速係数は以下のように近似できる。

$$
\begin{align}
\frac{k_s^{1/6}}{n \sqrt{g}} & \sim 7.66 \nonumber  \\
\phi &= \frac{V}{u_*} = 7.66 \left(\frac{R}{k_s} \right)^{1/6}
\end{align}
$$

これはManning・Stricklerの公式と呼ばれる。
上記のように近似できることは実用上は径深によってManningの粗度係数が変わらないことを示している。
今日では本式を使用することは少ないが、Manningの公式に水理学的な意味を与えた点で重要である。

[^4]: 椿東一郎 : 水理学I, p.110, 森北出版, 1973.

### 沖積河川の河床抵抗

多くの沖積河川では河床上に河床波（小規模河床形態）が形成されている。河床波とは砂漣、砂堆、反砂堆等の水深スケールの河床形状を示して、日本土木学会水理委員会によると次表のように分類される。[^5]
また、Simonsはより詳細な分類を示している。[^6]

河床波(ここでは砂堆)上の流れを模式的に示すと下図のとおりである。[^7]

ここで、（水深平均）流れに対する河床が与える抵抗を考えると「摩擦抵抗」と「剥離に伴う形状抵抗」に分類できる。
Manningの公式のような平均流速公式ではこの両者の影響が混ざって含まれることになる。

「摩擦抵抗」は河床材料によって決定するため対数則によって評価する。一方、「剥離に伴う形状抵抗」は河床波の形状を考慮して急拡損失の考え方により評価する。
ここで河床波の形状が問題となる。模型実験では二次元水路を使用することにより河床波の形状を計測することは比較的容易であるが、実河川では難しく、近年の研究で高解像度のセンサーを用いた実河川の河床波の計測事例が報告されている[^8]が、まだ一般的とは言えず、実河川の河床波形状を計測すること難しい。

さらに、実河川の流れは非定常にであり、流れの規模によって河床波の形状が変化する。このような実河川における出水中の河床波の変化を計測事例はほとんど報告されておらず[^9],[^10]、実態は不明である。

これらより実河川の河床抵抗を厳密に推定することは難しいことが理解できる。そのため、Manningの公式が積極的に代用されている。前項にはManningの粗度係数は水深によってほとんど変化しないと示したが、これは河床波形状が変化しない条件で成立し、変化する場合には形状抵抗による損失が変化するため、Manningの粗度係数も変化する。

なお、Manningの粗度係数は一定値として取り扱うことが一般的である。観測資料が十分でなく、大規模出水時に観測データから同定された値を使うためである。

[^5]: 水理委員会移動床流れの抵抗と河床形状研究小委員会 : 移動床流れにおける河床形態と粗度, 土木学会論文報告集第210号, pp.65-91, 1973.

[^6]: Simons,D.B.,Şentürk, F. : Sediment Transport Technology, Water Resources Publications, 1977.

[^7]: 芦田和男,江頭進治,中川一 : 21世紀の河川学:安全で自然豊かな河川を目指して, p.121, 京都大学学術出版会, 2008.

[^8]: 例えば、秋田麗子,西口亮太,野間口芳希 : 水中の河床地形の面的計測とその活用方策について, 河川技術論文集, 第23巻, pp.173-178, 2017.

[^9]: 高部一彦，人見寿，坂野章，山本浩一 : 涸沼川における河床波観測及び解析, 河川技術論文集, 第11巻, pp.387-392, 2005.

[^10]: 末次忠司, 日下部隆昭, 坊野聡子 : 土砂管理施策のためのキーノート, 国土技術政策総合研究所資料, No.231, 2005.

### 河床波の変化を考慮した河床抵抗の評価方法

前項のとおり、実河川での検証が難しいため、模型実験結果を元に河床抵抗の評価を行う。

Engelund[^11]は河床抵抗を以下のようにモデル化した。

$$
\begin{align}
 \tau_* = \tau_*^{\prime} + \tau_*^{\prime\prime}
\end{align}
$$

ここで、$\tau_*$:全無次元掃流力、$\tau_*^{\prime}$:摩擦抵抗による無次元掃流力（=無次元有効掃流力）、  $\tau_*^{\prime\prime}$:形状抵抗による無次元掃流力である。

相似則より$\tau_*$は$\tau_*^{\prime}$のみの関数であることを示した。これより実験結果を使用して次図[^12]の関係式を示した。

さらに、岸・黒木[^5]はEngelundの相似則を修正し、$\tau_*$は$\tau_*^{\prime}$,$R/d$の関数となることを示し、次図[^12]の関係を示した。

現時点ではこれが最も有用な研究成果と考えられる。

参考までにEngelundと岸・黒木の研究成果を比較する。両者による無次元掃流力-有効無次元掃流力の図を重ね合わせると次図のとおりである。なお、岸・黒木の図は$R/d$が1000、500、100の3ケースを示す。

両者を比較するとdune領域、flat-bed・antidune領域ではそれほど大きな差異はないが、transition領域の取り扱いが異なっている。
Engelundはtransition領域の変化が不明なため定式化していないが、岸・黒木は定式化しており、この領域の取り扱いが$R/d$によって異なっている。
よって、transition領域の影響を考慮するためには岸・黒木の方法を使う他はない。

河床波の変化による流れ場への影響を理解しやすくするため、岸・黒木の図を$\phi$と$\tau_*$の関係に変換した図[^12]を以下に示す。

縦軸の$\phi=V/u_*$は流れやすさを示すため、transition領域で急激に流れやすくなる、つまり、河床抵抗が減少することが理解できる。

[^11]: Engelund F. : Hydraulic Resistance of Alluvial Streams, Journal of the Hydraulics Division, Vol. 92, Issue 2, pp.315-326, 1966.

[^12]: 河村三郎 : 土砂水理学, pp.226-230, 森北出版, 1982.

### 岸・黒木の方法による河床抵抗の評価

岸・黒木の方法による河床抵抗の評価の計算方法について示す。
次図（再記）の各領域区分の無次元掃流力$\tau_*$と有効無次元掃流力$\tau_*^{\prime}$の関係式は以下のとおりとなっている。

$$
\begin{align}
\rm{dune1} : \tau_*^{\prime} &= 0.21\tau_*^{1/2} \\
\rm{dune2} : \tau_*^{\prime} &= 1.49(R/d)^{-1/4}\tau_* \\
\rm{flat\text{-}bed} : \tau_*^{\prime} &=  \tau_* \\
\rm{antidune} : \tau_*^{\prime} &= 0.264(R/d)^{1/5}\tau_*^{1/2} \\
\rm{transition1} : \tau_*^{\prime} &= 6.5 \times 10^7(R/d)^{-5/2} \tau_*^{11/2}
\end{align}
$$

また、dune領域とtransition領域、flat-bed領域とantidune領域の区分は次式となる。

$$
\begin{align}
\rm{dune \text{ -- } transition} : \tau_* &= 0.02(R/d)^{1/2} \\
\rm{flat\text{-}bed \text{ -- } antidune} : \tau_* &= 0.07(R/d)^{2/5}
\end{align}
$$

上図中のtransition2領域は関係式が設定されていない。transition2はdune2とantiduneを直線で繋いでおり、dune領域の上限値を示している。
transition領域では複雑な変化を示すため定式化は難しいが、岸・黒木の方法より、dune1 -- transition1 -- flat-bed -- antiduneの過程で遷移する(図中赤線)ものと考える。
なお、antiduneは射流場のみで発生するため、ほとんど沖積河川の場合、flat-bedまでの変化を考慮すれば良い。

### 岸・黒木の方法の課題

#### 河床波の遷移の履歴

ここまでに示した考え方は基本的に定常、等流、平衡を前提に構築されている。
また、模型実験のデータを基に関数をフィッティングしている。

実河川の適用性は、Engelund[^11]はRio Grande川での観測データと一致することを示しており、岸・黒木[^5]も同じデータを用いて妥当性を示している。
しかし、岸・黒木は石狩川の観測データとの比較により水理量と河床形状の関係が常に平衡にはならずに履歴の影響を受けること示しており、手法の適用上の課題を指摘している。

今後はより多くの河川で観測を実施して手法の適用性を検証する必要がある。

#### 河床波の形状抵抗の直接評価

Engelundおよび岸・黒木の方法は、相似を仮定して無次元掃流力と有効無次元掃流力の関係を用いて河床波の影響を評価しているが、河床波の形状損失を直接評価する方が理想的である。

この方法は、これまでの研究では一次元流れを仮定した急拡損失による評価が行われてきたが、乱流モデルを用いた鉛直二次元または三次元解析によって評価する必要がある。
また、現時点では実河川による検証データの取得が難しいため、模型実験を基本に検証を進めることが望ましい。

### 参考：流砂量評価における有効掃流力

掃流力は流れにとっては抵抗になるが河床土砂にとっては駆動力となる。その力は全抵抗から形状抵抗を差し引いた有効掃流力である。
そのため、河床波の遷移は掃流砂量にも大きな影響を与える。

日本で最も使用される芦田・道上の掃流砂量式には有効掃流力が含まれている。これはdune上の流れを想定していることを意味しており、本来であれば、河床波形状に応じてこの式形を変更する必要がある。

また、使用頻度は低いが、佐藤・吉川・芦田の式（土研公式）ではManningの粗度係数によって式形を変更している。これは、河床波形状の影響を示しているが、河床波形状はManningの粗度係数のみでは決定しないため、使用の際には注意が必要である。

---

## bibtex

```python
from pybtex.database.input import bibtex

parser = bibtex.Parser()
bib_data = parser.parse_file("refs.bib")
```

### book

```python
key = 'komura1982'
line = ''
ts = bib_data.entries[key]
s = bib_data.entries[key].persons['author']

for ss in s:
    for sl in ss.last_names:
        line += sl + ','

    for sl in ss.first_names:
        line += sl + ','

line += ":"

line += ts.fields['title'] \
+ ", pp." + ts.fields['pages'] \
+ ", " + ts.fields['publisher'] \
+ ", " + ts.fields['year'] + "."
```

### jarnal

```python
key = 'jsce1973'
line = ''
ts = bib_data.entries[key]
s = bib_data.entries[key].persons['author']

for ss in s:
    for sl in ss.last_names:
        line += sl + ','

    for sl in ss.first_names:
        line += sl + ','

line += ":"

line += ts.fields['title'] \
+ ", " + ts.fields['journal'] \
+ ", " + ts.fields['number'] \
+ ", pp." + ts.fields['pages'] \
+ ", " + ts.fields['year'] + "."
```

```python
line
```

    '河村,三郎,:土砂水理学, pp.226, 森北出版, 1982.'

```python

```

## graph

```python
import numpy as np
import pandas as pd
import holoviews as hv
import seaborn as sns
from matplotlib import rcParams
```

```python
# backend = 'bokeh'
backend = 'matplotlib'

if backend == 'matplotlib':
    sns.set(context='notebook', font_scale=1.0, style="whitegrid", palette="bright")
    rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP']

hv.extension(backend)

lw = 'line_width' if  backend == 'bokeh' else 'linewidth'
lstyle = 'line_dash' if  backend == 'bokeh' else 'linestyle'

lw1 = {lw:3}
lw2 = {lw:1}
lsdot = {lstyle:'dotted'}
lsdash = {lstyle:'dashed'}
grd = {'show_grid':True}
```

<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">

```python

```

```python
df = pd.read_csv('https://computational-sediment-hyd.github.io/HydraulicsTips-in-CivilEngineer/data/Engelund.csv', header=None)
df.columns = ['x','y']
```

```python
taus1 = np.logspace(-1,0.2,num=20,endpoint=True,base=10.0)
taus2 = np.logspace(-0.5,0.4,num=20,endpoint=True,base=10.0)

gEng = hv.Curve((df.x,df.y), label='Engelund').options(color='k', **lw1, **grd) \
*hv.Curve((0.06+0.4*taus1**2,taus1), label='Engelund').options(color='k', **lw1, **grd)
go1 = hv.Curve((0.4*taus1**2,taus1), label='$\\tau_{*}^{\prime}=0.4\\tau_*^2$').options(color='k', **lsdot, **grd)
go2 = hv.Curve((taus2,taus2), label='$\\tau_{*}^{\prime}=\\tau_*$').options(color='k', **lsdash, **grd)
```

```python
def kishikuroki1(taus, Rbyd):

    if taus < 0.02*(Rbyd)**0.5:
        tausd = 0.21*taus**0.5
    elif taus < 0.07*(Rbyd)**0.4:
        tausd = 1.49*(Rbyd)**(-0.25)*taus
    else:
        tausd = 0.264*(Rbyd)**0.2*taus**0.5

    return tausd

def kishikuroki2(taus, Rbyd):

    if taus < 0.02*(Rbyd)**0.5:
        tausd = 0.21*taus**0.5
    elif taus < 0.07*(Rbyd)**0.4:
        tausd = 6.5*10**7*(Rbyd)**(-2.5)*taus**5.5
        tausd = tausd if tausd < taus else taus
    else:
        tausd = 0.264*(Rbyd)**0.2*taus**0.5

    return tausd
```

```python
def mkfig(Rbyd, color):
    taus = np.arange(0.05,5.01,0.01)
    tausd1 = [ kishikuroki1(tt, Rbyd) for tt in taus ]
    tausd2 = [ kishikuroki2(tt, Rbyd) for tt in taus ]

    g = hv.Curve((tausd1, taus)).options(color=color, **grd) * hv.Curve((tausd2, taus),label='Kishi-Kuroki, R/d='+str(Rbyd)).options(color=color, **grd)

    return g
```

```python
gkk = (mkfig(1000,'r')*mkfig(500,'b')*mkfig(100,'g'))
```

```python
gl = (gkk*gEng*go1*go2).options(logx=True, logy=True, legend_position='top_left'
          , xlabel='dimensionless effective shear stress $\\tau_{*}^{\prime}$', ylabel='dimensionless shear stress $\\tau_*$').redim.range(x=(0.01,10), y=(0.1,10))

gl = gl.options(aspect=1.5, fig_size=200, **grd)
gl
```

```python
hv.save(gl,'engelund_add_kishikuroki.svg')
```

```python

```

```python
gl = (g*gkk).options(width=500,height=400, logx=True, logy=True, legend_position='top_left'
          , xlabel='dimensionless effective shear stress τ*d', ylabel='dimensionless shear stress τ*').redim.range(x=(0.01,10), y=(0.1,10))
gl
```


# PHY321 Classical Mechanics 1

**Final  project, due Friday April 30**, midnight (1159pm)

Date: **Apr 22, 2021**

## Practicalities about  homeworks and projects

1. You can work in groups (optimal groups are often 2-3 people) or by yourself. If you work as a group you can hand in one answer only if you wish. **Remember to write your name(s)**!

2. How do I(we)  hand in?  Due to the extraordinary situation we are in now, the final projec should be handed in fully via D2L. You can scan your handwritten notes and upload to D2L or you can hand in everyhting (if you are ok with typing mathematical formulae using say Latex) as a jupyter notebook at D2L. The numerical part should always be handed in as a jupyter notebook.

### Introduction to the final project, total score: 150  points

The relevant reading background is
1. chapters 2-8 and 14 of Taylor

2. lecture notes throughout the semester and previous homework and midterm projects.

The final project aims at covering most of the topics we have
discussed during the semester. You should feel free to use either
paper and pencil and/or symbolic software (sympy, Mathematica or
similar) for the non-computational exercises.

### Exercise 1, Two-body Problems and Conservative Forces (total 90pt)

The relevant material from Taylor are chapters 4 and 8. Homework sets 6-9 and the chapters on [forces](https://mhjensen.github.io/Physics321/doc/LectureNotes/_build/html/chapter4.html) and [two-body problems](https://mhjensen.github.io/Physics321/doc/LectureNotes/_build/html/chapter6.html) from the lecture notes may also be of use.

This exercise is a follow-up of hw6. There we studied the so-called
Lennard-Jones potential which is widely used in molecular dynamics
calculations. This potential is based on parametrizations from
expertiments. In molecular dynamics calculations the assumption is
that atoms move according to the laws of Newton, given the correct
model for interactions. We can say then that quantum-mechanical
degrees of freedom stemming from the interactions between electrons
and protons in an atom, are parametrized in terms of an effective
potential.

We will limit ourselves to a two-body problem.

The goal of this exercise is to model a gas of argon atoms (here two
atoms only interacting), where the atoms interact according to the
famous Lennard-Jones potential,

$$
\begin{equation}
    V(r) = 4\varepsilon\left((\frac{\sigma}{r})^{12} - (\frac{\sigma}{r})^6\right), \label{eq:lj} \tag{1}
\end{equation}
$$

where $r$ is the distance between two atoms,
$r=\vert\boldsymbol{r}_i-\boldsymbol{r}_j\vert$, that is the norm of the relative
distance vector $\boldsymbol{r}$. The quantities $\sigma$ and $\varepsilon$ are
parameters which determine which chemical compound is modelled. This
potential is a good approximation for noble gases like helium, neon, argon and other.

We start first with a basic study of the potential

* **1a (5pt):** Plot the potential as a function of $r$ with $\varepsilon=1$ and $\sigma=1$, for example for $r \in [0.9,3]$.

* **1b (5pt):** The behaviour of $V(r)$ is vastly different for $r < \sigma$ and $r > \sigma$. Which term in the potential, ([1](#eq:lj)), dominates in each case and what is the effect?

* **1c (5pt):** Find and characterise the equilibrium points of the potential.

* **1d (5pt):** Describe qualitatively the motion of two atoms which start at rest separated by a distance of ${1.5}\sigma$. What if they start with a separation of ${0.95}\sigma$?  (Hint: use the graph of the potential.)

* **1e (5pt):** Describe the shape of the potential close to the stable equilibrium point. Can you think of other force(s) with the same behaviour?

Then we switch our attention to the equations of motion.

* **1f (5pt):** Find the force on atom $i$ at position $\boldsymbol{r}_i$ from atom $j$ at position $\boldsymbol{r}_j$.

* **1g (5pt):**  Is this a conservative force? Show that the **curl** is zero.

* **1h (5pt):**  Are linear and angular momentum conserved? You need to show this by calculating the relevant quantities.

* **1i (5pt):** Show that the equation of motion for atom $i$ is

$$
\frac{d^2\boldsymbol{r}_i}{dt^2} = \frac{24\varepsilon}{m} \sum_{j \neq i} \left(2(\frac{\sigma}{\vert\boldsymbol{r}_i-\boldsymbol{r}_j}\vert)^{12}-(\frac{\sigma}{\vert\boldsymbol{r}_i-\boldsymbol{r}_j}\vert)^6\right)\frac{\boldsymbol{r}_i-\boldsymbol{r}_j}{\vert\boldsymbol{r}_i-\boldsymbol{r}_j\vert^2}.
$$

Numerical accuracy is reduced when computing with values which are
many orders of magnitude apart. This is often an issue in physics, and
molecular dynamics is no exception. For example, the mass of argon is
smaller than 10E-25kg, while typical length scales are
on the order of nanometers, 10E-9m.

The remedy is to change units so that most quantities are close to
$1$. From ([1](#eq:lj)) it is clear that $\sigma$ and $\varepsilon$
are the typical scales for length and energy.

* **1j (5pt):** Introduce the scaled coordinates $\boldsymbol{r}_i\,'=\boldsymbol{r}_i/\sigma$ and show that the equation of motion can be rewritten in terms of these coordinates as (where $t'=t/\tau$ for a suitable choice of $\tau$.)

$$
\begin{equation}
\frac{d^2\boldsymbol{r}_i\,'}{{dt'^2}} = 24 \sum_{j \neq i} \left(2\vert\boldsymbol{r}_i\,'-\boldsymbol{r}_j\,'\vert^{-12}-\vert\boldsymbol{r}_i\,'-\boldsymbol{r}_j\,\vert^{-6}\right)\frac{\boldsymbol{r}_i\,'-\boldsymbol{r}_j\,'}{\vert\boldsymbol{r}_i\,'-\boldsymbol{r}_j\,'\vert^2}, \label{eq:undim} \tag{2}
\end{equation}
$$

* **1k (5pt):** What is the characteristic time scale $\tau$, and what is its value for argon, which has $\sigma=3.405$Å (1Å=1E-10m), $m = 39.95u$ (with 1u=1.66E-27kg) and $\varepsilon=1.0318$ E-2eV (1eV=1.602E-19J)?

We switch now to a numerical procedure and study the simulation of two interacting atoms.
* **1l (10pt):** Write a function which solves ([2](#eq:undim)) for two atoms and finds the positions and velocities of the atoms as a function of time. Implement either the Euler-Cromer or the Velocity-Verlet method to solve the equations od motion.

* **1m (5pt):** Simulate the motion of two atoms which start at rest separated by a distance of ${1.5}\sigma$. Use $\Delta t'={0.01}$, simulate until $t'=5$ and integrate with one of the above methods.

* **1n (5pt):** Plot the distance between the atoms as a function of time. How does the motion fit with your expectations?

* **1o (5pt):** Repeat the previous tasks, but now with an initial separation of $0.95\sigma$. Explain your results.

* **1p (10pt):** Compute and plot the kinetic, potential and total energy as a function of time for. Should the total energy be conserved? Why, or why not? Does your program fulfil this? If not, what could be the cause?

### Exercise 2, Coupled Harmonic Oscillators (60pt)

The relevant chapters from Taylor are chapters 5-7 and the lectures notes on [harmonic oscillations](https://mhjensen.github.io/Physics321/doc/LectureNotes/_build/html/chapter5.html) and the [Lagrangian Formalism and Calculus of Variations](https://mhjensen.github.io/Physics321/doc/LectureNotes/_build/html/chapter8.html). Your codes from homework sets 5-8 and the first midterm may also be of interest.

Consider a mass $m$ that is connected to a wall by a spring with
spring constant $k$. A second identical mass $m$ is connected to the
first mass by an identical spring. Motion is confined to the $x$ direction only.

* **2a (10pt):** Make a drawing of the system, set up forces and define variables $x_1$ and $x_2$ for the two masses.

* **2b (10pt):** Write the Lagrangian in terms of the positions of the two masses $x_1$ and $x_2$.

* **2c (10pt):** Use the Euler-Lagrange equations to find the  equations of motion.

* **2d (10pt):** Find the analytical  solutions using a guess of  the type

$$
x_1=Ae^{i\omega t},~~~x_2=Be^{i\omega t}.
$$

Solve for $A/B$ and $\omega$. Express your answers in terms of $\omega_0^2=k/m$.

* **2e (20pt):** Write now a program which solves these two coupled differential equations for $x_1$ and $x_2$. Compute the positions $x_1$ and $x_2$ by choosing your initial conditions and compare with the analytical answers from 2d.

### Classical Mechanics Extra Credit Assignment: Scientific Writing and attending Talks

The following gives you an opportunity to earn **five extra credit
points** on each of the remaining homeworks and **ten extra credit points**
on the midterms and finals.  This assignment also covers an aspect of
the scientific process that is not taught in most undergraduate
programs: scientific writing.  Writing scientific reports is how
scientist communicate their results to the rest of the field.  Knowing
how to assemble a well written scientific report will greatly benefit
you in you upper level classes, in graduate school, and in the work
place.

The full information on extra credits is found at <https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/>. There you will also find examples on how to write a scientific article.
Below you can also find a description on how to gain extra credits by attending scientific talks.

This assignment allows you to gain extra credit points by practicing
your scientific writing.  For each of the remaining homeworks you can
submit the specified section of a scientific report (written about the
numerical aspect of the homework) for five extra credit points on the
assignment.  For the two midterms and the final, submitting a full
scientific report covering the numerical analysis problem will be
worth ten extra points.  For credit the grader must be able to tell
that you put effort into the assignment (i.e. well written, well
formatted, etc.).  If you are unfamiliar with writing scientific
reports, [see the information here](https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/IntroductionScientificWriting.md)

The following table explains what aspect of a scientific report is due
with which homework.  You can submit the assignment in any format you
like, in the same document as your homework, or in a different one.
Remember to cite any external references you use and include a
reference list.  There are no length requirements, but make sure what
you turn in is complete and through.  If you have any questions,
please contact Julie Butler at butler@frib.msu.edu.

  HW/Project 	 Due Date	 Extra Credit Assignment

   HW 3             	    2-8         	    Abstract

   HW 4             	    2-15        	    Introduction

   HW 5             	    2-22        	    Methods

   HW 6             	    3-1         	    Results and Discussion

   **Midterm 1**    	    **3-12**    	    *Full Written Report*

   HW 7             	    3-22        	    Abstract

   HW 8             	    3-29        	    Introduction

   HW 9             	    4-5         	    Results and Discussion

   **Midterm 2**    	    **4-16**    	    *Full Written Report*

   HW 10            	    4-26        	    Abstract

   **Final**        	    **4-30**    	    *Full Written Report*

You can also gain extra credits if you attend scientific talks.
This is described here.

### Integrating Classwork With Research

This opportunity will allow you to earn up to 5 extra credit points on a Homework per week. These points can push you above 100% or help make up for missed exercises.
In order to earn all points you must:

1. Attend an MSU research talk (recommended research oriented Clubs is  provided below)

2. Summarize the talk using at least 150 words

3. Turn in the summary along with your Homework.

Approved talks:
Talks given by researchers through the following clubs:
* Research and Idea Sharing Enterprise (RAISE): Meets Wednesday Nights Society for Physics Students (SPS): Meets Monday Nights

* Astronomy Club: Meets Monday Nights

* Facility For Rare Isotope Beam (FRIB) Seminars: Occur multiple times a week

If you have any questions please consult Jeremy Rebenstock, rebensto@msu.edu.

All the material on extra credits is at <https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/>.


```python
import numpy as np
np.set_printoptions(suppress=True)
```

# Linguagem Python

Python é uma linguagem interpretada, de alto nível e propósito geral. Possui gerenciamento de memória automático, e tipagem dinâmica. Suporta diferentes paradigmas de programação como imperativa, orientada a objetos, funcional e procedural.

Nosso foco será uma abordagem **imperativa**, **procedural** e **estruturada**.

## The Zen of Python

*Beautiful is better than ugly.*

*Explicit is better than implicit.*

*Simple is better than complex.*

*Complex is better than complicated.*

*Flat is better than nested.*

*Readability counts.*

## Versões de Python

* Python 2.7 (descontinuada em 2020)
* Python 3.~6~7 (disponível na maioria das distribuições)
* ~Python 3.7.2 (versão estável atual)~
* Python 3.10.1 (versão mais atual)

A maioria dos sistemas operacionais Linux da atualidade ainda utilizam o *Python2* como padrão, desta forma o binario `python` normalmente executa a versão antiga. O uso da versão 2 do Python será descontinuado em 2020. Qualquer referência que recomende o uso desta versão deve ser considerada não confiável.

A dependência ao Python 2 na maioria das versões de Linux se dá principalmente pelo grande conjunto de ferramentas que foram desenvolvidas em Python 2 ao longo dos últimos 15 anos. Na atualidade a grande parte dos programas já usa a nova versão, mas ainda não é possível abandonar a versão antiga. Ainda assim, novos aplicativos devem **SEMPRE** ser escritos com suporte a nova versão do Python em mente.

Por outro lado no ambiente Windows, como nenhuma ferramenta crítica é baseada em Python o uso da versão 2 se faz totalmente desnecessário.

# Variáveis

* Tipagem dinâmica
* Por referência
* Alocação de memória automática
* Coleta de lixo

Como já mencionado, Python é uma linguagem com *tipagem dinâmica*, isto significa que não é necessário declarar o tipo (numérico, texto, fluxo) do valor armazenado. A abordagem do Python define que o *tipo*, relaciona-se ao dado e não a variável, que atua somente como uma etiqueta (leia-se ponteiro).

Por exemplo:

```python
a = 3
b = 5
```

Operações podem ser realizadas com o literal ou com variáveis como:

```python
3 + 5
```

    8

```python
a + b
```

    8

## Tipos numéricos

Variáveis podem conter diferentes tipos de valores (inteiros, flutuantes ou *complexos*)

```python
pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286

i = 1j

idade = 22
```

É possível realizar operações algébricas entre diferentes tipos

```python
resultado = a + pi + i
resultado
```

    (6.141592653589793+1j)

Note que o resultado é um valor complexo (o maior conjunto).

### Métodos para tipos numéricos

Em Python é possível realizar operações específicas a cada tipo de dado. Chamamos estas operações de métodos.

Diferentes tipos de dados possuem métodos adequados as suas características, por exemplo, com nosso resultado complexo podemos extrair suas partes reais e imaginárias

```python
resultado.real
```

    6.141592653589793

```python
resultado.imag
```

    1.0

# Operações Aritméticas

Python utiliza os operadores tradicionais para realizar operações aritméticas como $+$, $-$, $*$ e $/$ para divisão e $**$ para potência.

Os parênteses (), são utilizados para priorizar uma operação (análogo a matemática convencional). Por outro lado os operadores [] {}, que definem níveis da priorização dos operadores não existem (em Python eles tem outra utilizade). Use os parentêses aninhados no lugar como

```12/(1+(2*(3+5)))```

tem como equivalente matemático

$$\frac{12}{1+\left[ 2 \cdot ( 3 + 5 ) \right]}$$

| Operação  | Significado |
|-----------|-------------|
| ()        | Executar operação primeiro |
| abs(x)     | Valor absoluto de $x$ |
| **        | Potência |
| *, /, //, %  | Multiplicação, Divisão, Divisão inteira, Divisão modular |
| +, -      | Soma, Subtração |

# Tipo de dados

Podemos descobrir o tipo do dado utilizando a *keyword* (palavra chave)

```type()```

Como em:

```python
type(a)
```

    int

```python
type(pi)
```

    float

```python
type(resultado.real)
```

    float

```python
type(resultado)
```

    complex

# Exercício: raízes de um polinômio de grau dois

Dada a equação polinomial

\begin{equation}
ax^2 + bx + c = 0,
\end{equation}

encontar as raízes $x_1$ e $x_2$ que podem ser obtidas através da fórmula

\begin{equation}\label{delta}
\Delta = b^2 - 4 a c
\end{equation}
e
\begin{equation}\label{raizes}
x = \frac{-b \pm \sqrt{\Delta}}{2a}.
\end{equation}

Vamos apresentar uma passo a passo para resolver este problema, tente preencher as lacunas. (e não se acostume)

1. Declare as variáveis Python `a`, `b` e `c`, que irão armazenar os coeficientes polinomiais. Lembre-se de sempre digitar `SHIFT + ENTER` para executar os comandos.

```python
# Faça aqui.
```

2. Declare uma variavel `delta` que armazena a operação da equação $\Delta$. Verifique a tabela de operações caso não lembre algum operador.

```python
# Faça aqui
```

3. Declare uma variável `x1` que recebe a forma positiva da equação $x$ e uma variável `x2` que recebe a forma negativa. Faça em dois comandos separados. Dica: A potência de $\frac{1}{2}$ pode ser utilizado como raiz quadrada. Exemplo:

\begin{equation}
4^{\frac{1}{2}} = 2
\end{equation}

```python
# Calcule e armazene x1 aqui
```

```python
# Calcule e armazene x2 aqui
```

Descomente abaixo (retirar o #) para exibir as raizes encontradas e execute a linha com `SHIFT-ENTER`

Por exemplo se utilizar $a = 3, b = 5, c = 2$, deve-se encontrar as raízes $x_1 = -\frac{2}{3} \approx -0,66$ e $x_2 = -1$

```python
#x1, x2
```

Abaixo você pode ver a resposta, recomenda-se não descomentar até tentar bastante. Aprendemos mais com os erros do que com os acertos.

```python
# RESPOSTA
# %load .resps/seggrau.py
```

# Strings

Strings (em português: cadeias), são normalmente utilizados para fazer referência a uma sequência de caracteres alfanuméricos. O uso mais comun é armazenar textos como *nomes*, *etiquetas*, *endereços*.

Strings são definidos como conjuntos de caracteres envoltos por aspas simples `'` ou duplas `"`.

É importante notar que números armazenados como *strings* perdem seu sentido numérico e passam a ser considerados como parte de um texto, por isso não podem ser utilizados em operações algébricas.

No Python prefere-se utilizar as aspas simples como delimitador de strings, exceto quando necessário usar as aspas duplas (no caso de haver as aspas simples no texto).

```python
nome = "Beto Silva"
universidade = "Universidade do Estado do Rio de Janeiro"
```

```python
universidade
```

    'Universidade do Estado do Rio de Janeiro'

```python
type(nome)
```

    str

## Operações com strings

É possível concatenar (podemos pensar como somar) strings utilizando o operador "+". O operador '*' permite repetir uma string um quantidade determinada de vezes.

Lembre-se que a soma de números dentro de uma string não é possível, ao invés disso as strings são concatenadas.

```python
nome + ' estuda na ' + universidade
```

    'Beto Silva estuda na Universidade do Estado do Rio de Janeiro'

```python
frase = nome + ' estuda na ' + universidade
frase
```

    'Beto Silva estuda na Universidade do Estado do Rio de Janeiro'

```python
10 * 'Nan' + ' Batman'
```

    'NanNanNanNanNanNanNanNanNanNan Batman'

```python
a = '10'
b = '20'
a + b
```

    '1020'

## Índices e Fatias

É possível acessar partes de uma string utilizando índices (*indexes*) e fatias (*slices*). Com isso, podemos selectionar um único caracter ou um grupo deles.

Um índice pode ser acessado com

`variavel[n]`

onde `n` é a posição que deseja acessar (começando em 0).

Podemos também acessar as fatias utilizando a notação:

`variavel[a:b:inc]`

Onde `a` é a posição inicial e `b` a posição final (não inclusa). Pode-se também fazer refererência a indexação reversa utilizando o sinal negativo ($-$). O terceiro valor `inc` é opcional e pode ser inclusive reverso (sinal negativo)

```python
universidade[0], universidade[16], universidade[26], universidade[33]
```

    ('U', 'E', 'R', 'J')

```python
nome[0:4]
```

    'Beto'

```python
universidade[-10:-2]
```

    'de Janei'

```python
alfabeto = 'abcdefghijlmnopqrstuvxyz'
alfabeto[0:15:4]
```

    'aein'

```python
universidade[-1:-15:-1]
```

    'orienaJ ed oiR'

## Funções e métodos

Assim como os tipos numéricos, as strings também possuem funções e métodos que podem ser utilizados. Abaixo existe alguns exemplos do que pode ser utilizado. Se estiver interessado veja outros [métodos](https://docs.python.org/3/library/stdtypes.html#string-methods) de strings.

```python
universidade.upper()
```

    'UNIVERSIDADE DO ESTADO DO RIO DE JANEIRO'

```python
nome.lower()
```

    'beto silva'

```python
nome.count('o')
```

    1

```python
len(nome)
```

    10

# Strings de formatação

* Usado para formatar strings

* Possui 3 formas

  * Antigo (`%`)

  * Atual (`{}` e `format`)

  * Futuro (f-strings)

Para imprimir strings em conjunto com outros tipos de dado é necessário criar uma string de formatação. Esta string utiliza-se de símbolos especiais que são substituídos pelo conteúdo das variáveis espeficidadas. Dentro do Python existem diversas formas de realizar esta formatação. Aqui daremos enfase o método mais utilizado.

Uma string de formatação utiliza os caracteres `{}` como um coringa a ser substituído pela variável, na ordem quem que ela aparece.

## Exemplos de Strings de Formatação

```python
frase_fmt = '{} estuda na {}'
```

```python
frase = frase_fmt.format(nome, universidade)
```

```python
print(frase)
```

    Beto Silva estuda na Universidade do Estado do Rio de Janeiro

```python
patrimonio = '1 milhão e 42 mil reais'
```

```python
print('Oi. Meu nome é {}, tenho {} anos e '
      '{} de patrimônio acumulado.'.format(nome, idade, patrimonio))
```

    Oi. Meu nome é Beto Silva, tenho 22 anos e 1 milhão e 42 mil reais de patrimônio acumulado.

No caso de querer formatar uma string, é melhor usar as representações com `f-string` ou `r-string`.

* `f-string`:
    Colocar `f` antes das aspas duplas (ou simples) que iram identificar a string. Permite usar de uma forma mais clara a criação de strings com variáveis.

* `r-string`:
    Colocar `r` antes das aspas duplas (ou simples). Essa opção identifica uma `raw-string`, em que cada caracter vai ser interpretado na sua forma original.

```python
f"{nome} estudo na {universidade}"
```

    'Beto Silva estudo na Universidade do Estado do Rio de Janeiro'

```python
r"{nome} estudo na {universidade}"
```

    '{nome} estudo na {universidade}'

```python
print(f'Oi. Meu nome é {nome}, tenho {idade} anos e {patrimonio} de patrimônio acumulado.')
```

    Oi. Meu nome é Beto Silva, tenho 22 anos e 1 milhão e 42 mil reais de patrimônio acumulado.

## Formatando variáveis

É possível formatar a apresentação das variáveis, como limitar o número de caracteres, alinhar a direita, mostrar somente 3 casas decimais. Para tal deve-se passar parametros para cada um dos coringas da string de formatação. Aqui veremos como formatar *strings*, *inteiros* e *valores de ponto flutuante*.

O elemento coringa `{}` deve ser formatado da seguinte forma:

```
'{:MNT}'
```

onde `M` é o modificador, `N` é o número de caracteres e `T` é o tipo sendo formatado. Os parametros `M`, `N` e não são obrigatórios e podem ser omitidos.

```python
print("Numero:  {:05d}".format(42))
```

    Numero:  00042

```python
print("A próxima palavra {:>10s} será alinhada à direita".format("qual"))
```

    A próxima palavra       qual será alinhada à direita

```python
print("Podemos representar PI {:4.2f} com 2 ou 10 casas "
      "decimais {:.10f}. Podemos inclusive mostrar em "
      "notação científica {:e}.".format(pi, pi, pi))
```

    Podemos representar PI 3.14 com 2 ou 10 casas decimais 3.1415926536. Podemos inclusive mostrar em notação científica 3.141593e+00.

### Mais exemplos de formatação

| Tipo | Formato | Explicação |
|------|---------|------------|
| {:d} | Inteiro | Exibe um valor inteiro |
| {:5d} | Inteiro | Exibe um inteiro alinhado a direita em 5 casas |
| {:05d} | Inteiro | Exibe um inteiro completando com 0 a direita até 5 casas |
| {:f} | Flutuante | Exibe um valor de ponto flutuante |
| {:<5f} | Flutuante | Exibe um valor de ponto flutuante até 4 dígitos e ponto alinhado a esquerda |
| {:5.2f} | Flutuante | Exibe um valor de ponto flutuante até 4 dígitos e ponto sendo 2 deles decimais |
| {:.2e} | Flutuante | Exibe em formato de notação científica com 2 casas decimais |
| {:s} | String | Exibe uma string |
| {:25s} | String | Exibe 25 caracteres de uma string |
| {:>25s} | String | Exibe 25 caracteres da string alinhado a direita |

# Condicionais

Operações condicionais são utilizadas para decidir o fluxo de um programa, normalmente são utilizados realizando comparações entre diferentes variáveis, caso a condição seja verdadeira, uma parte do código é executada, caso contrário outa parte do código é executada. Esta operação é uma das condições necessárias para que a lingaguem seja Turing Completa. Em Python os condicionais são as palavras chave `if`, `else`, `elif` e `while` (este último veremos mais adiante).

## Condições

```python
5 >= 3
```

    True

```python
5 < 3
```

    False

```python
nome.lower() == "beto"
```

    False

```python
nome[0:4].lower() == "beto"
```

    True

O valor de retorno de uma condição é do *tipo* **boleano**, que pode assumir dois valores `True` ou `False` (a primeira letra é uma maiúsculas).

## Tabela de operadores condicionais

Os operadores condicionais podem ser de dois tipo **unários** e **binários**. Os operadores unários atuam no elemento seguinte. O operador binário fica entre os dois elementos sendo avaliados. São equivalentes aos operadores lógico e matemáticos conhecidos.

| Operação  | Significado Matemático |
|-----------|-------------|
| ==, !=        | $=$, $\ne$ |
| >, >=, <, <=        | $\gt$, $\ge$, $\lt$, $\le$ |
| `in`  | $\subset$ |
| `not` | $\neg$ |
| `and` | $\land$ |
| `or` | $\vee$ |

Operadores condicionais tem menor prioridade do que os operadores aritméticos, ou seja, são analisados após as operações algébricas.

Os operadores `not`, `and` e `or` são operadores boleanos, isto é, somente são aplicados sobre tipos boleanos.

# Declaração condicional `if`, `elif` e `else`

* Três formas mais utilizadas
* Indentação é a estrutura de controle dos blocos de código
* Somente a primeira condição verdadeira é executada.

## Declaração `if`

Forma mais simples de realizar uma sentença condicional. Se `CONDIÇÃO` for verdadeira, executa o código indentado que segue imediatamente a declaração. Ao terminar o código indentado a execução do código continua na proxima linha após a declaração.

```
if CONDIÇÃO:
    Bloco de Código se verdadeiro
```

Exemplo:

```python
temperatura = 28
```

```python
if temperatura > 24:
    print("Muito quente, vou ligar o ar condicionado.")
    temperatura = temperatura - 5
print("Agora a temperatura é {}. Desta forma consigo estudar.".format(temperatura))
```

    Muito quente, vou ligar o ar condicionado.
    Agora a temperatura é 23. Desta forma consigo estudar.

## Declaração `if` `else`

Permite declarar blocos de código que são executados caso `CONDIÇÃO` seja verdadeira ou caso seja falsa.

```
if CONDIÇÃO:
    Bloco de Código se verdadeiro
else:
    Bloco de Código se falso
```

Exemplo:

```python
idade = 21
```

```python
if (idade < 18) or (idade > 65):
    print("Meia entrada garantida.")
else:
    print("Tem que pagar inteira.")
```

    Tem que pagar inteira.

## Declaração `if` `elif...` `else`

```
if CONDIÇÃO1:
    Bloco de Código se CONDIÇÃO1 verdadeira
elif CONDIÇÃO2:
    Bloco de código se CONDIÇÃO2 verdadeira
...
else:
    Bloco de código se todas condições são falsas
```

O bloco condicional com `elif` permite que múltiplas condições sejam testadas, é importante notar que no caso de uma das condições ser validadas nenhuma outra é testada pois no fim do bloco condicional o fluxo de execução pula para o fim da declaração if.

```python
idade = 22
if idade >= 35:
    print("Elegível para Presidente e Senador")
elif idade >= 30:
    print("Elegível para governador")
elif idade >= 21:
    print("Elegivel para deputado e prefeito")
elif idade >= 18:
    print("Elegível para vereador")
else:
    print("Não elegível")
# Codigo continua...
```

    Elegivel para deputado e prefeito

Repare que há um bug lógico no código, a idade definida é $22$, intuitivamente acredita-se que deveria mostrar tanto a string que referencia o `vereador` como a do `deputado e prefeito`, mas nao é isso que ocorre. Isto ocorre por que uma vezq que a declaração `if` é tomada como verdadeira (`True`) as outras hipóteses não são testadas. Como você poderia corrigir esta lógica?

## Exercício (condicionais)

Dado um intervalo qualquer $I = [a, b]$  verificar se o valor armazenado em `c` pertence à $I$, isto é, $c \in I$. Caso seja, imprimir $c$, caso não seja imprimir o valor mais próximo contido no intervalo. Pontos extra se resolver tanto os casos onde $a \le b$ e $b \le a$.

```python
# Sua resposta aqui
```

```python
# GABARITO
# %load .resps/cond.py
```

# Listas

```python
lst_vazia = []
```

```python
lst_numeros = [ 1, 2, 2, 4, 8, 32, ]
```

```python
lst_alunos = [ 'Alice', 'Betto', 'Carla', 'Daniel', 'Ericka' ]
```

```python
type(lst_numeros)
```

    list

```python
lst_alunos[0]
```

    'Alice'

```python
type(lst_alunos[2])
```

    str

```python
lst_numeros[1::2]
```

    [2, 4, 32]

```python
type(lst_alunos[:2])
```

    list

```python
'Ericka' in lst_alunos
```

    True

A *lista* é a a estrutura de dados mais elementar do Python, ela permite armazenar uma coleção de objetos de diferentes tipos de forma ordenada além disso possui métodos bastante úteis para realizar manipulações.

Para definir uma lista basta delimitar com `[` e `]`  uma sequencia de objetos separados por vírgulas.

A lista é um tipo próprio e os elementos dentro das listas preservam o seu tipo.

Elementos de uma lista podem ser acessados utilizando seu índice ou através de fatias (slices). Uma fatia de uma lista é também uma lista.

É possível utilizar o operador de pertinência `in` para verificar se um objeto existe na lista.

## Operações com listas

```python
2 * lst_numeros
```

    [1, 2, 2, 4, 8, 32, 1, 2, 2, 4, 8, 32]

```python
lst_numeros + lst_numeros
```

    [1, 2, 2, 4, 8, 32, 1, 2, 2, 4, 8, 32]

```python
lst_numeros + lst_alunos
```

    [1, 2, 2, 4, 8, 32, 'Alice', 'Betto', 'Carla', 'Daniel', 'Ericka']

Assim como as strings listas suportam a operação de concatenação `+` e repetição `*`. Repare que mesmo que uma lista contenha somente números os operadores `+` e `*` não realizam operações algébricas. *Uma lista **não** é um vetor matemático*.

## Métodos em listas

```python
lst_numeros.append(512)
lst_numeros
```

    [1, 2, 2, 4, 8, 32, 512]

```python
lst_alunos.reverse()
lst_alunos
```

    ['Ericka', 'Daniel', 'Carla', 'Betto', 'Alice']

```python
lst_alunos.sort()
lst_alunos
```

    ['Alice', 'Betto', 'Carla', 'Daniel', 'Ericka']

```python
lst_alunos.pop()
```

    'Ericka'

```python
lst_alunos.insert(1, 'Zoraide')
lst_alunos
```

    ['Alice', 'Zoraide', 'Betto', 'Carla', 'Daniel']

```python
lst_alunos.remove('Zoraide')
lst_alunos
```

    ['Alice', 'Betto', 'Carla', 'Daniel']

## Funções em listas

```python
len(lst_alunos)
```

    4

```python
max(lst_numeros)
```

    512

```python
min(lst_alunos)
```

    'Alice'

```python
sorted(lst_alunos)
```

    ['Alice', 'Betto', 'Carla', 'Daniel']

# Dividindo listas e unindo strings

```python
palavras = universidade.split(' ')
palavras
```

    ['Universidade', 'do', 'Estado', 'do', 'Rio', 'de', 'Janeiro']

```python
' boing '.join(palavras)
```

    'Universidade boing do boing Estado boing do boing Rio boing de boing Janeiro'

Por ser uma estrutura de dados muito elementar e muito utilizada, listas em Python otimizadas para performance (quanto possível). Listas podem ser facilmente adaptadas como uma pilha através das operações `append` e `pop`. Infelizmente o uso delas não serve como resposta para a disciplina de Algoritmos.

## Complexidade de operações em uma Lista

| Operação | $O$ |
|----------|-----|
| append | O(1) |
| pop    | O(1) |
| insert | O(n) |
| get    | O(1) |
| set    | O(1) |
| remove | O(n) |
| len    | O(1) |
| sort   | O(n log n) |
| x in   | O(n) |
| min    | O(n) |
| max    | O(n) |

Internamente as listas são armazenadas como um vetor, assim os maiores custos de operação em uma lista acontecem quando se insere um objeto proximo ao início, pois tudo deve ser remanejado e quando é necessário extender a lista pois toda memória deve ser copiada para uma nova região contígua.

# Laço condicional `while`

Executa repetidamente um bloco de código enquanto uma condição é verdadeira.

## Sintaxe:

```
while CONDIÇÃO:
    bloco a ser executado enquanto CONDIÇÃO é verdadeira
```

```python
# Imprime os números de Fibonacci menores que 10
a, b = 0, 1
while a < 10:
     print(a, end=', ')
     a, b = b, a+b
```

    0, 1, 1, 2, 3, 5, 8,

Repare no parâmetro adicional (`end`) passado à função `print`, ele indica que a string impressa não será terminada por uma nova linha (`\n`) e sim por uma vírgula e espaço.

## Exercício

Dado o algoritmo para obter os números de *Fibonacci* acima, altere-o para que exiba os $n$ primeiros. Onde $n$ é definido em uma variável.

```python
# Sua resposta aqui
```

```python
# GABARITO
# %load .resps/fibo.py
```