Brake based on Coulomb friction. This component models a brake, i.e., a component where a frictional
torque is acting between the housing and a flange and a controlled normal
force presses the flange to the housing in order to increase friction.
The normal force fn has to be provided as input signal f_normalized in a normalized form
(0 ≤ f_normalized ≤ 1),
fn = fn_max*f_normalized, where fn_max has to be provided as parameter.
Friction in the brake is modelled in the following way:

within Modelica.Mechanics.Rotational.Components;
model Brake "Brake based on Coulomb friction"
  extends Modelica.Mechanics.Rotational.Interfaces.PartialElementaryTwoFlangesAndSupport2;

  import Modelica.Blocks.Types.{ExternalCombiTable1D, Extrapolation, Smoothness};
  import Modelica.Blocks.Tables.Internal.{getTable1DValue, getTable1DValueNoDer, getTable1DValueNoDer2};

  parameter Real mu_pos[:, 2] = [0, 0.5]
    "Positive sliding friction coefficient [-] as function of w [rad/s] (w>=0)";
  parameter Smoothness smoothness = Smoothness.LinearSegments
    "Smoothness of table interpolation in mu_pos";
  parameter Real peak(final min=1) = 1
    "Peak for maximum value of mu at w==0 (mu0_max = peak*mu_pos[1,2])";
  parameter Real cgeo(final min=0) = 1
    "Geometry constant containing friction distribution assumption";
  parameter SI.Force fn_max(final min=0, start=1) "Maximum normal force";

  extends Rotational.Interfaces.PartialFriction;
  extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;

  SI.Angle phi
    "Angle between shaft flanges (flange_a, flange_b) and support";
  SI.Torque tau "Brake friction torque";
  SI.AngularVelocity w "Absolute angular velocity of flange_a and flange_b";
  SI.AngularAcceleration a
    "Absolute angular acceleration of flange_a and flange_b";

  Real mu "Friction coefficient";
  SI.Force fn "Normal force (=fn_max*f_normalized)";
  Modelica.Blocks.Interfaces.RealInput f_normalized
    "Normalized force signal 0..1 (normal force = fn_max*f_normalized; brake is active if > 0)"

protected
  final parameter ExternalCombiTable1D tableID = ExternalCombiTable1D(
    tableName="NoName",
    fileName="NoName",
    table=mu_pos,
    columns={2},
    smoothness=smoothness,
    extrapolation=Extrapolation.LastTwoPoints,
    verboseRead=false) "External table object for sliding friction coefficient";
  final parameter Real mu0 =
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, 0)
    else                                                  getTable1DValue(tableID, 1, 0)
    "Friction coefficient for w=0 and forward sliding";

  Real table_signs[2]
    "Signs for sliding friction coefficient table interpolation: [sign for w, sign for mu]";

equation
  assert(size(mu_pos, 1) > 0 and size(mu_pos, 2) > 0, "Parameter mu_pos is an empty matrix");

  phi = flange_a.phi - phi_support;
  flange_b.phi = flange_a.phi;

  // Angular velocity and angular acceleration of flanges flange_a and flange_b
  w = der(phi);
  a = der(w);
  w_relfric = w;
  a_relfric = a;

  // Friction torque, normal force and friction torque for w=0
  flange_a.tau + flange_b.tau - tau = 0;
  fn = fn_max*f_normalized;
  tau0 = mu0*cgeo*fn;
  tau0_max = peak*tau0;
  free = fn <= 0;

  // Friction torque
  table_signs =
    if     startForward         then { 1, 1}
    elseif startBackward        then {-1,-1}
    elseif pre(mode) == Forward then { 1, 1}
    else                             {-1,-1};
  mu = table_signs[2]*(
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, table_signs[1]*w)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, table_signs[1]*w)
    else                                                  getTable1DValue(tableID, 1, table_signs[1]*w));
  tau = if locked then sa*unitTorque else if free then 0 else mu*cgeo*fn;

  lossPower = tau*w_relfric;
end Brake;


Clutch based on Coulomb friction. This component models a clutch, i.e., a component with
two flanges where friction is present between the two flanges
and these flanges are pressed together via a normal force.
The normal force fn has to be provided as input signal f_normalized in a normalized form
(0 ≤ f_normalized ≤ 1),
fn = fn_max*f_normalized, where fn_max has to be provided as parameter. Friction in the
clutch is modelled in the following way:

within Modelica.Mechanics.Rotational.Components;
model Clutch "Clutch based on Coulomb friction"
  extends Modelica.Mechanics.Rotational.Icons.Clutch;
  extends Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;

  import Modelica.Blocks.Types.{ExternalCombiTable1D, Extrapolation, Smoothness};
  import Modelica.Blocks.Tables.Internal.{getTable1DValue, getTable1DValueNoDer, getTable1DValueNoDer2};

  parameter Real mu_pos[:, 2] = [0, 0.5]
    "Positive sliding friction coefficient [-] as function of w_rel [rad/s] (w_rel>=0)";
  parameter Smoothness smoothness = Smoothness.LinearSegments
    "Smoothness of table interpolation in mu_pos";
  parameter Real peak(final min=1) = 1
    "Peak for maximum value of mu at w==0 (mu0_max = peak*mu_pos[1,2])";
  parameter Real cgeo(final min=0) = 1
    "Geometry constant containing friction distribution assumption";
  parameter SI.Force fn_max(final min=0, start=1) "Maximum normal force";

  extends Rotational.Interfaces.PartialFriction;
  extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;

  Real mu "Friction coefficient";
  SI.Force fn "Normal force (fn=fn_max*f_normalized)";
  Modelica.Blocks.Interfaces.RealInput f_normalized
    "Normalized force signal 0..1 (normal force = fn_max*f_normalized; clutch is engaged if > 0)"

protected
  final parameter ExternalCombiTable1D tableID = ExternalCombiTable1D(
    tableName="NoName",
    fileName="NoName",
    table=mu_pos,
    columns={2},
    smoothness=smoothness,
    extrapolation=Extrapolation.LastTwoPoints,
    verboseRead=false) "External table object for sliding friction coefficient";
  final parameter Real mu0 =
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, 0)
    else                                                  getTable1DValue(tableID, 1, 0)
    "Friction coefficient for w=0 and forward sliding";

  Real table_signs[2]
    "Signs for sliding friction coefficient table interpolation: [sign for w_rel, sign for mu]";

equation
  assert(size(mu_pos, 1) > 0 and size(mu_pos, 2) > 0, "Parameter mu_pos is an empty matrix");

  // Relative quantities
  w_relfric = w_rel;
  a_relfric = a_rel;

  // Normal force and friction torque for w_rel=0
  fn = fn_max*f_normalized;
  free = fn <= 0;
  tau0 = mu0*cgeo*fn;
  tau0_max = peak*tau0;

  // Friction torque
  table_signs =
    if     startForward         then { 1, 1}
    elseif startBackward        then { 1,-1}
    elseif pre(mode) == Forward then { 1, 1}
    else                             {-1,-1};
  mu = table_signs[2]*(
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, table_signs[1]*w_rel)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, table_signs[1]*w_rel)
    else                                                  getTable1DValue(tableID, 1, table_signs[1]*w_rel));
  tau = if locked then sa*unitTorque elseif free then 0 else mu*cgeo*fn;

  lossPower = tau*w_relfric;
end Clutch;


Ideal rotational coupling. This is a model of an ideal stiff coupling (face to face),
i.e., the angular velocity if flange_b is exactly in opposite direction of flange_a,
and the torque of both flanges is identical.

within Modelica.Mechanics.Rotational.Components;
model Coupling "Ideal rotational coupling"
  extends Modelica.Mechanics.Rotational.Interfaces.PartialTwoFlanges;
  Modelica.Units.SI.AngularVelocity w(displayUnit="rpm") = der(flange_a.phi) "Angular velocity of flange_a";
  Modelica.Units.SI.Torque tau = flange_a.tau "Torque of flange_a and flange_b";
equation
  flange_a.phi + flange_b.phi = 0;
  flange_a.tau - flange_b.tau = 0;
end Coupling;


Linear 1D rotational damper. Linear, velocity dependent damper element. It can be either connected
between an inertia or gear and the housing (component Fixed), or
between two inertia/gear elements.

within Modelica.Mechanics.Rotational.Components;
model Damper "Linear 1D rotational damper"
  extends
    Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;
  parameter SI.RotationalDampingConstant d(final min=0, start=0)
    "Damping constant";
  extends
    Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;
equation
  tau = d*w_rel;
  lossPower = tau*w_rel;
end Damper;


1-dim. rotational rigid component without inertia, where right flange is rotated by a fixed angle with respect to left flange. Rotational component with two rigidly connected flanges without inertia.
The right flange is rotated by the fixed angle \"deltaPhi\" with respect to the left
flange.

within Modelica.Mechanics.Rotational.Components;
model Disc
  "1-dim. rotational rigid component without inertia, where right flange is rotated by a fixed angle with respect to left flange"
  extends Rotational.Interfaces.PartialTwoFlanges;
  parameter SI.Angle deltaPhi=0
    "Fixed rotation of left flange with respect to right flange (= flange_b.phi - flange_a.phi)";
  SI.Angle phi "Absolute rotation angle of component";

equation
  flange_a.phi = phi - deltaPhi/2;
  flange_b.phi = phi + deltaPhi/2;
  0 = flange_a.tau + flange_b.tau;
end Disc;


Backlash connected in series to linear spring and damper (backlash is modeled with elasticity). This element consists of a backlash element connected in series
to a spring and damper element which are connected in parallel.
The spring constant shall be non-zero, otherwise the component cannot be used.

within Modelica.Mechanics.Rotational.Components;
model ElastoBacklash
  "Backlash connected in series to linear spring and damper (backlash is modeled with elasticity)"

  parameter SI.RotationalSpringConstant c(final min=Modelica.Constants.small,
      start=1.0e5) "Spring constant (c > 0 required)";
  parameter SI.RotationalDampingConstant d(final min=0, start=0)
    "Damping constant";
  parameter SI.Angle b(final min=0) = 0 "Total backlash";
  parameter SI.Angle phi_rel0=0 "Unstretched spring angle";

  extends
    Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;
  extends
    Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;
protected
  final parameter SI.Angle bMax=b/2
    "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
  final parameter SI.Angle bMin=-bMax
    "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
  SI.Torque tau_c;
  SI.Torque tau_d;
  SI.Angle phi_diff=phi_rel - phi_rel0;

  // A minimum backlash is defined in order to avoid an infinite
  // number of state events if backlash b is set to zero.
  constant SI.Angle bEps=1e-10 "Minimum backlash";

equation
  if initial() then
    /* During initialization the characteristic is modified, in order that
        it is a strict monotone rising function. Otherwise, initialization might
        result in a singular system when the characteristic has to be
        inverted. The characteristic is modified in the range 1.5*bMin <= phi_rel - phi_rel0 <= 1.5 bMax,
        so that in this range a linear characteristic is present that approaches the original
        function continuously at its limits, e.g.,
          original:  tau(1.5*bMax) = c*(phi_diff - bMax)
                                   = c*(0.5*bMax)
          initial :  tau(1.5*bMax) = (c/3)*phi_diff
                                   = (c/3)*(3/2)*bMax
                                   = (c/2)*bMax
     */
    tau_c = if phi_diff > 1.5*bMax then c*(phi_diff - bMax) else if
      phi_diff < 1.5*bMin then c*(phi_diff - bMin) else (c/3)*phi_diff;
    tau_d = d*w_rel;
    tau = tau_c + tau_d;
    lossPower = tau_d*w_rel;
  else
    /*
     if abs(b) <= bEps then
        tau_c = c*phi_diff;
        tau_d = d*w_rel;
        tau   = tau_c + tau_d;
     elseif phi_diff > bMax then
        tau_c = c*(phi_diff - bMax);
        tau_d = d*w_rel;
        tau   = smooth(0, noEvent(if tau_c + tau_d <= 0 then 0 else tau_c + min(tau_c,tau_d)));
     elseif phi_diff < bMin then
        tau_c = c*(phi_diff - bMin);
        tau_d = d*w_rel;
        tau   = smooth(0, noEvent(if tau_c + tau_d >= 0 then 0 else tau_c + max(tau_c,tau_d)));
     else
        tau_c = 0;
        tau_d = 0;
        tau   = 0;
     end if;

     This is written in the form below, in order that parameter "b"
     is not evaluated during translation (i.e., in the above form
     it cannot be changed anymore after translation).
   */

    tau_c = if abs(b) <= bEps then c*phi_diff else if phi_diff > bMax then
      c*(phi_diff - bMax) else if phi_diff < bMin then c*(phi_diff - bMin)
       else 0;
    tau_d = d*w_rel;
    tau = if abs(b) <= bEps then tau_c + tau_d else if phi_diff > bMax
       then smooth(0, noEvent(if tau_c + tau_d <= 0 then 0 else tau_c + min(
      tau_c, tau_d))) else if phi_diff < bMin then smooth(0, noEvent(if
      tau_c + tau_d >= 0 then 0 else tau_c + max(tau_c, tau_d))) else 0;
    lossPower = if abs(b) <= bEps then tau_d*w_rel else if phi_diff > bMax
       then smooth(0, noEvent(if tau_c + tau_d <= 0 then 0 else min(tau_c,
      tau_d)*w_rel)) else if phi_diff < bMin then smooth(0, noEvent(if
      tau_c + tau_d >= 0 then 0 else max(tau_c, tau_d)*w_rel)) else 0;
  end if;    // spring torque
   tau_d = d*der(phi_rel);            // damper torque
   flange_b.tau = if tau_c + tau_d ≤ 0 then 0 else tau_c + min( tau_c, tau_d );
