> ## Documentation Index
> Fetch the complete documentation index at: https://calcs.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Example: Using solveSecant()

> Walkthrough of solveSecant() to find the unknown where demand equals capacity

This page walks through a real-world use of [`solveSecant()`](/docs/calcs_builder/equation_functions#solvers) to find the rail span where **demand equals capacity**. For syntax and general usage, see [Equation Functions](/docs/calcs_builder/equation_functions).

Calcs Builder equations are powered by [Math.js](https://mathjs.org/docs/index.html); `solveSecant()` is a custom solver built on top of it.

## Big Picture

1. We know that for a given rail span (the distance between rail supports), a panel will experience some demand (like wind load or snow load) that depends on that span.
2. We also know that the rail has a certain capacity to withstand that load, which depends on the rail span (longer spans mean lower capacity) and on the angle of the force acting on it.
3. The formula sets up: ***f(rail\_span) = Demand(rail\_span) - Capacity(rail\_span)***
4. We want to solve ***f(rail\_span) = 0***, where Demand equals Capacity.
5. To do that, we're using a numerical solver named `solveSecant()`. This function tries different values for ***rail\_span*** (starting between 30 cm and 300 cm) and zeroes in on the value that makes ***f(rail\_span) = 0***.

***

## High-Level Code Flow

<CodeBlock title="solveSecant Structure">
  ```javascript theme={null}
  solveSecant(
      30 cm,              // x0:  first guess for rail span
      300 cm,             // x1:  second guess for rail span
      0.00001 cm,         // tolerance: how close we need to get to 0
      100,                // max number of iterations
      f(rail_span) = ...  // the function we want to solve = 0
  )
  ```
</CodeBlock>

### 1. Secant Method Setup

<Note>
  **Initial Parameters:**

  * **`30 cm, 300 cm`**: These are our initial "guesses" or bracket for the solution. We know the actual required rail span is somewhere between 30 cm and 300 cm.
  * **`0.00001 cm`**: The solver will stop iterating if it finds a solution whose error is smaller than 10^{-5} cm.
  * **`100`**: This is the maximum number of iterations to try before giving up (i.e., if no solution is found within 100 tries, it'll fail).
</Note>

### 2. The Function ***f(rail\_span)***

Inside `solveSecant()`, we define:

<CodeBlock title="Complete Function Definition">
  ```javascript theme={null}
  f(rail_span) = 
     (matrixSubset(ultimateLCs_Resultant_Cpemin, rowIndex() + 1, 2) 
      * (panel_ornt == "Landscape Vert. Rails" ? pnlX : pnlY )
      * rail_span) / 2
     -
     interpolate(
         [
           1.298 * exp(-0.00828 * number(rail_span, "cm")) - 0.00702,
           1.296 * exp(-0.00820 * number(rail_span, "cm")) - 0.00719,
           1.244 * exp(-0.00669 * number(rail_span, "cm")) - 0.01198,
           1.242 * exp(-0.00662 * number(rail_span, "cm")) - 0.01232
         ],
         matrixSubset(angle_resultF_Cpemin, rowIndex() + 1, 2),
         [0 deg, 30 deg, 60 deg, 90 deg]
     )
     *
     interpolate([5700 N, 5350 N, 3250 N, 2900 N],
                 matrixSubset(angle_resultF_Cpemin, rowIndex() + 1, 2),
                 [0 deg, 30 deg, 60 deg, 90 deg])
  ```
</CodeBlock>

This breaks down into two major parts:

## A) Demand Part

<CodeBlock title="Demand Calculation">
  ```javascript theme={null}
  ( matrixSubset(ultimateLCs_Resultant_Cpemin, rowIndex() + 1, 2 )
    * (panel_ornt == "Landscape Vert. Rails" ? pnlX : pnlY )
    * rail_span ) / 2
  ```
</CodeBlock>

<Accordion title="Demand Components Breakdown">
  * **`matrixSubset(ultimateLCs_Resultant_Cpemin, rowIndex() + 1, 2)`**
    * This takes the loads of Ultimate Limit State - Resultant Loads
  * **`(panel_ornt == "Landscape Vert. Rails" ? pnlX : pnlY )`**
    * If the panel orientation is "Landscape Vert. Rails," we use `pnlX`; otherwise, we use `pnlY`. Essentially, this picks the relevant dimension of the panel based on orientation.
  * **`rail_span`**
    * The rail span (the variable we're trying to solve for).
  * **Divide by 2**
    * Because the demand is distributed in two rails.

  **Putting it together:**
  ***Demand = (load factor) \* (panel dimension) \* rail\_span / 2***
</Accordion>

## B) Capacity Part

Next, we subtract the "capacity part" from that Demand. The capacity expression is:

<CodeBlock title="Capacity Calculation">
  ```javascript theme={null}
  interpolate(
      [
        1.298 * exp(-0.00828 * number(rail_span, "cm")) - 0.00702,
        1.296 * exp(-0.00820 * number(rail_span, "cm")) - 0.00719,
        1.244 * exp(-0.00669 * number(rail_span, "cm")) - 0.01198,
        1.242 * exp(-0.00662 * number(rail_span, "cm")) - 0.01232
      ],
      matrixSubset(angle_resultF_Cpemin, rowIndex() + 1, 2),
      [0 deg, 30 deg, 60 deg, 90 deg]
  )
  *
  interpolate(
      [5700 N, 5350 N, 3250 N, 2900 N],
      matrixSubset(angle_resultF_Cpemin, rowIndex() + 1, 2),
      [0 deg, 30 deg, 60 deg, 90 deg]
  )
  ```
</CodeBlock>

This calculates the capacity by combining two interpolated factors: one for the span and one for the angle of force.

***

### Breaking Down the Capacity Part

#### 1. Angle-Based Interpolation

Notice that the capacity calculation involves two interpolations, each using four data points for angles **0°, 30°, 60°, and 90°**.

#### 2. First Interpolation

<CodeBlock title="Exponential Factor Interpolation">
  ```javascript theme={null}
  interpolate(
      [ 
        1.298 * exp(-0.00828 * number(rail_span, "cm")) - 0.00702,
        1.296 * exp(-0.00820 * number(rail_span, "cm")) - 0.00719,
        1.244 * exp(-0.00669 * number(rail_span, "cm")) - 0.01198,
        1.242 * exp(-0.00662 * number(rail_span, "cm")) - 0.01232
      ],
      angle_value,  // from matrixSubset(angle_resultF_Cpemin)
      [0 deg, 30 deg, 60 deg, 90 deg]
  )
  ```
</CodeBlock>

<Note>
  * Each element in the array represents an exponential formula for the ***rail\_span***:
    * ***A \* exp(B \* rail\_span) - C***
    * where the constants **A**, **B**, and **C** are slightly different for each angle (0°, 30°, 60°, 90°).
  * The `angle_value` comes from ***matrixSubset(angle\_resultF\_Cpemin)***. This value represents the force angle (in degrees) that we're considering.
  * The `interpolate()` function selects a capacity factor based on the actual angle by interpolating between the data points.
</Note>

#### 3. Second Interpolation

<CodeBlock title="Base Capacity Interpolation">
  ```javascript theme={null}
  interpolate(
      [5700 N, 5350 N, 3250 N, 2900 N],
      angle_value,
      [0 deg, 30 deg, 60 deg, 90 deg]
  )
  ```
</CodeBlock>

<Note>
  * This provides a **base capacity** (in Newtons) corresponding to the angles (0°, 30°, 60°, 90°).
  * Again, the actual angle is used to interpolate the specific base capacity.
</Note>

#### 4. Multiplying the Two Interpolations

<CodeBlock title="Final Capacity Formula">
  ```javascript theme={null}
  capacity = (exponential_factor_for_span_and_angle) * (base_capacity_for_angle)
  ```
</CodeBlock>

The final capacity is:
***capacity(rail\_span, angle) = (A \* exp(B \* rail\_span) - C) \* (base capacity for angle)***

<Note>
  * The exponential factor decreases as ***rail\_span*** increases.
  * The base capacity is adjusted according to the force angle.
</Note>

***

## Final Formula: Demand - Capacity

Putting the two parts together:

<CodeBlock title="Complete Equilibrium Equation">
  ```
  f(rail_span) = Demand(rail_span) - Capacity(rail_span, angle)
  ```
</CodeBlock>

Where:

* ***Demand(rail\_span) = (load factor) \* (panel dimension) \* rail\_span / 2***
* ***Capacity(rail\_span, angle) = (interpolated exponential factor) \* (interpolated base capacity)***

<Tip>
  The `solveSecant()` function iteratively adjusts the `rail_span` value until the difference between demand and capacity approaches zero, finding the optimal rail spacing that balances structural requirements with material efficiency.
</Tip>
