roadrunner  2.6.0
Fast simulator for SBML models
SetInitialValueCodeGenBase.h
1 /*
2  *
3  * Created on: Sept Oct 31, 2013
4  * Author: andy
5  */
6 
7 #ifndef SETINITIALVALUECODEGENBASE_H_
8 #define SETINITIALVALUECODEGENBASE_H_
9 
10 #include "CodeGenBase.h"
11 #include "ModelGeneratorContext.h"
12 #include "SymbolForest.h"
13 #include "ASTNodeFactory.h"
14 #include "ModelDataIRBuilder.h"
15 #include "ModelInitialValueSymbolResolver.h"
16 #include "LLVMException.h"
17 #include "rrLogger.h"
18 #include <sbml/Model.h>
19 #include <Poco/Logger.h>
20 #include <vector>
21 
22 namespace rrllvm
23 {
26  typedef bool (*SetInitialValueCodeGenBase_FunctionPtr)(LLVMModelData*, int32_t, double);
27 
28  template <typename Derived, bool substanceUnits>
29  class SetInitialValueCodeGenBase :
30  public CodeGenBase<SetInitialValueCodeGenBase_FunctionPtr>
31  {
32  public:
33  SetInitialValueCodeGenBase(const ModelGeneratorContext& mgc);
34  virtual ~SetInitialValueCodeGenBase();
35 
36  llvm::Value* codeGen();
37 
38  typedef SetInitialValueCodeGenBase_FunctionPtr FunctionPtr;
39 
40  };
41 
42  template <typename Derived, bool substanceUnits>
43  SetInitialValueCodeGenBase<Derived, substanceUnits>::SetInitialValueCodeGenBase(
44  const ModelGeneratorContext& mgc) :
45  CodeGenBase<SetInitialValueCodeGenBase_FunctionPtr>(mgc)
46  {
47  }
48 
49  template <typename Derived, bool substanceUnits>
50  SetInitialValueCodeGenBase<Derived, substanceUnits>::~SetInitialValueCodeGenBase()
51  {
52  }
53 
54  template <typename Derived, bool substanceUnits>
55  llvm::Value* SetInitialValueCodeGenBase<Derived, substanceUnits>::codeGen()
56  {
57  // make the set init value function
58  llvm::Type* argTypes[] = {
59  llvm::PointerType::get(ModelDataIRBuilder::getStructType(this->module), 0),
60  llvm::Type::getInt32Ty(this->context),
61  llvm::Type::getDoubleTy(this->context)
62  };
63 
64  const char* argNames[] = {
65  "modelData", Derived::IndexArgName, "value"
66  };
67 
68  llvm::Value* args[] = { 0, 0, 0 };
69 
70  llvm::BasicBlock* entry = this->codeGenHeader(Derived::FunctionName, llvm::Type::getInt8Ty(this->context),
71  argTypes, argNames, args);
72 
73  StringIntVector ids = static_cast<Derived*>(this)->getIds();
74 
75  ModelInitialValueSymbolResolver loadResolver(args[0], this->modelGenContext);
76 
77  ModelInitialValueStoreSymbolResolver storeResolver(args[0], this->model, this->modelSymbols,
78  this->dataSymbols, this->builder, loadResolver);
79 
80  // default, return false
81  llvm::BasicBlock* def = llvm::BasicBlock::Create(this->context, "default", this->function);
82  this->builder.SetInsertPoint(def);
83 
84  // false (0) retval
85  this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt8Ty(this->context), 0));
86 
87  // write the switch at the func entry point, the switch is also the
88  // entry block terminator
89  this->builder.SetInsertPoint(entry);
90 
91  llvm::SwitchInst* s = this->builder.CreateSwitch(args[1], def, static_cast<unsigned int>(ids.size()));
92 
93  for (int i = 0; i < ids.size(); ++i)
94  {
95  llvm::BasicBlock* block = llvm::BasicBlock::Create(this->context, ids[i].first + "_block", this->function);
96  this->builder.SetInsertPoint(block);
97 
98  // the value we are attempting to store, make a copy in loop scope
99  // because we can modify the copy.
100  llvm::Value* value = args[2];
101 
102  std::string element = ids[i].first;
103 
104  // need to check if we have an amount or concentration and check if we
105  // are asked for asked for an amount or concentration and convert accordingly
106  const libsbml::SBase* sbase = const_cast<libsbml::Model*>(model)->getElementBySId(ids[i].first);
107  if (sbase && sbase->getTypeCode() == libsbml::SBML_SPECIES)
108  {
109  const libsbml::Species* species = static_cast<const libsbml::Species*>(sbase);
110  // get the id of the compartment the species belongs to
111  std::string compId = species->getCompartment();
112 
113  llvm::Value* comp = loadResolver.loadSymbolValue(compId);
114 
115  if (species->getHasOnlySubstanceUnits())
116  {
117  // species is treated as an amount
118  if (!substanceUnits)
119  {
120  // given a conc, convert to amount
121  value = this->builder.CreateFMul(value, comp, ids[i].first + "_amt");
122  }
123  }
124  else
125  {
126  // species is treated as a concentration
127  if (substanceUnits)
128  {
129  // given an amount, need to convert to conc
130  value = this->builder.CreateFDiv(value, comp, ids[i].first + "_value_conc");
131  }
132  }
133  }
134 
135  // load after we've figured the species bits out
136  storeResolver.storeSymbolValue(ids[i].first, value);
137 
138  // true retval
139  this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt8Ty(this->context), 1));
140  s->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(this->context), ids[i].second), block);
141  }
142 
143  return this->verifyFunction();
144  }
145 
147 } /* namespace rrllvm */
148 #endif /* SETINITIALVALUECODEGENBASE_H_ */