# Homework 2

**Instructions:** Complete the notebook below. Download the completed notebook in HTML format. Upload assignment using Canvas.

**Due:** Jan. 23 at **11am**.

## Exercise: NumPy Arrays

Follow the instructions in the following cells.

```python
# Import numpy

```

```python
# Use the 'np.arange()' function to create a variable called 'numbers1' that stores the integers
# 1 through (and including) 10

# Print the value of 'numbers1'

```

```python
# Use the 'np.arange()' function to create a variable called 'numbers2' that stores the numbers
# 0 through (and including) 1 with a step increment of 0.01

# Print the value of 'numbers2'

```

```python
# Print the 5th value of 'numbers2'. (Remember that the index starts counting at 0)

```

```python
# Print the last value of 'numbers2'.

```

```python
# Print the first 12 values of 'numbers2'.

```

```python
# Print the last 12 values of 'numbers2'.

```

```python
# Use the 'np.zeros()' function to create a variable called 'zeros' that is an array of 20 zeros

# Print the value of 'zeros'

```

```python
# Change the second value of 'zeros' to 1 and print

# Print the value of 'zeros'

```

## Exercise: Random Numbers

Follow the instructions in the following cells.

```python
# Set the seed of NumPy's random number generator to 126

# Create a variable called 'epsilon' that is an array containing 25 draws from
# a normal distribution with mean 4 and standard deviation 2

# Print the value of epsilon

```

```python
# Print the mean of 'epsilon'

```

```python
# Print the standard deviation of 'epsilon'

```

## Exercise: The Cobb-Douglas Production Function

The Cobb-Douglas production function can be written in per worker terms as :
  \begin{align}
  y & = A k^{\alpha},
  \end{align}
where $y$ denotes output per worker, $k$ denotes capital per worker, and $A$ denotes total factor productivity or technology.

### Part (a)

On a single axis: plot the Cobb-Douglas production for $A$ = 0.8, 1, 1.2, and 1.4 with $\alpha$ = 0.35 and $k$ ranging from 0 to 10. Each line should have a different color. Your plot must have a title and axis labels. The plot should also contain a legend that clearly indicates which line is associated with which value of $A$ and does not cover the plotted lines.

```python
# Import the pyplot module from Matplotlib as plt

# Select the Matlplotlib style sheet to use (Optional)

# Use the '%matplotlib inline' magic command to ensure that Matplotlib plots are displayed in the Notebook

```

```python
# Set capital share (alpha)

# Create an array of capital values

# Plot production function for each of the given values for A

# Add x- and y-axis labels

# Add a title to the plot

# Create a legend

# Add a grid

```

**Question**

1. *Briefly* explain in words how increasing $A$ affects the shape of the production function.

**Answer**

1.

### Part (b)

On a single axis: plot the Cobb-Douglas production for $\alpha$ = 0.1, 0.2, 0.3, 0.4, and 0.5 with $A$ = 1 and $k$ ranging from 0 to 10. Each line should have a different color. Your plot must have a title and axis labels. The plot should also contain a legend that clearly indicates which line is associated with which value of $\alpha$ and does not cover the plotted lines.

```python
# Set TFP (A)

# Plot production function for each of the given values for alpha

# Add x- and y-axis labels

# Add a title to the plot

# Create a legend

# Add a grid

```

**Question**

1. *Briefly* explain in words how increasing $\alpha$ affects the shape of the production function.

**Answer**

1.

### Exercise: The Cardioid

The cardioid is a shape described by the parametric equations:

  \begin{align}
  x & = a(2\cos \theta - \cos 2\theta), \\
  y & = a(2\sin \theta - \sin 2\theta).
  \end{align}

Construct a well-labeled graph of the cardiod for $a=4$ and $\theta$ in $[0,2\pi]$. Your plot must have a title and axis labels.

```python
# Construct data for x and y

# Plot y against x

# Create x-axis label

# Create y-axis label

# Create title for plot

# Add a grid to the plot

```

## Exercise: Unconstrained optimization

Consider the quadratic function:

\begin{align}
f(x) & = -7x^2 + 930x + 30
\end{align}

You will use analytic (i.e., pencil and paper) and numerical methods to find the the value of $x$ that maximizes $f(x)$. Another name for $x$ that maximizes $f(x)$ is the *argument of the maximum* value $f(x)$.

### Part (a): Analytic solution

Use standard calculus methods to solve for the value of $x$ that maximizes $f(x)$ to **five decimal places**. Use your answer to complete the sentence in the next cell.

 The value of $x$ that maximizes $f(x)$ is:

### Part (b):  Numerical solution

In the cells below, you will use NumPy to try to compute the argument of the maximum of $f(x)$.

```python
# Use np.arange to create a variable called 'x' that is equal to the numbers 0 through 100
# with a spacing between numbers of 0.1

# Create a variable called 'f' that equals f(x) at each value of the array 'x' just defined

# Use np.argmax to create a variable called xstar equal to the value of 'x' that maximizes the function f(x).

# Print the value of xstar

```

```python
# Use np.arange to create a variable called 'x' that is equal to the numbers 0 through 100
# with a spacing between numbers of 0.001

# Create a variable called 'f' that equals f(x) at each value of the array 'x' just defined

# Use np.argmax to create a variable called xstar equal to the value of 'x' that maximizes the function f(x).

# Print the value of xstar

```

```python
# Use np.arange to create a variable called 'x' that is equal to the numbers 0 through *50*
# with a spacing between numbers of 0.001

# Create a variable called 'f' that equals f(x) at each value of the array 'x' just defined

# Use np.argmax to create a variable called xstar equal to the value of 'x' that maximizes the function f(x).

# Print the value of xstar

```

### Part (c): Evaluation

Provide answers to the follow questions in the next cell.

**Questions**

1. How did the choice of step size in the array `x` affect the accuracy of the computed results in the first two cells of Part (b)?

2. What do you think is the drawback to decreasing the stepsize in `x`?

3. In the previous cell, why did NumPy return value for `xstar` that is so different from the solution you derived in Part (a)?

**Answers**

1.

2.

3.

## Exercise: Utility Maximization

Recall the two good utility maximization problem from microeconomics. Let $x$ and $y$ denote the amount of two goods that a person consumes. The person receives utility from consumption given by:
  \begin{align}
  u(x,y) & = x^{\alpha}y^{\beta}
  \end{align}
The person has income $M$ to spend on the two goods and the price of the goods are $p_x$ and $p_y$. The consumer's budget constraint is:
  \begin{align}
  M & = p_x x + p_y y
  \end{align}
Suppose that $M = 100$, $\alpha=0.25$, $\beta=0.75$, $p_x = 1$. and $p_y = 0.5$. The consumer's problem is to maximize their utility subject to the budget constraint. While this problem can easily be solved by hand, we're going to use a computational approach. You can also solve the problem by hand to verify your solution.

### Part (a)

Use the budget constraint to solve for $y$ in terms of $x$, $p_x$, $p_y$, and $M$. Use the result to write the consumer's utility as a function of $x$ only. Create a variable called `x` equal to an array of values from 0 to 80 with step size equal to 0.001 and a variable called `utility` equal to the consumer's utility. Plot the consumer's utility against $x$.

```python
# Assign values to the constants alpha, beta, M, px, py

# Create an array of x values

# Create an array of utility values

# Plot utility against x.

# x- and y-axis labels

# Title

# Add grid

```

### Part (b)

The NumPy function `np.max()` returns the highest value in an array and `np.argmax()` returns the index of the highest value. Print the highest value and index of the highest value of `utility`.

```python

```

### Part (c)

Use the index of the highest value of utility to find the value in `x` with the same index and store value in a new variable called `xstar`. Print the value of `xstar`.

```python
# Create variable 'xstar' equal to value in 'x' that maximizes utility

# Print value of 'xstar'

```

### Part (d)

Use the budget constraint to the find the implied utility-maximizing vaue of $y$ and store this in a variable called `ystar`. Print `ystar`.

```python
# Create variable 'ystar' equal to value in 'y' that maximizes utility

# Print value of 'xstar'

```


# Bending of the lithosphere under seamounts

**Goal:** Implement the finite-difference solution to the 1D flexure equation and compare it's predictions against observations of gravity disturbances and bathymetry.

With the appropriate boundary condition, we can use the 1D flexure equation to model the bending of the oceanic lithosphere under the load of a seamount or island chain. **Our assumption is that the plate is perfectly elastic and structures are infinite perpendicular to the profile.**

Figure caption: Sketch of the elastic plate flexure for a load $q(x)$.

## Governing equations

The equation describing the deflection ($w$) of an elastic plate subject to a vertical load is:

$$ D\dfrac{\partial^4 w}{\partial x^4} = q(x) - g (\rho_m - \rho_w) w $$

in which $x$ is the position along the profile, $D$ is the flexural rigidity of the plate, $rho_w$ and $rho_m$ are the water and mantle densities, $g$ is gravity (for these purposes, assume $9.8\ m/s^2$), and $q(x)$ is a force density applied by the load on the plate (the weight of the topography). The term $g (\rho_m - \rho_w) w$ is the restoring hydrostatic force (buoyancy) from replacing mantle material at depth with water on top because of the flexure.

The **flexural rigidity** $D$ can be described in terms of the plate's elastic parameters:

$$ D = \dfrac{E T_e^3}{12(1 - \nu^2)} $$

where $E$ is [Young's modulus](https://en.wikipedia.org/wiki/Young's_modulus), $\nu$ is [Poisson's ratio](https://en.wikipedia.org/wiki/Poisson's_ratio), and $T_e$ is the *effective elastic thickness*.

The **load force per unit area** $q(x)$ is the weight of the load applied on the lithosphere. For a load of height $h$ and density $\rho_c$, the weight per unit area is (negative because the force is applied downwards):

$$ q(x) = -g \rho_c h(x) $$

## Boundary conditions

If we assume that the load is applied somewhere in the middle of the plate, we can consider the boundaries as stable lithosphere under no load. In that case, we don't expect to see any deflection at the boundaries. We can also impose that the first derivative of deflection is zero at the boundaries (the plate approaches the boundaries horizontally, not at an angle). This leads to the boundary conditions:

$$
\begin{align}
    w(x=0) &= 0 \\
    w(x=x_{max}) &= 0 \\
    \dfrac{\partial w}{\partial x}(x=0) &= 0 \\
    \dfrac{\partial w}{\partial x}(x=x_{max}) &= 0
\end{align}
$$

## The data

