Nektar++
Loading...
Searching...
No Matches
model.cpp
Go to the documentation of this file.
1<?
2#
3# model.cpp
4# A pype template for Nektar simulation
5#
6# Required variables
7# ---------------------------
8# model A model
9# protocol A pacing protocol
10# ---------------------------
11#
12# This file is derived from Myokit.
13# See http://myokit.org for copyright, sharing, and licensing details.
14#
15import myokit
16import myokit.lib.guess as guess
17import myokit.lib.hh as hh
18import nektar
19
20# Get model
21model.reserve_unique_names(*nektar.keywords)
22model.create_unique_names()
23
24# Find transmembrane potential
25vm = guess.membrane_potential(model)
26
27# Set Vm to first index by swapping if necessary
28indices = {var.qname(): var.indice() for var in model.states()}
29if indices[vm.qname()] != 0:
30 for var, i in indices.items():
31 if i == 0:
32 indices[var] = vm.indice()
33 indices[vm.qname()] = 0
34 break
35
36# Find any gating variables for Rush-Larsen integration
37gate_vars = []
38concentration_vars = []
39inf_vars = {}
40tau_vars = {}
41for var in model.states():
42 if var == vm:
43 continue
44 ret = hh.get_inf_and_tau(var, vm)
45 if ret:
46 gate_vars.append(var)
47 inf_vars[ret[0]] = indices[var.qname()]
48 tau_vars[ret[1]] = len(gate_vars)-1
49 else:
50 concentration_vars.append(var)
51
52# Define lhs function
53def v(var):
54 # if a gate var the outarray is updated with the steady-state
55 if isinstance(var, myokit.Derivative) and var not in gate_vars:
56 return 'outarray[' + str(indices[var.var().qname()]) + '][i]'
57 elif isinstance(var, myokit.Name):
58 var = var.var()
59 if var.is_state():
60 return 'inarray[' + str(indices[var.qname()]) + '][i]'
61 elif var.is_constant():
62 return 'AC_' + var.uname()
63 elif var in tau_vars:
64 return 'm_gates_tau[' + str(tau_vars[var]) + '][i]'
65 elif var in inf_vars:
66 return 'outarray[' + str(inf_vars[var]) + '][i]'
67 else:
68 return 'AV_' + var.uname()
69
70# Create expression writer
71w = nektar.NektarExpressionWriter()
72w.set_lhs_function(v)
73
74# Tab is four spaces
75tab = ' '
76
77# Get equations
78equations = model.solvable_order()
79
80# Get model name
81model_name = name if name is not None else model.name();
82?>
83///////////////////////////////////////////////////////////////////////////////
84//
85// File: <?= model_name ?>.cpp
86//
87// For more information, please see: http://www.nektar.info
88//
89// The MIT License
90//
91// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
92// Department of Aeronautics, Imperial College London (UK), and Scientific
93// Computing and Imaging Institute, University of Utah (USA).
94//
95// Permission is hereby granted, free of charge, to any person obtaining a
96// copy of this software and associated documentation files (the "Software"),
97// to deal in the Software without restriction, including without limitation
98// the rights to use, copy, modify, merge, publish, distribute, sublicense,
99// and/or sell copies of the Software, and to permit persons to whom the
100// Software is furnished to do so, subject to the following conditions:
101//
102// The above copyright notice and this permission notice shall be included
103// in all copies or substantial portions of the Software.
104//
105// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
106// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
107// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
108// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
109// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
110// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
111// DEALINGS IN THE SOFTWARE.
112//
113// Description: <?= model_name ?> cell model.
114// Generated from CellML on <?= myokit.date() ?>
115//
116///////////////////////////////////////////////////////////////////////////////
117
118#include <iostream>
119#include <string>
120
121#include <CardiacEPSolver/CellModels/<?= model_name ?>.h>
122
123namespace Nektar
124{
125
126std::string <?= model_name ?>::className
128 "<?= model_name ?>",
129 <?= model_name ?>::create,
130 "");
131
132<?
133if variants:
134 print('// Register cell model variants')
135 print('std::string ' + model_name + '::lookupIds[' + str(len(variants)) + '] = {')
136 for variant in variants.keys():
137 print(tab + 'LibUtilities::SessionReader::RegisterEnumValue("CellModelVariant",')
138 print(2*tab + '"' + variant + '", ' + model_name + '::e' + variant + '),')
139 print('};')
140 print('\n// Register default variant')
141 print('std::string ' + model_name + '::def =')
142 print(tab + 'LibUtilities::SessionReader::RegisterDefaultSolverInfo(')
143 print(2*tab + '"CellModelVariant", "' + list(variants.keys())[0] + '");')
144?>
145/**
146 *
147 */
148<?= model_name ?>::<?= model_name ?>(
149 const LibUtilities::SessionReaderSharedPtr& pSession,
150 const MultiRegions::ExpListSharedPtr& pField)
151 : CellModel(pSession, pField)
152{
153<?
154if variants:
155 print(tab + 'model_variant = pSession->GetSolverInfoAsEnum<')
156 print(3*tab + model_name + '::Variants>("CellModelVariant");')
157?>
158 m_nvar = <?= model.count_states() ?>;
159
160 // Gating states (Rush-Larsen)
161<?
162for var in gate_vars:
163 print(tab + 'm_gates.push_back(' + str(indices[var.qname()]) + '); // ' + str(var.qname()))
164?>
165 // Remaining states (Forward Euler)
166<?
167for var in concentration_vars:
168 print(tab + 'm_concentrations.push_back(' + str(indices[var.qname()]) + '); // ' + str(var.qname()))
169?>
170
171 // Set values of constants
172<?
173variant_dict = {}
174for label, eqs in equations.items():
175 if eqs.has_equations(const=True):
176 print(tab + '/* ' + label + ' */')
177 for eq in eqs.equations(const=True):
178 # check if included as a variant and will be handled after
179 if variants and eq.lhs.var().qname() in variants[list(variants.keys())[0]]:
180 variant_dict[eq.lhs.var().qname()] = eq.lhs.var()
181 continue
182 print(tab + w.eq(eq) + '; // ' + str(eq.lhs.var().unit()))
183 print('')
184
185if variants:
186 print(tab + 'switch (model_variant) {')
187 for variant_name, constant_dict in variants.items():
188 print(2*tab + 'case e' + variant_name + ':')
189 for name, value in constant_dict.items():
190 print(3*tab + v(variant_dict[name]) + ' = ' + str(value) + ';')
191 print(3*tab + 'break;')
192 print(tab + '}')
193?>}
194
195<?= model_name ?>::~<?= model_name ?>()
196{
197}
198
199
200void <?= model_name ?>::v_Update(
201 const Array<OneD, const Array<OneD, NekDouble> > &inarray,
202 Array<OneD, Array<OneD, NekDouble> > &outarray,
203 [[maybe_unused]] const NekDouble time)
204{
205 ASSERTL0(inarray.data() != outarray.data(),
206 "Must have different arrays for input and output.");
207
208 /* State variable ordering
209<?
210for var in model.states():
211 print(tab + v(var) + ' ' + var.qname())
212?> */
213
214 for (unsigned int i = 0; i < m_nq; ++i)
215 {
216<?
217for label, eqs in equations.items():
218 if eqs.has_equations(const=False):
219 print(2*tab + '/* ' + label + ' */')
220 for eq in eqs.equations(const=False):
221 var = eq.lhs.var()
222 if var in model.bindings():
223 print(2*tab + v(var) + ' = ' + model.binding(var) + ';')
224 elif var in gate_vars:
225 # don't want to fill derivatives of Rush-Larsen gating variables
226 continue
227 else:
228 print(2*tab + w.eq(eq) + ';')
229 print('')
230?> }
231}
232
233void <?= model_name ?>::v_GenerateSummary(SummaryList& s)
234{
235 SolverUtils::AddSummaryItem(s, "Cell model", "<?= model_name ?>");
236}
237
238void <?= model_name ?>::v_SetInitialConditions()
239{
240<?
242 print(tab + 'switch (model_variant) {')
243 for variant_name, variant_inits in initial_states.items():
244 print(2*tab + 'case e' + variant_name + ':')
245 for eq in variant_inits:
246 print(3*tab + 'Vmath::Fill(m_nq, (NekDouble)' + str(eq.rhs) + ', m_cellSol[' + str(indices[eq.lhs.var().qname()]) + '], 1);')
247 print(3*tab + 'break;')
248 print(tab + '}')
249else:
250 for eq in model.inits():
251 print(tab + 'Vmath::Fill(m_nq, (NekDouble)' + str(eq.rhs) + ', m_cellSol[' + str(indices[eq.lhs.var().qname()]) + '], 1);')
252?>
253}
254
255std::string <?= model_name ?>::v_GetCellVarName(size_t idx)
256{
257<?
258print(tab + 'switch (idx) {')
259for var in model.states():
260 print(2*tab + 'case ' + str(var.index()) + ':')
261 print(3*tab + 'return "' + var.name() + '";')
262print(2*tab + 'default:')
263print(3*tab + 'return "unknown";')
264print(tab + '}')
265?>
266}
267
268}
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
std::vector< std::pair< std::string, std::string > > SummaryList
Definition Misc.h:46
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition Misc.cpp:47
std::vector< double > w(NPUPPER)
CellModelFactory & GetCellModelFactory()
Definition CellModel.cpp:46
STL namespace.