end if;

Note, when sticking would occur (tau_c + tau_d ≤ 0), then the contact torque
is explicitly set to zero. The \"min(tau_c, tau_d)\" part in the if-expression,
limits the damping torque when it is pushing. This means that at the start of
the contact (phi_rel - phi_rel0 = b/2), the damping torque is zero and is continuous.
The effect of both modifications is that the absolute value of the damping torque
is always limited by the absolute value of the spring torque: |tau_d| ≤ |tau_c|.

In the next figure, a typical simulation with the ElastoBacklash model is shown
(Examples.Backlash)
where the different effects are visualized:

 Curve 1 (elastoBacklash1.tau) is the unmodified contact torque, i.e., the linear spring/damper
     characteristic. A pulling/sticking torque is present at the end of the contact.

 Curve 2 (elastoBacklash2.tau) is the contact torque, where the torque is explicitly set to
     zero when pulling/sticking occurs. The contact torque is discontinuous at begin of
     contact.

 Curve 3 (elastoBacklash3.tau) is the ElastoBacklash model of this library. No discontinuity and no
     pulling/sticking occurs.

See also the discussion
State Selection
in the User's Guide of the Rotational library.

"),
    Icon(
    coordinateSystem(preserveAspectRatio=true,
      extent={{-100,-100},{100,100}}),
      graphics={
    Line(points={{-80,32},{-58,32},{-48,0},{-34,61},{-20,0},{-8,60},{0,30},{20,30}}),
    Rectangle(extent={{-60,-10},{-10,-50}},
      fillColor={192,192,192},
      fillPattern=FillPattern.Solid),
    Line(points={{-60,-50},{0,-50}}),
    Line(points={{-60,-10},{0,-10}}),
    Line(points={{-10,-30},{20,-30}}),
    Line(points={{-80,-30},{-60,-30}}),
    Line(points={{-80,32},{-80,-30}}),
    Line(points={{20,30},{20,-30}}),
    Line(points={{-90,0},{-80,0}}),
    Line(points={{90,0},{80,0}}),
    Line(points={{20,0},{60,0},{60,-30}}),
    Line(points={{40,-12},{40,-40},{80,-40},{80,0}}),
    Text(extent={{-150,-130},{150,-90}},
      textString="b=%b"),
    Text(extent={{-150,100},{150,60}},
      textColor={0,0,255},
      textString="%name"),
    Text(extent={{-152,-92},{148,-52}},
      textString="c=%c"),
    Line(visible=useHeatPort,
      points={{-100,-100},{-100,-43},{-34,-43}},
      color={191,0,0},
      pattern=LinePattern.Dot)}));
end ElastoBacklash;


Backlash connected in series to linear spring and damper (backlash is modeled with elasticity; at start of contact the flange torque can jump, contrary to the ElastoBacklash model). This element consists of a backlash element connected in series
to a spring and damper element which are connected in parallel.
The spring constant shall be non-zero, otherwise the component cannot be used.

within Modelica.Mechanics.Rotational.Components;
model ElastoBacklash2
  "Backlash connected in series to linear spring and damper (backlash is modeled with elasticity; at start of contact the flange torque can jump, contrary to the ElastoBacklash model)"

  parameter SI.RotationalSpringConstant c(final min=Modelica.Constants.small,
      start=1.0e5) "Spring constant (c > 0 required)";
  parameter SI.RotationalDampingConstant d(final min=0, start=0)
    "Damping constant";
  parameter SI.Angle b(final min=0)=0 "Total backlash";
  parameter SI.Angle phi_rel0=0 "Unstretched spring angle";

  extends
    Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;
  extends
    Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;
protected
  final parameter SI.Angle bMax=b/2
    "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
  final parameter SI.Angle bMin=-bMax
    "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
  SI.Torque tau_c;
  SI.Torque tau_d;
  SI.Angle phi_diff=phi_rel - phi_rel0;

  // A minimum backlash is defined in order to avoid an infinite
  // number of state events if backlash b is set to zero.
  constant SI.Angle bEps=1e-10 "Minimum backlash";

equation
  if initial() then
    /* During initialization the characteristic is modified, in order that
        it is a strict monotone rising function. Otherwise, initialization might
        result in a singular system when the characteristic has to be
        inverted. The characteristic is modified in the range 1.5*bMin <= phi_rel - phi_rel0 <= 1.5 bMax,
        so that in this range a linear characteristic is present that approaches the original
        function continuously at its limits, e.g.,
          original:  tau(1.5*bMax) = c*(phi_diff - bMax)
                                   = c*(0.5*bMax)
          initial :  tau(1.5*bMax) = (c/3)*phi_diff
                                   = (c/3)*(3/2)*bMax
                                   = (c/2)*bMax
     */
    tau_c = if phi_diff > 1.5*bMax then c*(phi_diff - bMax) else if
      phi_diff < 1.5*bMin then c*(phi_diff - bMin) else (c/3)*phi_diff;
    tau_d = d*w_rel;
    tau = tau_c + tau_d;
    lossPower = tau_d*w_rel;
   else
     /*
     if abs(b) <= bEps then
        tau_c = c*phi_diff;
        tau_d = d*w_rel;
        tau   = tau_c + tau_d;
     elseif phi_diff > bMax then
        tau_c = c*(phi_diff - bMax);
        tau_d = d*w_rel;
        tau   = if tau_c + tau_d <= 0 then 0 else tau_c + tau_d;
     elseif phi_diff < bMin then
        tau_c = c*(phi_diff - bMin);
        tau_d = d*w_rel;
        tau   = if tau_c + tau_d >= 0 then 0 else tau_c + tau_d;
     else
        tau_c = 0;
        tau_d = 0;
        tau   = 0;
     end if;

     This is written in the form below, in order that parameter "b"
     is not evaluated during translation (i.e., in the above form
     it cannot be changed anymore after translation).
   */
    tau_c = if abs(b) <= bEps then
               c*phi_diff
            else if phi_diff > bMax then
               c*(phi_diff - bMax)
            else if phi_diff < bMin then
               c*(phi_diff - bMin)
            else 0;
    tau_d = d*w_rel;

    tau = if abs(b) <= bEps then
             tau_c + tau_d
          else if phi_diff > bMax then
             (if tau_c + tau_d <= 0 then 0 else tau_c + tau_d)
          else if phi_diff < bMin then
             (if tau_c + tau_d >= 0 then 0 else tau_c + tau_d)
          else 0;

    lossPower = if abs(b) <= bEps then
                   tau_d*w_rel
                else if phi_diff > bMax then
                   (if tau_c + tau_d <= 0 then 0 else tau_d*w_rel)
                else if phi_diff < bMin then
                   (if tau_c + tau_d >= 0 then 0 else tau_d*w_rel)
                else 0;
  end if;    // spring torque
   tau_d = d*der(phi_rel);            // damper torque
   flange_b.tau = if tau_c + tau_d ≤ 0 then 0 else tau_c + tau_d;
end if;

Note, when sticking would occur (tau_c + tau_d ≤ 0), then the contact torque
is explicitly set to zero.

This model of backlash is slightly different to the
ElastoBacklash
component:

 An event occurs when contact occurs or when contact is released (contrary to the ElastoBacklash component).

 When contact occurs, the torque changes discontinuously, due to the damping.
     The damping is larger as for the ElastoBacklash component (for the same damping coefficient),
    because the ElastoBacklash component has a heuristic to avoid the discontinuity of the torque when contact occurs.

 For some models, the ElastoBacklash2 component leads to faster simulations
      (as compared when using the ElastBacklash component).

See also the discussion
State Selection
in the User's Guide of the Rotational library.

"),
    Icon(
    coordinateSystem(preserveAspectRatio=false,
      extent={{-100,-100},{100,100}}),
      graphics={
    Line(points={{-80,32},{-58,32},{-48,0},{-34,61},{-20,0},{-8,60},{0,30},{20,30}}),
    Rectangle(extent={{-60,-10},{-10,-50}},
      fillColor={192,192,192},
      fillPattern=FillPattern.Solid),
    Line(points={{-60,-50},{0,-50}}),
    Line(points={{-60,-10},{0,-10}}),
    Line(points={{-10,-30},{20,-30}}),
    Line(points={{-80,-30},{-60,-30}}),
    Line(points={{-80,32},{-80,-30}}),
    Line(points={{20,30},{20,-30}}),
    Line(points={{-90,0},{-80,0}}),
    Line(points={{90,0},{80,0}}),
    Line(points={{20,0},{60,0},{60,-30}}),
    Line(points={{40,-12},{40,-40},{80,-40},{80,0}}),
    Text(extent={{-150,-130},{150,-90}},
      textString="b=%b"),
    Text(extent={{-150,100},{150,60}},
      textColor={0,0,255},
      textString="%name"),
    Text(extent={{-152,-92},{148,-52}},
      textString="c=%c"),
    Line(visible=useHeatPort,
      points={{-100,-100},{-100,-43},{-34,-43}},
      color={191,0,0},
      pattern=LinePattern.Dot),
        Text(
          extent={{20,48},{80,10}},
          textColor={95,95,95},
          textString="2")}));
end ElastoBacklash2;


Flange fixed in housing at a given angle. The flange of a 1D rotational mechanical system is fixed
at an angle phi0 in the housing. May be used:

within Modelica.Mechanics.Rotational.Components;
model Fixed "Flange fixed in housing at a given angle"
  parameter SI.Angle phi0=0 "Fixed offset angle of housing";

  Interfaces.Flange_b flange "(right) flange fixed in housing"

equation
  flange.phi = phi0;
end Fixed;


Realistic model of a gearbox (based on LossyGear). This component models the essential effects of a gearbox, in
particular

within Modelica.Mechanics.Rotational.Components;
model Gearbox "Realistic model of a gearbox (based on LossyGear)"
  extends Modelica.Mechanics.Rotational.Icons.Gearbox;
  extends Modelica.Mechanics.Rotational.Interfaces.PartialTwoFlangesAndSupport;

  parameter Real ratio(start=1)
    "Transmission ratio (flange_a.phi/flange_b.phi)";
  parameter Real lossTable[:, 5]=[0, 1, 1, 0, 0]
    "Array for mesh efficiencies and bearing friction depending on speed (see docu of LossyGear)";
  parameter SI.RotationalSpringConstant c(final min=Modelica.Constants.small,
      start=1.0e5) "Gear elasticity (spring constant)";
  parameter SI.RotationalDampingConstant d(final min=0, start=0)
    "Gear damping (relative damping)";
  parameter SI.Angle b(final min=0) = 0 "Total backlash";
  parameter StateSelect stateSelect=StateSelect.prefer
    "Priority to use phi_rel and w_rel as states"
  extends Modelica.Thermal.HeatTransfer.Interfaces.PartialConditionalHeatPort(
      final T=293.15);
  SI.Angle phi_rel(
    start=0,
    stateSelect=stateSelect,
    nominal=1e-4) = flange_b.phi - lossyGear.flange_b.phi
    "Relative rotation angle over gear elasticity (= flange_b.phi - lossyGear.flange_b.phi)";
  SI.AngularVelocity w_rel(
    start=0,
    stateSelect=stateSelect) = der(phi_rel)
    "Relative angular velocity over gear elasticity (= der(phi_rel))";
  SI.AngularAcceleration a_rel(start=0) = der(w_rel)
    "Relative angular acceleration over gear elasticity (= der(w_rel))";

  Rotational.Components.LossyGear lossyGear(
    final ratio=ratio,
    final lossTable=lossTable,
    final useSupport=true,
    final useHeatPort=true)
  Rotational.Components.ElastoBacklash elastoBacklash(
    final b=b,
    final c=c,
    final phi_rel0=0,
    final d=d,
    final useHeatPort=true)
equation
  connect(flange_a, lossyGear.flange_a)
  connect(lossyGear.flange_b, elastoBacklash.flange_a)
  connect(elastoBacklash.flange_b, flange_b)
  connect(elastoBacklash.heatPort, internalHeatPort)
  connect(lossyGear.heatPort, internalHeatPort)
  connect(lossyGear.support, internalSupport)
end Gearbox;


Signal adaptor for a rotational flange with torque as output and angle, speed and acceleration as input (especially useful for FMUs). Adaptor between a flange connector and a signal representation of the flange.
This component is used to provide a pure signal interface around a Rotational model
and export this model in form of an input/output block,
especially as FMU (Functional Mock-up Unit).
This adaptor has angle, angular velocity and angular acceleration as input signals and
torque as output signal.

within Modelica.Mechanics.Rotational.Components;
model GeneralAngleToTorqueAdaptor
  "Signal adaptor for a rotational flange with torque as output and angle, speed and acceleration as input (especially useful for FMUs)"
  extends
    Modelica.Blocks.Interfaces.Adaptors.PotentialToFlowAdaptor(
    final Name_p="phi",
    final Name_pder="w",
    final Name_pder2="a",
    final Name_f="tau",
    final Name_fder="der(tau)",
    final Name_fder2="der2(tau)",
    final use_fder=false,
    final use_fder2=false,
    final p(unit="rad"),
    final pder(unit="rad/s"),
    final pder2(unit="rad/s2"),
    final f(unit="N.m"),
    final fder(unit="N.m/s"),
    final fder2(unit="N.m/s2"));
  Modelica.Mechanics.Rotational.Interfaces.Flange_b    flange
equation
  y = flange.tau "output = flow = torque";
  u = flange.phi "input = potential = angle";
end GeneralAngleToTorqueAdaptor;


Signal adaptor for a rotational flange with angle, speed, and acceleration as outputs and torque as input (especially useful for FMUs). Adaptor between a flange connector and a signal representation of the flange.
This component is used to provide a pure signal interface around a Rotational model
and export this model in form of an input/output block,
especially as FMU (Functional Mock-up Unit).
This adaptor has torque as input and angle, angular velocity and angular acceleration as output signals.

within Modelica.Mechanics.Rotational.Components;
model GeneralTorqueToAngleAdaptor
  "Signal adaptor for a rotational flange with angle, speed, and acceleration as outputs and torque as input (especially useful for FMUs)"
  extends
    Modelica.Blocks.Interfaces.Adaptors.FlowToPotentialAdaptor(
    final Name_p="phi",
    final Name_pder="w",
    final Name_pder2="a",
    final Name_f="tau",
    final Name_fder="der(tau)",
    final Name_fder2="der2(tau)",
    final use_fder=false,
    final use_fder2=false,
    final p(unit="rad"),
    final pder(unit="rad/s"),
    final pder2(unit="rad/s2"),
    final f(unit="N.m"),
    final fder(unit="N.m/s"),
    final fder2(unit="N.m/s2"));
  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange
equation
  y = flange.phi "output = potential = angle";
  u = flange.tau "input = flow = torque";
end GeneralTorqueToAngleAdaptor;


Ideal gear without inertia. This element characterizes any type of gear box which is fixed in the
ground and which has one driving shaft and one driven shaft.
The gear is ideal, i.e., it does not have inertia, elasticity, damping
or backlash. If these effects have to be considered, the gear has to be
connected to other elements in an appropriate way.

within Modelica.Mechanics.Rotational.Components;
model IdealGear "Ideal gear without inertia"
  extends Modelica.Mechanics.Rotational.Icons.Gear;
  extends
    Modelica.Mechanics.Rotational.Interfaces.PartialElementaryTwoFlangesAndSupport2;
  parameter Real ratio(start=1)
    "Transmission ratio (flange_a.phi/flange_b.phi)";
  SI.Angle phi_a
    "Angle between left shaft flange and support";
  SI.Angle phi_b
    "Angle between right shaft flange and support";

equation
  phi_a = flange_a.phi - phi_support;
  phi_b = flange_b.phi - phi_support;
  phi_a = ratio*phi_b;
  0 = ratio*flange_a.tau + flange_b.tau;
end IdealGear;


Gearbox transforming rotational into translational motion. This is an ideal mass- and inertialess gearbox which transforms a
1D-rotational into a 1D-translational motion. If elasticity, damping
or backlash has to be considered, this ideal gearbox has to be
connected with corresponding elements.
This component defines the kinematic constraint:


Ideal planetary gear box. The IdealPlanetary gear box is an ideal gear without inertia,
elasticity, damping or backlash consisting
of an inner sun wheel, an outer ring wheel and a
planet wheel located between sun and ring wheel. The bearing
of the planet wheel shaft is fixed in the planet carrier.
The component can be connected to other elements at the
sun, ring and/or carrier flanges. It is not possible to connect
to the planet wheel. If inertia shall not be neglected,
the sun, ring and carrier inertias can be easily added by attaching
inertias (= model Inertia) to the corresponding connectors.
The inertias of the planet wheels are always neglected.

within Modelica.Mechanics.Rotational.Components;
model IdealPlanetary "Ideal planetary gear box"
  parameter Real ratio(start=100/50)
    "Number of ring_teeth/sun_teeth (e.g., ratio=100/50)";

  // kinematic relationship
  Interfaces.Flange_a sun "Flange of sun shaft"
  Interfaces.Flange_a carrier "Flange of carrier shaft"
  Interfaces.Flange_b ring "Flange of ring shaft"

equation
  (1 + ratio)*carrier.phi = sun.phi + ratio*ring.phi;

  // torque balance (no inertias)
  ring.tau = ratio*sun.tau;
  carrier.tau = -(1 + ratio)*sun.tau;
end IdealPlanetary;


Simple 1-dim. model of an ideal rolling wheel without inertia. A simple kinematic model of a rolling wheel which has no inertia and
no rolling resistance. This component defines the kinematic constraint:

within Modelica.Mechanics.Rotational.Components;
model IdealRollingWheel
  "Simple 1-dim. model of an ideal rolling wheel without inertia"

  extends Rotational.Interfaces.PartialElementaryRotationalToTranslational;
  parameter SI.Distance radius(start=0.3) "Wheel radius";

equation
  (flangeR.phi - internalSupportR.phi)*radius = (flangeT.s -
    internalSupportT.s);
  0 = radius*flangeT.f + flangeR.tau;
</pre></blockquote>
</html>"));
end IdealRollingWheel;


1D-rotational component with inertia. Rotational component with inertia and two rigidly connected flanges.

within Modelica.Mechanics.Rotational.Components;
model Inertia "1D-rotational component with inertia"
  extends Rotational.Interfaces.PartialTwoFlanges;
  parameter SI.Inertia J(min=0, start=1) "Moment of inertia";
  parameter StateSelect stateSelect=StateSelect.default
    "Priority to use phi and w as states"
  SI.Angle phi(stateSelect=stateSelect)
    "Absolute rotation angle of component"
  SI.AngularVelocity w(stateSelect=stateSelect)
    "Absolute angular velocity of component (= der(phi))"
  SI.AngularAcceleration a
    "Absolute angular acceleration of component (= der(w))"

equation
  phi = flange_a.phi;
  phi = flange_b.phi;
  w = der(phi);
  a = der(w);
  J*a = flange_a.tau + flange_b.tau;
end Inertia;


Initializes a flange with pre-defined angle, speed and angular acceleration (usually, this is reference data from a control bus). This component is used to optionally initialize the angle, speed,
and/or angular acceleration of the flange to which this component
is connected. Via parameters use_phi_start, use_w_start, use_a_start
the corresponding input signals phi_start, w_start, a_start are conditionally
activated. If an input is activated, the corresponding flange property
is initialized with the input value at start time.

within Modelica.Mechanics.Rotational.Components;
model InitializeFlange
  "Initializes a flange with pre-defined angle, speed and angular acceleration (usually, this is reference data from a control bus)"
  extends Modelica.Blocks.Icons.Block;
  parameter Boolean use_phi_start=true
    "= true, if initial angle is defined by input phi_start, otherwise not initialized";
  parameter Boolean use_w_start=true
    "= true, if initial speed is defined by input w_start, otherwise not initialized";
  parameter Boolean use_a_start=true
    "= true, if initial angular acceleration is defined by input a_start, otherwise not initialized";

  parameter StateSelect stateSelect=StateSelect.default
    "Priority to use flange angle and speed as states";

  Modelica.Blocks.Interfaces.RealInput phi_start(unit="rad") if use_phi_start
    "Initial angle of flange"
  Modelica.Blocks.Interfaces.RealInput w_start(unit="rad/s") if use_w_start
    "Initial speed of flange"
  Modelica.Blocks.Interfaces.RealInput a_start(unit="rad/s2") if use_a_start
    "Initial angular acceleration of flange"
  Interfaces.Flange_b flange "Flange that is initialized"

  SI.Angle phi_flange(stateSelect=stateSelect) = flange.phi
    "Flange angle";
  SI.AngularVelocity w_flange(stateSelect=stateSelect) = der(
    phi_flange) "= der(phi_flange)";

protected
  encapsulated model Set_phi_start "Set phi_start"
    import Modelica;
    extends Modelica.Blocks.Icons.Block;
    Modelica.Blocks.Interfaces.RealInput phi_start(unit="rad")
      "Start angle"

    Modelica.Mechanics.Rotational.Interfaces.Flange_b flange
  initial equation
    flange.phi = phi_start;
  equation
    flange.tau = 0;

  end Set_phi_start;

  encapsulated model Set_w_start "Set w_start"
    import Modelica;
    extends Modelica.Blocks.Icons.Block;
    Modelica.Blocks.Interfaces.RealInput w_start(unit="rad/s")
      "Start angular velocity"

    Modelica.Mechanics.Rotational.Interfaces.Flange_b flange
  initial equation
    der(flange.phi) = w_start;
  equation
    flange.tau = 0;

  end Set_w_start;

  encapsulated model Set_a_start "Set a_start"
    import Modelica;
    extends Modelica.Blocks.Icons.Block;
    Modelica.Blocks.Interfaces.RealInput a_start(unit="rad/s2")
      "Start angular acceleration"

    Modelica.Mechanics.Rotational.Interfaces.Flange_b flange(phi(
          stateSelect=StateSelect.avoid))

    Modelica.Units.SI.AngularVelocity w=der(flange.phi)
  initial equation
    der(w) = a_start;
  equation
    flange.tau = 0;
  end Set_a_start;

  encapsulated model Set_flange_tau "Set flange.tau to zero"
    import Modelica;
    extends Modelica.Blocks.Icons.Block;
    Modelica.Mechanics.Rotational.Interfaces.Flange_b flange
  equation
    flange.tau = 0;
  end Set_flange_tau;
protected
  Set_phi_start set_phi_start if use_phi_start
  Set_w_start set_w_start if use_w_start
  Set_a_start set_a_start if use_a_start
  Set_flange_tau set_flange_tau
equation
  connect(set_phi_start.phi_start, phi_start)
  connect(set_phi_start.flange, flange)
  connect(set_w_start.flange, flange)
  connect(set_w_start.w_start, w_start)
  connect(set_a_start.a_start, a_start)
  connect(set_a_start.flange, flange)
  connect(set_flange_tau.flange, flange)
end InitializeFlange;


within Modelica.Mechanics.Rotational.Components;
model LossyGear
  "Gear with mesh efficiency and bearing friction (stuck/rolling possible)"

  extends Modelica.Mechanics.Rotational.Icons.Gear;
  extends Modelica.Mechanics.Rotational.Interfaces.PartialElementaryTwoFlangesAndSupport2;

  import Modelica.Blocks.Types.{ExternalCombiTable1D, Extrapolation, Smoothness};
  import Modelica.Blocks.Tables.Internal.{getTable1DValue, getTable1DValueNoDer, getTable1DValueNoDer2};

  parameter Real ratio(start=1)
    "Transmission ratio (flange_a.phi/flange_b.phi)";
  parameter Real lossTable[:, 5]=[0, 1, 1, 0, 0]
    "Array for mesh efficiencies and bearing friction depending on speed";
  parameter Smoothness smoothness = Smoothness.LinearSegments
    "Smoothness of interpolation in lossTable table";
  extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;
  SI.Angle phi_a
    "Angle between left shaft flange and support";
  SI.Angle phi_b
    "Angle between right shaft flange and support";

  Real sa(final unit="1") "Path parameter for acceleration and torque loss";
  SI.AngularVelocity w_a
    "Angular velocity of flange_a with respect to support";
  SI.AngularAcceleration a_a
    "Angular acceleration of flange_a with respect to support";

  Real interpolation_result[1, 4]
    "Result of interpolation in lossTable (= [eta_mf1, eta_mf2, tau_bf1, tau_bf2])";
  Real eta_mf1(unit="1") "Mesh efficiency in case that flange_a is driving";
  Real eta_mf2(unit="1") "Mesh efficiency in case that flange_b is driving";
  SI.Torque tau_bf_a "Bearing friction torque on flange_a side";
  SI.Torque tau_eta
    "Torque that determines the driving side (= if forwardSliding then flange_a.tau-tau_bf_a else if backwardSliding then flange_a.tau+tau_bf_a else flange_a.tau)";

  SI.Torque tau_bf1
    "Absolute resultant bearing friction torque with respect to flange_a in case that flange_a is driving (= |tau_bf_a*eta_mf1 + tau_bf_b/i|)";
  SI.Torque tau_bf2
    "Absolute resultant bearing friction torque with respect to flange_a in case that flange_b is driving (= |tau_bf_a/eta_mf2 + tau_bf_b/i|)";

  SI.Torque quadrant1 "Torque loss if w_a > 0 and flange_a.tau >= 0";
  SI.Torque quadrant2 "Torque loss if w_a > 0 and flange_a.tau < 0";
  SI.Torque quadrant3 "Torque loss if w_a < 0 and flange_a.tau >= 0";
  SI.Torque quadrant4 "Torque loss if w_a < 0 and flange_a.tau < 0";

  // Resultant friction torques at quadrant values for angular velocities near zero
  SI.Torque quadrant1_p
    "Torque loss at w_a = 0+ to determine driving side (flange_a.tau >= 0)";
  SI.Torque quadrant2_p
    "Torque loss at w_a = 0+ to determine driving side (flange_a.tau < 0)";
  SI.Torque quadrant3_m
    "Torque loss at w_a = 0- to determine driving side (flange_a.tau >=0)";
  SI.Torque quadrant4_m
    "Torque loss at w_a = 0- to determine driving side (flange_a.tau < 0)";

  SI.Torque tauLoss
    "Torque loss due to friction in the gear teeth and in the bearings";
  SI.Torque tauLossMax "Torque loss for positive speed";
  SI.Torque tauLossMin "Torque loss for negative speed";

  SI.Torque tauLossMax_p "Torque loss for positive speed";
  SI.Torque tauLossMin_m "Torque loss for negative speed";

  Boolean tau_aPos(start=true)
    "Only for backwards compatibility (was previously: true, if torque of flange_a is not negative)";
  Boolean tau_etaPos(start=true) "= true, if torque tau_eta is not negative";
  Boolean startForward(start=false) "= true, if starting to roll forward";
  Boolean startBackward(start=false) "= true, if starting to roll backward";
  Boolean locked(start=false) "= true, if gear is locked";

  Boolean ideal
    "= true, if losses are neglected (that is lossTable = [0, 1, 1, 0, 0])";

  constant Integer Unknown=3 "Value of mode is not known";
  constant Integer Free=2 "Element is not active";
  constant Integer Forward=1 "w_a > 0 (forward rolling)";
  constant Integer Stuck=0
    "w_a = 0 (forward rolling, locked or backward rolling)";
  constant Integer Backward=-1 "w_a < 0 (backward rolling)";
  Integer mode(
    final min=Backward,
    final max=Unknown,
    start=Free,
    fixed=true)
    "Mode of friction element (unknown, not active, forward/backward rolling, stuck)";

  SI.Torque tau_eta_p "tau_eta assuming positive omega";
  SI.Torque tau_eta_m "tau_eta assuming negative omega";
