User:LeonKwek

From ASCEND
Jump to navigation Jump to search

Leon Kwek is working on adding support for integration of conditional models to ASCEND via modification of the IDA solver to add boundary-crossing/DAE reinitialisation support.

Goals

Implement code that completes the support for boundary-crossing in DAE integration:

  • Check support for boundary detection is complete/robust.
  • Using LRSlv, solve the logical problem and determine if any logical states have changed
  • Determine if as a result any WHEN statements have changed state
  • If so, reconfigure the model: turn of disused equations, turn on new equations.
  • Determine strategy to solve the initialisation problem, possibly bearing in mind the variables/relations that have recently been added to/removed from the model.
  • Solve the initialisation problem either using IDA's built-in routine or else through direct use of QRSlv
  • Restart IDA and continue integration.

Test the resulting code on a set of sample models given by Jan Huckleheim (in the first instance)

If possible: write some new solar energy simulation models that make use of the new freature, eg thermostat controller for a hot water system.

Progress made

14 Apr discussion with John, Leon

  • want to avoid letting LRSlv evaluate any boundary residuals, since IDA always knows their value already and will tell us if they have ever been crossed.
  • IDA actually doesn't know the truth-value of a boundary expression, so we need somehow to establish the truth-value before integration commences.
  • we anticipate needed to support crossing of multiple boundaries at once (simultaneously, as far as IDA is concerned). IDA can provide a list of boundaries that has been crossed, so we need to be able to deal with that returned information correctly.
  • CMSlv drives LRSlv to 'test' different truth values on boundaries. It does this by flagging boundaries that it wants to 'imagine' crossing, and LRSlv, via 'perturb' code in the SATISFIED evaluation routines, returns the altered truth value of boundaries where requested.
  • IDA in the other hand wants to drive LRSlv without letting LRSlv evaluate any of the boundary residuals. So we need a way of making SATISFIED evaluations refer back to some external data instead of visiting the relevant relation and evaluating it directly. Possible options:
    • double-purpose the current 'perturb' stuff using a special value of 'perturb_value' to indicate the IDA usage, and pass a list of boundaries plus IDA's reported truth values through in place of the perturb list.
    • remove existing perturb stuff and pass a function pointer plus data pointer through to the evaluation code, and allow the solver to implement its own boundary evaluation method. CMSlv+IDA would use this to artificially tweak the design boundary(ies) and IDA+LRSLv would use this to look up the desired value from some kind of list passed to LRSlv by IDA (generated by looking at the flags attached to bnd objects).
    • write a parallel set of evaluation functions that work differently, with no change to current CMSlv-related functionality.
    • do some dirty tricks using direct calls to ascend/compiler code from the solver, and flag boundary relations with their 'forced' truth-values in the case where they are being evaluated via IDA+LRSlv.
    • implement another dirty trick in which a global variable forces switched behaviour whenever an attempt to evaluate a SATISFIED statements comes along. Or is it possible to store some flag in some other high-level object in the compiler? We would still need a way of passing the required boundary states through to the compiler, as well.
  • If we modify LRSlv then we need to assure that CMSlv is not broken. Leon has a copy of CONOPT now for testing CMSlv still works. Models that you can check with are at Conditional modelling#Examples.
  • Compiling CONOPT needs gfortran; you should have a libconsub3.so at the end of the build process. Run 'scons install' as root to install to /usr/local/lib which ASCEND should then pick up.

29th March

logical states A way of flagging boundaries so that LRSlv looks up the desired state of boundary condition (as opposed to evaluating) in the event of a crossing detected by IDA. The issues described below was dealt with by adding flags to the compiler side relation structure -- most definitely not an ideal solution. Looking to seek advice from Ben Allan on the dangers of this move / some other way solver-side around.

WHENs A function written for CMSlv seems to handle everything we need for our purposes here, however I haven't yet found an efficient way to get variables to update once the appropriate equations have been switched on and off. Calling QRSlv does the trick, but that seems like overkill.

The bigger challenge at the moment however -- reinitialising IDA given that the number of variables in the problem may have changed as a result of a crossing. Ben has suggested that the smart approach is to simply bang up the whole system from the beginning and forget about nifty optimisations until they become glaringly necessary. I'm partial to this angle, largely because it's the most straight forward and obvious but also because it's intuitive and therefore robust in that it's harder to make programming mistakes.

