% Shared worksheet/solution source for an R1234yf swimming-pool heat pump.
% Every thermodynamic curve, cycle state, and reported value is regenerated.

\usepackage{luacoolprop}
\usetikzlibrary{arrows.meta,calc,intersections}
\pgfplotsset{compat=1.18}

\definecolor{RHeatPumpQuality}{RGB}{205,45,38}
\definecolor{RHeatPumpTemperature}{RGB}{35,85,205}
\definecolor{RHeatPumpEntropy}{RGB}{25,105,50}
\definecolor{RHeatPumpCycle}{RGB}{215,105,15}
\definecolor{RHeatPumpGuide}{RGB}{70,78,92}

\tikzset{
  r1234yf state/.style={
    circle,draw=RHeatPumpCycle,fill=white,very thick,
    inner sep=1.5pt,font=\sffamily\bfseries\small
  },
  r1234yf note/.style={
    fill=white,fill opacity=.93,text opacity=1,rounded corners=1pt,
    inner sep=2.5pt,font=\sffamily\scriptsize,align=left
  }
}

\newcommand{\RHeatPumpBackground}{%
  \LCPAddPHQuality[
    fluid=R1234yf,
    pressure min=100000,pressure max=8000000,
    enthalpy scale=1,pressure scale=1,
    quality values={0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1},
    quality symbol=x,
    quality color=RHeatPumpQuality,
    quality boundary color=RHeatPumpQuality,
    interior style={line width=.38pt},boundary style={line width=.9pt},
    labels=true,quality label every=1,quality label pos=.14,
    quality label sloped=true,
    initial intervals=28,max depth=9,tolerance=.11
  ]%
  \LCPAddPHIsotherms[
    fluid=R1234yf,
    pressure min=100000,pressure max=8000000,
    enthalpy scale=1,pressure scale=1,
    temperature unit=K,
    temperature values={253,263,273,283,293,303,313,
      323,333,343,353,363,373},
    isotherm color=RHeatPumpTemperature,
    isotherm style={line width=.42pt},
    labels=true,isotherm label every=1,isotherm label pos=.13,
    isotherm label sloped=true,
    initial intervals=28,max depth=9,tolerance=.11
  ]%
  \LCPAddPHIsentropes[
    fluid=R1234yf,
    pressure min=100000,pressure max=8000000,
    enthalpy scale=1,pressure scale=1,
    entropy unit=SI,
    entropy values={1500,1550,1600,1650,1700,
      1750,1800,1850,1900,1950,2000},
    isentrope color=RHeatPumpEntropy,
    isentrope style={line width=.42pt},
    labels=true,isentrope label every=1,isentrope label pos=.82,
    isentrope label sloped=true,
    initial intervals=28,max depth=9,tolerance=.11
  ]%
}

% Derive both operating pressures from the two saturation temperatures.  The
% short invisible quality paths expose the computed pressures as TeX macros;
% operating pressures are calculated rather than copied from a drawing.
\newcommand{\RHeatPumpOperatingPressures}{%
  \LCPAddPHProcess[
    fluid=R1234yf,type=quality,quality=1,
    from={temperature=-10C},to={temperature=-9C},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-low-saturation-helper,style={draw=none},
    export coordinates=RHeatPumpLowSaturation,coord digits=10
  ]%
  \LCPAddPHProcess[
    fluid=R1234yf,type=quality,quality=0,
    from={temperature=50C},to={temperature=49C},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-high-saturation-helper,style={draw=none},
    export coordinates=RHeatPumpHighSaturation,coord digits=10
  ]%
  \typeout{R1234yf saturation helper low pressure (Pa):
    \RHeatPumpLowSaturationFromPressureSI}%
  \typeout{R1234yf saturation helper high pressure (Pa):
    \RHeatPumpHighSaturationFromPressureSI}%
}

