Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot set parameter in a class being extended #47

Closed
christiankral opened this issue Jul 21, 2021 · 15 comments
Closed

Cannot set parameter in a class being extended #47

christiankral opened this issue Jul 21, 2021 · 15 comments
Assignees

Comments

@christiankral
Copy link
Contributor

christiankral commented Jul 21, 2021

Consider the following example and store it as Test.mo:

package Test

    model Example
        extends Test.Data;
        Real x(start = c);
    equation
        if dyn == 1 then
            der(x) = -c * x;
        else
            x = c;
        end if;
    end Example;
  
    model Data
        parameter Integer dyn = 1;
        parameter Real c = 1;
    equation
    end Data;
  
end Test;

The parameters dyn and c are declared in the model Test.Data which is extended in Test.Example.

When running the following Julia script I run into issues:

using OMJulia
mod = OMJulia.OMCSession()
ModelicaSystem(mod, "Test.mo", "Test.Example")
getParameters(mod)
# The following line DOES NOT WORK
sendExpression(mod, "setParameterValue(Test.Example, c, 9)")
# The following line DOES WORK and has the intended effect
sendExpression(mod, "setParameterValue(Test.Data, c, 9)")
buildModel(mod)
simulate(mod)
c = getParameters(mod, "c")
x = getSolutions(mod, "x")[end][end]
println("c  = ", c, "\tx = ", x)

Issues

  1. getParameters(mod) shows the following results, which totally makes sense, as c and dyn are parameters of Test.Example:
Dict{Any, Any} with 2 entries:
  "c"   => "1.0"
  "dyn" => "1"
  1. The command sendExpression(mod, "setParameterValue(Test.Example, c, 9)") causes an error for an unknown reason. As the parameter c is shown by getParameters(mod) I would expect setParameters to work properly: but it doesn't. The error message is:
Stacktrace:
 [1] tokenize(data::String)
   @ OMJulia.Parser ~/.julia/packages/OMJulia/qSIBn/src/lexer.jl:172
 [2] parseOM
   @ ~/.julia/packages/OMJulia/qSIBn/src/parser.jl:127 [inlined]
 [3] sendExpression(omc::OMJulia.OMCSession, expr::String; parsed::Bool)
   @ OMJulia ~/.julia/packages/OMJulia/qSIBn/src/OMJulia.jl:184
 [4] sendExpression(omc::OMJulia.OMCSession, expr::String)
   @ OMJulia ~/.julia/packages/OMJulia/qSIBn/src/OMJulia.jl:180
 [5] top-level scope
   @ REPL[70]:2
  1. The workarouind is to set the parameter c in model Data by sendExpression(mod, "setParameterValue(Test.Data, c, 9)"). But is not a good solution as I have to know that the model Test.Data is used in Test.Example. So I have to have knowledge on how the model Test.Example is written in Modelica and that cannot be a good solution.

I think that the error of item 2. is a bug.

@christiankral
Copy link
Contributor Author

I thought that it may be necessary to instantiate Test.Example before setting the parameter c, but instantiateModel(Test.Example) is not a solution.

@arun3688
Copy link
Contributor

@christiankral i tested your package, the error message is not correctly displayed due to parser error, So you can use the API in the following way , set the named argument parsed = false like below

julia> sendExpression(mod, "setParameterValue(Test.Example, c, 9)", parsed=false)
"Error: component with name: c in class: Test.Example not found.\n"

And the error message says that c is not found in Test.Example which is true, At least for this example you are not changing structural parameters and if your aim is to change only c then setParameters() API will work and no need to rebuild the model.

julia> using OMJulia
julia> mod = OMJulia.OMCSession()
julia> ModelicaSystem(mod, "Test.mo", "Test.Example")
julia> getParameters(mod)
Dict{Any,Any} with 2 entries:
  "c"   => "1.0"
  "dyn" => "1"
## use the setParameters() API 
julia> setParameters(mod, "c=9")
"9"
julia> simulate(mod)
LOG_SUCCESS       | info    | The initialization finished successfully without homotopy method.
LOG_SUCCESS       | info    | The simulation finished successfully.
julia> c = getParameters(mod, "c")
"9"
julia> x = getSolutions(mod, "x")[end][end]
0.001109553030142552
julia> println("c  = ", c, "\tx = ", x)
c  = 9  x = 0.001109553030142552

@christiankral
Copy link
Contributor Author

@arun3688 Thanks for your comment.

So if I want to change the structure of the model, too, by changing dyn, I have to use

  • sendExpression(mod, "setParameterValue(Test.Data, dyn, 0)")
  • setParameters(mod, "c=9")

then build and simulate the model.

I am wondering how I can automate the change of parameters independent of being a structural parameter or not.

The problem of automation is: how do I know the structural change cause by dyn has to be applied on Test.Data if I am investigating Test.Example. Some structural parameters may even be distributed over different (partial) models, depending on the user model.

