Regularization in Modelica

226 Views Asked by At

I wonder if other regularization techniques (e.g. hyperbolic tangent) rather than smoothStep function exist in Modelica. I work on a complex code that I used smoothStep several times to avoid chattering in my model; however, I have seen some side effects of this function in the results of my model and I'd rather to adopt other techniques. For more clarification, I just included a part of my code as follows:

model MassFlow
  import Modelica.SIunits.MassFlowRate;
  import Modelica.Media.Common.smoothStep;
  Real c1[15];
  parameter MassFlowRate mDotSource[15]={0.00,-0.10,0.10,1.00,2.00,0.00,0.10,0.01,0.09,-0.20,-0.30,0.00,-0.10,-0.03,0.06};

  parameter MassFlowRate smallFlow = 0.01 "Small flow value used to avoid chattering problems";
equation 
  c1 = smoothStep(mDotSource, 1, 0, smallFlow);
end MassFlow;

Therefore, the objective is to have more precise approximation in regularization of mDotSource. I would appreciate if you could help me with it.

Based on the helpful comment by @matth, I used spliceFunction. In order to return 0 when negative values are input, I modified the spliceFunction as follows:

function spliceFun "Spline interpolation of two functions"
  extends Modelica.Icons.Function;
  input Real pos "Returned value for x-deltax >= 0";
  input Real neg "Returned value for x+deltax <= 0";
  input Real x "Function argument";
  input Real deltax=1 "Region around x with spline interpolation";
  output Real out;
protected 
  Real scaledX;
  Real scaledX1;
  Real y;
algorithm 
  scaledX1 := x/deltax;
  scaledX := scaledX1*Modelica.Math.asin(1);
  if scaledX1 <= -0.00000001 then
    y := 0;
  elseif scaledX1 >= 0.999999 then
    y := 1;
  else
    y := (Modelica.Math.tanh(Modelica.Math.tan(scaledX)) + 1)/2;
  end if;
  out := pos*y + (1 - y)*neg;
  annotation (derivative=spliceFun_der);
end spliceFun;

As seen, only "if statement" when scaledX1 <= -0.00000001 is changed compared to the original spliceFunction. It works properly on the sample input data(mDotSource):

model MassFlow
  import Modelica.SIunits.MassFlowRate;

  parameter MassFlowRate mDotSource[15]={0.00,-0.10,0.20,1.00,2.00,0.00,0.10,0.01,0.09,-0.20,-2.0,0.00,-0.10,-0.03,-0.8};
  Real c1[15];

equation 
  c1 = SHCLibrary.Tests.spliceFun(1,0,mDotSource,1);

end MassFlow;

However, when I tried to apply the modified spliceFunction (spliceFun) in my complex code, the simulation running is endless. It neither stops nor gives an error. I have to add here that in my complex code, I use 6 times the spliceFun and when I replace 5 of them with smoothStep function and use only 1 spliceFun, it works, but I do not receive the results with the accuracy that I expect.
Would you please advise on this issue?

1

There are 1 best solutions below

0
On

You can use some other regularization than spliceFun but there are two requirements:

  • Smoothness at the edges
  • Correct derivative

If we look at your function we see that scaledX1=0 gives y=0 and scaledX1=1 gives y=1; that's fine but if we look at scaledX in the regularization branch we have:

(Modelica.Math.tanh(Modelica.Math.tan(scaledX1*asin(1))) + 1)/2;

which for scaledX1=0 gives y=0.5 and for scaledX1=1 gives y=1; not regular at all, and the slope at 0 is not 0. Basically it seems you have a shift and you wanted something like:

scaledX := (scaledX1-0.5)*Modelica.Math.asin(1);
...
y:= Modelica.Math.tan(scaledX)) + 1)/2;

so that scaledX1=0 gives scaledX=-0.5*Modelica.Math.asin(1) which gives y=0, but unfortunaley not with zero derivative at edges. With tanh it becomes messier, but there's still the requirement that the limit for scaledX=0 and 1 should match up.

Was the idea to use

   scaledX := (2*scaledX1-1)*Modelica.Math.asin(1);
   ...
     y := (Modelica.Math.tanh(Modelica.Math.tan(scaledX)) + 1)/2;

as if the edges were at -1 and 1 instead of 0 and 1? This variant seems to go from 0 to 1 and being smooth at the transitions.

The second part is easy to correct by writing: annotation (smoothOrder=2); and not trying to write a derivative.