\newcommand{\RHeatPumpCyclePaths}{%
  % B -> C: adiabatic reversible compression.
  \LCPAddPHProcess[
    fluid=R1234yf,type=isentrope,
    from={pressure=\RHeatPumpLowSaturationFromPressureSI Pa,
      temperature=0C},
    to={pressure=\RHeatPumpHighSaturationFromPressureSI Pa},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-bc,export coordinates=RHeatPumpBC,
    coord digits=10,log coordinates=true,
    color=RHeatPumpCycle,
    style={line width=1.65pt,-{Latex[length=2.6mm]}}
  ]%
  % C -> D: desuperheating, condensation at 50 C, then 10 K subcooling.
  \LCPAddPHProcess[
    fluid=R1234yf,type=isobar,
    pressure=\RHeatPumpHighSaturationFromPressureSI Pa,
    from={entropy=\RHeatPumpBCToEntropySI JkgK},
    to={temperature=40C},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-cd,export coordinates=RHeatPumpCD,
    coord digits=10,log coordinates=true,
    color=RHeatPumpCycle,
    style={line width=1.65pt,-{Latex[length=2.6mm]}}
  ]%
  % D -> A: adiabatic throttle with no moving parts, hence h_A=h_D.
  \LCPAddPHProcess[
    fluid=R1234yf,type=isenthalp,
    from={pressure=\RHeatPumpHighSaturationFromPressureSI Pa,
      temperature=40C},
    to={pressure=\RHeatPumpLowSaturationFromPressureSI Pa},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-da,export coordinates=RHeatPumpDA,
    coord digits=10,log coordinates=true,
    color=RHeatPumpCycle,
    style={line width=1.65pt,-{Latex[length=2.6mm]}}
  ]%
  % A -> B: evaporation at -10 C followed by 10 K isobaric superheating.
  \LCPAddPHProcess[
    fluid=R1234yf,type=isobar,
    pressure=\RHeatPumpLowSaturationFromPressureSI Pa,
    from={enthalpy=\RHeatPumpDAToEnthalpySI Jkg},
    to={temperature=0C},
    enthalpy scale=1,pressure scale=1,
    name=r1234yf-ab,export coordinates=RHeatPumpAB,
    coord digits=10,log coordinates=true,
    color=RHeatPumpCycle,
    style={line width=1.65pt,-{Latex[length=2.6mm]}}
  ]%
}

\newcommand{\RHeatPumpStateIntersections}{%
  \path[name intersections={of=r1234yf-da and r1234yf-ab,
    by=RHeatPumpA}];%
  \path[name intersections={of=r1234yf-ab and r1234yf-bc,
    by=RHeatPumpB}];%
  \path[name intersections={of=r1234yf-bc and r1234yf-cd,
    by=RHeatPumpC}];%
  \path[name intersections={of=r1234yf-cd and r1234yf-da,
    by=RHeatPumpD}];%
}