@christiankral
Copy link
Contributor Author

Asked differently: is there a way to flatten the investigated model Test.Example such way that "every" parameter appears in Test.Example?

@adrpo
Copy link
Member

adrpo commented Jul 22, 2021

Unfortunately currently there is no way to fetch all parameters from the flatten model with the API and then have just one API to set them in the top model. I am working on adding these.

For now what OMEdit does is that it fetches the extends then gets the parameters from the entire instance hierarchy. Then uses setExtendsModifierValue to set those, but it doesn't work in all cases.

@christiankral
Copy link
Contributor Author

For now I could even create a workaround based on proposal #45 (comment), which I somehow need for my project OMcsv.jl:

If setParameters draws a proper message then I can process it and make a parameter change using setParameterValue(...) to a Modelica class that I have to specify explicitly. This is -- for now -- not elegant, but a workaround solution until the "one API" call for all parameters is implemented.

Thanks @arun3688 and @adrpo for your support.

@arun3688
Copy link
Contributor

@christiankral , I am making changes to setParameters() so that it gives you the proper error message, I will soon push it, making some tests

@arun3688
Copy link
Contributor

@christiankral , the setParameters() API is fixed with d99f7b8, Now you can get proper info messages about structural parameters and it can be changed or not

>>>using OMJulia
>>>mod = OMJulia.OMCSession()
>>>ModelicaSystem(mod, "Test.mo", "Test.Example")
>>>setParameters(mod,"dyn=4")
| info |  setParameters() failed : It is not possible to set the following signal "dyn", It seems to be structural, final, protected or evaluated or has a non-constant binding, use sendExpression(setParameterValue(Test.Example, dyn, 4), parsed=false) and rebuild the model using buildModel() API

@christiankral
Copy link
Contributor Author

christiankral commented Jul 30, 2021

julia> using OMJulia
julia> mod = OMJulia.OMCSession()
julia> ModelicaSystem(mod, "Test.mo", "Test.Example")
julia> getParameters(mod)
Dict{Any,Any} with 2 entries:
  "c"   => "1.0"
  "dyn" => "1"
## use the setParameters() API 
julia> setParameters(mod, "c=9")
"9"
julia> simulate(mod)
LOG_SUCCESS       | info    | The initialization finished successfully without homotopy method.
LOG_SUCCESS       | info    | The simulation finished successfully.
julia> c = getParameters(mod, "c")
"9"
julia> x = getSolutions(mod, "x")[end][end]
0.001109553030142552
julia> println("c  = ", c, "\tx = ", x)
c  = 9  x = 0.001109553030142552

This makes sense and works. But, if I build the model prior to simulation, the parameter c SEEMS NOT TO BE CHANGED correctly.

In order to easier check this behavior, I provide the code:

using OMJulia
mod = OMJulia.OMCSession()
ModelicaSystem(mod, "Test.mo", "Test.Example")
getParameters(mod)
## use the setParameters() API 
setParameters(mod, "c=9")
buildModel(mod)
simulate(mod)
c = getParameters(mod, "c")
x = getSolutions(mod, "x")[end][end]
println("c  = ", c, "\tx = ", x)

This code returns c = 1.0 x = 0.001109553030142552.

The result x = 0.001109553030142552 is obviously obtained based on c = 9 (as c = 1 leads to the result x = 0.3678794515339768), but c is not obtained correctly (after building).

Is this a bug?

@arun3688
Copy link
Contributor

@christiankral Actually ModelicaSystem Constructor internally calls buildModel() API, so when you are calling the buildModel() API all the values which are used as part of sendExpression() gets updated, but the old values are ignored, and hence the values for c is wrong, but if you use c = getSolutions(mod, "c")[end][end], the you should get c=9

using OMJulia
mod = OMJulia.OMCSession()
ModelicaSystem(mod, "Test.mo", "Test.Example")
getParameters(mod)
## use the setParameters() API 
setParameters(mod, "c=9")
buildModel(mod)
simulate(mod)
x = getSolutions(mod, "x")[end][end]
c = getSolutions(mod, "x")[end][end]
println("c  = ", c, "\tx = ", x)

But as you pointed out it is a bug, the getParameters(c) should return c=9, When rebuilding the model, i have to check for list of values set by users and update the model. I will fix this issue

@arun3688
Copy link
Contributor

arun3688 commented Aug 2, 2021

@chrbertsch , the issue is fixed with this commit fd5e1ea, test it

@christiankral
Copy link
Contributor Author

@arun3688 Yes, it all works now. Thank you.

@arun3688
Copy link
Contributor

arun3688 commented Aug 4, 2021

@christiankral I will close this issue, if there are further problems, please open a new issue

@arun3688
Copy link
Contributor

@casella the issue is fixed and closed

@casella
Copy link
Contributor

casella commented Aug 22, 2021

@casella the issue is fixed and closed

Sure, I just wanted to give you due credit for that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants