---
title: A remote session called at fixed design points
summary: The calls an optimizer or MDO framework running on another machine would make on a warm session of a deployment — evaluate, gradients, adjoint and tangent products, a finite-difference cross-check, checkpoint and restore — shown at three fixed design points, with no optimizer.
section: examples
order: 11
level: 2
audience: [MDO integrators]
keywords: [remote session, GyreClient, RemoteDiscipline, evaluate, gradients, adjoint, tangent, checkpoint, restore_session, shape gradient, example]
---
<!-- gyre docs: expanded Markdown of examples/remote-session.md (generated tables, verification numbers and chart data are written out). Base level of this page: L2 Practice; passages at another level are bracketed by 'begin level N' / 'end level N' comments and start with [LN Name]. Built from revision ceb1f4b0be. -->

`examples/remote_session.py` shows what an external driver *calls* on a remote Gyre
deployment. **The script contains no optimizer and no loop that updates a design**: it visits
three fixed design points and makes, at each, the calls a driver would make. Gyre, somewhere
on the network, evaluates the flow and returns exact derivatives; what to do with them is
the business of the caller.

```bash
.venv/bin/python examples/remote_session.py http://HOST:8600
```

`HOST` is the machine the deployment runs on (default `http://127.0.0.1:8600`). The client
needs the `gyre` package (for `gyre.client`) and NumPy; no flow is solved on the client.

<!-- begin level 2 (Practice) -->
**[L2 Practice] What the script does**

1. Opens a warm session on the preset `naca0012_euler` with `GyreClient(url).session(...)`
   and prints the inputs (with units) and outputs the session declares (`flow.describe()`).
2. Reads the surface nodes (`flow.surface_coordinates()`) and builds **one** smooth camber
   mode on them: a displacement field of the shape of `x_surface`, zero at the leading and
   trailing edge.
3. Visits the design points `POINTS` — (angle of attack in degrees, mode amplitude in
   chords) = (2.0, 0), (2.5, 0), (2.5, 2·10⁻³) — and at each calls

```python
out = flow.evaluate(alpha_deg=alpha_deg, x_surface=amplitude * mode)
grad = flow.gradients(of=["cl", "cm"], wrt=["alpha_deg", "x_surface"])
```

   It stops with an error if `out["converged"]` is false, and obtains the derivative with
   respect to the amplitude by the chain rule of its own parameterisation: the sum of the
   shape-sensitivity field `grad[...]["x_surface"]` times the mode.
4. At the last point, asks for products instead of whole gradients:
   `flow.adjoint({"cl": 1.0, "cm": -0.5}, wrt=["alpha_deg", "x_surface"])` (one transposed
   solve for a weighted combination of outputs) and
   `flow.tangent({"x_surface": mode}, outputs=["cl", "cm"])` (one forward solve along the
   mode), and prints both next to the values assembled from the gradients of step 3.
5. Cross-checks `dcl/dalpha_deg` against a central difference of two re-converged
   evaluations at `alpha_deg ± 0.01`.
6. Takes a checkpoint (`flow.checkpoint()`, bytes), lets the session close, rebuilds it with
   `GyreClient.restore_session(blob)`, asks it for its status (`flow.state()`) and
   re-evaluates: the restored session has the inputs and the converged state of the
   original.

The forward product and the checkpoint are skipped, with a printed remark, on a deployment
that answers 404 or 405 for those routes (one installed before they existed).

<!-- end level 2 -->

<!-- begin level 2 (Practice) -->
**[L2 Practice] What to notice**

* **The cost of a gradient does not grow with the number of shape variables.** The derivative
  with respect to every surface node comes back as one field per output; projecting it on
  one mode or two hundred costs the client a sum.
* **Units.** The session takes and differentiates with respect to `alpha_deg` (degrees); the
  in-process discipline would use `alpha` in radians
  ([outputs and units](../theory/outputs-and-functionals.md)).
* **Warm starts.** Each evaluation starts from the previous converged flow.
* **Failures are data.** If an evaluation does not converge, `evaluate` returns
  `converged: false` with a `reason`; the script raises at that point rather than
  differentiating a state that is not a solution
  ([MDO integration](../guide/mdo-integration.md), [Troubleshooting](../guide/troubleshooting.md)).
* The mode, the design points and the chain rule are client code. Nothing in the service
  knows what the caller does with the numbers.

<!-- end level 2 -->

> **Note: No recorded output on this page**
>
> The pages of this section normally show numbers rendered from a verification study. This
> script has no such study and no output of it is quoted here. The script itself is executed,
> on a small case and against an in-process service, by
> `tests/test_sessions.py::test_remote_example_calls_the_discipline_and_contains_no_optimizer`,
> which checks that the adjoint and tangent products agree with the gradients, the gradient
> with the finite difference, and the restored session with the original.
