A list for the developers of CellML tools

Text archives Help


[cellml-dev] A couple of CellML API questions


Chronological Thread 
  • From: alan.garny at dpag.ox.ac.uk (Alan Garny)
  • Subject: [cellml-dev] A couple of CellML API questions
  • Date: Wed, 14 Dec 2011 10:08:51 +0100

Hi Andrew,

> > Trying to find my way around the CellML API (C++ binding), I have two
main
> > questions at this stage:
> > Is there a way to tell whether a model needs a ?simple? ODE solver (e.g.
> > CVODE) or a DAE solver (e.g. IDA) to be computed? It seems to me, from
> > looking at the source code of both the CellML API and OpenCell, that
there
> > might not be. I mean, I couldn?t find anything in the CellML API while,
in
> > OpenCell, generation of ODE or DAE code seems to be based on the choice
> > of integration scheme (i.e. IDA or not). This being said, could
> > CodeInformation::algebraicIndexCount() be a way to determine what I am
> > after?
>
> The CCGS and CIS do not provide any mechanism to only solve ODE systems;
> DAE systems can be solved using CVODE by solving for the algebraic
> equations through decomposition into systems that can be solved; for
> example, if you have a simple DAE system:
> ? y = 2x
> ? dx/dt = y
> Then asking for code to solve it with CVODE will generate a function for
> solving for the rates by computing the algebraic variables ('y') first,
and then
> computing the rates needed.
>
> If you have a more complex DAE system:
> ? 0 = sin(y + 2x)
> ? dx/dt = y
> then the solver won't be able to work out analytically how to compute y
> from x, so the function to compute rates will include a call to a
non-linear
> solver; however, from the perspective of CVODE, it is still a function
that
> takes the state variables and computes the rate.

Yes, I can see how CVODE could be used for any of DAE system (potentially
requiring a non-linear solver in some cases), but would it as efficient as
IDA? I would guess not (otherwise the authors of CVODE wouldn't have
bothered writing IDA!).

> IDA code generation, on the other hand, will make x and y variables in the
> system. Therefore, both methods will allow the above two systems to be
> solved.
>
> The code generation will give an error if it can't generate code of the
> appropriate type; if you really want ODEs only, you can use
> algebraicIndexCount as you mention. OpenCell put the choice of integrator
> up to the user, had a default (which I think was to always use IDA in the
final
> release), but would support nearly all models using either CVODE or IDA.

Nearly all models? Are you saying that some models couldn't be solved using
either CVODE or IDA, or that some models could be solved using IDA but not
CVODE? I would imagine the former? If so, then is there a means by which the
CellML API can tell us that this would be the case (i.e. a model couldn't be
used using either CVODE or IDA, or similar ODE/DAE solvers).

Anyway, I am, in OpenCOR, going to 'formally' distinguish between ODE and
DAE systems.

> > I need to convert CellML models to binary code (using the LLVM-JIT AP),
so I
> > don?t think I can rely on the CeLEDS and CeLEDSExporter services for
this
> > task? Ideally, there would be a way, using the CellML API, to get a
procedural
> > representation of the model, making it ?easy? then to generate binary
code.
> > Right now, I am thinking of writing my own code based on that of
> > CodeGenerationState::GenerateCode(), but needless to say that I would
> > rather not go that route. So, have I missed something or should I sit
down
> > and get coding
?
>
> Going directly to binary procedural code using the API has not been
tested; in
> theory, there should be no limits on the code that can be generated, but I
> think in practice there are a few places where we call C functions / pass
> strings in null-terminated form (e.g. in libxml if you are using CeLEDS),
which
> will make embedding null bytes in the output difficult - something that is
> essential for generating machine code directly.

I guess I will have to see for myself whether it can be done then. Note,
however, that I am not intending to use CeLEDS. In fact, I am intending to
write my own code based on what you did in
CodeGenerationState::GenerateCode(). Now, it's true that I haven't yet
looked into that code in details, but I can't see why it wouldn't work. Say
that you have the following equation:

A = B+C

What I would need from the API is some kind of a binary tree that represents
the equation, so that I can (using the LLVM API) generate something like:

Get address of B
Get address of C
Create addition of B and C
Store result in A

> I'd suggest generating some kind of plain-text intermediate procedural
> language - I don't see any fundamental reason why it wouldn't be possible
to
> generate LLVM Assembly using CeLEDS and CeLEDSExporter, you would just
> need to create an XML file describing the transformation.

It might be possible, but if you have looked at the LLVM assembly language,
you will have to agree that generating LLVM assembly would be significantly
more involved than generating C or even Fortran. For example, the LLVM
assembly for the 'very simple' van der Pol model
(http://models.cellml.org/exposure/5756af26cfb20a7f66a51f66af10a70a) is as
follows (based on the C code generated by OpenCell and using the online demo
version of LLVM which can be found at http://www.llvm.org/demo/):

; ModuleID = '/tmp/webcompile/_29219_0.bc'
target datalayout =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:6
4-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @initConsts(double* nocapture %CONSTANTS, double*
nocapture %RATES, double* nocapture %STATES) nounwind uwtable {
store double -2.000000e+00, double* %STATES, align 8, !tbaa
!0
%1 = getelementptr inbounds double* %STATES, i64 1
store double 0.000000e+00, double* %1, align 8, !tbaa !0
store double 1.000000e+00, double* %CONSTANTS, align 8,
!tbaa !0
ret void
}

define void @computeRates(double %VOI, double* nocapture %CONSTANTS,
double* nocapture %RATES, double* nocapture %STATES, double* nocapture
%ALGEBRAIC) nounwind uwtable {
%1 = getelementptr inbounds double* %STATES, i64 1
%2 = load double* %1, align 8, !tbaa !0
store double %2, double* %RATES, align 8, !tbaa !0
%3 = load double* %CONSTANTS, align 8, !tbaa !0
%4 = load double* %STATES, align 8, !tbaa !0
%pow2 = fmul double %4, %4
%5 = fsub double 1.000000e+00, %pow2
%6 = fmul double %3, %5
%7 = load double* %1, align 8, !tbaa !0
%8 = fmul double %6, %7
%9 = fsub double %8, %4
%10 = getelementptr inbounds double* %RATES, i64 1
store double %9, double* %10, align 8, !tbaa !0
ret void
}

define void @computeVariables(double %VOI, double* nocapture
%CONSTANTS, double* nocapture %RATES, double* nocapture %STATES, double*
nocapture %ALGEBRAIC) nounwind uwtable readnone {
ret void
}

Needless to say that I can't see myself coming up with an XML file
describing that transformation (assuming it could ever be done in the first
place!).

> That said, I'm not sure why you aren't just using CIS, which does
everything
> automatically, compiling via C, so all you have to do is make sure gcc is
> available (with linking on Mac being the only tricky part, and one that
looks
> like it can be easily overcome).

Regarding Mac OS X and as you said, it *looks like* it can be easily
overcome. If I am not mistaken you had a quick go at it and quickly faces
various problems (e.g. missing dependencies?) which is not to say that they
couldn't be addressed, but that it wasn't going to be as straightforward as
one might have hoped.

This aside, I must confess that I just don't like the idea of having to rely
on gcc. Also, if I recall correctly, CIS makes certain assumptions (with
regards to certain dependencies) which made it impossible for me to use it
straight out of the box, be it either on Linux or on Mac OS X, and this
despite the fact that both environments were fully set up for gcc use.

Anyway, my point is that using LLVM, I can avoid this kind of issue (and
possibly others that I haven't come across), not to mention that LLVM-JIT is
fully supported on x86, PowerPC, Mips and partially supported (at this
stage, at least) on ARM. As you probably know, LLVM is growing in popularity
(and is well documented, supported, etc.), so I think it's worth investing
time in it.

Alan





Archive powered by MHonArc 2.6.18.

Top of page