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

Implement Kinsol as non-linear solver for non-linear loops over components #815

Merged
merged 6 commits into from
Oct 28, 2020

Conversation

AnHeuermann
Copy link
Member

@AnHeuermann AnHeuermann commented Sep 22, 2020

Related Issues

#812, #808

Purpose

A fixed-point iterations is currently the only solver available to solve algebraic loops over components but not suitable for all problems.
Implementing KINSOL as alternative to the fixed-point iteration will enable more FMUs connected to run smoothly.

@AnHeuermann AnHeuermann changed the title [WIP] Reduce duplicate code [WIP] Implement Kinsol as non-linear solver for non-linear loops over components Sep 24, 2020
@AnHeuermann AnHeuermann self-assigned this Sep 24, 2020
@AnHeuermann AnHeuermann force-pushed the reduceDuplicateCode branch 2 times, most recently from fa192dd to 9d26c4a Compare September 29, 2020 15:11
@AnHeuermann
Copy link
Member Author

I need some test case to verify that everything is correct.
Do we have some FMUs with non-linear loops over them already? Otherwise I could add a test to OpenModelica or add some generated FMUs this testsuite.

Currently I'm using

loadModel(Modelica);

loadString("model loopsOverFMUsA
  Real a, b, c;
  Modelica.Blocks.Interfaces.RealOutput a_out;
  Modelica.Blocks.Interfaces.RealOutput b_out;
  Modelica.Blocks.Interfaces.RealInput c_in;
equation
  c = c_in;
  // Eq. 1 and 2 of loop
  a + b + c=0;
  2*a - 3*b + 2*c=9;
  a_out = a;
  b_out = b;
end loopsOverFMUsA;
"); getErrorString();

loadString("model loopsOverFMUsB
  Real a, b, c;
  Modelica.Blocks.Interfaces.RealInput a_in;
  Modelica.Blocks.Interfaces.RealInput b_in;
  Modelica.Blocks.Interfaces.RealOutput c_out;
equation
  a = a_in;
  b = b_in;
  // Equation 3 of loop
  a*a + b*b + c*c=5;
  c_out = c;
end loopsOverFMUsB;
"); getErrorString();

buildModelFMU(loopsOverFMUsA, fmuType="me"); getErrorString();
buildModelFMU(loopsOverFMUsB, fmuType="me"); getErrorString();

system("rm -rf FMU_A && unzip -qq loopsOverFMUsA.fmu -d FMU_A"); getErrorString();
system("rm -rf FMU_B && unzip -qq loopsOverFMUsB.fmu -d FMU_B"); getErrorString();

writeFile("loopsOverFMUs.lua","
oms_setTempDirectory(\"./temp/\")
oms_newModel(\"loopsOverFMUs\")
oms_addSystem(\"loopsOverFMUs.root\", oms_system_sc)

-- instantiate FMUs
oms_addSubModel(\"loopsOverFMUs.root.A1\", \"loopsOverFMUsA.fmu\")
oms_addSubModel(\"loopsOverFMUs.root.B1\", \"loopsOverFMUsB.fmu\")
oms_addSubModel(\"loopsOverFMUs.root.A2\", \"loopsOverFMUsA.fmu\")
oms_addSubModel(\"loopsOverFMUs.root.B2\", \"loopsOverFMUsB.fmu\")

-- connections: A1 -> B1
oms_addConnection(\"loopsOverFMUs.root.A1.a_out\", \"loopsOverFMUs.root.B1.a_in\")
oms_addConnection(\"loopsOverFMUs.root.A1.b_out\", \"loopsOverFMUs.root.B1.b_in\")
oms_addConnection(\"loopsOverFMUs.root.A1.c_in\", \"loopsOverFMUs.root.B1.c_out\")

-- connections: A2 -> B2
oms_addConnection(\"loopsOverFMUs.root.A2.a_out\", \"loopsOverFMUs.root.B2.a_in\")
oms_addConnection(\"loopsOverFMUs.root.A2.b_out\", \"loopsOverFMUs.root.B2.b_in\")
oms_addConnection(\"loopsOverFMUs.root.A2.c_in\", \"loopsOverFMUs.root.B2.c_out\")

-- simulation settings
oms_setResultFile(\"loopsOverFMUs\", \"loopsOverFMUs.csv\")
oms_setStartTime(\"loopsOverFMUs\", 0)
oms_setStopTime(\"loopsOverFMUs\", 0.1)

oms_instantiate(\"loopsOverFMUs\")
oms_setReal(\"loopsOverFMUs.root.B1.a_in\", 0.635425)
oms_setReal(\"loopsOverFMUs.root.B1.b_in\", -1.8)
oms_setReal(\"loopsOverFMUs.root.A1.c_in\", 1.16458)
--oms_setReal(\"loopsOverFMUs.root.B2.a_in\", 0.635425)
--oms_setReal(\"loopsOverFMUs.root.B2.b_in\", -1.8)
--oms_setReal(\"loopsOverFMUs.root.A2.c_in\", 1.16458)

oms_initialize(\"loopsOverFMUs\")
oms_simulate(\"loopsOverFMUs\")
oms_terminate(\"loopsOverFMUs\")
oms_delete(\"loopsOverFMUs\")
"); getErrorString();

system("OMSimulator loopsOverFMUs.lua --algLoopSolver=kinsol --logLevel=2"); getErrorString();

But it is a bit to simple to solve for a good test.

Also I'm not sure how to change values for B2.a_in, B2.b_in and A2.c_in in an automated fassion if the fmi2getReal function failed. We could add or substract 10% or something similar. But otherwise we need the user to give initial values that are good enough.

@AnHeuermann
Copy link
Member Author

Okay, here comes an example that is ridiculous simple but impossible to solve for the fixed-point iteration. Just connect FMUA and FMUB in the obvious way:

model FMUA
  Modelica.Blocks.Interfaces.RealInput x_in;
  Modelica.Blocks.Interfaces.RealOutput x_out;
  Real y(fixed=true, start=2);
  parameter Real a = 2;
equation
  der(y) = a*y;
  x_out = 2*x_in-y;
end FMUA;

model FMUB
  Modelica.Blocks.Interfaces.RealInput x_in;
  Modelica.Blocks.Interfaces.RealOutput x_out;
equation
  x_out = x_in;
end FMUB;

But we have a remaining problem: The equation system during initialization

warning: Alg. loop (size 2)                                                                                                                                                 debug:   debug:   Create new KinsolSolver object for algebraic loop number 0
debug:   Solving algebraic loop formed by connections
                A.x_out <-> B.x_in
                B.x_out <-> A.x_in
debug:   Using solver KINSOL
debug:   Solving system 0

is solved correctly, but after initialization the graph or SCC changes and we get a "new" system

warning: Alg. loop (size 2)
debug:   Solving algebraic loop formed by connections
                A.y <-> B.x_in
                B.x_out <->
debug:   Using solver Kinsol
debug:   Solving system 0

which seems a bit odd and results in a segmentation fault.

@AnHeuermann AnHeuermann changed the title [WIP] Implement Kinsol as non-linear solver for non-linear loops over components Implement Kinsol as non-linear solver for non-linear loops over components Sep 30, 2020
@AnHeuermann AnHeuermann marked this pull request as ready for review September 30, 2020 13:42
@AnHeuermann AnHeuermann requested a review from lochel September 30, 2020 13:42
@AnHeuermann
Copy link
Member Author

I will add a test case to OpenModelica/testsuite/omsimulator, see PR OpenModelica/OpenModelica#6787

Documentation will follow in a separate PR.

AnHeuermann added 4 commits October 6, 2020 16:11
  - Collected some duplicant code and moved it to System.cpp / System.h
  Added debug log to display alg. loop
  - Added enums for different alg solver methods
  - Added debug print to display loops
  - Create object for each alg loop bundled with solver
  - Added KINSOL solver to AlgLoop class.
  - Added a new flag `--algLoopSolver` to choose alg. solver method.
    Defaults to fixed-point-iteration. Use "kinsol" for KINSOL.
  - Also added a new type oms_ssc_t for strong connected components.
@lochel lochel merged commit 784af99 into OpenModelica:master Oct 28, 2020
lochel added a commit to lochel/OMSimulator that referenced this pull request Oct 28, 2020
lochel added a commit that referenced this pull request Oct 28, 2020
lochel pushed a commit to lochel/OMSimulator that referenced this pull request Oct 28, 2020
…nents (OpenModelica#815)

* Reduce redundant code

  - Collected some duplicant code and moved it to System.cpp / System.h

* Move alg loop solver to own file

  Added debug log to display alg. loop

* Capsulate fixed-point iteration

  - Added enums for different alg solver methods
  - Added debug print to display loops
  - Create object for each alg loop bundled with solver

* Added algebraic solver KINSOL for non-linear loops over components.

  - Added KINSOL solver to AlgLoop class.
  - Added a new flag `--algLoopSolver` to choose alg. solver method.
    Defaults to fixed-point-iteration. Use "kinsol" for KINSOL.
  - Also added a new type oms_ssc_t for strong connected components.

* Bug fix for wrong index of alg loops
lochel pushed a commit to lochel/OMSimulator that referenced this pull request Nov 21, 2020
…nents (OpenModelica#815)

* Reduce redundant code

  - Collected some duplicant code and moved it to System.cpp / System.h

* Move alg loop solver to own file

  Added debug log to display alg. loop

* Capsulate fixed-point iteration

  - Added enums for different alg solver methods
  - Added debug print to display loops
  - Create object for each alg loop bundled with solver

* Added algebraic solver KINSOL for non-linear loops over components.

  - Added KINSOL solver to AlgLoop class.
  - Added a new flag `--algLoopSolver` to choose alg. solver method.
    Defaults to fixed-point-iteration. Use "kinsol" for KINSOL.
  - Also added a new type oms_ssc_t for strong connected components.

* Bug fix for wrong index of alg loops
lochel pushed a commit to lochel/OMSimulator that referenced this pull request Dec 27, 2020
…nents (OpenModelica#815)

* Reduce redundant code

  - Collected some duplicant code and moved it to System.cpp / System.h

* Move alg loop solver to own file

  Added debug log to display alg. loop

* Capsulate fixed-point iteration

  - Added enums for different alg solver methods
  - Added debug print to display loops
  - Create object for each alg loop bundled with solver

* Added algebraic solver KINSOL for non-linear loops over components.

  - Added KINSOL solver to AlgLoop class.
  - Added a new flag `--algLoopSolver` to choose alg. solver method.
    Defaults to fixed-point-iteration. Use "kinsol" for KINSOL.
  - Also added a new type oms_ssc_t for strong connected components.

* Bug fix for wrong index of alg loops
lochel added a commit to lochel/OMSimulator that referenced this pull request Jan 22, 2021
lochel added a commit that referenced this pull request Jan 25, 2021
@AnHeuermann AnHeuermann deleted the reduceDuplicateCode branch December 8, 2021 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants