Skip to content

Commit bf439b6

Browse files
committedAug 9, 2009
merging initial files required for building the OpenCMISS(cellml) library from the basicSimulationApplication branch, revision 209, into the trunk
git-svn-id: https://opencmiss.svn.sourceforge.net/svnroot/opencmiss/cellml/trunk@605 61e36070-c886-4827-b7c0-ed9e4dc59cc8
1 parent 3e181eb commit bf439b6

18 files changed

+2343
-0
lines changed
 

‎CMakeLists.txt

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
cmake_minimum_required(VERSION 2.6)
2+
3+
PROJECT(bsa)
4+
5+
ENABLE_LANGUAGE(Fortran)
6+
7+
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${bsa_SOURCE_DIR})
8+
9+
FIND_PACKAGE(CellML REQUIRED)
10+
FIND_PACKAGE(CCGS REQUIRED)
11+
FIND_PACKAGE(Redland REQUIRED)
12+
FIND_PACKAGE(LibXml2 REQUIRED QUIET)
13+
14+
# Probably better to not do this as it probably overrides and external value?
15+
SET (CMAKE_CXX_FLAGS "-Wall -Werror ${LIBXML2_DEFINITIONS} ${Redland_DEFINITIONS}")
16+
17+
INCLUDE_DIRECTORIES(
18+
${CELLML_INCLUDE_DIR}
19+
${CCGS_INCLUDE_DIR}
20+
${LIBXML2_INCLUDE_DIR}
21+
)
22+
23+
SET(liboccellml_SRCS
24+
src/CellMLModelDefinitionF.cpp
25+
src/cellml_model_definition.f90
26+
src/CellMLModelDefinition.cpp
27+
src/RDFGraph.cpp
28+
src/SimulationDescription.cpp
29+
src/ccgs_required_functions.cpp
30+
)
31+
32+
SET(bsa_SRCS
33+
src/bsa.cpp
34+
src/CellMLModelDefinition.cpp
35+
src/RDFGraph.cpp
36+
src/SimulationDescription.cpp
37+
src/ccgs_required_functions.cpp
38+
)
39+
40+
SET(bsaF_SRCS
41+
src/bsa.f90
42+
${liboccellml_SRCS}
43+
)
44+
45+
SET(testF2C_SRCS
46+
src/testF2C.f90
47+
src/testF2C.cpp
48+
)
49+
50+
ADD_EXECUTABLE(bsa ${bsa_SRCS})
51+
TARGET_LINK_LIBRARIES(bsa
52+
${CELLML_LIBRARIES}
53+
${CCGS_LIBRARIES}
54+
${Redland_LIBRARIES}
55+
${LIBXML2_LIBRARIES}
56+
-ldl -lm
57+
)
58+
59+
ADD_EXECUTABLE(bsaF ${bsaF_SRCS})
60+
TARGET_LINK_LIBRARIES(bsaF
61+
${CELLML_LIBRARIES}
62+
${CCGS_LIBRARIES}
63+
${Redland_LIBRARIES}
64+
${LIBXML2_LIBRARIES}
65+
-ldl -lm
66+
-lstdc++
67+
)
68+
SET_TARGET_PROPERTIES(bsaF PROPERTIES LINKER_LANGUAGE Fortran)
69+
70+
ADD_EXECUTABLE(testF2C ${testF2C_SRCS})
71+
TARGET_LINK_LIBRARIES(testF2C
72+
-lstdc++
73+
)
74+
SET_TARGET_PROPERTIES(testF2C PROPERTIES LINKER_LANGUAGE Fortran)
75+
76+
ADD_LIBRARY(occellml STATIC ${liboccellml_SRCS})

‎FindCCGS.cmake

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# - Find CCGS
2+
# Find the CellML API C Code Generation Service includes and library
3+
# This module defines
4+
# CCGS_INCLUDE_DIR, where to find CCGS header files.
5+
# CCGS_LIBRARIES, the libraries needed to use the CCGS.
6+
# CCGS_FOUND, If false, do not try to use the CCGS.
7+
# also defined, but not for general use are
8+
# CCGS_LIBRARY, where to find the CCGS library.
9+
10+
FIND_PATH(CCGS_INCLUDE_DIR IfaceCCGS.hxx
11+
/usr/include/
12+
/usr/local/include/
13+
)
14+
15+
FIND_LIBRARY(CCGS_LIBRARY ccgs
16+
/usr/lib
17+
/usr/local/lib
18+
)
19+
FIND_LIBRARY(ANNO_TOOLS_LIBRARY annotools
20+
/usr/lib
21+
/usr/local/lib
22+
)
23+
FIND_LIBRARY(CEVAS_LIBRARY cevas
24+
/usr/lib
25+
/usr/local/lib
26+
)
27+
FIND_LIBRARY(CUSES_LIBRARY cuses
28+
/usr/lib
29+
/usr/local/lib
30+
)
31+
FIND_LIBRARY(MALAES_LIBRARY malaes
32+
/usr/lib
33+
/usr/local/lib
34+
)
35+
36+
IF (CCGS_INCLUDE_DIR AND CCGS_LIBRARY AND ANNO_TOOLS_LIBRARY AND CEVAS_LIBRARY AND CUSES_LIBRARY AND MALAES_LIBRARY)
37+
SET(CCGS_LIBRARIES ${CCGS_LIBRARY} ${ANNO_TOOLS_LIBRARY} ${CEVAS_LIBRARY} ${CUSES_LIBRARY} ${MALAES_LIBRARY})
38+
SET(CCGS_FOUND TRUE)
39+
ENDIF (CCGS_INCLUDE_DIR AND CCGS_LIBRARY AND ANNO_TOOLS_LIBRARY AND CEVAS_LIBRARY AND CUSES_LIBRARY AND MALAES_LIBRARY)
40+
41+
42+
IF (CCGS_FOUND)
43+
IF (NOT CCGS_FIND_QUIETLY)
44+
MESSAGE(STATUS "Found CCGS: ${CCGS_LIBRARIES}")
45+
ENDIF (NOT CCGS_FIND_QUIETLY)
46+
ELSE (CCGS_FOUND)
47+
IF (CCGS_FIND_REQUIRED)
48+
MESSAGE(FATAL_ERROR "Could not find CCGS")
49+
ELSE (CCGS_FIND_REQUIRED)
50+
MESSAGE(STATUS "CCGS not found")
51+
ENDIF (CCGS_FIND_REQUIRED)
52+
ENDIF (CCGS_FOUND)

‎FindCellML.cmake

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# - Find CellML
2+
# Find the CellML API includes and library
3+
# This module defines
4+
# CELLML_INCLUDE_DIR, where to find CellML API header files.
5+
# CELLML_LIBRARIES, the libraries needed to use the CellML API.
6+
# CELLML_FOUND, If false, do not try to use the CellML API.
7+
# also defined, but not for general use are
8+
# CELLML_LIBRARY, where to find the CellML library.
9+
10+
FIND_PATH(CELLML_INCLUDE_DIR IfaceCellML_APISPEC.hxx
11+
/usr/include/
12+
/usr/local/include/
13+
)
14+
15+
FIND_LIBRARY(CELLML_LIBRARY cellml
16+
/usr/lib
17+
/usr/local/lib
18+
)
19+
20+
IF (CELLML_INCLUDE_DIR AND CELLML_LIBRARY)
21+
SET(CELLML_LIBRARIES ${CELLML_LIBRARY})
22+
SET(CELLML_FOUND TRUE)
23+
ENDIF (CELLML_INCLUDE_DIR AND CELLML_LIBRARY)
24+
25+
26+
IF (CELLML_FOUND)
27+
IF (NOT CellML_FIND_QUIETLY)
28+
MESSAGE(STATUS "Found CellML: ${CELLML_LIBRARIES}")
29+
ENDIF (NOT CellML_FIND_QUIETLY)
30+
ELSE (CELLML_FOUND)
31+
IF (CellML_FIND_REQUIRED)
32+
MESSAGE(FATAL_ERROR "Could not find CellML")
33+
ELSE (CellML_FIND_REQUIRED)
34+
MESSAGE(STATUS "CellML API not found")
35+
ENDIF (CellML_FIND_REQUIRED)
36+
ENDIF (CELLML_FOUND)