**Download** (if you haven't already): [global-geophysical-data.nc](https://github.com/leouieda/lithosphere/raw/main/data/global-geophysical-data.nc) (place it in the **same folder** as this notebook)

The data grids are stored in a [netCDF](https://en.wikipedia.org/wiki/NetCDF) file, which is a very common standard for storing and distributing gridded data. It's used throughout the Earth, ocean, and climate sciences and can be read an manipulated with most software platforms. It contains global grids of gravity, topography, and heat flow. All grids were interpolated onto the same resolution of 0.2 degrees (a compromise between resolution and size of the file) so that we can easily compare and use all of the data together.

* **Gravity**: generated from the [EIGEN-6C4 spherical harmonic model](https://doi.org/10.5880/icgem.2015.1) through the [ICGEM webservice](http://icgem.gfz-potsdam.de/home). It includes two grids: the gravity disturbance calculated with the WGS84 ellipsoid and the Bouguer gravity disturbance calculated using a topography density of 2670 kg/m³. The data for both grids was generated on top of the Earth's surface (the water surface in the oceans and topography on land).
* **Topography and bathymetry**: a downsampled version of [ETOPO1](https://doi.org/10.7289/V5C8276M) and includes a version smoothed using a Gaussian filter with 1 degree width (~100 km).
* **Heat flow**: an upsampled version of the compilation by [Lucazeau (2019)](https://doi.org/10.1029/2019GC008389) (originally 0.5 degree resolution).
* **Lithosphere age (oceanic)**: a downsampled version of the grid by [Müller et al. (2008)](https://doi.org/10.1029/2007GC001743) (originally 6 arc-minutes).

## Import the required libraries

Load the required software to load the data, make maps, and perform calculations.

```python
# For arrays and linear algebra
import numpy as np
# To make figures and maps
import matplotlib.pyplot as plt
# To load and manipulate grids
import xarray as xr
# Import our own module (lithosphere.py)
import lithosphere
```

## Load the data grids

Once again, we'll use xarray to load the data from the netCDF file.

```python

```

```python

```

## Extracting a profile

Once again, we'll extract a profile from our data grids. This time, we will use the function that we placed in `lithosphere.py` so we don't have to copy the code into this notebook.

First, let's slice a region in the North Atlantic where there are some nice seamounts.

```python

```

Now extract a profile that cuts across the seamount chain.

```python

```

Plot the location of the profile.

```python

```

And the profile topography and gravity disturbance data.

```python

```

We will need the height of the seamount load above the background bathymetry for our modeling. So let's see if we can calculate that.

```python

```

```python

```

## Solving the flexure equation by finite-differences

The finite-difference solution to the flexure equation is the solution (the $w_i$ terms) to the equation system:

$$
\begin{align}
  D w_{4} - 4 D w_{3} + \left[6D + \Delta x^4 (\rho_m - \rho_w) g\right] w_2 - 4 D w_{1} + D w_{0} &= \Delta x^4 q_2  \\
  D w_{5} - 4 D w_{4} + \left[6D + \Delta x^4 (\rho_m - \rho_w) g\right] w_3 - 4 D w_{2} + D w_{1} &= \Delta x^4 q_3  \\
  \vdots & \\
  D w_{N-1} - 4 D w_{N-2} + \left[6D + \Delta x^4 (\rho_m - \rho_w) g\right] w_{N-3} - 4 D w_{N-4} + D w_{N-5} &= \Delta x^4 q_{N-3} \\
  w_0 &= 0  \\
  w_{N-1} &= 0  \\
  w_1 - w_0 &= 0  \\
  w_{N-1} - w_{N-2} &= 0
\end{align}
$$

Here, the continuous $w$ and $q$ have been discretized into $N$ values with a spacing of $\Delta x$ between them.

Another way of writing this equation system is using a matrix notation:

$$
\underbrace{
\begin{bmatrix}
  D  & -4D & \left[6D + \Delta x^4 (\rho_m - \rho_w) g\right] & -4D & D & 0 & 0 & \ldots & 0 & 0 \\
  0 & D  & -4D & \left[6D + \Delta x^4 (\rho_m - \rho_w) g\right] & -4D & D & 0 & \ldots & 0 & 0 \\
  \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots  \\
  1 & 0 & 0 & 0 & 0 & 0 & 0 & \ldots & 0 & 0  \\
  0 & 0 & 0 & 0 & 0 & 0 & 0 & \ldots & 0 & 1  \\
  -1 & 1 & 0 & 0 & 0 & 0 & 0 & \ldots & 0 & 0  \\
  0 & 0 & 0 & 0 & 0 & 0 & 0 & \ldots & -1 & 1
 \end{bmatrix}
}_{\bar{\bar{A}}}
\underbrace{
\begin{bmatrix}
  w_0 \\
  w_1 \\
  w_2 \\
  w_3 \\
  w_4 \\
  w_5 \\
  w_6 \\
  \vdots \\
  w_{N-1}
 \end{bmatrix}
}_{\bar{w}}
 =
\underbrace{
\begin{bmatrix}
  \Delta x^4 q_2 \\
  \Delta x^4 q_3 \\
  \vdots \\
  0\\
  0\\
  0\\
  0
 \end{bmatrix}
}_{\bar{b}}
$$

$$
\bar{\bar{A}} \bar{w} = \bar{b}
$$

We'll need to figure out a way to build the $\bar{\bar{A}}$ matrix and $\bar{b}$ vector. Once we have those, we can the deflection $\bar{w}$ using `numpy.linalg.solve`.

Let's write write a function that builds the matrix and vector and then solves the system.

```python

```

We'll assume that the flexural parameters of the lithosphere are:

* Poisson's ratio: $\nu = 0.25$
* Young's modulus: $E = 70 \times 10^9\ \frac{kg}{s^2 m}$

We'll vary the effective elastic thickness $T_e$ as needed but it will probably be around 20-40 km.
With these, we can calculate the flexural rigidity $D$.

```python

```

Now we can solve for $w$.

```python

```

```python

```

## Predicting gravity

We can also predict the observed gravity disturbances from the calculated deflection. To do so, we derive the density anomalies caused by the downward deflection of the oceanic crust. The figure below illustrate a conceptual model of the density anomalies causing the observed data.

Figure caption: Model of the density anomalies causing the observed gravity disturbance due to the flexure and the presence of the seamount.

The gravitational effect of these density anomalies can be estimated using a **Bouguer plate approximation** by carefully assigning the correct density contrasts to each part of the model:

$$ g \approx 2 \pi G \Delta\rho |w| $$

To make things easier, we can split the effect into 3 parts which can be added together to produce the final result:

1. The seamount
2. The deflection at the surface
3. The deflection at the Moho

Let's write a function that calculates the predicted gravity for our seamount flexure.

```python

```

Now we can predict the gravity disturbance and plot it agaisnt our observed data.

```python

```

```python

```

The fit is not great. Our predictions seem to be a bit too small. There are 2 effects that we neglected in our gravity calculations above:

1. The effect of the surface deflection should not be included underneath the seamount
2. The downwards flexure at the surface is not filled with water (look at the bathymetry data). It's actually been packged with sediments.

Let's make a new function that takes these 2 effects into account.

```python

```

Recalculate the predicted gravity and plot it along side the data and our previous estimate.

```python

```

```python

```

---

## **Your turn!**

Try out the new modelling tools to investigate a group of seamounts in the Southwest Pacific ocean. The age of the lithosphere is much larger than the example from the Atlantic we just saw (which was next to the mid-ocean ridge). So we expect the lithosphere to be thicker, colder, and denser.

In groups:

1. Extract a profile cutting across one (or more) seamounts
1. Plot the observed gravity and bathymetry along the profile
1. Calculate the deflection caused by the load of the seamount(s)
1. Use the deflection to predict the gravity distubance and compare against observations (you may have to adjust the values of density and effective elastic thickness)
1. Discuss:
    1. What we can learn from these models about seamounts and elastic properties of the oceanic lithosphere
    1. The main limitations of the 1D modelling approach and the approximations we used for the gravity calculations

Share with the class:

1. The plots of your profile data, location, and model predictions
1. The key discussion points

```python
pacific = data.sel(longitude=slice(150, 180), latitude=slice(5, 20))
pacific.topography.plot(figsize=(14, 8))
```

```python

```

```python

```

```python

```


## Demonstration of Lorenz Coefficient for Quantifying Spatial, Subsurface Heterogeneity

#### Alan Scherman, Rice University, UT PGE 2020 SURI

#### Supervised by:

#### Michael Pyrcz, Associate Professor, University of Texas at Austin

##### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1) | [GeostatsPy](https://github.com/GeostatsGuy/GeostatsPy)

***
#### Introduction

This is a demonstration of how to calculate the Lorenz Coefficient of a subsurface sample from well log porosity and permeability measurements. The Lorenz Coefficient is an important heuristic imported form the sphere of macroeconomics used to quantify the spatial heterogeneity of a subsurface sample. The Lorenz Coefficient is obtained by doubling the area between the Lorenz Curve and the Homogeneous Line. It ranges from 0 to 1 where, by convention, a coefficient of less than 0.3 suggests low heterogeneity and a coefficient of more than 0.6 indicates high heterogeneity. In practical terms, a low spatial heterogeneity allows for simple displacement of subsurface fluids and a high recovery factor.
***
#### Objective

To understand and apply the methodology to calculate the Lorenz Curve and Coefficient from porosity and permeability measurements through Python functionalities.

***
#### Calculation procedure

The following list contains the necessary steps to determine the Lorenz Coefficient of a subsurface sample:

**(1)** Sort porosity ($\phi$) and permeability (**_k_**) in descending order of ratio **_k_**/$\phi$;

**(2)** Calculate storage (**_S.C._**) and flow capacity (**_F.C._**) of each layer (region between depth measurements) with:

\begin{equation}
S.C. = \phi*h
\end{equation}
\begin{equation}
F.C. = k*h
\end{equation}

where **_h_** is the layer thickness;

**(3)** Calculate the _cumulative_ storage (**_C.S.C._**) and flow capacities (**_C.F.C._**) of each layer with:

\begin{equation}
C.S.C. = \sum^{current layer}_{i = 1} \phi*h
\end{equation}
\begin{equation}
C.F.C. = \sum^{current layer}_{i = 1} k*h
\end{equation}

**(4)** Normalize the cumulative storage and flow capacities by dividing them by the largest cumulative storage and flow capacities (i.e. the last cumulative capacities calculated), respectively;

**(5)** _(Optional)_ Plot the normalized cumulative flow capacities against the normalized cumulative storage capacities (i.e. the Lorenz Curve);

**(6)** Find a curve fit for the normalized capacities in the Cartesian plane (usually a 3rd degree polynomial is sufficient);

**(7)** Integrate to find the area between the Lorenz Curve and the Homogenous Line;

**(8)** Divide the result found in **(7)** by 0.5 to obtain the Lorenz Coefficient:

\begin{equation}
LorenzCoefficient = \frac{\int^{1}_{0} (LorenzCurve - HomogeneousLine)}{0.5}
\end{equation}
***
#### Load the required libraries

The program below utilizes some standard Python packages. These should be previously installed if you have Anaconda or other similar software.

```python
import pandas as pd                                                  # To import data from .xlsx or .csv file
import numpy as np                                                   # For numerical array management
from matplotlib import pyplot as plt                                 # For graphical display of Lorenz Curve
```

If you get a package import error, you may have to first install some of these packages. This can usually be accomplished by opening up a command window on Windows and then typing 'python -m pip install [package-name]'. More assistance is available with the respective package docs.
***
#### Importing porosity and permeability data

The data file for this demonstration is availbale at [here](https://github.com/GeostatsGuy/GeoDataSets/blob/master/WellPorPermSample_3.xlsx).

The well log data will be imported from an Excel (.xlsx) file. There are similar Pandas methods which allow the importation of data from .csv and other common file types. First, the Excel data is stored as a Pandas data frame. Then, the depth, porosity, and permeability data are placed into separate data frames by means of their Excel column names. Make sure that the strings match every character of the column titles in the Excel file.

```python
import os
#os.chdir('C:\PGE383')
#df = pd.read_excel('WellPorPermSample_3.xlsx')                # Include file directory with os.chdir() method if necessary
df = pd.read_csv(r'https://raw.githubusercontent.com/GeostatsGuy/GeoDataSets/master/WellPorPermSample_3.csv')

depth = pd.DataFrame(df, columns = ['Depth (m)']);
poros = pd.DataFrame(df, columns = ['Por (%)']);
perme = pd.DataFrame(df, columns = ['Perm (mD)']);
```

To certify that the subsurface data have been imported appropriately:

```python
df.head()
```

      Depth (m)
      Por (%)
      Perm (mD)

      0
      0.25
      13.0
      265.5

      1
      0.50
      13.6
      116.9

      2
      0.75
      9.0
      136.9

      3
      1.00
      17.6
      216.7

      4
      1.25
      9.4
      131.6

***
#### Convert data frames to NumPy arrays

In order to facilitate data management and allow the use of helpful mathematical methods, we'll convert the Pandas data frames to NumPy arrays. Also, let's transpose the arrays to row format for conventionality.

```python
depth = np.transpose(depth.to_numpy()[:,0])
poros = np.transpose(poros.to_numpy()[:,0])
perme = np.transpose(perme.to_numpy()[:,0])
```

Once again, let's take a look at the resulting arrays:

```python
print('depth =', depth[:5], '\nporos =', poros[:5], '\nperme =', perme[:5])   # To visualize the first 5 elements of each array
```

    depth = [0.25 0.5  0.75 1.   1.25]
    poros = [13.  13.6  9.  17.6  9.4]
    perme = [265.5 116.9 136.9 216.7 131.6]

***
#### Determine thicknesses of layers

The layer thickness is found by subtracting a shallower depth from a deeper depth. For most well logs, the layers will have a uniform thickness. However, irregular thicknesses are also possible and should be accounted for. Whichever is the case, the layer thicknesses array can be calculated in the following manner:

```python
layer_thick = depth - np.concatenate(([0],depth[:-1]))
```

Note that the layer_thick array should have the same dimensions as the porosity and permeability arrays.
***
#### Step (1) - Sort data in decreasing order of k/$\phi$

Recall that the first step to calculate the Lorenz Coefficient is to sort all layers in descending order of their ratio of permeability by porosity. Because both the porosity and permeability values are expressed as NumPy arrays, these ratios can be easily obtained by:

```python
ratio = perme/poros                                                           # Equivalent to np.multiply(perme,poros)
```

Now, it's possible to sort the layer thickness, porosity and permeability arrays in the desired pattern:

```python
layer_thick = np.flip(layer_thick[np.argsort(ratio)], axis = 0);
poros = np.flip(poros[np.argsort(ratio)], axis = 0)
perme = np.flip(perme[np.argsort(ratio)], axis = 0)
```

***
#### Step (2) - Calculate storage and flow capacities

The storage and flow capacities are found by performing element-wise multiplication of the porosity and permeability arrays by the thickness array. Hence:

```python
storage_cap = poros*layer_thick
flow_cap = perme*layer_thick
```

***
#### Step (3) - Calculate the cumulative storage and flow capacities

The next step is to compute the cumulative capacities for each layer. An easy solution to this assignment is provided by a for-loop. First, we pre-allocate the cumulative storage and flow capacities arrays. Then, we set the cumulative capacities of the first layer equal to its own capacities. Finally, we run a for-loop to compute the remaining cumlative capacities for the sequential layers.

```python
cumul_storage_cap = np.zeros(len(flow_cap)+1)
cumul_flow_cap = np.zeros(len(flow_cap)+1)

cumul_storage_cap[1] = storage_cap[0]
cumul_flow_cap[1] = flow_cap[0]

for i in range(2,len(flow_cap)+1):
    cumul_storage_cap[i] = cumul_storage_cap[i-1] + storage_cap[i-1]
    cumul_flow_cap[i] = cumul_flow_cap[i-1] + flow_cap[i-1]
```

Note that the length of the cumulative capacities arrays are one index greater than the flow and storage capacity arrays. In fact, the first entry of both arrays is set to 0 (zero) in order to ensure convergence of the future Lorenz Curve to the origin.

***
#### Step (4) - Normalize the cumulative storage and flow capacities

To normalize the cumulative storage and flow capacities (i.e. limiting the range to [0,1]), we'll perform element-wise division of the cumulative storage and flow capacities by the sum of the all layers' storage and flow capacities, respectively. Thus, the normalized (also known as fractional) storage and flow capacities are given by:

```python
frac_storage_cap = cumul_storage_cap/cumul_storage_cap[-1]
frac_flow_cap = cumul_flow_cap/cumul_flow_cap[-1]
```

***
#### Step (5) - Plot the Lorenz Curve

Even though we say plot the Lorenz Curve, we'll indeed plot the fractional flow capacities against the fractional storage capacities (i.e. we'll plot some of the points on the Lorenz Curve).

Let's instantiate a figure to hold our Lorenz Curve points:

```python
plt.figure(figsize = (16,12))
plt.style.use('fivethirtyeight')                                             # Just a plot style I find pretty

plt.plot([0,1], [0,1], color = 'red', label = 'Homogeneous Line')            # Homogeneous line
plt.plot(frac_storage_cap, frac_flow_cap, color = 'black', \
         label = 'Lorenz Curve points', linestyle = 'dotted')                # Sample points of Lorenz Curve

plt.title('Lorenz Curve', size = 50)
plt.xlabel('Fraction of Total Storage Capacity (m)', size = 36)
plt.ylabel('Fraction of Total Flow Capacity (mD*m)', size = 36)
plt.legend(loc = 4, facecolor = '#C0C0C0', fontsize = 25)

plt.show()
```

***
#### Step (6) - Find a curve fit

Now that we have some of the data points of the Lorenz Curve, we can apply a curve fit to predict the behavior of this entire subsurface sample. We'll use a 3rd degree polynomial to fit the Lorenz Curve.

```python
weights = np.ones(len(frac_storage_cap))
weights[0] = 1000; weights[-1] = 1000                                           # To ensure the fit converges to (0,0) and (1,1)

poly_fit = np.polyfit(frac_storage_cap, frac_flow_cap, deg=3, w=weights)
print('poly_fit = ', poly_fit)
```

    poly_fit =  [ 2.83252318e-01 -1.00166028e+00  1.71840790e+00  1.64140837e-07]

The resulting array contains the coefficients of the polynomial fit. To better visualize this polynomial in standard equation form:

```python
poly_fit = np.poly1d(poly_fit)
print(poly_fit)
```

            3         2
    0.2833 x - 1.002 x + 1.718 x + 1.641e-07

***
#### Step (7) - Integrate to find the area between the Lorenz Curve and the Homogenenous LIne

The advantage of having applied the _numpy.poly1d()_ method on Step (6) is that we now have a callable object for which we can evaluate it over any domain (here [0,1]). Then:

```python
integral = np.polyint(poly_fit)
print(integral)
```

             4          3          2
    0.07081 x - 0.3339 x + 0.8592 x + 1.641e-07 x

The result above can be easily validated since the fit has polynomial behavior. Now, we can evaluate the definite integral for the area under the Lorenz Curve and then subtract the area under the homogeneous line (i.e. area of isosceles triangle of side length 1 = 0.5):

```python
lorenz_area = integral(1) - integral(0) - 0.5
print(lorenz_area)
```

    0.09613043353885031

Note that for practical purposes the integral(0) term could have been ignored since the integration constant is assumed to be 0.
***
#### Step (8) - Obtain the Lorenz Coefficient

The final step of this procedure is to divide the _lorenz_area_ calculated on Step (7) by 0.5, which is the total area between the lines **y = 1** and **y = x** in the domain [0,1]:

```python
lorenz_coefficient = lorenz_area/0.5
print('Lorenz Coefficient = %.3f' %lorenz_coefficient)
```

    Lorenz Coefficient = 0.192

Because the Lorenz Coefficient sits below the conventional threshold of 0.3, we can assume that the subsurface sample near the well exhibits simple displacement of fluids and a potentially high recovery factor.

Let's replicate the plot from Step (5) with shaded areas to better illustrate this Lorenz Coefficient:

```python
fig = plt.figure(figsize = (16,12))

plt.style.use('fivethirtyeight')

plt.plot([0,1],[0,1], label='Homogeneous Curve', color = 'red', linewidth = '3')                # Homogeneous line
plt.plot(frac_storage_cap, frac_flow_cap, label = 'Lorenz Curve points', \
         linestyle = 'dotted', color = 'black')
plt.plot(np.linspace(0,1,100), poly_fit(np.linspace(0,1,100)), linestyle = 'dashed',\
         linewidth = '3', label = 'Polynomial Fit', color = 'white')                            # Polynomial fit
plt.fill_between(np.linspace(0,1,100), poly_fit(np.linspace(0,1,100)),\
                 np.linspace(0,1,100), alpha = 0.75)                                            # Blue area
plt.fill_between(np.linspace(0,1,100), poly_fit(np.linspace(0,1,100)), 1,\
                 alpha = 0.75, color = 'orange')                                                # Orange area

plt.title('Lorenz Curve and Coefficient', size = 50)
plt.xlabel('Fraction of Total Storage Capacity (m)', size = 36)
plt.ylabel('Fraction of Total Flow Capacity (mD*m)', size = 36)
plt.legend(loc = 4, facecolor = '#C0C0C0', fontsize = 25)
plt.text(0.3, 0.8, 'Lorenz Coefficient = \n %.3f' %lorenz_coefficient, size = 40, horizontalalignment = 'center', \
         bbox=dict(facecolor='none', edgecolor='black'))

plt.show()
```

It's now clear that, graphically, the Lorenz Coefficient is equivalent to the blue area divided by the sum of the blue and orange areas.
***
#### Conclusion

This exercise detailed the procedure towards calculating the Lorenz Coefficient of a subsurface sample from its porosity and permeability measurements. We also covered some of the Python resources available to improve management of well data, perform the necessary mathematical transformations, and visualize the solution curve and the Lorenz Coefficient.

If you use the GeostatsPy package, the calculation and display of the Lorenz Coefficient are available through the **lorenz_curve()** and **lorenz_display()** functions. Please check the documentation on those for more detail.

***

#### More on Michael Pyrcz and the Texas Center for Geostatistics:

### Michael Pyrcz, Associate Professor, University of Texas at Austin
*Novel Data Analytics, Geostatistics and Machine Learning Subsurface Solutions*

With over 17 years of experience in subsurface consulting, research and development, Michael has returned to academia driven by his passion for teaching and enthusiasm for enhancing engineers' and geoscientists' impact in subsurface resource development.

For more about Michael check out these links:

#### [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1)

#### Want to Work Together?

I hope this content is helpful to those that want to learn more about subsurface modeling, data analytics and machine learning. Students and working professionals are welcome to participate.

* Want to invite me to visit your company for training, mentoring, project review, workflow design and / or consulting? I'd be happy to drop by and work with you!

* Interested in partnering, supporting my graduate student research or my Subsurface Data Analytics and Machine Learning consortium (co-PIs including Profs. Foster, Torres-Verdin and van Oort)? My research combines data analytics, stochastic modeling and machine learning theory with practice to develop novel methods and workflows to add value. We are solving challenging subsurface problems!

* I can be reached at mpyrcz@austin.utexas.edu.

I'm always happy to discuss,

*Michael*

Michael Pyrcz, Ph.D., P.Eng. Associate Professor The Hildebrand Department of Petroleum and Geosystems Engineering, Bureau of Economic Geology, The Jackson School of Geosciences, The University of Texas at Austin

#### More Resources Available at: [Twitter](https://twitter.com/geostatsguy) | [GitHub](https://github.com/GeostatsGuy) | [Website](http://michaelpyrcz.com) | [GoogleScholar](https://scholar.google.com/citations?user=QVZ20eQAAAAJ&hl=en&oi=ao) | [Book](https://www.amazon.com/Geostatistical-Reservoir-Modeling-Michael-Pyrcz/dp/0199731446) | [YouTube](https://www.youtube.com/channel/UCLqEr-xV-ceHdXXXrTId5ig)  | [LinkedIn](https://www.linkedin.com/in/michael-pyrcz-61a648a1)

```python

```


# 使用标准库处理基本数学问题

python内置了多数情况下足够用的数学工具用于做一些简单计算,主要包括几个部分:

+ 专用的数据类型

    包括有标准库中的理数,高精度数类型以及默认支持的复数类型

+ 常用计算算法

    包括针对自然数和复数的log,三角函数等计算

+ 统计学工具

    包括常用的统计计算算法和随机数模块

## 默认数的形式

python中的数分为

+ 整数

```python
0
```

+ 浮点数

```python
1.1
```

+ 复数,而且大数计算是内置的被优化的相当好.

```python
1+2j
```

### 数的进制

默认的数是10进制的,但python中也支持其他几种进制

+ 16进制

```python
0x10
```

    16

+ 8进制

```python
0O10
```

    8

+ 2进制

```python
0b10
```

    2

而十进制转换成别的进制就会麻烦一些,需要使用`bin(dec)`,`oct(dec)`,`hex(dec)`这样的内置函数

```python
bin(2)
```

    '0b10'

```python
oct(8)
```

    '0o10'

```python
hex(16)
```

    '0x10'

可以看到转换后得到的其实是字符串,这个需要注意.

### 大数的表示[3.6]

从python3.6起,大数可以使用每三位加一格下划线的表述方式输入了

```python
12_234
```

    12234

## 内置的计算操作

python内置的合法计算符号包括:

符号|操作名
---|---
`+`|加
`-`|减
`*`|乘
`/`|除
`//`|整除
`**`|求幂
`abs`|取绝对值

另外还有一个符号`@`表示矩阵乘法,这个官方的数据结构没有实现但numpy和pandas倒是实现了

## 高精度数(decimal)

高精度数模块(decimal)提供了一种可用于代替float的数据类型,这种数据类型并不适合常用计算,因为高精度意味着更耗时;但在需要高精度浮点运算时比较好用,适合用在财务上.

这种数据类型可以由整数,浮点数,数字字符串转化得来

### 获得当前精度环境

```python
from decimal import getcontext
```

```python
getcontext()
```

    Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

### 设定精度

```python
getcontext().prec = 10
```

### 转化为`decimal`数据类型

```python
from decimal import Decimal
Decimal(1) / Decimal(7)
```

    Decimal('0.1428571429')

## 有理数(fractions)

有理数(fractions)模块提供了一种用来表示有理数的数据类型,它可以用整数,浮点数,高精度数或者数字和除号字符串创建

```python
from fractions import Fraction
Fraction(16, -10)
```

    Fraction(-8, 5)

```python
Fraction(123)
```

    Fraction(123, 1)

```python
Fraction()
```

    Fraction(0, 1)

```python
Fraction('3/7')
```

    Fraction(3, 7)

```python
Fraction('1.414213 \t\n')
```

    Fraction(1414213, 1000000)

```python
Fraction('-.125')
```

    Fraction(-1, 8)

```python
Fraction('7e-6')
```

    Fraction(7, 1000000)

```python
Fraction(2.25)
```

    Fraction(9, 4)

```python
Fraction(1.1)
```

    Fraction(2476979795053773, 2251799813685248)

```python
from decimal import Decimal
Fraction(Decimal('1.1'))
```

    Fraction(11, 10)

## 数学运算模块math
python自带的math模块提供了一些常用的数学运算和常数

### 常数

常数|说明
---|---
`math.e`|  自然常数e
`math.pi`| 圆周率pi
`math.tau`[Python3.6]|数学常数$τ = 6.283185...$,精确到可用精度.Tau 是一个圆周常数,等于 2π,圆的周长与半径之比
`math.inf`[Python3.5]|浮点正无穷大,相当于`float('inf')`
`math.nan`[Python3.5]|浮点"非数字"(NaN)值,相当于`float('nan')`

### 数值计算

函数|说明|例子
---|---|---
`math.ceil(x)`|返回大于x的整数上限的浮点数,x为整数则返回自己的浮点形式|`math.ceil(1)->1.0,</br>math.ceil(1.1)->2.0,</br>math.ceil(-1.5)->-1.0`
`math.copysign(x, y)|返回绝对值为x,符号为y的符号的数|`math.copysign(1.0, -0.0)->-1.0`
`math.fabs(x)`|相当于`abs(x)`,返回绝对值|`math.fabs(-3.4)->3.4`
`math.factorial(x)`|数学上的x!,阶乘|`math.factorial(3)->6`
`math.floor(x)`|与ceil相反,得到上限|`math.floor(-0.5)->-1.0`
`math.fmod(x, y)`|求模运算,适合用在浮点数,注意和`%`的不同|`math.fmod(3.5, -2)->1.5</br>3.5%-2->-0.5`
`math.frexp(x)`|将x拆成分`(m,e)`,$ x = m \cdot 2^e $|`math.frexp(2.43)->(0.6075, 2)`
`math.fsum(iterable)`|求序列中所有数的和的精确值|`fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])->1.0`
`math.isinf(x)`|判断x是不是`float("inf")`|---
`math.isfinite(x)`|如果 x 既不是无穷大也不是`NaN`,则返回`True`,否则返回`False`
`math.isclose(a, b, rel_tol=1e-09, abs_tol=0.0)`[Python3.5]|用于测试近似相等的函数,`rel_tol`为相对容差,`abs_tol`为最小绝对容差|---
`math.isnan(x)`|判断x是不是`float("NaN")`|---
`math.ldexp(m,e)`|求$m \cdot 2^e$|`math.ldexp(3, 1)->6.0`
`math.modf(x)`|拆分整数小数部分|`math.modf(-3.5)->(-0.5, -3.0)`
`math.trunc(x)`|返回整数部分|`math.trunc(3.5)->3`
`math.gcd(a, b)`[Python3.5]|返回两个数的最大公约数|`math.gcd(12,15)->3`
`math.remainder(x, y)`[Python3.7]|返回`IEEE 754`风格的`x`相对于`y`的余数|---

### 平方和对数

函数|说明|例子
---|---|---
`math.exp(x)`|自然数的幂$e^x$|`math.exp(2)->7.38905609893065`
`math.expm1(x)`|返回e的x次方减1|`math.expm1(2)->6.38905609893065`
`math.log(x[, base])`| 返回x的以base为底的对数,base默认为`e`|`math.log(math.e)->1.0</br>math.log(10,2)->3.3219280948873626`
`math.log10(x)`|返回x的以10为底的对数|`math.log10(2)->0.30102999566398114`
`math.log1p(x)`|返回1+x的自然对数（以e为底)|`math.log1p(math.e-1)->1.0`
`math.pow(x, y)`|返回x的y次方|`math.pow(5,3)->125.0`
`math.sqrt(x)`|返回x的平方根|`math.sqrt(3)->1.7320508075688772`

### 三角函数

+ 弧度

函数|说明
---|---
`math.acos(x)`|`acos(x)`
`math.asin(x)`|`asin(x)`
`math.atan(x)`|`atan(x)`
`math.atan2(y, x)`|`atan(y / x)`
`math.cos(x)`|`cos(x)`
`math.hypot(x, y)`|`sqrt(x*x + y*y)`
`math.sin(x)`|`sin(x)`
`math.tan(x)`|`tan(x)`

+ 角度,弧度转换

函数|说明
---|---
`math.degrees(x)`|弧度转度
`math.radians(x)`|度转弧度

### 双曲函数

函数|说明
---|---
`math.sinh(x)`|双曲正弦 $ \sinh x = {\frac {e^x  - e^{ - x} } 2} $
`math.cosh(x)`|双曲余弦 $ \cosh x = {\frac {e^x  + e^{ - x} }  2} $
`math.tanh(x)`|双曲正切 $ \tanh x = {\frac {\sinh x} {\cosh x}} $
`math.acosh(x)`|反双曲余弦
`math.asinh(x)`|反双曲正弦
`math.atanh(x)`|反双曲正切

### 特殊函数:

函数|说明
---|---
`math.erf(x)`|误差函数: $\operatorname{erf}(x) = \frac{2}{\sqrt{\pi}}\int_0^x e^{-t^2}\,\mathrm dt.$
`math.erfc(x)`|互补误差函数:$\operatorname{erfc}(x) = 1-\operatorname{erf}(x) = \frac{2}{\sqrt{\pi}} \int_x^{\infty} e^{-t^2}\,\mathrm dt\,.$
`math.gamma(x)`|伽玛函数 $\Gamma(z) = \int_{0}^{\infty} \frac{t^{z-1}}{\mathrm{e}^t} \,{\rm{d}}t$
`math.lgamma(x)`|伽马函数绝对值的自然对数

```python
import math
math.gcd(12,15)
```

    3

## 复数运算(cmath)

这个模块和math很像,只是面向的操作对象是复数.它独有的接口有

```python
from cmath import phase,polar,rect
```

### 极坐标转换

+ `phase()`求相(相当于求`atan2(x.imag, x.real)`)

```python
phase(-1.0+0.0j)
```

    3.141592653589793

```python
phase(complex(-1.0,-0.0))
```

    -3.141592653589793

+ `polar(x)`转换为极坐标

polar(x) 相当于 (abs(x), phase(x)).

```python
polar(complex(-1.0,-0.0))
```

    (1.0, -3.141592653589793)

+ `rect(r,phi)`已知半径和度数求以两边长为值的复数

$$ r * (math.cos(phi) + math.sin(phi)*1j) $$

```python
from math import pi
rect(1,pi/4)
```

    (0.7071067811865476+0.7071067811865475j)

## 统计模块(statistics)

该模块是3.4后新增的模块,这个模块提供一些统计学方法

### 均值中心性

函数|说明
---|---
mean()|	均值
harmonic_mean()|计算调和平均,比如求a,b,c三个数的调和平均就是计算$ \frac3 {(\frac 1 a + \frac 1 b + \frac 1 c)}$
median()|中位数
median_low()|	Low median of data.
median_high()|	High median of data.
median_grouped()|	Median, or 50th percentile, of grouped data.
mode()|众数	Mode (most common value) of discrete data.

```python
L = range(10000)
from statistics import mean,median,median_low,median_high,median_grouped,mode
mean(L)
```

    4999.5

```python
median(L)
```

    4999.5

```python
median_low(L)
```

    4999

```python
median_low(L)
```

    4999

```python
median_high(L)
```

    5000

```python
median_high(L)
```

    5000

```python
median_grouped(L)
```

    4999.5

```python
median_grouped(L, interval=2)
```

    4999.0

```python
from random import randint
XL = [randint(1,10) for i in range(10000)]
mode(XL)
```

    3

### 分布统计

函数|说明
---|---
pstdev()| 总体标准差
pvariance()|总体方差
stdev()|样本标准差
variance()|样本方差

```python
from statistics import pstdev,pvariance,stdev,variance
pstdev(L)
```

    2886.751331514372

```python
pvariance(L)
```

    8333333.25

```python
stdev(L)
```

    2886.8956799071675

```python
variance(L)
```

    8334166.666666667

## 随机模块random

### 常规用法

无论在做测试中还是在做模拟中,随机都是必须的模块,具体这样用:

```python
import random
```

```python
random.random()        # [0,1)内随机浮点数
```

    0.25415523691401276

```python
random.uniform(1, 10)  # [1,10)内随机浮点数
```

    5.470078932858412

```python
random.randint(1, 10)  # [1,10]范围内的随机整数
```

    4

```python
random.randrange(0, 101, 2)  # 从等差数列中随机挑一个数
```

    54

```python
random.choice('abcdefghij')  # 随机选一个
```

    'e'

```python
items = [1, 2, 3, 4, 5, 6, 7]
random.shuffle(items)#随机排序
```

```python
random.sample([1, 2, 3, 4, 5],  3)  # 随机选3个元素
```

    [5, 2, 1]

### 随机种子

学过C的都知道[伪随机](http://baike.baidu.com/link?url=jnG_iX8HCXPxH-bsD2_HH2Z7XvX-o_6AfQvmNPMq9d2PaFv34aCoS33yJ7n94XOrt2I0EhZGjttpOEYPIR8cHK),python也是伪随机,所以可以通过设定`seed`值来改变随机状态

```python
from matplotlib import pyplot as plt
```

```python
%matplotlib inline
```

### 数学上的一些特殊随机

+ **三角分布**

三角分布式是连续概率分布,可以看做是在一个范围中有一个数(众数)它附近有最高的概率密度即最有可能出现在该众数上
```python
random.triangular(low, high, mode)#三角形分布,默认众数(mode)是中值
```

```python
hight,low,mode = 0,2,0.5
random.triangular(hight,low,mode)
```

    1.1251317155398355

```python
from collections import Counter
```

```python
c = Counter()
for nbr in [round(random.triangular(0,2,0.5),2) for i in range(10000)]:
    c[nbr] = c[nbr] + 1
```

```python
plt.plot([float(i) for i in c.keys()],[float(i) for i in c.values()],".")
plt.show()
```

+ **β分布**

β分布是在0到1上的特殊分布,

做硬币试验的假定分布，即做伯努利试验的假定分布在确定伯努利试验的分布之前，我们利用试验的少量数据来估计试验的概率（作为先验概率）beta分布涉及两个参数：1、试验成功的次数2、试验失败的次数.

概率密度函数为:

$$
\begin{align}
f(x)=&
x^{\alpha-1}(1-x)^{\beta-1}
\over
\int_0^1 u^{\alpha-1}(1-u)^{\beta-1}du\\
=&{\frac {\Gamma(\alpha+\beta)} {\Gamma(\alpha)\Gamma(\beta)}}x^{\alpha-1}(1-x)^{\beta-1}\\
=&{\frac {1} {B(\alpha-\beta)}}x^{\alpha-1}(1-x)^{\beta-1}
\end{align}
$$

累积分布函数:

$$
\begin{align}
F(x;\alpha,\beta)=& \frac {B_x(\alpha,\beta)} {B(\alpha,\beta)}&=I_x(\alpha,\beta)
\end{align}
$$

其中$${B_x(\alpha,\beta)}$$是不完全Β函数,$${I_x(\alpha,\beta)}$$ 是正则不完全贝塔函数

是不完全Β函数，$$I_x (\alpha,\beta)$$ 是正则不完全贝塔函数

```python
random.betavariate(alpha, beta)#beta分布
```

```python
l0=[random.betavariate(0.5,1) for i in range(100000)]
l1=[random.betavariate(2,3) for i in range(100000)]
l2=[random.betavariate(3,4) for i in range(100000)]
l3=[random.betavariate(2,5) for i in range(100000)]

r0=[len([1 for j in l0 if i+0.005>j>i-0.005])
    for i in map(lambda x:round(x*0.01,3),range(0,100,1))]
r1=[len([1 for j in l1 if i+0.005>j>i-0.005])
    for i in map(lambda x:round(x*0.01,3),range(0,100,1))]
r2=[len([1 for j in l2 if i+0.005>j>i-0.005])
    for i in map(lambda x:round(x*0.01,3),range(0,100,1))]
r3=[len([1 for j in l3 if i+0.005>j>i-0.005])
    for i in map(lambda x:round(x*0.01,3),range(0,100,1))]

plt.plot(list(map(lambda x:round(x*0.01,3),
                  range(0,100,1))),r0,color="red")
plt.plot(list(map(lambda x:round(x*0.01,3),
                  range(0,100,1))),r1,color="blue")
plt.plot(list(map(lambda x:round(x*0.01,3),
                  range(0,100,1))),r2,color="green")
plt.plot(list(map(lambda x:round(x*0.01,3),
                  range(0,100,1))),r3,color="yellow")
plt.show()
```

+ **指数分布**

概率密度函数:

指数分布可以用来表示独立随机事件发生的时间间隔，比如旅客进机场的时间间隔、中文维基百科新条目出现的时间间隔等等。
许多电子产品的寿命分布一般服从指数分布。有的系统的寿命分布也可用指数分布来近似。它在可靠性研究中是最常用的一种分布形式。指数分布是伽玛分布和威布尔分布的特殊情况，产品的失效是偶然失效时，其寿命服从指数分布。
指数分布可以看作当威布尔分布中的形状系数等于1的特殊分布，指数分布的失效率是与时间t无关的常数，所以分布函数简单。

概率密度函数:

$$
f(x)=\begin{cases}
    \lambda e^{-\lambda x}&x>0,\\
    0&x\le0.
\end{cases}
$$
累积分布函数:

$$
F(x;\lambda)=\begin{cases}
    1- e^{-\lambda x}&x\ge0,\\
    0&x<0.
\end{cases}
$$

期望值:

$$ EX=\lambda^{-1} $$

方差:
$$D(X)=Var(X)=\lambda ^{-2}$$

```python
random.expovariate(lambd)
```

```python
random.expovariate(3)
```

    0.00044025063564512545

```python
c_e3 = Counter()
for nbr in [round(random.expovariate(3),2 )
            for i in range(10000)]:
    c_e3[nbr] = c_e3[nbr] + 1
plt.plot([float(i) for i in c_e3.keys()],
         [float(i) for i in c_e3.values()],".")
plt.show()
```

+ **伽玛分布**

概率密度函数:

令  $$X\sim  \Gamma(\alpha,\beta)$$ ;
则有:
$$
f(x)={\frac {x^{(\alpha-1)} e^{(-\lambda x)}} {\Gamma(\alpha)\beta^\alpha}} ,x>0
$$

```python
random.gammavariate(alpha, beta)
```

```python
c_gamma = Counter()
for nbr in [round(random.gammavariate(5,0.5),2 )
            for i in range(10000)]:
    c_gamma [nbr] = c_gamma [nbr] + 1
plt.plot([float(i) for i in c_gamma.keys()],
         [float(i) for i in c_gamma.values()],".")
plt.show()
```

+ **高斯分布(正态分布)**

概率密度函数:

$$
f(x)={\frac 1 {\sqrt {2\pi}\sigma}} e^{-{\frac {(x-\mu)^2} {2\sigma^2}}}
$$
其中 $$\mu$$ 与 $$\sigma$$ 分别是变量对数的平均值与标准差

```python
random.gauss(mu, sigma)#略快于下面的方法

random.normalvariate(mu, sigma)
```

```python
c_gauss = Counter()
for nbr in [round(random.gauss(0,1),2 )
            for i in range(10000)]:
    c_gauss[nbr] = c_gauss[nbr] + 1
plt.plot([float(i) for i in c_gauss.keys()],
         [float(i) for i in c_gauss.values()],".")
plt.show()
```

+ **对数正态分布**

如果 X 是正态分布的随机变量，则 exp(X) 为对数正态分布；同样，如果 Y 是对数正态分布，则 ln(Y) 为正态分布。 如果一个变量可以看作是许多很小独立因子的乘积，则这个变量可以看作是对数正态分布。

概率密度函数:
$$
f(x;\mu,\sigma) = \frac{1}{ \sigma \sqrt{2 \pi}} e^{-(\ln x - \mu)^2/2\sigma^2}
$$

其中 $$\mu$$ 与 $$\sigma$$ 分别是变量对数的平均值与标准差

```python
random.lognormvariate(mu, sigma)
```

```python
c_log = Counter()
for nbr in [round(random.lognormvariate(0.5,0.5),2 )
            for i in range(10000)]:
    c_log[nbr] = c_log[nbr] + 1
plt.plot([float(i) for i in c_log.keys()],[float(i)
                                           for i in c_log.values()],".")
plt.show()
```

+ **冯·米塞斯分布**

冯·米塞斯分布（von Mises distribution）指一种圆上连续概率分布模型，它也被称作循环正态分布

概率密度函数:
$$
f(x|\mu,\kappa)=\frac{e^{\kappa\cos(x-\mu)}}{2\pi I_0(\kappa)}
$$

参数μ和1/κ是μ和σ^2（对应正态分布中的均值和方差）的模拟量
+ μ是位置的度量（分布将围绕μ成簇）
+ κ是集中度的度量（分散度的倒数，所以1/κ是σ^2的模拟量）
+ + 如果κ为0，分布是均匀分布，对于κ很小的情形，分布近似均匀分布
+ + 如果κ很大，分布紧紧围绕μ集中分布。实际上，随着κ增加，分布将趋于x以μ为均值1/κ为方差的正态分布

```python
random.vonmisesvariate(mu, kappa)
```

```python
c_von = Counter()
for nbr in [round(random.vonmisesvariate(10,1),2 )
            for i in range(10000)]:
    c_von[nbr] = c_von[nbr] + 1
plt.plot([float(i) for i in c_von.keys()],
         [float(i) for i in c_von.values()],".")
plt.show()
```

+ **帕累托分布**

帕累托法则(2,8定律)
帕累托分布是以意大利经济学家维弗雷多·帕雷托命名的。 是从大量真实世界的现象中发现的幂定律分布。这个分布在经济学以外，也被称为布拉德福分布。

概率密度函数:
$$
p(x) = \left \{ \begin{matrix} 0, & x < x_{\min}; \\  \\ {\frac{k \; x_{\min}^k} {x^{k+1}}}, &x > x_{\min}. \end{matrix} \right.
$$

k是形状参数(shape parameter)

```python
random.paretovariate(k)
```

```python
c_par = Counter()
for nbr in [round(random.paretovariate(10),2 )
            for i in range(10000)]:
    c_par[nbr] = c_par[nbr] + 1
plt.plot([float(i) for i in c_par.keys()],
         [float(i) for i in c_par.values()],".")
plt.show()
```

+ **韦伯分布**

韦伯分布（Weibull distribution），又称韦氏分布或威布尔分布，是可靠性分析和寿命检验的理论基础。

概率密度函数:

$$
f(x;\lambda,k) =  \begin{cases}
\frac{k}{\lambda}\left(\frac{x}{\lambda}\right)^{k-1}e^{-(x/\lambda)^{k}} & x\geq0\\
0 & x<0\end{cases}
$$

λ＞0是比例参数（scale parameter），k＞0是形状参数（shape parameter）
```python
random.weibullvariate(lambda, k)
```

```python
c_wei = Counter()
for nbr in [round(random.weibullvariate(2,1),2 )
            for i in range(10000)]:
    c_wei[nbr] = c_wei[nbr] + 1
plt.plot([float(i) for i in c_wei.keys()],
         [float(i) for i in c_wei.values()],".")
plt.show()
```

src/数据分析篇/工具介绍/python标准库中的计算工具/使用标准库处理基本数学问题.ipynb


# Heat transfer for Extended surfaces

Fins are widely used to increase heat transfer through an increase of the surface area exposed to convection and radiation heat transfer. The following shows the comparison between theory and (an almost realistic) simulation of a rectangular fin subjected to a convection flow, with characteristics $h$ and $T_\infty$. The fin material has a conductivity of $k$ assumed to be constant for the range of temperature of our problem

The theory starts with the geometry of the fin. Here we consider the simplest case, a rectangular thin. The cross-sectional area is $A_c=wt$, where $w$ is the width and $t$ the tickness. The perimeter of this area is $P=2(w+t)$. The length is $L$.

A control volume between $x$ and $x+\Delta x$ and bounded from the whole of cross sectional area $A_c$. If one assumes on any cross-sectional area temperature variation to be negligible, the problem reduces to the following ODE (derived in great details in your book).
$$
\frac{d^2T}{dx^2}-\frac{hP}{kA_c}\left(T(x)-T_\infty\right)=0
$$
and by operating the variable transformation $\theta(x)=\left(T(x)-T_\infty\right)$:
$$
\frac{d^2\theta}{dx^2}-m^2\theta=0 \text{ with }m^2=\frac{hP}{kA_c}
$$
The general solution is
$$
\theta(x)=C_1e^{+mx}+C_2e^{-mx}
$$
The constants are determined by the boundary conditions at

 $x=0$. Here we assume constant base temperature $T_b$ or $\theta_b=T_b-T_\infty$
$$
\theta_b=C_1+C_2
$$

 $x=L$. The solution for this boundary depends on the approximation we think we can make:

 Convection flow
$$
h\theta(L)=-k\left.\frac{d\theta}{dx}\right\vert_{x=L}
$$

 Adiabatic
$$
\left.\frac{d\theta}{dx}\right\vert_{x=L}=0
$$

 Constant temperature
$$
\theta(L)=T_L-T_\infty
$$

 Infinite fin ($L/t\gg 1$?)
$$
\theta(L)=0
$$

```python
%matplotlib inline

from IPython.display import clear_output

import schemdraw as schem
import schemdraw.elements as e

import matplotlib.pyplot as plt
import numpy as np
import math
import scipy.constants as sc

import sympy as sym

```

## Discretized heat equation for steady, pure conduction

Under the assumption of constant thermodynamic properties, the heat transport equation can be derived as:
$$
\rho C_p\left(\frac{\partial T}{\partial t}+\mathbf{u}.\boldsymbol{\nabla}T\right)=k\nabla^2T
$$
For a pure conduction (velocity vector $\mathbf{u}=\mathbf{0}$) and steady state $\partial T/\partial t=0$, the temperature field is the solution of:
$$
\nabla^2 T=0\Leftrightarrow \frac{\partial^2 T}{\partial x^2}+\frac{\partial^2 T}{\partial y^2}+\frac{\partial^2 T}{\partial z^2}=0
$$

This equation can be derived by using a 2D control volume of dimensions $\Delta x\times\Delta y$ and applying the conservation of energy and Fourier's law on the surface of the control volume.

Show that:

$$
\frac{k\Delta y}{\Delta x}\left(T_{i,j}-T_{i-1,j}\right)
-\frac{k\Delta y}{\Delta x}\left(T_{i+1,j}-T_{i,j}\right)
+\frac{k\Delta x}{\Delta y}\left(T_{i,j}-T_{i,j-1}\right)
-\frac{k\Delta x}{\Delta y}\left(T_{i,j+1}-T_{i,j}\right)=0
$$

Using Taylor series expansion, show that:
$$
\frac{\partial^2 T}{\partial x^2}=\frac{T_{i+1,j} - 2T_{i,j} + T_{i-1,j}}{\Delta x^2}
$$
and then show
$$
-\frac{k\Delta x}{\Delta y}T_{i,j-1}
-\frac{k\Delta x}{\Delta y}T_{i-1,j}
+\left(2\frac{k\Delta x}{\Delta y}+2\frac{k\Delta y}{\Delta x}\right)T_{i,j}
-\frac{k\Delta x}{\Delta y}T_{i+1,j}
-\frac{k\Delta x}{\Delta y}T_{i,j+1}=0
$$
$$
\Leftrightarrow\frac{\partial^2 T}{\partial x^2}+\frac{\partial^2 T}{\partial y^2}=0
$$

```python
def build_matrix(n,A,b,nx,ny,dx,dy,k_cond,h,alpha,beta,T_infty,Tiso):
    for j in range (1,ny-1):
        for i in range (1,nx-1):
            k = i + j * nx
            kim = k - 1
            kip = k + 1
            kjm = k - nx
            kjp = k + nx
            A[k, k] = k_cond*(2.*dx/dy+2.*dy/dx)
            A[k, kim] = -k_cond*dy/dx
            A[k, kip] = -k_cond*dy/dx
            A[k, kjm] = -k_cond*dx/dy
            A[k, kjp] = -k_cond*dx/dy

    i = 0
    j = 0
    k = i + j * nx
    kip = 1
    kjp = nx
    A[k,k] = 3.*k_cond*dy/dx+k_cond*dx/dy+alpha*h*dx
    A[k,kip] = -k_cond*dy/dx
    A[k,kjp] = -k_cond*dx/dy+beta*h*dx
    b[k] = 2.*k_cond*dy/dx*T_iso+h*dx*T_infty

    i = 0
    j = ny-1
    k = i + j * nx
    kim = k - 1
    kip = k + 1
    kjm = k - nx
    kjp = k + nx

    A[k,kjm] = -k_cond*dx/dy + beta*h*dx
    A[k,k] = 3.*k_cond*dy/dx+k_cond*dx/dy + alpha*h*dx
    A[k,kip] = -k_cond*dy/dx
    b[k] = 2.*k_cond*dy/dx*T_iso + h*dx*T_infty

    i = 0
    for j in range (1,ny-1):
        k = i + j * nx
        kim = k - 1
        kip = k + 1
        kjm = k - nx
        kjp = k + nx
        A[k,kjm] = -k_cond*dx/dy
        A[k,k] = 3.*k_cond*dy/dx+2.*k_cond*dx/dy
        A[k,kip] = -k_cond*dy/dx
        A[k,kjp] = -k_cond*dx/dy
        b[k] = 2.*k_cond*dy/dx*T_iso

    i = nx-1
    j = 0
    k = i + j * nx
    kim = k - 1
    kip = k + 1
    kjm = k - nx
    kjp = k + nx
    A[k,kim] = -k_cond*dy/dx+beta*h*dy
    A[k,k] = k_cond*dy/dx+k_cond*dx/dy+alpha*h*dy
    A[k,kjp] = -k_cond*dx/dy
    b[k] = +h*dy*T_infty

    i = nx-1
    j = ny-1
    k = i + j * nx
    kim = k - 1
    kip = k + 1
    kjm = k - nx
    kjp = k + nx
    A[k,kjm] = -k_cond*dx/dy
    A[k,kim] = -k_cond*dy/dx+beta*h*dy
    A[k,k] = k_cond*dy/dx+k_cond*dx/dy+alpha*h*dy
    b[k] = h*dy*T_infty

    i = nx-1
    for j in range (1,ny-1):
        k = i + j * nx
        kim = k - 1
        kip = k + 1
        kjm = k - nx
        kjp = k + nx
        A[k,kjm] = -k_cond*dx/dy
        A[k,kim] = -k_cond*dy/dx + beta*h*dy
        A[k,k] = k_cond*dy/dx+2.*k_cond*dx/dy + alpha*h*dy
        A[k,kjp] = -k_cond*dx/dy
        b[k] = h*dy*T_infty

    j = 0
    for i in range (1,nx-1):
        k = i + j * nx
        kim = k - 1
        kip = k + 1
        kjm = k - nx
        kjp = k + nx
        A[k,kim] = -k_cond*dy/dx
        A[k,k] = 2.*k_cond*dy/dx+k_cond*dx/dy + alpha*h*dx
        A[k,kip] = -k_cond*dy/dx
        A[k,kjp] = -k_cond*dx/dy + beta*h*dx
        b[k] = h*dx*T_infty

    j = ny-1
    for i in range (1,nx-1):
        k = i + j * nx
        kim = k - 1
        kip = k + 1
        kjm = k - nx
        kjp = k + nx
        A[k,kjm] = -k_cond*dx/dy+beta*h*dx
        A[k,kim] = -k_cond*dy/dx
        A[k,k] = 2.*k_cond*dy/dx+k_cond*dx/dy+alpha*h*dx
        A[k,kip] = -k_cond*dy/dx
        b[k] = h*dx*T_infty

```

A major difficulty of this code resides in the rearrangement of the matrix $T_{i,j}$ into the vector $T_k$ with $k=i+j.nx$. The matrix is now pentadiagonal with its two furthest diagonal at $\pm nx$ from the main diagonal

Boundary condition: Isothermal at the base, convection everywhere else.
$i=0,j=0$:
$$
k\frac{T_{0,0}-T_a}{\Delta x/2}\Delta y-k\frac{T_{1,0}-T_{0,0}}{\Delta x}\Delta y+h\Delta x\left(\alpha T_{0,0}+\beta T_{0,1}-T\infty\right)-k\frac{T_{0,1}-T_{0,0}}{\Delta y}\Delta x = 0
$$

$$\left(3\frac{k\Delta y}{\Delta x}+k\frac{\Delta x}{\Delta y}+\alpha h \Delta x\right)T_{0,0}
-\frac{k\Delta y}{\Delta x}T_{1,0}
+\left(-\frac{k\Delta x}{\Delta y}+\beta h \Delta x\right)T_{0,1}
=2\frac{k\Delta y}{\Delta x}T_a+h\Delta x T_\infty
$$

$i=0,j=ny-1$:
$$
k\frac{T_{0,ny-1}-T_a}{\Delta x/2}\Delta y-k\frac{T_{1,ny-1}-T_{0,ny-1}}{\Delta x}\Delta y +k\frac{T_{0,ny-1}-T_{0,ny-2}}{\Delta y}\Delta x +h\Delta x\left(\alpha T_{0,ny-1}+\beta T_{0,ny-2}-T_\infty\right) = 0
$$

$$
\left(-\frac{k\Delta x}{\Delta y}+\beta h\Delta x\right)T_{0,ny-2}+\left(3\frac{k\Delta y}{\Delta x}T+\frac{k\Delta x}{\Delta y}+\alpha h\Delta x\right)T_{0,ny-1}-\frac{k\Delta y}{\Delta x}T_{1,ny-1}=2\frac{k\Delta y}{\Delta x}T_a + h\Delta x T_\infty
$$

$i=0,j\in\left]0,ny-1\right[$:
$$
k\frac{T_{0,j}-T_a}{\Delta x/2}\Delta y-k\frac{T_{1,j}-T_{0,j}}{\Delta x}\Delta y +k\frac{T_{0,j}-T_{0,j-1}}{\Delta y}\Delta x -k\frac{T_{0,j+1}-T_{0,j}}{\Delta y}\Delta x = 0
$$

$$
-\frac{k\Delta x}{\Delta y}T_{0,j-1}
+\left(3\frac{k\Delta y}{\Delta x}+2\frac{k\Delta x}{\Delta y}\right)T_{0,j}
-\frac{k\Delta y}{\Delta x}T_{1,j}
-\frac{k\Delta x}{\Delta y}T_{0,j+1}=2\frac{k\Delta y}{\Delta x}T_a
$$

$i=nx-1,j=0$:
$$
k\frac{T_{nx-1,0}-T_{nx-2,0}}{\Delta x}\Delta y-h\Delta y\left(\alpha T_{nx-1,0}+\beta T_{nx-2,0}-T_\infty\right)-k\frac{T_{nx-1,1}-T_{nx-1,0}}{\Delta y}\Delta x = 0
$$

$$
\left(-\frac{k\Delta y}{\Delta x}-\beta h \Delta y\right)T_{nx-2,0}+
\left(\frac{k\Delta y}{\Delta x}+k\frac{\Delta x}{\Delta y}-\alpha h \Delta y\right)T_{nx-1,0}-\frac{k\Delta x}{\Delta y}T_{nx-1,1}=-h\Delta y T_\infty
$$

$i=nx-1,j=ny-1$:
$$
k\frac{T_{nx-1,ny-1}-T_{nx-2,ny-1}}{\Delta x}\Delta y+h\Delta y\left(\alpha T_{nx-1,ny-1}+\beta T_{nx-2,ny-1}-T_\infty\right)+k\frac{T_{nx-1,ny-1}-T_{nx-1,ny-2}}{\Delta y}\Delta x = 0
$$

$$
-\frac{k\Delta x}{\Delta y}T_{nx-1,ny-2}
+\left(-\frac{k\Delta y}{\Delta x}+\beta h\Delta y\right)T_{nx-2,ny-1}+
\left(\frac{k\Delta y}{\Delta x}+k\frac{\Delta x}{\Delta y}+\alpha h \Delta y\right)T_{nx-1,ny-1}
=h\Delta yT_\infty
$$

$i=nx-1,j\in\left]0,ny-1\right[$:
$$
k\frac{T_{nx-1,j}-T_{nx-2,j}}{\Delta x}\Delta y+h\Delta y\left(\alpha T_{nx-1,j}+\beta T_{nx-2,j}-T_\infty\right)
+k\frac{T_{nx-1,j}-T_{nx-1,j-1}}{\Delta y}\Delta x-k\frac{T_{nx-1,j+1}-T_{nx-1,j}}{\Delta y}\Delta x = 0
$$

$$
-\frac{k\Delta x}{\Delta y}T_{nx-1,j-1}
+\left(-\frac{k\Delta y}{\Delta x}+\beta h \Delta y\right)T_{nx-2,j}+
\left(\frac{k\Delta y}{\Delta x}+2k\frac{\Delta x}{\Delta y}+\alpha h \Delta y\right)T_{nx-1,j}-\frac{k\Delta x}{\Delta y}T_{nx-1,j+1}=h\Delta y T_\infty
$$

$0<i<nx-1,j=0$:
$$
k\frac{T_{i,0}-T_{i-1,0}}{\Delta x}\Delta y-k\frac{T_{i+1,0}-T_{i,0}}{\Delta x}\Delta y
+h\Delta x\left(\alpha T_{i,0}+\beta T_{i,1}-T_\infty\right)-k\frac{T_{i,1}-T_{i,0}}{\Delta y}\Delta x = 0
$$

$$
-\frac{k\Delta y}{\Delta x}T_{i-1,0}+\left(2\frac{k\Delta y}{\Delta x}+\frac{k\Delta x}{\Delta y}+\alpha h \Delta x\right)T_{i,0}
-\frac{k\Delta y}{\Delta x}T_{i+1,0}
+\left(-\frac{k\Delta x}{\Delta y}+\beta h\Delta x\right)T_{i,1} = h\Delta x T_\infty
$$

$0<i<nx-1,j=ny-1$:
$$
k\frac{T_{i,ny-1}-T_{i-1,ny-1}}{\Delta x}\Delta y-k\frac{T_{i+1,ny-1}-T_{i,ny-1}}{\Delta x}\Delta y +k\frac{T_{i,ny-1}-T_{i,ny-2}}{\Delta y}\Delta x +h\Delta x\left(\alpha T_{i,ny-1}+\beta T_{i,ny-2}-T_\infty\right) = 0
$$

$$
\left(-\frac{k\Delta x}{\Delta y}+\beta h\Delta x\right)T_{i,ny-2}-\frac{k\Delta y}{\Delta x}T_{i-1,ny-1}+\left(2\frac{k\Delta y}{\Delta x}+\frac{k\Delta x}{\Delta y}+\alpha h \Delta x\right)T_{i,ny-1}-\frac{k\Delta y}{\Delta x}T_{i+1,ny-1} = h\Delta x T_\infty
$$

```python
def fin(k_cond,T_iso,T_infty,h,lx,ly,nx,ny):

    dx = lx/(nx)
    dy = ly/(ny)
    n = nx*ny
    alpha = 3./2.
    beta = -1./2.
    t = ly
    w = 1 #m
    A_c = t*w
    P = 2.*(t+w)
    m = np.sqrt(h*P/(k_cond*A_c))
    L = lx
    theta_b = T_iso - T_infty

    A = np.zeros((n,n), dtype = np.float)
    b = np.zeros((n,1), dtype = np.float)
    Tn = np.zeros((nx,ny), dtype = np.float)
    theta_comp = np.zeros((nx,ny))
    theta_conv = np.zeros(nx)
    theta_inf = np.zeros(nx)
    Xn = np.zeros((nx,ny), dtype = np.float)
    Yn = np.zeros((nx,ny), dtype = np.float)

    x = np.array([(i+0.5)*dx for i in range(nx)])
    y = np.array([(j+0.5)*dy for j in range(ny)])

    for j in range (ny):
        for i in range (nx):
            Xn[i,j] = x[i]
            Yn[i,j] = y[j]

    build_matrix(n,A,b,nx,ny,dx,dy,k_cond,h,alpha,beta,T_infty,T_iso)

    T = np.linalg.solve(A, b)

    i = 0
    j = 0
    for k in range (n):
        i = k - j*nx
        if (i > nx-1):
            j += 1
            i = 0
        Tn[i,j] = T[k]
        theta_comp[i,j] = Tn[i,j] - T_infty

    for i in range (nx):
        # Temperature distribution for an infinite fin
        theta_inf[i] = np.exp(-m*x[i])
        # Temperature for convection boundary condition at the tip
        theta_conv[i] = (np.cosh(m*(L-x[i]))+(h/(m*k_cond))*np.sinh(m*(L-x[i]))) \
                        /(np.cosh(m*L)+(h/(m*k_cond))*np.sinh(m*L))
    theta_conv *= theta_b
    theta_inf *= theta_b
    return x,y,dx,dy,Xn,Yn,Tn,theta_comp,theta_conv,theta_inf,m*L
```

```python
import numpy as np
##############################
#        Parameters          #
##############################
k_cond = 180.
nx = 100
ny = 20

lx = 1.2
ly = 0.1

n = nx*ny

T_iso = 100.
T_infty = 25.
h = 100. #W/m^2.K

x,y,dx,dy,Xn,Yn,Tn,theta_comp,theta_conv,theta_inf,mL = \
        fin(k_cond,T_iso,T_infty,h,lx,ly,nx,ny)

```

```python
fig = plt.figure(num=None, figsize=(6, 4), dpi=160, facecolor='w', edgecolor='k')
ax = fig.add_subplot(211)
im = ax.contourf(Xn, Yn, Tn, 20, cmap='jet')
ax.set_aspect('equal')
#ax.set_xlabel('$x$ (m)')
ax.set_ylabel('$y$ (m)')
fig.colorbar(im, ax = ax, orientation = 'horizontal')
bx = fig.add_subplot(212)
bx.plot(x, theta_comp[:,0], label='Computed at $y=0$')
bx.plot(x, theta_comp[:,ny//2], label='Computed at $y=t/2$')
bx.plot(x, theta_conv,'--', label='tip convection b.c.')
bx.plot(x, theta_inf,'-', label='Infinite fin sol.')
bx.set_xlabel('$x$ (m)')
bx.set_ylabel(r'$\theta$ ($^\circ$C)')
bx.legend(loc='upper center', bbox_to_anchor=(0.5, -0.5),
          fancybox=True, shadow=True, ncol=5)

heat_rate = 0.

heat_rate = np.sum(-k_cond*(Tn[0,:]-T_iso)/(dx/2.)*dy)
print('heat rate= %4.1f W/m' %heat_rate)
print('mL= %2.3f' %mL)
```

```python
print('error:',np.mean(theta_comp[-1,:])/T_infty)
```

    error: 0.09950832845317478

```python

```

```python

```


```python
from __future__ import division, print_function
%matplotlib inline
```

```python
import sympy
from sympy import Matrix, eye, symbols, sin, cos, zeros
from sympy.physics.mechanics import *
from IPython.display import display
sympy.init_printing(use_latex='mathjax')

```

# Quaternion Math Functions

```python
def expq(n):
    n *= 0.5
    nNorm = n.norm()
    qn = Matrix([cos(nNorm),n/nNorm*sin(nNorm)])
    return qn

def quat2dcm(q):
    """
    Convert quaternion to DCM
    """

    # Extract components
    w = q[0]
    x = q[1]
    y = q[2]
    z = q[3]

    # Reduce repeated calculations
    ww = w*w
    xx = x*x
    yy = y*y
    zz = z*z
    wx = w*x
    wy = w*y
    wz = w*z
    xy = x*y
    xz = x*z
    yz = y*z

    # Build Direction Cosine Matrix (DCM)
    dcm = Matrix([
        [ww + xx - yy - zz,       2*(xy - wz),       2*(xz + wy)],
        [      2*(xy + wz), ww - xx + yy - zz,       2*(yz - wx)],
        [      2*(xz - wy),       2*(yz + wx), ww - xx - yy + zz]
    ])
    return dcm

def dcm2quat(dcm):
    """
    Determine quaternion corresponding to dcm using
    the stanley method.

    Flips sign to always return shortest path quaterion
    so w >= 0

    Converts the 3x3 DCM into the quaterion where the
    first component is the real part
    """

    tr = Matrix.trace(dcm)

    w = 0.25*(1+tr)
    x = 0.25*(1+2*dcm[0,0]-tr)
    y = 0.25*(1+2*dcm[1,1]-tr)
    z = 0.25*(1+2*dcm[2,2]-tr)

    #kMax = np.argmax([w,x,y,z])

    kMax = 0

    if kMax == 0:
        w = sqrt(w)
        x = 0.25*(dcm[1,2]-dcm[2,1])/w
        y = 0.25*(dcm[2,0]-dcm[0,2])/w
        z = 0.25*(dcm[0,1]-dcm[1,0])/w

    elif kMax == 1:
        x = sqrt(x)
        w = 0.25*(dcm[1,2]-dcm[2,1])/x
        if w<0:
            x = -x
            w = -w
        y = 0.25*(dcm[0,1]+dcm[1,0])/x
        z = 0.25*(dcm[2,0]+dcm[0,2])/x

    elif kMax == 2:
        y = sqrt(y)
        w = 0.25*(dcm[2,0]-dcm[0,2])/y
        if w<0:
            y = -y
            w = -w
        x = 0.25*(dcm[0,1]+dcm[1,0])/y
        z = 0.25*(dcm[1,2]+dcm[2,1])/y

    elif kMax == 3:
        z = sqrt(z)
        w = 0.25*(dcm[0,1]-dcm[1,0])/z
        if w<0:
            z = -z
            w = -w
        x = 0.25*(dcm[2,0]+dcm[0,2])/z
        y = 0.25*(dcm[1,2]+dcm[2,1])/z

    q = Matrix([w,x,y,z])

    return q

def skew3(v):
    vx,vy,vz = v
    out = Matrix([[  0, -vz,   vy],
                  [ vz,   0,  -vx],
                  [-vy,  vx,    0]])
    return out

def skew4Left(v):
    if len(v)==3:
        v = Matrix.vstack(zeros(1),v)
    w,x,y,z = v
    out = Matrix([
            [w, -x, -y, -z],
            [x,  w, -z,  y],
            [y,  z,  w, -x],
            [z, -y,  x,  w],
        ])
    return out

def skew4Right(v):
    if len(v)==3:
        v = Matrix.vstack(zeros(1),v)
    w,x,y,z = v
    out = Matrix([
            [w, -x, -y, -z],
            [x,  w,  z, -y],
            [y, -z,  w,  x],
            [z,  y, -x,  w],
        ])
    return out

def quatConj(q):
    q_out = Matrix(q[:])
    q_out = q_out.T*sympy.diag(1,-1,-1,-1)
    q_out = q_out.T

    return q_out

def qRot(q,v):
    qPrime = quatConj(q)
    v = Matrix.vstack(zeros(1),v)
    vout = skew4Left(q)*skew4Right(qPrime)*v
    return Matrix(vout[1:])
```

# Inertia Tensor

```python
def build_inertia_tensor(Ivec):
    Ixx,Iyy,Izz,Ixy,Ixz,Iyz = Ivec

    Imat = zeros(3,3)
    Imat[0,0] = Ixx
    Imat[0,1] = Ixy
    Imat[0,2] = Ixz
    Imat[1,0] = Ixy
    Imat[1,1] = Iyy
    Imat[1,2] = Iyz
    Imat[2,0] = Ixz
    Imat[2,1] = Iyz
    Imat[2,2] = Izz

    return Imat
```

# 6DOF EOM using general body frame Force and Moment

Define Sympy Symbols

```python
rx,ry,rz = symbols('r_x r_y r_z')
vx,vy,vz = symbols('v_x v_y v_z')
qw, qx, qy, qz = symbols('q_w, q_x, q_y, q_z')
wx, wy, wz = symbols('w_x, w_y, w_z')
Ixx, Iyy, Izz, Ixy, Ixz, Iyz = symbols('I_xx, I_yy, I_zz, I_xy, I_xz, I_yz')
Mx, My, Mz = symbols('M_x, M_y, M_z')
Fbx, Fby, Fbz = symbols('F_x, F_y, F_z')
m,g = symbols('m g')
L = symbols('L') # Quadcopter arm length
```

Setup Vectors

```python
r_BwrtLexpL = Matrix([rx,ry,rz])
v_BwrtLexpL = Matrix([vx,vy,vz])
q_toLfromB  = Matrix([qw,qx,qy,qz])
wb          = Matrix([wx,wy,wz])
Fb          = Matrix([Fbx,Fby,Fbz])
Mb          = Matrix([Mx,My,Mz])
```

## Build Inertia Tensor

```python
Ixy = 0
Ixz = 0
Iyz = 0
Ivec = Ixx,Iyy,Izz,Ixy,Ixz,Iyz
inertiaTensor = build_inertia_tensor(Ivec)
display(inertiaTensor)
display(inertiaTensor.inv())
```

$\displaystyle \left[\begin{matrix}I_{xx} & 0 & 0\\0 & I_{yy} & 0\\0 & 0 & I_{zz}\end{matrix}\right]$

$\displaystyle \left[\begin{matrix}\frac{1}{I_{xx}} & 0 & 0\\0 & \frac{1}{I_{yy}} & 0\\0 & 0 & \frac{1}{I_{zz}}\end{matrix}\right]$

Gravity Vector in local frame (NED)

```python
g_expL = Matrix([0,0,g])
```

## Body Forces & Moments

```python
# Motor speeds
wm1, wm2, wm3, wm4 = symbols('w_m1, w_m2, w_m3, w_m4')
# Motor force and moment coefficients
kF, kM = symbols('k_F, k_M')

# Motor Thrust and Torque
Fm1 = kF*wm1**2
Fm2 = kF*wm2**2
Fm3 = kF*wm3**2
Fm4 = kF*wm4**2
Mm1 = kM*wm1**2
Mm2 = kM*wm2**2
Mm3 = kM*wm3**2
Mm4 = kM*wm4**2

# Calc Body Forces due to motors
Fb[0] = 0
Fb[1] = 0
Fb[2] = -(Fm1+Fm2+Fm3+Fm4)

# Calc Body Moments dut to motors
Mb[0] = L*(Fm4-Fm2)
Mb[1] = L*(Fm1-Fm3)
Mb[2] = Mm2 + Mm4 - Mm1 -Mm3

print('Fb')
display(Fb)
print('Mb')
display(Mb)

```

    Fb

$\displaystyle \left[\begin{matrix}0\\0\\- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\end{matrix}\right]$

    Mb

$\displaystyle \left[\begin{matrix}L \left(- k_{F} w_{m2}^{2} + k_{F} w_{m4}^{2}\right)\\L \left(k_{F} w_{m1}^{2} - k_{F} w_{m3}^{2}\right)\\- k_{M} w_{m1}^{2} + k_{M} w_{m2}^{2} - k_{M} w_{m3}^{2} + k_{M} w_{m4}^{2}\end{matrix}\right]$

## Sum of forces

```python
a_BwrtLexpL = 1/m*qRot(q_toLfromB,Fb) + g_expL

print('a_BwrtLexpL')
display(a_BwrtLexpL)
```

    a_BwrtLexpL

$\displaystyle \left[\begin{matrix}\frac{\left(2 q_{w} q_{y} + 2 q_{x} q_{z}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\\\frac{\left(- 2 q_{w} q_{x} + 2 q_{y} q_{z}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\\g + \frac{\left(q_{w}^{2} - q_{x}^{2} - q_{y}^{2} + q_{z}^{2}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\end{matrix}\right]$

## Sum of moments

```python
wbDot = inertiaTensor.inv() * (-skew3(wb)*inertiaTensor*wb + Mb)

print('wbDot')
display(wbDot)
```

    wbDot

$\displaystyle \left[\begin{matrix}\frac{I_{yy} w_{y} w_{z} - I_{zz} w_{y} w_{z} + L \left(- k_{F} w_{m2}^{2} + k_{F} w_{m4}^{2}\right)}{I_{xx}}\\\frac{- I_{xx} w_{x} w_{z} + I_{zz} w_{x} w_{z} + L \left(k_{F} w_{m1}^{2} - k_{F} w_{m3}^{2}\right)}{I_{yy}}\\\frac{I_{xx} w_{x} w_{y} - I_{yy} w_{x} w_{y} - k_{M} w_{m1}^{2} + k_{M} w_{m2}^{2} - k_{M} w_{m3}^{2} + k_{M} w_{m4}^{2}}{I_{zz}}\end{matrix}\right]$

## Quaternion Kinematic Equation

```python
qDot = 0.5*skew4Left(q_toLfromB) * Matrix.vstack(zeros(1),wb)
# 0.5*skew4Left(q_toLfromB)[:,1:] * wb

#display(skew4Left(q_toLfromB))
#display(skew4Left(q_toLfromB)[:,1:])
#display(0.5*skew4Left(q_toLfromB)[:,1:] * wb)

print('qDot')
display(qDot)
```

    qDot

$\displaystyle \left[\begin{matrix}- 0.5 q_{x} w_{x} - 0.5 q_{y} w_{y} - 0.5 q_{z} w_{z}\\0.5 q_{w} w_{x} + 0.5 q_{y} w_{z} - 0.5 q_{z} w_{y}\\0.5 q_{w} w_{y} - 0.5 q_{x} w_{z} + 0.5 q_{z} w_{x}\\0.5 q_{w} w_{z} + 0.5 q_{x} w_{y} - 0.5 q_{y} w_{x}\end{matrix}\right]$

## State and dstate vectors

```python
state = Matrix([r_BwrtLexpL, v_BwrtLexpL, q_toLfromB, wb])
dstate = Matrix([
    v_BwrtLexpL,
    a_BwrtLexpL,
    qDot,
    wbDot
])
display(state.T)
display(dstate)

mprint(dstate)

```

$\displaystyle \left[\begin{array}{ccccccccccccc}r_{x} & r_{y} & r_{z} & v_{x} & v_{y} & v_{z} & q_{w} & q_{x} & q_{y} & q_{z} & w_{x} & w_{y} & w_{z}\end{array}\right]$

$\displaystyle \left[\begin{matrix}v_{x}\\v_{y}\\v_{z}\\\frac{\left(2 q_{w} q_{y} + 2 q_{x} q_{z}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\\\frac{\left(- 2 q_{w} q_{x} + 2 q_{y} q_{z}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\\g + \frac{\left(q_{w}^{2} - q_{x}^{2} - q_{y}^{2} + q_{z}^{2}\right) \left(- k_{F} w_{m1}^{2} - k_{F} w_{m2}^{2} - k_{F} w_{m3}^{2} - k_{F} w_{m4}^{2}\right)}{m}\\- 0.5 q_{x} w_{x} - 0.5 q_{y} w_{y} - 0.5 q_{z} w_{z}\\0.5 q_{w} w_{x} + 0.5 q_{y} w_{z} - 0.5 q_{z} w_{y}\\0.5 q_{w} w_{y} - 0.5 q_{x} w_{z} + 0.5 q_{z} w_{x}\\0.5 q_{w} w_{z} + 0.5 q_{x} w_{y} - 0.5 q_{y} w_{x}\\\frac{I_{yy} w_{y} w_{z} - I_{zz} w_{y} w_{z} + L \left(- k_{F} w_{m2}^{2} + k_{F} w_{m4}^{2}\right)}{I_{xx}}\\\frac{- I_{xx} w_{x} w_{z} + I_{zz} w_{x} w_{z} + L \left(k_{F} w_{m1}^{2} - k_{F} w_{m3}^{2}\right)}{I_{yy}}\\\frac{I_{xx} w_{x} w_{y} - I_{yy} w_{x} w_{y} - k_{M} w_{m1}^{2} + k_{M} w_{m2}^{2} - k_{M} w_{m3}^{2} + k_{M} w_{m4}^{2}}{I_{zz}}\end{matrix}\right]$

    Matrix([
    [                                                                                v_x],
    [                                                                                v_y],
    [                                                                                v_z],
    [                (2*q_w*q_y + 2*q_x*q_z)*(-k_F*w_m1**2 - k_F*w_m2**2 - k_F*w_m3**2 - k_F*w_m4**2)/m],
    [               (-2*q_w*q_x + 2*q_y*q_z)*(-k_F*w_m1**2 - k_F*w_m2**2 - k_F*w_m3**2 - k_F*w_m4**2)/m],
    [g + (q_w**2 - q_x**2 - q_y**2 + q_z**2)*(-k_F*w_m1**2 - k_F*w_m2**2 - k_F*w_m3**2 - k_F*w_m4**2)/m],
    [                                                          -0.5*q_x*w_x - 0.5*q_y*w_y - 0.5*q_z*w_z],
    [                                                           0.5*q_w*w_x + 0.5*q_y*w_z - 0.5*q_z*w_y],
    [                                                           0.5*q_w*w_y - 0.5*q_x*w_z + 0.5*q_z*w_x],
    [                                                           0.5*q_w*w_z + 0.5*q_x*w_y - 0.5*q_y*w_x],
    [                               (I_yy*w_y*w_z - I_zz*w_y*w_z + L*(-k_F*w_m2**2 + k_F*w_m4**2))/I_xx],
    [                               (-I_xx*w_x*w_z + I_zz*w_x*w_z + L*(k_F*w_m1**2 - k_F*w_m3**2))/I_yy],
    [        (I_xx*w_x*w_y - I_yy*w_x*w_y - k_M*w_m1**2 + k_M*w_m2**2 - k_M*w_m3**2 + k_M*w_m4**2)/I_zz]])

```python
from sympy.physics.mechanics import *
from sympy import sin, cos, symbols, Matrix, solve
```

```python
# Inertial Reference Frame
N = ReferenceFrame('N')

# Define world corredinate origin
O = Point('O')
O.set_vel(N, 0.0)
```

```python

```

```python

```

```python

```


# <ins>Lab #1: Python Basics</ins>

These exercises are meant to give you some practice with the concepts from Tutorials 1.1 & 1.2. There's a prompt or two for each section, as well as a final question that brings it all together. Show your work! GLHF!

***
## Basic Arithmetic

1. Use the Pythagorean theorem, $a^2 + b^2 = c^2$, to find the hypotenuse length of a right triangle with side lengths $a = 6.1$ and $b = 5.6$.

```python
# Your answer below:

a, b = 6.1, 5.6
c = (a**2 + b**2)**(1/2.0)

print(c)
```

    8.280700453464066

2. Use the distance modulus, $m_v - M_v = 5log(d/10 \text{ pc})$, to find the distance to a star with apparent magnitude $m_v = 0.5$ and absolute magnitude $M_v = -5.85$.

```python
# Your answer below:

m, M = 0.5, -5.85
d = 10**((m-M)/5)*10

print(d, 'pc')
```

    186.20871366628677 pc

***
## Comments

1. Write a single-line comment containing your Swings order.

```python
# Your answer below:

# Whatever the best-looking special is
```

2. Write a multi-line comment describing your favorite astronomy fact.

```python
# Your answer below:

'''
Tycho Brahe died of a ruptured bladder
because he was too polite to get up
to use the bathroom at a dinner party.
He also got into swordfights all the time,
one of which cost him part of his nose.
'''
```

***
## Printing

1. Print your favorite letter, number and symbol on the same line.

```python
# Your answer here:

print('W', 5318008, '~')
```

    W 5318008 ~

***
## Data types

1. Use both string multiplication and concatenation to print 3 different animal noises.

```python
# Your answer here:

print('m' + 'o'*5)
print('b' + 'a'*5 + 'h')
print('n' + 'e'*5 + 'igh')
```

    mooooo
    baaaaah
    neeeeeigh

2. Print a true statement using four different comparison operators.

```python
# Your answer here:

print(((1 > 4) or (1 < 4)) and ((1 == 2) or (1 != 2)))
```

    True

***
## Variables

1. Use the quadratic equation, $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$, to find the roots of $5x^2 + 3x - 1$ by calculating the numerator and denominator separately. (**Tip:** When parintheses in a big equation get a little hard to read, breaking it up like this is a good way to make code easier to read.)

```python
# Your answer here:

import math
a,b,c = 5,3,-1

num_plus = -b + math.sqrt(b**2 - 4 * a * c)
num_minus = -b - math.sqrt(b**2 - 4 * a * c)
denom = 2*a

root_plus = num_plus/denom
root_minus = num_minus/denom

print(root_plus, root_minus)
```

    0.23851648071345039 -0.8385164807134504

***
## User input

1. Prompt the user for their age and calculate the percent of their life they've completed assuming they live to 80 years old.

```python
# Your answer here:

age = input('How old are you in years? ')

print((int(age)/80.0)*100.0, '%')
```

    How old are you in years? 21
    26.25 %

***
## Debugging

1. Rewrite the code below, fixing the errors and formatting with best practices.

```python
X1 = 1
Y1 = 2
X2 = 2
Y2 = 6

Dist = sqrt((X2-X1)^2-(Y2+Y1)^2))
print(Dist)
```

```python
# Your answer below:

import math
x1, y1, x2, y2 = 1, 2, 2, 6

dist = math.sqrt((x2-x1)**2 + (y2-y1)**2)
print(dist)
```

    4.123105625617661

***

## Indexing

1. Print the 4th, 9th, and 15th letter and the letter at the 20th, 3rd, and 12th indices of the word "pneumonoultramicroscopicsilicovolcanoconiosis" by indexing.

```python
# Your answer below:

string = "pneumonoultramicroscopicsilicovolcanoconiosis"

fourth,ninth,fifteenth = string[3], string[9], string[15]
index_20, index_3, index_12 = string[20], string[3], string[12]

print("Fourth letter:", fourth)
print("Ninth letter:", ninth)
print("Fifteenth letter:", fifteenth)

print("Third index:", index_3)
print("Twelfth index:", index_12)
print("Twentieth index:", index_20)
```

    Fourth letter: u
    Ninth letter: l
    Fifteenth letter: c
    Third index: u
    Twelfth index: a
    Twentieth index: o

2. Print the strings "pneumono," "ultra," "volcano," and "coniosis" by slicing the word from part one.

```python
# Your answer below:

string = "pneumonoultramicroscopicsilicovolcanoconiosis"

pneumono = string[:8]
ultra = string[8:13]
microscopic = string[13:24]
volcanoconiosis = string[-15:]

print(pneumono, ultra, microscopic, volcanoconiosis)
```

    pneumono ultra microscopic volcanoconiosis

3. Add together every third number in the list [155,2,54,34,5,16,7,38,26,10] and print the result.

```python
# Your answer below
lst = [155,2,54,34,5,6,7,38,9,10]

print(lst[2]+lst[5]+lst[8])
```

    69

***

## Manipulating strings and lists

1. Fix the string "peea7nut. bt-tt9r" with string (or list) functions.

```python
# Your code below:

string = "peea7nut. bt-tt9r"

string = string.replace('ea','a')
string = string.replace('7','')
string = string.replace('.','')
string = string.replace('t-','u')
string = string.replace('9','e')

print(string)

# Alternatively...

string = "peea7nut. bt-tt9r"

string = list(string)
string.remove('e')
string.remove('7')
string.remove('.')
string.remove('-')
string[8] = 'u'
string[-2] = 'e'
string = ''.join(string)

print(string)
```

    peanut butter
    peanut butter

***

## `numpy` arrays

1. Use the Wien displacement law to calculate the temperatures of blackbodies with 20 peak wavelengths between 300nm and 700nm using arrays.

\begin{equation}
    \lambda_{peak}T = 0.29 \text{ cm K}
\end{equation}

```python
# Your code below:

import numpy as np

lambdas = np.linspace(300,700,20)
lambdas_cm = lambdas*1E-7

temps = 0.29 / lambdas_cm

print(temps)
```

    [9666.66666667 9032.78688525 8476.92307692 7985.50724638 7547.94520548
     7155.84415584 6802.4691358  6482.35294118 6191.01123596 5924.7311828
     5680.41237113 5455.44554455 5247.61904762 5055.04587156 4876.10619469
     4709.4017094  4553.71900826 4408.         4271.31782946 4142.85714286]

## Challenge I: DMS/HMS Converter

While DMS (degrees, minutes, seconds) and HMS (hours, minutes, seconds) formats for celestial coordinates have their place (e.g. in every database ever), having them in decimal degrees is often more convenient for calculations. Write two scripts: one that allows the user to enter in a DMS coordinate and prints it in decimal degrees, and another for HMS coordinates.

```python
# Your code below:

# DMS

dms = input("Enter D:M:S coordinates, separated by colons: ")
dms = dms.split(":")
degs, mins, secs = dms
decdeg = float(degs) + float(mins)/60.0 + float(secs)/3600.0

print("Decimal degrees:", decdeg)
```

    Enter D:M:S coordinates, separated by colons: 54:54:54
    Decimal degrees: 54.915

```python
# HMS

hms = input("Enter H:M:S coordinates, separated by colons: ")
hms = hms.split(":")
hrs, mins, secs = hms
decdeg = (float(hrs) + float(mins)/60.0 + float(secs)/3600.0) * 15

print("Decimal degrees:", decdeg)
```

    Enter H:M:S coordinates, separated by colons: 12:00:00
    Decimal degrees: 180.0


### Vanden Bussche, Fromment 1995

```python
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
from tc_lib import *
%matplotlib inline
plt.style.use('seaborn-deep')

# Stoechiometrische Koeffizienten
nuij = np.zeros([len(namen), 3])
# Hydrierung von CO2
nuij[[
    namen.index('CO2'),
    namen.index('H2'),
    namen.index('CH3OH'),
    namen.index('H2O'),
    namen.index('CO'),
],0] = np.array([-1, -3, +1, +1, 0], dtype=float)
# Hydrierung von CO
nuij[[
    namen.index('CO2'),
    namen.index('H2'),
    namen.index('CH3OH'),
    namen.index('H2O'),
    namen.index('CO'),
],1] = np.array([0, -2, +1, 0, -1], dtype=float)
# RWGS Rückwassergasshiftreaktion
nuij[[
    namen.index('CO2'),
    namen.index('H2'),
    namen.index('CH3OH'),
    namen.index('H2O'),
    namen.index('CO'),
],2] = np.array([+1, +1, 0, -1, -1], dtype=float)

# T-abhängige Parameter, dem Artikel nach
def k_gg(t):
    # Geschwindigkeitskonstanten der 3 Reaktionen
    k_1 = 10**(3066/t-10.592)
    k_2 = 10**(5139/t-12.621)
    k_3 = 10**(2073/t-2.029)
    # Angepasste Parameter des kinetischen Modells
    # A(i) exp(B(i)/RT)
    a = np.array([
        0.499, 6.62e-11, 3453.38, 1.07, 1.22e-10
    ], dtype=float)
    b = np.array([
        17197, 124119, 0, 36696, -94765
    ], dtype=float)
    k_h2 = a[0]**2 * np.exp(2 * b[0]/(r * t))
    k_h2o = a[1] * np.exp(b[1]/(r * t))
    k_h2o_d_k_8_k_9_k_h2 = a[2] * np.exp(b[2]/(r * t))
    k5a_k_2_k_3_k_4_k_h2 = a[3] * np.exp(b[3]/(r * t))
    k1_strich = a[4] * np.exp(b[4]/(r * t))
    return np.array([
        k_1, k_2, k_3,
        k_h2, k_h2o, k_h2o_d_k_8_k_9_k_h2,
        k5a_k_2_k_3_k_4_k_h2, k1_strich
    ])

# Gleichgewichtskonstanten bei T, berechnet
def k_t(t, nuij):
    h_t = h(t)
    g_t = g(t, h_t)
    k_t = k(t, g_t, nuij)
    return k_t

t = np.linspace(50, 1000, 35) + 273.15
fig = plt.figure()
ax = fig.add_subplot(111)
for i in range(nuij.shape[1]):
    ax.plot(1000/t,
            [k_t(temp, nuij[:,i]) for temp in t],
            'o', label='K_berechnet'+str(i+1))
    ax.plot(1000/t, k_gg(t)[i],
            '-', label='K_Artikel'+str(i+1))
ax.set_yscale('log')
ax.set_xlabel(r'$\frac{1000}{T/K}$')
ax.legend()

print('Tabelle 8 Kp(RWGS)')
for t in np.array([467, 489, 522, 511, 360, 381, 404]):
    print(
        str(t) + 'K' + '. Berechnet ' +
        '{:.2e}'.format(1/k_t(t+273.15, nuij)[2]*10) +
        '\t' + 'Artikel ' +
        '{:.2e}'.format(1/k_gg(t+273.15)[2]*10)
    )

def r_i(t, p_i):
    p_co2 = p[namen.index('CO2')]
    p_h2 = p[namen.index('H2')]
    p_ch3oh = p[namen.index('CH3OH')]
    p_h2o = p[namen.index('H2O')]
    [k_1, k_2, k_3,
    k_h2, k_h2o, k_h2o_d_k_8_k_9_k_h2,
    k5a_k_2_k_3_k_4_k_h2, k1_strich] = k_gg(t)
    r_meoh = k5a_k_2_k_3_k_4_k_h2 * p_co2 * p_h2 * (
        1 - 1/k_1 * p_h2o * p_ch3oh / (
            p_h2**3 * p_co2
        )
    ) / (
        1 + k_h2o_d_k_8_k_9_k_h2 * ph2o / p_h2 +
        np.sqrt(k_h2 * p_h2) + k_h20 * p_h2o
    )
    r_rwgs = k1_strich * p_co2 * (
        1 - k_3 * p_h2o * p_co / (p_co2 * p_h2) /(
            1 + k_h2o_d_k_8_k_9_k_h2 * p_h2o / p_h2 +
            np.sqrt(k_h2 * p_h2) + k_h2o * p_h2o
        )
    )
    return np.array([r_meoh, r_rwgs])
```

#### Umformung auf Aspen-Form

```python
print('1.65*np.exp(-(-94765)/8.3145/501.57)/1e10=' +
      '{:g}'.format(1.65*np.exp(-(-94765)/8.3145/501.57)/1e10))
a = np.array([
        0.499, 6.62e-11, 3453.38, 1.07, 1.22e10
    ], dtype=float)
b = np.array([
    17197, 124119, 0, 36696, -94765
], dtype=float)
print('')
print('k5a_k_2_k_3_k_4_k_h2:')
print('A_Asp=ln(A/1000)=' + '{:g}'.format(np.log(a[3]/1000.)))
print('B_Asp=B/R=' + '{:g}'.format(b[3]/8.3145)+'K')
print('k5a_k_2_k_3_k_4_k_h2 / k_1:')
print('A_Asp=ln(A/1000)-C ln(10)=' +
      '{:g}'.format(np.log(a[3]/1000.)-(-10.592*np.log(10))))
print('B_Asp=B/R-D ln(10)=' +
      '{:g}'.format(b[3]/8.3145 - 3066*np.log(10))+'K')
print('')
print('k1_strich:')
print('A_Asp=ln(A/1000)=' + '{:g}'.format(np.log(a[4]/1000.)))
print('B_Asp=B/R=' + '{:g}'.format(b[4]/8.3145)+'K')
print('k1_strich * k_3:')
print('A_Asp=ln(A/1000)+C ln(10)=' +
      '{:g}'.format(np.log(a[4]/1000.)+(-2.029*np.log(10))))
print('B_Asp=B/R+D ln(10)=' +
      '{:g}'.format(b[4]/8.3145 + 2073*np.log(10))+'K')
print('')
print('k_h2o_d_k_8_k_9_k_h2:')
print('A_Asp=ln(A)=' + '{:g}'.format(np.log(a[2])))
print('B_Asp=B/R=' + '{:g}'.format(b[2]/8.3145)+'K')
print('')
print('k_h2^(1/2):')
print('A_Asp=ln(A)=' + '{:g}'.format(np.log(a[0])))
print('B_Asp=B/R=' + '{:g}'.format(b[0]/8.3145)+'K')
print('')
print('k_h2o:')
print('A_Asp=ln(A)=' + '{:g}'.format(np.log(a[1])))
print('B_Asp=B/R=' + '{:g}'.format(b[1]/8.3145)+'K')
```

    1.65*np.exp(-(-94765)/8.3145/501.57)/1e10=1.2198

    k5a_k_2_k_3_k_4_k_h2:
    A_Asp=ln(A/1000)=-6.8401
    B_Asp=B/R=4413.49K
    k5a_k_2_k_3_k_4_k_h2 / k_1:
    A_Asp=ln(A/1000)-C ln(10)=17.5489
    B_Asp=B/R-D ln(10)=-2646.23K

    k1_strich:
    A_Asp=ln(A/1000)=16.3169
    B_Asp=B/R=-11397.6K
    k1_strich * k_3:
    A_Asp=ln(A/1000)+C ln(10)=11.645
    B_Asp=B/R+D ln(10)=-6624.3K

    k_h2o_d_k_8_k_9_k_h2:
    A_Asp=ln(A)=8.14711
    B_Asp=B/R=0K

    k_h2^(1/2):
    A_Asp=ln(A)=-0.695149
    B_Asp=B/R=2068.31K

    k_h2o:
    A_Asp=ln(A)=-23.4383
    B_Asp=B/R=14928K

## Umformung auf Hysys-Form

*Konventionen*

| Froment etc. | Hysys |
| - | - |
| $r[=]\frac{mol}{kg_{Kat}\cdot s}$ | $r_{Hysys}[=]\frac{kgmol}{m^3_{Gas} \cdot s}$ |

$\begin{array}{ccl}
\phi &[=]& \frac{m^3_{Gas}}{m^3_{Kat, Schüttung}}=\frac{m^3_{Gas}}{m^3_{Kat}+m^3_{Gas}}\\
1-\phi &[=]& \frac{m^3_{Kat}}{m^3_{Kat, Schüttung}}=\frac{m^3_{Kat}}{m^3_{Kat}+m^3_{Gas}}\\
\rho_b &[=]& \frac{kg_{Kat}}{m^3_{Kat, Schüttung}}=\frac{kg_{Kat}}{m^3_{Kat}+m^3_{Gas}}\\
\rho_c &[=]& \frac{kg_{Kat}}{m^3_{Kat}}\\
\Rightarrow \rho_b &=&  (1-\phi)\rho_c\\
\Rightarrow r_{Hysys} &=& r\cdot \left( \frac{1-\phi}{\phi}\right)\rho_c
\end{array}$

**Kinetik-Ausdrücke**, aus Van den Bussche-Froment, auf $Cu/ZnO/Al_2O_3$ Katalysator

$p_i$ hier eigentlich: $p_i/p^{\circ}$ , $p^{\circ}=1bar$. Es heißt, $r_{MeOH}$ hat die Einheiten $r_{MeOH}[=]k_{5a}'=k_{5a}c_t^2=\frac{mol}{kg_{Kat}\cdot s}$, und die Reaktionsquotienten haben keine Einheiten.

$r_{MeOH}=\frac{k_{5a}' K_2' K_3 K_4 K_{H_2} p_{CO_2}p_{H_2}\left(1-\frac{1}{K_1^*}\cdot\frac{p_{H_2O}\cdot p_{MeOH}}{p_{H_2}^3\cdot p_{CO_2}}\right)}{\left(1+\left(\frac{K_{H_2O}}{K_8 K_9 K_{H_2}}\right)\frac{p_{H_2O}}{p_{H_2}}+\sqrt{K_{H_2}\cdot p_{H2}}+K_{H_2O}\cdot p_{H_2O}\right)^3}$

$r_{RWGS}=\frac{k_1' p_{CO_2}\left(1-K_3^*\cdot\frac{p_{H_2O}\cdot p_{CO}}{p_{H_2}\cdot p_{CO_2}}\right)}{\left(1+\left(\frac{K_{H_2O}}{K_8 K_9 K_{H_2}}\right)\frac{p_{H_2O}}{p_{H_2}}+\sqrt{K_{H_2}\cdot p_{H2}}+K_{H_2O}\cdot p_{H_2O}\right)}$

Umformung der Geschwindigkeitskonstanten von der Form im Artikel auf die Form
in Hysys:

$k = A \cdot exp\left(\frac{-E}{R T}\right)*T^\beta$

* $r_{MeOH}$, Vorwärtsreation

im Artikel (Tabelle 1):

$k(i) = A(i) \cdot exp\left(\frac{B(i)}{R T}\right)$

$\begin{align}
k_{5a}' K_2' K_3 K_4 K_{H_2} &=7070,34 \cdot e^{\frac{-36696}{8,3145\cdot501,57}} \frac{mol}{kg_{Kat}\cdot s} \cdot exp\left(\frac{\frac{36,696 J/mol}{8,3145 J/(mol K)}}{ T}\right) \\
& = 1,066\frac{mol}{kg_{Kat}\cdot s} \cdot exp\left(\frac{4413,49K}{ T}\right)
\end{align}$

Da

$r_{MeOH}[=]k_{5a}'=k_{5a}c_t^2=\frac{mol}{kg_{Kat}\cdot s} \quad \text{ und } \quad r_{Hysys}[=]\frac{kgmol}{m^3_{Gas} \cdot s}$,

$\Rightarrow r_{Hysys, MeOH} = r_{MeOH}\cdot \left( \frac{1-\phi}{\phi}\right)\rho_c \cdot \left(\frac{1 kgmol}{1000 mol}\right)$

Diese Faktoren werden am Preexponentiellen Faktor des Geschwindigkeits-Ausdrucks übernommen. Z. B. bei $\phi=0,285$, $\rho_b=1190\frac{kg_{Kat}}{m^3_{Kat, Schüttung}}=(1-\phi)\rho_c$:

$\begin{align}
k_{Vorwärtsreaktion} &=\\
k_{5a}' K_2' K_3 K_4 K_{H_2} &= 7070,34\cdot e^{\frac{-36696}{8,3145\cdot501,57}}  \frac{mol}{kg_{Kat}\cdot s} \cdot \left( \frac{1-\phi}{\phi}\right)\rho_c \cdot \left(\frac{1 kgmol}{1000 mol}\right)  \cdot exp\left(\frac{4413,49K}{ T}\right)\\
&= 7070,34\cdot e^{\frac{-36696}{8,3145\cdot501,57}}  \frac{mol}{kg_{Kat}\cdot s} \cdot \left( \frac{1190\frac{kg_{Kat}}{m^3_{Kat, Schüttung}}}{0,285\frac{m^3_{Gas}}{m^3_{Kat, Schüttung}} }\right) \cdot \left(\frac{1 kgmol}{1000 mol}\right)  \cdot exp\left(\frac{4413,49K}{ T}\right)\\
&= 7070,34\cdot e^{\frac{-36696}{8,3145\cdot501,57}} \cdot \frac{1190}{0,285\cdot 1000} \frac{kgmol}{m^3_{Gas}\cdot s} \cdot exp\left(\frac{4413,49K}{ T}\right)\\
&= 4,4528 \frac{kgmol}{m^3_{Gas}\cdot s} \cdot exp\left(\frac{36696J/mol}{ R T}\right)\\
\end{align}$

* $r_{MeOH}$, Rückwärtsreaktion

$\begin{align}
k_{Rückwärtsreaktion} &= k_{5a}' K_2' K_3 K_4 K_{H_2} \cdot \frac{1}{K_1*} \\ &= 7070,34\cdot e^{\frac{-36696}{8,3145\cdot501,57}}\cdot \frac{1190}{0,285\cdot 1000} \frac{kgmol}{m^3_{Gas}\cdot s} \cdot exp\left(\frac{36696J/mol}{R T}\right) \cdot 10^\left(-\frac{3066K}{T}+10,592\right)\\
&=7070,34\cdot e^{\frac{-36696}{8,3145\cdot501,57}}\cdot \frac{1190}{0,285\cdot 1000}\cdot 10^{10,592} \frac{kgmol}{m^3_{Gas}\cdot s} \cdot exp\left(\frac{(36696-3066\cdot ln(10)\cdot8,3145)J/mol}{R T}\right)\\
&=1,740321\cdot 10^{11} \frac{kgmol}{m^3_{Gas}\cdot s} \cdot exp\left(\frac{-22002.09J/mol}{R T}\right)\\
\end{align}$

Zusammenfassung der Eingabe von Geschwindigkeitskonstanten aus Tabelle 2 (im Artikel) auf Hysys

$r_{MeOH}$

| Geschwindigkeitskonstante | Parameter | Artikel | Hysys-Eingabe |
| - | - | - | - |
| $k_{5a}' K_2' K_3 K_4 K_{H_2}$ | A(4) |  1,066 $\frac{mol}{kg_{Kat}\cdot s}$ |  4,452761 $\frac{mol}{m^3_{Gas}\cdot s}$ |
| $k_{5a}' K_2' K_3 K_4 K_{H_2}$ | B(4) | 36696 J/mol | -36696 kJ/kgmol |
| $k_{5a}' K_2' K_3 K_4 K_{H_2}\cdot\frac{1}{K_1}$ | |  $1,066\cdot10^{10,592}$$ \frac{mol}{kg_{Kat}\cdot s}$  | $1,740321\cdot10^{11}$$\frac{mol}{m^3_{Gas}\cdot s}$ |
| $k_{5a}' K_2' K_3 K_4 K_{H_2}\cdot\frac{1}{K_1}$ | | $(36696-8,3145\cdot 3066)$ J/mol | -11203,743 kJ/kgmol |

$r_{RWGS}$

| Geschwindigkeitskonstante | Parameter | Artikel | Hysys-Eingabe |
| - | - | - | - |
| $k_1'$ | A(5) |  1,220 $\frac{mol}{kg_{Kat}\cdot s}$ | 5,093209e+10 $\frac{mol}{m^3_{Gas}\cdot s}$ |
| $k_1'$ | B(5) | -94765 J/mol | +94765 kJ/kgmol |
| $k_1'\cdot K_3$ | |  $1,220\cdot 10^{+2,029}$ $mol/kg_{Kat}/s$ | 4,764217e+08 $\frac{kgmol}{m^3_{Gas} \cdot s}$ |
| $k_1'\cdot K_3$ | | $(-94765+8,3145\cdot 2073)$ J/mol | +77529,04 kJ/kgmol |

Adsorptionsterme

| Adsorptionsterm | Parameter | Artikel | Hysys-Eingabe |
| - | - | - | - |
| $\sqrt{K_{H_2}}$ | A(1) | 30,82 | 30,82 |
| $\sqrt{K_{H_2}}$ | B(1) | 17197 J/mol |  -17197 J/mol |
| $K_{H_2O}$ | A(2) |  558,17 | 558,17 |
| $K_{H_2O}$ | B(2) | 124119 J/mol | -124119 J/mol |
| $\frac{K_{H_2O}}{K_8 K_9 K_{H2}}$ | A(3) |  3453,38 | 3453,38 |
| $\frac{K_{H_2O}}{K_8 K_9 K_{H2}}$ | B(3) | 0 J/mol | 0 J/mol |

```python
import locale
import numpy as np
from IPython.display import Latex
locale.setlocale(locale.LC_ALL, '')

phi = 0.3

table_latex_str = [
    r'\text{Hohlraumvolumen: } \phi=', locale.format('%4.8g',phi),
    r'\\',
    r'\begin{array}{lccccc}',
    '\hline ',
    'Var & A(i) & A(i)_{Hysys} & B(i) & B(i)_{Hysys} & ',
    r'\text{Hysys Param}', r'\\',
    r'\text{Form } K=A(i) \cdot exp\left(\frac{B(i)}{R T}\right) ','&',
    r' \frac{mol}{kg_{Kat}\cdot s} & \frac{mol}{m^3_{Gas}\cdot s}',
    r' & \frac{J}{mol} & \frac{kJ}{kgmol} & ',
    r'\text{Form } K=A_{Hysys} \cdot exp\left(-\frac{E_{Hysys}}{R T}\right) ',
    r'\\',
    '\hline ',
    r'\\','r_{MeOH}', r'\\', r'\\',
    "k_{5a}' K_2' K_3 K_4 K_{H_2}", '&',
    locale.format('%4.8g', 7070.34*np.exp(-36696/(8.3145*501.57))), '&',
    locale.format('%4.8g', 7070.34*np.exp(-36696/(8.3145*501.57)
                                           )*1190/phi/1000 ),
    '&',
    locale.format('%4.8g', 36696), '&',
    locale.format('%4.8g', -36696), '&', 'k_{Vorwärts}',
    r'\\',
    r"k_{5a}' K_2' K_3 K_4 K_{H_2}\cdot \frac{1}{K_1}", '&',
    locale.format('%4.8g', 7070.34*
                  np.exp(-36696/(8.3145*501.57)
                        )*
                  10**10.592
                   ),'&',
    locale.format('%4.8g', 7070.34*
                    np.exp(-36696/(8.3145*501.57)
                          )*
                    1190/phi/1000 *10**10.592
                   ),'&',
    locale.format('%4.8g', (36696-3066*8.3145*np.log(10))),'&',
    locale.format('%4.8g', -(36696-3066*8.3145*np.log(10))),'&',
    "k'_{Rückwärts}", r'\\'
    r'\\','r_{RWGS}', r'\\', r'\\',
    "k_1'", '&',
    locale.format('%4.8g', 1.65*np.exp(-(-94765)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 1.65*np.exp(-(-94765)/(8.3145*501.57)
                                           )*1190/phi/1000 ), '&',
    locale.format('%4.8g', -94765), '&',
    locale.format('%4.8g', 94765), '&', 'k_{Vorwärts}',
    r'\\',
    r"k_1' \cdot K_3", '&',
    locale.format('%4.8g', 1.65*np.exp(-(-94765)/(8.3145*501.57))*
                  10**-2.029), '&',
    locale.format('%4.8g', 1.65*np.exp(-(-94765)/(8.3145*501.57))*
                  1190/phi/1000 *10**-2.029 ), '&',
    locale.format('%4.8g', (-94765+2073*8.3145*np.log(10))),'&',
    locale.format('%4.8g', -(-94765+2073*8.3145*np.log(10))),'&',
    "k'_{Rückwärts}", r'\\',
    r'\\',r'Adsorptionsterme (\beta)', r'\\', r'\\',
    r'\sqrt{K_{H_2}}', '&',
    locale.format('%4.8g', 30.82*np.exp(-(17197)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 30.82*np.exp(-(17197)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 17197.), '&',
    locale.format('%4.8g', -17197.), '&', 'K1', r'\\',
    'K_{H_2O}','&',
    locale.format('%4.8g', 558.17*np.exp(-(124119)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 558.17*np.exp(-(124119)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 124119), '&',
    locale.format('%4.8g', -124119), '&', 'K2', r'\\',
    r'\frac{K_{H_2O}}{K_8 K_9 K_{H2}}','&',
    locale.format('%4.8g', 3453.38*np.exp(-(0)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 3453.38*np.exp(-(0)/(8.3145*501.57))), '&',
    locale.format('%4.8g', 0), '&',
    locale.format('%4.8g', -0), '&', 'K3', r'\\',
    r'\hline'
    r'\end{array}'
]
Latex('$'+''.join(table_latex_str)+'$')
```

$\text{Hohlraumvolumen: } \phi= 0,3\\\begin{array}{lccccc}\hline Var & A(i) & A(i)_{Hysys} & B(i) & B(i)_{Hysys} & \text{Hysys Param}\\\text{Form } K=A(i) \cdot exp\left(\frac{B(i)}{R T}\right) & \frac{mol}{kg_{Kat}\cdot s} & \frac{mol}{m^3_{Gas}\cdot s} & \frac{J}{mol} & \frac{kJ}{kgmol} & \text{Form } K=A_{Hysys} \cdot exp\left(-\frac{E_{Hysys}}{R T}\right) \\\hline \\r_{MeOH}\\\\k_{5a}' K_2' K_3 K_4 K_{H_2}&1,0664174&4,2301225&36696&-36696&k_{Vorwärts}\\k_{5a}' K_2' K_3 K_4 K_{H_2}\cdot \frac{1}{K_1}&4,1679955e+10&1,6533049e+11&-22002,091&22002,091&k'_{Rückwärts}\\\\r_{RWGS}\\\\k_1'&1,2198022e+10&4,8385487e+10&-94765&94765&k_{Vorwärts}\\k_1' \cdot K_3&1,1410099e+08&4,5260059e+08&-55077,739&55077,739&k'_{Rückwärts}\\\\Adsorptionsterme (\beta)\\\\\sqrt{K_{H_2}}&0,4988167&0,4988167&17197&-17197&K1\\K_{H_2O}&6,6228081e-11&6,6228081e-11&124119&-124119&K2\\\frac{K_{H_2O}}{K_8 K_9 K_{H2}}&3453,38&3453,38&   0&   0&K3\\\hline\end{array}$

### WGS auf ICI-Fe3O4-Cr2O3

```python
import locale
import numpy as np
from IPython.display import Latex
locale.setlocale(locale.LC_ALL, '')

epsilon_b = 0.457

table_latex_str = [
    r'\text{Hohlraumvolumen: } \phi=', locale.format('%4.8g',epsilon_b),
    r'\\',
    r'\begin{array}{lccccc}',
    '\hline ',
    'Var & A(i) & A(i)_{Hysys} & B(i) & E(i)_{Hysys} & ',
    r'\text{Hysys Param}', r'\\',
    r'\text{Form } K=A(i) \cdot exp\left(\frac{B(i)}{R T}\right) ','&',
    r' \frac{mol^{0,36} (m^3_{G})^{0,64}}{kg_{Kat}\cdot s}',
    r' & \left(\frac{kgmol}{m^3_{G}}\right)^{0,36} \cdot \frac{1}{s}',
    r' & \frac{J}{mol} & \frac{kJ}{kgmol} & ',
    r'\text{Form } K=A_{Hysys} \cdot exp\left(-\frac{E_{Hysys}}{R T}\right) ',
    r'\\',
    '\hline ',
    r'\\','r_{WGS}', r'\\', r'\\',
    "k_m", '&',
    locale.format('%4.8g', np.exp(8.22)), '&',
    locale.format('%4.8g', np.exp(8.22)*(1-epsilon_b)/epsilon_b*1960/1000.**0.36),
    '&',
    locale.format('%4.8g', -8008*8.3145), '&',
    locale.format('%4.8g', +8008*8.3145), '&', 'k_{Vorwärts}',
    r'\\',
    r"k_m\cdot \frac{1}{K_{eq}}", '&',
    locale.format('%4.8g', np.exp(8.22+4.27)),'&',
    locale.format('%4.8g', np.exp(8.22+4.27)*(1-epsilon_b)/epsilon_b*1960/1000.**0.36),'&',
    locale.format('%4.8g', (-8008-4483)*8.3145),'&',
    locale.format('%4.8g', -(-8008-4483)*8.3145),'&',
    "k'_{Rückwärts}", r'\\'
    r'\hline'
    r'\end{array}'
]
Latex('$'+''.join(table_latex_str)+'$')
```

$\text{Hohlraumvolumen: } \phi=0,457\\\begin{array}{lccccc}\hline Var & A(i) & A(i)_{Hysys} & B(i) & E(i)_{Hysys} & \text{Hysys Param}\\\text{Form } K=A(i) \cdot exp\left(\frac{B(i)}{R T}\right) & \frac{mol^{0,36} (m^3_{G})^{0,64}}{kg_{Kat}\cdot s} & \left(\frac{kgmol}{m^3_{G}}\right)^{0,36} \cdot \frac{1}{s} & \frac{J}{mol} & \frac{kJ}{kgmol} & \text{Form } K=A_{Hysys} \cdot exp\left(-\frac{E_{Hysys}}{R T}\right) \\\hline \\r_{WGS}\\\\k_m&3714,5024&719515,81&-66582,516&66582,516&k_{Vorwärts}\\k_m\cdot \frac{1}{K_{eq}}&265667,29&51460948&-103856,42&103856,42&k'_{Rückwärts}\\\hline\end{array}$

### Wedel 1988

```python
k_0_hin = 1.98e+7 # mol/(kg Kat * h * (MPa)^0,58)
ea_hin = 56343 # J/mol
nu_i_hin = np.array([0.18, 0.4, 0]) # CO, H2, CH3OH
k_0_zur = 2.15e+10 # mol/(kg Kat * h * (MPa)^0,13)
ea_zur = 85930 # J/mol
nu_i_zur = np.array([0, 0, 0.13]) # CO, H2, CH3OH
r = 8.314 # J/(mol K)

def r_j_wedel(k_0, ea, p_i, t, nu_i):
    k_t = k_0 * np.exp(-ea/(r * t))
    return k_t * np.product(np.power(p_i, nu_i))

```

    0.0030628317126543598

```python
nco0 = 2115
nco20 = 235
xi=(nco0-nco20)/2
print(1/10**(2073/(220+273.15)-2.029))
print(xi)
(2115+xi)/10**(2073/(219.9783+273.15)-2.029)+xi-235
#(2115+xi)*0.00631477737+xi-235
```

    0.006689764481429299
    940.0

    725.4285275642302

### Chem. Eng. Technol. 2011, 34, No. 5, 817–822

```python
d =
```