Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some examples #6

Draft
wants to merge 4 commits into
base: www
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions content/getting_started/Examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "Examples"
date: "2022-08-17"
draft: false
weight: 40
---

# Automatic Differentiation in Scientific Computing

It goes without saying that `derivatives` are essential in formulating, hence simulating, physical phenomena. However, in real world problems, they can be complicated or error-prone to be derived analytically, and numerical differentiation can introduce round-off errors in the discretization process and cancellation. These problems become more serious with higher derivatives beside being slow. Automatic differentiation, on the other hand, doesn't have any of these problems.

Differentiation in general is all about chain rule. We know from Calculus that we can differentiate a given composition $h(g(f(x)))$ via

$$ \operatorname d h = \frac{dh}{dg} \left(\frac{dg}{df} \left(\frac{df}{dx} \operatorname d x \right) \right) .$$

This method is called `forward-mode` and it is mostly used when there are one input and multiple outputs. While forward-mode differentiation is more efficient than other methods, the Scientific Community has shown more interest in cases where there are multiple inputs and a single output. This can be obtained via reverse-mode differentiation. Rearranging the parentheses in the expression above, we will have

$$ \operatorname d h = \left( \left( \left( \frac{dh}{dg} \right) \frac{dg}{df} \right) \frac{df}{dx} \right) \operatorname d x $$

which we can compute with `reverse-mode` via

$$ \underbrace{\bar x}_{\frac{dh}{dx}} = \underbrace{\bar g \frac{dg}{df}}_{\bar f} \frac{df}{dx} .$$

Enzyme is a primarily targeting reverse-mode differentiation, though it supports the forward-mode as well. In the following examples we show some common use cases in scientific computing with both modes.

## Constant Function

Let's start with the simplest case in calculus: constant functions/values. The following example demonstrates that the derivative of a constant function is, indeed, zero.

```c
// constant_rev.c
// This function demonstrates the derivative of a constant function.

#include <stdio.h>
extern double __enzyme_autodiff(void *);
double Constant() { return 2.; }
double dConstant() { return __enzyme_autodiff((void *) Constant); }
int main() {
printf(" Constant = %f \n dConstant = %f \n", Constant(), dConstant());
}
```

One way to compile this code is with the following arguments:
```bash
$ clang constant_rev.c -Xclang -load -Xclang ./Enzyme/ClangEnzyme-13.so -O2 -flegacy-pass-manager
```

Output:
```bash
Constant = 2.000000
dConstant = 0.000000
```


## Scalar Function

The following example computes the volume of a cylinder, $v$, given $r$ (radius) and $h$ (height), and the constant value $\pi$.
Taking the derivative of $v$ with respect to $r$ and $h$, we obtain the lateral surface area and the cross-sectional surface area, respectively. Note that this is a multi-variable scalar function, for which we demonstrate how to treat constant/frozen variables (e.g. $\pi$) as well.

```c
// scalar_rev.c
// This function demonstrates the derivative of a scalar function.
#include <stdio.h>
extern double __enzyme_autodiff(void *, ...);
int enzyme_const; // This is a built-in Enzyme variable for frozen variables
void V_cylinder(double *v, double *r, double *h, const double pi) {
*v = pi * (*r) * (*r) * (*h);
}
void dV_cylinder(double *v, double *r, double *dr, double *h, double *dh, const double pi) {
double dv = 1;
__enzyme_autodiff((void *) V_cylinder, v, &dv, r, dr, h, dh, enzyme_const, pi);
}
int main() {
const double pi = 3.141593;
double r = 3, h = 2, volume_cylinder = 0, surface_lateral = 0, surface_cross_sectional = 0;
dV_cylinder(&volume_cylinder, &r, &surface_lateral, &h, &surface_cross_sectional, pi);
printf("Cylinder with r=%f and h=%f \n", r, h);
printf("----------------------------------------\n");
printf("Volume = %f \n", volume_cylinder);
printf("Lateral Surface Area = %f \n", surface_lateral);
printf("Cross-sectional Surface Area = %f \n", surface_cross_sectional);
return 0;
}
```

Output:
```bash
Cylinder with r=3.000000 and h=2.000000
----------------------------------------
Volume = 56.548674
Lateral Surface Area = 37.699116
Cross-sectional Surface Area = 28.274337
```
2 changes: 1 addition & 1 deletion content/getting_started/Faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "FAQ"
date: "2019-11-29"
menu: "main"
weight: 40
weight: 50
---

## Enzyme builds successfully but won't run tests
Expand Down
4 changes: 3 additions & 1 deletion content/getting_started/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ Please see the [Using Enzyme](/getting_started/UsingEnzyme) guide for informatio

Please see the [Calling Convention](/getting_started/CallingConvention) guide for detailed information on Enzyme's calling convention and ABI, as well as how to specify how functions should be differentiated.

Please see the [CUDA Guide](/getting_started/CUDAGuide) guide for information on working with CUDA code.
Please see the [CUDA Guide](/getting_started/CUDAGuide) guide for information on working with CUDA code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to add a Examples tab on the higher level file, otherwise it doesn't show up.

Also the latex isn't getting rendered right now, so we probably need to include a plugin.

Please see [Examples](/getting_started/Examples) to see how Enzyme can be used in scientific applications.