I'm a bit late to the party, but wanted to study this answer of Symbol 1 in depth and give it a try here. The result is a little generalization of his code, plus a few things added for the drawing of the Earth's crust. What I mean by generalization: with my code, you have all the parameters you need to apply the transformation to an arbitrary rectangle, and you can change the mesh size in either direction without needing to adapt anything: just change the value of nbXcells
or nbYcells
and recompile).
For the deformation curve, I computed smooth joints between line segments with functions based on tanh. In order to obtain a nice result from the Symbol 1 method, one needs to use a lot of triangles (on each triangle, the transformation is approximated by an affine transformation defined for PGF with \pgfsettransformentries
). The screenshot below has been produced with nbXcells = 150; nbYcells = 50;
, as in the code below. Such a dense mesh unfortunately requires:
about 22 minutes of compilation time with pdflatex
on a computer from 2009;
very large memory parameters in effect when building the pdflatex
format (for the mesh size used here, the following is sufficient: main_memory = 8000000
, extra_mem_top = 70000000
and extra_mem_bot = 70000000
);
a few minutes of rendering time in Okular, my PDF viewer (conversion to PNG format using ImageMagick is much quicker: 15 seconds for 700 dpi output).
But the journey was interesting and the end result is not bad. :-) So, if you want to try the code below, I suggest to first start with a very gross mesh, for instance nbXcells = 20; nbYcells = 5;
(this compiles in 30 seconds here). For this, you shouldn't need to increase the TeX memory parameters.
There are parameters for almost everything, so it's very easy to adjust things without disturbing the rest (every aspect of the transformation function, the size of the grey “ribbon,” rule widths, etc.). I use the PGF fpu
library for most computations, otherwise one easily gets the dreaded “Dimension too large” error that spoils all the fun (the “ribbon” I was initially playing with was 78 cm long...).
I use pgfplots
to draw in invisible ink the deformation curve. In fact, this serves to make the “compression” and “extension” annotations very accurately follow the border of the Earth's crust. These are placed using the text along path
path decoration via \addplot
's postaction
key.
The first version of this answer didn't preserve orthogonality of the grid lines—a defect present in all answers posted so far, except the one that produces a parabola (update: Symbol 1's answer was added later and doesn't have this defect). Making the “vertical” lines of the grid follow the deformation curve required some careful tuning of the transformation function determined by fx
and fy
in my code. The numbers 0.67, 0.27 and 5 in corrective factors such as 0.67*exp(-5*(\x-\aplusdeltai)^2)
and 0.27*exp(-5*(\x-\aplusdeltai)^2)
have been determined by trial and error. If the primary parameters of the deformation curve (a
, b
, c
, d
, yMin
, omega
, deltai
and deltaii
) are modified, the three non-primary ones used in corrective factors (here, 0.67, 0.27 and 5) will likely need to be adapted accordingly.
\documentclass[tikz, border=1mm]{standalone}
\usepackage{lmodern}
\usepackage{expl3}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{calc, decorations.text, fpu}
\ExplSyntaxOn
\cs_new_eq:NN \clistMapInline \clist_map_inline:nn
\ExplSyntaxOff
\newcommand*{\toFixedFormat}[2]{%
\pgfmathparse{#2}%
\pgfmathfloattofixed{\pgfmathresult}%
\let#1\pgfmathresult
}
% Faster than \toFixedFormat, but #2 must be a macro storing a result in the
% 'float' output format (of the PGF 'fpu' library).
\newcommand*{\convertToFixedFormat}[2]{%
\pgfmathfloattofixed{#2}%
\let#1\pgfmathresult
}
\newcommand*{\computeParam}[1]{%
\expandafter\pgfmathsetmacro\expandafter{\csname my#1\endcsname}{#1}%
}
\tikzset{
declare function={
Xstart = 0; Ystart = 0; % south west corner of source rectangle
Xstop = 15; Ystop = 0.6; % north east corner of source rectangle
% Tight mesh for nice output. This requires a lot of computations and
% you'll most probably need to increase some TeX memory size parameters
% (I have succesfully compiled this with a pdflatex format built with
% main_memory = 8000000, extra_mem_top = 70000000 and
% extra_mem_bot = 70000000).
nbXcells = 150; nbYcells = 50;
% nbXcells = 3; nbYcells = 2; % That's enough for debugging!
meshXstep = (Xstop-Xstart) / nbXcells;
meshYstep = (Ystop-Ystart) / nbYcells;
% Prerequesites for the transformation we want to apply.
% Increase omega for a sharper transition. deltai(i) is (for each of the
% two pieces) half the width of the interval where we use a tanh-like func.
omega = 2; deltai = 1.4; deltaii = deltai;
% Possible parameters. 'yMin' tells how much the deformation “pushes
% downwards.”
a = 1.8; b = a + 2*deltai; d = Xstop - a; c = d - 2*deltaii; yMin = -0.95;
A = -yMin/(2*tanh(omega*deltai));
B = -yMin/(tanh(omega*(d-c-deltaii)) + tanh(omega*deltaii));
mu = -B*tanh(omega*(d-c-deltaii));
% The transformation we want to apply (see below for the constants).
fx(\x,\y) = \x +
ifthenelse(\x < \mya, 0,
ifthenelse(\x < \myb,
0.67*exp(-5*(\x-\aplusdeltai)^2)* % transition with the straight part
(\y-\yMid)/(\Aomega*(1-(tanh(\myomega*(\aplusdeltai-\x)))^2)),
ifthenelse(\x < \myc, 0,
ifthenelse(\x < \myd,
.67*exp(-5*(\x-\cplusdeltaii)^2)* % transition
(\yMid-\y)/(\Bomega*(1-(tanh(\myomega*(\x-\cplusdeltaii)))^2)),
0
))));
fy(\x,\y) = \y +
ifthenelse(\x < \mya, 0,
ifthenelse(\x < \myb,
\myA*(tanh(\myomega*(\aplusdeltai-\x)) - \tanhomegadeltai)
% Compensate for the “transition deltax” we added in fx()
- 0.27*exp(-5*(\x-\aplusdeltai)^2)*(\y-\yMid),
ifthenelse(\x < \myc, \myyMin,
ifthenelse(\x < \myd,
\myB*tanh(\myomega*(\x-\cplusdeltaii)) + \mymu
% Compensate here too
- 0.27*exp(-5*(\x-\cplusdeltaii)^2)*(\y-\yMid),
0 % intentional: back at the same level
))));
}
}
% Precompute all constants. This gives a huge speed-up.
\pgfset{fpu=true}
\clistMapInline{yMin, a, b, c, d, A, B, deltai, deltaii, omega, mu}
{\computeParam{#1}} % Define \myyMin, \mya, \myb, etc.
\toFixedFormat{\meshXstep}{meshXstep}
\toFixedFormat{\meshYstep}{meshYstep}
\pgfmathsetmacro{\yMid}{0.5*(Ystart+Ystop)}
\pgfmathsetmacro{\aplusdeltai}{\mya+\mydeltai}
\pgfmathsetmacro{\cplusdeltaii}{\myc+\mydeltaii}
\pgfmathsetmacro{\Aomega}{\myA*\myomega}
\pgfmathsetmacro{\Bomega}{\myB*\myomega}
\pgfmathsetmacro{\tanhomegadeltai}{tanh(\myomega*\mydeltai)}
\pgfmathsetmacro{\Bomega}{\myB*\myomega}
\pgfset{fpu=false}
% Inspired by code from Symbol 1 <https://tex.stackexchange.com/a/332173/194703>
\pgfmathdeclarefunction{fxx}{2}{%
\pgfmathparse{1/\meshXstep*(fx(#1+\meshXstep, #2) - fx(#1,#2))}}
\pgfmathdeclarefunction{fxy}{2}{%
\pgfmathparse{1/\meshXstep*(fy(#1+\meshXstep, #2) - fy(#1,#2))}}
\pgfmathdeclarefunction{fyx}{2}{%
\pgfmathparse{1/\meshYstep*(fx(#1, #2+\meshYstep) - fx(#1,#2))}}
\pgfmathdeclarefunction{fyy}{2}{%
\pgfmathparse{1/\meshYstep*(fy(#1, #2+\meshYstep) - fy(#1,#2))}}
\newlength{\myWidth}
\newlength{\myHeight}
\pgfmathsetlengthmacro{\myBorderRuleWidth}{0.6pt}
% Assume the default unit vectors. Half of the border rule with is outside the
% border when a node is drawn; take this into account.
\pgfmathsetlength{\myWidth}{(Xstop - Xstart)*1cm - \myBorderRuleWidth}
\pgfmathsetlength{\myHeight}{(Ystop - Ystart)*1cm - \myBorderRuleWidth}
\begin{document}
\begin{tikzpicture}[
my background/.initial=gray!55, % this color is used in three places
my pic/.pic = {
\node at (0,0)
[rectangle, draw=black,
fill/.expanded={\pgfkeysvalueof{/tikz/my background}},
line width=\myBorderRuleWidth,
inner sep=0, anchor=south west, minimum width=\myWidth,
minimum height=\myHeight,
path picture={
\draw[line width=0.1pt, gray!80]
(path picture bounding box.south west) grid[step=0.2]
(path picture bounding box.north east);}]
{};
}]
% Set the bounding box (leave room for 'text along path' annotations)
\path (Xstart, Ystart+yMin) ([yshift=0.2cm]Xstop, Ystop);
\pgfmathtruncatemacro\iMax{nbXcells-1}
\pgfmathtruncatemacro\jMax{nbYcells-1}
\foreach \i in {0,...,\iMax} {
\foreach \j in {0,...,\jMax} {
\typeout{Processing cell (\i,\j); the last one will be (\iMax,\jMax).}
\pgfset{fpu=true}
\pgfmathsetmacro\Xi{Xstart + \i*\meshXstep}
\pgfmathsetmacro\Yi{Ystart + \j*\meshYstep}
\convertToFixedFormat{\XiF}{\Xi}
\convertToFixedFormat{\YiF}{\Yi}
\toFixedFormat{\aa}{fxx(\Xi, \Yi)}
\toFixedFormat{\ab}{fxy(\Xi, \Yi)}
\toFixedFormat{\ba}{fyx(\Xi, \Yi)}
\toFixedFormat{\bb}{fyy(\Xi, \Yi)}
\toFixedFormat{\xx}{fx (\Xi, \Yi)}
\toFixedFormat{\yy}{fy (\Xi, \Yi)}
\pgfset{fpu=false}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\path[fill/.expanded={\pgfkeysvalueof{/tikz/my background}}]
(\meshXstep, 0) -- (0,0) -- (0, \meshYstep) -- cycle;
\clip (\meshXstep, 0) -- (0,0) -- (0, \meshYstep) -- cycle;
\tikzset{shift={(-\XiF, -\YiF)}}
\pic at (Xstart, Ystart) {my pic};
}
\pgfset{fpu=true}
\pgfmathsetmacro\Xii{\Xi + \meshXstep}
\pgfmathsetmacro\Yii{\Yi + \meshYstep}
\convertToFixedFormat{\XiiF}{\Xii}
\convertToFixedFormat{\YiiF}{\Yii}
\toFixedFormat{\aa}{fxx(\Xi, \Yii)}
\toFixedFormat{\ab}{fxy(\Xi, \Yii)}
\toFixedFormat{\ba}{fyx(\Xii, \Yi)}
\toFixedFormat{\bb}{fyy(\Xii, \Yi)}
\toFixedFormat{\xx}{fx (\Xii, \Yii)}
\toFixedFormat{\yy}{fy (\Xii, \Yii)}
\pgfset{fpu=false}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\path[fill/.expanded={\pgfkeysvalueof{/tikz/my background}}]
(0,0) -- (-\meshXstep,0) -- (0,-\meshYstep) -- cycle;
\clip (0,0) -- (-\meshXstep,0) -- (0,-\meshYstep) -- cycle;
\tikzset{shift={(-\XiiF, -\YiiF)}}
\pic at (Xstart, Ystart) {my pic};
}
}
}
\pgfmathsetmacro{\annotRaiseAmount}{2.54*1.8/72.27} % in 'xyz cs' units
% We won't draw the curve representing the deformation, but we'll use it to
% very accurately place the “compression” and “extension” annotations, so that
% they nicely follow the curved border.
\begin{axis}
[anchor=north west,
width={(Xstop - Xstart)*1cm},
yshift={(Ystop - Ystart)*1cm},
scale only axis=true,
axis equal image,
axis line style={draw=none},
tick style={draw=none},
xticklabel=\empty,
yticklabel=\empty,
every axis label/.append style={draw=none, minimum size=0, inner sep=0},
xlabel={},
ylabel={},
domain=Xstart:Xstop,
samples=500,
enlarge x limits=false,
enlarge y limits=false,
clip=false,
]
\addplot[draw=none,
% Raise the annotations a little bit above the border
yshift={\annotRaiseAmount*1cm},
postaction={
decorate,
decoration={
text along path,
text={%
|\normalfont\fontsize{5.5}{0}\selectfont|compression},
text align={left indent=10.88cm, right indent=3.45cm, fit to path},
},
},
postaction={
decorate,
decoration={
text along path,
text={%
|\normalfont\fontsize{5.5}{0}\selectfont|extension},
text align={left indent=12.7cm, right indent=1.93cm, fit to path},
},
},
] ({fx(x,Ystop)}, {fy(x,Ystop)}) coordinate[pos=0.735] (LeftTick)
coordinate[pos=0.843] (RightTick);
\end{axis}
% We defined (LeftTick) and (RightTick) on a curve that was raised by
% \annotRaiseAmount because of the textual annotations. Compensate for this
% raising and make sure the ticks don't overshoot above the curvy border.
\begin{scope}[color=black,
transform canvas={
shift={
($(0,-\annotRaiseAmount) + (0,-0.5*\myBorderRuleWidth)$)}}]
\draw (LeftTick) -- +(0, {-0.3*(Ystop - Ystart)});
\draw (RightTick) -- +(0, {-0.3*(Ystop - Ystart)});
\end{scope}
\draw[dashed] ([yshift={0.5*(Ystop - Ystart))*1cm}]Xstart,Ystart)
-- ([yshift={0.5*(Ystop - Ystart))*1cm}]Xstop,Ystart)
node[above, midway, inner ysep=0.5mm] {flexed lithosphere};
\end{tikzpicture}
\end{document}
The grid is barely visible on the preview here, but the whole is quite nice if you click and zoom in:

The same with the grid in a darker gray (gray!40!black
instead of gray!80
):

The part with annotations (using the gray!80
grid):

As per user request, here is a way to show the triangles used to approximate the modelled non-linear transformation. I reduce the numbers to nbXcells = 30; nbYcells = 10;
so that the triangles are not too difficult to see.
\documentclass[tikz, border=1mm]{standalone}
\usepackage{lmodern}
\usepackage{expl3}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{calc, decorations.text, fpu}
\ExplSyntaxOn
\cs_new_eq:NN \clistMapInline \clist_map_inline:nn
\ExplSyntaxOff
\newcommand*{\toFixedFormat}[2]{%
\pgfmathparse{#2}%
\pgfmathfloattofixed{\pgfmathresult}%
\let#1\pgfmathresult
}
% Faster than \toFixedFormat, but #2 must be a macro storing a result in the
% 'float' output format (of the PGF 'fpu' library).
\newcommand*{\convertToFixedFormat}[2]{%
\pgfmathfloattofixed{#2}%
\let#1\pgfmathresult
}
\newcommand*{\computeParam}[1]{%
\expandafter\pgfmathsetmacro\expandafter{\csname my#1\endcsname}{#1}%
}
\tikzset{
declare function={
Xstart = 0; Ystart = 0; % south west corner of source rectangle
Xstop = 15; Ystop = 0.6; % north east corner of source rectangle
nbXcells = 30; nbYcells = 10;
meshXstep = (Xstop-Xstart) / nbXcells;
meshYstep = (Ystop-Ystart) / nbYcells;
% Prerequesites for the transformation we want to apply.
% Increase omega for a sharper transition. deltai(i) is (for each of the
% two pieces) half the width of the interval where we use a tanh-like func.
omega = 2; deltai = 1.4; deltaii = deltai;
% Possible parameters. 'yMin' tells how much the deformation “pushes
% downwards.”
a = 1.8; b = a + 2*deltai; d = Xstop - a; c = d - 2*deltaii; yMin = -0.95;
A = -yMin/(2*tanh(omega*deltai));
B = -yMin/(tanh(omega*(d-c-deltaii)) + tanh(omega*deltaii));
mu = -B*tanh(omega*(d-c-deltaii));
% The transformation we want to apply (see below for the constants).
fx(\x,\y) = \x +
ifthenelse(\x < \mya, 0,
ifthenelse(\x < \myb,
0.67*exp(-5*(\x-\aplusdeltai)^2)* % transition with the straight part
(\y-\yMid)/(\Aomega*(1-(tanh(\myomega*(\aplusdeltai-\x)))^2)),
ifthenelse(\x < \myc, 0,
ifthenelse(\x < \myd,
.67*exp(-5*(\x-\cplusdeltaii)^2)* % transition
(\yMid-\y)/(\Bomega*(1-(tanh(\myomega*(\x-\cplusdeltaii)))^2)),
0
))));
fy(\x,\y) = \y +
ifthenelse(\x < \mya, 0,
ifthenelse(\x < \myb,
\myA*(tanh(\myomega*(\aplusdeltai-\x)) - \tanhomegadeltai)
% Compensate for the “transition deltax” we added in fx()
- 0.27*exp(-5*(\x-\aplusdeltai)^2)*(\y-\yMid),
ifthenelse(\x < \myc, \myyMin,
ifthenelse(\x < \myd,
\myB*tanh(\myomega*(\x-\cplusdeltaii)) + \mymu
% Compensate here too
- 0.27*exp(-5*(\x-\cplusdeltaii)^2)*(\y-\yMid),
0 % intentional: back at the same level
))));
}
}
% Precompute all constants. This gives a huge speed-up.
\pgfset{fpu=true}
\clistMapInline{yMin, a, b, c, d, A, B, deltai, deltaii, omega, mu}
{\computeParam{#1}} % Define \myyMin, \mya, \myb, etc.
\toFixedFormat{\meshXstep}{meshXstep}
\toFixedFormat{\meshYstep}{meshYstep}
\pgfmathsetmacro{\yMid}{0.5*(Ystart+Ystop)}
\pgfmathsetmacro{\aplusdeltai}{\mya+\mydeltai}
\pgfmathsetmacro{\cplusdeltaii}{\myc+\mydeltaii}
\pgfmathsetmacro{\Aomega}{\myA*\myomega}
\pgfmathsetmacro{\Bomega}{\myB*\myomega}
\pgfmathsetmacro{\tanhomegadeltai}{tanh(\myomega*\mydeltai)}
\pgfmathsetmacro{\Bomega}{\myB*\myomega}
\pgfset{fpu=false}
% Inspired by code from Symbol 1 <https://tex.stackexchange.com/a/332173/194703>
\pgfmathdeclarefunction{fxx}{2}{%
\pgfmathparse{1/\meshXstep*(fx(#1+\meshXstep, #2) - fx(#1,#2))}}
\pgfmathdeclarefunction{fxy}{2}{%
\pgfmathparse{1/\meshXstep*(fy(#1+\meshXstep, #2) - fy(#1,#2))}}
\pgfmathdeclarefunction{fyx}{2}{%
\pgfmathparse{1/\meshYstep*(fx(#1, #2+\meshYstep) - fx(#1,#2))}}
\pgfmathdeclarefunction{fyy}{2}{%
\pgfmathparse{1/\meshYstep*(fy(#1, #2+\meshYstep) - fy(#1,#2))}}
\newlength{\myWidth}
\newlength{\myHeight}
\pgfmathsetlengthmacro{\myBorderRuleWidth}{0.6pt}
% Assume the default unit vectors. Half of the border rule with is outside the
% border when a node is drawn; take this into account.
\pgfmathsetlength{\myWidth}{(Xstop - Xstart)*1cm - \myBorderRuleWidth}
\pgfmathsetlength{\myHeight}{(Ystop - Ystart)*1cm - \myBorderRuleWidth}
\begin{document}
\begin{tikzpicture}[
my background/.initial=gray!55, % this color is used in three places
show triangles/.style={color=white, line width=0.06pt},
my pic/.pic = {
\node at (0,0)
[rectangle, draw=black,
fill/.expanded={\pgfkeysvalueof{/tikz/my background}},
line width=\myBorderRuleWidth,
inner sep=0, anchor=south west, minimum width=\myWidth,
minimum height=\myHeight,
path picture={
\draw[line width=0.1pt, gray!80]
(path picture bounding box.south west) grid[step=0.2]
(path picture bounding box.north east);}]
{};
}]
% Set the bounding box (leave room for 'text along path' annotations)
\path (Xstart, Ystart+yMin) ([yshift=0.2cm]Xstop, Ystop);
\pgfmathtruncatemacro\iMax{nbXcells-1}
\pgfmathtruncatemacro\jMax{nbYcells-1}
\foreach \i in {0,...,\iMax} {
\foreach \j in {0,...,\jMax} {
\typeout{Processing cell (\i,\j); the last one will be (\iMax,\jMax).}
\pgfset{fpu=true}
\pgfmathsetmacro\Xi{Xstart + \i*\meshXstep}
\pgfmathsetmacro\Yi{Ystart + \j*\meshYstep}
\convertToFixedFormat{\XiF}{\Xi}
\convertToFixedFormat{\YiF}{\Yi}
\toFixedFormat{\aa}{fxx(\Xi, \Yi)}
\toFixedFormat{\ab}{fxy(\Xi, \Yi)}
\toFixedFormat{\ba}{fyx(\Xi, \Yi)}
\toFixedFormat{\bb}{fyy(\Xi, \Yi)}
\toFixedFormat{\xx}{fx (\Xi, \Yi)}
\toFixedFormat{\yy}{fy (\Xi, \Yi)}
\pgfset{fpu=false}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\path[fill/.expanded={\pgfkeysvalueof{/tikz/my background}}]
(\meshXstep, 0) -- (0,0) -- (0, \meshYstep) -- cycle;
\clip (\meshXstep, 0) -- (0,0) -- (0, \meshYstep) -- cycle;
\pic[shift={(-\XiF, -\YiF)}] at (Xstart, Ystart) {my pic};
\draw[show triangles]
(\meshXstep, 0) -- (0,0) -- (0, \meshYstep) -- cycle;
}
\pgfset{fpu=true}
\pgfmathsetmacro\Xii{\Xi + \meshXstep}
\pgfmathsetmacro\Yii{\Yi + \meshYstep}
\convertToFixedFormat{\XiiF}{\Xii}
\convertToFixedFormat{\YiiF}{\Yii}
\toFixedFormat{\aa}{fxx(\Xi, \Yii)}
\toFixedFormat{\ab}{fxy(\Xi, \Yii)}
\toFixedFormat{\ba}{fyx(\Xii, \Yi)}
\toFixedFormat{\bb}{fyy(\Xii, \Yi)}
\toFixedFormat{\xx}{fx (\Xii, \Yii)}
\toFixedFormat{\yy}{fy (\Xii, \Yii)}
\pgfset{fpu=false}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\path[fill/.expanded={\pgfkeysvalueof{/tikz/my background}}]
(0,0) -- (-\meshXstep,0) -- (0,-\meshYstep) -- cycle;
\clip (0,0) -- (-\meshXstep,0) -- (0,-\meshYstep) -- cycle;
\pic[shift={(-\XiiF, -\YiiF)}] at (Xstart, Ystart) {my pic};
\draw[show triangles]
(0,0) -- (-\meshXstep,0) -- (0,-\meshYstep) -- cycle;
}
}
}
\pgfmathsetmacro{\annotRaiseAmount}{2.54*1.8/72.27} % in 'xyz cs' units
% We won't draw the curve representing the deformation, but we'll use it to
% very accurately place the “compression” and “extension” annotations, so that
% they nicely follow the curved border.
\begin{axis}
[anchor=north west,
width={(Xstop - Xstart)*1cm},
yshift={(Ystop - Ystart)*1cm},
scale only axis=true,
axis equal image,
axis line style={draw=none},
tick style={draw=none},
xticklabel=\empty,
yticklabel=\empty,
every axis label/.append style={draw=none, minimum size=0, inner sep=0},
xlabel={},
ylabel={},
domain=Xstart:Xstop,
samples=500,
enlarge x limits=false,
enlarge y limits=false,
clip=false,
]
\addplot[draw=none,
% Raise the annotations a little bit above the border
yshift={\annotRaiseAmount*1cm},
postaction={
decorate,
decoration={
text along path,
text={%
|\normalfont\fontsize{5.5}{0}\selectfont|compression},
text align={left indent=10.88cm, right indent=3.45cm, fit to path},
},
},
postaction={
decorate,
decoration={
text along path,
text={%
|\normalfont\fontsize{5.5}{0}\selectfont|extension},
text align={left indent=12.7cm, right indent=1.93cm, fit to path},
},
},
] ({fx(x,Ystop)}, {fy(x,Ystop)}) coordinate[pos=0.735] (LeftTick)
coordinate[pos=0.843] (RightTick);
\end{axis}
% We defined (LeftTick) and (RightTick) on a curve that was raised by
% \annotRaiseAmount because of the textual annotations. Compensate for this
% raising and make sure the ticks don't overshoot above the curvy border.
\begin{scope}[color=black,
transform canvas={
shift={
($(0,-\annotRaiseAmount) + (0,-0.5*\myBorderRuleWidth)$)}}]
\draw (LeftTick) -- +(0, {-0.3*(Ystop - Ystart)});
\draw (RightTick) -- +(0, {-0.3*(Ystop - Ystart)});
\end{scope}
\draw[dashed] ([yshift={0.5*(Ystop - Ystart))*1cm}]Xstart,Ystart)
-- ([yshift={0.5*(Ystop - Ystart))*1cm}]Xstop,Ystart)
node[above, midway, inner ysep=0.5mm] {flexed lithosphere};
\end{tikzpicture}
\end{document}



And since traditions are important:

(the source code is here; I had to post it in a separate answer due to the maximal answer length).