‎FindRedland.cmake

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# - Find Redland
2+
# Find the Redland includes and libraries
3+
# This module defines
4+
# Redland_DEFINITIONS, compiler switches required for using Redland.
5+
# Redland_LIBRARIES, the libraries needed to use Redland.
6+
# Redland_VERSION, the version of Redland found
7+
# Redland_FOUND, If false, do not try to use Redland.
8+
# also defined, but not for general use are
9+
# Redland_LIBRARY, where to find Redland.
10+
11+
# Find all the config scripts
12+
FIND_PROGRAM(Redland_CONFIG redland-config
13+
/usr/bin
14+
/usr/local/bin
15+
)
16+
FIND_PROGRAM(Redland_RAPTOR_CONFIG raptor-config
17+
/usr/bin
18+
/usr/local/bin
19+
)
20+
FIND_PROGRAM(Redland_RASQAL_CONFIG rasqal-config
21+
/usr/bin
22+
/usr/local/bin
23+
)
24+
25+
IF(Redland_CONFIG AND Redland_RAPTOR_CONFIG AND Redland_RASQAL_CONFIG)
26+
MESSAGE(STATUS "Found config scripts")
27+
EXECUTE_PROCESS(COMMAND ${Redland_CONFIG} --cflags OUTPUT_VARIABLE Redland_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
28+
EXECUTE_PROCESS(COMMAND ${Redland_RAPTOR_CONFIG} --cflags OUTPUT_VARIABLE Redland_RAPTOR_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
29+
EXECUTE_PROCESS(COMMAND ${Redland_RASQAL_CONFIG} --cflags OUTPUT_VARIABLE Redland_RASQAL_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
30+
SET(Redland_DEFINITIONS
31+
${Redland_CFLAGS}
32+
${Redland_RAPTOR_CFLAGS}
33+
${Redland_RASQAL_CFLAGS}
34+
)
35+
EXECUTE_PROCESS(COMMAND ${Redland_CONFIG} --libs OUTPUT_VARIABLE Redland_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
36+
EXECUTE_PROCESS(COMMAND ${Redland_RAPTOR_CONFIG} --libs OUTPUT_VARIABLE Redland_RAPTOR_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
37+
EXECUTE_PROCESS(COMMAND ${Redland_RASQAL_CONFIG} --libs OUTPUT_VARIABLE Redland_RASQAL_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
38+
SET(Redland_LIBRARIES
39+
${Redland_LIBS}
40+
${Redland_RAPTOR_LIBS}
41+
${Redland_RASQAL_LIBS}
42+
)
43+
EXECUTE_PROCESS(COMMAND ${Redland_CONFIG} --version OUTPUT_VARIABLE Redland_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
44+
ENDIF(Redland_CONFIG AND Redland_RAPTOR_CONFIG AND Redland_RASQAL_CONFIG)
45+
46+
# Sytem installed redland 1.0.7 has no cflags?
47+
#IF (Redland_DEFINITIONS AND Redland_LIBRARIES)
48+
IF (Redland_LIBRARIES)
49+
SET(Redland_FOUND TRUE)
50+
ENDIF (Redland_LIBRARIES)
51+
#ENDIF (Redland_DEFINITIONS AND Redland_LIBRARIES)
52+
53+
54+
IF (Redland_FOUND)
55+
IF (NOT Redland_FIND_QUIETLY)
56+
MESSAGE(STATUS "Found Redland (${Redland_VERSION}): ${Redland_LIBRARIES}")
57+
ENDIF (NOT Redland_FIND_QUIETLY)
58+
ELSE (Redland_FOUND)
59+
IF (Redland_FIND_REQUIRED)
60+
MESSAGE(FATAL_ERROR "Could not find Redland")
61+
ELSE (Redland_FIND_REQUIRED)
62+
MESSAGE(STATUS "Redland not found")
63+
ENDIF (Redland_FIND_REQUIRED)
64+
ENDIF (Redland_FOUND)

‎runCmake.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
3+
# args:
4+
# -DCMAKE_BUILD_TYPE=Debug
5+
# -DCMAKE_BUILD_TYPE=Release
6+
7+
export CMAKE_INCLUDE_PATH=$OPENCMISSEXTRAS_ROOT/cellml/x86_64-linux/include
8+
export CMAKE_LIBRARY_PATH=$OPENCMISSEXTRAS_ROOT/cellml/x86_64-linux/lib
9+
10+
cmake $OPENCMISS_ROOT/cellml/basicSimulationApplication $@

‎src/CellMLModelDefinition.cpp

+495
Large diffs are not rendered by default.

‎src/CellMLModelDefinition.hpp

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#ifndef _CELLMLMODELDEFINITION_H_
2+
#define _CELLMLMODELDEFINITION_H_
3+
4+
/**
5+
* The primary object used to define a CellML model for use in openCMISS.
6+
*
7+
* This is the interface object sitting between a CellML description of a mathematical model and the use of that model in openCMISS.
8+
*/
9+
class CellMLModelDefinition
10+
{
11+
public:
12+
/**
13+
* Default constructor
14+
*/
15+
CellMLModelDefinition();
16+
/**
17+
* TODO: Need to do a copy constructor
18+
*/
19+
CellMLModelDefinition(const CellMLModelDefinition& src) {}
20+
21+
/**
22+
* Construct a model definition from a given source document at the givien URL.
23+
* @param url The URL of the source document form which to create the model defintion.
24+
*/
25+
CellMLModelDefinition(const char* url);
26+
/**
27+
* Destructor.
28+
*/
29+
~CellMLModelDefinition();
30+
31+
/**
32+
* Instantiate the model definition into simulat-able code.
33+
* @return 0 if success; non-zero otherwise.
34+
*/
35+
int instantiate();
36+
37+
/**
38+
* Set the compile command to use to compile the generated code into a dynamic shared object.
39+
* @param command The compile command.
40+
*/
41+
void compileCommand(const std::string& command)
42+
{
43+
mCompileCommand = command;
44+
}
45+
/**
46+
* Get the current compile command used to compile generated code.
47+
* @return The current compile command.
48+
*/
49+
std::string compileCommand()
50+
{
51+
return mCompileCommand;
52+
}
53+
54+
/**
55+
* Set the save temporary files flag.
56+
* @param state Should be set to true to save generated temporary files.
57+
*/
58+
void saveTempFiles(bool state)
59+
{
60+
mSaveTempFiles = state;
61+
}
62+
/**
63+
* Get the current state of the save temporary files flag.
64+
* @return The state of the save temporary files flag.
65+
*/
66+
bool saveTempFiles()
67+
{
68+
return mSaveTempFiles;
69+
}
70+
71+
/**
72+
* Check model instantiation.
73+
* @return True if the model is instantiated; false otherwise.
74+
*/
75+
bool instantiated()
76+
{
77+
return mInstantiated;
78+
}
79+
80+
uint32_t nBound;
81+
uint32_t nRates;
82+
uint32_t nAlgebraic;
83+
uint32_t nConstants;
84+
85+
// loaded from the generated and compiled DSO
86+
/* Initialise all variables which aren't state variables but have an
87+
* initial_value attribute, and any variables & rates which follow.
88+
*/
89+
void (*SetupFixedConstants)(double* CONSTANTS,double* RATES,double* STATES);
90+
/* Compute all rates which are not static
91+
*/
92+
void (*ComputeRates)(double VOI,double* STATES,double* RATES,
93+
double* CONSTANTS,double* ALGEBRAIC);
94+
/* Compute all variables not computed by initConsts or rates
95+
* (i.e., these are not required for the integration of the model and
96+
* thus only need to be called for output or presentation or similar
97+
* purposes)
98+
*/
99+
void (*EvaluateVariables)(double VOI,double* CONSTANTS,double* RATES,
100+
double* STATES,double* ALGEBRAIC);
101+
102+
private:
103+
/**
104+
* Generate C code for the given CellML model.
105+
* @param model The CellML model for which to generate C code.
106+
* @return The generated code, if successfull; and empty string otherwise.
107+
*/
108+
std::wstring getModelAsCCode(void* model);
109+
class SimulationDescription* mSimulationDescription;
110+
std::string mTmpDirName;
111+
bool mTmpDirExists;
112+
std::string mCodeFileName;
113+
bool mCodeFileExists;
114+
std::string mDsoFileName;
115+
bool mDsoFileExists;
116+
std::string mCompileCommand;
117+
bool mSaveTempFiles;
118+
void* mHandle;
119+
bool mInstantiated;
120+
};
121+
122+
#endif // _CELLMLMODELDEFINITION_H_

‎src/CellMLModelDefinitionF.cpp

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#include <iostream>
2+
#include <wchar.h>
3+
#include <string>
4+
#include <string.h>
5+
#include <stdlib.h>
6+
#include <math.h>
7+
8+
#include "CellMLModelDefinitionF.h"
9+
#include "CellMLModelDefinition.hpp"
10+
#include "ccgs_required_functions.h"
11+
12+
static char* getAbsoluteURI(const char* uri);
13+
14+
void* create_cellml_model_definition_f(const char* uri)
15+
{
16+
void* cellml_model_definition = (void*)NULL;
17+
if (uri && strlen(uri) > 1)
18+
{
19+
// make sure we have an absolute URI
20+
std::cout << "uri: \"" << uri << "\"" << std::endl;
21+
char* inputURI = getAbsoluteURI(uri);
22+
std::cout << "C uri = \"" << inputURI << "\"" << std::endl;
23+
/*
24+
* Create the model defintion object
25+
*/
26+
CellMLModelDefinition* def = new CellMLModelDefinition(inputURI);
27+
free(inputURI);
28+
cellml_model_definition = (void*)def;
29+
}
30+
else
31+
{
32+
std::cerr << "Invalid model URI" << std::endl;
33+
}
34+
return(cellml_model_definition);
35+
}
36+
37+
void destroy_cellml_model_definition_f(void** _ptr)
38+
{
39+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
40+
if (_ptr && *_ptr && (def = (CellMLModelDefinition*)(*_ptr)))
41+
{
42+
delete def;
43+
// want to make sure that we don't try to delete it again...
44+
*_ptr = (void*)NULL;
45+
_ptr = (void**)NULL;
46+
std::cout << "C destroying CellML model definition." << std::endl;
47+
}
48+
else
49+
{
50+
std::cerr << "[destroy_cellml_model_definition_f] Invalid arguments."
51+
<< std::endl;
52+
}
53+
}
54+
55+
void cellml_model_definition_set_save_temp_files_f(void* _ptr,int state)
56+
{
57+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
58+
if (_ptr && (def = (CellMLModelDefinition*)_ptr))
59+
{
60+
if (state != 0) def->saveTempFiles(true);
61+
else def->saveTempFiles(false);
62+
}
63+
else
64+
{
65+
std::cerr << "[cellml_model_definition_set_save_temp_files_f] "
66+
<< "Invalid arguments." << std::endl;
67+
}
68+
}
69+
70+
int cellml_model_definition_get_save_temp_files_f(void* _ptr)
71+
{
72+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
73+
if (_ptr && (def = (CellMLModelDefinition*)_ptr))
74+
{
75+
if (def->saveTempFiles()) return 1;
76+
else return 0;
77+
}
78+
else
79+
{
80+
std::cerr << "[cellml_model_definition_get_save_temp_files_f] "
81+
<< "Invalid arguments." << std::endl;
82+
}
83+
return -1;
84+
}
85+
86+
int cellml_model_definition_instantiate_f(void* _ptr)
87+
{
88+
int code = -1;
89+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
90+
if (_ptr && (def = (CellMLModelDefinition*)_ptr))
91+
{
92+
code = def->instantiate();
93+
}
94+
else
95+
{
96+
std::cerr << "[cellml_model_definition_instantiate_f] "
97+
<< "Invalid arguments." << std::endl;
98+
}
99+
return code;
100+
}
101+
102+
int cellml_model_definition_get_n_constants_f(void* _ptr)
103+
{
104+
int code = -1;
105+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
106+
if (_ptr && (def = (CellMLModelDefinition*)_ptr) && def->instantiated())
107+
{
108+
code = def->nConstants;
109+
}
110+
else
111+
{
112+
std::cerr << "[cellml_model_definition_get_n_constants_f] "
113+
<< "Invalid arguments." << std::endl;
114+
}
115+
return code;
116+
}
117+
118+
int cellml_model_definition_get_n_rates_f(void* _ptr)
119+
{
120+
int code = -1;
121+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
122+
if (_ptr && (def = (CellMLModelDefinition*)_ptr) && def->instantiated())
123+
{
124+
code = def->nRates;
125+
}
126+
else
127+
{
128+
std::cerr << "[cellml_model_definition_get_n_rates_f] "
129+
<< "Invalid arguments." << std::endl;
130+
}
131+
return code;
132+
}
133+
134+
int cellml_model_definition_get_n_algebraic_f(void* _ptr)
135+
{
136+
int code = -1;
137+
CellMLModelDefinition* def = (CellMLModelDefinition*)NULL;
138+
if (_ptr && (def = (CellMLModelDefinition*)_ptr) && def->instantiated())
139+
{
140+
code = def->nAlgebraic;
141+
}
142+
else
143+
{
144+
std::cerr << "[cellml_model_definition_get_n_algebraic_f] "
145+
<< "Invalid arguments." << std::endl;
146+
}
147+
return code;
148+
}
149+
150+
void cellml_model_definition_call_setup_fixed_constants_f(void* _ptr,
151+
double* constants, double* rates, double* states)
152+
{
153+
// no error checks to optimise?
154+
CellMLModelDefinition* def = (CellMLModelDefinition*)_ptr;
155+
def->SetupFixedConstants(constants,rates,states);
156+
}
157+
158+
void cellml_model_definition_call_compute_rates_f(void* _ptr,
159+
double voi,double* states, double* rates, double* constants,
160+
double* algebraic)
161+
{
162+
// no error checks to optimise?
163+
CellMLModelDefinition* def = (CellMLModelDefinition*)_ptr;
164+
def->ComputeRates(voi,states,rates,constants,algebraic);
165+
}
166+
167+
void cellml_model_definition_call_evaluate_variables_f(void* _ptr,
168+
double voi,double* states, double* rates, double* constants,
169+
double* algebraic)
170+
{
171+
// no error checks to optimise?
172+
CellMLModelDefinition* def = (CellMLModelDefinition*)_ptr;
173+
def->EvaluateVariables(voi,constants,rates,states,algebraic);
174+
}
175+
176+
static char* getAbsoluteURI(const char* uri)
177+
{
178+
if (uri)
179+
{
180+
if (strstr(uri,"://") != NULL)
181+
{
182+
/*printf("URI (%s) already absolute.\n",uri);*/
183+
char* abs = (char*)malloc(strlen(uri)+1);
184+
strcpy(abs,uri);
185+
return(abs);
186+
}
187+
else if (uri[0]=='/')
188+
{
189+
/*printf("URI (%s) absolute path, making absolute URI: ",uri);*/
190+
char* abs = (char*)malloc(strlen(uri)+1+7);
191+
sprintf(abs,"file://%s",uri);
192+
/*printf("%s\n",abs);*/
193+
return(abs);
194+
}
195+
else
196+
{
197+
/* relative filename ? append absoulte path */
198+
/*printf("URI (%s) is relative path, making absolute URI: ",uri);*/
199+
int size = pathconf(".",_PC_PATH_MAX);
200+
char* cwd = (char*)malloc(size);
201+
getcwd(cwd,size);
202+
char* abs = (char*)malloc(strlen(cwd)+strlen(uri)+1+8);
203+
sprintf(abs,"file://%s/%s",cwd,uri);
204+
free(cwd);
205+
/*printf("%s\n",abs);*/
206+
return(abs);
207+
}
208+
}
209+
return((char*)NULL);
210+
}

‎src/CellMLModelDefinitionF.h

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#ifndef _CELLMLMODELDEFINITIONF_H_
2+
#define _CELLMLMODELDEFINITIONF_H_
3+
4+
#ifdef __cplusplus
5+
extern "C"
6+
{
7+
#endif
8+
9+
/**
10+
* Create the CellMLModelDefinition from the provided URI.
11+
* @param uri NULL-terminated string containing the URI of the model definition.
12+
* @return A newly created cellml_model_definition_f object.
13+
*/
14+
void* create_cellml_model_definition_f(const char* uri);
15+
16+
/**
17+
* Destroy an allocated CellMLModelDefinition.
18+
* @param model An existing CellML model definition object
19+
*/
20+
void destroy_cellml_model_definition_f(void** model);
21+
22+
/**
23+
* Set the save temporary files flag.
24+
* @param model The CellML model definition to use.
25+
* @param state Should be set to non-zero to save generated temporary files.
26+
*/
27+
void cellml_model_definition_set_save_temp_files_f(void* model,int state);
28+
29+
/**
30+
* Get the current state of the save temporary files flag.
31+
* @param model The CellML model definition to use.
32+
* @return 1 if the current state is true (save), zero if it is false, and -1 in case of error.
33+
*/
34+
int cellml_model_definition_get_save_temp_files_f(void* model);
35+
36+
/**
37+
* Instantiate the CellML model definition into simulat-able code.
38+
* @return 0 if success; non-zero otherwise.
39+
*/
40+
int cellml_model_definition_instantiate_f(void* model);
41+
42+
/**
43+
* Get the required size of the constants array for the given instantiated model.
44+
* @param model The CellML model definition to use.
45+
* @return The required size of the constants array.
46+
*/
47+
int cellml_model_definition_get_n_constants_f(void* model);
48+
/**
49+
* Get the required size of the rates array for the given instantiated model.
50+
* @param model The CellML model definition to use.
51+
* @return The required size of the rates array.
52+
*/
53+
int cellml_model_definition_get_n_rates_f(void* model);
54+
/**
55+
* Get the required size of the algebraic array for the given instantiated model.
56+
* @param model The CellML model definition to use.
57+
* @return The required size of the algebraic array.
58+
*/
59+
int cellml_model_definition_get_n_algebraic_f(void* model);
60+
61+
/**
62+
* Call the model's SetupFixedConstant method.
63+
* @param model The CellML model definition to use.
64+
* @param constants The array to use for constants.
65+
* @param rates The array to use for rates.
66+
* @param states The array to use for states.
67+
*/
68+
void cellml_model_definition_call_setup_fixed_constants_f(void* model,
69+
double* constants, double* rates, double* states);
70+
71+
/**
72+
* Call the model's ComputeRates method.
73+
* @param model The CellML model definition to use.
74+
* @param voi The current value of the variable of integration.
75+
* @param states The array to use for states.
76+
* @param rates The array to use for rates.
77+
* @param rates The array to use for constants.
78+
* @param rates The array to use for algebraic.
79+
*/
80+
void cellml_model_definition_call_compute_rates_f(void* model,
81+
double voi, double* states, double* rates, double* constants,
82+
double* algebraic);
83+
84+
/**
85+
* Call the model's EvaluateVariables method.
86+
* @param model The CellML model definition to use.
87+
* @param voi The current value of the variable of integration.
88+
* @param states The array to use for states.
89+
* @param rates The array to use for rates.
90+
* @param rates The array to use for constants.
91+
* @param rates The array to use for algebraic.
92+
*/
93+
void cellml_model_definition_call_evaluate_variables_f(void* model,
94+
double voi, double* states, double* rates, double* constants,
95+
double* algebraic);
96+
97+
#ifdef __cplusplus
98+
} /* extern C */
99+
#endif
100+
101+
#endif // _CELLMLMODELDEFINITIONF_H_
102+

‎src/RDFGraph.cpp

+319
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
#include <string.h>
2+
#include <iostream>
3+
#include <string>
4+
#include <vector>
5+
6+
#include <libxml/xmlreader.h>
7+
8+
#include "SimulationDescription.hpp"
9+
#include "RDFGraph.hpp"
10+
#include "namespaces.h"
11+
12+
/* Only need to have one world at a time */
13+
struct RDFWorld
14+
{
15+
librdf_world* world;
16+
int counter;
17+
};
18+
static struct RDFWorld* rdfWorld = (struct RDFWorld*)NULL;
19+
static librdf_world* AccessRDFWorld()
20+
{
21+
if (rdfWorld) ++(rdfWorld->counter);
22+
else
23+
{
24+
rdfWorld = (struct RDFWorld*)malloc(sizeof(struct RDFWorld));
25+
rdfWorld->world = librdf_new_world();
26+
librdf_world_open(rdfWorld->world);
27+
rdfWorld->counter = 1;
28+
}
29+
return rdfWorld->world;
30+
}
31+
static void DeaccessRDFWorld()
32+
{
33+
if (rdfWorld)
34+
{
35+
if (rdfWorld->counter > 1) --(rdfWorld->counter);
36+
else
37+
{
38+
librdf_free_world(rdfWorld->world);
39+
free(rdfWorld);
40+
rdfWorld = (struct RDFWorld*)NULL;
41+
}
42+
}
43+
}
44+
static int rdfWorldAccessCount()
45+
{
46+
if (rdfWorld) return rdfWorld->counter;
47+
else return(0);
48+
}
49+
50+
/* prototype local methods */
51+
static char* getXMLFileContentsAsString(const char* uri);
52+
static int buildSimulationDescription(RDFGraph* graph,void** nodes,int N,
53+
void* user_data);
54+
55+
56+
RDFGraph::RDFGraph()
57+
{
58+
this->world = AccessRDFWorld();
59+
this->storage = (librdf_storage*)NULL;
60+
this->rdfmodel = (librdf_model*)NULL;
61+
this->parser = (librdf_parser*)NULL;
62+
this->uri = (librdf_uri*)NULL;
63+
}
64+
65+
RDFGraph::~RDFGraph()
66+
{
67+
if (this->storage) librdf_free_storage(this->storage);
68+
if (this->rdfmodel) librdf_free_model(this->rdfmodel);
69+
if (this->parser) librdf_free_parser(this->parser);
70+
if (this->uri) librdf_free_uri(this->uri);
71+
DeaccessRDFWorld();
72+
}
73+
74+
void RDFGraph::print(FILE* file)
75+
{
76+
if (file && this->rdfmodel)
77+
{
78+
librdf_model_print(this->rdfmodel,file);
79+
}
80+
else std::cerr << "rdfGraphPrint - Invalid argument(s)\n" << std::endl;
81+
}
82+
83+
int RDFGraph::buildFromURL(const char* uri)
84+
{
85+
int code = -1;
86+
if (this->world && uri)
87+
{
88+
/* do we have any metadata? */
89+
char* metadata = getXMLFileContentsAsString(uri);
90+
/* if not, we can quit now */
91+
if (metadata)
92+
{
93+
/* make an in-memory storage to store our RDF triples */
94+
if (this->storage == NULL)
95+
{
96+
char* identifier = (char*)malloc(16);
97+
sprintf(identifier,"%015d",rdfWorldAccessCount());
98+
//DEBUG(0,"rdfGraphBuildFromURI","Making new storage with id: %s\n",
99+
// identifier);
100+
this->storage = librdf_new_storage(this->world,"memory",
101+
identifier,/*options*/NULL);
102+
free(identifier);
103+
}
104+
/* make a new RDF graph */
105+
if (this->rdfmodel == NULL) this->rdfmodel =
106+
librdf_new_model(this->world,this->storage,/*options*/NULL);
107+
/* and a RDF parser */
108+
if (this->parser == NULL) this->parser =
109+
librdf_new_parser(this->world,/*parser name*/"rdfxml",
110+
/*mime type*/NULL,/*syntax URI*/NULL);
111+
if (this->uri == NULL) this->uri =
112+
librdf_new_uri(this->world,(const unsigned char*)uri);
113+
/* PARSE the metadata string as RDF/XML */
114+
if (librdf_parser_parse_string_into_model(this->parser,
115+
(unsigned char*)metadata,this->uri,this->rdfmodel) == 0) code = 0;
116+
free(metadata);
117+
}
118+
}
119+
else std::cerr << "rdfGraphBuildFromURL - Invalid argument(s)" << std::endl;
120+
return(code);
121+
}
122+
123+
SimulationDescription* RDFGraph::createSimulationDescription()
124+
{
125+
SimulationDescription* description = new SimulationDescription();
126+
// create the SPARQL query to find the simulation
127+
std::string query = "prefix cs: <";
128+
query += CS_NS;
129+
query += ">";
130+
query += " select ?parent ?simulation";
131+
query += " where {";
132+
query += " ?parent cs:simulation ?simulation";
133+
query += " filter isURI(?parent)";
134+
query += " }";
135+
std::vector<std::string> names(2);
136+
names[0] = "parent";
137+
names[1] = "simulation";
138+
int code = this->iterateQueryResults(query.c_str(),names,
139+
&buildSimulationDescription,(void*)description);
140+
if (code != 0)
141+
{
142+
std::cerr << "RDFGraph::createSimulationDescription(): "
143+
<< "error creating simulation description" << std::endl;
144+
delete description;
145+
description = (SimulationDescription*)NULL;
146+
}
147+
return(description);
148+
}
149+
150+
int RDFGraph::iterateQueryResults(const char* query,
151+
const std::vector<std::string>& names,QueryIterFunc func,void* user_data)
152+
{
153+
int code = -1;
154+
if (this->rdfmodel)
155+
{
156+
librdf_query* q = librdf_new_query(this->world,"sparql",NULL,
157+
(unsigned char*)query,NULL);
158+
librdf_query_results* results =
159+
librdf_model_query_execute(this->rdfmodel,q);
160+
if (results)
161+
{
162+
code = 0;
163+
while(!librdf_query_results_finished(results))
164+
{
165+
int N = names.size();
166+
void** nodes = (void**)malloc(sizeof(void*)*N);
167+
int i;
168+
for (i=0;i<N;i++) nodes[i] =
169+
(void*)librdf_query_results_get_binding_value_by_name(
170+
results,names[i].c_str());
171+
if (nodes)
172+
{
173+
code = func(this,nodes,N,user_data);
174+
for (i=0;i<N;i++) librdf_free_node((librdf_node*)nodes[i]);
175+
free(nodes);
176+
}
177+
librdf_query_results_next(results);
178+
if (code != 0) break;
179+
}
180+
librdf_free_query_results(results);
181+
}
182+
librdf_free_query(q);
183+
}
184+
else
185+
{
186+
std::cerr << "iterateQueryResults: missing RDF model" << std::endl;
187+
}
188+
return(code);
189+
}
190+
191+
bool RDFGraph::nodeIsResource(void* _node)
192+
{
193+
int code = 0;
194+
if (_node)
195+
{
196+
librdf_node* node = (librdf_node*)_node;
197+
code = librdf_node_is_resource(node);
198+
}
199+
if (code) return(true);
200+
return(false);
201+
}
202+
203+
char* RDFGraph::nodeGetURI(void* _node)
204+
{
205+
char* uri = (char*)NULL;
206+
if (_node)
207+
{
208+
librdf_node* node = (librdf_node*)_node;
209+
if (librdf_node_is_resource(node)) uri =
210+
(char*)librdf_uri_to_string(librdf_node_get_uri(node));
211+
}
212+
else std::cerr << "rdfGraphGetURI -- Invalid argument(s)" << std::endl;
213+
return(uri);
214+
}
215+
216+
/*
217+
* Local methods
218+
*/
219+
/** Print the contents of the given RDF node */
220+
/*static void printNode(void* _node,FILE* file)
221+
{
222+
if (_node && file)
223+
{
224+
librdf_node* node = (librdf_node*)_node;
225+
librdf_node_print(node,file);
226+
}
227+
else std::cerr << "rdfGraphPrint - Invalid argument(s)" << std::endl;
228+
}*/
229+
230+
/** Get the contents of the given XML file as a standard C string */
231+
static char* getXMLFileContentsAsString(const char* uri)
232+
{
233+
char* string = (char*)NULL;
234+
if (uri)
235+
{
236+
/* ensure startup libxml */
237+
xmlInitParser();
238+
LIBXML_TEST_VERSION;
239+
/* make an xml text reader for the given URI */
240+
xmlTextReaderPtr reader = xmlNewTextReaderFilename(uri);
241+
if (reader != NULL)
242+
{
243+
/* parse and preserve the entire document */
244+
int ret = xmlTextReaderRead(reader);
245+
xmlTextReaderPreservePattern(reader,BAD_CAST "*",NULL);
246+
while (ret == 1) ret = xmlTextReaderRead(reader);
247+
if (ret != 0)
248+
{
249+
std::cerr << "getXMLFileContentsAsString" << uri
250+
<< ": failed to parse" << std::endl;
251+
}
252+
else
253+
{
254+
/* grab the resulting XML document */
255+
xmlDocPtr doc = xmlTextReaderCurrentDoc(reader);
256+
if (doc)
257+
{
258+
/* and dump it into the result string */
259+
xmlChar* s;
260+
int l;
261+
/*xmlDocDump(stdout,doc);*/
262+
xmlDocDumpMemory(doc,&s,&l);
263+
if (s)
264+
{
265+
string = (char*)malloc(strlen((const char*)s)+1);
266+
strcpy(string,(const char*)s);
267+
/*printf("string: **%s**\n",string);*/
268+
xmlFree(s);
269+
}
270+
else std::cerr << "getXMLFileContentsAsString" << uri
271+
<< ": failed to dump to string" << std::endl;
272+
/* free up the XML doc */
273+
xmlFreeDoc(doc);
274+
}
275+
}
276+
/* free the reader */
277+
xmlFreeTextReader(reader);
278+
}
279+
else
280+
{
281+
std::cerr << "getXMLFileContentsAsString - "
282+
<< "Unable to make the XML reader for the uri: " << uri
283+
<< std::endl;
284+
}
285+
/* Shutdown libxml - don't want to as it may be used elsewhere */
286+
//xmlCleanupParser();
287+
}
288+
else std::cerr << "Invalid args: getXMLFileContentsAsString" << std::endl;
289+
return(string);
290+
}
291+
292+
/** Callback function for the iterate query results method to build a simulation description.
293+
* Will only populate the provided simulation description if it is not already a valid description.
294+
*/
295+
static int buildSimulationDescription(RDFGraph* graph,void** nodes,
296+
int N,void* _ptr)
297+
{
298+
int code = -1;
299+
SimulationDescription* description = (SimulationDescription*)_ptr;
300+
if (description->isValid())
301+
{
302+
// already have a valid simulation description, look no further
303+
code = 0;
304+
std::cout << "Already have a valid simulation description" << std::endl;
305+
}
306+
else
307+
{
308+
std::cout << "Setting up simulation description" << std::endl;
309+
void* parent = nodes[0];
310+
if (graph->nodeIsResource(parent))
311+
{
312+
char* modelURI = graph->nodeGetURI(parent);
313+
description->modelURI(modelURI);
314+
free(modelURI);
315+
code = 0;
316+
}
317+
}
318+
return(code);
319+
}

‎src/RDFGraph.hpp

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef _RDFGRAPH_H_
2+
#define _RDFGRAPH_H_
3+
4+
#include <redland.h>
5+
6+
class RDFGraph;
7+
8+
/* User function prototype called in iterate methods */
9+
typedef int (*QueryIterFunc)(RDFGraph*,void**,int,void*);
10+
11+
/**
12+
* A basic wrapper providing the RDF functionality required for openCMISS.
13+
*/
14+
class RDFGraph
15+
{
16+
public:
17+
RDFGraph();
18+
~RDFGraph();
19+
20+
void print(FILE* file);
21+
/**
22+
* Build a RDF graph from a given source URL.
23+
* Create a RDF graph from the given source RDF/XML document. Expects a
24+
* straight RDF/XML document only.
25+
* @param url The URL of the source document.
26+
* @return 0 on success, non-zero for error.
27+
*/
28+
int buildFromURL(const char* url);
29+
/**
30+
* Attempt to find a simulation description it this graph.
31+
* Will look for the first simulation description found in this RDF graph and craete the corresponding simulation description.
32+
* @return The created simulation description, if found; NULL otherwise.
33+
*/
34+
class SimulationDescription* createSimulationDescription();
35+
/**
36+
* Check if the given graph node is a resource node.
37+
* @param node Node pointer to check.
38+
* @return true if node is a resource node; false otherwise.
39+
*/
40+
bool nodeIsResource(void* node);
41+
/**
42+
* Get the URI of the given resource node.
43+
* @return The URI of the given node if possible; NULL otherwise.
44+
*/
45+
char* nodeGetURI(void* node);
46+
47+
private:
48+
librdf_world* world;
49+
librdf_storage* storage;
50+
librdf_model* rdfmodel;
51+
librdf_parser* parser;
52+
librdf_uri* uri;
53+
int iterateQueryResults(const char* query,const std::vector<std::string>& names,
54+
QueryIterFunc func,void* user_data);
55+
};
56+
57+
#endif // _RDFGRAPH_H_

‎src/SimulationDescription.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <string>
2+
#include <iostream>
3+
4+
#include "SimulationDescription.hpp"
5+
6+
bool SimulationDescription::isValid()
7+
{
8+
bool valid = false;
9+
if (mModelURI.size() > 1) valid = true;
10+
return valid;
11+
}
12+
13+
void SimulationDescription::modelURI(const char* uri)
14+
{
15+
mModelURI = std::string(uri);
16+
}
17+
18+
const char* SimulationDescription::modelURI()
19+
{
20+
return mModelURI.c_str();
21+
}

‎src/SimulationDescription.hpp

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef _SIMULATIONDESCRIPTION_H_
2+
#define _SIMULATIONDESCRIPTION_H_
3+
4+
/**
5+
* Contains a complete description of a CellML simulation.
6+
* About the only thing we need from a CellML simulation is the URI of the model to be used in the simulation. For now we are ignoring all other information as openCMISS will override the numerical methods and integration paramters.
7+
*/
8+
class SimulationDescription
9+
{
10+
public:
11+
/**
12+
* Check if the simulation description is currently valid.
13+
* @return true if valid; false otherwise.
14+
*/
15+
bool isValid();
16+
/**
17+
* Set the URI of the CellML model defined for this simulation.
18+
* @param uri The URI of the CellML model.
19+
*/
20+
void modelURI(const char* uri);
21+
/**
22+
* Get the URI of the CellML model defined for this simulation.
23+
* @return The URI of the CellML model.
24+
*/
25+
const char* modelURI();
26+
27+
private:
28+
std::string mModelURI;
29+
};
30+
31+
#endif // _SIMULATIONDESCRIPTION_H_

‎src/ccgs_required_functions.cpp

+396
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,396 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <math.h>
4+
#include <assert.h>
5+
6+
#include "ccgs_required_functions.h"
7+
8+
/* functions all taken from CISSolve.cxx */
9+
double
10+
factorial(double x)
11+
{
12+
double ret = 1.0;
13+
while (x > 0.0)
14+
{
15+
ret *= x;
16+
x -= 1.0;
17+
}
18+
return ret;
19+
}
20+
21+
double arbitrary_log(double value, double logbase)
22+
{
23+
return log(value) / log(logbase);
24+
}
25+
26+
double gcd_pair(double a, double b)
27+
{
28+
uint32_t ai = (uint32_t)fabs(a), bi = (uint32_t)fabs(b);
29+
unsigned int shift = 0;
30+
if (ai == 0)
31+
return bi;
32+
if (bi == 0)
33+
return ai;
34+
#define EVEN(x) ((x&1)==0)
35+
while (EVEN(ai) && EVEN(bi))
36+
{
37+
shift++;
38+
ai >>= 1;
39+
bi >>= 1;
40+
}
41+
do
42+
{
43+
if (EVEN(ai))
44+
ai >>= 1;
45+
else if (EVEN(bi))
46+
bi >>= 1;
47+
else if (ai >= bi)
48+
ai = (ai - bi) >> 1;
49+
else
50+
bi = (bi - ai) >> 1;
51+
}
52+
while (ai > 0);
53+
54+
return (bi << shift);
55+
}
56+
57+
double lcm_pair(double a, double b)
58+
{
59+
return (a * b) / gcd_pair(a, b);
60+
}
61+
62+
double gcd_multi(uint32_t count, ...)
63+
{
64+
va_list val;
65+
double* storage1, *storage2, *t, ret;
66+
uint32_t i, j = 0;
67+
68+
if (count == 0)
69+
return 1.0;
70+
71+
storage1 = new double[count];
72+
assert(storage1 != NULL /* Out of memory? */);
73+
storage2 = new double[count >> 1];
74+
assert(storage2 != NULL /* Out of memory? */);
75+
76+
va_start(val, count);
77+
for (i = 0; i < count - 1; i += 2)
78+
{
79+
double a1, a2;
80+
a1 = va_arg(val, double);
81+
a2 = va_arg(val, double);
82+
storage1[j++] = gcd_pair(a1, a2);
83+
}
84+
if (i < count)
85+
storage1[j++] = va_arg(val, double);
86+
va_end(val);
87+
88+
while (j != 1)
89+
{
90+
count = j;
91+
j = 0;
92+
93+
for (i = 0; i < j - 1; i += 2)
94+
storage2[j++] = gcd_pair(storage1[i], storage1[i + 1]);
95+
if (i < j)
96+
storage2[j++] = storage1[i];
97+
98+
t = storage1;
99+
storage1 = storage2;
100+
storage2 = t;
101+
}
102+
103+
ret = storage1[0];
104+
delete [] storage1;
105+
delete [] storage2;
106+
107+
return ret;
108+
}
109+
110+
double lcm_multi(uint32_t count, ...)
111+
{
112+
va_list val;
113+
double* storage1, *storage2, *t, ret;
114+
uint32_t i, j = 0;
115+
116+
if (count == 0)
117+
return 1.0;
118+
119+
storage1 = new double[count];
120+
assert(storage1 != NULL /* Out of memory? */);
121+
storage2 = new double[count >> 1];
122+
assert(storage2 != NULL /* Out of memory? */);
123+
124+
va_start(val, count);
125+
for (i = 0; i < count - 1; i += 2)
126+
{
127+
double a1, a2;
128+
a1 = va_arg(val, double);
129+
a2 = va_arg(val, double);
130+
storage1[j++] = lcm_pair(a1, a2);
131+
}
132+
if (i < count)
133+
storage1[j++] = va_arg(val, double);
134+
va_end(val);
135+
136+
while (j != 1)
137+
{
138+
count = j;
139+
j = 0;
140+
141+
for (i = 0; i < j - 1; i += 2)
142+
storage2[j++] = lcm_pair(storage1[i], storage1[i + 1]);
143+
if (i < j)
144+
storage2[j++] = storage1[i];
145+
146+
t = storage1;
147+
storage1 = storage2;
148+
storage2 = t;
149+
}
150+
151+
ret = storage1[0];
152+
delete [] storage1;
153+
delete [] storage2;
154+
155+
return ret;
156+
}
157+
158+
double multi_min(uint32_t count, ...)
159+
{
160+
va_list val;
161+
double best, attempt;
162+
if (count == 0)
163+
return strtod("NAN", NULL);
164+
va_start(val, count);
165+
best = va_arg(val, double);
166+
while (--count)
167+
{
168+
attempt = va_arg(val, double);
169+
if (attempt < best)
170+
best = attempt;
171+
}
172+
va_end(val);
173+
174+
return best;
175+
}
176+
177+
double multi_max(uint32_t count, ...)
178+
{
179+
va_list val;
180+
double best, attempt;
181+
if (count == 0)
182+
return strtod("NAN", NULL);
183+
va_start(val, count);
184+
best = va_arg(val, double);
185+
while (--count)
186+
{
187+
attempt = va_arg(val, double);
188+
if (attempt > best)
189+
best = attempt;
190+
}
191+
va_end(val);
192+
193+
return best;
194+
}
195+
196+
double
197+
safe_quotient(double num, double den)
198+
{
199+
if (!isfinite(num) || !isfinite(den))
200+
return strtod("NAN", NULL);
201+
int inum = (int)num, iden = (int)den;
202+
if (iden == 0)
203+
return strtod("NAN", NULL);
204+
205+
return inum / iden;
206+
}
207+
208+
double
209+
safe_remainder(double num, double den)
210+
{
211+
if (!isfinite(num) || !isfinite(den))
212+
return strtod("NAN", NULL);
213+
int inum = (int)num, iden = (int)den;
214+
if (iden == 0)
215+
return strtod("NAN", NULL);
216+
217+
return inum % iden;
218+
}
219+
220+
double
221+
safe_factorof(double num, double den)
222+
{
223+
if (!isfinite(num) || !isfinite(den))
224+
return strtod("NAN", NULL);
225+
int inum = (int)num, iden = (int)den;
226+
if (iden == 0)
227+
return strtod("NAN", NULL);
228+
229+
return ((inum % iden) == 0) ? 1.0 : 0.0;
230+
}
231+
232+
#define NR_RANDOM_STARTS 100
233+
#define NR_MAX_STEPS 1000
234+
#define NR_MAX_STEPS_INITIAL 10
235+
236+
static double
237+
random_double_logUniform()
238+
{
239+
union
240+
{
241+
double asDouble;
242+
#ifdef WIN32
243+
uint16_t asIntegers[4];
244+
#else
245+
uint32_t asIntegers[2];
246+
#endif
247+
} X;
248+
249+
#ifdef WIN32
250+
uint16_t spareRand;
251+
#else
252+
uint32_t spareRand;
253+
#endif
254+
255+
do
256+
{
257+
spareRand = rand();
258+
#ifdef WIN32
259+
X.asIntegers[0] = rand() | ((spareRand & 0x1) << 15);
260+
X.asIntegers[1] = rand() | ((spareRand & 0x2) << 14);
261+
X.asIntegers[2] = rand() | ((spareRand & 0x4) << 13);
262+
X.asIntegers[3] = rand() | ((spareRand & 0x8) << 12);
263+
#else
264+
X.asIntegers[0] = rand() | ((spareRand & 0x1) << 31);
265+
X.asIntegers[1] = rand() | ((spareRand & 0x2) << 30);
266+
#endif
267+
}
268+
while (!isfinite(X.asDouble));
269+
270+
return X.asDouble;
271+
}
272+
273+
static double
274+
take_numeric_derivative
275+
(
276+
double(*func)(double VOI, double *C, double *R, double *S, double *A),
277+
double VOI,
278+
double *C,
279+
double *R,
280+
double *S,
281+
double *A,
282+
double *x
283+
)
284+
{
285+
double saved_x, value0, value1, value2, delta, slope1, slope2, ratio;
286+
saved_x = *x;
287+
/*
288+
* Since we have only 52 bits of mantissa, we need delta to flip only the
289+
* last couple of bits.
290+
*/
291+
delta = saved_x * 1E-10;
292+
value0 = func(VOI, C, R, S, A);
293+
*x -= delta;
294+
value1 = func(VOI, C, R, S, A);
295+
*x = saved_x + delta;
296+
value2 = func(VOI, C, R, S, A);
297+
*x = saved_x;
298+
/* We take two numeric derivatives, so we can compare them. This stops us
299+
* from getting trapped at around discontinuities(which otherwise produce
300+
* very steep trapping slopes).
301+
*/
302+
slope1 = (value0 - value1) / delta;
303+
slope2 = (value2 - value0) / delta;
304+
305+
/* If one slope is zero, return the other... */
306+
if (slope1 == 0.0 || !isfinite(slope1))
307+
return slope2;
308+
if (slope2 == 0.0 || !isfinite(slope2))
309+
return slope1;
310+
311+
ratio = slope1 / slope2;
312+
/* If the slopes are similar, return the average... */
313+
if (ratio > 0.5 && ratio < 2)
314+
return (slope1 + slope2) / 2.0;
315+
/* Otherwise, return the least steep of the two... */
316+
if (fabs(slope1) < fabs(slope2))
317+
return slope1;
318+
return slope2;
319+
}
320+
321+
void
322+
NR_MINIMISE
323+
(
324+
double(*func)(double VOI, double *C, double *R, double *S, double *A),
325+
double VOI,
326+
double *C,
327+
double *R,
328+
double *S,
329+
double *A,
330+
double *x
331+
)
332+
{
333+
double best_X = 0.0, best_fX = INFINITY;
334+
double current_X, current_fX, current_dfX_dX;
335+
uint32_t steps, maxsteps;
336+
uint32_t i;
337+
338+
current_X = *x;
339+
340+
/* We use a 100 random start Newton-Raphson algorithm... */
341+
for (i = 0; i < NR_RANDOM_STARTS; i++)
342+
{
343+
/* Choose a random X as a starting point, except for the first run. */
344+
if (i > 0 || !isfinite(current_X))
345+
current_X = random_double_logUniform();
346+
347+
maxsteps = NR_MAX_STEPS_INITIAL;
348+
for (steps = 0; steps < maxsteps; steps++)
349+
{
350+
*x = current_X;
351+
current_fX = func(VOI, C, R, S, A);
352+
if (!isfinite(current_fX))
353+
{
354+
break;
355+
}
356+
357+
if (best_fX > current_fX)
358+
{
359+
/* We can go past NR_MAX_STEPS_INITIAL steps up to NR_MAX_STEPS steps,
360+
* but only if we keep improving on our previous answer.
361+
*/
362+
maxsteps += 2;
363+
if (maxsteps > NR_MAX_STEPS)
364+
maxsteps = NR_MAX_STEPS;
365+
best_fX = current_fX;
366+
best_X = current_X;
367+
/* This is quite far from 0(relatively speaking for a double) to avoid
368+
* numerical instability issues when the minimum doesn't exist but the
369+
* limit at a point from a particular direction would otherwise be the
370+
* minimum.
371+
*/
372+
if (best_fX <= 1E-250)
373+
{
374+
break;
375+
}
376+
}
377+
378+
current_dfX_dX = take_numeric_derivative(func, VOI, C, R, S, A, x);
379+
/* If it is completely flat, or infinite, we are done with this round. */
380+
if (!isfinite(current_dfX_dX) || current_dfX_dX == 0.0)
381+
{
382+
break;
383+
}
384+
385+
current_X -= current_fX / current_dfX_dX;
386+
if (!isfinite(current_X))
387+
{
388+
break;
389+
}
390+
}
391+
if (best_fX <= 1E-250)
392+
break;
393+
}
394+
395+
*x = best_X;
396+
}

‎src/ccgs_required_functions.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef _CCGS_REQUIRED_FUNCTIONS_H_
2+
#define _CCGS_REQUIRED_FUNCTIONS_H_
3+
4+
#include <inttypes.h>
5+
#include <stdarg.h>
6+
7+
#ifdef __cplusplus
8+
extern "C"
9+
{
10+
#endif
11+
/* The functions which may be used by the code generated by the CCGS */
12+
double factorial(double x);
13+
double arbitrary_log(double value, double logbase);
14+
double gcd_pair(double a, double b);
15+
double lcm_pair(double a, double b);
16+
double gcd_multi(uint32_t size, ...);
17+
double lcm_multi(uint32_t size, ...);
18+
double multi_min(uint32_t size, ...);
19+
double multi_max(uint32_t size, ...);
20+
double safe_quotient(double num, double den);
21+
double safe_remainder(double num, double den);
22+
double safe_factorof(double num, double den);
23+
void NR_MINIMISE(double(*func)(double VOI, double *C, double *R, double *S, double *A),
24+
double VOI,double *C,double *R,double *S,double *A,double *V);
25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
29+
30+
#endif /* _CCGS_REQUIRED_FUNCTIONS_H_ */

‎src/cellml_model_definition.f90

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
! The module for mapping to the C++ (via C) code
2+
MODULE CELLML_MODEL_DEFINITION
3+
USE, INTRINSIC :: ISO_C_BINDING
4+
IMPLICIT NONE
5+
INTERFACE
6+
FUNCTION CREATE_CELLML_MODEL_DEFINITION (URI) &
7+
BIND(C, NAME='create_cellml_model_definition_f')
8+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
9+
CHARACTER, DIMENSION(*) :: URI
10+
TYPE (C_PTR) :: CREATE_CELLML_MODEL_DEFINITION
11+
END FUNCTION CREATE_CELLML_MODEL_DEFINITION
12+
SUBROUTINE DESTROY_CELLML_MODEL_DEFINITION (MODEL) &
13+
BIND(C,NAME='destroy_cellml_model_definition_f')
14+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
15+
TYPE (C_PTR) :: MODEL
16+
END SUBROUTINE DESTROY_CELLML_MODEL_DEFINITION
17+
SUBROUTINE CELLML_MODEL_DEFINITION_SET_SAVE_TEMP_FILES (MODEL,STATE) &
18+
BIND(C,NAME='cellml_model_definition_set_save_temp_files_f')
19+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
20+
TYPE (C_PTR), VALUE :: MODEL
21+
INTEGER (C_INT), VALUE :: STATE
22+
END SUBROUTINE CELLML_MODEL_DEFINITION_SET_SAVE_TEMP_FILES
23+
INTEGER (C_INT) FUNCTION CELLML_MODEL_DEFINITION_GET_SAVE_TEMP_FILES &
24+
(MODEL) &
25+
BIND(C,NAME='cellml_model_definition_get_save_temp_files_f')
26+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
27+
TYPE (C_PTR), VALUE :: MODEL
28+
END FUNCTION CELLML_MODEL_DEFINITION_GET_SAVE_TEMP_FILES
29+
INTEGER (C_INT) FUNCTION CELLML_MODEL_DEFINITION_INSTANTIATE &
30+
(MODEL) &
31+
BIND(C,NAME='cellml_model_definition_instantiate_f')
32+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
33+
TYPE (C_PTR), VALUE :: MODEL
34+
END FUNCTION CELLML_MODEL_DEFINITION_INSTANTIATE
35+
INTEGER (C_INT) FUNCTION CELLML_MODEL_DEFINITION_GET_N_CONSTANTS &
36+
(MODEL) &
37+
BIND(C,NAME='cellml_model_definition_get_n_constants_f')
38+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
39+
TYPE (C_PTR), VALUE :: MODEL
40+
END FUNCTION CELLML_MODEL_DEFINITION_GET_N_CONSTANTS
41+
INTEGER (C_INT) FUNCTION CELLML_MODEL_DEFINITION_GET_N_RATES &
42+
(MODEL) &
43+
BIND(C,NAME='cellml_model_definition_get_n_rates_f')
44+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
45+
TYPE (C_PTR), VALUE :: MODEL
46+
END FUNCTION CELLML_MODEL_DEFINITION_GET_N_RATES
47+
INTEGER (C_INT) FUNCTION CELLML_MODEL_DEFINITION_GET_N_ALGEBRAIC &
48+
(MODEL) &
49+
BIND(C,NAME='cellml_model_definition_get_n_algebraic_f')
50+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_INT
51+
TYPE (C_PTR), VALUE :: MODEL
52+
END FUNCTION CELLML_MODEL_DEFINITION_GET_N_ALGEBRAIC
53+
SUBROUTINE CELLML_MODEL_DEFINITION_CALL_SETUP_FIXED_CONSTANTS &
54+
(MODEL,CONSTANTS,RATES,STATES) &
55+
BIND(C,NAME='cellml_model_definition_call_setup_fixed_constants_f')
56+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_DOUBLE
57+
TYPE (C_PTR), VALUE :: MODEL
58+
REAL (C_DOUBLE) :: CONSTANTS(*)
59+
REAL (C_DOUBLE) :: RATES(*)
60+
REAL (C_DOUBLE) :: STATES(*)
61+
END SUBROUTINE CELLML_MODEL_DEFINITION_CALL_SETUP_FIXED_CONSTANTS
62+
SUBROUTINE CELLML_MODEL_DEFINITION_CALL_COMPUTE_RATES &
63+
(MODEL,VOI,STATES,RATES,CONSTANTS,ALGEBRAIC) &
64+
BIND(C,NAME='cellml_model_definition_call_compute_rates_f')
65+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_DOUBLE
66+
TYPE (C_PTR), VALUE :: MODEL
67+
REAL (C_DOUBLE), VALUE :: VOI
68+
REAL (C_DOUBLE) :: STATES(*)
69+
REAL (C_DOUBLE) :: RATES(*)
70+
REAL (C_DOUBLE) :: CONSTANTS(*)
71+
REAL (C_DOUBLE) :: ALGEBRAIC(*)
72+
END SUBROUTINE CELLML_MODEL_DEFINITION_CALL_COMPUTE_RATES
73+
SUBROUTINE CELLML_MODEL_DEFINITION_CALL_EVALUATE_VARIABLES &
74+
(MODEL,VOI,STATES,RATES,CONSTANTS,ALGEBRAIC) &
75+
BIND(C,NAME='cellml_model_definition_call_evaluate_variables_f')
76+
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR,C_DOUBLE
77+
TYPE (C_PTR), VALUE :: MODEL
78+
REAL (C_DOUBLE), VALUE :: VOI
79+
REAL (C_DOUBLE) :: STATES(*)
80+
REAL (C_DOUBLE) :: RATES(*)
81+
REAL (C_DOUBLE) :: CONSTANTS(*)
82+
REAL (C_DOUBLE) :: ALGEBRAIC(*)
83+
END SUBROUTINE CELLML_MODEL_DEFINITION_CALL_EVALUATE_VARIABLES
84+
END INTERFACE
85+
END MODULE CELLML_MODEL_DEFINITION

‎src/namespaces.h

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef _NAMESPACES_H_
2+
#define _NAMESPACES_H_
3+
4+
#define CS_NS "http://www.cellml.org/metadata/simulation/1.0#"
5+
6+
#endif // _NAMESPACES_H_

‎src/utils.hxx

+231
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
#ifndef _UTILS_HXX_
2+
#define _UTILS_HXX_
3+
4+
#define RETURN_INTO_WSTRING(lhs, rhs) \
5+
wchar_t* tmp_##lhs = rhs; \
6+
std::wstring lhs; \
7+
if (tmp_##lhs) \
8+
{ \
9+
lhs = std::wstring(tmp_##lhs); \
10+
free(tmp_##lhs); \
11+
}
12+
13+
#define RETURN_INTO_STRING(lhs, rhs) \
14+
char* tmp_##lhs = rhs; \
15+
std::string lhs; \
16+
if (tmp_##lhs) \
17+
{ \
18+
lhs = std::string(tmp_##lhs); \
19+
free(tmp_##lhs); \
20+
}
21+
22+
#define QUERY_INTERFACE(lhs, rhs, type) \
23+
if (rhs != NULL) \
24+
{ \
25+
void* _qicast_obj = rhs->query_interface(#type); \
26+
if (_qicast_obj != NULL) \
27+
{ \
28+
lhs = already_AddRefd<iface::type>(reinterpret_cast<iface::type*>(_qicast_obj)); \
29+
} \
30+
else \
31+
lhs = NULL; \
32+
} \
33+
else lhs = NULL;
34+
35+
#define QUERY_INTERFACE_REPLACE(lhs, rhs, type) \
36+
QUERY_INTERFACE(lhs, rhs, type); \
37+
if (rhs != NULL) \
38+
{ \
39+
rhs->release_ref(); \
40+
rhs = NULL; \
41+
}
42+
43+
#define DECLARE_QUERY_INTERFACE(lhs, rhs, type) \
44+
iface::type* lhs; \
45+
QUERY_INTERFACE(lhs, rhs, type)
46+
47+
#define DECLARE_QUERY_INTERFACE_REPLACE(lhs, rhs, type) \
48+
iface::type* lhs; \
49+
QUERY_INTERFACE_REPLACE(lhs, rhs, type)
50+
51+
#define CELLML_TO_VARIABLE_INTERFACE( cellml, variable) \
52+
if (cellml == iface::cellml_api::INTERFACE_IN) variable(Variable::IN); \
53+
else if (cellml == iface::cellml_api::INTERFACE_OUT) \
54+
variable(Variable::OUT); \
55+
else if (cellml == iface::cellml_api::INTERFACE_NONE) \
56+
variable(Variable::NONE); \
57+
else ERROR("CELLML_TO_VARIABLE_INTERFACE","Invalid variable interface\n")
58+
59+
template<class T>
60+
class already_AddRefd
61+
{
62+
public:
63+
already_AddRefd(T* aPtr)
64+
: mPtr(aPtr)
65+
{
66+
}
67+
68+
~already_AddRefd()
69+
{
70+
}
71+
72+
operator T*() const
73+
{
74+
return mPtr;
75+
}
76+
77+
T* getPointer() const
78+
{
79+
return mPtr;
80+
}
81+
private:
82+
T* mPtr;
83+
};
84+
85+
template<class T>
86+
class ObjRef
87+
{
88+
public:
89+
ObjRef()
90+
: mPtr(NULL)
91+
{
92+
}
93+
94+
ObjRef(const ObjRef<T>& aPtr)
95+
{
96+
mPtr = aPtr.getPointer();
97+
if (mPtr != NULL)
98+
mPtr->add_ref();
99+
}
100+
101+
ObjRef(T* aPtr)
102+
: mPtr(aPtr)
103+
{
104+
mPtr->add_ref();
105+
}
106+
107+
ObjRef(const already_AddRefd<T> aar)
108+
{
109+
mPtr = aar.getPointer();
110+
}
111+
112+
~ObjRef()
113+
{
114+
if (mPtr != NULL)
115+
mPtr->release_ref();
116+
}
117+
118+
T* operator-> () const
119+
{
120+
return mPtr;
121+
}
122+
123+
T* getPointer() const
124+
{
125+
return mPtr;
126+
}
127+
128+
operator T* () const
129+
{
130+
return mPtr;
131+
}
132+
133+
void operator= (T* newAssign)
134+
{
135+
if (mPtr == newAssign)
136+
return;
137+
if (mPtr)
138+
mPtr->release_ref();
139+
mPtr = newAssign;
140+
if (newAssign != NULL)
141+
mPtr->add_ref();
142+
}
143+
144+
// We need these explicit forms or the default overloads the templates below.
145+
void operator= (const already_AddRefd<T>& newAssign)
146+
{
147+
T* nap = newAssign.getPointer();
148+
if (mPtr == nap)
149+
return;
150+
if (mPtr)
151+
mPtr->release_ref();
152+
mPtr = nap;
153+
}
154+
155+
void operator= (const ObjRef<T>& newAssign)
156+
{
157+
T* nap = newAssign.getPointer();
158+
if (mPtr == nap)
159+
return;
160+
if (mPtr)
161+
mPtr->release_ref();
162+
mPtr = nap;
163+
if (mPtr != NULL)
164+
mPtr->add_ref();
165+
}
166+
167+
template<class U>
168+
void operator= (const already_AddRefd<U>& newAssign)
169+
{
170+
T* nap = newAssign.getPointer();
171+
if (mPtr == nap)
172+
return;
173+
if (mPtr)
174+
mPtr->release_ref();
175+
mPtr = nap;
176+
}
177+
178+
template<class U>
179+
void operator= (const ObjRef<U>& newAssign)
180+
{
181+
T* nap = newAssign.getPointer();
182+
if (mPtr == nap)
183+
return;
184+
if (mPtr)
185+
mPtr->release_ref();
186+
mPtr = nap;
187+
if (mPtr != NULL)
188+
mPtr->add_ref();
189+
}
190+
191+
private:
192+
T* mPtr;
193+
};
194+
195+
template<class T, class U> bool
196+
operator==(const ObjRef<T>& lhs, const ObjRef<U>& rhs)
197+
{
198+
return (lhs.getPointer() == rhs.getPointer());
199+
}
200+
201+
template<class T, class U> bool
202+
operator!=(const ObjRef<T>& lhs, const ObjRef<U>& rhs)
203+
{
204+
return (lhs.getPointer() != rhs.getPointer());
205+
}
206+
207+
#define RETURN_INTO_OBJREF(lhs, type, rhs) \
208+
ObjRef<type> lhs \
209+
( \
210+
already_AddRefd<type> \
211+
( \
212+
static_cast<type*> \
213+
( \
214+
rhs \
215+
) \
216+
) \
217+
)
218+
219+
#define RETURN_INTO_OBJREFD(lhs, type, rhs) \
220+
ObjRef<type> lhs \
221+
( \
222+
already_AddRefd<type> \
223+
( \
224+
dynamic_cast<type*> \
225+
( \
226+
rhs \
227+
) \
228+
)\
229+
)
230+
231+
#endif /* _UTILS_HXX_ */

0 commit comments

Comments
 (0)
Please sign in to comment.