protected
  constant SI.AngularAcceleration unitAngularAcceleration=1;
  constant SI.Torque unitTorque=1;

  // get friction and eta information for omega=0
  parameter Real eta_mf1_0(unit="1")=
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, 0)
    else                                                  getTable1DValue(tableID, 1, 0);
  parameter Real eta_mf2_0(unit="1")=
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 2, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 2, 0)
    else                                                  getTable1DValue(tableID, 2, 0);
  parameter SI.Torque tau_bf1_0 = abs(
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 3, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 3, 0)
    else                                                  getTable1DValue(tableID, 3, 0));
  parameter SI.Torque tau_bf2_0 = abs(
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 4, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 4, 0)
    else                                                  getTable1DValue(tableID, 4, 0));
  parameter SI.Torque tau_bf_a_0=if Modelica.Math.isEqual(
          eta_mf1_0,
          1.0,
          Modelica.Constants.eps) and Modelica.Math.isEqual(
          eta_mf2_0,
          1.0,
          Modelica.Constants.eps) then tau_bf1_0/2 else (tau_bf1_0 -
      tau_bf2_0)/(eta_mf1_0 - 1.0/eta_mf2_0);
  // For eta_mf1_0=eta_mf2_0=1 the given bearing
  // friction can not be separated into a part
  // on side A or B, so it is done arbitrarily.
  // Calculate tau_bf_a_0 from the following equations
  //  tau_bf1_0=eta_mf1_0*tau_bf_a_0 + 1/ratio a_0
  //  tau_bf2_0=1/eta_mf2*tau_bf_a_0 + 1/ratio tau_bf_a_0

  final parameter ExternalCombiTable1D tableID = ExternalCombiTable1D(
    tableName="NoName",
    fileName="NoName",
    table=lossTable,
    columns={2,3,4,5},
    smoothness=smoothness,
    extrapolation=Extrapolation.LastTwoPoints,
    verboseRead=false) "External table object for sliding friction coefficient";

equation
  assert(abs(ratio) > 0,
    "Error in initialization of LossyGear: ratio may not be zero");
  assert(size(lossTable, 1) > 0 and size(lossTable, 2) > 0, "Parameter lossTable is an empty matrix");

  ideal = Modelica.Math.Matrices.isEqual(
        lossTable,
        [0, 1, 1, 0, 0],
        Modelica.Constants.eps);

  if ideal then
    interpolation_result = [1, 1, 0, 0];
    eta_mf1 = 1;
    eta_mf2 = 1;
    tau_bf1 = 0;
    tau_bf2 = 0;
  else
    for i in 1:size(interpolation_result,2) loop
      interpolation_result[1, i] =
        if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, i, noEvent(abs(w_a)))
        elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, i, noEvent(abs(w_a)))
        else                                                  getTable1DValue(tableID, i, noEvent(abs(w_a)));
    end for;
    eta_mf1 = interpolation_result[1, 1];
    eta_mf2 = interpolation_result[1, 2];
    tau_bf1 = noEvent(abs(interpolation_result[1, 3]));
    tau_bf2 = noEvent(abs(interpolation_result[1, 4]));
  end if;

  if Modelica.Math.isEqual(
          eta_mf1,
          1.0,
          Modelica.Constants.eps) and Modelica.Math.isEqual(
          eta_mf2,
          1.0,
          Modelica.Constants.eps) then
    // For eta_mf1=eta_mf2=1 the given bearing friction can not be
    // separated into a part on side A or B, so it is done arbitrarily.
    tau_bf_a = tau_bf1/2;
  else
    //calculate tau_bf_a from the following equations
    //tau_bf1 = eta_mf1*tau_bf_a + tau_bf_b / ratio
    //tau_bf2 = 1/eta_mf2*tau_bf_a + tau_bf_b / ratio
    tau_bf_a = (tau_bf1 - tau_bf2)/(eta_mf1 - 1.0/eta_mf2);
  end if;

  phi_a = flange_a.phi - phi_support;
  phi_b = flange_b.phi - phi_support;
  phi_a = ratio*phi_b;

  // Torque balance (no inertias)
  0 = flange_b.tau + ratio*(flange_a.tau - tauLoss);

  // Speed for friction element
  w_a = der(phi_a);
  a_a = der(w_a);

  // Determine driving side
  //assuming positive omega
  tau_eta_p = flange_a.tau - tau_bf_a_0;
  //assuming negative omega
  tau_eta_m = flange_a.tau + tau_bf_a_0;

  // assuming w>=0, take value at w=0 to decide rolling/stuck mode
  quadrant1_p = (1 - eta_mf1_0)*flange_a.tau + tau_bf1_0;
  quadrant2_p = (1 - 1/eta_mf2_0)*flange_a.tau + tau_bf2_0;
  tauLossMax_p = if noEvent(tau_eta_p > 0) then quadrant1_p else
    quadrant2_p;

  // assuming w<=0, take value at w=0 to decide rolling/stuck mode
  quadrant4_m = (1 - 1/eta_mf2_0)*flange_a.tau - tau_bf2_0;
  quadrant3_m = (1 - eta_mf1_0)*flange_a.tau - tau_bf1_0;
  tauLossMin_m = if noEvent(tau_eta_m > 0) then quadrant4_m else
    quadrant3_m;

  quadrant1 = (1 - eta_mf1)*flange_a.tau + tau_bf1;
  quadrant2 = (1 - 1/eta_mf2)*flange_a.tau + tau_bf2;
  quadrant4 = (1 - 1/eta_mf2)*flange_a.tau - tau_bf2;
  quadrant3 = (1 - eta_mf1)*flange_a.tau - tau_bf1;

  //tau eta: only for determination of driving side for calculation of tauloss
  tau_eta = if ideal then flange_a.tau else (if locked then flange_a.tau
     else (if (startForward or pre(mode) == Forward) then flange_a.tau -
    tau_bf_a else flange_a.tau + tau_bf_a));

  // Torque Losses
  tau_etaPos = tau_eta >= 0;
  tau_aPos = tau_etaPos;
  tauLossMax = if tau_etaPos then quadrant1 else quadrant2;
  tauLossMin = if tau_etaPos then quadrant4 else quadrant3;

  // Determine rolling/stuck mode when w_a = 0
  startForward = pre(mode) == Stuck and sa > tauLossMax_p/unitTorque or
    initial() and w_a > 0;
  startBackward = pre(mode) == Stuck and sa < tauLossMin_m/unitTorque or
    initial() and w_a < 0;
  locked = not (ideal or pre(mode) == Forward or startForward or pre(mode)
     == Backward or startBackward);

  /* Parameterized curve description a_a = f1(sa), tauLoss = f2(sa)
       In comparison to Modelica.Mechanics.Rotational.FrictionBase it is possible
       to simplify the following expression as mode == Stuck is assured in case
       of startForward or startBackward */
  tauLoss = if ideal then 0 else (if locked then sa*unitTorque else (if (
    startForward or pre(mode) == Forward) then tauLossMax else tauLossMin));

  a_a = unitAngularAcceleration*(if locked then 0 else sa - tauLoss/
    unitTorque);

  /* Finite state machine to fix configuration after the computation above
       The above equations are only dependent on pre(mode) and not on the actual
       value of mode. This prevents loops. So mode can be determined in one step. */
  mode = if ideal then Free else (if (pre(mode) == Forward or startForward)
     and w_a > 0 then Forward else if (pre(mode) == Backward or
    startBackward) and w_a < 0 then Backward else Stuck);

  lossPower = tauLoss*w_a;

// or        -flange_b.tau = i*eta_mf*(flange_a.tau - tau_bf_a - tau_bf_b/(i*eta_mf));

where

 i is the constant gear ratio,

 eta_mf = eta_mf(w_a) is the mesh efficiency due to the
     friction between the teeth of the gear wheels,

 tau_bf_a = tau_bf_a(w_a) is the bearing friction torque
     on the flange_a side,

 tau_bf_b = tau_bf_b(w_a) is the bearing friction torque
     on the flange_b side, and

w_a = der(flange_a.phi) is the speed of flange_a

The loss terms \"eta_mf\", \"tau_bf_a\" and \"tau_bf_b\" are functions of the
absolute value of the input shaft speed w_a and of the energy
flow direction. They are defined by parameter lossTable[:,5]
 where the columns of this table have the following
meaning:

      |w_a|
      eta_mf1
      eta_mf2
      |tau_bf1|
      |tau_bf2|

      …
      …
      …
      …
      …

      …
      …
      …
      …
      …

with

      |w_a|
      Absolute value of angular velocity of input shaft flange_a

      eta_mf1
      Mesh efficiency in case that flange_a is driving

      eta_mf2
      Mesh efficiency in case that flange_b is driving

      |tau_bf1|
       Absolute resultant bearing friction torque with respect to flange_a
                        in case that flange_a is driving

                        (= |tau_bf_a*eta_mf1 + tau_bf_b/i|)

      |tau_bf2|
       Absolute resultant bearing friction torque with respect to flange_a
                        in case that flange_b is driving

                        (= |tau_bf_a/eta_mf2 + tau_bf_b/i|)

With these variables, the mesh efficiency and the bearing friction
are formally defined as:

if (flange_a.tau - tau_bf_a)*w_a > 0 or
   (flange_a.tau - tau_bf_a) == 0 and w_a > 0 then
   eta_mf := eta_mf1
   tau_bf := tau_bf1
elseif (flange_a.tau - tau_bf_a)*w_a < 0 or
       (flange_a.tau - tau_bf_a) == 0 and w_a < 0 then
   eta_mf := 1/eta_mf2
   tau_bf := tau_bf2
else // w_a == 0
   eta_mf and tau_bf are computed such that der(w_a) = 0
end if;
-flange_b.tau = i*(eta_mf*flange_a.tau - tau_bf);

Note, that the losses are modeled in a physically meaningful way taking
into account that at zero speed the movement may be locked due
to the friction in the gear teeth and/or in the bearings.
Due to this important property, this component can be used in
situations where the combination of the components
Modelica.Mechanics.Rotational.IdealGear and
Modelica.Mechanics.Rotational.GearEfficiency will fail because,
e.g., chattering occurs when using the
Modelica.Mechanics.Rotational.GearEfficiency model.

Acknowledgement

 The essential idea to model efficiency
     in this way is from Christoph Pelchen, ZF Friedrichshafen.

 The article (Pelchen et.al. 2002), see Literature below,
     and the first implementation of LossyGear (up to version 3.1 of package Modelica)
     contained a bug leading to a non-converging solution in cases where the
     driving side is not obvious.
     This was pointed out by Christian Bertsch and Max Westenkirchner, Bosch,
     and Christian Bertsch proposed a concrete solution how to fix this
     bug, see Literature below.

Literature

Pelchen C.,
Schweiger C.,
and Otter M.:
"Modeling
and Simulating the Efficiency of Gearboxes and of Planetary Gearboxes," in
Proceedings of the 2nd International Modelica Conference, Oberpfaffenhofen, Germany,
pp. 257-266, The Modelica Association and Institute of Robotics and Mechatronics,
Deutsches Zentrum für Luft- und Raumfahrt e. V., March 18-19, 2002.

Bertsch C. (2009):
"Problem
with model LossyGear and a proposed solution",
Ticket #108,
Sept. 11, 2009.

"),
       Icon(
    coordinateSystem(preserveAspectRatio=true,
        extent={{-100.0,-100.0},{100.0,100.0}}),
    graphics={
    Polygon(fillColor={161,35,41},
      pattern=LinePattern.None,
      fillPattern=FillPattern.Solid,
      points={{-110,50},{-80,50},{-80,80},{-90,80},{-70,100},{-50,80},{-60,80},{-60,30},{-110,30},{-110,50}}),
    Line(points={{-80.0,20.0},{-60.0,20.0}}),
    Text(textColor={0,0,255},
      extent={{-148.0,105.0},{152.0,145.0}},
      textString="%name"),
    Text(extent={{-145.0,-79.0},{155.0,-49.0}},
      textString="ratio=%ratio"),
    Line(visible=useHeatPort,
      points={{-100.0,-100.0},{-100.0,-30.0},{0.0,-30.0},{0.0,0.0}},
      color={191,0,0},
      pattern=LinePattern.Dot)}));
end LossyGear;


Parallel connection of freewheel and clutch. This component models a one-way clutch, i.e., a component with
two flanges where friction is present between the two flanges
and these flanges are pressed together via a normal force. These
flanges may be sliding with respect to each other.

within Modelica.Mechanics.Rotational.Components;
model OneWayClutch "Parallel connection of freewheel and clutch"
  extends Modelica.Mechanics.Rotational.Icons.Clutch;
  extends Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;

  import Modelica.Blocks.Types.{ExternalCombiTable1D, Extrapolation, Smoothness};
  import Modelica.Blocks.Tables.Internal.{getTable1DValue, getTable1DValueNoDer, getTable1DValueNoDer2};

  parameter Real mu_pos[:, 2] = [0, 0.5]
    "Positive sliding friction coefficient [-] as function of w_rel [rad/s] (w_rel>=0)";
  parameter Smoothness smoothness = Smoothness.LinearSegments
    "Smoothness of table interpolation in mu_pos";
  parameter Real peak(final min=1) = 1
    "Peak for maximum value of mu at w==0 (mu0_max = peak*mu_pos[1,2])";
  parameter Real cgeo(final min=0) = 1
    "Geometry constant containing friction distribution assumption";
  parameter SI.Force fn_max(final min=0, start=1) "Maximum normal force";
  parameter SI.AngularVelocity w_small=1e10
    "Relative angular velocity near to zero if jumps due to a reinit(..) of the velocity can occur (set to low value only if such impulses can occur)"
  extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;

  Real u "Normalized force input signal (0..1)";
  Real mu "Friction coefficient";
  SI.Force fn "Normal force (fn=fn_max*inPort.signal)";
  Boolean startForward(start=false)
    "= true, if w_rel=0 and start of forward sliding or w_rel > w_small";
  Boolean locked(start=false) "= true, if w_rel=0 and not sliding";
  Boolean stuck(start=false) "w_rel=0 (locked or start forward sliding)";

protected
  SI.Torque tau0 "Friction torque for w=0 and sliding";
  SI.Torque tau0_max "Maximum friction torque for w=0 and locked";
  final parameter ExternalCombiTable1D tableID = ExternalCombiTable1D(
    tableName="NoName",
    fileName="NoName",
    table=mu_pos,
    columns={2},
    smoothness=smoothness,
    extrapolation=Extrapolation.LastTwoPoints,
    verboseRead=false) "External table object for sliding friction coefficient";
  final parameter Real mu0 =
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, 0)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, 0)
    else                                                  getTable1DValue(tableID, 1, 0)
    "Friction coefficient for w=0 and sliding";
  Boolean free "= true, if frictional element is not active";
  Real sa(final unit="1")
    "Path parameter of tau = f(a_rel) Friction characteristic";
  constant Real eps0=1.0e-4 "Relative hysteresis epsilon";
  final parameter SI.Torque tau0_max_low = eps0*mu0*cgeo*fn_max
    "Lowest value for tau0_max";
  parameter Real peak2=max([peak, 1 + eps0]);
  constant SI.AngularAcceleration unitAngularAcceleration=1;
  constant SI.Torque unitTorque=1;

public
  Modelica.Blocks.Interfaces.RealInput f_normalized
    "Normalized force signal 0..1 (normal force = fn_max*f_normalized; clutch is engaged if > 0)"

equation
  assert(size(mu_pos, 1) > 0 and size(mu_pos, 2) > 0, "Parameter mu_pos is an empty matrix");

  // Normal force and friction torque for w_rel=0
  u = f_normalized;
  free = u <= 0;
  fn = if free then 0 else fn_max*u;
  tau0 = mu0*cgeo*fn;
  tau0_max = if free then tau0_max_low else peak2*tau0;

  /* Friction characteristic
       (locked is introduced to help the Modelica translator determining
       the different structural configurations, if for each configuration
       special code shall be generated)
    */
  startForward = pre(stuck) and (sa > tau0_max/unitTorque or pre(
    startForward) and sa > tau0/unitTorque or w_rel > w_small) or initial()
     and (w_rel > 0);
  locked = pre(stuck) and not startForward;

  // Acceleration and friction torque
  mu =
    if     smoothness == Smoothness.ConstantSegments then getTable1DValueNoDer(tableID, 1, w_rel)
    elseif smoothness == Smoothness.LinearSegments   then getTable1DValueNoDer2(tableID, 1, w_rel)
    else                                                  getTable1DValue(tableID, 1, w_rel);
  a_rel = unitAngularAcceleration*(if locked then 0 else sa - tau0/unitTorque);
  tau = if locked then sa*unitTorque elseif free then 0 else mu*cgeo*fn;

  // Determine configuration
  stuck = locked or w_rel <= 0;

  lossPower = if stuck then 0 else tau*w_rel;
end OneWayClutch;


within Modelica.Mechanics.Rotational;
package Components "Components for 1D rotational mechanical drive trains"
  extends Modelica.Icons.Package;
end Components;


Definition of relative state variables. Usually, the absolute angle and the absolute angular velocity of
Modelica.Mechanics.Rotational.Components.Inertia models are used as state variables.
In some circumstances, relative quantities are better suited, e.g.,
because it may be easier to supply initial values.
In such cases, model RelativeStates allows the definition of state variables
in the following way:

within Modelica.Mechanics.Rotational.Components;
model RelativeStates "Definition of relative state variables"
  extends Rotational.Interfaces.PartialTwoFlanges;
  parameter StateSelect stateSelect=StateSelect.prefer
    "Priority to use the relative angle and relative speed as states";
  parameter SI.Angle phi_nominal(
    displayUnit="rad",
    min=0.0) = 1.0 "Nominal value of the relative angle (used for scaling)";

  SI.Angle phi_rel(
    start=0,
    stateSelect=stateSelect,
    nominal=if phi_nominal >= Modelica.Constants.eps then phi_nominal else
        1) "Relative rotation angle used as state variable";
  SI.AngularVelocity w_rel(start=0, stateSelect=stateSelect)
    "Relative angular velocity used as state variable";
  SI.AngularAcceleration a_rel(start=0) "Relative angular acceleration";

equation
  phi_rel = flange_b.phi - flange_a.phi;
  w_rel = der(phi_rel);
  a_rel = der(w_rel);
  flange_a.tau = 0;
  flange_b.tau = 0;
end RelativeStates;


Linear 1D rotational spring. A linear 1D rotational spring. The component can be connected either
between two inertias/gears to describe the shaft elasticity, or between
a inertia/gear and the housing (component Fixed), to describe
a coupling of the element with the housing via a spring.

within Modelica.Mechanics.Rotational.Components;
model Spring "Linear 1D rotational spring"
  extends Modelica.Mechanics.Rotational.Interfaces.PartialCompliant;
  parameter SI.RotationalSpringConstant c(final min=0, start=1.0e5)
    "Spring constant";
  parameter SI.Angle phi_rel0=0 "Unstretched spring angle";

equation
  tau = c*(phi_rel - phi_rel0);
end Spring;


Linear 1D rotational spring and damper in parallel. A spring and damper element connected in parallel.
The component can be
connected either between two inertias/gears to describe the shaft elasticity
and damping, or between an inertia/gear and the housing (component Fixed),
to describe a coupling of the element with the housing via a spring/damper.

within Modelica.Mechanics.Rotational.Components;
model SpringDamper "Linear 1D rotational spring and damper in parallel"
  parameter SI.RotationalSpringConstant c(final min=0, start=1.0e5)
    "Spring constant";
  parameter SI.RotationalDampingConstant d(final min=0, start=0)
    "Damping constant";
  parameter SI.Angle phi_rel0=0 "Unstretched spring angle";
  extends
    Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;
  extends
    Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;
protected
  SI.Torque tau_c "Spring torque";
  SI.Torque tau_d "Damping torque";
equation
  tau_c = c*(phi_rel - phi_rel0);
  tau_d = d*w_rel;
  tau = tau_c + tau_d;
  lossPower = tau_d*w_rel;
end SpringDamper;


Signal adaptor for a Rotational flange with angle, speed, and acceleration as outputs and torque as input (especially useful for FMUs). Adaptor between a flange connector and a signal representation of the flange.
This component is used to provide a pure signal interface around a Rotational model
and export this model in form of an input/output block,
especially as FMU (Functional Mock-up Unit).
Examples of the usage of this adaptor are provided in
Rotational.Examples.GenerationOfFMUs.
This adaptor has torque as input and angle, angular velocity and angular acceleration as output signals.

within Modelica.Mechanics.Rotational.Components;
model TorqueToAngleAdaptor
  "Signal adaptor for a Rotational flange with angle, speed, and acceleration as outputs and torque as input (especially useful for FMUs)"
  parameter Boolean use_w=true
    "= true, enable the output connector w (angular velocity)"
  parameter Boolean use_a=true
    "= true, enable the output connector a (angular acceleration)"

  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange
  Modelica.Blocks.Interfaces.RealOutput phi(unit="rad")
    "Flange moves with angle phi due to torque tau"
  Modelica.Blocks.Interfaces.RealOutput w(unit="rad/s") if use_w
    "Flange moves with speed w due to torque tau"
  Modelica.Blocks.Interfaces.RealOutput a(unit="rad/s2") if use_a
    "Flange moves with angular acceleration a due to torque tau"
  Modelica.Blocks.Interfaces.RealInput tau(unit="N.m")
    "Torque to drive the flange"
protected
  Modelica.Blocks.Interfaces.RealInput w_internal(unit="rad/s")
    "Needed to connect to conditional connector w";
  Modelica.Blocks.Interfaces.RealInput a_internal(unit="rad/s2")
    "Needed to connect to conditional connector a";
equation
  connect(w, w_internal);
  connect(a, a_internal);
  phi = flange.phi;
  if use_w then
    w_internal = der(phi);
  else
    w_internal = 0.0;
  end if;
  if use_a then
    a_internal = der(w_internal);
  else
    a_internal = 0.0;
  end if;
  flange.tau = tau;
end TorqueToAngleAdaptor;


Example to demonstrate backlash. This model demonstrates the effect of a backlash on eigenfrequency, and
also that the damping torque does not lead to unphysical pulling torques
(since the ElastoBacklash model takes care of it).
Furthermore, it shows the differences of the
ElastoBacklash and
ElastoBacklash2 components
(the ElastoBacklash2 component generates events when contact occurs and the torque changes discontinuously).

within Modelica.Mechanics.Rotational.Examples;
model Backlash "Example to demonstrate backlash"
  extends Modelica.Icons.Example;
  Rotational.Components.Fixed fixed1
  Rotational.Components.SpringDamper springDamper(
    c=20E3,
    d=50,
    phi_nominal=1)
  Rotational.Components.Inertia inertia1(
    J=5,
    w(fixed=true, start=0),
    phi(
      fixed=true,
      displayUnit="deg",
      start=1.570796326794897))
  Rotational.Components.Fixed fixed2
  Rotational.Components.ElastoBacklash elastoBacklash(
    c=20E3,
    d=50,
    b(displayUnit="deg") = 0.7853981633974483,
    phi_nominal=1)
  Rotational.Components.Inertia inertia2(
    J=5,
    w(fixed=true, start=0),
    phi(
      fixed=true,
      start=1.570796326794897,
      displayUnit="deg"))
  Rotational.Components.Fixed fixed3
  Components.ElastoBacklash2           elastoBacklash2(
    c=20E3,
    d=50,
    phi_nominal=1,
    b(displayUnit="deg") = 0.78539816339745)
  Rotational.Components.Inertia inertia3(
    J=5,
    w(fixed=true, start=0),
    phi(
      fixed=true,
      start=1.570796326794897,
      displayUnit="deg"))
equation
  connect(springDamper.flange_b, inertia1.flange_a)
  connect(elastoBacklash.flange_b, inertia2.flange_a)
  connect(fixed1.flange, springDamper.flange_a)
  connect(fixed2.flange, elastoBacklash.flange_a)
  connect(elastoBacklash2.flange_b, inertia3.flange_a)
  connect(fixed3.flange, elastoBacklash2.flange_a)
end Backlash;


Compare different braking torques. Compare the effect of different braking torques on inertia's angular velocity
(inertiaN.w, N = {1, 2, 3, 4}):

within Modelica.Mechanics.Rotational.Examples;
model CompareBrakingTorque "Compare different braking torques"
  extends Modelica.Icons.Example;
  parameter SI.Inertia J=1 "Moment of inertia";
  parameter SI.AngularVelocity w_start=100 "Initial speed of inertia";
  parameter SI.Torque tau_nominal=100 "Nominal torque";
  parameter SI.AngularVelocity w_nominal=abs(w_start) "Nominal speed";
  parameter SI.AngularVelocity w0=1 "Speed limit for regularization";
  Modelica.Mechanics.Rotational.Components.Inertia inertia1(
    J=J,
    phi(fixed=true, start=0),
    w(fixed=true, start=w_start))
  Modelica.Mechanics.Rotational.Sources.SignTorque signTorque(
    tau_nominal=-tau_nominal,
    reg=Modelica.Blocks.Types.Regularization.Linear,
    w0=w0)
  Modelica.Mechanics.Rotational.Components.Inertia inertia2(
    J=J,
    phi(fixed=true, start=0),
    w(fixed=true, start=w_start))
  Modelica.Mechanics.Rotational.Sources.LinearSpeedDependentTorque
    linearSpeedDependentTorque(
    tau_nominal=-tau_nominal,
    TorqueDirection=false,
    w_nominal=w_nominal)
  Modelica.Mechanics.Rotational.Components.Inertia inertia3(
    J=J,
    phi(fixed=true, start=0),
    w(fixed=true, start=w_start))
  Modelica.Mechanics.Rotational.Sources.QuadraticSpeedDependentTorque
    quadraticSpeedDependentTorque(
    tau_nominal=-tau_nominal,
    TorqueDirection=false,
    w_nominal=w_nominal)
  Modelica.Mechanics.Rotational.Components.Inertia inertia4(
    J=J,
    phi(fixed=true, start=0),
    w(fixed=true, start=w_start))
  Modelica.Mechanics.Rotational.Sources.InverseSpeedDependentTorque
    inverseSpeedDependentTorque(
    tau_nominal=-tau_nominal,
    TorqueDirection=false,
    w_nominal=w_nominal,
    w0=w0)
equation
  connect(signTorque.flange, inertia1.flange_a)
  connect(linearSpeedDependentTorque.flange, inertia2.flange_a)
  connect(quadraticSpeedDependentTorque.flange, inertia3.flange_a)
  connect(inverseSpeedDependentTorque.flange, inertia4.flange_a)
end CompareBrakingTorque;


Drive train with 3 dynamically coupled clutches. This example demonstrates how variable structure
drive trains are handled. The drive train consists
of 4 inertias and 3 clutches, where the clutches
are controlled by input signals. The system has
2^3=8 different configurations and 3^3 = 27
different states (every clutch may be in forward
sliding, backward sliding or locked mode when the
relative angular velocity is zero). By invoking the
clutches at different time instances, the switching
of the configurations can be studied.

within Modelica.Mechanics.Rotational.Examples;
model CoupledClutches "Drive train with 3 dynamically coupled clutches"
  extends Modelica.Icons.Example;
  parameter SI.Frequency f=0.2
    "Frequency of sine function to invoke clutch1";
  parameter SI.Time T2=0.4 "Time when clutch2 is invoked";
  parameter SI.Time T3=0.9 "Time when clutch3 is invoked";

  Rotational.Components.Inertia J1(
    J=1,
    phi(fixed=true, start=0),
    w(start=10, fixed=true))
  Rotational.Sources.Torque torque(useSupport=true)
  Rotational.Components.Clutch clutch1(peak=1.1, fn_max=20)
  Modelica.Blocks.Sources.Sine sin1(amplitude=10, f=5)
  Modelica.Blocks.Sources.Step step1(startTime=T2)
  Rotational.Components.Inertia J2(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Rotational.Components.Clutch clutch2(peak=1.1, fn_max=20)
  Rotational.Components.Inertia J3(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Rotational.Components.Clutch clutch3(peak=1.1, fn_max=20)
  Rotational.Components.Inertia J4(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Blocks.Sources.Sine sin2(
    amplitude=1,
    f=f,
    phase=1.570796326794897)
  Modelica.Blocks.Sources.Step step2(startTime=T3)
  Rotational.Components.Fixed fixed
equation
  connect(torque.flange, J1.flange_a)
  connect(J1.flange_b, clutch1.flange_a)
  connect(clutch1.flange_b, J2.flange_a)
  connect(J2.flange_b, clutch2.flange_a)
  connect(clutch2.flange_b, J3.flange_a)
  connect(J3.flange_b, clutch3.flange_a)
  connect(clutch3.flange_b, J4.flange_a)
  connect(sin1.y, torque.tau)
  connect(sin2.y, clutch1.f_normalized)
  connect(step1.y, clutch2.f_normalized)
  connect(step2.y, clutch3.f_normalized)
  connect(fixed.flange, torque.support)
end CoupledClutches;


Demonstrate the usage of the rotational eddy current brake. An eddy current brake reduces the speed of a rotating inertia. Kinetic energy is converted to thermal energy which leads to a temperature increase of the thermal capacitance of the brake, which can be assumed as adiabatic during the rather short time span of the braking.

within Modelica.Mechanics.Rotational.Examples;
model EddyCurrentBrake "Demonstrate the usage of the rotational eddy current brake"
  extends Modelica.Icons.Example;
  Modelica.Mechanics.Rotational.Sources.EddyCurrentTorque eddyCurrentTorque(
    useExcitationInput=true,
    tau_nominal=100,
    w_nominal=10,
    useSupport=false,
    alpha20(displayUnit="1/K") = Modelica.Electrical.Machines.Thermal.Constants.alpha20Copper,
    TRef=293.15,
    useHeatPort=true)
  Modelica.Mechanics.Rotational.Components.Inertia inertia(
    phi(fixed=true, start=0),
    J=1,
    w(fixed=true, start=20))
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heatCapacitor(C=1, T(
        fixed=true))
  Blocks.Sources.Ramp ramp(
    height=1,
    duration=0.1,
    offset=0,
    startTime=0.1)
equation
  connect(eddyCurrentTorque.flange, inertia.flange_a)
  connect(eddyCurrentTorque.heatPort, heatCapacitor.port)
  connect(ramp.y, eddyCurrentTorque.excitation)
end EddyCurrentBrake;


Example to show possible usage of support flange. This model demonstrates the usage of the bearing flange.
The gearbox is not connected rigidly to the ground, but by
a spring-damper-system. This allows examination of the gearbox
housing dynamics.

within Modelica.Mechanics.Rotational.Examples;
model ElasticBearing "Example to show possible usage of support flange"
  extends Modelica.Icons.Example;
  Rotational.Components.Inertia shaft(
    phi(fixed=true, start=0),
    J=1,
    w(fixed=true, start=0))
  Rotational.Components.Inertia load(J=50, w(fixed=true, start=0))
  Rotational.Components.Spring spring(c=1e3, phi_rel(fixed=true))
  Rotational.Components.Fixed fixed
  Rotational.Components.SpringDamper springDamper(
    c=1e5,
    d=5,
    phi_rel(fixed=true),
    w_rel(fixed=true, nominal=1e-4))
  Rotational.Sources.Torque torque(useSupport=true)
  Modelica.Blocks.Sources.Ramp ramp(duration=5, height=100)
  Rotational.Components.IdealGear idealGear(ratio=3, useSupport=true)
  Rotational.Components.Inertia housing(J=5)
  Sensors.MultiSensor multiSensor
equation
  connect(torque.flange, shaft.flange_a)
  connect(spring.flange_b, load.flange_a)
  connect(springDamper.flange_a, fixed.flange)
  connect(shaft.flange_b, idealGear.flange_a)
  connect(idealGear.flange_b, spring.flange_a)
  connect(idealGear.support, housing.flange_b)
  connect(ramp.y, torque.tau)
  connect(fixed.flange, torque.support)
  connect(housing.flange_a, multiSensor.flange_b)
  connect(multiSensor.flange_a, springDamper.flange_b)
end ElasticBearing;


First example: simple drive train. The drive train consists of a motor inertia which is driven by
a sine-wave motor torque. Via a gearbox the rotational energy is
transmitted to a load inertia. Elasticity in the gearbox is modeled
by a spring element. A linear damper is used to model the
damping in the gearbox bearing.

within Modelica.Mechanics.Rotational.Examples;
model First "First example: simple drive train"
  extends Modelica.Icons.Example;
  parameter SI.Torque amplitude=10
    "Amplitude of driving torque";
  parameter SI.Frequency f=5 "Frequency of driving torque";
  parameter SI.Inertia Jmotor(min=0) = 0.1 "Motor inertia";
  parameter SI.Inertia Jload(min=0) = 2 "Load inertia";
  parameter Real ratio=10 "Gear ratio";
  parameter Real damping=10 "Damping in bearing of gear";

  Rotational.Components.Fixed fixed
  Rotational.Sources.Torque torque(useSupport=true)
  Rotational.Components.Inertia inertia1(J=Jmotor)
  Rotational.Components.IdealGear idealGear(ratio=ratio, useSupport=true)
  Rotational.Components.Inertia inertia2(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Rotational.Components.Spring spring(c=1.e4, phi_rel(fixed=true))
  Rotational.Components.Inertia inertia3(J=Jload, w(fixed=true, start=0))
  Rotational.Components.Damper damper(d=damping)
  Modelica.Blocks.Sources.Sine sine(amplitude=amplitude, f=f)
equation
  connect(inertia1.flange_b, idealGear.flange_a)
  connect(idealGear.flange_b, inertia2.flange_a)
  connect(inertia2.flange_b, spring.flange_a)
  connect(spring.flange_b, inertia3.flange_a)
  connect(damper.flange_a, inertia2.flange_b)
  connect(damper.flange_b, fixed.flange)
  connect(sine.y, torque.tau)
  connect(torque.support, fixed.flange)
  connect(idealGear.support, fixed.flange)
  connect(torque.flange, inertia1.flange_a)
end First;


First example: simple drive train with grounded elements. The drive train consists of a motor inertia which is driven by
a sine-wave motor torque. Via a gearbox the rotational energy is
transmitted to a load inertia. Elasticity in the gearbox is modeled
by a spring element. A linear damper is used to model the
damping in the gearbox bearing.

within Modelica.Mechanics.Rotational.Examples;
model FirstGrounded
  "First example: simple drive train with grounded elements"
  extends Modelica.Icons.Example;
  parameter SI.Torque amplitude=10
    "Amplitude of driving torque";
  parameter SI.Frequency f=5 "Frequency of driving torque";
  parameter SI.Inertia Jmotor(min=0) = 0.1 "Motor inertia";
  parameter SI.Inertia Jload(min=0) = 2 "Load inertia";
  parameter Real ratio=10 "Gear ratio";
  parameter Real damping=10 "Damping in bearing of gear";

  Rotational.Components.Fixed fixed
  Rotational.Sources.Torque torque(useSupport=false)
  Rotational.Components.Inertia inertia1(J=Jmotor)
  Rotational.Components.IdealGear idealGear(ratio=ratio, useSupport=false)
  Rotational.Components.Inertia inertia2(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Rotational.Components.Spring spring(c=1.e4, phi_rel(fixed=true))
  Rotational.Components.Inertia inertia3(J=Jload, w(fixed=true, start=0))
  Rotational.Components.Damper damper(d=damping)
  Modelica.Blocks.Sources.Sine sine(amplitude=amplitude, f=f)
equation
  connect(inertia1.flange_b, idealGear.flange_a)
  connect(idealGear.flange_b, inertia2.flange_a)
  connect(inertia2.flange_b, spring.flange_a)
  connect(spring.flange_b, inertia3.flange_a)
  connect(damper.flange_a, inertia2.flange_b)
  connect(damper.flange_b, fixed.flange)
  connect(sine.y, torque.tau)
  connect(torque.flange, inertia1.flange_a)
end FirstGrounded;


Drive train with clutch and brake. This drive train contains a frictional clutch and a brake.
Simulate the system for 1 second using the following initial
values (defined already in the model):

within Modelica.Mechanics.Rotational.Examples;
model Friction "Drive train with clutch and brake"
  import Modelica.Constants.pi;
  extends Modelica.Icons.Example;
  parameter SI.Time startTime=0.5 "Start time of step";
  output SI.Torque tMotor=torque.tau "Driving torque of inertia3";
  output SI.Torque tClutch=clutch.tau "Friction torque of clutch";
  output SI.Torque tBrake=brake.tau "Friction torque of brake";
  output SI.Torque tSpring=spring.tau "Spring torque";

  Rotational.Sources.Torque torque(useSupport=true)
  Rotational.Components.Inertia inertia3(
    J=1,
    phi(
      start=0,
      fixed=true,
      displayUnit="deg"),
    w(start=100,
      fixed=true,
      displayUnit="rad/s"))
  Rotational.Components.Clutch clutch(fn_max=160)
  Rotational.Components.Inertia inertia2(
    J=0.05,
    phi(start=0, fixed=true),
    w(start=90, fixed=true))
  Rotational.Components.SpringDamper spring(c=160, d=1)
  Rotational.Components.Inertia inertia1(
    J=1,
    phi(start=0, fixed=true),
    w(start=90, fixed=true))
  Rotational.Components.Brake brake(fn_max=1600, useSupport=true)
  Modelica.Blocks.Sources.Constant const(k=1)
  Modelica.Blocks.Sources.Step step(startTime=startTime)
  Modelica.Blocks.Sources.Step step2(
    height=-1,
    offset=1,
    startTime=startTime)
  Modelica.Blocks.Sources.Sine sine(amplitude=200, f=50/pi)
  Modelica.Blocks.Math.Product product
  Rotational.Components.Fixed fixed
equation
  connect(torque.flange, inertia3.flange_a)
  connect(inertia3.flange_b, clutch.flange_a)
  connect(clutch.flange_b, inertia2.flange_a)
  connect(inertia2.flange_b, spring.flange_a)
  connect(spring.flange_b, brake.flange_a)
  connect(brake.flange_b, inertia1.flange_a)
  connect(sine.y, product.u1)
  connect(step2.y, product.u2)
  connect(product.y, torque.tau)
  connect(const.y, clutch.f_normalized)
  connect(step.y, brake.f_normalized)
  connect(torque.support, fixed.flange)
  connect(brake.support, fixed.flange)
end Friction;


Example to demonstrate variants to generate FMUs (Functional Mock-up Units). This example demonstrates how to generate an input/output block (e.g. in form of an
FMU - Functional Mock-up Unit) from various Rotational components.
The goal is to export such an input/output block from Modelica and import
it in another modeling environment. The essential issue is that before
exporting it must be known in which way the component is utilized in the
target environment. Depending on the target usage, different flange variables
need to be in the interface with either input or output causality.
Note, this example model can be used to test the FMU export/import of a Modelica tool.
Just export the components marked in the icons as \"toFMU\" as FMUs and import
them back. The models should then still work and give the same results as a
pure Modelica model.

within Modelica.Mechanics.Rotational.Examples;
model GenerationOfFMUs
  "Example to demonstrate variants to generate FMUs (Functional Mock-up Units)"
  extends Modelica.Icons.Example;

  Modelica.Blocks.Sources.Sine sine1(f=2, amplitude=10)
  Modelica.Mechanics.Rotational.Examples.Utilities.DirectInertia
    directInertia(J=1.1)
  Modelica.Mechanics.Rotational.Examples.Utilities.InverseInertia
    inverseInertia(J=2.2)
  Modelica.Mechanics.Rotational.Examples.Utilities.SpringDamper
    springDamper(c=1e4, d=100)
  Modelica.Mechanics.Rotational.Components.Inertia inertia2a(
    J=1.1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Mechanics.Rotational.Sources.Torque torque2
  Components.TorqueToAngleAdaptor
    torqueToAngle2a(use_a=false)
  Modelica.Mechanics.Rotational.Components.Inertia inertia2b(
    J=2.2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.TorqueToAngleAdaptor
    torqueToAngle2b(use_a=false)
  Modelica.Mechanics.Rotational.Examples.Utilities.Spring spring(c=1e4)
  Modelica.Mechanics.Rotational.Components.Inertia inertia3a(
    J=1.1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Mechanics.Rotational.Sources.Torque   force3
  Components.TorqueToAngleAdaptor
    torqueToAngle3a(use_w=false, use_a=false)
  Modelica.Mechanics.Rotational.Components.Inertia inertia3b(
    J=2.2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.TorqueToAngleAdaptor
    torqueToAngle3b(use_w=false, use_a=false)
equation
  connect(sine1.y, directInertia.tauDrive)
  connect(directInertia.phi, inverseInertia.phi)
  connect(directInertia.w, inverseInertia.w)
  connect(directInertia.a, inverseInertia.a)
  connect(inverseInertia.tau, directInertia.tau)
  connect(sine1.y, torque2.tau)
  connect(sine1.y, force3.tau)
  connect(torqueToAngle2b.flange, inertia2b.flange_a)
  connect(inertia2a.flange_b, torqueToAngle2a.flange)
  connect(torque2.flange, inertia2a.flange_a)
  connect(inertia3a.flange_b, torqueToAngle3a.flange)
  connect(force3.flange, inertia3a.flange_a)
  connect(torqueToAngle3b.flange, inertia3b.flange_a)
  connect(torqueToAngle2a.phi, springDamper.phi1)
  connect(torqueToAngle2a.w, springDamper.w1)
  connect(torqueToAngle2a.tau, springDamper.tau1)
  connect(springDamper.tau2, torqueToAngle2b.tau)
  connect(springDamper.phi2, torqueToAngle2b.phi)
  connect(springDamper.w2, torqueToAngle2b.w)
  connect(torqueToAngle3a.phi, spring.phi1)
  connect(torqueToAngle3a.tau, spring.tau1)
  connect(spring.phi2, torqueToAngle3b.phi)
  connect(spring.tau2, torqueToAngle3b.tau)
end GenerationOfFMUs;


Demonstrate the modeling of heat losses. This model demonstrates how to model the dissipated power of a drive train,
by enabling the heatPort of all components and connecting these heatPorts via
a convection element to the environment. The total heat flow generated by the
elements of the drive train and transported to the environment
is present in variable convection.fluid.

within Modelica.Mechanics.Rotational.Examples;
model HeatLosses "Demonstrate the modeling of heat losses"
  extends Modelica.Icons.Example;
  Blocks.Sources.Sine sine(f=5, amplitude=20)
  Sources.Torque torque
  Components.Inertia inertia1(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.Damper damper(useHeatPort=true, d=10)
  Components.Fixed fixed
  Thermal.HeatTransfer.Components.Convection convection
  Thermal.HeatTransfer.Celsius.FixedTemperature TAmbient(T=25)
    "Ambient temperature"
  Blocks.Sources.Constant const(k=20)
  Components.SpringDamper springDamper(
    c=1e4,
    d=20,
    useHeatPort=true)
  Components.Inertia inertia2(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.ElastoBacklash elastoBacklash(
    c=1e5,
    d=100,
    useHeatPort=true,
    b(displayUnit="rad") = 0.001)
  Components.Inertia inertia3(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.BearingFriction bearingFriction(useHeatPort=true)
  Components.Spring spring3(c=1e4)
  Components.Inertia inertia4(
    J=2,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Components.LossyGear lossyGear(
    ratio=2,
    lossTable=[0, 0.8, 0.8, 1, 1; 1, 0.7, 0.7, 2, 2],
    useHeatPort=true)
  Components.Clutch clutch(
    useHeatPort=true,
    fn_max=10,
    phi_rel(fixed=true),
    w_rel(fixed=true))
  Components.Inertia inertia5(J=2)
  Blocks.Sources.Sine sine2(f=0.2, amplitude=1)
  Components.Inertia inertia6(J=2)
  Components.OneWayClutch oneWayClutch(
    phi_rel(fixed=true),
    w_rel(fixed=true),
    startForward(fixed=true),
    stuck(fixed=true),
    fn_max=1,
    useHeatPort=true)
  Components.Brake brake(fn_max=2, useHeatPort=true)
equation

  connect(sine.y, torque.tau)
  connect(torque.flange, inertia1.flange_a)
  connect(inertia1.flange_b, damper.flange_b)
  connect(damper.flange_a, fixed.flange)
  connect(damper.heatPort, convection.solid)
  connect(TAmbient.port, convection.fluid)
  connect(const.y, convection.Gc)
  connect(inertia1.flange_b, springDamper.flange_a)
  connect(springDamper.heatPort, convection.solid)
  connect(springDamper.flange_b, inertia2.flange_a)
  connect(elastoBacklash.flange_a, inertia2.flange_b)
  connect(elastoBacklash.heatPort, convection.solid)
  connect(elastoBacklash.flange_b, inertia3.flange_a)
  connect(inertia3.flange_b, bearingFriction.flange_a)
  connect(convection.solid, bearingFriction.heatPort)
  connect(spring3.flange_b, inertia4.flange_a)
  connect(bearingFriction.flange_b, spring3.flange_a)
  connect(inertia4.flange_b, lossyGear.flange_a)
  connect(lossyGear.heatPort, convection.solid)

  connect(lossyGear.flange_b, clutch.flange_a)
  connect(clutch.heatPort, convection.solid)

  connect(clutch.flange_b, inertia5.flange_a)
  connect(sine2.y, clutch.f_normalized)
  connect(inertia5.flange_b, oneWayClutch.flange_a)
  connect(oneWayClutch.flange_b, inertia6.flange_a)
  connect(sine2.y, oneWayClutch.f_normalized)
  connect(inertia6.flange_b, brake.flange_a)
  connect(sine2.y, brake.f_normalized)
  connect(oneWayClutch.heatPort, convection.solid)

  connect(brake.heatPort, convection.solid)
end HeatLosses;


Example to show that gear efficiency may lead to stuck motion. This model contains two inertias which are connected by an ideal
gear where the friction between the teeth of the gear is modeled in
a physical meaningful way (friction may lead to stuck mode which
locks the motion of the gear). The friction is defined by an
efficiency factor (= 0.5) for forward and backward driving condition leading
to a torque dependent friction loss. Simulate for about 0.5 seconds.
The friction in the gear will take all modes
(forward and backward rolling, as well as stuck).

within Modelica.Mechanics.Rotational.Examples;
model LossyGearDemo1
  "Example to show that gear efficiency may lead to stuck motion"
  extends Modelica.Icons.Example;
  SI.Power PowerLoss=gear.flange_a.tau*der(gear.flange_a.phi) + gear.flange_b.tau
      *der(gear.flange_b.phi) "Power lost in the gear";
  Rotational.Components.LossyGear gear(
    ratio=2,
    lossTable=[0, 0.5, 0.5, 0, 0],
    useSupport=true)
  Rotational.Components.Inertia Inertia1(J=1)
  Rotational.Components.Inertia Inertia2(
    J=1.5,
    phi(fixed=true, start=0, nominal=0.001),
    w(fixed=true, start=0, nominal=0.01))
  Rotational.Sources.Torque torque1(useSupport=true)
  Rotational.Sources.Torque torque2(useSupport=true)
  Modelica.Blocks.Sources.Sine DriveSine(amplitude=10, f=1)
  Modelica.Blocks.Sources.Ramp load(
    height=5,
    duration=2,
    offset=-10)
  Rotational.Components.Fixed fixed
equation
  connect(Inertia1.flange_b, gear.flange_a)
  connect(gear.flange_b, Inertia2.flange_a)
  connect(torque1.flange, Inertia1.flange_a)
  connect(torque2.flange, Inertia2.flange_b)
  connect(DriveSine.y, torque1.tau)
  connect(load.y, torque2.tau)
  connect(fixed.flange, gear.support)
  connect(fixed.flange, torque1.support)
  connect(fixed.flange, torque2.support)
end LossyGearDemo1;


Example to show combination of LossyGear and BearingFriction. This model contains bearing friction and gear friction (= efficiency).
If both friction models are stuck, there is no unique solution.
Still a reliable Modelica simulator should
be able to handle this situation.

within Modelica.Mechanics.Rotational.Examples;
model LossyGearDemo2
  "Example to show combination of LossyGear and BearingFriction"
  extends Modelica.Icons.Example;
  SI.Power PowerLoss=gear.flange_a.tau*der(gear.flange_a.phi) + gear.flange_b.tau
      *der(gear.flange_b.phi) "Power lost in the gear";

  Rotational.Components.LossyGear gear(
    ratio=2,
    lossTable=[0, 0.5, 0.5, 0, 0],
    useSupport=true)
  Rotational.Components.Inertia Inertia1(J=1)
  Rotational.Components.Inertia Inertia2(
    J=1.5,
    phi(fixed=true, start=0, nominal=1e-4),
    w(fixed=true, start=0, nominal=0.001))
  Rotational.Sources.Torque torque1(useSupport=true)
  Rotational.Sources.Torque torque2(useSupport=true)
  Modelica.Blocks.Sources.Sine DriveSine(amplitude=10, f=1)
  Modelica.Blocks.Sources.Ramp load(
    height=5,
    duration=2,
    offset=-10)
  Rotational.Components.BearingFriction bearingFriction(tau_pos=[0, 0.5; 1,
        1], useSupport=true)
  Rotational.Components.Fixed fixed
equation
  connect(torque2.flange, Inertia2.flange_b)
  connect(Inertia2.flange_a, gear.flange_b)
  connect(gear.flange_a, Inertia1.flange_b)
  connect(Inertia1.flange_a, bearingFriction.flange_b)
  connect(bearingFriction.flange_a, torque1.flange)
  connect(DriveSine.y, torque1.tau)
  connect(load.y, torque2.tau)
  connect(gear.support, fixed.flange)
  connect(fixed.flange, torque2.support)
  connect(fixed.flange, bearingFriction.support)
  connect(torque1.support, fixed.flange)
end LossyGearDemo2;


within Modelica.Mechanics.Rotational.Examples;
model LossyGearDemo3
  "Example that failed in the previous version of the LossyGear version"
  extends Modelica.Icons.Example;

  Modelica.Mechanics.Rotational.Components.LossyGear gear(
    ratio=1,
    lossTable=[0, 0.25, 0.25, 0.625, 2.5],
    useSupport=false)
  Modelica.Mechanics.Rotational.Components.Inertia Inertia1(w(start=10), J=
        0.001)
  Modelica.Mechanics.Rotational.Sources.Torque torque1(useSupport=false)
  Modelica.Mechanics.Rotational.Sources.Torque torque2(useSupport=false)
  Modelica.Blocks.Sources.Step step(height=0)
  Modelica.Blocks.Sources.Step step1(
    startTime=0.5,
    height=1,
    offset=0)
  Modelica.Mechanics.Rotational.Components.Inertia Inertia2(
    J=0.001,
    phi(fixed=true, start=0),
    w(start=10, fixed=true))
equation
  connect(Inertia1.flange_b, gear.flange_a)
  connect(torque1.flange, Inertia1.flange_a)
  connect(step.y, torque1.tau)
  connect(gear.flange_b, Inertia2.flange_a)
  connect(Inertia2.flange_b, torque2.flange)
  connect(step1.y, torque2.tau)
end LossyGearDemo3;


Drive train with actively engaged one-way clutch. The drive train consists of a one-way clutch and driving and driven inertias.
The one-way clutch is engaged periodically thus forcing both the inertias to
match their rotational velocity.
When disengaged, only the freewheel functionality of the one-way clutch is
available and is active as long as the relative angular velocity w_rel becomes zero.

within Modelica.Mechanics.Rotational.Examples;
model OneWayClutch "Drive train with actively engaged one-way clutch"
  extends Modelica.Icons.Example;

  Modelica.Mechanics.Rotational.Components.Inertia inertiaIn(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=-0.5))
  Modelica.Mechanics.Rotational.Components.Inertia inertiaOut(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Mechanics.Rotational.Components.OneWayClutch oneWayClutch(
    peak=25,
    fn_max=3,
    startForward(fixed=true),
    stuck(fixed=true))
  Modelica.Mechanics.Rotational.Sources.Torque torque
  Modelica.Blocks.Sources.Sine signalTorque(
    amplitude=10,
    f=3)
  Modelica.Blocks.Sources.Pulse signalEngagement(
    amplitude=1,
    width=50,
    period=1.3,
    startTime=0.3)
equation
  connect(torque.flange, inertiaIn.flange_a)
  connect(signalTorque.y, torque.tau)
  connect(inertiaIn.flange_b, oneWayClutch.flange_a)
  connect(oneWayClutch.flange_b, inertiaOut.flange_a)
  connect(signalEngagement.y, oneWayClutch.f_normalized)
end OneWayClutch;


Drive train with disengaged one-way clutch. The drive train consists of a one-way clutch and driving and driven inertias.
To demonstrate the behavior of the clutch's freewheel only, the clutch stays
disengaged for all the time.
The sine torque is applied on the driving inertia forcing inertia's speed change.
On the driven side there is applied constant load torque only.

within Modelica.Mechanics.Rotational.Examples;
model OneWayClutchDisengaged "Drive train with disengaged one-way clutch"
  extends Modelica.Icons.Example;

  Modelica.Mechanics.Rotational.Components.Inertia inertiaIn(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=-0.5))
  Modelica.Mechanics.Rotational.Components.Inertia inertiaOut(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Mechanics.Rotational.Components.OneWayClutch oneWayClutch(
    peak=25,
    fn_max=3,
    startForward(fixed=true),
    stuck(fixed=true))
  Modelica.Mechanics.Rotational.Sources.Torque torque
  Modelica.Mechanics.Rotational.Sources.ConstantTorque torqueLoad(tau_constant=-0.3)
  Modelica.Blocks.Sources.Sine signalTorque(
    amplitude=10,
    offset=-torqueLoad.tau_constant,
    f=2)
  Modelica.Blocks.Sources.Constant signalEngagement(k=0)
equation
  connect(torque.flange, inertiaIn.flange_a)
  connect(signalTorque.y, torque.tau)
  connect(inertiaIn.flange_b, oneWayClutch.flange_a)
  connect(oneWayClutch.flange_b, inertiaOut.flange_a)
  connect(signalEngagement.y, oneWayClutch.f_normalized)
  connect(inertiaOut.flange_b, torqueLoad.flange)
end OneWayClutchDisengaged;


within Modelica.Mechanics.Rotational;
package Examples "Demonstration examples of the components of this package"

  extends Modelica.Icons.ExamplesPackage;
end Examples;


Demonstrate coupling Rotational - Translational. This model demonstrates the coupling between rotational and translational components:

A torque (step) accelerates both the inertia (of the wheel) and the mass (of the vehicle).

Due to a speed dependent force (like a driving resistance), we find an equilibrium at 5 m/s after approx. 5 s.

within Modelica.Mechanics.Rotational.Examples;
model RollingWheel "Demonstrate coupling Rotational - Translational"
  extends Modelica.Icons.Example;
  Rotational.Components.IdealRollingWheel idealRollingWheel(radius=1)
  Rotational.Components.Inertia inertia(
    J=1,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Rotational.Sources.TorqueStep torqueStep(
    stepTorque=10,
    offsetTorque=0,
    startTime=0.1,
    useSupport=false)
  Translational.Components.Mass mass(L=0, m=1)
  Translational.Sources.QuadraticSpeedDependentForce
    quadraticSpeedDependentForce(
    f_nominal=-10,
    ForceDirection=false,
    v_nominal=5)
equation

  connect(torqueStep.flange, inertia.flange_a)
  connect(inertia.flange_b, idealRollingWheel.flangeR)
  connect(idealRollingWheel.flangeT, mass.flange_a)
  connect(quadraticSpeedDependentForce.flange, mass.flange_b)
end RollingWheel;


Simple Gearshift. This model shows how an automatic gear shift is built up from a planetary gear, a brake and a clutch.

within Modelica.Mechanics.Rotational.Examples;
model SimpleGearShift "Simple Gearshift"
  extends Modelica.Icons.Example;
  output SI.AngularVelocity wEngine=engine.w
    "Speed of engine";
  output SI.AngularVelocity wLoad=load.w "Speed of load";
  output Real gearRatio=wLoad/max(wEngine, 1E-6) "Gear ratio load/engine";
  Modelica.Mechanics.Rotational.Sources.TorqueStep torqueStep(
    offsetTorque=0,
    startTime=0.5,
    stepTorque=20)
  Modelica.Mechanics.Rotational.Components.Inertia engine(J=1)
  Modelica.Mechanics.Rotational.Components.IdealPlanetary idealPlanetary(
      ratio=75/50)
  Modelica.Mechanics.Rotational.Components.Inertia load(
    J=10,
    phi(fixed=true, start=0),
    w(fixed=true, start=0))
  Modelica.Mechanics.Rotational.Sources.QuadraticSpeedDependentTorque
    quadraticSpeedDependentTorque(w_nominal(displayUnit="rpm")=
      10.471975511966, tau_nominal=-20)
  Modelica.Mechanics.Rotational.Components.Clutch clutch(
    cgeo=2,
    fn_max=100,
    phi_rel(fixed=true),
    w_rel(fixed=true))
  Modelica.Mechanics.Rotational.Components.Brake brake(cgeo=2, fn_max=100)
  Modelica.Blocks.Math.Feedback feedback
  Modelica.Blocks.Sources.Constant const1(k=1)
  Modelica.Blocks.Sources.Ramp ramp(
    height=1,
    offset=0,
    startTime=2,
    duration=0.1)
equation
  connect(torqueStep.flange, engine.flange_a)
  connect(quadraticSpeedDependentTorque.flange, load.flange_b)
  connect(feedback.y, brake.f_normalized)
  connect(engine.flange_b, idealPlanetary.sun)
  connect(idealPlanetary.sun, clutch.flange_a)
  connect(idealPlanetary.ring, clutch.flange_b)
  connect(idealPlanetary.ring, brake.flange_a)
  connect(idealPlanetary.carrier, load.flange_a)
  connect(const1.y, feedback.u1)
  connect(feedback.u2, clutch.f_normalized)
  connect(ramp.y, clutch.f_normalized)
end SimpleGearShift;


Input/output block of a direct inertia model. A rotational component with pure signal interface which can be applied for
a FMU (Functional Mock-up Unit)
exchange.
The input torque tauDrive is applied on one side of a rotational
component with inertia whereby the input torque tau is applied
on the other side of it.

within Modelica.Mechanics.Rotational.Examples.Utilities;
model DirectInertia "Input/output block of a direct inertia model"
  extends Modelica.Blocks.Icons.Block;
  parameter SI.Inertia J(min=0)=1 "Inertia";
  Modelica.Mechanics.Rotational.Components.Inertia inertia(
    J=J,
    phi(start=0, fixed=true),
    w(start=0, fixed=true))
  Modelica.Mechanics.Rotational.Sources.Torque torqueSource
  Modelica.Blocks.Interfaces.RealInput tauDrive(unit="N.m")
    "Accelerating torque acting at flange (= -flange.tau)"
  Components.TorqueToAngleAdaptor
    torqueToAngle
  Modelica.Blocks.Interfaces.RealOutput phi(unit="rad")
    "Inertia moves with angle phi due to torque tau"
  Modelica.Blocks.Interfaces.RealOutput w(unit="rad/s")
    "Inertia moves with speed w due to torque tau"
  Modelica.Blocks.Interfaces.RealOutput a(unit="rad/s2")
    "Inertia moves with acceleration a due to torque tau"
  Modelica.Blocks.Interfaces.RealInput tau(unit="N.m")
    "Torque to drive the inertia"
equation
  connect(tauDrive, torqueSource.tau)
  connect(torqueSource.flange, inertia.flange_a)
  connect(inertia.flange_b, torqueToAngle.flange)
  connect(torqueToAngle.phi, phi)
  connect(torqueToAngle.w, w)
  connect(torqueToAngle.a, a)
  connect(torqueToAngle.tau, tau)
end DirectInertia;


Input/output block of an inverse inertia model. A rotational component with pure signal interface which can be applied for
a FMU (Functional Mock-up Unit)
exchange.
Based on the kinematic inputs applied on a component with inertia
the output torque tau is returned.

within Modelica.Mechanics.Rotational.Examples.Utilities;
model InverseInertia "Input/output block of an inverse inertia model"
  extends Modelica.Blocks.Icons.Block;
  parameter SI.Inertia J=1 "Inertia";
  Modelica.Mechanics.Rotational.Components.Inertia inertia(
    J=J,
    phi(start=0),
    w(start=0))
  Components.AngleToTorqueAdaptor
    angleToTorque
  Modelica.Blocks.Interfaces.RealInput phi(unit="rad")
    "Angle to drive the inertia"
  Modelica.Blocks.Interfaces.RealInput w(unit="rad/s")
    "Speed to drive the inertia"
  Modelica.Blocks.Interfaces.RealInput a(unit="rad/s2")
    "Acceleration to drive the inertia"
  Modelica.Blocks.Interfaces.RealOutput tau(unit="N.m")
    "Torque needed to drive the flange according to phi, w, a"
equation

  connect(angleToTorque.flange, inertia.flange_a)
  connect(phi, angleToTorque.phi)
  connect(w, angleToTorque.w)
  connect(a, angleToTorque.a)
  connect(tau, angleToTorque.tau)
end InverseInertia;


within Modelica.Mechanics.Rotational.Examples;
package Utilities "Utility classes used by rotational example models"
  extends Modelica.Icons.UtilitiesPackage;
end Utilities;


Input/output block of a spring model. A linear 1D rotational spring with pure signal
interface which can be applied for
a FMU (Functional Mock-up Unit)
exchange.

within Modelica.Mechanics.Rotational.Examples.Utilities;
model Spring "Input/output block of a spring model"
  extends Modelica.Blocks.Icons.Block;
  parameter SI.RotationalSpringConstant c=1e4
    "Spring constant";
  parameter SI.Angle phi_rel0=0
    "Unstretched spring angle";

  Components.AngleToTorqueAdaptor
    angleToTorque1(use_w=false, use_a=false)
  Modelica.Blocks.Interfaces.RealInput phi1(unit="rad")
    "Angle of left flange of force element"
  Modelica.Blocks.Interfaces.RealOutput tau1(unit="N.m")
    "Torque generated by the force element"
  Modelica.Mechanics.Rotational.Components.Spring spring(c=c,
      phi_rel0=phi_rel0)
  Modelica.Blocks.Interfaces.RealInput phi2(unit="rad")
    "Angle of right flange of force element"
  Modelica.Blocks.Interfaces.RealOutput tau2(unit="N.m")
    "Torque generated by the force element"
  Components.AngleToTorqueAdaptor
    angleToTorque2(use_w=false, use_a=false)
equation

  connect(angleToTorque1.flange, spring.flange_a)
  connect(spring.flange_b, angleToTorque2.flange)
  connect(phi1, angleToTorque1.phi)
  connect(tau1, angleToTorque1.tau)
  connect(angleToTorque2.phi, phi2)
  connect(angleToTorque2.tau, tau2)
end Spring;