diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8d055fe..bcaf674 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,7 +33,7 @@ endif()
add_executable(mountaindiff src/mountaindiff.cpp ${COMMON_INCLUDES})
# initial
-add_executable(initial src/initial.cpp ${COMMON_INCLUDES})
+add_executable(initial src/initial.cpp src/MountainRangeBasic.hpp)
# mountainsolve_serial
add_executable(mountainsolve_serial src/mountainsolve.cpp ${COMMON_INCLUDES})
diff --git a/README.md b/README.md
index 58a3e14..a6cfcd2 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ The other binaries mirror those that will be built for the C++ phases of the pro
| Corresponding phase | Binary | Source files |
| --- | --- | --- |
-| [Phase 1](https://byuhpc.github.io/sci-comp-course/project/phase1) | `initial` | [initial](src/initial.cpp), [MountainRange](src/MountainRange.hpp) |
+| [Phase 1](https://byuhpc.github.io/sci-comp-course/project/phase1) | `initial` | [initial](src/initial.cpp), [MountainRangeBasic](src/MountainRangeBasic.hpp) |
| [Phase 2](https://byuhpc.github.io/sci-comp-course/project/phase2) | `mountainsolve_serial`* | [MountainRange](src/MountainRange.hpp) |
| [Phase 3](https://byuhpc.github.io/sci-comp-course/project/phase3) | `mountainsolve_openmp` | [MountainRange](src/MountainRange.hpp) |
| [Phase 6](https://byuhpc.github.io/sci-comp-course/project/phase6) | `mountainsolve_thread` | [MountainRangeThreaded](src/MountainRangeThreaded.hpp) |
diff --git a/docs/MountainRange-sequence-diagram.md b/docs/MountainRange-sequence-diagram.md
deleted file mode 100644
index d128a9e..0000000
--- a/docs/MountainRange-sequence-diagram.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# Mountain Range Threaded — Sequence Diagram
-
-> [!IMPORTANT]
-> This diagram relies on [Mermaid diagrams](https://mermaid.js.org/) which display properly when rendered within GitHub.
->
-> It may not work properly when rendered within other websites. [Click here to view the source](https://github.com/BYUHPC/sci-comp-course-example-cxx/blob/main/docs/MountainRange-sequence-diagram.md).
-
-## Intro
-
-This [sequence diagram](https://mermaid.js.org/syntax/sequenceDiagram.html#sequence-diagrams) written with Mermaid visually represents
-the calls and work being performed in the `MountainRange` example.
-
-It is designed to help visualize the relationships between
-the various entities involved in running the program. The close reader will observe stacked activation functions representing calls
-to methods on the base or subclass of the `MountainRange` object.
-
-The code covered by this diagram exists in two separate example files:
-* [MountainRange.hpp](../src/MountainRange.hpp) (base class)
-* [initial.cpp](../src/initial.cpp) (driver code)
-
-## Diagram
-
-```mermaid
----
-title: Mountain Range — Sequence Diagram
----
-
-sequenceDiagram
-
-participant main
-participant MR as MountainRange
-participant cout as std::cout
-
-note left of main: Program starts
-activate main
-
-%% Initialize MountainRange
-note over main,MR: Construct MountainRange
-note right of main: Init constants and
fill vectors with zeros.
-main->>+MR: constructor()
- MR->>+MR: step(0)
- note right of MR: Initialize g
- MR-->>-MR: void
-MR-->>-main: MountainRange
-%% End construct MountainRange
-
-%% Call Solve
-note over main,MR: Begin Solving
-main->>+MR: solve()
- loop While dsteepness() > epsilon()
-
- %% Evaluate steepness
- MR->>+MR: dsteepness()
- loop for cell in interior cells
- MR->>MR: ds_cell(cell)
- end
- MR-->>-MR: total energy
-
- %% Perform step
- MR->>+MR: step()
- %% Modify h cells
- loop for cell in cells
- MR->>MR: update_h_cell(cell)
- end
-
- %% Modify g cells
- loop for cell in interior cells
- MR->>MR: update_g_cell(cell)
- end
-
- %% Update other state variables
- note right of MR: Update other state variables
- MR-->>-MR: void
-
- end
-MR-->>-main: t
-%% End solve
-
-%% Print result
-note over main,MR: Print Result
-main->>cout: t << std::endl
-%% end print
-
-note left of main: Program exits
-deactivate main
-```
diff --git a/docs/MountainRange-sequence-diagram.md b/docs/MountainRange-sequence-diagram.md
new file mode 120000
index 0000000..8657d74
--- /dev/null
+++ b/docs/MountainRange-sequence-diagram.md
@@ -0,0 +1 @@
+MountainRangeBasic-sequence-diagram.md
\ No newline at end of file
diff --git a/docs/MountainRangeBasic-sequence-diagram.md b/docs/MountainRangeBasic-sequence-diagram.md
new file mode 100644
index 0000000..38ae439
--- /dev/null
+++ b/docs/MountainRangeBasic-sequence-diagram.md
@@ -0,0 +1,83 @@
+# Mountain Range Basic — Sequence Diagram
+
+> [!IMPORTANT]
+> This diagram relies on [Mermaid diagrams](https://mermaid.js.org/) which display properly when rendered within GitHub.
+>
+> It may not work properly when rendered within other websites. [Click here to view the source](https://github.com/BYUHPC/sci-comp-course-example-cxx/blob/main/docs/MountainRangeBasic-sequence-diagram.md).
+
+## Intro
+
+This [sequence diagram](https://mermaid.js.org/syntax/sequenceDiagram.html#sequence-diagrams) written with Mermaid visually represents the calls and work being performed in the `MountainRange` example.
+
+It is designed to help visualize the relationships between the various entities involved in running the program.
+
+The code covered by this diagram exists in two separate example files:
+* [MountainRangeBasic.hpp](../src/MountainRangeBasic.hpp) (base class)
+* [initial.cpp](../src/initial.cpp) (driver code)
+
+## Diagram
+
+```mermaid
+---
+title: Mountain Range — Sequence Diagram
+---
+
+sequenceDiagram
+
+participant main
+participant MR as MountainRangeBasic
+participant cout as std::cout
+
+note left of main: Program starts
+activate main
+
+%% Initialize MountainRange
+note over main,MR: Construct MountainRange
+note right of main: Init constants and
fill vectors with zeros.
+main->>+MR: constructor()
+ MR->>+MR: step(0)
+ note right of MR: Initialize g
+ MR-->>-MR: void
+MR-->>-main: MountainRange
+%% End construct MountainRange
+
+%% Call Solve
+note over main,MR: Begin Solving
+main->>+MR: solve()
+ loop While dsteepness() > epsilon()
+
+ %% Evaluate steepness
+ MR->>+MR: dsteepness()
+ loop for cell in interior cells
+ MR->>MR: ds_cell(cell)
+ end
+ MR-->>-MR: total energy
+
+ %% Perform step
+ MR->>+MR: step()
+ %% Modify h cells
+ loop for cell in cells
+ MR->>MR: update_h_cell(cell)
+ end
+
+ %% Modify g cells
+ loop for cell in interior cells
+ MR->>MR: update_g_cell(cell)
+ end
+
+ %% Update other state variables
+ note right of MR: Update other state variables
+ MR-->>-MR: void
+
+ end
+MR-->>-main: t
+%% End solve
+
+%% Print result
+note over main,MR: Print Result
+main->>cout: t << std::endl
+%% end print
+
+note left of main: Program exits
+deactivate main
+```
diff --git a/src/MountainRangeBasic.hpp b/src/MountainRangeBasic.hpp
new file mode 100644
index 0000000..df03c84
--- /dev/null
+++ b/src/MountainRangeBasic.hpp
@@ -0,0 +1,92 @@
+#pragma once
+#include
+#include
+#include
+
+
+// This header containes the Basic MountainRange class. It is a simplification of the MountainRange class.
+
+
+// Basic MountainRange. Derived classes can override write, dsteepness, and step.
+class MountainRangeBasic {
+public:
+ using size_type = size_t;
+ using value_type = double;
+
+
+protected:
+ // Parameters and members
+ static constexpr const value_type default_dt = 0.01;
+ const size_type ndims, cells;
+ value_type t;
+ std::vector r, h, g;
+
+
+public:
+ // Accessors
+ auto size() const { return cells; }
+ auto sim_time() const { return t; }
+ auto &uplift_rate() const { return r; }
+ auto &height() const { return h; }
+
+ // Build a MountainRange from an uplift rate and a current height
+ MountainRangeBasic(const auto &r, const auto &h): ndims{1ul}, cells{r.size()}, t{0.0}, r{r}, h{h} {
+ step(0);
+ }
+
+
+protected:
+ // Helpers for step and dsteepness
+ constexpr void update_g_cell(auto i) {
+ auto L = (h[i-1] + h[i+1]) / 2 - h[i];
+ g[i] = r[i] - pow(h[i], 3) + L;
+ }
+
+ constexpr void update_h_cell(auto i, auto dt) {
+ h[i] += g[i] * dt;
+ }
+
+ constexpr value_type ds_cell(auto i) const {
+ return ((h[i-1] - h[i+1]) * (g[i-1] - g[i+1])) / 2 / (cells - 2);
+ }
+
+
+public:
+ // Calculate the steepness derivative
+ virtual value_type dsteepness() {
+ value_type ds = 0;
+ for (size_t i=1; i std::numeric_limits::epsilon()) {
+ step(default_dt);
+ }
+
+ // Return total simulation time
+ return t;
+ }
+};
diff --git a/src/initial.cpp b/src/initial.cpp
index 7718710..ebc6265 100644
--- a/src/initial.cpp
+++ b/src/initial.cpp
@@ -1,13 +1,10 @@
#include
#include
-#include "MountainRange.hpp"
-
+#include "MountainRangeBasic.hpp"
// Run a basic mountain range simulation and print its simulation time
-
-
int main() {
// Simulation parameters
size_t len = 1000;
@@ -18,7 +15,7 @@ int main() {
std::vector r(len), h(len);
std::fill(r.begin()+plateau_start, r.begin()+plateau_end, value);
h[0] = 1;
- auto m = MountainRange(r, h);
+ auto m = MountainRangeBasic(r, h);
// Solve and return
std::cout << m.solve() << std::endl;