\newcommand{\RHeatPumpStateMarker}[3]{%
  \filldraw[draw=RHeatPumpCycle,fill=white,line width=1pt]
    (#1) circle[radius=2.1pt];%
  \node[r1234yf state,#3] at (#1) {#2};%
}

\begin{document}
\LCPSetup{fluid=R1234yf}
\begin{tikzpicture}
\begin{axis}[
  lcp fluid=R1234yf,
  width=24cm,height=15cm,
  xmin=100000,xmax=620000,
  ymin=100000,ymax=8000000,ymode=log,
  xlabel={Specific enthalpy $h$ (\si{\joule\per\kilogram})},
  ylabel={Pressure $p$ (\si{\pascal})},
  title={R1234yf pressure--enthalpy diagram},
  grid=both,
  major grid style={black!28},minor grid style={black!10},
  tick label style={font=\small},label style={font=\small},
  title style={font=\sffamily\large},
  clip mode=individual,
  auto node placement,
  % This background contains many labelled curves.  The greedy algorithm is
  % deterministic and keeps worksheet builds fast while still allowing the
  % autonomous pgfplots library to choose a readable position on each curve.
  auto node algorithm=greedy,
  auto node candidates=21,
  auto node bbox mode=oriented,
  auto node failure mode=hide-low-priority
]
  \RHeatPumpBackground

  \ifRHeatPumpSolution
    \RHeatPumpOperatingPressures
    \RHeatPumpCyclePaths
    \RHeatPumpStateIntersections

    \coordinate (RHeatPumpAxisBottom) at (axis cs:100000,100000);
    \path (RHeatPumpC |- RHeatPumpAxisBottom)
      coordinate (RHeatPumpCBottom);
    \path (RHeatPumpD |- RHeatPumpAxisBottom)
      coordinate (RHeatPumpDBottom);
    \draw[RHeatPumpGuide,densely dashed]
      (RHeatPumpCBottom)--(RHeatPumpC);
    \draw[RHeatPumpGuide,densely dashed]
      (RHeatPumpDBottom)--(RHeatPumpD);

    \RHeatPumpStateMarker{RHeatPumpA}{A}{anchor=north east}
    \RHeatPumpStateMarker{RHeatPumpB}{B}{anchor=south east}
    \RHeatPumpStateMarker{RHeatPumpC}{C}{anchor=south west}
    \RHeatPumpStateMarker{RHeatPumpD}{D}{anchor=south east}

    % LaTeX's expandable floating-point evaluator accepts the full SI values
    % without TeX's fixed-point dimension limit.  Division by 1000 returns kW.
    \edef\RHeatPumpCondenserPowerKW{\fpeval{
      5*(\RHeatPumpCDToEnthalpySI
        -\RHeatPumpCDFromEnthalpySI)/1000}}
    \edef\RHeatPumpEvaporatorPowerKW{\fpeval{
      5*(\RHeatPumpABToEnthalpySI
        -\RHeatPumpABFromEnthalpySI)/1000}}
    \edef\RHeatPumpCompressorPowerKW{\fpeval{
      5*(\RHeatPumpBCToEnthalpySI
        -\RHeatPumpBCFromEnthalpySI)/1000}}

    \node[r1234yf note,anchor=north west]
      at (rel axis cs:.012,.985) {%
      $p_e=\qty[round-mode=figures,round-precision=4]
        {\RHeatPumpLowSaturationFromPressureSI}{\pascal}$,\quad
      $p_c=\qty[round-mode=figures,round-precision=5]
        {\RHeatPumpHighSaturationFromPressureSI}{\pascal}$\\
      $h_C=\qty[round-mode=figures,round-precision=6]
        {\RHeatPumpCDFromEnthalpySI}{\joule\per\kilogram}$,\quad
      $h_D=\qty[round-mode=figures,round-precision=6]
        {\RHeatPumpCDToEnthalpySI}{\joule\per\kilogram}$\\
      $\mathcal P_1=\dot m(h_D-h_C)
        =\qty[round-mode=figures,round-precision=4]
          {\RHeatPumpCondenserPowerKW}{\kilo\watt}$
    };

    \node[r1234yf note,anchor=south west,text=RHeatPumpCycle]
      at (RHeatPumpA) {throttle:\\$h_A=h_D$};
    \node[r1234yf note,anchor=north,text=RHeatPumpCycle]
      at ($(RHeatPumpA)!.55!(RHeatPumpB)$) {evaporator};
    \node[r1234yf note,anchor=south east,text=RHeatPumpCycle]
      at ($(RHeatPumpB)!.55!(RHeatPumpC)$) {compressor:\\$s_C=s_B$};
    \node[r1234yf note,anchor=south,text=RHeatPumpCycle]
      at ($(RHeatPumpC)!.5!(RHeatPumpD)$) {condenser};

    \typeout{R1234yf heat-pump low pressure (Pa):
      \RHeatPumpLowSaturationFromPressureSI}
    \typeout{R1234yf heat-pump high pressure (Pa):
      \RHeatPumpHighSaturationFromPressureSI}
    \typeout{R1234yf heat-pump h_C (J/kg):
      \RHeatPumpCDFromEnthalpySI}
    \typeout{R1234yf heat-pump h_D (J/kg):
      \RHeatPumpCDToEnthalpySI}
    \typeout{R1234yf heat-pump condenser power received (kW):
      \RHeatPumpCondenserPowerKW}
  \fi
\end{axis}
\end{tikzpicture}
\end{document}