9th March

logical states Decided to abandon the perturb stuff as on reflection it refers to a different sort of problem. When numerically integrating we always certain which boundary we are crossing and where we will end up after the event.

Current understanding of the logical problem: we need to recognise an arbitrary setup of logical states. For example, say we want to model a valve that opens when both a given mass flow rate exceeds a value m1 and a temperature reaches T1

CONDITIONAL
c1: m > m1;
c2: T > T1;
END CONDITIONAL

Then we want to be able to express opening of the valve equally as

b1 == SATISFIED(c1, 0.001{kg/s})
b2 == SATISFIED(c2, 0.1{K})

WHEN(b1, b2)
CASE(TRUE, TRUE)
END WHEN

or alternatively

b == ( SATISFIED(c1, 0.001{kg/s}) && SATISFIED(c2, 0.1{K}) )

WHEN(b)
CASE(TRUE)
END WHEN

Now for the latest issue: LRSlv sorts the boolean variable simply by calling the slv_common function slv_direct_log_solve. This in turn uses ASCEND's internal relation and logical relation evaluator, which can handle the required branches of arbitrary length. The scope of these functions however, is such that we don't have access to the boundary or logrel structures, either of which would allow the flagging of boundary crossings detected by IDA.


7th March

boundary detection Issues with multiple detection during integration found to actually be the result of the incorrect assumption that IDA's 'internal' independent variable always matches the requested return value (tret). Re-initialising IDA with the desired start time solves this issue.

logical states Seems that simply calling LRSlv's solve function bypasses the boundaries and evaluates logical relations directly. This is to be expected -- it is a logical not boundary solver -- however this means that we cannot get the desired switch in conditional relations without modifying LRSlv. All this worry may be for nought however. The following from logrel_util.h :

*  The easier way to test if the crossing of a boundary affects the current
*  configuration is to solve the logical relations assuming such a
*  crossing and finding if the configuration of the problem changes.
*  This task is performed here by using the "perturb" flag and a list
*  of pointers to the relation instance which constitutes the boundary(ies).
*  The activation of the perturbation flag causes the calculation
*  routines to INVERT the truth value of the SATISFIED terms containing
*  the relation instances pointed by the list of pointers.
*  The flag and the list of pointers are needed because the SATISFIED term
*  is not an instance by itself and we have access to it only trough the
*  logrel instance.

As is to be expected, CMSlv already has a means for handling this issue, though I can't make sense of how it works at the moment.

23rd Feb (at revision 3253)

boundary detection IDA's built-in root finding engine seems to do the job in the case of boundary crossings of independent, dependant, derivatives and combinations of the three. Existing code suggests that IDA will return a positive or negative flag for a respective increasing or decreasing root however I cant get this to work.

ideas for further testing: minimum separation of boundaries IDA will detect. Speed of the rootfinding.

Logical States Setting LRSlv to work is straightforward however there is the issue of setting the model parameters for the logical solution. For example, IDA may indicate a root at t = 3.99983 for the boundary t >= 4, in which case calling LRSlv immediately does not trigger a change in the appropriate boolean variable. I think IDA also returns a minimum step size used during the integration which could be used to 'bump' a variable over to the correct side of a boundary if the issue of increasing/decreasing roots described above can be resolved. What about bumping multi variable boundaries?

Another thing to consider: boundaries that occur on the time samples of the integration loop are picked up twice by the rootfinding algorithm. If a root occurs on or very close to the next time step tnext, upon restarting IDA will need to run to tnext +1 before back to the top of the loop. Notes on handling conditional branches from the documentation of a similar modelling program[1] mention that boundaries that depend only on the independent variable have the bonus of being known ahead of time. In that case it is possible to handle the discontinuity by arranging for an integration time step to fall on the boundary and switching the model appropriately. However the need to control the time step probably adds more complexity than it saves (especially for nested components).


WHEN statements have changed Will look next into how the WHEN conditions are handled.

References

  1. Elmegaard and Houbak, 2004, DNA – A General Energy System Simulation Tool, Technical University of Denmark