Search code examples
modelica

How to override default equations?


All the derived classes should inherit some default equations from their base class. When the default equation is not valid for a derived class then it should redeclare it. This minimalistic example below is somewhat silly.

Am I on the right track to achieve the above goal? Or is there a better way to express this in the Modelica language?

package Pkg

  partial class Equations
    Real x;
  end Equations;

  class DefaultEquations
    extends Equations;
    equation
      x = 0.0;
  end DefaultEquations;

  class Base
    replaceable class T = DefaultEquations;
    replaceable T equations extends Equations;
  end Base;

end Pkg;

model TestEquations

  import Pkg.*;

  class CustomEquation
    extends Equations;
    equation
      x = 3;
  end CustomEquation;

  class CustomizedClass
    extends Base(redeclare class T = CustomEquation);
  end CustomizedClass;

  CustomizedClass customized;

end TestEquations;

Solution

  • If I understand your goal, there is a very simple way to accomplish this. Consider this alternative:

    package Pkg
      partial class Equations
        Real x;
      end Equations;
    
      class DefaultEquations
        extends Equations(x=0);
      end DefaultEquations;
    
      class Base
        replaceable class T = DefaultEquations;
        replaceable T equations extends Equations;
      end Base;
    end Pkg;
    
    model TestEquations
      import Pkg.*;
    
      class CustomEquation
        extends Equations(x=3);
      end CustomEquation;
    
      class CustomizedClass
        extends Base(redeclare class T = CustomEquation);
      end CustomizedClass;
    
      CustomizedClass customized;
    end TestEquations;
    

    But you can simplify it ever further if you are willing to eliminate all the redeclarations:

    package Pkg
      class Equations
        Real x;
      end Equations;
    
      class Base
        Equations equations;
      end Base;
    end Pkg;
    
    model TestEquations
      import Pkg.*;
    
      class CustomizedClass
        extends Base(equations(x=3));
      end CustomizedClass;
    
      CustomizedClass customized;
    end TestEquations;
    

    ...and yet further if you don't need all the layers of inheritance:

    package Pkg
      class Equations
        Real x;
      end Equations;
    end Pkg;
    
    model TestEquations
      import Pkg.*;
    
      Equations equations(x=3);
    end TestEquations;
    

    These modifications (the x=3 parts) work the same for variables as they do for parameters. So you can take the "initialization equation" for any variable (the part that appears after the variable declaration) and override. The limitation of this approach is that it doesn't let you override general equations, just equations that solve for a single variable explicitly.

    Update (May 2nd, 2012)

    If you need to handle general equations (including the possibility to introduce internal state), then you also have to deal with the issue of "balancing" the equations. That is to say that Modelica (v 3+) includes certain semantics on what is considered a partial (non-instantiable) model vs. a non-partial model. The point is, you need to give the compiler enough information about what will be computed internally and what will be provided externally in order for it to figure out if the definition is really partial or not.

    In general, you should define a partial model/block to describe the potential external interactions and then use replaceable components to substitute the equations in. Based on your original example, it might look something like this:

    package Pkg
      partial block Equations
        input Real y; // Input for any information it will need in the calculation
        output Real x; // Output to indicate something the model will compute
      end Equations;
    
      block DefaultEquations
        extends Equations;
      equation
        x = 0;
      end DefaultEquations;
    
      class Base
        replaceable DefaultEquations equations constrainedby Equations;
      end Base;
    end Pkg;
    
    model TestEquations
      import Pkg.*;
    
      block CustomEquation
        extends Equations
      equation
        x*x + y*y = 25.0; // example of non explicit equation
      end CustomEquation;
    
      class CustomizedClass
        extends Base(redeclare CustomEquation equations);
      end CustomizedClass;
    
      CustomizedClass customized;
    end TestEquations;
    

    I should add that (at least in your example above), you could completely eliminate Base and CustomizedClass. But I left them in because I assume they somehow map to your actual problem. Finally, I never use class in actual code (I try to be more specific) so I changed some of your definitions to block definitions.