In [22]:

```
import numpy as np
```

**Write code to print the numbers 0 to 4 on each line below.**

In [53]:

```
print(0)
print(1)
print(2)
print(3)
print(4)
```

- Okay, let's keep going to 10000...(!?)

- Loops in programing are used to simplify repetative work.
- Above, each line is a print statement.
- The only thing different on each line is the number we are printing.

- We can write a loop statment to do the above problem as follows

In [54]:

```
for i in range(10):
print(i)
```

- What are the parts of this: list them?
`i`

can be any variable, not just "i"- Is there anything weird or unexpected here?

- We can put
**any**code in the for loop- Variables, functions, expressions, math, etc.

- We can put variables outside of the loop that are available inside of the loop

For the ideal gas law, pressure is given by $$P = nRT/V$$

- n = 1 kmol
- R = 8314 J/kmol*K
- T = 300 K

**For V = 2, 3, 4, 5, ... 20, use a loop to find and print the values of P for each V.**

In [1]:

```
n = 1
R = 8314
T = 300
for V in range(2,21):
P = n*R*T/V
print(P)
```

- What if you wanted V to not step by integers?
- Step by 2? Step by 5?
- Step by 0.2?

**Add all the numbers from 0 to 100**

- Before you start the code, think about what you would do if solving this in your head?
- How do you start?
- What things do you keep track of?
- What variables to use?
- What is the loop syntax?
- How do variables interact with the loop?

- Think through the process of the problem to the solution
- Talk to your neighbor
- If you've solved it, help your neighbor.

In [9]:

```
s = 0
for i in range(101):
s = s + i
print(s)
```

- We can put
**any**code in a`for`

loop. Even another loop. - Look at the code below.
**Before running it, think of what you expect to see.**- Now run it and compare. Did you get what you thought you would?

```
for i in range(3):
print(f"i={i}")
for j in range(4):
print(f" j={j}")
```

In [4]:

```
for i in range(3):
print(f"i={i}")
for j in range(4):
print(f" j={j}")
```

- Note, each time through the top (outer) loop,
**everything**inside is done. - This means the
**whole**inner loop is computed for each outer loop. **Think of an actual application for a nested loop.**

Given the following function $$f(x) = x^2 - 3,$$ we can use Newton's method to find $x$ for $f(x)=0$.

Recall, Newton recurrence formula: $$x_{new} = x_{old} - \frac{f(x_{old})}{f^\prime(x_{old})}$$

**Open Excel and solve this problem.**- Think about the steps involved, how we set it up.
**Use the simplest method possible.**

Excel | Python |
---|---|

cell for guess | ?? |

Newton equation in terms of x cell A2 - (A2^2-3)/(2*A2) |
?? |

repeat: fill down | ?? |

In [5]:

```
x = 1
for i in range(6):
x = x - (x**2 - 3)/(2*x)
print(x)
```

- Variable
`i`

is not being used, it is just for convenience in creating the loop. - Note how
`x`

is used on both sides of the equation. It is*reused*.

- We don't have to code it from top to bottom...
- Compare to Excel

Excel | Python |
---|---|

cell for guess | variable for x |

Newton equation in terms of x cell A2 - (A2^2-3)/(2*A2) |
Newton equation in terms of x x = x - (x**2-3)/(2*x) |

repeat: fill down | repeat: wrap in loop |

In [6]:

```
# step 1: initial guess
x = 1
# step 2: add Newton equation
x=1
x = x - (x**2 - 3)/(2*x)
# step 3: wrap in loop
x=1
for i in range(6):
x = x - (x**2 - 3)/(2*x)
# step 4: add a print
x=1
for i in range(6):
x = x - (x**2 - 3)/(2*x)
print(x)
```

**Redo Solution 1 using functions for $f(x)$ and $f^\prime(x)$.**

- Recall: we discussed functions two classes back.

In [7]:

```
def f(x):
return x**2 - 3
def fprime(x):
return 2*x
x = 1
for i in range(6):
x = x - f(x)/fprime(x)
print(f"after iteration {i+1}, x={x:.4f}")
```

- Now, to get to three decimal places we only needed 3 iterations.
- But we didn't know this at the beginning, so we guessed 6.
- If 6 wasn't enough, we would do more.

- This guess and check is not very efficient.

**Modify the code above to do just the right number of iterations.**

- What Python features do you need to use?
- How do you decide when you are done?
**Talk with your neighbor.**

In [8]:

```
def f(x):
return x**2 - 3
def fprime(x):
return 2*x
xold = 1
for i in range(6):
xnew = xold - f(xold)/fprime(xold)
err = np.abs( (xnew-xold) / xnew )
if np.abs(err < 1E-3):
break
print(f"after iteration {i+1}, x={xnew:.4f}")
xold = xnew
```

- Keep track of old and new x:
`xold`

and`xnew`

.- Need to reset
`xold=xnew`

at the end to get set for next interation.

- Need to reset
- New keyword
`break`

- Define the error and compare it to the desired accuracy.
- Use absolute value:
`np.abs()`

- Use absolute value:

In [ ]:

```
```