diff --git a/docs/source/_static/img/int_mu_f1_dx.png b/docs/source/_static/img/int_mu_f1_dx.png index 578d55e73..f4c86ab0c 100644 Binary files a/docs/source/_static/img/int_mu_f1_dx.png and b/docs/source/_static/img/int_mu_f1_dx.png differ diff --git a/docs/source/_static/img/int_mu_f1a_dx.png b/docs/source/_static/img/int_mu_f1a_dx.png index 590e85037..05b432bbf 100644 Binary files a/docs/source/_static/img/int_mu_f1a_dx.png and b/docs/source/_static/img/int_mu_f1a_dx.png differ diff --git a/docs/source/_static/img/mu.png b/docs/source/_static/img/mu.png index c33121da4..50ca60fd4 100644 Binary files a/docs/source/_static/img/mu.png and b/docs/source/_static/img/mu.png differ diff --git a/docs/source/_static/img/mu_f1.png b/docs/source/_static/img/mu_f1.png index cbc7a0499..169b98e3f 100644 Binary files a/docs/source/_static/img/mu_f1.png and b/docs/source/_static/img/mu_f1.png differ diff --git a/docs/source/_static/img/mu_f1a.png b/docs/source/_static/img/mu_f1a.png index 9de462a42..50a01c1e3 100644 Binary files a/docs/source/_static/img/mu_f1a.png and b/docs/source/_static/img/mu_f1a.png differ diff --git a/docs/source/tutorials/adhesion.rst b/docs/source/tutorials/adhesion.rst index 5772cf4da..29e4901bf 100644 --- a/docs/source/tutorials/adhesion.rst +++ b/docs/source/tutorials/adhesion.rst @@ -201,4 +201,4 @@ We integrate their product to obtain a smooth tangential adhesion mollifier: .. figure:: /_static/img/int_mu_f1a_dx.png :align: center - Integrated mollifier :math:`\int \mu(y) f_1^a(y) \mathrm{d} y` where :math:`\mu_s = 1`, :math:`\mu_k = 0.1`, and :math:`\epsilon_v = 0.001`. \ No newline at end of file + Integrated mollifier :math:`\int \mu(y) f_1^a(y) \mathrm{d} y` where :math:`y=\|\mathbf{u}\|`, :math:`\mu_s = 1`, :math:`\mu_k = 0.1`, and :math:`\epsilon_v = 0.001`. \ No newline at end of file diff --git a/docs/source/tutorials/advanced_friction.rst b/docs/source/tutorials/advanced_friction.rst index 554be8dfc..01c1a9968 100644 --- a/docs/source/tutorials/advanced_friction.rst +++ b/docs/source/tutorials/advanced_friction.rst @@ -108,8 +108,10 @@ Smooth :math:`\mu` When adding separate coefficients for static and kinetic friction, we need to maintain the :math:`C^1` continuity of the friction force. This lead us to define a smooth coefficient of friction :math:`\mu(y)` that transitions between the static and kinetic coefficients based on the magnitude of the relative velocity :math:`y = \|\mathbf{u}\|`. The smooth coefficient of friction is defined as .. math:: - \mu(y) = \begin{cases} \mu_{s} + \left(\mu_{k} - \mu_{s}\right) \left(\frac{3 y^{2}}{\epsilon_{v}^{2}} - \frac{2 y^{3}}{\epsilon_{v}^{3}}\right) & \text{for}\: 0 \leq y \leq \epsilon_{v}\\ - \mu_{k} & \text{otherwise}. + \mu(y) = \begin{cases} + 2(\mu_{k} - \mu_{s})\frac{y^{2}}{\epsilon_{v}^{2}} + \mu_{s} & \text{for}\: y \leq \frac{\epsilon_{v}}{2} \\ + -2(\mu_{k} - \mu_{s})\frac{\left(\epsilon_{v} - y\right)^{2}}{\epsilon_{v}^{2}} + \mu_k & \text{for}\: y \leq \epsilon_{v} \\ + \mu_{k} & \text{for}\: y > \epsilon_{v} \end{cases} We plot the smooth coefficient of friction :math:`\mu(y)` below: @@ -132,13 +134,9 @@ Replacing the constant coefficient of friction :math:`\mu` with a smooth functio However, :math:`\frac{\mathrm{d}}{\mathrm{d}y} \mu(y) f_0(y) \neq \mu(y) f_1(y)`, so we need to adjust the integrated mollifier by integrating the product of the smooth coefficient of friction and the mollifier: .. math:: - \int \mu(y) f_1(y) \mathrm{d} y = \begin{cases} - \frac{\epsilon_{v}^{6} \left(17 \mu_{k} - 7 \mu_{s}\right) + 30 \epsilon_{v}^{4} \mu_{s} y^{2} - 10 \epsilon_{v}^{3} \mu_{s} y^{3} + 45 \epsilon_{v}^{2} \left(\mu_{k} - \mu_{s}\right) y^{4} + 42 \epsilon_{v} \left(- \mu_{k} + \mu_{s}\right) y^{5} + 10 \left(\mu_{k} - \mu_{s}\right) y^{6}}{30 \epsilon_{v}^{5}} & \text{for}\: \epsilon_{v} > y \\ - \mu_{k} y & \text{otherwise} - \end{cases}. - - - + \int \mu(y) f_1(y) \mathrm{d} y = \begin{cases} \frac{\frac{\epsilon_{v}^{5} \left(27 \mu_{k} - 11 \mu_{s}\right)}{48} + \epsilon_{v}^{3} \mu_{s} y^{2} - \frac{\epsilon_{v}^{2} \mu_{s} y^{3}}{3} + \epsilon_{v} y^{4} \left(\mu_{k} - \mu_{s}\right) + \frac{2 y^{5} \left(- \mu_{k} + \mu_{s}\right)}{5}}{\epsilon_{v}^{4}} & \text{for}\: y \leq \frac{\epsilon_{v}}{2} \\ + \frac{\epsilon_{v}^{5} \left(9 \mu_{k} - 4 \mu_{s}\right) + 15 \epsilon_{v}^{3} y^{2} \left(- \mu_{k} + 2 \mu_{s}\right) + 5 \epsilon_{v}^{2} y^{3} \left(9 \mu_{k} - 10 \mu_{s}\right) - 30 \epsilon_{v} y^{4} \left(\mu_{k} - \mu_{s}\right) + 6 y^{5} \left(\mu_{k} - \mu_{s}\right)}{15 \epsilon_{v}^{4}} & \text{for}\: y \leq \epsilon_{v} \\ + \mu_{k} y & \text{for}\: y > \epsilon_v \end{cases} The following plot shows the behavior of the integrated mollifier multiplied by the smooth coefficient of friction: @@ -155,11 +153,10 @@ While this approach provides a smooth transition between static and kinetic fric 1. The product :math:`\mu(y) f_1(y)` underestimates the friction force in the static regime, which may lead to less accurate simulations of static friction. - This is, when :math:`\mu_k < \mu_s` and :math:`|y| \leq \epsilon_v`, :math:`\max(\mu(y) f_1(y)) < \mu_s`. - We could address this by scaling by :math:`\frac{\max(\mu(y) f_1(y))}{\mu_s}`, but computing the maximum is non-trivial. -2. The combined function :math:`\mu(y) f_1(y)` is a degree 5 polynomial, which is more complex than the original mollifier :math:`f_1(y)` (degree 2). This may lead to more difficult to optimize problems. There are two options to address this: - a. Replacing :math:`\mu(y)` with a piecewise quadratic function would reduce the degree to 4, but it would still be more complex than the original mollifier. - b. Replacing :math:`\mu(y) f_1(y)` with a piecewise quadratic function that has the desired behavior. This help with 1. as well. However making it backwards compatible with the original mollifier is challenging. +2. The combined function :math:`\mu(y) f_1(y)` is a degree 4 polynomial, which is more complex than the original mollifier :math:`f_1(y)` (degree 2). This may lead to more difficult to optimize problems. + - We could replace :math:`\mu(y) f_1(y)` with a piecewise quadratic function that has the desired behavior. This help with (1) as well. However making it backwards compatible with the original mollifier is challenging. -If you have suggestions for improving this approach or alternative methods, please reach out on our `GitHub Discussions `. +If you have suggestions for improving this approach or alternative methods, please reach out on our `GitHub Discussions `_. Future Directions ----------------- diff --git a/notebooks/separate_mu.ipynb b/notebooks/separate_mu.ipynb index 20b79b68c..d4be9c39d 100644 --- a/notebooks/separate_mu.ipynb +++ b/notebooks/separate_mu.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 562, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 563, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -3941,31 +3941,32 @@ }, { "cell_type": "code", - "execution_count": 564, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "x = Symbol('x')\n", - "eps_v = Symbol(r'\\epsilon_v')\n", - "mu_s, mu_k = symbols(r'\\mu_s \\mu_k')" + "x = Symbol('x', real=True)\n", + "eps_v = Symbol(r'\\epsilon_v', real=True, positive=True)\n", + "mu_s, mu_k = symbols(r'\\mu_s \\mu_k', real=True, positive=True)" ] }, { "cell_type": "code", - "execution_count": 565, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import re\n", "\n", "\n", - "def plot(*fs, title=None, min_x=-2, max_x=2, **subs):\n", + "def plot(*fs, title=None, min_x=-2, max_x=2, even=False, odd=False, **subs):\n", " subs = {eps_v: subs.get(\n", " \"eps_v\", 1e-3), mu_s: subs.get(\"mu_s\", 1), mu_k: subs.get(\"mu_k\", 0.1)}\n", " xs = np.linspace(min_x*subs[eps_v], max_x*subs[eps_v], 201)\n", + " s = np.sign(xs) if odd else np.ones_like(xs)\n", "\n", " def ys(f):\n", - " return np.array([f.subs({x: xi} | subs) for xi in xs], dtype=float)\n", + " return s * np.array([f.subs({x: abs(xi) if (even or odd) else xi} | subs) for xi in xs], dtype=float)\n", "\n", " fig = go.Figure(\n", " [go.Scatter(x=xs, y=ys(f)) for f in fs],\n", @@ -3975,9 +3976,17 @@ " ))\n", " file_name = re.sub(\n", " r'[\\$\\_\\{\\}\\^\\\\]|\\(x\\)', '', title).replace(\"mathrm\", \"\").replace(' ', '_').strip()\n", - " fig.write_image(\n", - " f\"../docs/source/_static/img/{file_name}.png\")\n", - " fig.show()" + " # fig.write_image(f\"../docs/source/_static/img/{file_name}.png\")\n", + " fig.show()\n", + "\n", + "\n", + "def print_latex(expr):\n", + " print(latex(expr).replace(r\"\\\\\", r\"\\\\\" + \"\\n\"))\n", + "\n", + "\n", + "def print_code(expr):\n", + " print(cxxcode(expr).replace(r\"\\epsilon\", \"eps\").replace(\n", + " r\"\\mu\", \"mu\").replace(\"x\", \"y\"))" ] }, { @@ -3989,16 +3998,16 @@ }, { "cell_type": "code", - "execution_count": 566, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/latex": [ - "$\\displaystyle f_{0}(x) = \\begin{cases} \\left|{x}\\right| & \\text{for}\\: \\epsilon_{v} \\leq \\left|{x}\\right| \\\\\\frac{\\epsilon_{v}}{3} + \\frac{\\left|{x}\\right|^{2}}{\\epsilon_{v}} - \\frac{\\left|{x}\\right|^{3}}{3 \\epsilon_{v}^{2}} & \\text{otherwise} \\end{cases}$" + "$\\displaystyle f_{0}(x) = \\begin{cases} x & \\text{for}\\: \\epsilon_{v} \\leq x \\\\\\frac{\\epsilon_{v}}{3} + \\frac{x^{2}}{\\epsilon_{v}} - \\frac{x^{3}}{3 \\epsilon_{v}^{2}} & \\text{otherwise} \\end{cases}$" ], "text/plain": [ - "Eq(f_{0}(x), Piecewise((Abs(x), \\epsilon_v <= Abs(x)), (\\epsilon_v/3 + Abs(x)**2/\\epsilon_v - Abs(x)**3/(3*\\epsilon_v**2), True)))" + "Eq(f_{0}(x), Piecewise((x, \\epsilon_v <= x), (\\epsilon_v/3 + x**2/\\epsilon_v - x**3/(3*\\epsilon_v**2), True)))" ] }, "metadata": {}, @@ -4008,7 +4017,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "\\begin{cases} \\left|{x}\\right| & \\text{for}\\: \\epsilon_{v} \\leq \\left|{x}\\right| \\\\\\frac{\\epsilon_{v}}{3} + \\frac{\\left|{x}\\right|^{2}}{\\epsilon_{v}} - \\frac{\\left|{x}\\right|^{3}}{3 \\epsilon_{v}^{2}} & \\text{otherwise} \\end{cases}\n" + "\\begin{cases} x & \\text{for}\\: \\epsilon_{v} \\leq x \\\\\n", + "\\frac{\\epsilon_{v}}{3} + \\frac{x^{2}}{\\epsilon_{v}} - \\frac{x^{3}}{3 \\epsilon_{v}^{2}} & \\text{otherwise} \\end{cases}\n" ] }, { @@ -4829,9 +4839,892 @@ } }, "text/html": [ - "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def f0(x):\n", + " \"\"\"Smooth friction mollifier\"\"\"\n", + " return x * x * (1 - x / (3 * eps_v)) / eps_v + eps_v / 3\n", + "\n", + "\n", + "sym_f0 = Piecewise(\n", + " (x, x >= eps_v),\n", + " (f0(x), x < eps_v)\n", + ")\n", + "\n", + "display(Eq(Symbol(\"f_{0}(x)\"), sym_f0.expand()))\n", + "print_latex(sym_f0.expand())\n", + "\n", + "plot(sym_f0, title=r'$f_0(x)$', even=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle f_{1}(x) = \\begin{cases} \\frac{2 x}{\\epsilon_{v}} - \\frac{x^{2}}{\\epsilon_{v}^{2}} & \\text{for}\\: \\epsilon_{v} \\geq x \\\\1 & \\text{otherwise} \\end{cases}$" + ], + "text/plain": [ + "Eq(f_{1}(x), Piecewise((2*x/\\epsilon_v - x**2/\\epsilon_v**2, \\epsilon_v >= x), (1, True)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "type": "scatter", + "x": { + "bdata": "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", + "dtype": "f8" + }, + "y": { + "bdata": "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", + "dtype": "f8" + } + } + ], + "layout": { + "height": 600, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#f2f5fa" + }, + "error_y": { + "color": "#f2f5fa" + }, + "marker": { + "line": { + "color": "rgb(17,17,17)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(17,17,17)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#A2B1C6", + "gridcolor": "#506784", + "linecolor": "#506784", + "minorgridcolor": "#506784", + "startlinecolor": "#A2B1C6" + }, + "baxis": { + "endlinecolor": "#A2B1C6", + "gridcolor": "#506784", + "linecolor": "#506784", + "minorgridcolor": "#506784", + "startlinecolor": "#A2B1C6" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "line": { + "color": "#283442" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "line": { + "color": "#283442" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#506784" + }, + "line": { + "color": "rgb(17,17,17)" + } + }, + "header": { + "fill": { + "color": "#2a3f5f" + }, + "line": { + "color": "rgb(17,17,17)" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#f2f5fa", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#f2f5fa" + }, + "geo": { + "bgcolor": "rgb(17,17,17)", + "lakecolor": "rgb(17,17,17)", + "landcolor": "rgb(17,17,17)", + "showlakes": true, + "showland": true, + "subunitcolor": "#506784" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "dark" + }, + "paper_bgcolor": "rgb(17,17,17)", + "plot_bgcolor": "rgb(17,17,17)", + "polar": { + "angularaxis": { + "gridcolor": "#506784", + "linecolor": "#506784", + "ticks": "" + }, + "bgcolor": "rgb(17,17,17)", + "radialaxis": { + "gridcolor": "#506784", + "linecolor": "#506784", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(17,17,17)", + "gridcolor": "#506784", + "gridwidth": 2, + "linecolor": "#506784", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#C8D4E3" + }, + "yaxis": { + "backgroundcolor": "rgb(17,17,17)", + "gridcolor": "#506784", + "gridwidth": 2, + "linecolor": "#506784", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#C8D4E3" + }, + "zaxis": { + "backgroundcolor": "rgb(17,17,17)", + "gridcolor": "#506784", + "gridwidth": 2, + "linecolor": "#506784", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#C8D4E3" + } + }, + "shapedefaults": { + "line": { + "color": "#f2f5fa" + } + }, + "sliderdefaults": { + "bgcolor": "#C8D4E3", + "bordercolor": "rgb(17,17,17)", + "borderwidth": 1, + "tickwidth": 0 + }, + "ternary": { + "aaxis": { + "gridcolor": "#506784", + "linecolor": "#506784", + "ticks": "" + }, + "baxis": { + "gridcolor": "#506784", + "linecolor": "#506784", + "ticks": "" + }, + "bgcolor": "rgb(17,17,17)", + "caxis": { + "gridcolor": "#506784", + "linecolor": "#506784", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "updatemenudefaults": { + "bgcolor": "#506784", + "borderwidth": 0 + }, + "xaxis": { + "automargin": true, + "gridcolor": "#283442", + "linecolor": "#506784", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#283442", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "#283442", + "linecolor": "#506784", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#283442", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "$f_1(x)$" + }, + "width": 800, + "xaxis": { + "title": { + "text": "speed" + } + } + } + }, + "text/html": [ + "