├── .gitignore ├── LICENSE ├── MANIFEST.in ├── NOTICE ├── README.md ├── domains ├── contraction │ ├── Lumens2009.mel │ ├── mechanics.mel │ └── rice.mel └── electrophysiology │ ├── HH.mel │ ├── ORd.mel │ ├── ORd_with_TT06_INa.mel │ ├── Passive.mel │ ├── TT06.mel │ ├── continuity.mel │ ├── decker_2009.mel │ ├── fenton_karma_1998_MLR1.mel │ ├── inada_2009.mel │ └── singleCell.mel ├── license_templates ├── cpp └── python ├── melodee ├── __init__.py ├── cardioidGenerator.py ├── carpGenerator.py ├── celerisGenerator.py ├── cellmlConverter.py ├── chasteGenerator.py ├── coinGenerator.py ├── continuityGenerator.py ├── main.py ├── matlabGenerator.py ├── mechCardioidGenerator.py ├── parser.py ├── units.py └── utility.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled python modules. 2 | *.pyc 3 | 4 | # Setuptools distribution folder. 5 | /dist/ 6 | 7 | # Python egg metadata, regenerated from source files by setuptools. 8 | /*.egg-info 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017, Lawrence Livermore National Security, 2 | LLC. Produced at the Lawrence Livermore National Laboratory. Written 3 | by Robert Blake . 4 | 5 | LLNL-CODE-720003. 6 | All rights reserved. 7 | 8 | This file is part of MELODEE. For details, see 9 | http://github.com/llnl/melodee. 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # M E L O D E E 2 | Modular Expression Language for Ordinary Differential Equation Editing 3 | ---------------------------------------------------------------------- 4 | 5 | Author: Robert Clayton Blake III, Lawrence Livermore National Laboratory 6 | 7 | Melodee is a new language for ODE modeling and development. It has been designed to make it easy for domain experts to write modular equation systems. Using a familiar Matlab-like syntax, modelers can describe their systems of interests and combine them in new and novel ways at run time. Existing models can easily be converted to MELODEE because of its familiar semantics and syntax. 8 | 9 | Included in this package are the following files: 10 | * Parser.py 11 | * A parser for the language 12 | * Code-generation tools that can be used to write MELODEE source-to-source translation tools (i.e. convert a MELODEE model to code that solves the equations in a given software suite like Matlab or CVODE) 13 | * Units.py 14 | * Python module handling unit conversions 15 | * Cellml_converter.py 16 | * A CellML conversion tool that converts XML-based [CellML models](http://cellml.org) to the MELODEE syntax 17 | * TT06.mel 18 | * A MELODEE file describing TT06, converted from the [following CellML model](https://models.physiomeproject.org/exposure/a7179d94365ff0c9c0e6eb7c6a787d3d/ten_tusscher_model_2006_IK1Ko_endo_units.cellml/view). The generated MELODEE code was then cleaned up and modified to show off more MELODEE features. 19 | 20 | Requirements: 21 | * Python - language everything is written in 22 | * PLY - for LR parsing 23 | * sympy - for symobolic expression manipulation 24 | 25 | To get started, create a virtual environment and install the package. 26 | 27 | ```bash 28 | virtualenv venv 29 | source venv/bin/activate 30 | pip install -e . 31 | ``` 32 | 33 | ... then run the simulator 34 | ```bash 35 | melodee -g matlab -t modifiedModel -t bclDefault HH.mel domains/electrophysiology/singleCell.mel 36 | ``` 37 | 38 | ----------------- 39 | 40 | This work was performed under the auspices of the United States Department of Energy by the Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. Release Number LLNL-CODE-720003. 41 | 42 | -------------------------------------------------------------------------------- /domains/contraction/Lumens2009.mel: -------------------------------------------------------------------------------- 1 | 2 | integrate time {ms}; 3 | 4 | shared stretch {1}; 5 | shared tension {N}; 6 | 7 | shared actTime {ms}; 8 | 9 | subsystem Lumens2009 { 10 | 11 | 12 | @flag celltype {enum(SLAVA,HUMAN,PAPER)}; 13 | celltype = PAPER; 14 | 15 | if (celltype == HUMAN) { 16 | tau_r = 48; 17 | tau_d = 32; 18 | tau_sc = 425; 19 | sigma_act = 100; 20 | } else if (celltype == PAPER) { 21 | tau_r = 48; 22 | tau_d = 32; 23 | tau_sc = 425; 24 | sigma_act = 120; 25 | } else { 26 | tau_r = 28.1; 27 | tau_d = 33.8; 28 | tau_sc = 292.5; 29 | sigma_act = 60; 30 | } 31 | 32 | C_rest = 0.02; 33 | L_s0 = 1.51; 34 | L_serel = 0.04; 35 | 36 | ls_unloaded = 2; 37 | v_max {um/s} = 0.007; //WARNING, slava has complicated calculations for this parameter. 38 | 39 | diffvar Lsc {um}; 40 | diffvar C {1}; 41 | 42 | ls = stretch * ls_unloaded; 43 | Lsc.init = L_s0; 44 | C.init = C_rest; 45 | /* 46 | if (celltype == PAPER) { 47 | Lsc.init = L_s0; 48 | } else { 49 | Lsc.init = ls - L_serel; 50 | } 51 | if (celltype == PAPER) { 52 | C.init = C_rest; 53 | } else { 54 | C.init = 0; 55 | } 56 | */ 57 | 58 | C_l = tanh(4.0 * pow(Lsc - L_s0, 2)); 59 | T = tau_sc * (0.29 + 0.3 * Lsc); 60 | x = actTime / tau_r; 61 | if (x > 8) { 62 | x = 8; 63 | } 64 | f_rise = 0.02 * pow(8.0 - x, 2) * pow(x,3) * exp(-x); 65 | l_snorm = (ls - Lsc) / L_serel; 66 | Lsc.diff = (l_snorm - 1) * v_max; 67 | 68 | 69 | 70 | C.diff = C_l * f_rise / tau_r + (C_rest - C) / (1 + exp((T - actTime) / tau_d) ) / tau_d; 71 | 72 | provides tension; 73 | if (Lsc - L_s0 < 0) { 74 | tension = 0; 75 | } else if (C < 0) { 76 | tension = 0; 77 | } else { 78 | tension = sigma_act * C * (Lsc - L_s0) * l_snorm; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /domains/contraction/mechanics.mel: -------------------------------------------------------------------------------- 1 | integrate t {ms}; 2 | 3 | shared lambda {1}; 4 | shared lambda_diff {1/ms}; 5 | 6 | subsystem isometric { 7 | @param lambda_constraint {1} = 1; 8 | provides lambda = lambda_constraint; 9 | provides lambda_diff = 0; 10 | } 11 | 12 | /* 13 | shared tension {N}; 14 | 15 | subsystem isotonic { 16 | param tension_constraint {1} = 1; 17 | constraint tension = tension_constraint; 18 | } 19 | */ 20 | 21 | -------------------------------------------------------------------------------- /domains/contraction/rice.mel: -------------------------------------------------------------------------------- 1 | 2 | integrate time {ms}; 3 | 4 | shared lambda {1}; 5 | shared lambda_diff {1/ms}; 6 | shared tension {N}; 7 | 8 | shared Cai {mM}; 9 | 10 | subsystem Rice { 11 | 12 | xbmod = 0.4; 13 | 14 | 15 | xPsi = 2; 16 | kxb = 205; 17 | 18 | 19 | //SLmax = 2.4; 20 | //SLmin = 1.4; 21 | 22 | //SLcol = 2.25; 23 | //PCon_col = 0.02; 24 | //PExp_col = 70; 25 | 26 | 27 | gxb = 140.e-3; 28 | //gxmdc = 60.0; 29 | 30 | // PCon_t = 0.002; 31 | //PExp_t = 10; 32 | 33 | hf = 360.0e-3; 34 | hb = 400.0e-3; 35 | //hbmdc = 0; 36 | //hfmdc = 5; 37 | 38 | sigmap = 1.0; 39 | sigman = 1.0; 40 | 41 | fapp = 5000.e-3; 42 | gapp = 7.0e-3; 43 | gslmod = 6.; 44 | len_thick = 1.65; 45 | len_hbare = 0.1; 46 | len_thin = 1.2; 47 | 48 | kon = 30.e-3; 49 | koffL = 250.e-3; 50 | koffH = 25.e-3; 51 | 52 | 53 | Qkon = 1.5; 54 | Qkoff = 1.3; 55 | Qkn_p = 1.6; 56 | Qkp_n = 1.6; 57 | Qfapp = 6.25; 58 | Qgapp = 2.5; 59 | Qhf = 6.25; 60 | Qhb = 6.25; 61 | Qgxb = 6.25; 62 | 63 | 64 | perm50 = 0.5; 65 | nperm = 15.0; 66 | 67 | kn_p = 500e-3; 68 | kp_n = 50e-3; 69 | 70 | //RTOL = 1e-4; 71 | //Feedback_factor = 1.5; 72 | 73 | 74 | //SLset = 2.3; 75 | SLrest = 1.9; 76 | 77 | 78 | x_0 = 0.007; 79 | 80 | TempCelsius = 36; 81 | //TempKelvin = (273.0 + TempCelsius); 82 | 83 | diffvar N {1}; 84 | diffvar P {1}; 85 | diffvar XBprer {1}; 86 | diffvar XBpostr {1}; 87 | diffvar xXBprer {1/ms}; 88 | diffvar xXBpostr {1/ms}; 89 | diffvar TnCaL {mM}; 90 | diffvar TnCaH {mM}; 91 | 92 | 93 | N.init = 1 - 0.000001; 94 | P.init = 0.000001; 95 | XBprer.init = 0.000001; 96 | XBpostr.init = 0.000001; 97 | xXBprer.init = 0.000001; 98 | xXBpostr.init = x_0; 99 | TnCaL.init = 0.000001; 100 | TnCaH.init = 0.000001; 101 | 102 | SSXBpostr = fapp * hf / 103 | (gxb * hf + fapp * hf + gxb * gapp + hb * fapp + hb * gapp + gxb*fapp); 104 | 105 | force_coeff = 1.0 / x_0 / SSXBpostr; 106 | 107 | konT = kon * pow(Qkon, (TempCelsius - 37) / 10.); 108 | koffLT = koffL * pow(Qkoff, (TempCelsius - 37) / 10.); 109 | koffHT = koffH * pow(Qkoff, (TempCelsius - 37) / 10.); 110 | 111 | 112 | Ca_concentration = Cai; 113 | 114 | TnCaL.diff = konT * Ca_concentration * (1.0 - TnCaL) - koffLT * TnCaL; 115 | TnCaH.diff = konT * Ca_concentration * (1.0 - TnCaH) - koffHT * TnCaH; 116 | 117 | rl = lambda * SLrest; 118 | sovr_ze = Min(len_thick / 2., rl / 2.); 119 | sovr_cle = Max(rl / 2. - (rl - len_thin), len_hbare / 2.); 120 | len_sovr = sovr_ze - sovr_cle; 121 | SOVFThick = len_sovr * 2. / (len_thick - len_hbare); 122 | SOVFThin = len_sovr / len_thin; 123 | 124 | perm = (1.0 - SOVFThin) * TnCaL + SOVFThin * TnCaH; 125 | permtot = sqrt((1.0 / (1.0 + pow((perm50 / perm), nperm)))); 126 | 127 | /*if(!isfinite(permtot)) { 128 | permtot = 0.00000001; 129 | } 130 | */ 131 | 132 | if(permtot < 0.00000001) { 133 | permtot = 0.00000001; 134 | } 135 | 136 | if(100.0 < 1.0 / permtot) { 137 | inprmt = 100.0; 138 | } else { 139 | inprmt = 1.0 / permtot; 140 | } 141 | 142 | 143 | kn_pT = kn_p * permtot * pow(Qkn_p, (TempCelsius - 37.) / 10.); 144 | kp_nT = kp_n * inprmt * pow(Qkp_n, (TempCelsius - 37.) / 10.); 145 | 146 | fappT = fapp * xbmod * pow(Qfapp, (TempCelsius - 37.) / 10.); 147 | 148 | gapslmd = 1.0 + (1.0 - SOVFThick) * gslmod; 149 | gappT = gapp * gapslmd * xbmod * pow(Qgapp, (TempCelsius - 37) / 10.); 150 | 151 | 152 | hfmd = exp(-sign(xXBprer) * 5.0 * ((xXBprer / x_0) * (xXBprer / x_0))); 153 | hfT = hf * hfmd * xbmod * pow(Qhf, (TempCelsius - 37) / 10.); 154 | hbT = hb * xbmod * pow(Qhb, (TempCelsius - 37) / 10.); 155 | 156 | if(x_0 - xXBpostr > 0) { 157 | gxbmd = exp(sigmap * ((x_0 - xXBpostr) / x_0) * ((x_0 - xXBpostr) / x_0)); 158 | } else { 159 | gxbmd = exp(sigman * (((xXBpostr - x_0) / x_0) * (xXBpostr - x_0) / x_0)); 160 | } 161 | 162 | gxbT = gxb * gxbmd * xbmod * pow(Qgxb, (TempCelsius - 37.) / 10.); 163 | 164 | 165 | delta_SL = lambda_diff * SLrest; 166 | 167 | 168 | N.diff = -kn_pT * N + kp_nT * P; 169 | P.diff = -kp_nT * P + kn_pT * N - fappT * P + gappT * XBprer + gxbT * XBpostr; 170 | XBprer.diff = fappT * P - gappT * XBprer - hfT * XBprer + hbT * XBpostr; 171 | XBpostr.diff = hfT * XBprer - hbT * XBpostr - gxbT * XBpostr; 172 | 173 | dtyf_prer = (hbT * fappT + gxbT * fappT) / (fappT * hfT + gxbT * hfT + gxbT * gappT + hbT * fappT + hbT * gappT + gxbT * fappT); 174 | dtyf_postr = fappT * hfT / (fappT * hfT + gxbT * hfT + gxbT * gappT + hbT * fappT + hbT * gappT + gxbT * fappT); 175 | 176 | v = delta_SL; 177 | 178 | if(delta_SL > 0.1) { 179 | v = 0.1; 180 | } 181 | 182 | if(delta_SL < -0.1) { 183 | v = -0.1; 184 | } 185 | 186 | xXBprer.diff = v / 2. + 187 | xPsi / dtyf_prer * (-xXBprer * fappT + (xXBpostr - x_0 - xXBprer) * hbT); 188 | xXBpostr.diff = v / 2. + 189 | xPsi / dtyf_postr * ((x_0 + xXBprer - xXBpostr)) * hfT; 190 | 191 | 192 | provides tension = kxb * SOVFThick * ( xXBpostr*XBpostr + xXBprer*XBprer) * force_coeff; 193 | } 194 | 195 | shared bcl_time {ms}; 196 | 197 | subsystem Rice_normal_calcium { 198 | param scale_Ca_amp {1} = 1; 199 | 200 | tau1 = 35; 201 | tau2 = 170; 202 | Ca_amp = 1.0 * scale_Ca_amp; 203 | Ca_amp1 = 0.7 * scale_Ca_amp; 204 | Cad = 0.09; 205 | betta = pow(tau1 / tau2, -1.0 / (tau1 / tau2 - 1)) - pow(tau1 / tau2, -1.0 / (1 - tau2 / tau1)); 206 | 207 | provides Cai; 208 | res = (Ca_amp - Cad) / betta * (exp(-bcl_time / tau1) - exp(-bcl_time / tau2)) + Cad; 209 | 210 | if(res > Ca_amp1) { 211 | Cai = Ca_amp1; 212 | } else { 213 | Cai = (Ca_amp - Cad) / betta * (exp(-bcl_time / tau1) - exp(-bcl_time / tau2)) + Cad; 214 | } 215 | } 216 | 217 | -------------------------------------------------------------------------------- /domains/electrophysiology/HH.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate time {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | shared E_Na {mV}; 34 | subsystem HH { 35 | 36 | shared Iion_area {uA/cm^2}; 37 | provides E_R {mV} = -75; 38 | provides E_Na {mV} = (E_R+115{mV}); 39 | subsystem leakage_current { 40 | E_L {mV} = (E_R+10.613{mV}); 41 | @param g_L {mS/cm^2} = 0.3; 42 | i_L {uA/cm^2} = g_L*(V-E_L); 43 | provides accum Iion_area += i_L; 44 | } 45 | subsystem potassium_channel { 46 | shared n {1}; 47 | subsystem potassium_channel_n_gate { 48 | provides diffvar n {1}; 49 | alpha_n {1/ms} = -0.01{1/mV/ms}*(V+65{mV})/(exp(-(V+65{mV})/10{mV})-1{1}); 50 | beta_n {1/ms} = 0.125{1/ms}*exp((V+75{mV})/80{mV}); 51 | n.init = 0.325; 52 | n.diff = (alpha_n*(1-n)-beta_n*n); 53 | } 54 | E_K {mV} = (E_R-12{mV}); 55 | g_K {mS/cm^2} = 36; 56 | i_K {uA/cm^2} = g_K*n^4*(V-E_K); 57 | provides accum Iion_area += i_K; 58 | } 59 | subsystem sodium_channel { 60 | shared h {1}; 61 | shared m {1}; 62 | subsystem sodium_channel_h_gate { 63 | provides diffvar h {1}; 64 | alpha_h {1/ms} = 0.07{1/ms}*exp(-(V+75{mV})/20{mV}); 65 | beta_h {1/ms} = 1{1/ms}/(exp(-(V+45{mV})/10{mV})+1); 66 | h.init = 0.6; 67 | h.diff = (alpha_h*(1-h)-beta_h*h); 68 | } 69 | subsystem sodium_channel_m_gate { 70 | provides diffvar m {1}; 71 | alpha_m {1/ms} = -0.1{1/mV/ms}*(V+50{mV})/(exp(-(V+50{mV})/10{mV})-1); 72 | beta_m {1/ms} = 4{1/ms}*exp(-(V+75{mV})/18{mV}); 73 | m.init = 0.05; 74 | m.diff = (alpha_m*(1-m)-beta_m*m); 75 | } 76 | g_Na {mS/cm^2} = 120; 77 | i_Na {uA/cm^2} = g_Na*m^3*h*(V-E_Na); 78 | provides accum Iion_area += i_Na; 79 | } 80 | provides V_init = -75; 81 | @param Cm {uF/cm^2} = 1; 82 | provides accum Iion += Iion_area/Cm; 83 | } 84 | 85 | subsystem newINa { 86 | diffvar m {1}; 87 | diffvar j {1}; 88 | diffvar h {1}; 89 | 90 | alpha_h = ((V < -40) ? 0.057*exp(-(V+80)/6.8) : 0); 91 | beta_h = ((V < -40) ? (2.7*exp(0.079*V)+310000*exp(0.3485*V)) : 0.77/0.13*(1+exp((V+10.66)/-11.1))); 92 | h_inf = 1/pow((1+exp((V+71.55)/7.43)),2); 93 | tau_h = 1/(alpha_h+beta_h); 94 | h.init = 0.7573; 95 | h.diff = (h_inf-h)/tau_h; 96 | 97 | alpha_j = ((V < -40) ? (-25428*exp(0.2444*V)-6.948e-6*exp(-0.04391*V))*(V+37.78)/1/(1+exp(0.311*(V+79.23))) : 0); 98 | beta_j = ((V < -40) ? 0.02424*exp(-0.01052*V)/(1+exp(-0.1378*(V+40.14))) : 0.6*exp(0.057*V)/(1+exp(-0.1*(V+32)))); 99 | j_inf = 1/pow((1+exp((V+71.55)/7.43)),2); 100 | tau_j = 1/(alpha_j+beta_j); 101 | j.init = 0.7225; 102 | j.diff = (j_inf-j)/tau_j; 103 | 104 | alpha_m = 1/(1+exp((-60-V)/5)); 105 | beta_m = (0.1/(1+exp((V+35)/5))+0.1/(1+exp((V-50)/200))); 106 | m_inf = 1/pow((1+exp((-56.86-V)/9.03)),2); 107 | tau_m = 1*alpha_m*beta_m; 108 | m.init = 0.00155; 109 | m.diff = (m_inf-m)/tau_m; 110 | 111 | @param g_Na {mS/cm^2} = 14.838; 112 | i_Na = g_Na*pow(m,3)*h*j*(V-E_Na); 113 | provides accum i_Natot {uA/cm^2} += i_Na; 114 | } 115 | 116 | subsystem modifiedModel { 117 | use HH - .sodium_channel; 118 | use newINa as INa { 119 | export i_Natot as Iion; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /domains/electrophysiology/ORd.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate time {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | subsystem ORd { 34 | @external(Vm) V; 35 | provides @interp(-100,100,1e-2) v {mV} = V; 36 | //provides v {mV} = V; 37 | provides V_init = -85; 38 | 39 | diffvar nai {mM}; 40 | diffvar nass {mM}; 41 | diffvar ki {mM}; 42 | diffvar kss {mM}; 43 | diffvar @interp(1e-5,1e-3,1e-5) cai {mM}; 44 | //diffvar cai {mM}; 45 | diffvar cass {mM}; 46 | diffvar cansr {mM}; 47 | diffvar cajsr {mM}; 48 | diffvar Jrelnp {mM/ms}; 49 | diffvar Jrelp {mM/ms}; 50 | diffvar CaMKt {mM}; 51 | nai.init=7; 52 | nass.init=7; 53 | ki.init=145; 54 | kss.init=145; 55 | cai.init=1.0e-4; 56 | cass.init=1.0e-4; 57 | cansr.init=1.2; 58 | cajsr.init=1.2; 59 | Jrelnp.init=0; 60 | Jrelp.init=0; 61 | CaMKt.init=0; 62 | 63 | @param celltype {enum(ENDO,MID,EPI)} = ENDO; 64 | 65 | nao=140.0; 66 | cao=1.8; 67 | ko=5.4; 68 | 69 | //physical constants 70 | R=8314.0; 71 | T=310.0; 72 | F=96485.0; 73 | 74 | //cell geometry 75 | L=0.01; 76 | rad=0.0011; 77 | vcell=1000*3.14*rad*rad*L; 78 | Ageo=2*3.14*rad*rad+2*3.14*rad*L; 79 | Acap=2*Ageo; 80 | vmyo=0.68*vcell; 81 | vnsr=0.0552*vcell; 82 | vjsr=0.0048*vcell; 83 | vss=0.02*vcell; 84 | 85 | //reversal potentials 86 | provides ENa {mV} = (R*T/F)*log(nao/nai); 87 | EK=(R*T/F)*log(ko/ki); 88 | PKNa=0.01833; 89 | EKs=(R*T/F)*log((ko+PKNa*nao)/(ki+PKNa*nai)); 90 | 91 | //convenient shorthand calculations 92 | vffrt=v*F*F/(R*T); 93 | vfrt=v*F/(R*T); 94 | 95 | //CaMK constants 96 | provides KmCaMK {mM} =0.15; 97 | aCaMK=0.05; 98 | bCaMK=0.00068; 99 | CaMKo=0.05; 100 | KmCaM=0.0015; 101 | 102 | //update CaMK 103 | CaMKb=CaMKo*(1.0-CaMKt)/(1.0+KmCaM/cass); 104 | provides CaMKa {mM} =CaMKb+CaMKt; 105 | CaMKt.diff=aCaMK*CaMKb*(CaMKb+CaMKt)-bCaMK*CaMKt; 106 | 107 | //// Membrane Currents 108 | shared INa {uA/uF}; 109 | shared tm {ms}; 110 | subsystem sodium_current { 111 | diffvar @gate m j hf hs hsp jp {1}; 112 | m.init=0; 113 | hf.init=1; 114 | hs.init=1; 115 | j.init=1; 116 | hsp.init=1; 117 | jp.init=1; 118 | 119 | mss=1.0/(1.0+exp((-(v+39.57))/9.871)); 120 | provides tm = 1.0/(6.765*exp((v+11.64)/34.77)+8.552*exp(-(v+77.42)/5.955)); 121 | hss=1.0/(1+exp((v+82.90)/6.086)); 122 | thf=1.0/(1.432e-5*exp(-(v+1.196)/6.285)+6.149*exp((v+0.5096)/20.27)); 123 | jss=hss; 124 | tj=2.038+1.0/(0.02136*exp(-(v+100.6)/8.281)+0.3052*exp((v+0.9941)/38.45)); 125 | 126 | m.diff=(mss-m)/tm; 127 | hf.diff=(hss-hf)/thf; 128 | j.diff=(jss-j)/tj; 129 | 130 | ths=1.0/(0.009794*exp(-(v+17.95)/28.05)+0.3343*exp((v+5.730)/56.66)); 131 | hs.diff=(hss-hs)/ths; 132 | hspss=1.0/(1+exp((v+89.1)/6.086)); 133 | thsp=3.0*ths; 134 | hsp.diff=(hspss-hsp)/thsp; 135 | tjp=1.46*tj; 136 | jp.diff=(jss-jp)/tjp; 137 | 138 | Ahf=0.99; 139 | Ahs=1.0-Ahf; 140 | h=Ahf*hf+Ahs*hs; 141 | hp=Ahf*hf+Ahs*hsp; 142 | fINap=(1.0/(1.0+KmCaMK/CaMKa)); 143 | GNa=75; 144 | provides INa=GNa*(v-ENa)*m*m*m*((1.0-fINap)*h*j+fINap*hp*jp); 145 | 146 | } 147 | 148 | diffvar @gate mL hL hLp {1}; 149 | mL.init=0; 150 | hL.init=1; 151 | hLp.init=1; 152 | 153 | mLss=1.0/(1.0+exp((-(v+42.85))/5.264)); 154 | tmL=tm; 155 | mL.diff=(mLss-mL)/tmL; 156 | hLss=1.0/(1.0+exp((v+87.61)/7.488)); 157 | thL=200.0; 158 | hL.diff=(hLss-hL)/thL; 159 | hLpss=1.0/(1.0+exp((v+93.81)/7.488)); 160 | thLp=3.0*thL; 161 | hLp.diff=(hLpss-hLp)/thLp; 162 | GNaL=0.0075; 163 | if (celltype==MID) 164 | { 165 | GNaL*=0.6; 166 | } 167 | fINaLp=(1.0/(1.0+KmCaMK/CaMKa)); 168 | INaL=GNaL*(v-ENa)*mL*((1.0-fINaLp)*hL+fINaLp*hLp); 169 | 170 | diffvar @gate a iF iS ap iFp iSp {1}; 171 | a.init=0; 172 | iF.init=1; 173 | iS.init=1; 174 | ap.init=0; 175 | iFp.init=1; 176 | iSp.init=1; 177 | 178 | ass=1.0/(1.0+exp((-(v-14.34))/14.82)); 179 | ta=1.0515/(1.0/(1.2089*(1.0+exp(-(v-18.4099)/29.3814)))+3.5/(1.0+exp((v+100.0)/29.3814))); 180 | a.diff=(ass-a)/ta; 181 | iss=1.0/(1.0+exp((v+43.94)/5.711)); 182 | if (celltype==MID) 183 | { 184 | delta_epi=1.0-(0.95/(1.0+exp((v+70.0)/5.0))); 185 | } 186 | else 187 | { 188 | delta_epi=1.0; 189 | } 190 | tiF=4.562+1/(0.3933*exp((-(v+100.0))/100.0)+0.08004*exp((v+50.0)/16.59)); 191 | tiS=23.62+1/(0.001416*exp((-(v+96.52))/59.05)+1.780e-8*exp((v+114.1)/8.079)); 192 | tiF*=delta_epi; 193 | tiS*=delta_epi; 194 | AiF=1.0/(1.0+exp((v-213.6)/151.2)); 195 | AiS=1.0-AiF; 196 | iF.diff=(iss-iF)/tiF; 197 | iS.diff=(iss-iS)/tiS; 198 | i=AiF*iF+AiS*iS; 199 | apss=1.0/(1.0+exp((-(v-24.34))/14.82)); 200 | ap.diff=(apss-ap)/ta; 201 | dti_develop=1.354+1.0e-4/(exp((v-167.4)/15.89)+exp(-(v-12.23)/0.2154)); 202 | dti_recover=1.0-0.5/(1.0+exp((v+70.0)/20.0)); 203 | tiFp=dti_develop*dti_recover*tiF; 204 | tiSp=dti_develop*dti_recover*tiS; 205 | iFp.diff=(iss-iFp)/tiFp; 206 | iSp.diff=(iss-iSp)/tiSp; 207 | ip=AiF*iFp+AiS*iSp; 208 | Gto=0.02; 209 | if (celltype==MID) 210 | { 211 | Gto*=4.0; 212 | } 213 | else if (celltype==EPI) 214 | { 215 | Gto*=4.0; 216 | } 217 | fItop=(1.0/(1.0+KmCaMK/CaMKa)); 218 | Ito=Gto*(v-EK)*((1.0-fItop)*a*i+fItop*ap*ip); 219 | 220 | diffvar @gate d ff fs fcaf fcas nca ffp fcafp {1}; 221 | diffvar @interp(0,1,1e-4) @gate jca {1}; 222 | //diffvar @gate jca {1}; 223 | d.init=0; 224 | ff.init=1; 225 | fs.init=1; 226 | fcaf.init=1; 227 | fcas.init=1; 228 | jca.init=1; 229 | nca.init=0; 230 | ffp.init=1; 231 | fcafp.init=1; 232 | 233 | dss=1.0/(1.0+exp((-(v+3.940))/4.230)); 234 | td=0.6+1.0/(exp(-0.05*(v+6.0))+exp(0.09*(v+14.0))); 235 | d.diff=(dss-d)/td; 236 | fss=1.0/(1.0+exp((v+19.58)/3.696)); 237 | tff=7.0+1.0/(0.0045*exp(-(v+20.0)/10.0)+0.0045*exp((v+20.0)/10.0)); 238 | tfs=1000.0+1.0/(0.000035*exp(-(v+5.0)/4.0)+0.000035*exp((v+5.0)/6.0)); 239 | Aff=0.6; 240 | Afs=1.0-Aff; 241 | ff.diff=(fss-ff)/tff; 242 | fs.diff=(fss-fs)/tfs; 243 | f=Aff*ff+Afs*fs; 244 | fcass=fss; 245 | tfcaf=7.0+1.0/(0.04*exp(-(v-4.0)/7.0)+0.04*exp((v-4.0)/7.0)); 246 | tfcas=100.0+1.0/(0.00012*exp(-v/3.0)+0.00012*exp(v/7.0)); 247 | Afcaf=0.3+0.6/(1.0+exp((v-10.0)/10.0)); 248 | Afcas=1.0-Afcaf; 249 | fcaf.diff=(fcass-fcaf)/tfcaf; 250 | fcas.diff=(fcass-fcas)/tfcas; 251 | fca=Afcaf*fcaf+Afcas*fcas; 252 | tjca=75.0; 253 | jca.diff=(fcass-jca)/tjca; 254 | tffp=2.5*tff; 255 | ffp.diff=(fss-ffp)/tffp; 256 | fp=Aff*ffp+Afs*fs; 257 | tfcafp=2.5*tfcaf; 258 | fcafp.diff=(fcass-fcafp)/tfcafp; 259 | fcap=Afcaf*fcafp+Afcas*fcas; 260 | Kmn=0.002; 261 | k2n=1000.0; 262 | km2n=jca*1.0; 263 | anca=1.0/(k2n/km2n+pow(1.0+Kmn/cass,4.0)); 264 | nca.diff=anca*k2n-nca*km2n; 265 | PhiCaL=4.0*vffrt*(cass*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0); 266 | PhiCaNa=1.0*vffrt*(0.75*nass*exp(1.0*vfrt)-0.75*nao)/(exp(1.0*vfrt)-1.0); 267 | PhiCaK=1.0*vffrt*(0.75*kss*exp(1.0*vfrt)-0.75*ko)/(exp(1.0*vfrt)-1.0); 268 | zca=2.0; 269 | PCa=0.0001; 270 | if (celltype==MID) 271 | { 272 | PCa*=1.2; 273 | } 274 | else if (celltype==EPI) 275 | { 276 | PCa*=2.5; 277 | } 278 | PCap=1.1*PCa; 279 | PCaNa=0.00125*PCa; 280 | PCaK=3.574e-4*PCa; 281 | PCaNap=0.00125*PCap; 282 | PCaKp=3.574e-4*PCap; 283 | fICaLp=(1.0/(1.0+KmCaMK/CaMKa)); 284 | ICaL=(1.0-fICaLp)*PCa*PhiCaL*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCap*PhiCaL*d*(fp*(1.0-nca)+jca*fcap*nca); 285 | ICaNa=(1.0-fICaLp)*PCaNa*PhiCaNa*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaNap*PhiCaNa*d*(fp*(1.0-nca)+jca*fcap*nca); 286 | ICaK=(1.0-fICaLp)*PCaK*PhiCaK*d*(f*(1.0-nca)+jca*fca*nca)+fICaLp*PCaKp*PhiCaK*d*(fp*(1.0-nca)+jca*fcap*nca); 287 | 288 | 289 | diffvar @gate xrf {1}; 290 | diffvar @gate xrs {1}; 291 | xrf.init=0; 292 | xrs.init=0; 293 | 294 | xrss=1.0/(1.0+exp((-(v+8.337))/6.789)); 295 | txrf=12.98+1.0/(0.3652*exp((v-31.66)/3.869)+4.123e-5*exp((-(v-47.78))/20.38)); 296 | txrs=1.865+1.0/(0.06629*exp((v-34.70)/7.355)+1.128e-5*exp((-(v-29.74))/25.94)); 297 | Axrf=1.0/(1.0+exp((v+54.81)/38.21)); 298 | Axrs=1.0-Axrf; 299 | xrf.diff=(xrss-xrf)/txrf; 300 | xrs.diff=(xrss-xrs)/txrs; 301 | xr=Axrf*xrf+Axrs*xrs; 302 | rkr=1.0/(1.0+exp((v+55.0)/75.0))*1.0/(1.0+exp((v-10.0)/30.0)); 303 | GKr=0.046; 304 | if (celltype==MID) 305 | { 306 | GKr*=1.3; 307 | } 308 | else if (celltype==EPI) 309 | { 310 | GKr*=0.8; 311 | } 312 | IKr=GKr*sqrt(ko/5.4)*xr*rkr*(v-EK); 313 | 314 | diffvar @gate xs1 {1}; 315 | diffvar @gate xs2 {1}; 316 | xs1.init=0; 317 | xs2.init=0; 318 | 319 | xs1ss=1.0/(1.0+exp((-(v+11.60))/8.932)); 320 | txs1=817.3+1.0/(2.326e-4*exp((v+48.28)/17.80)+0.001292*exp((-(v+210.0))/230.0)); 321 | xs1.diff=(xs1ss-xs1)/txs1; 322 | xs2ss=xs1ss; 323 | txs2=1.0/(0.01*exp((v-50.0)/20.0)+0.0193*exp((-(v+66.54))/31.0)); 324 | xs2.diff=(xs2ss-xs2)/txs2; 325 | KsCa=1.0+0.6/(1.0+pow(3.8e-5/cai,1.4)); 326 | GKs=0.0034; 327 | if (celltype==MID) 328 | { 329 | GKs*=1.4; 330 | } 331 | IKs=GKs*KsCa*xs1*xs2*(v-EKs); 332 | 333 | diffvar @gate xk1 {1}; 334 | xk1.init=1; 335 | 336 | xk1ss=1.0/(1.0+exp(-(v+2.5538*ko+144.59)/(1.5692*ko+3.8115))); 337 | txk1=122.2/(exp((-(v+127.2))/20.36)+exp((v+236.8)/69.33)); 338 | xk1.diff=(xk1ss-xk1)/txk1; 339 | rk1=1.0/(1.0+exp((v+105.8-2.6*ko)/9.493)); 340 | GK1=0.1908; 341 | if (celltype==MID) 342 | { 343 | GK1*=1.2; 344 | } 345 | else if (celltype==EPI) 346 | { 347 | GK1*=1.3; 348 | } 349 | IK1=GK1*sqrt(ko)*rk1*xk1*(v-EK); 350 | 351 | kna1=15.0; 352 | kna2=5.0; 353 | kna3=88.12; 354 | kasymm=12.5; 355 | wna=6.0e4; 356 | wca=6.0e4; 357 | wnaca=5.0e3; 358 | kcaon=1.5e6; 359 | kcaoff=5.0e3; 360 | qna=0.5224; 361 | qca=0.1670; 362 | hca=exp((qca*v*F)/(R*T)); 363 | hna=exp((qna*v*F)/(R*T)); 364 | h1=1+nai/kna3*(1+hna); 365 | h2=(nai*hna)/(kna3*h1); 366 | h3=1.0/h1; 367 | h4=1.0+nai/kna1*(1+nai/kna2); 368 | h5=nai*nai/(h4*kna1*kna2); 369 | h6=1.0/h4; 370 | h7=1.0+nao/kna3*(1.0+1.0/hna); 371 | h8=nao/(kna3*hna*h7); 372 | h9=1.0/h7; 373 | h10=kasymm+1.0+nao/kna1*(1.0+nao/kna2); 374 | h11=nao*nao/(h10*kna1*kna2); 375 | h12=1.0/h10; 376 | k1=h12*cao*kcaon; 377 | k2=kcaoff; 378 | k3p=h9*wca; 379 | k3pp=h8*wnaca; 380 | k3=k3p+k3pp; 381 | k4p=h3*wca/hca; 382 | k4pp=h2*wnaca; 383 | k4=k4p+k4pp; 384 | k5=kcaoff; 385 | k6=h6*cai*kcaon; 386 | k7=h5*h2*wna; 387 | k8=h8*h11*wna; 388 | x1=k2*k4*(k7+k6)+k5*k7*(k2+k3); 389 | x2=k1*k7*(k4+k5)+k4*k6*(k1+k8); 390 | x3=k1*k3*(k7+k6)+k8*k6*(k2+k3); 391 | x4=k2*k8*(k4+k5)+k3*k5*(k1+k8); 392 | E1=x1/(x1+x2+x3+x4); 393 | E2=x2/(x1+x2+x3+x4); 394 | E3=x3/(x1+x2+x3+x4); 395 | E4=x4/(x1+x2+x3+x4); 396 | KmCaAct=150.0e-6; 397 | allo=1.0/(1.0+(KmCaAct/cai)*(KmCaAct/cai)); 398 | zna=1.0; 399 | JncxNa=3.0*(E4*k7-E1*k8)+E3*k4pp-E2*k3pp; 400 | JncxCa=E2*k2-E1*k1; 401 | Gncx=0.0008; 402 | if (celltype==MID) 403 | { 404 | Gncx*=1.1; 405 | } 406 | else if (celltype==EPI) 407 | { 408 | Gncx*=1.4; 409 | } 410 | INaCa_i=0.8*Gncx*allo*(zna*JncxNa+zca*JncxCa); 411 | 412 | h1=1+nass/kna3*(1+hna); 413 | h2=(nass*hna)/(kna3*h1); 414 | h3=1.0/h1; 415 | h4=1.0+nass/kna1*(1+nass/kna2); 416 | h5=nass*nass/(h4*kna1*kna2); 417 | h6=1.0/h4; 418 | h7=1.0+nao/kna3*(1.0+1.0/hna); 419 | h8=nao/(kna3*hna*h7); 420 | h9=1.0/h7; 421 | h10=kasymm+1.0+nao/kna1*(1+nao/kna2); 422 | h11=nao*nao/(h10*kna1*kna2); 423 | h12=1.0/h10; 424 | k1=h12*cao*kcaon; 425 | k2=kcaoff; 426 | k3p=h9*wca; 427 | k3pp=h8*wnaca; 428 | k3=k3p+k3pp; 429 | k4p=h3*wca/hca; 430 | k4pp=h2*wnaca; 431 | k4=k4p+k4pp; 432 | k5=kcaoff; 433 | k6=h6*cass*kcaon; 434 | k7=h5*h2*wna; 435 | k8=h8*h11*wna; 436 | x1=k2*k4*(k7+k6)+k5*k7*(k2+k3); 437 | x2=k1*k7*(k4+k5)+k4*k6*(k1+k8); 438 | x3=k1*k3*(k7+k6)+k8*k6*(k2+k3); 439 | x4=k2*k8*(k4+k5)+k3*k5*(k1+k8); 440 | E1=x1/(x1+x2+x3+x4); 441 | E2=x2/(x1+x2+x3+x4); 442 | E3=x3/(x1+x2+x3+x4); 443 | E4=x4/(x1+x2+x3+x4); 444 | KmCaAct=150.0e-6; 445 | allo=1.0/(1.0+(KmCaAct/cass)*(KmCaAct/cass)); 446 | JncxNa=3.0*(E4*k7-E1*k8)+E3*k4pp-E2*k3pp; 447 | JncxCa=E2*k2-E1*k1; 448 | INaCa_ss=0.2*Gncx*allo*(zna*JncxNa+zca*JncxCa); 449 | 450 | k1p=949.5; 451 | k1m=182.4; 452 | k2p=687.2; 453 | k2m=39.4; 454 | k3p=1899.0; 455 | k3m=79300.0; 456 | k4p=639.0; 457 | k4m=40.0; 458 | Knai0=9.073; 459 | Knao0=27.78; 460 | delta=-0.1550; 461 | Knai=Knai0*exp((delta*v*F)/(3.0*R*T)); 462 | Knao=Knao0*exp(((1.0-delta)*v*F)/(3.0*R*T)); 463 | Kki=0.5; 464 | Kko=0.3582; 465 | MgADP=0.05; 466 | MgATP=9.8; 467 | Kmgatp=1.698e-7; 468 | H=1.0e-7; 469 | eP=4.2; 470 | Khp=1.698e-7; 471 | Knap=224.0; 472 | Kxkur=292.0; 473 | P=eP/(1.0+H/Khp+nai/Knap+ki/Kxkur); 474 | a1=(k1p*pow(nai/Knai,3.0))/(pow(1.0+nai/Knai,3.0)+pow(1.0+ki/Kki,2.0)-1.0); 475 | b1=k1m*MgADP; 476 | a2=k2p; 477 | b2=(k2m*pow(nao/Knao,3.0))/(pow(1.0+nao/Knao,3.0)+pow(1.0+ko/Kko,2.0)-1.0); 478 | a3=(k3p*pow(ko/Kko,2.0))/(pow(1.0+nao/Knao,3.0)+pow(1.0+ko/Kko,2.0)-1.0); 479 | b3=(k3m*P*H)/(1.0+MgATP/Kmgatp); 480 | a4=(k4p*MgATP/Kmgatp)/(1.0+MgATP/Kmgatp); 481 | b4=(k4m*pow(ki/Kki,2.0))/(pow(1.0+nai/Knai,3.0)+pow(1.0+ki/Kki,2.0)-1.0); 482 | x1=a4*a1*a2+b2*b4*b3+a2*b4*b3+b3*a1*a2; 483 | x2=b2*b1*b4+a1*a2*a3+a3*b1*b4+a2*a3*b4; 484 | x3=a2*a3*a4+b3*b2*b1+b2*b1*a4+a3*a4*b1; 485 | x4=b4*b3*b2+a3*a4*a1+b2*a4*a1+b3*b2*a1; 486 | E1=x1/(x1+x2+x3+x4); 487 | E2=x2/(x1+x2+x3+x4); 488 | E3=x3/(x1+x2+x3+x4); 489 | E4=x4/(x1+x2+x3+x4); 490 | zk=1.0; 491 | JnakNa=3.0*(E1*a3-E2*b3); 492 | JnakK=2.0*(E4*b1-E3*a1); 493 | Pnak=30; 494 | if (celltype==MID) 495 | { 496 | Pnak*=0.9; 497 | } 498 | else if (celltype==EPI) 499 | { 500 | Pnak*=0.7; 501 | } 502 | INaK=Pnak*(zna*JnakNa+zk*JnakK); 503 | 504 | xkb=1.0/(1.0+exp(-(v-14.48)/18.34)); 505 | GKb=0.003; 506 | if (celltype==MID) 507 | { 508 | GKb*=0.6; 509 | } 510 | IKb=GKb*xkb*(v-EK); 511 | 512 | PNab=3.75e-10; 513 | INab=PNab*vffrt*(nai*exp(vfrt)-nao)/(exp(vfrt)-1.0); 514 | 515 | PCab=2.5e-8; 516 | ICab=PCab*4.0*vffrt*(cai*exp(2.0*vfrt)-0.341*cao)/(exp(2.0*vfrt)-1.0); 517 | 518 | GpCa=0.0005; 519 | IpCa=GpCa*cai/(0.0005+cai); 520 | 521 | //Fluxes and Buffers 522 | 523 | JdiffNa=(nass-nai)/2.0; 524 | JdiffK=(kss-ki)/2.0; 525 | Jdiff=(cass-cai)/0.2; 526 | 527 | bt=4.75; 528 | a_rel=0.5*bt; 529 | Jrel_inf=a_rel*(-ICaL)/(1.0+pow(1.5/cajsr,8.0)); 530 | if (celltype==EPI) 531 | { 532 | Jrel_inf*=1.7; 533 | } 534 | tau_rel=bt/(1.0+0.0123/cajsr); 535 | if (tau_rel<0.001) 536 | { 537 | tau_rel=0.001; 538 | } 539 | Jrelnp.diff=(Jrel_inf-Jrelnp)/tau_rel; 540 | 541 | btp=1.25*bt; 542 | a_relp=0.5*btp; 543 | Jrelp_inf=a_relp*(-ICaL)/(1.0+pow(1.5/cajsr,8.0)); 544 | if (celltype==EPI) 545 | { 546 | Jrelp_inf=Jrelp_inf*1.7; 547 | } 548 | tau_relp=btp/(1.0+0.0123/cajsr); 549 | if (tau_relp<0.001) 550 | { 551 | tau_relp=0.001; 552 | } 553 | Jrelp.diff=(Jrelp_inf-Jrelp)/tau_relp; 554 | fJrelp=(1.0/(1.0+KmCaMK/CaMKa)); 555 | Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp; 556 | 557 | /* May 2011: 558 | RCB: 559 | Ok, I came up with a hack for Jrel that doesn't involve clamping if 560 | cajsr goes negative. This gives the same results as an adaptive 561 | integration scheme. 562 | 563 | jrel_stiff_const should be 0.1*dt, roughly. 564 | 565 | 566 | -Jrel=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp; 567 | +Jrel_canidate=(1.0-fJrelp)*Jrelnp+fJrelp*Jrelp; 568 | +Jrel=Jrel_canidate; 569 | + 570 | +jrel_stiff_const = 0.005; .param(); 571 | +if (Jrel_canidate*jrel_stiff_const > cajsr) { 572 | + Jrel = cajsr/jrel_stiff_const; 573 | +} 574 | 575 | Tom: 576 | 577 | This is terrific news. My evening beers are dedicated to your 578 | efforts! She runs fast and smooth now? I want very much to make it 579 | so. Please let me know what's next. 580 | 581 | Rob: 582 | I think she runs fast and smooth, at least in a single cell. Simulation 583 | results are going to take a few days to run and process. 584 | 585 | The Jrel hack should maintain conservation of calcium. I spent a couple 586 | of hours writing equations to figure out what was happening. Basically, 587 | near zero the differential equation for cajsr turns into something like 588 | this (I forget the exact details): 589 | 590 | y'' = -(1+c/y)*y'-b*y - d 591 | 592 | All my fix does is damp that (1+c/y) term when y is near zero. cajsr 593 | might take an extra timestep or two to reach zero, but it won't go negative. 594 | */ 595 | @param JrelStiffConst = 0.005; 596 | if (Jrel*JrelStiffConst > cajsr) 597 | { 598 | Jrel = cajsr/JrelStiffConst; 599 | } 600 | 601 | Jupnp=0.004375*cai/(cai+0.00092); 602 | Jupp=2.75*0.004375*cai/(cai+0.00092-0.00017); 603 | if (celltype==MID) 604 | { 605 | Jupnp*=1.3; 606 | Jupp*=1.3; 607 | } 608 | fJupp=(1.0/(1.0+KmCaMK/CaMKa)); 609 | Jleak=0.0039375*cansr/15.0; 610 | Jup=(1.0-fJupp)*Jupnp+fJupp*Jupp-Jleak; 611 | 612 | Jtr=(cansr-cajsr)/100.0; 613 | 614 | cmdnmax=0.05; 615 | if (celltype==MID) 616 | { 617 | cmdnmax*=1.3; 618 | } 619 | kmcmdn=0.00238; 620 | trpnmax=0.07; 621 | kmtrpn=0.0005; 622 | BSRmax=0.047; 623 | KmBSR=0.00087; 624 | BSLmax=1.124; 625 | KmBSL=0.0087; 626 | csqnmax=10.0; 627 | kmcsqn=0.8; 628 | 629 | nai.diff=-(INa+INaL+3.0*INaCa_i+3.0*INaK+INab)*Acap/(F*vmyo)+JdiffNa*vss/vmyo; 630 | nass.diff=-(ICaNa+3.0*INaCa_ss)*Acap/(F*vss)-JdiffNa; 631 | 632 | ki.diff=-(Ito+IKr+IKs+IK1+IKb-2.0*INaK)*Acap/(F*vmyo)+JdiffK*vss/vmyo; 633 | kss.diff=-(ICaK)*Acap/(F*vss)-JdiffK; 634 | 635 | Bcai=1.0/(1.0+cmdnmax*kmcmdn/pow(kmcmdn+cai,2.0)+trpnmax*kmtrpn/pow(kmtrpn+cai,2.0)); 636 | cai.diff=Bcai*(-(IpCa+ICab-2.0*INaCa_i)*Acap/(2.0*F*vmyo)-Jup*vnsr/vmyo+Jdiff*vss/vmyo); 637 | 638 | Bcass=1.0/(1.0+BSRmax*KmBSR/pow(KmBSR+cass,2.0)+BSLmax*KmBSL/pow(KmBSL+cass,2.0)); 639 | cass.diff=Bcass*(-(ICaL-2.0*INaCa_ss)*Acap/(2.0*F*vss)+Jrel*vjsr/vss-Jdiff); 640 | 641 | cansr.diff=Jup-Jtr*vjsr/vnsr; 642 | 643 | Bcajsr=1.0/(1.0+csqnmax*kmcsqn/pow(kmcsqn+cajsr,2.0)); 644 | cajsr.diff=Bcajsr*(Jtr-Jrel); 645 | 646 | 647 | //// Membrane Potential 648 | //// 649 | provides accum @external Iion += INa+INaL+Ito+ICaL+ICaNa+ICaK+IKr+IKs+IK1+INaCa_i+INaCa_ss+INaK+INab+IKb+IpCa+ICab; 650 | } 651 | 652 | -------------------------------------------------------------------------------- /domains/electrophysiology/ORd_with_TT06_INa.mel: -------------------------------------------------------------------------------- 1 | 2 | shared V {mV}; 3 | shared Iion {uA/uF}; 4 | shared V_init {mV}; 5 | 6 | 7 | subsystem ORd_with_TT06_INa { 8 | use ORd - .sodium_current { 9 | export ENa; 10 | } 11 | use TT06.fast_sodium_current { 12 | export i_Naitot as INa; 13 | export fast_sodium_current_m_gate.tau_m as tm; 14 | export E_Na as ENa; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domains/electrophysiology/Passive.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate time {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | subsystem Passive { 34 | @param E_R {mV} = -85; 35 | @param G {mS/uF} = 0.00060643000000000003; 36 | 37 | provides V_init = E_R; 38 | provides Iion = G*(V-E_R); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /domains/electrophysiology/TT06.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate time {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | subsystem TT06 { 34 | 35 | @interp(-100,100,1e-2,1e-3) V; 36 | provides V_init = -83; 37 | 38 | provides @flag celltype {enum(ENDO,MID,EPI)} = ENDO; 39 | 40 | provides Cm {uF} = 0.185; 41 | provides F {C/mol} = 96485.3415; 42 | provides R {J/K/kmol} = 8314.472; 43 | provides T {K} = 310; 44 | provides V_c {um^3} = 0.016404; 45 | 46 | provides factor_fix {nA/A} = 1{uA/pA}/1{L/um^3}; 47 | shared Na_o {mM}; 48 | shared Na_i {mM}; 49 | shared i_Naitot {uA/uF}; 50 | subsystem sodium_dynamics { 51 | provides diffvar Na_i; 52 | Na_i.init = 10.355; 53 | /* Na_i.diff = -1*(i_Na+i_b_Na+3*i_NaK+3*i_NaCa)/1*V_c*F*Cm; */ 54 | Na_i.diff = -i_Naitot*Cm/V_c/F*factor_fix; 55 | provides Na_o = 140; 56 | } 57 | 58 | shared K_o {mM}; 59 | shared K_i {mM}; 60 | shared i_Kitot {uA/uF}; 61 | subsystem potassium_dynamics { 62 | provides diffvar K_i; 63 | K_i.init = 138.4; 64 | //K_i.diff = -1*((i_K1+i_to+i_Kr+i_Ks+i_p_K+i_Stim)-2*i_NaK)/1*V_c*F*Cm; 65 | K_i.diff = -i_Kitot*Cm/V_c/F*factor_fix; 66 | provides K_o = 5.4; 67 | } 68 | 69 | shared E_K {mV}; 70 | shared E_Na {mV}; 71 | subsystem reversal_potentials { 72 | provides E_K = R*T/F*log(K_o/K_i); 73 | provides E_Na = R*T/F*log(Na_o/Na_i); 74 | } 75 | provides @interp(-100,100,1e-2,1e-3) VEK {mV} = V - E_K; 76 | 77 | subsystem sodium_potassium_pump_current { 78 | K_mNa = 40; 79 | K_mk = 1; 80 | P_NaK = 2.724; 81 | i_NaK_term = P_NaK*K_o/(K_o+K_mk)/(1+0.1245*exp(-0.1*V*F/(R*T))+0.0353*exp(-V*F/(R*T))); 82 | @trace i_NaK = i_NaK_term*Na_i/(Na_i+K_mNa); 83 | provides accum i_Naitot += 3*i_NaK; 84 | provides accum i_Kitot -= 2*i_NaK; 85 | } 86 | 87 | subsystem fast_sodium_current { 88 | shared h {1}; 89 | shared j {1}; 90 | shared m {1}; 91 | subsystem fast_sodium_current_h_gate { 92 | provides diffvar @gate h; 93 | //@nointerp alpha_h,beta_h; 94 | if (V < -40) { 95 | alpha_h = 0.057*exp(-(V+80)/6.8); 96 | beta_h = (2.7*exp(0.079*V)+310000*exp(0.3485*V)); 97 | } else { 98 | alpha_h = 0; 99 | beta_h = 0.77/(0.13*(1+exp((V+10.66)/-11.1))); 100 | } 101 | h_inf = 1/(pow((1+exp((V+71.55)/7.43)),2)); 102 | tau_h = 1/(alpha_h+beta_h); 103 | h.init = 0.55; 104 | h.diff = (h_inf-h)/tau_h; 105 | } 106 | subsystem fast_sodium_current_j_gate { 107 | provides diffvar @gate j; 108 | //@nointerp alpha_j,beta_j; 109 | if (V < -40) { 110 | alpha_j = (-25428*exp(0.2444*V)-6.948e-6*exp(-0.04391*V))*(V+37.78)/1/(1+exp(0.311*(V+79.23))); 111 | beta_j = 0.02424*exp(-0.01052*V)/(1+exp(-0.1378*(V+40.14))); 112 | } else { 113 | alpha_j = 0; 114 | beta_j = 0.6*exp(0.057*V)/(1+exp(-0.1*(V+32))); 115 | } 116 | j_inf = 1/(pow((1+exp((V+71.55)/7.43)),2)); 117 | tau_j = 1/(alpha_j+beta_j); 118 | j.init = 0.66; 119 | j.diff = (j_inf-j)/tau_j; 120 | } 121 | subsystem fast_sodium_current_m_gate { 122 | provides diffvar @gate m; 123 | alpha_m = 1/(1+exp((-60-V)/5)); 124 | beta_m = (0.1/(1+exp((V+35)/5))+0.1/(1+exp((V-50)/200))); 125 | m_inf = 1/pow((1+exp((-56.86-V)/9.03)),2); 126 | provides tau_m {ms} = 1*alpha_m*beta_m; 127 | m.init = 0.00155; 128 | m.diff = (m_inf-m)/tau_m; 129 | } 130 | @param g_Na = 14.838; 131 | @trace i_Na = g_Na*pow(m,3)*h*j*(V-E_Na); 132 | provides accum i_Naitot += i_Na; 133 | } 134 | 135 | subsystem inward_rectifier_potassium_current { 136 | alpha_K1 = 0.1/(1+exp(0.06*(VEK-200))); 137 | beta_K1 = (3*exp(0.0002*(VEK+100))+exp(0.1*(VEK-10)))/(1+exp(-0.5*VEK)); 138 | @param g_K1 = 5.405; 139 | xK1_inf = alpha_K1/(alpha_K1+beta_K1); 140 | @trace i_K1 = g_K1*xK1_inf*sqrt(K_o/5.4)*VEK; 141 | provides accum i_Kitot += i_K1; 142 | } 143 | 144 | subsystem potassium_pump_current { 145 | @param g_pK = 0.0146; 146 | //@nointerp 147 | i_p_K_term = 1/(1+exp((25-V)/5.98)); 148 | @trace i_p_K = g_pK*VEK*i_p_K_term; 149 | provides accum i_Kitot += i_p_K; 150 | } 151 | 152 | subsystem rapid_time_dependent_potassium_current { 153 | shared Xr1 {1}; 154 | shared Xr2 {1}; 155 | subsystem rapid_time_dependent_potassium_current_Xr1_gate { 156 | provides diffvar @gate Xr1; 157 | alpha_xr1 = 450/(1+exp((-45-V)/10)); 158 | beta_xr1 = 6/(1+exp((V+30)/11.5)); 159 | xr1_inf = 1/(1+exp((-26-V)/7)); 160 | tau_xr1 = 1*alpha_xr1*beta_xr1; 161 | Xr1.init = 0.00448; 162 | Xr1.diff = (xr1_inf-Xr1)/tau_xr1; 163 | } 164 | subsystem rapid_time_dependent_potassium_current_Xr2_gate { 165 | provides diffvar @gate Xr2; 166 | alpha_xr2 = 3/(1+exp((-60-V)/20)); 167 | beta_xr2 = 1.12/(1+exp((V-60)/20)); 168 | xr2_inf = 1/(1+exp((V+88)/24)); 169 | tau_xr2 = 1*alpha_xr2*beta_xr2; 170 | Xr2.init = 0.476; 171 | Xr2.diff = (xr2_inf-Xr2)/tau_xr2; 172 | } 173 | @param g_Kr = 0.153; 174 | @trace i_Kr = g_Kr*sqrt(K_o/5.4)*Xr1*Xr2*VEK; 175 | provides accum i_Kitot += i_Kr; 176 | } 177 | 178 | subsystem slow_time_dependent_potassium_current { 179 | shared Xs {1}; 180 | subsystem slow_time_dependent_potassium_current_Xs_gate { 181 | provides diffvar @gate Xs; 182 | alpha_xs = 1400/sqrt((1+exp((5-V)/6))); 183 | beta_xs = 1/(1+exp((V-35)/15)); 184 | xs_inf = 1/(1+exp((-5-V)/14)); 185 | tau_xs = (1*alpha_xs*beta_xs+80); 186 | Xs.init = 0.0087; 187 | Xs.diff = (xs_inf-Xs)/tau_xs; 188 | } 189 | P_kna = 0.03; 190 | E_Ks = R*T/F*log((K_o+P_kna*Na_o)/(K_i+P_kna*Na_i)); 191 | @param g_Ks; 192 | if (celltype == MID) { 193 | g_Ks = 0.098; 194 | } else { 195 | g_Ks = 0.392; 196 | } 197 | @trace i_Ks = g_Ks*pow(Xs,2)*(V-E_Ks); 198 | provides accum i_Kitot += i_Ks; 199 | } 200 | 201 | subsystem sodium_background_current { 202 | @param g_bna = 0.00029; 203 | @trace i_b_Na = g_bna*(V-E_Na); 204 | provides accum i_Naitot += i_b_Na; 205 | } 206 | 207 | subsystem transient_outward_current { 208 | shared r {1}; 209 | shared s {1}; 210 | subsystem transient_outward_current_r_gate { 211 | provides diffvar @gate r; 212 | r_inf = 1/(1+exp((20-V)/6)); 213 | tau_r = (9.5*exp(-pow((V+40),2)/1800)+0.8); 214 | r.init = 2.235e-8; 215 | r.diff = (r_inf-r)/tau_r; 216 | } 217 | subsystem transient_outward_current_s_gate { 218 | provides diffvar @gate s; 219 | if (celltype == ENDO) { 220 | s_inf = 1/(1+exp((V+28)/5)); 221 | tau_s = 1000*exp(-pow(V+67,2)/1000)+8; 222 | } else { 223 | s_inf = 1/(1+exp((V+20)/5)); 224 | tau_s = 85*exp(-pow(V+45,2)/320)+5/(1+exp((V-20)/5))+3; 225 | } 226 | s.init = 0.6012; 227 | s.diff = (s_inf-s)/tau_s; 228 | } 229 | @param g_to; 230 | if (celltype == ENDO) { 231 | g_to = 0.073; 232 | } else { 233 | g_to = 0.294; 234 | } 235 | @trace i_to = g_to*r*s*VEK; 236 | provides accum i_Kitot += i_to; 237 | } 238 | 239 | shared i_Caitot {uA/uF}; 240 | subsystem calcium_dynamics { 241 | provides Ca_o {uM} = 2; 242 | provides diffvar Ca_i {uM}; 243 | provides diffvar @interp(1e-7,1e-1,1e-6) Ca_ss {uM}; 244 | //provides diffvar Ca_ss {uM}; 245 | diffvar Ca_SR {uM}; 246 | diffvar R_prime {1}; 247 | shared i_b_Ca {uA/uF}; 248 | shared i_p_Ca {uA/uF}; 249 | shared i_CaL {uA/uF}; 250 | shared i_NaCa {uA/uF}; 251 | subsystem L_type_Ca_current { 252 | shared d {1}; 253 | shared f {1}; 254 | shared f2 {1}; 255 | shared fCass {1}; 256 | subsystem L_type_Ca_current_d_gate { 257 | provides diffvar @gate d; 258 | alpha_d = (1.4/(1+exp((-35-V)/13))+0.25); 259 | beta_d = 1.4/(1+exp((V+5)/5)); 260 | d_inf = 1/(1+exp((-8-V)/7.5)); 261 | gamma_d = 1/(1+exp((50-V)/20)); 262 | tau_d = (1*alpha_d*beta_d+gamma_d); 263 | d.init = 3.164e-5; 264 | d.diff = (d_inf-d)/tau_d; 265 | } 266 | subsystem L_type_Ca_current_f2_gate { 267 | provides diffvar @gate f2; 268 | f2_inf = (0.67/(1+exp((V+35)/7))+0.33); 269 | tau_f2 = (562*exp(-pow((V+27),2)/240)+31/(1+exp((25-V)/10))+80/(1+exp((V+30)/10))); 270 | f2.init = 0.9778; 271 | f2.diff = (f2_inf-f2)/tau_f2; 272 | } 273 | subsystem L_type_Ca_current_fCass_gate { 274 | provides diffvar @gate fCass; 275 | fCass_inf = (0.6/(1+pow(Ca_ss/0.05,2))+0.4); 276 | tau_fCass = (80/(1+pow(Ca_ss/0.05,2))+2); 277 | fCass.init = 0.9953; 278 | fCass.diff = (fCass_inf-fCass)/tau_fCass; 279 | } 280 | subsystem L_type_Ca_current_f_gate { 281 | provides diffvar @gate f; 282 | f_inf = 1/(1+exp((V+20)/7)); 283 | tau_f = (1102.5*exp(-pow((V+27),2)/225)+200/(1+exp((13-V)/10))+180/(1+exp((V+30)/10))+20); 284 | f.init = 0.9609; 285 | f.diff = (f_inf-f)/tau_f; 286 | } 287 | @param g_CaL = 0.0000398; 288 | i_CalTerm1 = 4*(V-15)*pow(F,2)/(R*T); 289 | i_CalTerm2 = exp(2*(V-15)*F/(R*T)); 290 | if( V==15 ) { 291 | i_CalTerm3 = 2*F; 292 | } else { 293 | i_CalTerm3 = i_CalTerm1/(i_CalTerm2-1); 294 | } 295 | i_CalTerm4 = i_CalTerm3*i_CalTerm2; 296 | provides @trace i_CaL = g_CaL*d*f*f2*fCass*(0.25*Ca_ss*i_CalTerm4-Ca_o*i_CalTerm3); 297 | provides accum i_Caitot += i_CaL; 298 | } 299 | subsystem calcium_pump_current { 300 | K_pCa = 0.0005; 301 | @param g_pCa = 0.1238; 302 | provides @trace i_p_Ca = g_pCa*Ca_i/(Ca_i+K_pCa); 303 | provides accum i_Caitot += i_p_Ca; 304 | } 305 | subsystem sodium_calcium_exchanger_current { 306 | K_NaCa = 1000; 307 | K_sat = 0.1; 308 | Km_Ca = 1.38; 309 | Km_Nai = 87.5; 310 | alpha = 2.5; 311 | gamma = 0.35; 312 | exp_gamma_VFRT = exp(gamma*V*F/(R*T)); 313 | exp_gamma_m1_VFRT = exp((gamma-1)*V*F/(R*T)); 314 | provides @trace i_NaCa = K_NaCa*(exp_gamma_VFRT*pow(Na_i,3)*Ca_o-exp_gamma_m1_VFRT*pow(Na_o,3)*Ca_i*alpha)/((pow(Km_Nai,3)+pow(Na_o,3))*(Km_Ca+Ca_o)*(1+K_sat*exp_gamma_m1_VFRT)); 315 | provides accum i_Naitot += 3*i_NaCa; 316 | provides accum i_Caitot -= 2*i_NaCa; 317 | } 318 | subsystem calcium_background_current { 319 | @param g_bca = 0.000592; 320 | E_Ca = 0.5*R*T/F*log(Ca_o/Ca_i); 321 | provides @trace i_b_Ca = g_bca*(V-E_Ca); 322 | provides accum i_Caitot += i_b_Ca; 323 | } 324 | Buf_c = 0.2; 325 | Buf_sr = 10; 326 | Buf_ss = 0.4; 327 | EC = 1.5; 328 | K_buf_c = 0.001; 329 | K_buf_sr = 0.3; 330 | K_buf_ss = 0.00025; 331 | K_up = 0.00025; 332 | V_leak = 0.00036; 333 | V_rel = 0.102; 334 | V_sr = 0.001094; 335 | V_ss = 0.00005468; 336 | V_xfer = 0.0038; 337 | Vmax_up = 0.006375; 338 | k1_prime = 0.15; 339 | k2_prime = 0.045; 340 | k3 = 0.06; 341 | k4 = 0.005; 342 | max_sr = 2.5; 343 | min_sr = 1; 344 | Ca_i_bufc = 1/(1+Buf_c*K_buf_c/pow((Ca_i+K_buf_c),2)); 345 | Ca_sr_bufsr = 1/(1+Buf_sr*K_buf_sr/pow((Ca_SR+K_buf_sr),2)); 346 | Ca_ss_bufss = 1/(1+Buf_ss*K_buf_ss/pow((Ca_ss+K_buf_ss),2)); 347 | @trace i_leak = V_leak*(Ca_SR-Ca_i); 348 | @trace i_up = Vmax_up/(1+pow(K_up,2)/pow(Ca_i,2)); 349 | @trace i_xfer = V_xfer*(Ca_ss-Ca_i); 350 | kcasr = (max_sr-(max_sr-min_sr)/(1+pow(EC/Ca_SR,2))); 351 | Ca_i.init = 0.00002; 352 | Ca_i.diff = Ca_i_bufc*(((i_leak-i_up)*V_sr/V_c+i_xfer)-1*((i_b_Ca+i_p_Ca)-2*i_NaCa)*Cm/(2*1*V_c*F)); 353 | k1 = k1_prime/kcasr; 354 | k2 = k2_prime*kcasr; 355 | O = k1*pow(Ca_ss,2)*R_prime/(k3+k1*pow(Ca_ss,2)); 356 | R_prime.init = 0.9868; 357 | R_prime.diff = (-k2*Ca_ss*R_prime+k4*(1-R_prime)); 358 | @trace i_rel = V_rel*O*(Ca_SR-Ca_ss); 359 | Ca_SR.init = 3.155; 360 | Ca_SR.diff = Ca_sr_bufsr*(i_up-(i_rel+i_leak)); 361 | Ca_ss.init = 0.00017; 362 | Ca_ss.diff = Ca_ss_bufss*((-1*i_CaL*Cm/(2*1*V_ss*F)+i_rel*V_sr/V_ss)-i_xfer*V_c/V_ss); 363 | } 364 | 365 | provides accum Iion += i_Naitot+i_Kitot+i_Caitot; 366 | } 367 | 368 | -------------------------------------------------------------------------------- /domains/electrophysiology/continuity.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate t {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | shared iStim {uA/uF}; 34 | 35 | subsystem Vm { 36 | provides diffvar @coupled V; 37 | V.init = V_init; 38 | V.diff = -Iion + iStim; 39 | } 40 | 41 | subsystem noStim { 42 | provides iStim; 43 | iStim = 0; 44 | } 45 | 46 | shared bcl_time {ms}; 47 | 48 | subsystem bcl_time { 49 | provides bcl_time; 50 | 51 | @param offset {ms} = 0; 52 | @param n {1} = 1; 53 | @param bcl {ms} = 1000; 54 | 55 | if (t < offset) { 56 | bcl_time = bcl*1000+t-offset; 57 | } else { 58 | beat = floor((t-offset)/bcl); 59 | if (beat >= n) { 60 | beat = n-1; 61 | } 62 | bcl_time = t-offset - beat*bcl; 63 | } 64 | } 65 | 66 | shared stim_time {ms}; 67 | shared stim_amp {uA/uF}; 68 | 69 | subsystem squareStim { 70 | @param duration {ms} = 1; 71 | 72 | provides iStim = 0; 73 | if (stim_time < duration) { 74 | iStim = stim_amp; 75 | } 76 | } 77 | 78 | subsystem bclDefault { 79 | use Vm; 80 | use bcl_time; 81 | use squareStim { 82 | export stim_time as bcl_time; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /domains/electrophysiology/decker_2009.mel: -------------------------------------------------------------------------------- 1 | integrate time {ms}; 2 | 3 | shared V {mV}; 4 | shared V_init {mV}; 5 | shared Iion {uA/uF}; 6 | 7 | subsystem decker_2009 { 8 | 9 | shared VEK {mV}; 10 | shared AF {uF*mol/C}; 11 | shared Acap {cm^2}; 12 | shared CT_K_Cl {mmol/L/ms}; 13 | shared CT_Na_Cl {mmol/L/ms}; 14 | shared CaMK_active {1}; 15 | shared Ca_JSR {mmol/L}; 16 | shared Ca_NSR {mmol/L}; 17 | shared Ca_i {mmol/L}; 18 | shared Ca_ss_CaL {mmol/L}; 19 | shared Ca_ss_sr {mmol/L}; 20 | shared Cl_i {mmol/L}; 21 | shared Cl_ss {mmol/L}; 22 | shared ECl {mV}; 23 | shared EK {mV}; 24 | shared EKs {mV}; 25 | shared ENa {mV}; 26 | shared ICaL {uA/uF}; 27 | shared ICab {uA/uF}; 28 | shared IClb {uA/uF}; 29 | shared IK1 {uA/uF}; 30 | shared IKp {uA/uF}; 31 | shared IKr {uA/uF}; 32 | shared IKs {uA/uF}; 33 | shared INa {uA/uF}; 34 | shared INaCa {uA/uF}; 35 | shared INaCa_ss_sr {uA/uF}; 36 | shared INaK {uA/uF}; 37 | shared INaL {uA/uF}; 38 | shared INab {uA/uF}; 39 | shared I_stim {uA/uF}; 40 | shared Ileak {mmol/L/ms}; 41 | shared IpCa {uA/uF}; 42 | shared Irel {mmol/L/ms}; 43 | shared Ito1 {uA/uF}; 44 | shared Ito2 {uA/uF}; 45 | shared Itr {mmol/L/ms}; 46 | shared Iup {mmol/L/ms}; 47 | shared K_i {mmol/L}; 48 | shared Na_i {mmol/L}; 49 | shared Na_ss_sr {mmol/L}; 50 | shared Vjsr {uL}; 51 | shared Vm {mV}; 52 | shared Vmyo {uL}; 53 | shared Vnsr {uL}; 54 | shared Vsr {uL}; 55 | shared Vss_CaL {uL}; 56 | shared Vss_sr {uL}; 57 | shared i_Stim {uA/uF}; 58 | shared Ca_o {mmol/L}; 59 | shared Cl_o {mmol/L}; 60 | shared F {C/mol}; 61 | shared K_o {mmol/L}; 62 | shared Km {mmol/L}; 63 | shared Na_o {mmol/L}; 64 | shared R {J/kmol/K}; 65 | shared T {K}; 66 | shared tau_diff {ms}; 67 | subsystem CaMK_active { 68 | provides Km {mmol/L}; 69 | provides CaMK_active {1}; 70 | diffvar CaMK_trap {1}; 71 | CaMK_0 {1} = 0.05; 72 | Km {mmol/L} = 0.0015; 73 | alpha_CaMK {1/ms} = 0.05; 74 | beta_CaMK {1/ms} = 0.00068; 75 | CaMK_active {1} = (CaMK_0*(1-CaMK_trap)/(1+Km/Ca_ss_sr)+CaMK_trap); 76 | CaMK_trap.init {1} = 0.0114911034744777; 77 | CaMK_trap.diff = (alpha_CaMK*CaMK_active*(CaMK_active-CaMK_trap)-beta_CaMK*CaMK_trap); 78 | } 79 | subsystem ICaL { 80 | provides ICaL {uA/uF}; 81 | diffvar @markov C {1}; 82 | diffvar @markov CI {1}; 83 | diffvar @markov CI_star {1}; 84 | diffvar @markov C_star {1}; 85 | diffvar @markov O {1}; 86 | diffvar @markov OI {1}; 87 | diffvar @markov O_star {1}; 88 | ACT_infinity {1} = 1/(1+exp(-(Vm-13.56)/9.45)); 89 | ACT_tau {ms} = (0.59+0.8*exp(0.052*(Vm+13))/(1+exp(0.132*(Vm+13)))); 90 | IV_beta_infinity_star {1} = (25-17.5/(1+pow(0.003/Ca_ss_CaL,4))); 91 | IV_infinity {1} = (1/(1+exp((Vm+17.5)/3))+0.25)/1.25; 92 | IV_infinity_star {1} = (1/(1+exp((Vm+17.5)/3))+0.0001)/1.0001; 93 | IV_tau {ms} = 1/(1/(24.828*(1+exp((Vm+49.1)/10.349)))+1/(30.553*(1+exp(-(Vm+0.213)/10.807)))); 94 | OI_star {1} = (1-(C+O+C_star+O_star+CI+OI+CI_star)); 95 | PCa {L/ms/F} = 0.00015552; 96 | delta {1/ms} = 3/(1+pow(0.003/Ca_ss_CaL,4)); 97 | gamma_Cai {1} = 1; 98 | gamma_Cao {1} = 0.341; 99 | theta {1/ms} = 1; 100 | theta_I {1/ms} = 1e-6; 101 | ICaL_max {uA/uF} = PCa*4*Vm*pow(F,2)/(R*T)*(gamma_Cai*Ca_ss_CaL*exp(2*Vm*F/(R*T))-gamma_Cao*Ca_o)/(exp(2*Vm*F/(R*T))-1); 102 | IV_beta_star {1} = 1/(IV_beta_infinity_star*(1+exp(-(Vm+0.213)/10.807))); 103 | alpha {1/ms} = ACT_infinity/ACT_tau; 104 | beta {1/ms} = (1-ACT_infinity)/ACT_tau; 105 | x {1/ms} = IV_infinity/IV_tau; 106 | y {1/ms} = (1-IV_infinity)/IV_tau; 107 | C.init {1} = 0.99996982093287; 108 | C.diff = (-(alpha+delta+y)*C+beta*O+theta*C_star+x*CI); 109 | ICaL {uA/uF} = ICaL_max*(O+O_star); 110 | IV_tau_star {ms} = 1/(1/(24.828*(1+exp((Vm+49.1)/10.349)))+IV_beta_star); 111 | O.init {1} = 2.26882961412491e-5; 112 | O.diff = (-(beta+delta+y)*O+alpha*C+theta*O_star+x*OI); 113 | x_star {1/ms} = IV_infinity_star/IV_tau_star; 114 | y_star {1/ms} = (1-IV_infinity_star)/IV_tau_star; 115 | C_star.init {1} = 7.49117189549873e-6; 116 | C_star.diff = (-(alpha+theta+y_star)*C_star+delta*C+beta*O_star+x_star*CI_star); 117 | O_star.init {1} = 1.23556404128518e-10; 118 | O_star.diff = (-(beta+theta+y_star)*O_star+delta*O+alpha*C_star+x_star*OI_star); 119 | delta_I {1/ms} = theta_I*x*y_star*delta/(y*x_star*theta); 120 | CI.init {1} = 5.89853003114132e-11; 121 | CI.diff = (-(alpha+delta_I+x)*CI+y*C+theta_I*CI_star+beta*OI); 122 | CI_star.init {1} = 1.9237001017021e-9; 123 | CI_star.diff = (-(alpha+theta_I+x_star)*CI_star+delta_I*CI+y_star*C_star+beta*OI_star); 124 | OI.init {1} = 8.01952813127322e-17; 125 | OI.diff = (-(beta+delta_I+x)*OI+y*O+theta_I*OI_star+alpha*CI); 126 | } 127 | subsystem ICab { 128 | provides ICab {uA/uF}; 129 | PCab {L/ms/F} = 1.99508e-7; 130 | gamma_Ca_i {1} = 1; 131 | gamma_Ca_o {1} = 0.341; 132 | ICab {uA/uF} = PCab*4*Vm*pow(F,2)/(R*T)*(gamma_Ca_i*Ca_i*exp(2*Vm*F/(R*T))-gamma_Ca_o*Ca_o)/(exp(2*Vm*F/(R*T))-1); 133 | } 134 | subsystem INaCa { 135 | provides INaCa {uA/uF}; 136 | provides INaCa_ss_sr {uA/uF}; 137 | KmCa_act {mmol/L} = 0.000125; 138 | KmCai {mmol/L} = 0.0036; 139 | KmCao {mmol/L} = 1.3; 140 | KmNai {mmol/L} = 12.3; 141 | KmNao {mmol/L} = 87.5; 142 | Vmax {uA/uF} = 4.5; 143 | eta {1} = 0.27; 144 | ksat {1} = 0.32; 145 | denom_1 {1} = (1+pow(KmCa_act/Ca_i,2)); 146 | denom_2 {1} = (1+ksat*exp((eta-1)*Vm*F/(R*T))); 147 | denom_3 {mmol^4/L^4} = (KmCao*pow(Na_i,3)+pow(KmNao,3)*Ca_i+pow(KmNai,3)*Ca_o*(1+Ca_i/KmCai)); 148 | denom_4 {mmol^4/L^4} = (KmCai*pow(Na_o,3)*(1+pow(Na_i/KmNai,3))+pow(Na_i,3)*Ca_o+pow(Na_o,3)*Ca_i); 149 | denom_ss_1 {1} = (1+pow(KmCa_act/Ca_ss_sr,2)); 150 | denom_ss_2 {1} = (1+ksat*exp((eta-1)*Vm*F/(R*T))); 151 | denom_ss_3 {mmol^4/L^4} = (KmCao*pow(Na_ss_sr,3)+pow(KmNao,3)*Ca_ss_sr+pow(KmNai,3)*Ca_o*(1+Ca_ss_sr/KmCai)); 152 | denom_ss_4 {mmol^4/L^4} = (KmCai*pow(Na_o,3)*(1+pow(Na_ss_sr/KmNai,3))+pow(Na_ss_sr,3)*Ca_o+pow(Na_o,3)*Ca_ss_sr); 153 | num_ss {uA*mmol^4/uF/L^4} = 0.2*Vmax*(pow(Na_ss_sr,3)*Ca_o*exp(eta*Vm*F/(R*T))-pow(Na_o,3)*Ca_ss_sr*exp((eta-1)*Vm*F/(R*T))); 154 | numerator {uA*mmol^4/uF/L^4} = 0.8*Vmax*(pow(Na_i,3)*Ca_o*exp(eta*Vm*F/(R*T))-pow(Na_o,3)*Ca_i*exp((eta-1)*Vm*F/(R*T))); 155 | INaCa_cai {uA/uF} = numerator/(denom_1*denom_2*(denom_3+denom_4)); 156 | INaCa_ss_sr {uA/uF} = num_ss/(denom_ss_1*denom_ss_2*(denom_ss_3+denom_ss_4)); 157 | INaCa {uA/uF} = (INaCa_cai+INaCa_ss_sr); 158 | } 159 | subsystem INaK { 160 | provides INaK {uA/uF}; 161 | V_half {mV} = -92; 162 | ibarnak {uA/uF} = 1.4; 163 | kmko {mmol/L} = 1.5; 164 | kmnai {mmol/L} = 2.6; 165 | sigma {1} = 1; 166 | PK {1} = K_o/(K_o+kmko); 167 | PNa {1} = pow(Na_i/(Na_i+kmnai),3); 168 | phi {1} = sigma*(Vm-V_half)*F/(R*T); 169 | fv {1} = 1/(1+exp(-phi)); 170 | INaK {uA/uF} = ibarnak*fv*PK*PNa; 171 | } 172 | subsystem INab { 173 | provides INab {uA/uF}; 174 | PNab {L/ms/F} = 3.2e-9; 175 | phi {1} = F*Vm/(R*T); 176 | INab {uA/uF} = F*PNab*phi*(Na_i*exp(phi)-Na_o)/(exp(phi)-1); 177 | } 178 | subsystem Ileak { 179 | provides Ileak {mmol/L/ms}; 180 | nsrbar {mmol/L} = 15; 181 | Ileak {mmol/L/ms} = 0.004375/nsrbar*Ca_NSR; 182 | } 183 | subsystem IpCa { 184 | provides IpCa {uA/uF}; 185 | KmpCa {mmol/L} = 0.0005; 186 | gpCa {uA/uF} = 0.0575; 187 | IpCa {uA/uF} = gpCa*Ca_i/(KmpCa+Ca_i); 188 | } 189 | subsystem Ito2 { 190 | provides Ito2 {uA/uF}; 191 | shared i2f {1}; 192 | subsystem Ito2_i2f_gate { 193 | provides diffvar i2f {1}; 194 | alpha_i2f {1/ms} = 0.025/(1+exp((Vm+58)/5)); 195 | beta_i2f {1/ms} = 1/(5*(1+exp((Vm+19)/-9))); 196 | tau_i2f {ms} = 8; 197 | i2f_infinity {1} = alpha_i2f/(alpha_i2f+beta_i2f); 198 | i2f.init {1} = 0.996044894628276; 199 | i2f.diff = (i2f_infinity-i2f)/tau_i2f; 200 | } 201 | Ito2_max_scaling_factor {1} = 1; 202 | PCl {L/ms/F} = 9e-7; 203 | kCa_ito2 {mmol/L/ms} = 0.4; 204 | zCl {1} = -1; 205 | Ito2_max {uA/uF} = PCl*pow(zCl,2)*Vm*pow(F,2)/(R*T)*(Cl_i-Cl_o*exp(Vm*F/(R*T)))/(1-exp(Vm*F/(R*T))); 206 | KCa_ito2 {1} = (1-1/(1+pow(Irel/kCa_ito2,2))); 207 | Ito2 {uA/uF} = Ito2_max*Ito2_max_scaling_factor*i2f*KCa_ito2; 208 | } 209 | subsystem Itr { 210 | provides Itr {mmol/L/ms}; 211 | tautr {ms} = 25; 212 | Itr {mmol/L/ms} = (Ca_NSR-Ca_JSR)/tautr; 213 | } 214 | subsystem cell_geometry { 215 | provides AF {uF*mol/C}; 216 | provides Acap {cm^2}; 217 | provides Vjsr {uL}; 218 | provides Vmyo {uL}; 219 | provides Vnsr {uL}; 220 | provides Vsr {uL}; 221 | provides Vss_CaL {uL}; 222 | provides Vss_sr {uL}; 223 | a {cm} = 0.0011; 224 | l {cm} = 0.01; 225 | ageo {cm^2} = (2*3.1415926535897932*a*a+2*3.1415926535897932*a*l); 226 | vcell {uL} = 1000*3.1415926535897932*a*a*l; 227 | Acap {cm^2} = ageo*2; 228 | Vjsr {uL} = vcell*0.0048; 229 | Vmyo {uL} = vcell*0.678; 230 | Vnsr {uL} = vcell*0.0552; 231 | Vsr {uL} = vcell*0.06; 232 | Vss_CaL {uL} = vcell*0.002; 233 | Vss_sr {uL} = vcell*0.02; 234 | AF {uF*mol/C} = 1*1*Acap/(F*1); 235 | } 236 | subsystem model_parameters { 237 | provides Ca_o {mmol/L}; 238 | provides Cl_o {mmol/L}; 239 | provides F {C/mol}; 240 | provides K_o {mmol/L}; 241 | provides Na_o {mmol/L}; 242 | provides R {J/kmol/K}; 243 | provides T {K}; 244 | Ca_o {mmol/L} = 1.8; 245 | Cl_o {mmol/L} = 100; 246 | F {C/mol} = 96485; 247 | K_o {mmol/L} = 5.4; 248 | Na_o {mmol/L} = 140; 249 | R {J/kmol/K} = 8314; 250 | T {K} = 310; 251 | } 252 | subsystem reversal_potentials { 253 | provides ECl {mV}; 254 | provides EK {mV}; 255 | provides EKs {mV}; 256 | provides ENa {mV}; 257 | ECl {mV} = -R*T/F*log(Cl_o/Cl_i); 258 | EK {mV} = R*T/F*log(K_o/K_i); 259 | ENa {mV} = R*T/F*log(Na_o/Na_i); 260 | prnak {1} = 0.01833; 261 | EKs {mV} = R*T/F*log((K_o+prnak*Na_o)/(K_i+prnak*Na_i)); 262 | } 263 | subsystem CT_K_Cl { 264 | provides CT_K_Cl {mmol/L/ms}; 265 | CT_K_Cl_max {mmol/L/ms} = 1.77e-5; 266 | CT_K_Cl {mmol/L/ms} = CT_K_Cl_max*(EK-ECl)/((EK+87.8251)-ECl); 267 | } 268 | subsystem CT_Na_Cl { 269 | provides CT_Na_Cl {mmol/L/ms}; 270 | CT_Na_Cl_max {mmol/L/ms} = 2.46108e-5; 271 | CT_Na_Cl {mmol/L/ms} = CT_Na_Cl_max*pow((ENa-ECl),4)/(pow((ENa-ECl),4)+pow(87.8251,4)); 272 | } 273 | subsystem IClb { 274 | provides IClb {uA/uF}; 275 | gClb {mS/uF} = 0.000225; 276 | IClb {uA/uF} = gClb*(Vm-ECl); 277 | } 278 | subsystem IK1 { 279 | provides IK1 {uA/uF}; 280 | shared K1 {1}; 281 | subsystem IK1_K1_gate { 282 | provides K1 {1}; 283 | alpha_k1 {1} = 1.02/(1+exp(0.2385*((VEK)-59.215))); 284 | beta_k1 {1} = (0.49124*exp(0.08032*((VEK)+5.476))+exp(0.06175*((VEK)-594.31)))/(1+exp(-0.5143*((VEK)+4.753))); 285 | K1 {1} = alpha_k1/(alpha_k1+beta_k1); 286 | } 287 | g_K1_max {mS/uF} = 0.5; 288 | gK1 {mS/uF} = g_K1_max*sqrt(K_o/5.4); 289 | IK1 {uA/uF} = gK1*K1*(VEK); 290 | } 291 | subsystem IKp { 292 | provides IKp {uA/uF}; 293 | Kp {1} = 1/(1+exp((7.488-Vm)/5.98)); 294 | gKp {mS/uF} = 0.00276; 295 | IKp {uA/uF} = gKp*Kp*(VEK); 296 | } 297 | subsystem IKr { 298 | provides IKr {uA/uF}; 299 | shared r {1}; 300 | shared xr {1}; 301 | subsystem IKr_r_gate { 302 | provides r {1}; 303 | r {1} = 1/(1+exp((Vm+10)/15.4)); 304 | } 305 | subsystem IKr_xr_gate { 306 | provides diffvar @gate xr {1}; 307 | tau_xr {ms} = 1/(0.0006*(Vm-1.7384)/(1-exp(-0.136*(Vm-1.7384)))+0.0003*(Vm+38.3608)/(exp(0.1522*(Vm+38.3608))-1)); 308 | xr_infinity {1} = 1/(1+exp(-(Vm+10.085)/4.25)); 309 | xr.init {1} = 4.06959064407486e-6; 310 | xr.diff = (xr_infinity-xr)/tau_xr; 311 | } 312 | gKr_max {mS/uF} = 0.0138542; 313 | gKr {mS/uF} = gKr_max*sqrt(K_o/5.4); 314 | IKr {uA/uF} = gKr*xr*r*(VEK); 315 | } 316 | subsystem IKs { 317 | provides IKs {uA/uF}; 318 | diffvar @markov C1 {1}; 319 | diffvar @markov C10 {1}; 320 | diffvar @markov C11 {1}; 321 | diffvar @markov C12 {1}; 322 | diffvar @markov C13 {1}; 323 | diffvar @markov C14 {1}; 324 | diffvar @markov C15 {1}; 325 | diffvar @markov C2 {1}; 326 | diffvar @markov C3 {1}; 327 | diffvar @markov C4 {1}; 328 | diffvar @markov C5 {1}; 329 | diffvar @markov C6 {1}; 330 | diffvar @markov C7 {1}; 331 | diffvar @markov C8 {1}; 332 | diffvar @markov C9 {1}; 333 | diffvar @markov O1 {1}; 334 | O2 {1} = (1-(C1+C2+C3+C4+C5+C6+C7+C8+C9+C10+C11+C12+C13+C14+C15+O1)); 335 | alpha {1/ms} = 0.01486459798086*exp(0.02987730123588*Vm*F/(R*T)); 336 | beta {1/ms} = 0.08398631219983*exp(-0.05546105712664*Vm*F/(R*T)); 337 | delta {1/ms} = 0.0031173268874*exp(-0.42625451944376*Vm*F/(R*T)); 338 | eta {1/ms} = 0.07731990097331*exp(-0.06472612248871*Vm*F/(R*T)); 339 | gKs_max {mS/uF} = 0.0826; 340 | gamma {1/ms} = 0.01460066118316*exp(0.24464953099645*Vm*F/(R*T)); 341 | omega {1/ms} = 0.7940545995864*exp(-0.08017378192977*Vm*F/(R*T)); 342 | psi {1/ms} = 0.58638228663014*exp(0.28205554331496*Vm*F/(R*T)); 343 | theta {1/ms} = 0.08953830641102; 344 | C1.init {1} = 0.476679784307081; 345 | C1.diff = (-4*alpha*C1+beta*C2); 346 | C10.init {1} = 0.0138769647384953; 347 | C10.diff = (-(2*alpha+2*delta)*C10+beta*C11+gamma*C7); 348 | C11.init {1} = 0.00371438476499172; 349 | C11.diff = (-(alpha+beta+gamma+2*delta)*C11+2*alpha*C10+2*beta*C12+2*gamma*C8+3*delta*C13); 350 | C12.init {1} = 0.000248553788631871; 351 | C12.diff = (-(2*beta+2*gamma+2*delta)*C12+alpha*C11+3*gamma*C9+3*delta*C14); 352 | C13.init {1} = 0.000644426171899078; 353 | C13.diff = (-(alpha+3*delta)*C13+beta*C14+gamma*C11); 354 | C14.init {1} = 8.62495047666861e-5; 355 | C14.diff = (-(beta+gamma+3*delta)*C14+alpha*C13+2*gamma*C12+4*delta*C15); 356 | C15.init {1} = 1.12344645485893e-5; 357 | C15.diff = (-(4*delta+theta)*C15+gamma*C14+eta*O1); 358 | C2.init {1} = 0.255181042718489; 359 | C2.diff = (-(3*alpha+beta+gamma)*C2+4*alpha*C1+2*beta*C3+delta*C6); 360 | C3.init {1} = 0.0512272866698557; 361 | C3.diff = (-(2*alpha+2*beta+2*gamma)*C3+3*alpha*C2+3*beta*C4+delta*C7); 362 | C4.init {1} = 0.0045705849736195; 363 | C4.diff = (-(alpha+3*beta+3*gamma)*C4+2*alpha*C3+4*beta*C5+delta*C8); 364 | C5.init {1} = 0.000152923243503507; 365 | C5.diff = (-(4*beta+4*gamma)*C5+alpha*C4+delta*C9); 366 | C6.init {1} = 0.132814156809568; 367 | C6.diff = (-(3*alpha+delta)*C6+beta*C7+gamma*C2); 368 | C7.init {1} = 0.053324572164618; 369 | C7.diff = (-(2*alpha+beta+gamma+delta)*C7+3*alpha*C6+2*beta*C8+2*gamma*C3+2*delta*C10); 370 | C8.init {1} = 0.00713656414955778; 371 | C8.diff = (-(alpha+2*beta+2*gamma+delta)*C8+2*alpha*C7+3*beta*C9+3*gamma*C4+2*delta*C11); 372 | C9.init {1} = 0.000318368292970148; 373 | C9.diff = (-(3*beta+3*gamma+delta)*C9+alpha*C8+4*gamma*C5+2*delta*C12); 374 | O1.init {1} = 1.05292905767805e-5; 375 | O1.diff = (-(eta+psi)*O1+omega*O2+theta*C15); 376 | OKs {1} = (O1+O2); 377 | gKs {mS/uF} = gKs_max*(1+0.6/(1+pow(3.8e-5/Ca_i,1.4))); 378 | IKs {uA/uF} = gKs*OKs*(Vm-EKs); 379 | } 380 | subsystem INa { 381 | provides INa {uA/uF}; 382 | shared h {1}; 383 | shared j {1}; 384 | shared m {1}; 385 | subsystem INa_h_gate { 386 | provides diffvar @gate h {1}; 387 | ah {1/ms} = ((Vm >= -40) ? 0 : 0.135*exp((80+Vm)/-6.8)); 388 | bh {1/ms} = ((Vm >= -40) ? 1/(0.13*(1+exp((Vm+10.66)/-11.1))) : (3.56*exp(0.079*Vm)+3.1e5*exp(0.35*Vm))); 389 | h.init {1} = 0.991354143386887; 390 | h.diff = (ah*(1-h)-bh*h); 391 | } 392 | subsystem INa_j_gate { 393 | provides diffvar @gate j {1}; 394 | aj {1/ms} = ((Vm >= -40) ? 0 : (-1.2714e5*exp(0.2444*Vm)-6.948e-5*exp(-0.04391*Vm))*(Vm+37.78)/(1+exp(0.311*(Vm+79.23)))); 395 | bj {1/ms} = ((Vm >= -40) ? 0.3*exp(-2.535e-7*Vm)/(1+exp(-0.1*(Vm+32))) : 0.1212*exp(-0.01052*Vm)/(1+exp(-0.1378*(Vm+40.14)))); 396 | j.init {1} = 0.99709036251243; 397 | j.diff = (aj*(1-j)-bj*j); 398 | } 399 | subsystem INa_m_gate { 400 | provides diffvar @gate m {1}; 401 | am {1/ms} = 0.32*(Vm+47.13)/(1-exp(-0.1*(Vm+47.13))); 402 | bm {1/ms} = 0.08*exp(-Vm/11); 403 | m.init {1} = 0.00101841101248412; 404 | m.diff = (am*(1-m)-bm*m); 405 | } 406 | g_Na {mS/uF} = 9.075; 407 | INa {uA/uF} = g_Na*pow(m,3)*h*j*(Vm-ENa); 408 | } 409 | subsystem INaL { 410 | provides INaL {uA/uF}; 411 | shared hL {1}; 412 | shared mL {1}; 413 | subsystem INaL_hL_gate { 414 | provides diffvar @gate hL {1}; 415 | hL_infinity {1} = 1/(1+exp((Vm+91)/6.1)); 416 | tau_hL {ms} = 600; 417 | hL.init {1} = 0.319611809402137; 418 | hL.diff = (hL_infinity-hL)/tau_hL; 419 | } 420 | subsystem INaL_mL_gate { 421 | provides diffvar @gate mL {1}; 422 | amL {1/ms} = 0.32*(Vm+47.13)/(1-exp(-0.1*(Vm+47.13))); 423 | bmL {1/ms} = 0.08*exp(-Vm/11); 424 | mL.init {1} = 0.00101841101248412; 425 | mL.diff = (amL*(1-mL)-bmL*mL); 426 | } 427 | gNaL {mS/uF} = 0.0065; 428 | INaL {uA/uF} = gNaL*pow(mL,3)*hL*(Vm-ENa); 429 | } 430 | subsystem Irel { 431 | provides diffvar Irel {mmol/L/ms}; 432 | K_beta {mmol/L} = 0.28; 433 | Krel_infinity {mmol/L} = 1; 434 | Krel_tau {mmol/L} = 0.0123; 435 | beta_0 {ms} = 4.75; 436 | delta_beta_0 {1} = 1; 437 | h_beta {1} = 10; 438 | h_rel {1} = 8; 439 | kappa {uF*mmol/ms^2/uA/L} = 0.1125; 440 | delta_beta_CaMK {1} = delta_beta_0/(1+pow(K_beta/(1*CaMK_active),h_beta)); 441 | beta_tau {ms} = beta_0*(1+delta_beta_CaMK); 442 | alpha_rel {uF*mmol/uA/L/ms} = beta_tau*kappa; 443 | tau_rel {ms} = beta_tau/(1+Krel_tau/Ca_JSR); 444 | rel_infinity {mmol/L/ms} = ICaL*alpha_rel/(1+pow(Krel_infinity/Ca_JSR,h_rel)); 445 | Irel.init {mmol/L/ms} = 0.000714227102027745; 446 | Irel.diff = -(rel_infinity+Irel)/tau_rel; 447 | } 448 | subsystem Ito1 { 449 | provides Ito1 {uA/uF}; 450 | shared a {1}; 451 | shared i1f {1}; 452 | shared i1s {1}; 453 | subsystem Ito1_a_gate { 454 | provides diffvar @gate a {1}; 455 | a_infinity {1} = 1/(1+exp((Vm+9.437)/-7.133)); 456 | alpha_a {1/ms} = 1/(1.2089*(1+exp((Vm-18.4099)/-29.3814))); 457 | beta_a {1/ms} = 3.5/(1+exp((Vm+100)/29.3814)); 458 | tau_a {ms} = 1/(alpha_a+beta_a); 459 | a.init {1} = 1.76776038804228e-5; 460 | a.diff = (a_infinity-a)/tau_a; 461 | } 462 | subsystem Ito1_i1f_gate { 463 | provides diffvar @gate i1f {1}; 464 | alpha_i1f {1/ms} = 0.025/(1+exp((Vm+58)/5)); 465 | beta_i1f {1/ms} = 1/(9.7953*(1+exp((Vm+19)/-9))); 466 | i1f.init {1} = 0.997976503910799; 467 | i1f.diff = (alpha_i1f*(1-i1f)-beta_i1f*i1f); 468 | } 469 | subsystem Ito1_i1s_gate { 470 | provides diffvar @gate i1s {1}; 471 | alpha_i1s {1/ms} = 1/(250*(1+exp((Vm+60)/5))); 472 | beta_i1s {1/ms} = 1/(9.7953*(1+exp((Vm+19)/-9))); 473 | i1s.init {1} = 0.947581184798815; 474 | i1s.diff = (alpha_i1s*(1-i1s)-beta_i1s*i1s); 475 | } 476 | gto1 {mS/uF} = 0.497458; 477 | rto1 {1} = exp(Vm/550); 478 | Ito1 {uA/uF} = gto1*pow(a,3)*i1f*i1s*rto1*(VEK); 479 | } 480 | subsystem Iup { 481 | provides Iup {mmol/L/ms}; 482 | delta_iupCaMK_bar {1} = 0.75; 483 | delta_kmPLB_bar {mmol/L} = 0.00017; 484 | iupbar {mmol/L/ms} = 0.004375; 485 | kmCaMK {mmol/L} = 0.15; 486 | kmup {mmol/L} = 0.00092; 487 | delta_iupCaMK {1} = delta_iupCaMK_bar*CaMK_active*1/(kmCaMK+CaMK_active*1); 488 | delta_kmPLB {mmol/L} = delta_kmPLB_bar*CaMK_active*1/(kmCaMK+CaMK_active*1); 489 | Iup {mmol/L/ms} = (delta_iupCaMK+1)*iupbar*Ca_i/((Ca_i+kmup)-delta_kmPLB); 490 | } 491 | subsystem Ca { 492 | provides diffvar Ca_JSR {mmol/L}; 493 | provides diffvar Ca_NSR {mmol/L}; 494 | provides diffvar Ca_i {mmol/L}; 495 | provides diffvar Ca_ss_CaL {mmol/L}; 496 | provides diffvar Ca_ss_sr {mmol/L}; 497 | provides tau_diff {ms}; 498 | BSLmax {mmol/L} = 1.124; 499 | BSRmax {mmol/L} = 0.047; 500 | Ca_NSR.init {mmol/L} = 1.01475649943057; 501 | Ca_NSR.diff = (Iup-(Ileak+Itr*Vjsr/Vnsr)); 502 | KmBSL {mmol/L} = 0.0087; 503 | KmBSR {mmol/L} = 0.00087; 504 | cmdn_bar {mmol/L} = 0.05; 505 | csqnbar {mmol/L} = 10; 506 | km_cmdn {mmol/L} = 0.00238; 507 | km_trpn {mmol/L} = 0.0005; 508 | kmcsqn {mmol/L} = 0.8; 509 | tau_diff {ms} = 0.2; 510 | tau_diff_ss {ms} = 2; 511 | trpn_bar {mmol/L} = 0.07; 512 | Idiff {mmol/L/ms} = (Ca_ss_sr-Ca_i)/tau_diff; 513 | Idiff_ss {mmol/L/ms} = (Ca_ss_sr-Ca_ss_CaL)/tau_diff_ss; 514 | bcsqn {1} = 1/(1+kmcsqn*csqnbar/pow((Ca_JSR+kmcsqn),2)); 515 | bmyo {1} = 1/(1+cmdn_bar*km_cmdn/pow((Ca_i+km_cmdn),2)+km_trpn*trpn_bar/pow((Ca_i+km_trpn),2)); 516 | bss_cal {1} = 1/(1+BSRmax*KmBSR/pow((KmBSR+Ca_ss_CaL),2)+BSLmax*KmBSL/pow((KmBSL+Ca_ss_CaL),2)); 517 | bss_sr {1} = 1/(1+BSRmax*KmBSR/pow((KmBSR+Ca_ss_sr),2)+BSLmax*KmBSL/pow((KmBSL+Ca_ss_sr),2)); 518 | Ca_JSR.init {mmol/L} = 0.993914988616979; 519 | Ca_JSR.diff = bcsqn*(Itr-Irel); 520 | Ca_i.init {mmol/L} = 8.38749860095482e-5; 521 | Ca_i.diff = bmyo*(-((ICab+IpCa)-2*INaCa)*AF/(Vmyo*2)+(Ileak-Iup)*Vnsr/Vmyo+Idiff*Vss_sr/Vmyo); 522 | Ca_ss_CaL.init {mmol/L} = 0.000119239795531548; 523 | Ca_ss_CaL.diff = -bss_cal*(ICaL*AF/(2*Vss_CaL)-Idiff_ss*Vss_sr/Vss_CaL); 524 | Ca_ss_sr.init {mmol/L} = 0.00011296707102434; 525 | Ca_ss_sr.diff = -bss_sr*((Idiff+Idiff_ss)-(2*INaCa_ss_sr*AF/(2*Vss_sr)+Irel*Vjsr/Vss_sr)); 526 | } 527 | subsystem Cl { 528 | provides diffvar Cl_i {mmol/L}; 529 | provides diffvar Cl_ss {mmol/L}; 530 | Idiff_Cl {mmol/L/ms} = (Cl_ss-Cl_i)/tau_diff; 531 | Cl_i.init {mmol/L} = 20.6683603724432; 532 | Cl_i.diff = -(IClb*AF/(-1*Vmyo)-(CT_Na_Cl+CT_K_Cl+Idiff_Cl*Vss_sr/Vmyo)); 533 | Cl_ss.init {mmol/L} = 20.6683605553303; 534 | Cl_ss.diff = -(Ito2*AF/(-1*Vss_sr)+Idiff_Cl); 535 | } 536 | subsystem Na { 537 | provides diffvar Na_i {mmol/L}; 538 | provides diffvar Na_ss_sr {mmol/L}; 539 | Idiff_Na {mmol/L/ms} = (Na_ss_sr-Na_i)/tau_diff; 540 | Na_i.init {mmol/L} = 8.01031392415197; 541 | Na_i.diff = -((3*INaCa+3*INaK+INa+INaL+INab)*AF/Vmyo-(CT_Na_Cl+Idiff_Na*Vss_sr/Vmyo)); 542 | Na_ss_sr.init {mmol/L} = 8.01033434859049; 543 | Na_ss_sr.diff = -(3*INaCa_ss_sr*AF/Vss_sr+Idiff_Na); 544 | } 545 | 546 | subsystem membrane { 547 | provides @interp(-100,100,1e-2) Vm {mV} = V; 548 | provides @interp(-100,100,1e-2) VEK = Vm-EK; 549 | provides i_Stim {uA/uF}; 550 | caiont {uA/uF} = ((ICaL+ICab+IpCa)-2*(INaCa+INaCa_ss_sr)); 551 | clont {uA/uF} = (IClb+Ito2); 552 | naiont {uA/uF} = (INa+3*(INaCa+INaCa_ss_sr)+3*INaK+INaL+INab); 553 | i_Stim = 0; 554 | kiont {uA/uF} = (IKr+IKs+IK1+IKp+-2*INaK+Ito1+i_Stim); 555 | 556 | provides V_init = -87; 557 | provides Iion = naiont+kiont+caiont+clont; 558 | } 559 | 560 | subsystem K { 561 | provides diffvar K_i {mmol/L}; 562 | K_i.init {mmol/L} = 144.907134343314; 563 | K_i.diff = -(((IKs+IKr+IK1+Ito1+IKp+i_Stim)-2*INaK)*AF/Vmyo-CT_K_Cl); 564 | } 565 | } 566 | -------------------------------------------------------------------------------- /domains/electrophysiology/fenton_karma_1998_MLR1.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | * 26 | * Taken and adaped from 27 | * https://models.physiomeproject.org/e/40/fenton_karma_1998_MLR1.cellml/view 28 | * 29 | */ 30 | 31 | integrate time {ms}; 32 | 33 | shared V {mV}; 34 | shared V_init {mV}; 35 | shared Iion {uA/uF}; 36 | 37 | subsystem fenton_karma_1998_MLR1 { 38 | diffvar v {1}; 39 | diffvar w {1}; 40 | 41 | provides V_init = -85; 42 | V_fi {mV} = 15; 43 | 44 | u {1} = (V-V_init)/(V_fi-V_init); 45 | 46 | Cm {uF/cm^2} = 1; 47 | 48 | u_c = 0.13; 49 | p = ((u < u_c) ? 0 : 1); 50 | 51 | u_v = 0; 52 | q = ((u < u_v) ? 0 : 1); 53 | 54 | tau_v1_minus {ms} = 18.2; 55 | tau_v2_minus {ms} = 18.2; 56 | tau_v_plus {ms} = 10; 57 | tau_v_minus {ms} = (q*tau_v1_minus+(1-q)*tau_v2_minus); 58 | v.init = 1; 59 | v.diff = ((1-p)*(1-v)/tau_v_minus-p*v/tau_v_plus); 60 | 61 | 62 | g_fi_max {mS/cm^2} = 5.8; 63 | tau_d {ms} = Cm/g_fi_max; 64 | J_fi {1/ms} = -v*p*(1-u)*(u-u_c)/tau_d; 65 | 66 | tau_w_minus {ms} = 80; 67 | tau_w_plus {ms} = 1020; 68 | w.init {1} = 1; 69 | w.diff = ((1-p)*(1-w)/tau_w_minus-p*w/tau_w_plus); 70 | 71 | k {1} = 10; 72 | tau_si {ms} = 127; 73 | u_csi {1} = 0.85; 74 | J_si {1/ms} = -w*(1+tanh(k*(u-u_csi)))/(2*tau_si); 75 | 76 | 77 | tau_0 {ms} = 12.5; 78 | tau_r {ms} = 130; 79 | J_so {1/ms} = (u*(1-p)/tau_0+p/tau_r); 80 | 81 | 82 | provides Iion = (V_fi-V_init)*(J_fi+J_so+J_si); 83 | 84 | } 85 | -------------------------------------------------------------------------------- /domains/electrophysiology/inada_2009.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | 28 | //NOTE: Initial conditions for statevariables don't match the cellML version 29 | //I was too lazy to transcribe all those numbers. 30 | 31 | integrate time {s}; 32 | 33 | shared V {mV}; 34 | shared V_init {mV}; 35 | shared Iion {uA/uF}; 36 | 37 | shared cell_type {enum(AN,NH,N)}; 38 | subsystem inada_N_switch { provides cell_type = N; } 39 | subsystem inada_NH_switch { provides cell_type = NH; } 40 | subsystem inada_AN_switch { provides cell_type = AN; } 41 | 42 | 43 | shared Iion_sum {nA}; 44 | 45 | shared RTONF {mV}; 46 | shared Nao {mM}; 47 | shared Kc {mM}; 48 | shared Nai {mM}; 49 | shared F {C/mol}; 50 | shared Ki {mM}; 51 | shared ACh {mmol/L}; 52 | subsystem inada_base { 53 | provides F {C/mol} = 96485.3415; 54 | provides R {J/kmol/K} = 8314.472; 55 | provides T {K}= 310; 56 | provides RTONF {mV}= R*T/F; 57 | 58 | provides V_init {mV}; 59 | if (cell_type == N) { 60 | V_init {mV} = -49.7094187908202; 61 | } else if (cell_type == NH) { 62 | V_init {mV} = -69.760276376489; 63 | } else { 64 | V_init {mV} = -71.5535452525735; 65 | } 66 | 67 | if (cell_type == NH) { 68 | C {uF} = 2.9e-5; 69 | } else { 70 | C {uF} = 4e-5; 71 | } 72 | provides accum Iion += convert(Iion_sum, uA)/C; 73 | 74 | shared Cai {mmol/L}; 75 | shared Casub {mmol/L}; 76 | shared E_K {mV}; 77 | shared E_Na {mV}; 78 | 79 | provides Ki {mmol/L} = 140; 80 | provides Nai {mmol/L} = 8; 81 | provides Cao {mmol/L} = 2; 82 | provides Kc {mmol/L} = 5.4; 83 | provides Nao {mmol/L} = 140; 84 | 85 | subsystem background_current { 86 | if (cell_type == N) { 87 | E_b {mV} = -22.5; 88 | g_b {uS} = 0.0012; 89 | } else if (cell_type == NH) { 90 | E_b {mV} = -40; 91 | g_b {uS} = 0.002; 92 | } else { 93 | E_b {mV} = -52.5; 94 | g_b {uS} = 0.0018; 95 | } 96 | provides accum Iion_sum += g_b*(V-E_b); 97 | } 98 | subsystem sodium_potassium_pump { 99 | if (cell_type == N) { 100 | I_p {nA} = 0.14268; 101 | } else if (cell_type == NH) { 102 | I_p {nA} = 0.1968; 103 | } else { 104 | I_p {nA} = 0.0246; 105 | } 106 | provides accum Iion_sum += I_p*pow(Nai/(5.64{mmol/L}+Nai),3{1})*pow(Kc/(0.621{mmol/L}+Kc),2{1})*1.6{1}/(1.5{1}+exp(-(V+60{mV})/40{mV})); 107 | } 108 | //WARNING, circular dependency detected, dumping the rest. You'll have to fix this manually. 109 | shared i_ACh {nA}; 110 | shared i_CaL {nA}; 111 | subsystem L_type_calcium_current { 112 | shared d {1}; 113 | shared f {1}; 114 | shared f2 {1}; 115 | subsystem L_type_calcium_current_d_gate { 116 | provides diffvar d {1}; 117 | if (cell_type == N) { 118 | act_shift {mV} = -15; 119 | } else { 120 | act_shift {mV} = 0; 121 | } 122 | alpha_d {1/s} = (-26.12{1/s/mV}*(V+35{mV})/(exp((V+35{mV})/-2.5{mV})-1{1})+-78.11{1/s/mV}*V/(exp(-0.208{1/mV}*V)-1{1})); 123 | beta_d {1/s} = 10.52{1/s/mV}*(V-5{mV})/(exp(0.4{1/mV}*(V-5{mV}))-1{1}); 124 | if (cell_type == N) { 125 | slope_factor_act {mV} = -5; 126 | } else { 127 | slope_factor_act {mV} = -6.61; 128 | } 129 | d_inf {1} = 1{1}/(1{1}+exp((V-(-3.2{mV}+act_shift))/slope_factor_act)); 130 | tau_d {s} = 1{1}/(alpha_d+beta_d); 131 | d.init {1} = 0.00179250298710316; 132 | d.diff = (d_inf-d)/tau_d; 133 | } 134 | subsystem L_type_calcium_current_f2_gate { 135 | provides diffvar f2 {1}; 136 | inact_shift {mV} = -5; 137 | tau_f2 {s} = (0.06{s}+0.48076{s}*2.25{1}*exp(-pow((V--40{mV}),2{1})/138.04{mV^2})); 138 | f2_inf {1} = 1{1}/(1{1}+exp((V-(-24{mV}+inact_shift))/6.31{mV})); 139 | f2.init {1} = 0.774394220125623; 140 | f2.diff = (f2_inf-f2)/tau_f2; 141 | } 142 | subsystem L_type_calcium_current_f_gate { 143 | provides diffvar f {1}; 144 | inact_shift {mV} = -5; 145 | tau_f {s} = (0.01{s}+0.1539{s}*exp(-pow((V+40{mV}),2{1})/185.67{mV^2})); 146 | f_inf {1} = 1{1}/(1{1}+exp((V-(-24{mV}+inact_shift))/6.31{mV})); 147 | f.init {1} = 0.975550840189597; 148 | f.diff = (f_inf-f)/tau_f; 149 | } 150 | if (cell_type == N) { 151 | E_CaL {mV} = 62; 152 | g_CaL {uS} = 0.009; 153 | } else if (cell_type == NH) { 154 | E_CaL {mV} = 62.1; 155 | g_CaL {uS} = 0.021; 156 | } else { 157 | E_CaL {mV} = 62.5; 158 | g_CaL {uS} = 0.0185; 159 | } 160 | provides i_CaL {nA} = g_CaL*d*(0.675{1}*f+0.325{1}*f2)*(V-E_CaL)*(1{1}-i_ACh*ACh/(0.9e-4{mmol/L}+ACh)/1{nA}); 161 | provides accum Iion_sum += i_CaL; 162 | } 163 | subsystem acetylcholine_sensitive_current { 164 | provides ACh {mmol/L}; 165 | shared achf {1}; 166 | shared achs {1}; 167 | subsystem acetylcholine_sensitive_current_achf_gate { 168 | provides diffvar achf {1}; 169 | alpha_achf {1/s} = 73.1; 170 | beta_achf {1/s} = 120{1/s}/(1{1}+exp(-(V+50{mV})/15{mV})); 171 | achf.init {1} = 0.550559577208797; 172 | achf.diff = (alpha_achf*(1{1}-achf)-beta_achf*achf); 173 | } 174 | subsystem acetylcholine_sensitive_current_achs_gate { 175 | provides diffvar achs {1}; 176 | alpha_achs {1/s} = 3.7; 177 | beta_achs {1/s} = 5.82{1/s}/(1{1}+exp(-(V+50{mV})/15{mV})); 178 | achs.init {1} = 0.567277036232041; 179 | achs.diff = (alpha_achs*(1{1}-achs)-beta_achs*achs); 180 | } 181 | ACh {mmol/L} = 0; 182 | K_ACh {mmol/L} = 0.00035; 183 | g_ACh_max {uS} = 0.0198; 184 | g_ACh {uS} = g_ACh_max*achf*achs*pow(ACh,1.5{1})/(pow(K_ACh,1.5{1})+pow(ACh,1.5{1})); 185 | provides i_ACh {nA} = g_ACh*Kc/(10{mmol/L}+Kc)*(V-E_K)/(1{1}+exp(((V-E_K)-140{mV})/(2.5{1}*RTONF))); 186 | provides accum Iion_sum += i_ACh; 187 | } 188 | 189 | shared i_NaCa {nA}; 190 | subsystem intracellular_calcium_concentration { 191 | provides diffvar Cai {mmol/L}; 192 | provides diffvar Casub {mmol/L}; 193 | diffvar Ca_rel {mmol/L}; 194 | diffvar Ca_up {mmol/L}; 195 | diffvar f_CMi {1}; 196 | diffvar f_CMs {1}; 197 | diffvar f_CQ {1}; 198 | diffvar f_CSL {1}; 199 | diffvar f_TC {1}; 200 | diffvar f_TMC {1}; 201 | diffvar f_TMM {1}; 202 | K_up {mmol/L} = 0.0006; 203 | if (cell_type == N) { 204 | P_rel {1/s} = 1500; 205 | V_cell {um^3} = 3.18872e-6; 206 | } else { 207 | P_rel {1/s} = 1805.6; 208 | V_cell {um^3} = 4.39823e-6; 209 | } 210 | diff_f_CMi {1/s} = (227.7e3{L/s/mmol}*Cai*(1{1}-f_CMi)-0.542e3{1/s}*f_CMi); 211 | diff_f_CMs {1/s} = (227.7e3{L/s/mmol}*Casub*(1{1}-f_CMs)-0.542e3{1/s}*f_CMs); 212 | diff_f_CQ {1/s} = (0.534e3{L/s/mmol}*Ca_rel*(1{1}-f_CQ)-0.445e3{1/s}*f_CQ); 213 | diff_f_CSL {1/s} = 0.001{1}*(115{L/s/mmol}*Casub*(1{1}-f_CSL)-1000{1/s}*f_CSL); 214 | diff_f_TC {1/s} = (88.8e3{L/s/mmol}*Cai*(1{1}-f_TC)-0.446e3{1/s}*f_TC); 215 | diff_f_TMC {1/s} = (227.7e3{L/s/mmol}*Cai*((1{1}-f_TMC)-f_TMM)-0.00751e3{1/s}*f_TMC); 216 | diff_f_TMM {1/s} = (2.277e3{L/s/mmol}*2.5{mmol/L}*((1{1}-f_TMC)-f_TMM)-0.751e3{1/s}*f_TMM); 217 | i_diff {mmol/s/L} = (Casub-Cai)/0.04e-3{s}; 218 | tau_tr {s} = 0.06; 219 | V_rel {um^3} = 0.0012{1}*V_cell; 220 | V_sub {um^3} = 0.01{1}*V_cell; 221 | V_up {um^3} = 0.0116{1}*V_cell; 222 | f_CMi.init {1} = 0.0723007987059414; 223 | f_CMi.diff = diff_f_CMi; 224 | f_CMs.init {1} = 0.0630771339141488; 225 | f_CMs.diff = diff_f_CMs; 226 | f_CQ.init {1} = 0.261430602900137; 227 | f_CQ.diff = diff_f_CQ; 228 | f_CSL.init {1} = 4.1497704886823e-5; 229 | f_CSL.diff = diff_f_CSL; 230 | f_TC.init {1} = 0.0356473236675985; 231 | f_TC.diff = diff_f_TC; 232 | f_TMC.init {1} = 0.443317425115817; 233 | f_TMC.diff = diff_f_TMC; 234 | f_TMM.init {1} = 0.491718960234865; 235 | f_TMM.diff = diff_f_TMM; 236 | i_rel {mmol/s/L} = P_rel*(Ca_rel-Casub)/(1{1}+pow(0.0012{mmol/L}/Casub,2{1})); 237 | i_tr {mmol/s/L} = (Ca_up-Ca_rel)/tau_tr; 238 | i_up {mmol/s/L} = 5{mmol/s/L}/(1{1}+K_up/Cai); 239 | Ca_rel.init {mmol/L} = 0.296249516481577; 240 | Ca_rel.diff = ((i_tr-i_rel)-10{mmol/L}*diff_f_CQ); 241 | Ca_up.init {mmol/L} = 1.11092514657408; 242 | Ca_up.diff = (i_up-i_tr*V_rel/V_up); 243 | Casub.init {mmol/L} = 0.000160310601192365; 244 | Casub.diff = ((((-(i_CaL-2{1}*i_NaCa)/(2{uL/um^3}*F)+i_rel*V_rel)/V_sub-i_diff)-0.045{mmol/L}*diff_f_CMs)-0.031{mmol/L}/1.2{1}*diff_f_CSL); 245 | Vi {um^3} = (0.46{1}*V_cell-V_sub); 246 | Cai.init {mmol/L} = 0.000184969821581882; 247 | Cai.diff = ((i_diff*V_sub-i_up*V_up)/Vi-(0.045{mmol/L}*diff_f_CMi+0.031{mmol/L}*diff_f_TC+0.062{mmol/L}*diff_f_TMC)); 248 | } 249 | 250 | subsystem rapid_delayed_rectifier_potassium_current { 251 | provides E_K {mV}; 252 | shared paf {1}; 253 | shared pas {1}; 254 | shared pik {1}; 255 | subsystem rapid_delayed_rectifier_potassium_current_paf_gate { 256 | provides diffvar paf {1}; 257 | paf_infinity {1} = 1{1}/(1{1}+exp((V+10.22{mV})/-8.5{mV})); 258 | tau_paf {s} = 1{1}/(17{1/s}*exp(0.0398{1/mV}*V)+0.211{1/s}*exp(-0.051{1/mV}*V)); 259 | paf.init {1} = 0.192515363116553; 260 | paf.diff = (paf_infinity-paf)/tau_paf; 261 | } 262 | subsystem rapid_delayed_rectifier_potassium_current_pas_gate { 263 | provides diffvar pas {1}; 264 | pas_infinity {1} = 1{1}/(1{1}+exp((V+10.22{mV})/-8.5{mV})); 265 | tau_pas {s} = (0.33581{s}+0.90673{s}*exp(-pow((V+10{mV}),2{1})/988.05{mV^2})); 266 | pas.init {1} = 0.0797182955833868; 267 | pas.diff = (pas_infinity-pas)/tau_pas; 268 | } 269 | subsystem rapid_delayed_rectifier_potassium_current_pik_gate { 270 | provides diffvar pik {1}; 271 | alpha_pik {1/s} = 92.01{1/s}*exp(-0.0183{1/mV}*V); 272 | beta_pik {1/s} = 603.6{1/s}*exp(0.00942{1/mV}*V); 273 | pik_infinity {1} = 1{1}/(1{1}+exp((V+4.9{mV})/15.14{mV}))*(1{1}-0.3{1}*exp(-pow(V,2{1})/500{mV^2})); 274 | tau_pik {s} = 1{1}/(alpha_pik+beta_pik); 275 | pik.init {1} = 0.949023698965401; 276 | pik.diff = (pik_infinity-pik)/tau_pik; 277 | } 278 | E_K {mV} = RTONF*log(Kc/Ki); 279 | if (cell_type == N) { 280 | g_Kr {uS} = 0.0035; 281 | } else if (cell_type == NH) { 282 | g_Kr {uS} = 0.002; 283 | } else { 284 | g_Kr {uS} = 0.0015; 285 | } 286 | provides accum Iion_sum += g_Kr*(0.9{1}*paf+0.1{1}*pas)*pik*(V-E_K); 287 | } 288 | subsystem sodium_calcium_exchange_current { 289 | K1ni {mmol/L} = 395.3; 290 | K1no {mmol/L} = 1628; 291 | K2ni {mmol/L} = 2.289; 292 | K2no {mmol/L} = 561.4; 293 | K3ni {mmol/L} = 26.44; 294 | K3no {mmol/L} = 4.663; 295 | Kci {mmol/L} = 0.0207; 296 | Kcni {mmol/L} = 26.44; 297 | Kco {mmol/L} = 3.663; 298 | Qci {1} = 0.1369; 299 | Qco {1} = 0; 300 | Qn {1} = 0.4315; 301 | if (cell_type == N) { 302 | kNaCa {nA} = 2.14455; 303 | } else { 304 | kNaCa {nA} = 5.916; 305 | } 306 | di {1} = (1{1}+Casub/Kci*(1{1}+exp(-Qci*V/RTONF)+Nai/Kcni)+Nai/K1ni+pow(Nai,2{1})/(K1ni*K2ni)+pow(Nai,3{1})/(K1ni*K2ni*K3ni)); 307 | do_ {1} = (1{1}+Cao/Kco*(1{1}+exp(Qco*V/RTONF))+Nao/K1no+pow(Nao,2{1})/(K1no*K2no)+pow(Nao,3{1})/(K1no*K2no*K3no)); 308 | k32 {1} = exp(Qn*V/(2{1}*RTONF)); 309 | k34 {1} = Nao/(K3no+Nao); 310 | k41 {1} = exp(-Qn*V/(2{1}*RTONF)); 311 | k43 {1} = Nai/(K3ni+Nai); 312 | k12 {1} = Casub/Kci*exp(-Qci*V/RTONF)/di; 313 | k14 {1} = (pow(Nai,2{1})/(K1ni*K2ni)+pow(Nai,3{1})/(K1ni*K2ni*K3ni))*exp(Qn*V/(2{1}*RTONF))/di; 314 | k21 {1} = Cao/Kco*exp(-Qco*V/RTONF)/do_; 315 | k23 {1} = (pow(Nao,2{1})/(K1no*K2no)+pow(Nao,3{1})/(K1no*K2no*K3no))*exp(-Qn*V/(2{1}*RTONF))/do_; 316 | x1 {1} = (k41*k34*(k23+k21)+k21*k32*(k43+k41)); 317 | x2 {1} = (k32*k43*(k14+k12)+k41*k12*(k34+k32)); 318 | x3 {1} = (k14*k43*(k23+k21)+k12*k23*(k43+k41)); 319 | x4 {1} = (k23*k34*(k14+k12)+k14*k21*(k34+k32)); 320 | provides i_NaCa {nA} = kNaCa*(x2*k21-x1*k12)/(x1+x2+x3+x4); 321 | provides accum Iion_sum += i_NaCa; 322 | } 323 | } 324 | 325 | subsystem inada_not_N { 326 | subsystem fast_sodium_current { 327 | provides E_Na {mV}; 328 | shared h1 {1}; 329 | shared h2 {1}; 330 | shared m {1}; 331 | subsystem fast_sodium_current_h1_gate { 332 | provides diffvar h1 {1}; 333 | alpha_h1 {1/s} = 44.9{1/s}*exp((V+66.9{mV})/-5.57{mV}); 334 | beta_h1 {1/s} = 1491{1/s}/(1{1}+323.3{1}*exp((V+94.6{mV})/-12.9{mV})); 335 | tau_h1 {s} = (0.03{s}/(1{1}+exp((V+40{mV})/6{mV}))+0.00035{s}); 336 | h1_inf {1} = alpha_h1/(alpha_h1+beta_h1); 337 | h1.init {1} = 0.0243210273637729; 338 | h1.diff = (h1_inf-h1)/tau_h1; 339 | } 340 | subsystem fast_sodium_current_h2_gate { 341 | provides diffvar h2 {1}; 342 | alpha_h2 {1/s} = 44.9{1/s}*exp((V+66.9{mV})/-5.57{mV}); 343 | beta_h2 {1/s} = 1491{1/s}/(1{1}+323.3{1}*exp((V+94.6{mV})/-12.9{mV})); 344 | tau_h2 {s} = (0.12{s}/(1{1}+exp((V+60{mV})/2{mV}))+0.00295{s}); 345 | h2_inf {1} = alpha_h2/(alpha_h2+beta_h2); 346 | h2.init {1} = 0.0157156121147801; 347 | h2.diff = (h2_inf-h2)/tau_h2; 348 | } 349 | subsystem fast_sodium_current_m_gate { 350 | provides diffvar m {1}; 351 | E0_m {mV} = (V+44.4{mV}); 352 | delta_m {mV} = 1e-5; 353 | alpha_m {1/s} = ((fabs(E0_m) < delta_m) ? -460{1/s}*-12.673{1}/(exp(E0_m/-12.673{mV})) : -460{1/s/mV}*E0_m/(exp(E0_m/-12.673{mV})-1{1})); 354 | beta_m {1/s} = 18400{1/s}*exp(E0_m/-12.673{mV}); 355 | m.init {1} = 0.143642247226618; 356 | m.diff = (alpha_m*(1{1}-m)-beta_m*m); 357 | } 358 | E_Na {mV} = RTONF*log(Nao/Nai); 359 | g_Na {uL/s} = 5e-7; 360 | provides accum Iion_sum += g_Na*pow(m,3{1})*(0.635{1}*h1+0.365{1}*h2)*Nao*V*F/RTONF*(exp((V-E_Na)/RTONF)-1{1})/(exp(V/RTONF)-1{1}); 361 | } 362 | 363 | subsystem time_independent_potassium_current { 364 | if (cell_type == NH) { 365 | g_K1 {uS} = 0.015; 366 | } else { 367 | g_K1 {uS} = 0.0125; 368 | } 369 | g_K1_prime {uS} = g_K1*(0.5{1}+0.5{1}/(1{1}+exp((V+30{mV})/5{mV}))); 370 | provides accum Iion_sum += g_K1_prime*pow(Kc/(Kc+0.59{mmol/L}),3{1})*(V+81.9{mV})/(1{1}+exp(1.393{1}*(V+81.9{mV}+3.6{mV})/RTONF)); 371 | } 372 | 373 | subsystem transient_outward_potassium_current { 374 | provides E_K {mV}; 375 | shared q_fast {1}; 376 | shared q_slow {1}; 377 | shared r {1}; 378 | subsystem transient_outward_potassium_current_qfast_gate { 379 | provides diffvar q_fast {1}; 380 | qfast_infinity {1} = 1{1}/(1{1}+exp((V+33.8{mV})/6.12{mV})); 381 | tau_qfast {s} = (12.66e-3{s}+4.72716{s}/(1{1}+exp((V+154.5{mV})/23.96{mV}))); 382 | q_fast.init {1} = 0.899732315818241; 383 | q_fast.diff = (qfast_infinity-q_fast)/tau_qfast; 384 | } 385 | subsystem transient_outward_potassium_current_qslow_gate { 386 | provides diffvar q_slow {1}; 387 | qslow_infinity {1} = 1{1}/(1{1}+exp((V+33.8{mV})/6.12{mV})); 388 | tau_qslow {s} = (0.1{s}+4{s}*exp(-pow((V+65{mV}),2{1})/500{mV^2})); 389 | q_slow.init {1} = 0.190111737767474; 390 | q_slow.diff = (qslow_infinity-q_slow)/tau_qslow; 391 | } 392 | subsystem transient_outward_potassium_current_r_gate { 393 | provides diffvar r {1}; 394 | r_infinity {1} = 1{1}/(1{1}+exp((V-7.44{mV})/-16.4{mV})); 395 | tau_r {s} = (0.596e-3{s}+3.118e-3{s}/(1.037{1}*exp(0.09{1/mV}*(V+30.61{mV}))+0.396{1}*exp(-0.12{1/mV}*(V+23.84{mV})))); 396 | r.init {1} = 0.0296516611999521; 397 | r.diff = (r_infinity-r)/tau_r; 398 | } 399 | E_K {mV} = RTONF*log(Kc/Ki); 400 | if (cell_type == NH) { 401 | g_to {uS} = 0.014; 402 | } else { 403 | g_to {uS} = 0.02; 404 | } 405 | provides accum Iion_sum += g_to*r*(0.45{1}*q_fast+0.55{1}*q_slow)*(V-E_K); 406 | } 407 | } 408 | 409 | subsystem inada_N_only { 410 | subsystem hyperpolarising_activated_current { 411 | shared y {1}; 412 | subsystem hyperpolarising_activated_current_y_gate { 413 | provides diffvar y {1}; 414 | tau_y {s} = (0.25{s}+2{s}*exp(-pow((V+70{mV}),2{1})/500{mV^2})); 415 | y_inf {1} = 1{1}/(1{1}+exp(((V+83.19{mV})--7.2{mV}*pow(ACh,0.69{1})/(pow(1.26e-5{mmol/L},0.69{1})+pow(ACh,0.69{1})))/13.56{mV})); 416 | y.init {1} = 0.0462303183096481; 417 | y.diff = (y_inf-y)/tau_y; 418 | } 419 | g_f {uS} = 0.001; 420 | provides accum Iion_sum += y*g_f*(V- -30{mV}); 421 | } 422 | subsystem sustained_outward_potassium_current { 423 | shared qa {1}; 424 | shared qi {1}; 425 | subsystem sustained_outward_potassium_current_qa_gate { 426 | provides diffvar qa {1}; 427 | alpha_qa {1/s} = 1{1}/(0.15{s}*exp(-V/11{mV})+0.2{s}*exp(-V/700{mV})); 428 | beta_qa {1/s} = 1{1}/(16{s}*exp(V/8{mV})+15{s}*exp(V/50{mV})); 429 | qa_infinity {1} = 1{1}/(1{1}+exp((V--49.1{mV})/-8.98{mV})); 430 | tau_qa {s} = 0.001{1}/(alpha_qa+beta_qa); 431 | qa.init {1} = 0.476404610622697; 432 | qa.diff = (qa_infinity-qa)/tau_qa; 433 | } 434 | subsystem sustained_outward_potassium_current_qi_gate { 435 | provides diffvar qi {1}; 436 | alpha_qi {1/s} = 0.1504{1}/(3100{s}*exp(V/13{mV})+700{s}*exp(V/70{mV})); 437 | beta_qi {1/s} = (0.1504{1}/(95{s}*exp(-V/10{mV})+50{s}*exp(-V/700{mV}))+0.000229{1/s}/(1{1}+exp(-V/5{mV}))); 438 | qi_infinity {1} = alpha_qi/(alpha_qi+beta_qi); 439 | tau_qi {s} = 0.001{1}/(alpha_qi+beta_qi); 440 | qi.init {1} = 0.542303657353244; 441 | qi.diff = (qi_infinity-qi)/tau_qi; 442 | } 443 | E_st {mV} = -37.4; 444 | g_st {uS} = 0.0001; 445 | 446 | provides accum Iion_sum += g_st*qa*qi*(V-E_st); 447 | } 448 | 449 | } 450 | 451 | subsystem inada_N { 452 | use inada_N_switch; 453 | use inada_base; 454 | use inada_N_only; 455 | } 456 | 457 | subsystem inada_NH { 458 | use inada_NH_switch; 459 | use inada_base; 460 | use inada_not_N; 461 | } 462 | 463 | subsystem inada_AN { 464 | use inada_AN_switch; 465 | use inada_base; 466 | use inada_not_N; 467 | } 468 | -------------------------------------------------------------------------------- /domains/electrophysiology/singleCell.mel: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | 27 | integrate t {ms}; 28 | 29 | shared V {mV}; 30 | shared Iion {uA/uF}; 31 | shared V_init {mV}; 32 | 33 | shared iStim {uA/uF}; 34 | 35 | subsystem Vm { 36 | provides diffvar V; 37 | V.init = V_init; 38 | V.diff = -Iion + iStim; 39 | } 40 | 41 | subsystem noStim { 42 | provides iStim; 43 | iStim = 0; 44 | } 45 | 46 | shared bcl_time {ms}; 47 | 48 | subsystem bcl_time { 49 | provides bcl_time; 50 | 51 | @param offset {ms} = 0; 52 | @param n {1} = 1; 53 | @param bcl {ms} = 1000; 54 | 55 | if (t < offset) { 56 | bcl_time = bcl*1000+t-offset; 57 | } else { 58 | beat = floor((t-offset)/bcl); 59 | if (beat >= n) { 60 | beat = n-1; 61 | } 62 | bcl_time = t-offset - beat*bcl; 63 | } 64 | } 65 | 66 | shared stim_time {ms}; 67 | 68 | subsystem squareStim { 69 | @param duration {ms} = 1; 70 | @param strength {uA/uF} = 60; 71 | 72 | provides iStim = 0; 73 | if (stim_time < duration) { 74 | iStim = strength; 75 | } 76 | } 77 | 78 | subsystem bclDefault { 79 | use Vm; 80 | use bcl_time; 81 | use squareStim { 82 | export stim_time as bcl_time; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /license_templates/cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | * LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | * by Robert Blake . 6 | * 7 | * LLNL-CODE-720003. 8 | * All rights reserved. 9 | * 10 | * This file is part of MELODEE. For details, see 11 | * http://github.com/llnl/melodee. 12 | * 13 | * Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | * may not use this file except in compliance with the License. You may 15 | * obtain a copy of the License at: 16 | * 17 | * http://www.apache.org/licenses/LICENSE-2.0 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | * implied. See the License for the specific language governing 23 | * permissions and limitations under the license. 24 | * 25 | */ 26 | -------------------------------------------------------------------------------- /license_templates/python: -------------------------------------------------------------------------------- 1 | #### #### 2 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 3 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 4 | # by Robert Blake . 5 | # 6 | # LLNL-CODE-720003. 7 | # All rights reserved. 8 | # 9 | # This file is part of MELODEE. For details, see 10 | # http://github.com/llnl/melodee. 11 | # 12 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 13 | # may not use this file except in compliance with the License. You may 14 | # obtain a copy of the License at: 15 | # 16 | # http://www.apache.org/licenses/LICENSE-2.0 17 | # 18 | # Unless required by applicable law or agreed to in writing, software 19 | # distributed under the License is distributed on an "AS IS" BASIS, 20 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 21 | # implied. See the License for the specific language governing 22 | # permissions and limitations under the license. 23 | #### #### 24 | -------------------------------------------------------------------------------- /melodee/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/melodee/31694cb438d992e3c56873c43b16237161552eb0/melodee/__init__.py -------------------------------------------------------------------------------- /melodee/carpGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import sys 27 | import re 28 | import sympy 29 | from sympy.core import S 30 | 31 | 32 | from melodee.parser import MelodeeParser,Differentiator 33 | from melodee import utility 34 | from melodee.utility import order 35 | 36 | from melodee.cardioidGenerator import MyCCodeSympyPrinter, repeat, CPrintVisitor 37 | 38 | def printParamConst(out,thesevars): 39 | out.inc() 40 | for var in order(thesevars): 41 | out("GlobalData_t %s = p->%s;",var,var) 42 | out.dec() 43 | 44 | def stateName(var,statevars): 45 | if var in statevars: 46 | return "sv->%s" % var 47 | else: 48 | return str(var) 49 | 50 | class LookupPrintVisitor(CPrintVisitor): 51 | def __init__(self,out, ssa, declared, interpTargets, decltype="double"): 52 | self.interpTargets = interpTargets 53 | self.fitFromTarget = {} 54 | for (fit,targets) in interpTargets.items(): 55 | for target in targets: 56 | self.fitFromTarget[target] = fit 57 | super(LookupPrintVisitor,self).__init__(out,ssa,declared,decltype) 58 | 59 | def printLookup(self,lhs): 60 | if lhs in self.interpTargets: 61 | self.out("LUT_data_t %s_row[NROWS_%s];",lhs,lhs) 62 | self.out("LUT_interpRow(&IF->tables[_%s_TAB], %s, __i, %s_row);",lhs,lhs,lhs) 63 | 64 | def equationPrint(self,lhs,rhs): 65 | if lhs in self.fitFromTarget: 66 | rhsText = "%s_row[%s_idx]" % (self.fitFromTarget[lhs],lhs) 67 | self.equationPrintWithRhs(lhs,rhsText) 68 | else: 69 | super(LookupPrintVisitor,self).equationPrint(lhs,rhs) 70 | if lhs in self.interpTargets: 71 | self.printLookup(lhs) 72 | def printChoice(self, lhs): 73 | if lhs in self.fitFromTarget: 74 | self.equationPrint(lhs,None) 75 | 76 | def generateCarp(model, targetName): 77 | si = model.si 78 | unitFromExternalName = {"Vm" : si.get("mV"), 79 | "Lambda" : si.get("1"), 80 | "delLambda" : si.get("1")/si.get("ms"), 81 | "Tension" : si.get("kPa"), 82 | "K_e" : si.get("mM"), 83 | "Na_e" : si.get("mM"), 84 | "Ca_e" : si.get("uM"), 85 | "Iion" : si.get("uA")/si.get("uF"), 86 | "tension_component" : si.get("1"), 87 | "K_i" : si.get("mM"), 88 | "Na_i" : si.get("mM"), 89 | "Ca_i" : si.get("uM"), 90 | "Ca_b" : si.get("uM"), 91 | "CaRel" : si.get("uM"), 92 | "CaUp" : si.get("uM"), 93 | "ATP" : si.get("mM"), 94 | "ADP" : si.get("uM"), 95 | } 96 | publicNames = set(["Vm", 97 | "Lambda", 98 | "delLambda", 99 | "Tension", 100 | "K_e", 101 | "Na_e", 102 | "Ca_e", 103 | "Iion", 104 | "tension_component", 105 | ]) 106 | privateNames = set(["K_i", 107 | "Na_i", 108 | "Ca_i", 109 | "Ca_b", 110 | "CaRel", 111 | "CaUp", 112 | "ATP", 113 | "ADP", 114 | ]) 115 | 116 | template = {} 117 | template["target"] = targetName 118 | template["uppercaseModel"] = targetName.upper() 119 | template["timeFactor"] = "1" #FIXME 120 | 121 | 122 | reqvars=None # anything with a req 123 | modvars=None # anything with a mod 124 | statevars=None # anything with a s-> 125 | paramvars=None # anything with a p-> 126 | flagvars=None # anything that can be used as a flag 127 | nodevars=None 128 | diffvars=None 129 | simvars=None 130 | interpvars=None # interp vars. 131 | interpTargets=None 132 | fevars = None 133 | tracevars = None 134 | 135 | ## Vars for printing 136 | externalNameFromVar = {} 137 | for var in model.varsWithAttribute("external"): 138 | externalName = model.info("external",var) 139 | if not externalName: 140 | externalName = str(var) 141 | externalNameFromVar[var] = externalName 142 | 143 | diffvars = model.diffvars() 144 | exvars = set(externalNameFromVar.keys()) 145 | reqvars = exvars & set(model.inputs()) 146 | modvars = exvars & set(model.ssa.keys()) 147 | 148 | paramvars = model.varsWithAttribute("param") 149 | flagvars = model.varsWithAttribute("flag") 150 | nodevars = model.varsWithAttribute("nodal") 151 | tracevars = model.varsWithAttribute("trace") 152 | 153 | statevars = (diffvars | nodevars) - exvars 154 | 155 | fevars = set(diffvars) 156 | 157 | simvars = set() 158 | dt = model.addSymbol("_dt") 159 | if model.time: 160 | simvars.add(model.time) 161 | simvars.add(dt) 162 | 163 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 164 | V = model.input("V") 165 | V_init = model.output("V_init") 166 | Iion = model.output("Iion") 167 | 168 | modvars.add(Iion); externalNameFromVar.setdefault(Iion,"Iion") 169 | reqvars.add(V); externalNameFromVar.setdefault(V,"Vm") 170 | 171 | rushvars = model.varsWithAttribute("gate") & diffvars 172 | differ = Differentiator(model, diffvars | paramvars | reqvars | modvars) 173 | rushJacobians = {} 174 | for rush in order(rushvars): 175 | (rushJacobians[rush],dontcare) = differ.diff(diffvarUpdate[rush],rush) 176 | differ.augmentInstructions() 177 | rushTargets = {} 178 | for rush in order(rushvars): 179 | F = model.ssa[diffvarUpdate[rush]].sympy 180 | L = model.ssa[rushJacobians[rush]].sympy 181 | M = (F-L*rush).simplify() 182 | 183 | RLA = model.addInstruction("_%s_RLA" % rush, sympy.exp(dt*L)) 184 | RLB = model.addInstruction("_%s_RLB" % rush, M/L*(RLA-1)) 185 | rushTargets[rush] = model.addInstruction("_%s_update" % rush,rush*RLA+RLB) 186 | 187 | fevars -= rushvars 188 | 189 | expensiveVars = model.extractExpensiveFunctions() 190 | model.makeNamesUnique() 191 | 192 | computeTargets = set() 193 | computeTargets.add(Iion) 194 | computeTargets |= set([diffvarUpdate[var] for var in diffvars-rushvars]) 195 | for gate in rushvars: 196 | computeTargets.add(rushTargets[gate]) 197 | 198 | approxvars = set([dt]) 199 | computeAllDepend = model.allDependencies(approxvars|statevars|reqvars, computeTargets) 200 | 201 | constants = model.allExcluding(approxvars, statevars|reqvars) & computeAllDepend 202 | 203 | interpvars = model.varsWithAttribute("interp") 204 | interpTargets = {} 205 | allinterps = set() 206 | for fit in interpvars: 207 | good = approxvars | set([fit]) 208 | dependsOnlyOnFitvar = model.allExcluding(good, (statevars|reqvars)-good) 209 | interpCandidates = (dependsOnlyOnFitvar & computeAllDepend) - constants 210 | 211 | expensiveInterps = expensiveVars & interpCandidates 212 | inexpensiveInterps = model.allExcluding(good, ((statevars|reqvars)-good)|expensiveInterps) 213 | interpCandidates -= inexpensiveInterps 214 | 215 | externallyUsedInterps = ( 216 | model.allDependencies(approxvars|statevars|reqvars|interpCandidates, computeTargets) 217 | & 218 | interpCandidates 219 | ) 220 | interpTargets[fit] = externallyUsedInterps 221 | allinterps |= externallyUsedInterps 222 | 223 | computeAllDepend = model.allDependencies( 224 | approxvars|statevars|reqvars|allinterps, 225 | computeTargets) 226 | constants = model.allExcluding(approxvars,statevars|reqvars) & computeAllDepend 227 | 228 | out = utility.Indenter(open(targetName+".h","w"), " ") 229 | cprinter=CPrintVisitor(out, model.ssa, set()) 230 | out(''' 231 | //// HEADER GUARD /////////////////////////// 232 | // If automatically generated, keep above 233 | // comment as first line in file. 234 | #ifndef __%(uppercaseModel)s_H__ 235 | #define __%(uppercaseModel)s_H__ 236 | //// HEADER GUARD /////////////////////////// 237 | // DO NOT EDIT THIS SOURCE CODE FILE 238 | // ANY CHANGES TO THIS FILE WILL BE OVERWRITTEN!!!! 239 | // If you need to make a change, do what you have to do and send Rob 240 | // an email with what you had to change and why. He'll fix the translator 241 | // so your fix will be recorded the next time the translator runs. 242 | 243 | ''', template) 244 | out('#define %(target)s_REQDAT 0|%(req)s', 245 | target=targetName, 246 | req="|".join(["%s_DATA_FLAG"% externalNameFromVar[var] for var in reqvars]) 247 | ) 248 | out('#define %(target)s_MODDAT 0|%(mod)s', 249 | target=targetName, 250 | mod="|".join(["%s_DATA_FLAG"% externalNameFromVar[var] for var in modvars]) 251 | ) 252 | out(''' 253 | 254 | typedef struct %(target)s_params { 255 | ''', template) 256 | out.inc() 257 | for var in order(paramvars): 258 | out("GlobalData_t %s;", var) 259 | out.dec() 260 | out(''' 261 | char* flags; 262 | } %(target)s_Params;''', template) 263 | 264 | out('static char* %(target)s_flags = "%(flags)s";', 265 | target=targetName, 266 | flags="|".join([str(var) for var in flagvars]) 267 | ) 268 | out(''' 269 | 270 | typedef struct %(target)s_state {''', template) 271 | out.inc() 272 | for var in order(statevars): 273 | out("GlobalData_t %s;", var) 274 | out.dec() 275 | out(''' 276 | } %(target)s_state; 277 | 278 | #ifdef __CUDACC__ 279 | extern "C" { 280 | #endif 281 | 282 | void initialize_params_%(target)s(ION_IF *); 283 | void construct_tables_%(target)s(ION_IF *); 284 | void destroy_%(target)s(ION_IF *); 285 | void initialize_sv_%(target)s(ION_IF *, GlobalData_t**); 286 | GLOBAL void compute_%(target)s(int, int, ION_IF *, GlobalData_t**); 287 | 288 | #ifdef __CUDACC__ 289 | }; 290 | #endif 291 | 292 | //// HEADER GUARD /////////////////////////// 293 | #endif 294 | //// HEADER GUARD /////////////////////////// 295 | 296 | ''', template) 297 | 298 | out = utility.Indenter(open(targetName+".c","w"), " ") 299 | out(''' 300 | // DO NOT EDIT THIS SOURCE CODE FILE 301 | // ANY CHANGES TO THIS FILE WILL BE OVERWRITTEN!!!! 302 | // If you need to make a change, do what you have to do and send Rob 303 | // an email with what you had to change and why. He'll fix the translator 304 | // so your fix will be recorded the next time the translator runs. 305 | 306 | #include "ION_IF.h" 307 | #include "NumComp.h" 308 | #include "%(target)s.h" 309 | 310 | 311 | #ifdef __CUDACC__ 312 | #define pow powf 313 | #define log logf 314 | #endif 315 | 316 | void trace_%(target)s(ION_IF* IF, int node, FILE* file, GlobalData_t** impdata); 317 | 318 | void destroy_%(target)s( ION_IF *IF ) 319 | { 320 | destroy_luts( IF ); 321 | SV_free( &IF->sv_tab ); 322 | // rarely need to do anything else 323 | } 324 | 325 | void initialize_params_%(target)s( ION_IF *IF ) 326 | { 327 | cell_geom *region = &IF->cgeom; 328 | %(target)s_Params *p = (%(target)s_Params *)IF->params; 329 | 330 | ''', template) 331 | out.inc() 332 | 333 | good = set() 334 | 335 | out("//Compute the paramaters") 336 | cprinter=CPrintVisitor(out, model.ssa, set()) 337 | model.printTarget(good, paramvars, cprinter) 338 | for var in order(paramvars): 339 | out("p->%s = %s;", var, var) 340 | 341 | out.dec() 342 | out(''' 343 | //p->Bufc = 0.2; 344 | //p->cell_type = EPI; 345 | //if (0) ; 346 | //else if (flag_set(p->flags, "EPI")) p->cell_type = EPI; 347 | //else if (flag_set(p->flags, "MCELL")) p->cell_type = MCELL; 348 | //else if (flag_set(p->flags, "ENDO")) p->cell_type = ENDO; 349 | 350 | IF->type->trace = trace_%(target)s; 351 | 352 | } 353 | 354 | 355 | // Define the parameters for the lookup tables 356 | enum Tables { 357 | ''', template) 358 | out.inc() 359 | for var in order(interpvars): 360 | out("_%s_TAB,",var) 361 | out.dec() 362 | out(''' 363 | 364 | N_TABS 365 | }; 366 | 367 | // Define the indices into the lookup tables. 368 | ''', template) 369 | for var in order(interpvars): 370 | out("enum %s_TableIndex {" % var) 371 | out.inc() 372 | for target in order(interpTargets[var]): 373 | out("%s_idx,", target) 374 | out("NROWS_%s", var) 375 | out.dec() 376 | out("};") 377 | out(''' 378 | 379 | void construct_tables_%(target)s( ION_IF *IF ) 380 | { 381 | GlobalData_t _dt = IF->dt*%(timeFactor)s; 382 | cell_geom *region = &IF->cgeom; 383 | %(target)s_Params *p = (%(target)s_Params *)IF->params; 384 | 385 | IF->numLUT = N_TABS; 386 | IF->tables = (LUT *)IMP_malloc( N_TABS, sizeof(LUT) );''', template) 387 | printParamConst(out,paramvars-nodevars) 388 | good = set() 389 | good |= paramvars-nodevars 390 | good.add(dt) 391 | out(''' 392 | 393 | ''', template) 394 | for var in order(interpvars): 395 | (lb,ub,inc) = model.info("interp",var).split(",") 396 | out(''' 397 | // Create the %(var)s lookup table 398 | LUT* %(var)s_tab = &IF->tables[_%(var)s_TAB]; 399 | { 400 | double epsilon=fabs(%(lb)s)*1e-7; 401 | LUT_alloc(%(var)s_tab, NROWS_%(var)s, %(lb)s+epsilon, %(ub)s+epsilon, %(inc)s, "%(target)s %(var)s"); 402 | } 403 | for (int __i=%(var)s_tab->mn_ind; __i<=%(var)s_tab->mx_ind; __i++) { 404 | double %(var)s = %(var)s_tab->res*__i; 405 | LUT_data_t* %(var)s_row = %(var)s_tab->tab[__i]; 406 | ''', 407 | target=targetName, 408 | var=var, 409 | lb=lb, 410 | ub=ub, 411 | inc=inc, 412 | ) 413 | out.inc(2) 414 | cprinter=CPrintVisitor(out, model.ssa, set()) 415 | model.printTarget(good | set([var]), interpTargets[var], cprinter) 416 | for target in order(interpTargets[var]): 417 | out('%(var)s_row[%(target)s_idx] = %(target)s;', 418 | var=var, 419 | target=target) 420 | out.dec() 421 | out('}') 422 | out('check_LUT(%(var)s_tab);', var=var) 423 | out.dec() 424 | 425 | out(''' 426 | } 427 | 428 | 429 | 430 | void initialize_sv_%(target)s( ION_IF *IF, GlobalData_t **impdata ) 431 | { 432 | GlobalData_t _dt = IF->dt*%(timeFactor)s; 433 | cell_geom *region = &IF->cgeom; 434 | %(target)s_Params *p = (%(target)s_Params *)IF->params; 435 | 436 | SV_alloc( &IF->sv_tab, IF->numNode, sizeof(%(target)s_state) ); 437 | %(target)s_state *sv_base = (%(target)s_state *)IF->sv_tab.y; 438 | GlobalData_t t = 0;''', template) 439 | printParamConst(out,paramvars-nodevars) 440 | good = set() 441 | good |= paramvars-nodevars 442 | good.add(dt) 443 | out(''' 444 | 445 | //Prepare all the public arrays.''', template) 446 | out.inc() 447 | for var in order(reqvars|modvars): 448 | out("GlobalData_t* %s_ext = impdata[%s];",var,externalNameFromVar[var]) 449 | out.dec() 450 | out(''' 451 | //Prepare all the private functions. 452 | 453 | //set the initial values 454 | for(int __i=0; __isv_tab.numSeg; __i++ ){ 455 | %(target)s_state *sv = sv_base+__i;''', template) 456 | out.inc(2) 457 | 458 | out("//Get the definition of nodal vars") 459 | for var in order(paramvars & nodevars): 460 | out("GlobalData_t %s = p->%s;", var, var) 461 | good |= paramvars & nodevars 462 | 463 | out("//Read in the input vars") 464 | for var in order(reqvars-set([V])): 465 | out("GlobalData_t %s = %s_ext[__i];",var, var) 466 | good |= reqvars-set([V]) 467 | 468 | out("//Define voltage") 469 | valid = paramvars|(reqvars-set([V])) 470 | cprinter=CPrintVisitor(out, model.ssa, set()) 471 | model.printTarget(valid,set([V_init]),cprinter) 472 | out("double %s = %s;",V,V_init) 473 | good |= set([V]) 474 | 475 | out("//Define statevars and modvars") 476 | valid |= set([V]) 477 | model.printTarget(valid,(statevars|modvars)-valid,cprinter) 478 | 479 | out("//Save all the state variables") 480 | for var in order(statevars): 481 | out("sv->%s = %s;",var,var) 482 | out("//Save all external vars") 483 | for var in order(modvars): 484 | out("%s_ext[__i] = %s;",var,var) 485 | out("//Save voltage") 486 | out("%s_ext[__i] = %s;",V,V); 487 | 488 | out.dec(2) 489 | out(''' 490 | //Change the units of external variables as appropriate. 491 | //sv->Ca_i *= 1e-3; 492 | } 493 | 494 | } 495 | 496 | /** compute the current 497 | * 498 | * param start index of first node 499 | * param end index of last node 500 | * param IF IMP 501 | * param plgdata external data needed by IMP 502 | */ 503 | GLOBAL void compute_%(target)s(int start, int end, ION_IF *IF, GlobalData_t **impdata ) 504 | { 505 | GlobalData_t _dt = IF->dt*%(timeFactor)s; 506 | cell_geom *region = &IF->cgeom; 507 | %(target)s_Params *p = (%(target)s_Params *)IF->params; 508 | %(target)s_state *sv_base = (%(target)s_state *)IF->sv_tab.y; 509 | 510 | GlobalData_t t = IF->tstp.cnt*_dt; 511 | 512 | ''', template) 513 | printParamConst(out,paramvars-nodevars) 514 | good = set() 515 | good |= paramvars-nodevars 516 | good.add(dt) 517 | out(''' 518 | 519 | //Prepare all the public arrays.''', template) 520 | out.inc() 521 | for var in order(reqvars|modvars): 522 | out("GlobalData_t* %s_ext = impdata[%s];",var,externalNameFromVar[var]) 523 | out.dec() 524 | out(''' 525 | 526 | #ifdef __CUDACC__ 527 | int __i = blockDim.x * blockIdx.x + threadIdx.x; 528 | if ( __i>=end ) { return; } 529 | { 530 | #else 531 | #pragma omp parallel for schedule(static) 532 | for (int __i=start; __i%s;", var, var) 547 | good |= statevars 548 | 549 | out('//Change the units of external variables as appropriate.') 550 | out('//sv->Ca_i *= 1e-3;') 551 | 552 | cprinter=LookupPrintVisitor(out, model.ssa, set(),interpTargets) 553 | out('//Compute lookup tables for things that have already been defined.') 554 | for var in order(good & set(interpTargets.keys())): 555 | cprinter.printLookup(var) 556 | 557 | out('//Compute external modvars') 558 | justDefined = model.allDependencies(good|allinterps,modvars-diffvars)-good 559 | model.printSet(justDefined,cprinter) 560 | good |= justDefined 561 | 562 | out('//Complete Forward Euler Update', template) 563 | justDefined = model.allDependencies(good|allinterps,set([diffvarUpdate[var] for var in fevars]))-good 564 | model.printSet(justDefined,cprinter) 565 | good |= justDefined 566 | 567 | out('//Complete Rush Larsen Update', template) 568 | justDefined = model.allDependencies(good|allinterps,set(rushTargets.values()))-good 569 | model.printSet(justDefined,cprinter) 570 | good |= justDefined 571 | 572 | out('//Finish the update', template) 573 | for var in order(fevars): 574 | out("%s += %s*_dt;",stateName(var,statevars),diffvarUpdate[var]) 575 | for var in order(rushvars): 576 | out("%s = %s;",stateName(var,statevars),rushTargets[var]) 577 | out('//Change the units of external variables as appropriate.', template) 578 | out('//sv->Ca_i *= 1e3;',template) 579 | 580 | for var in order(modvars): 581 | out("%s_ext[__i] = %s;", var,var) 582 | out.dec(2) 583 | out(''' 584 | } 585 | 586 | 587 | } 588 | 589 | 590 | void trace_%(target)s(ION_IF* IF, int node, FILE* file, GlobalData_t** impdata) 591 | { 592 | static bool first = true; 593 | if (first) { 594 | first = false; 595 | FILE_SPEC theader = f_open("%(target)s_trace_header.txt","wt"); 596 | f_printf( theader, 597 | ''', template) 598 | out.inc(2) 599 | for var in order(tracevars): 600 | out('"%s\\n"',var) 601 | out.dec(2) 602 | out(''' 603 | ); 604 | 605 | f_close(theader); 606 | } 607 | 608 | CUDA_TRACE( %(target)s, IF, node, file ) 609 | #ifdef HAVE_CUDA_LIMPET 610 | #define fprintf(A,F, ...) printf( F, __VA_ARGS__ ) 611 | #endif 612 | 613 | GlobalData_t _dt = IF->dt*%(timeFactor)s; 614 | cell_geom *region = &IF->cgeom; 615 | %(target)s_Params *p = (%(target)s_Params *)IF->params; 616 | 617 | %(target)s_state *sv_base = (%(target)s_state *)IF->sv_tab.y; 618 | %(target)s_state *sv = sv_base+node; 619 | int __i = node; 620 | 621 | GlobalData_t t = IF->tstp.cnt*_dt; 622 | 623 | ''', template) 624 | out.inc() 625 | printParamConst(out,paramvars-nodevars) 626 | good = set() 627 | good |= paramvars-nodevars 628 | good.add(dt) 629 | out('//Prepare all the public arrays.', template) 630 | 631 | for var in order(reqvars|modvars): 632 | out("GlobalData_t* %s_ext = impdata[%s];",var,externalNameFromVar[var]) 633 | 634 | out("//Read in the input vars") 635 | for var in order(reqvars): 636 | out("GlobalData_t %s = %s_ext[__i];",var, var) 637 | good |= reqvars 638 | 639 | out("//Get the definition of statevars") 640 | for var in order(statevars): 641 | out("GlobalData_t %s = sv->%s;", var, var) 642 | good |= statevars 643 | 644 | out('//Change the units of external variables as appropriate.') 645 | out('//sv->Ca_i *= 1e-3;') 646 | 647 | cprinter=CPrintVisitor(out, model.ssa, set()) 648 | model.printTarget(good,tracevars-good,cprinter) 649 | 650 | out('//Output the desired variables') 651 | for var in order(tracevars): 652 | out('fprintf(file, "%%4.12f\\t", %s);',var) 653 | 654 | out.dec() 655 | out(''' 656 | //Change the units of external variables as appropriate. 657 | //sv->Ca_i *= 1e3; 658 | 659 | #ifdef HAVE_CUDA_LIMPET 660 | #undef fprintf 661 | #endif 662 | 663 | }''', template) 664 | 665 | generators = { 666 | frozenset(["carp"]) : generateCarp, 667 | } 668 | -------------------------------------------------------------------------------- /melodee/celerisGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import sys 27 | import re 28 | import sympy 29 | import io 30 | from sympy.printing.fortran import FCodePrinter 31 | from sympy.core import S 32 | 33 | 34 | from melodee.parser import MelodeeParser,Differentiator 35 | from melodee import utility 36 | from melodee.utility import order 37 | 38 | def repeat(thing, repetitions): 39 | return (thing,) * repetitions 40 | 41 | class MyFCodeSympyPrinter(FCodePrinter): 42 | def __init__(self,*args,**kwargs): 43 | FCodePrinter.__init__(self,*args,**kwargs) 44 | def _print_Pow(self, expr): 45 | PREC = sympy.printing.precedence.precedence(expr) 46 | if expr.exp == 0: 47 | return 1 48 | elif expr.exp == 0.5: 49 | return 'sqrt(%s)' % self._print(expr.base) 50 | elif expr.exp.is_constant and int(expr.exp) == expr.exp: 51 | result = self.parenthesize(expr.base,PREC) 52 | if expr.exp > 0: 53 | return "*".join(repeat(result, int(expr.exp))) 54 | else: 55 | return "1.0/"+"/".join(repeat(result, -int(expr.exp))) 56 | return '%s**%s' % (self._print(expr.base), 57 | self._print(expr.exp)) 58 | def _print_Relational(self,expr): 59 | if expr.rel_op == "==" or expr.rel_op == "!=": 60 | PREC = sympy.printing.precedence.precedence(expr) 61 | return "%s %s %s" % (self.parenthesize(expr.lhs, PREC), 62 | expr.rel_op, 63 | self.parenthesize(expr.rhs, PREC)) 64 | else: 65 | return super(MyFCodeSympyPrinter, self)._print_Relational(expr) 66 | def fortranifyCode(self, code): 67 | codeLines = code.splitlines() 68 | paddedLines = self._pad_leading_columns(codeLines) 69 | wrappedLines = self._wrap_fortran(paddedLines) 70 | return "\n"+"\n".join(wrappedLines) 71 | 72 | def pretty(symbol): 73 | return str(symbol) 74 | 75 | class FPrintVisitor: 76 | def __init__(self, ssa, decltype="double"): 77 | self.newBuffer() 78 | self.ssa = ssa 79 | self.decltype = decltype 80 | self.cprinter = MyFCodeSympyPrinter() 81 | 82 | def newBuffer(self): 83 | self.ioBuf = io.BytesIO() 84 | self.out = utility.Indenter(self.ioBuf) 85 | 86 | def getBuffer(self): 87 | return self.ioBuf.getvalue() 88 | 89 | def ifPrint(self,printer,ifSymbol,thenList,elseList,choiceList): 90 | self.out("if (%s)",pretty(ifSymbol)) 91 | self.out("then") 92 | self.out.inc() 93 | printer(thenList) 94 | for choiceVar in choiceList: 95 | choice = self.ssa[choiceVar] 96 | lhs = pretty(choiceVar) 97 | rhs = pretty(choice.thenVar) 98 | if lhs != rhs: 99 | self.out("%s = %s;",lhs,rhs) 100 | self.out.dec() 101 | self.out("else") 102 | self.out.inc() 103 | printer(elseList) 104 | for choiceVar in choiceList: 105 | choice = self.ssa[choiceVar] 106 | lhs = pretty(choiceVar) 107 | rhs = pretty(choice.elseVar) 108 | if lhs != rhs: 109 | self.out("%s = %s;",lhs,rhs) 110 | self.out.dec() 111 | self.out("end if") 112 | def equationPrint(self,lhs,rhs): 113 | rhsText = self.cprinter._print(rhs.sympy) 114 | self.equationPrintWithRhs(lhs,rhsText) 115 | def equationPrintWithRhs(self,lhs,rhsText): 116 | self.out("%s = %s;",pretty(lhs),rhsText) 117 | def finalize(self): 118 | retval = self.fortranifyCode(self.getBuffer()) 119 | self.newBuffer() 120 | return retval 121 | def fortranifyCode(self, code): 122 | return self.cprinter.fortranifyCode(code) 123 | 124 | def generateCeleris(model, targetName): 125 | template = {} 126 | template["target"] = targetName 127 | 128 | diffvars = model.diffvars() 129 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 130 | 131 | llambda = model.input("lambda") 132 | actTime = model.input("actTime") 133 | if "stretchVel" not in model._inputs: 134 | stretchVel = model.addSymbol("_stretchVel") 135 | else: 136 | stretchVel = model.input("stretchVel") 137 | tension = model.output("tension") 138 | 139 | inputs = set([llambda,actTime,stretchVel]) 140 | ############ 141 | 142 | partialFromDiff = {} 143 | diffPartialFromDiff = {} 144 | 145 | differ = Differentiator(model, set([actTime,stretchVel])) 146 | partialvars = set() 147 | for diffvar in diffvars: 148 | partial = model.addSymbol("_partial_"+str(diffvar)) 149 | differ.cacheResult(diffvar, stretchVel, partial, None) 150 | partialFromDiff[diffvar] = partial 151 | partialLambda = model.addSymbol("_partial_lambda") 152 | differ.cacheResult(llambda, stretchVel, partialLambda, None) 153 | 154 | for diffvar in diffvars: 155 | (diffvarUpdate[partialFromDiff[diffvar]],dontcare) = differ.diff(diffvarUpdate[diffvar],stretchVel) 156 | (dtension_dstretchVel,dontcare) = differ.diff(tension, stretchVel) 157 | differ.augmentInstructions() 158 | ############### 159 | 160 | partialvars = set(partialFromDiff.values()+[partialLambda]) 161 | good=inputs|diffvars|partialvars 162 | 163 | indexFromVar = {} 164 | numRhsVars=0 165 | for var in order(diffvars): 166 | numRhsVars += 1 167 | indexFromVar[var] = numRhsVars 168 | for var in order(good-diffvars): 169 | numRhsVars += 1 170 | indexFromVar[var] = numRhsVars 171 | 172 | 173 | diffTargets = set() 174 | diffTargets |= set(diffvarUpdate.values()) 175 | 176 | tensionTargets = set() 177 | tensionTargets |= set([tension]) 178 | tensionTargets |= set([dtension_dstretchVel]) 179 | 180 | fprinter = FPrintVisitor(model.ssa) 181 | out = utility.Indenter(open(targetName+".f","w")) 182 | out(''' 183 | SUBROUTINE %(target)sRHS (M_NEQ, M_T, M_SV, M_DSV) 184 | ! Declare inputs and outputs 185 | REAL (KRSIM) :: M_T, M_SV(*), M_DSV(*) 186 | 187 | ''', template) 188 | 189 | out(''' 190 | ! Declare the local variables 191 | ''', template) 192 | 193 | good=inputs|diffvars|partialvars 194 | diffDepend = model.allDependencies(good,diffTargets)|good 195 | varnames = set([pretty(var) for var in diffDepend]) 196 | code = "" 197 | for name in order(varnames): 198 | code += "REAL (KRSIM) :: %s\n" % name 199 | out(fprinter.fortranifyCode(code)) 200 | 201 | out(''' 202 | ! Set up the initial conditions from SV 203 | ''', template) 204 | code = "" 205 | for var in order(good): 206 | code += "%s = M_SV[%d];\n" % (pretty(var), indexFromVar[var]) 207 | out(fprinter.fortranifyCode(code)) 208 | out(''' 209 | ! Compute the derivatives 210 | ''', template) 211 | 212 | model.printTarget(diffvars|partialvars|inputs, diffTargets, fprinter) 213 | out(fprinter.finalize()) 214 | out(''' 215 | ! Store the derivatives 216 | ''', template) 217 | code = "" 218 | for diffvar in order(diffvars): 219 | code += "M_DSV[%d] = %s;\n" %(indexFromVar[diffvar], pretty(diffvarUpdate[diffvar])) 220 | partial = partialFromDiff[diffvar] 221 | code += "M_DSV[%d] = %s;\n" %(indexFromVar[partial], pretty(diffvarUpdate[partial])) 222 | code += "M_DSV[%d] = 1;\n" % indexFromVar[actTime] 223 | code += "M_DSV[%d] = %s;\n" % (indexFromVar[llambda], pretty(stretchVel)) 224 | code += "M_DSV[%d] = 1;\n" % indexFromVar[partialLambda] 225 | code += "M_DSV[%d] = 0;\n" % indexFromVar[stretchVel] 226 | out(fprinter.fortranifyCode(code)) 227 | 228 | template["numRhsVars"] = numRhsVars 229 | template["numDiffVars"] = len(diffvars) 230 | out(''' 231 | 232 | RETURN 233 | END SUBROUTINE %(target)sRHS 234 | 235 | 236 | SUBROUTINE %(target)s (SV_0, PREV_LAMBDA, NEXT_LAMBDA, DT, 237 | @ PREV_ACTTIME, SV_1, TENSION, DTENSION) 238 | 239 | REAL (KRSIM), INTENT (IN) :: SV_0(%(numDiffVars)d), THIS_LAMBDA 240 | REAL (KRSIM), INTENT (OUT) :: SV_1(%(numDiffVars)d), TENSION, DTENSION 241 | REAL (KRSIM), INTENT (IN) :: PREV_LAMBDA, NEXT_LAMBDA, DT, 242 | @ PREV_ACTTIME 243 | REAL (KRSIM), INTENT (OUT) :: TENSION, DTENSION 244 | 245 | ! Declare the local variables 246 | REAL (KRSIM) :: ODEPACK_VARS(%(numRhsVars)d) 247 | ''', template) 248 | 249 | varnames = set([pretty(var) for var in model.allDependencies(good,tensionTargets)|good]) 250 | code = "" 251 | for name in order(varnames): 252 | code += "REAL (KRSIM) :: %s\n" % name 253 | out(fprinter.fortranifyCode(code)) 254 | out(''' 255 | ! Setup the local variables correctly 256 | ''', template) 257 | code = "" 258 | for diffvar in order(diffvars): 259 | code += "ODEPACK_VARS[%d] = SV_0[%d];\n" %(indexFromVar[diffvar],indexFromVar[diffvar]) 260 | partial = partialFromDiff[diffvar] 261 | code += "ODEPACK_VARS[%d] = 0;\n" %(indexFromVar[partial]) 262 | code += "ODEPACK_VARS[%d] = PREV_ACTIME;\n" % indexFromVar[actTime] 263 | code += "ODEPACK_VARS[%d] = PREV_LAMBDA;\n" % indexFromVar[llambda] 264 | code += "ODEPACK_VARS[%d] = 0;\n" % indexFromVar[partialLambda] 265 | code += "ODEPACK_VARS[%d] = (NEXT_LAMBDA-PREV_LAMBDA)/DT;\n" % indexFromVar[stretchVel] 266 | out(fprinter.fortranifyCode(code)) 267 | out(''' 268 | 269 | ! Integrate the equations 270 | ''', template) 271 | out(''' 272 | 273 | ! Evaluate tension 274 | ''', template) 275 | code = "" 276 | for diffvar in order(diffvars): 277 | code += "%s = ODEPACK_VARS[%d];\n" %(pretty(diffvar) , indexFromVar[diffvar]) 278 | partial = partialFromDiff[diffvar] 279 | code += "%s = ODEPACK_VARS[%d];\n" %(pretty(partial), indexFromVar[partial]) 280 | code += "%s = PREV_ACTTIME+DT;\n" % pretty(actTime) 281 | code += "%s = NEXT_LAMBDA;\n" % pretty(llambda) 282 | code += "%s = DT;\n" % pretty(partialLambda) 283 | code += "%s = (NEXT_LAMBDA-PREV_LAMBDA)/DT;\n" % pretty(stretchVel) 284 | out(fprinter.fortranifyCode(code)) 285 | 286 | 287 | model.printTarget(diffvars|partialvars|inputs, tensionTargets, fprinter) 288 | out(fprinter.finalize()) 289 | out(''' 290 | ! Set up the final outputs 291 | ''', template) 292 | code = "" 293 | for diffvar in order(diffvars): 294 | code += "SV_1[%d] = %s;\n" %(indexFromVar[diffvar], pretty(diffvar)) 295 | code += "TENSION = %s;\n" % pretty(tension) 296 | code += "DTENSION = %s/DT;\n" % pretty(dtension_dstretchVel) 297 | out(fprinter.fortranifyCode(code)) 298 | out(''' 299 | 300 | RETURN 301 | END SUBROUTINE %(target)s 302 | 303 | ''', template) 304 | 305 | generators = { 306 | frozenset(["celeris"]) : generateCeleris, 307 | } 308 | -------------------------------------------------------------------------------- /melodee/chasteGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import sys 27 | import re 28 | import sympy 29 | from sympy.printing.c import C99CodePrinter 30 | from sympy.core import S 31 | 32 | 33 | from melodee.parser import MelodeeParser,Differentiator 34 | from melodee import utility 35 | from melodee.utility import order 36 | 37 | from melodee.cardioidGenerator import repeat,MyCCodeSympyPrinter,CPrintVisitor 38 | 39 | def pretty(symbol): 40 | return str(symbol) 41 | 42 | def generateChaste(model, targetName): 43 | template = {} 44 | template["target"] = targetName 45 | 46 | diffvars = model.diffvars() 47 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 48 | params = model.varsWithAttribute("param") 49 | gates = model.varsWithAttribute("gate") & diffvars 50 | tracevars = model.varsWithAttribute("trace") 51 | markovs = model.varsWithAttribute("markov") & diffvars 52 | 53 | lbLookup = {} 54 | ubLookup = {} 55 | for var in gates|markovs: 56 | lbLookup[var] = 0 57 | ubLookup[var] = 1 58 | 59 | for var in model.varsWithAttribute("lb"): 60 | lbLookup[var] = model.info("lb",var) 61 | ubLookup[var] = model.info("ub",var) 62 | 63 | V = model.input("V") 64 | V_init = model.output("V_init") 65 | Iion = model.output("Iion") 66 | hasCai = False 67 | if "Cai" in model.outputs(): 68 | Cai = model.output("Cai") 69 | hasCai = True 70 | 71 | out = utility.Indenter(open(targetName+".hpp","w")) 72 | out(''' 73 | #ifndef %(target)s_HPP_ 74 | #define %(target)s_HPP_ 75 | 76 | #include "ChasteSerialization.hpp" 77 | #include 78 | 79 | #include "AbstractCardiacCell.hpp" 80 | #include "AbstractStimulusFunction.hpp" 81 | #include "AbstractDynamicallyLoadableEntity.hpp" 82 | #include 83 | 84 | /** 85 | * This class represents the Luo-Rudy 1991 system of equations, 86 | * with support for being compiled into a .so and loaded at run-time. 87 | */ 88 | class %(target)s : public AbstractCardiacCell, public AbstractDynamicallyLoadableEntity 89 | { 90 | private: 91 | /** Needed for serialization. */ 92 | friend class boost::serialization::access; 93 | /** 94 | * Archive the member variables. 95 | * 96 | * @param archive 97 | * @param version 98 | */ 99 | template 100 | void serialize(Archive & archive, const unsigned int version) 101 | { 102 | archive & boost::serialization::base_object(*this); 103 | archive & boost::serialization::base_object(*this); 104 | } 105 | 106 | /** 107 | * Range-checking on the current values of the state variables. Make sure 108 | * all gating variables have are within zero and one, and all concentrations 109 | * are positive 110 | */ 111 | void VerifyStateVariables(); 112 | 113 | public: 114 | /** 115 | * Constructor 116 | * 117 | * @param pSolver is a pointer to the ODE solver 118 | * @param pIntracellularStimulus is a pointer to the intracellular stimulus 119 | */ 120 | %(target)s(boost::shared_ptr pSolver, 121 | boost::shared_ptr pIntracellularStimulus); 122 | 123 | /** 124 | * Destructor 125 | */ 126 | ~%(target)s(); 127 | 128 | /** 129 | * Fill in a vector representing the RHS of the Luo-Rudy 1991 system 130 | * of Odes at each time step, y' = [y1' ... yn']. 131 | * Some ODE solver will call this function repeatedly to solve for y = [y1 ... yn]. 132 | * 133 | * @param time the current time, in milliseconds 134 | * @param rY current values of the state variables 135 | * @param rDY to be filled in with derivatives 136 | */ 137 | void EvaluateYDerivatives(double time, const std::vector &rY, std::vector &rDY); 138 | 139 | /** 140 | * Returns the ionic current 141 | * 142 | * @param pStateVariables optional state at which to evaluate the current 143 | * @return the total ionic current 144 | */ 145 | double GetIIonic(const std::vector* pStateVariables=NULL);''',template) 146 | if hasCai: 147 | out(''' 148 | /** 149 | * Get the intracellular calcium concentration 150 | * 151 | * @return the intracellular calcium concentration 152 | */ 153 | double GetIntracellularCalciumConcentration(); 154 | ''') 155 | out(r''' 156 | }; 157 | 158 | #include "SerializationExportWrapper.hpp" 159 | CHASTE_CLASS_EXPORT(%(target)s) 160 | 161 | namespace boost 162 | { 163 | namespace serialization 164 | { 165 | /** 166 | * Allow us to not need a default constructor, by specifying how Boost should 167 | * instantiate a %(target)s instance. 168 | */ 169 | template 170 | inline void save_construct_data( 171 | Archive & ar, const %(target)s * t, const unsigned int file_version) 172 | { 173 | const boost::shared_ptr p_solver = t->GetSolver(); 174 | const boost::shared_ptr p_stimulus = t->GetStimulusFunction(); 175 | ar << p_solver; 176 | ar << p_stimulus; 177 | } 178 | 179 | /** 180 | * Allow us to not need a default constructor, by specifying how Boost should 181 | * instantiate a %(target)s instance (using existing constructor). 182 | * 183 | * NB this constructor allocates memory for the other member variables too. 184 | */ 185 | template 186 | inline void load_construct_data( 187 | Archive & ar, %(target)s * t, const unsigned int file_version) 188 | { 189 | 190 | boost::shared_ptr p_solver; 191 | boost::shared_ptr p_stimulus; 192 | ar >> p_solver; 193 | ar >> p_stimulus; 194 | ::new(t)%(target)s(p_solver, p_stimulus); 195 | } 196 | } 197 | } // namespace ... 198 | 199 | #endif // %(target)s_ 200 | 201 | ''', template) 202 | 203 | out = utility.Indenter(open(targetName+".cpp","w")) 204 | out(r''' 205 | #include "%(target)s.hpp" 206 | #include "OdeSystemInformation.hpp" 207 | #include 208 | //#include 209 | #include "Exception.hpp" 210 | 211 | enum StateVarEnum { 212 | ''',template) 213 | for var in order(diffvars): 214 | out("_enum_%s,",var) 215 | out(r''' 216 | NUMSTATES 217 | }; 218 | 219 | /** 220 | * Constructor 221 | */ 222 | %(target)s::%(target)s( 223 | boost::shared_ptr pSolver, 224 | boost::shared_ptr pIntracellularStimulus) 225 | : AbstractCardiacCell(pSolver, NUMSTATES+1, 0, pIntracellularStimulus) 226 | { 227 | mpSystemInfo = OdeSystemInformation<%(target)s>::Instance(); 228 | 229 | Init(); 230 | } 231 | 232 | /** 233 | * Destructor 234 | */ 235 | %(target)s::~%(target)s(void) 236 | { 237 | } 238 | ''',template) 239 | if hasCai: 240 | out(''' 241 | double %s::GetIntracellularCalciumConcentration() 242 | { 243 | return mStateVariables[_enum_%s+1]; 244 | } 245 | ''', targetName, Cai) 246 | out(r''' 247 | 248 | /** 249 | * Fill in a vector representing the RHS of the %(target)s system 250 | * of Odes at each time step, y' = [y1' ... yn']. 251 | * Some ODE solver will call this function repeatedly to solve for y = [y1 ... yn]. 252 | * 253 | * @param time the current time, in milliseconds 254 | * @param rY current values of the state variables 255 | * @param rDY to be filled in with derivatives 256 | */ 257 | void %(target)s::EvaluateYDerivatives(double time, 258 | const std::vector &_rY, 259 | std::vector &_rDY) 260 | { 261 | ''', template) 262 | out.inc() 263 | 264 | out("double %s = _rY[0];", V) 265 | for var in order(diffvars): 266 | out("double %s = _rY[_enum_%s+1];", var, var) 267 | ii=0 268 | for var in order(params): 269 | out("double %s = GetParameter(%d);", var, ii); 270 | ii+=1 271 | 272 | cprinter = CPrintVisitor(out, model.ssa, params) 273 | good=diffvars|set([V])|params 274 | model.printTarget(good, set(diffvarUpdate.values())|set([Iion]), cprinter) 275 | 276 | out("_rDY[0] = -%s;", Iion) 277 | for var in order(diffvars): 278 | out("_rDY[_enum_%s+1] = %s;", var, diffvarUpdate[var]) 279 | out.dec() 280 | out(''' 281 | } 282 | 283 | 284 | double %(target)s::GetIIonic(const std::vector* pStateVariables) 285 | { 286 | ''', template) 287 | out.inc() 288 | 289 | out("double %s = _rY[0];", V) 290 | for var in order(diffvars): 291 | out("double %s = _rY[_enum_%s+1];", var, var) 292 | ii=0 293 | for var in order(params): 294 | out("double %s = GetParameter(%d);", var, ii); 295 | ii+=1 296 | 297 | cprinter = CPrintVisitor(out, model.ssa, params) 298 | model.printTarget(good, set([Iion]), cprinter) 299 | 300 | out("assert(!std::isnan(%s));",Iion) 301 | out("return %s;",Iion) 302 | 303 | out.dec() 304 | out(''' 305 | } 306 | 307 | void %(target)s::VerifyStateVariables() 308 | { 309 | const std::vector& _rY = rGetStateVariables(); 310 | ''', template) 311 | out.inc() 312 | 313 | for var in order(diffvars): 314 | out("double %s = _rY[_enum_%s+1];", var, var) 315 | if var in lbLookup: 316 | out("if (%s < %s)", var, lbLookup[var]) 317 | out("{") 318 | out.inc() 319 | out('EXCEPTION(DumpState("%s has gone under its lower bound. Check model parameters, for example spatial stepsize"));', var) 320 | out.dec() 321 | out("}") 322 | if var in ubLookup: 323 | out("if (%s > %s)", var, ubLookup[var]) 324 | out("{") 325 | out.inc() 326 | out('EXCEPTION(DumpState("%s has gone over its upper bound. Check model parameters, for example spatial stepsize"));', var) 327 | out.dec() 328 | out("}") 329 | 330 | out.dec() 331 | out(''' 332 | } 333 | 334 | template<> 335 | void OdeSystemInformation<%(target)s>::Initialise(void) 336 | { 337 | ''', template) 338 | out.inc() 339 | 340 | cprinter = CPrintVisitor(out, model.ssa, params) 341 | model.printTarget(set(),diffvars|set([V_init])|params,cprinter) 342 | 343 | out('this->mVariableNames.push_back("%s");',V) 344 | out('this->mVariableUnits.push_back("mV");') # FIXME, make generic 345 | out('this-mInitialConditions.push_back(%s);',V_init) 346 | 347 | for var in order(diffvars): 348 | out('this->mVariableNames.push_back("%s");',var) 349 | out('this->mVariableUnits.push_back("%s");', model.ssa[var].astUnit.rawUnit) 350 | out('this-mInitialConditions.push_back(%s);',var) 351 | 352 | for var in order(params): 353 | out('this->mParameterNames.push_back("%s");',var) 354 | out('this->mParameterUnits.push_back("");') #FIXME, put in a unit if we have one. 355 | out('this->mParameters.push_back(%s);',var) 356 | 357 | out.dec() 358 | out(''' 359 | this->mInitialised = true; 360 | } 361 | 362 | #include "SerializationExportWrapperForCpp.hpp" 363 | CHASTE_CLASS_EXPORT(%(target)s) 364 | 365 | extern "C" { 366 | /** 367 | * C-style constructor with a standard name, so the main program can create instances 368 | * of this cell model when it is loaded from a .so. 369 | * 370 | * @param pSolver ODE solver used to simulate the cell 371 | * @param pIntracellularStimulus intracellular stimulus 372 | */ 373 | AbstractCardiacCellInterface* MakeCardiacCell(boost::shared_ptr pSolver, 374 | boost::shared_ptr pStimulus){ 375 | return new %(target)s(pSolver, pStimulus); 376 | } 377 | } 378 | ''', template) 379 | 380 | generators = { 381 | frozenset(["chaste"]) : generateChaste 382 | } 383 | -------------------------------------------------------------------------------- /melodee/coinGenerator.py: -------------------------------------------------------------------------------- 1 | # 2 | # LLNL-CODE-720003. 3 | # All rights reserved. 4 | # 5 | # This file is part of MELODEE. For details, see 6 | # http://github.com/llnl/melodee. 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 9 | # may not use this file except in compliance with the License. You may 10 | # obtain a copy of the License at: 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 17 | # implied. See the License for the specific language governing 18 | # permissions and limitations under the license. 19 | #### #### 20 | 21 | 22 | from melodee.parser import MelodeeParser,Differentiator 23 | from melodee import utility 24 | from melodee.utility import order 25 | from melodee.cardioidGenerator import CPrintVisitor 26 | 27 | def generateCoin(model, targetName): 28 | 29 | template = {'target' : targetName} 30 | 31 | givenvars = model.inputs() 32 | targetvars = model.varsWithAttribute("target") 33 | diffvars = model.diffvars() 34 | unknownvars = model.varsWithAttribute("unknown") 35 | constraintvars = model.varsWithAttribute("constraint") 36 | markovs = model.varsWithAttribute("markov") & diffvars 37 | gates = model.varsWithAttribute("gate") & diffvars 38 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 39 | 40 | lowerVals = {var : model.info("lb",var) 41 | for var in model.varsWithAttribute("lb")} 42 | upperVals = {var : model.info("ub",var) 43 | for var in model.varsWithAttribute("ub")} 44 | 45 | good = set() 46 | if model.time: 47 | good.add(time) 48 | 49 | differ = Differentiator(model, good|givenvars) 50 | gateJacobians = {} 51 | for gate in order(gates): 52 | (dontcare,gateJacobians[gate]) = differ.diff(diffvarUpdate[gate],gate) 53 | markovJacobians = { var : {} for var in markovs} 54 | for imarkov in order(markovs): 55 | for jmarkov in order(markovs): 56 | (dontcare,markovJacobians[imarkov][jmarkov]) = differ.diff(diffvarUpdate[imarkov],jmarkov) 57 | differ.augmentInstructions() 58 | 59 | dt = model.addSymbol("_dt") 60 | gateTargets = {} 61 | for gate in order(gates): 62 | F = model.ssa[diffvarUpdate[gate]].sympy 63 | L = gateJacobians[gate].sympy 64 | M = (F-L*gate).simplify() 65 | 66 | RLA = model.addInstruction("_%s_RLA" % gate, sympy.exp(dt*L)) 67 | RLB = model.addInstruction("_%s_RLB" % gate, M/L*(RLA-1)) 68 | gateTargets[gate] = (RLA,RLB) 69 | 70 | markovOld = {} 71 | for markov in order(markovs): 72 | markovOld[markov] = model.addSymbol("_mi_old_%s" % markov) 73 | markovTargets = {} 74 | for imarkov in order(markovs): 75 | summation = 0 76 | for jmarkov in order(markovs): 77 | if imarkov == jmarkov: 78 | continue 79 | if jmarkov in markovTargets: 80 | thisSym = markovTargets[jmarkov] 81 | else: 82 | thisSym = markovOld[jmarkov] 83 | summation += markovJacobians[imarkov][jmarkov].sympy*thisSym 84 | sss = (diffvarUpdate[imarkov]+dt*summation)/(1-dt*markovJacobians[imarkov][imarkov].sympy) 85 | markovTargets[imarkov] = model.addInstruction("_mi_new_%s" % imarkov,sss) 86 | 87 | out = utility.Indenter(open(targetName+".hpp","w")) 88 | cprinter = CPrintVisitor(out, model.ssa, set()) 89 | 90 | out(''' 91 | #ifndef __%(target)s_HPP__ 92 | #define __%(target)s_HPP__ 93 | 94 | #include 95 | #include 96 | #include "IpTNLP.hpp" 97 | 98 | namespace %(target)s { 99 | 100 | class ThisTNLP : public Ipopt::TNLP 101 | { 102 | public: 103 | double _dtRequested; 104 | double _time_lb; 105 | double _time_ub;''', template) 106 | 107 | out.inc() 108 | for var in order(givenvars)+order(targetvars): 109 | out('std::function _func_%s;',var) 110 | out.dec() 111 | out(r''' 112 | 113 | /** default constructor */ 114 | ThisTNLP(){} 115 | 116 | /** default destructor */ 117 | virtual ~ThisTNLP(){} 118 | 119 | virtual bool get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g, 120 | Ipopt::Index& nnz_h_lag, Ipopt::TNLP::IndexStyleEnum& index_style); 121 | 122 | virtual bool get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u, 123 | Ipopt::Index m, Ipopt::Number* g_l, Ipopt::Number* g_u); 124 | 125 | virtual bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x, 126 | bool init_z, Ipopt::Number* z_L, Ipopt::Number* z_U, 127 | Ipopt::Index m, bool init_lambda, Ipopt::Number* lambda); 128 | 129 | virtual bool eval_f(Ipopt::Index n, const Ipopt::Number* x, 130 | bool new_x, Ipopt::Number& obj_value); 131 | 132 | virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number* grad_f){return false;} 133 | 134 | virtual bool eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Number* g){return false;} 135 | 136 | /** Method to return: 137 | * 1) The structure of the jacobian (if "values" is NULL) 138 | * 2) The values of the jacobian (if "values" is not NULL) 139 | */ 140 | virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, 141 | Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index* iRow, Ipopt::Index *jCol, 142 | Ipopt::Number* values){return false;} 143 | 144 | /** Method to return: 145 | * 1) The structure of the hessian of the lagrangian (if "values" is NULL) 146 | * 2) The values of the hessian of the lagrangian (if "values" is not NULL) 147 | */ 148 | virtual bool eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x, 149 | Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number* lambda, 150 | bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index* iRow, 151 | Ipopt::Index* jCol, Ipopt::Number* values){return false;} 152 | 153 | virtual void finalize_solution(Ipopt::SolverReturn status, 154 | Ipopt::Index n, const Ipopt::Number* x, const Ipopt::Number* z_L, const Ipopt::Number* z_U, 155 | Ipopt::Index m, const Ipopt::Number* g, const Ipopt::Number* lambda, 156 | Ipopt::Number obj_value, 157 | const Ipopt::IpoptData* ip_data, 158 | Ipopt::IpoptCalculatedQuantities* ip_cq){} 159 | 160 | }; 161 | 162 | void getRequirements(std::vector&); 163 | int getHandle(const std::string&); 164 | 165 | Ipopt::TNLP* factory(const std::vector >& functions, const double time_lb, const double time_ub, const double dt); 166 | } 167 | 168 | #endif''', template) 169 | 170 | out = utility.Indenter(open(targetName+".cpp","w")) 171 | cprinter = CPrintVisitor(out, model.ssa, set()) 172 | 173 | out(r''' 174 | #include "%(target)s.hpp" 175 | #include 176 | #include 177 | 178 | using namespace Ipopt; 179 | using namespace std; 180 | 181 | namespace %(target)s { 182 | 183 | enum ReqEnum { 184 | ''', template) 185 | out.inc() 186 | for var in order(givenvars)+order(targetvars): 187 | out('_req_%s,',var) 188 | out.dec() 189 | out(r''' 190 | NUMREQS 191 | }; 192 | 193 | void getRequirements(vector& reqs) 194 | { 195 | reqs.clear();''', template) 196 | out.inc() 197 | for var in order(givenvars)+order(targetvars): 198 | out('reqs.push_back("%s");',var) 199 | out.dec() 200 | out(r''' 201 | } 202 | 203 | int getHandle(const string& inname) 204 | { 205 | if (0) {}''', template) 206 | out.inc() 207 | for var in order(givenvars)+order(targetvars): 208 | out('else if (inname == "%s") { return _req_%s; }',var,var) 209 | out.dec() 210 | out(r''' 211 | 212 | return -1; 213 | } 214 | 215 | Ipopt::TNLP* factory(const vector >& functions, const double time_lb, const double time_ub, const double dt) 216 | { 217 | assert(functions.size() == NUMREQS); 218 | ThisTNLP* thisTNLP = new ThisTNLP();''', template) 219 | out.inc() 220 | for var in order(givenvars)+order(targetvars): 221 | out('thisTNLP->_func_%s = functions[_req_%s];',var,var) 222 | out.dec() 223 | out(r''' 224 | thisTNLP->_dtRequested = dt; 225 | thisTNLP->_time_lb = time_lb; 226 | thisTNLP->_time_ub = time_ub; 227 | return thisTNLP; 228 | } 229 | 230 | enum UnkEnum {''', template) 231 | out.inc() 232 | for var in order(unknownvars): 233 | out('_unknown_%s,',var) 234 | out.dec() 235 | out(r''' 236 | NUMUNKNOWN 237 | }; 238 | 239 | enum ConstraintEnum {''', template) 240 | out.inc() 241 | for var in order(constraintvars): 242 | out('_constraint_%s,',var) 243 | out.dec() 244 | out(r''' 245 | NUMCONSTRAINT 246 | }; 247 | 248 | bool ThisTNLP::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, 249 | Index& nnz_h_lag, IndexStyleEnum& index_style) 250 | { 251 | n = NUMUNKNOWN; 252 | m = NUMCONSTRAINT; 253 | nnz_jac_g = n*m; 254 | nnz_h_lag = n*n; 255 | index_style = FORTRAN_STYLE; 256 | return true; 257 | } 258 | 259 | bool ThisTNLP::get_bounds_info(Index n, Number* x_l, Number* x_u, 260 | Index m, Number* g_l, Number* g_u) 261 | {''', template) 262 | out.inc() 263 | 264 | for var in order(unknownvars): 265 | #lb = lowerVals.get(var,'-nlp_lower_bound_inf') 266 | #ub = upperVals.get(var,'nlp_upper_bound_inf') 267 | lb = lowerVals.get(var,'-1e35') 268 | ub = upperVals.get(var,'1e35') 269 | out("x_l[_unknown_%s] = %s;",var,lb); 270 | out("x_u[_unknown_%s] = %s;",var,ub); 271 | 272 | for var in order(constraintvars): 273 | lb = lowerVals.get(var,'-1e35') 274 | ub = upperVals.get(var,'1e35') 275 | out("g_l[_constraint_%s] = %s;",var,lb); 276 | out("g_u[_constraint_%s] = %s;",var,ub); 277 | 278 | out.dec() 279 | out(r''' 280 | return true; 281 | } 282 | 283 | bool ThisTNLP::get_starting_point(Index , bool _init_x, Number* _x, 284 | bool _init_z, Number* _z_L, Number* _z_U, 285 | Index , bool _init_lambda, Number* _lambda) 286 | { 287 | double _time = _time_lb; 288 | 289 | if (_init_x) 290 | { 291 | ''', template) 292 | out.inc(2) 293 | for var in order(givenvars): 294 | out('double %s = _func_%s(_time);',var,var) 295 | 296 | model.printTarget(givenvars,unknownvars,cprinter) 297 | 298 | for var in order(unknownvars): 299 | out('_x[_unknown_%s ] = %s;',var,var) 300 | out.dec(2) 301 | out(r''' 302 | } 303 | if (_init_z) 304 | { 305 | assert(0 && "No idea what to put for z bounds."); 306 | } 307 | if (_init_lambda) 308 | { 309 | assert(0 && "No idea how to initialize lambda."); 310 | } 311 | return true; 312 | } 313 | 314 | bool ThisTNLP::eval_f(Index, const Number* _x, 315 | bool _new_x, Number& _obj_value) 316 | { 317 | int _tsCount = round((_time_ub-_time_lb)/_dtRequested); 318 | double _dt = (_time_ub-_time_lb)/_tsCount; 319 | _obj_value = 0; 320 | 321 | ''', template) 322 | out.inc() 323 | for var in order(unknownvars): 324 | out('double %s = _x[_unknown_%s];',var,var) 325 | model.printTarget(unknownvars, 326 | diffvars, 327 | cprinter) 328 | out.dec() 329 | out(r''' 330 | for (int _ii=0; _ii<_tsCount; _ii++) 331 | { 332 | double _time = _time_lb+_ii*_dt;''', template) 333 | out.inc(2) 334 | for var in order(givenvars): 335 | out('double %s = _func_%s(_time);',var,var) 336 | 337 | out("//get the targets") 338 | good |= unknownvars|givenvars|diffvars 339 | targetSet = model.allDependencies(good,targetvars)-good 340 | model.printSet(targetSet,cprinter) 341 | good |= targetSet 342 | 343 | 344 | out("//get the gate updates (diagonalized exponential integrator)") 345 | gateGoals = set() 346 | for RLA,RLB in gateTargets.values(): 347 | gateGoals.add(RLA) 348 | gateGoals.add(RLB) 349 | good.add(dt) 350 | gateSet = model.allDependencies(good,gateGoals)-good 351 | model.printSet(gateSet,cprinter) 352 | good |= gateSet 353 | 354 | out("//get the other differential updates") 355 | diffGoals = set([diffvarUpdate[var] for var in diffvars-gates]) 356 | diffSet = model.allDependencies(good,diffGoals)-good 357 | model.printSet(diffSet, cprinter) 358 | good |= diffSet 359 | 360 | out("//Do the markov update (1 step rosenbrock with gauss siedel)") 361 | for var in order(markovs): 362 | out("double %s = %s;",markovTargets[var],diffvarUpdate[var]) 363 | out("int _count=0;") 364 | out("double _error;") 365 | out("do") 366 | out("{") 367 | out.inc() 368 | cprinter.pushStack() 369 | 370 | 371 | for var in order(markovs): 372 | out("double %s = %s;",markovOld[var], markovTargets[var]) 373 | markovGoals = set(markovOld.values()) 374 | good |= markovGoals 375 | cprinter.declaredStack[-1] |= set(["%s" % var for var in markovTargets.values()]) 376 | markovSet = model.allDependencies(good,set(markovTargets.values())) 377 | model.printSet(markovSet,cprinter) 378 | 379 | out("_error = 0;") 380 | for var in order(markovs): 381 | old = markovOld[var] 382 | new = markovTargets[var] 383 | out("_error += (%s-%s)*(%s-%s);",old,new,old,new) 384 | out("_count++;") 385 | 386 | cprinter.popStack() 387 | out.dec() 388 | out("} while (_error > 1e-100 && _count<50);") 389 | 390 | for var in order(diffvars-gates-markovs): 391 | out("%s += _dt*%s;",var,diffvarUpdate[var]) 392 | 393 | for var in order(gates): 394 | RLA,RLB = gateTargets(var) 395 | out("%s = %s*%s + %s;",var,RLA,var,RLB) 396 | 397 | for var in order(markovs): 398 | out("%s += _dt*%s;",var,markovTargets[var]) 399 | 400 | for var in order(targetvars): 401 | out("double _residual_%s = %s - _func_%s(_time);",var,var,var) 402 | out("_obj_value += _dt*_residual_%s*_residual_%s;",var,var) 403 | out.dec(2) 404 | out(r''' 405 | } 406 | return true; 407 | } 408 | 409 | } // namespace HergCoinStandalone 410 | ''' % template) 411 | 412 | generators = { 413 | frozenset(["coin"]) : generateCoin 414 | } 415 | -------------------------------------------------------------------------------- /melodee/continuityGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import sys 27 | import re 28 | import sympy 29 | from sympy.core import S 30 | 31 | from melodee.cardioidGenerator import MyCCodeSympyPrinter,CPrintVisitor 32 | 33 | from melodee.parser import MelodeeParser,Differentiator 34 | from melodee import utility 35 | from melodee.utility import order 36 | 37 | 38 | def pretty(symbol): 39 | return str(symbol) 40 | 41 | def generateContinuity(model, targetName): 42 | template = {} 43 | template["target"] = targetName 44 | 45 | diffvars = model.diffvars() 46 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 47 | gates = model.varsWithAttribute("gate") & diffvars 48 | params = model.varsWithAttribute("param") 49 | coupled = model.varsWithAttribute("coupled") & diffvars 50 | 51 | inputs=model.inputs() 52 | 53 | differ = Differentiator(model, diffvars | params | inputs) 54 | gateJacobians = {} 55 | for gate in diffvars: 56 | (gateJacobians[gate],dontcare) = differ.diff(diffvarUpdate[gate],gate) 57 | differ.augmentInstructions() 58 | 59 | dt = model.addSymbol("_dt") 60 | approxvars = set([dt]) 61 | if model.time != None: 62 | approxvars.add(model.time) 63 | 64 | expensiveVars = model.extractExpensiveFunctions() 65 | model.makeNamesUnique() 66 | 67 | computeTargets = set() 68 | computeTargets |= set([diffvarUpdate[var] for var in diffvars]) 69 | computeTargets |= set([gateJacobians[var] for var in diffvars]) 70 | 71 | statevars = model.inputs()|diffvars 72 | computeAllDepend = model.allDependencies(approxvars|statevars, computeTargets) 73 | constants = model.allExcluding(approxvars, statevars) & computeAllDepend 74 | 75 | varCount = {} 76 | ii=0 77 | for var in order(coupled): 78 | varCount[var] = ii 79 | ii += 1 80 | for var in order(diffvars-coupled): 81 | varCount[var] = ii 82 | ii += 1 83 | 84 | ii=0 85 | for var in order(inputs): 86 | varCount[var] = ii 87 | ii += 1 88 | for var in order(params): 89 | varCount[var] = ii 90 | ii += 1 91 | 92 | fieldNumbers = {} 93 | ii=1 94 | for var in order(inputs): 95 | fieldNumbers[var] = ii 96 | ii += 1 97 | for var in order(coupled): 98 | fieldNumbers[var] = ii 99 | ii += 1 100 | out = utility.Indenter(open(targetName+".txt","w")) 101 | out(" component %(target)s StateVar", template) 102 | for var in order(coupled): 103 | out("voltage spatially coupled [['Field %d', '']] d%s_dt = 0 StateVar %s", fieldNumbers[var], pretty(var), pretty(var)) 104 | for var in order(diffvars-coupled): 105 | out("voltage state [['Value', '1']] d%s_dt = 0 StateVar %s", pretty(var),pretty(var)) 106 | out("param root component __root__ Parameters") 107 | out.inc() 108 | for var in order(inputs): 109 | out("parameter [['Field %s', '']] Parameters %s", fieldNumbers[var], pretty(var)) 110 | 111 | for var in order(params): 112 | out("parameter [['Value', '%s']] Parameters %s", str(model.ssa[var].sympy), pretty(var)) 113 | out.dec() 114 | 115 | 116 | out = utility.Indenter(open(targetName+".continuity.c","w")) 117 | out(''' 118 | void cpu_advance_be1(REAL _t, REAL _t_end, REAL *_y_global, REAL *_y_global_temp, REAL *_rpar_global, int num_gauss_pts, int num_gpus, int gp_offset) 119 | { 120 | //REAL bi; 121 | REAL _dt = _t_end-_t; 122 | 123 | 124 | ''' % template) 125 | out.inc() 126 | if model.time: 127 | out("REAL %s = _t;", pretty(model.time)) 128 | good = set() 129 | good |= approxvars 130 | for var in order(diffvars): 131 | out("REAL %s=_y_global[%d];", pretty(var), varCount[var]); 132 | good |= statevars 133 | for var in order(params|inputs): 134 | out("REAL %s=_rpar_global[%d];", pretty(var), varCount[var]); 135 | good |= params 136 | 137 | cprinter = CPrintVisitor(out, model.ssa, good, "REAL") 138 | model.printTarget(good,computeTargets,cprinter) 139 | 140 | 141 | for var in order(diffvars): 142 | out("_y_global_temp[%d] = _y_global[%d] + %s*_dt/(1-_dt*%s);", varCount[var], varCount[var], diffvarUpdate[var], gateJacobians[var]) 143 | 144 | out.dec() 145 | out(''' 146 | 147 | //assigned_vars: 10 148 | 149 | } 150 | ''' % template) 151 | 152 | generators = { 153 | frozenset(["continuity"]): generateContinuity, 154 | } 155 | -------------------------------------------------------------------------------- /melodee/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from melodee.parser import MelodeeParser 4 | 5 | class GeneratorFactory: 6 | def __init__(self): 7 | self.tagLookup = {} 8 | def register(self, function, tags): 9 | self.tagLookup[frozenset(tags)] = function 10 | def lookup(self,tags): 11 | return self.tagLookup[frozenset(tags)] 12 | 13 | def main(): 14 | import sys 15 | import argparse 16 | import os 17 | import glob 18 | import importlib 19 | import melodee.cardioidGenerator 20 | 21 | genFactory = GeneratorFactory() 22 | #search all the Generators and register them. 23 | modules = glob.glob(os.path.join(os.path.dirname(__file__),"*Generator.py")) 24 | for modulePath in modules: 25 | if os.path.samefile(modulePath,__file__): 26 | continue 27 | moduleName = os.path.split(modulePath)[-1][:-3] 28 | importlib.import_module("melodee."+moduleName) 29 | #melodee = __import__("melodee."+moduleName, globals(), locals(), [], -1) 30 | module = eval("melodee."+moduleName) 31 | for (tags, function) in module.generators.items(): 32 | genFactory.register(function, tags) 33 | 34 | ap=argparse.ArgumentParser(description="Convert Melodee into source code") 35 | ap.add_argument("-g", "--generate", 36 | help="Specify the type of code to generate. Multiple options lets you specialize within a translaton method", 37 | dest="generators", 38 | action="append", 39 | required=True, 40 | ) 41 | ap.add_argument("-o", "--output", 42 | help="Change the default name of the output model.", 43 | dest="output", 44 | action="store", 45 | ) 46 | ap.add_argument("-t", "--target", 47 | help="Specify a target model.", 48 | dest="targets", 49 | action="append", 50 | required=True, 51 | ) 52 | ap.add_argument("filenames", nargs=argparse.REMAINDER, 53 | help="Filenames containing all the targets", 54 | ) 55 | options=ap.parse_args() 56 | targets = options.targets 57 | filenames = options.filenames 58 | outputName = options.output 59 | generators = options.generators 60 | if not outputName: 61 | outputName = "_".join(targets) 62 | 63 | p = MelodeeParser() 64 | 65 | for filename in filenames: 66 | p.parse(open(filename,"r").read()) 67 | 68 | if len(targets) > 1: 69 | targetModel = "" 70 | targetModel += "subsystem %s {\n" % outputName 71 | for model in targets: 72 | targetModel += " use %s;\n" % model 73 | targetModel += "}\n" 74 | p.parse(targetModel) 75 | finalTarget = outputName 76 | else: 77 | finalTarget = targets[0] 78 | 79 | genFactory.lookup(generators)(p.getModel(finalTarget),outputName) 80 | -------------------------------------------------------------------------------- /melodee/matlabGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import sys 27 | import re 28 | import sympy 29 | from sympy.printing.octave import OctaveCodePrinter 30 | 31 | 32 | from melodee.parser import MelodeeParser 33 | from melodee import utility 34 | from melodee.utility import order 35 | 36 | def pretty(symbol): 37 | if str(symbol)[0] == '_': 38 | return "U"+str(symbol) 39 | else: 40 | return str(symbol) 41 | return str(symbol) 42 | 43 | class MyOctaveCodeSympyPrinter(OctaveCodePrinter): 44 | def __init__(self,*args,**kwargs): 45 | OctaveCodePrinter.__init__(self, *args, **kwargs) 46 | def _print_Relational(self,expr): 47 | if expr.rel_op == "==" or expr.rel_op == "!=": 48 | PREC = sympy.printing.precedence.precedence(expr) 49 | return "%s %s %s" % (self.parenthesize(expr.lhs, PREC), 50 | expr.rel_op, 51 | self.parenthesize(expr.rhs, PREC)) 52 | else: 53 | return super(MyOctaveCodeSympyPrinter, self)._print_Relational(expr) 54 | def _print_Symbol(self,symbol): 55 | return pretty(symbol) 56 | 57 | class MatlabPrintVisitor: 58 | def __init__(self, out, ssa, params): 59 | self.out = out 60 | self.ssa = ssa 61 | self.params = params 62 | self.oprinter = MyOctaveCodeSympyPrinter() 63 | 64 | def ifPrint(self,printer,ifSymbol,thenList,elseList,choiceList): 65 | self.out("if (%s)",pretty(ifSymbol)) 66 | self.out.inc() 67 | printer(thenList) 68 | for choiceVar in choiceList: 69 | choice = self.ssa[choiceVar] 70 | lhs = pretty(choiceVar) 71 | rhs = pretty(choice.thenVar) 72 | if lhs != rhs: 73 | self.out("%s = %s;",lhs,rhs) 74 | self.out.dec() 75 | self.out("else") 76 | self.out.inc() 77 | printer(elseList) 78 | for choiceVar in choiceList: 79 | choice = self.ssa[choiceVar] 80 | lhs = pretty(choiceVar) 81 | rhs = pretty(choice.elseVar) 82 | if lhs != rhs: 83 | self.out("%s = %s;",lhs,rhs) 84 | self.out.dec() 85 | self.out("end") 86 | def equationPrint(self,lhs,rhs): 87 | rhsText = self.oprinter.doprint(rhs.sympy) 88 | lhsText = self.oprinter.doprint(lhs) 89 | if lhs in self.params: 90 | self.out(""" 91 | if (isfield(U_params, '%(name)s')) 92 | %(name)s = U_params.%(name)s; 93 | else 94 | %(name)s = %(rhs)s; 95 | U_params.%(name)s = %(name)s; 96 | end""", name=lhsText, rhs=rhsText) 97 | else: 98 | self.out("%s = %s;", lhsText, rhsText) 99 | 100 | def numberVars(diffvars): 101 | ret = {} 102 | count = 1 103 | for var in order(diffvars): 104 | ret[var] = count 105 | count += 1 106 | return ret 107 | 108 | def generateMatlab(model, targetName): 109 | template = {} 110 | template["target"] = targetName 111 | 112 | inputs = model.inputs() 113 | if inputs: 114 | template["arglower"] = 1 115 | else: 116 | template["arglower"] = 0 117 | 118 | good = set() 119 | if model.time != None: 120 | good.add(model.time) 121 | timename = str(model.time) 122 | else: 123 | timename = "U_current_time" 124 | template["timename"] = timename 125 | 126 | out = utility.Indenter(open(targetName+"_init.m","w")) 127 | params = model.varsWithAttribute("param") 128 | printer = MatlabPrintVisitor(out,model.ssa,params) 129 | out(""" 130 | function [U_y_init, U_ordering, U_params] = %(target)s_init(%(timename)s,varargin) 131 | narginchk(1+%(arglower)d,2); 132 | if (nargin >= 1) 133 | U_params = varargin{1}; 134 | else 135 | U_params = struct(); 136 | end 137 | """ % template) 138 | out.inc() 139 | 140 | if inputs: 141 | out("%define the inputs") 142 | good |= inputs 143 | for symbol in order(inputs): 144 | out("%s = U_params.%s(%s);",pretty(symbol),pretty(symbol),timename) 145 | 146 | out("\n\n") 147 | out("%define the initial conditions") 148 | diffvars = model.diffvars() 149 | model.printTarget(good,params|diffvars,printer) 150 | 151 | diffvarNumbering = numberVars(diffvars) 152 | out("U_y_init = zeros(%d, 1);", len(diffvarNumbering)) 153 | for var in order(diffvars): 154 | out("U_y_init(%d) = %s;",diffvarNumbering[var],pretty(var)) 155 | 156 | out("U_ordering = struct();") 157 | for var in order(diffvars): 158 | out("U_ordering.%s = %d;", pretty(var),diffvarNumbering[var]) 159 | 160 | out.dec() 161 | out(""" 162 | end 163 | """ % template) 164 | 165 | out = utility.Indenter(open(targetName+".m","w")) 166 | printer = MatlabPrintVisitor(out,model.ssa,params) 167 | out(""" 168 | function U_dydt = %(target)s(%(timename)s,U_diffvars,varargin) 169 | """ % template) 170 | out.inc() 171 | out("U_dydt = zeros(%d,1);" % len(diffvarNumbering)) 172 | 173 | good = set() 174 | if model.time != None: 175 | good.add(model.time) 176 | 177 | out("% make copies of the differential vars") 178 | for var in order(diffvars): 179 | out("%s = U_diffvars(%d);", pretty(var), diffvarNumbering[var]) 180 | good |= diffvars 181 | 182 | out(""" 183 | narginchk(2+%(arglower)d,3); 184 | if (nargin >= 3) 185 | U_params = varargin{1}; 186 | else 187 | U_params = struct(); 188 | end 189 | """ % template) 190 | 191 | if inputs: 192 | out("% define all inputs") 193 | good |= inputs 194 | for symbol in order(inputs): 195 | out("%s = U_params.%s(%s);",pretty(symbol),pretty(symbol),timename) 196 | 197 | out("% define the differential update") 198 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 199 | model.printTarget(good,set(diffvarUpdate.values()),printer) 200 | 201 | out("% stuff the differential update into an array") 202 | for var in order(diffvars): 203 | out("U_dydt(%d) = %s;", diffvarNumbering[var], pretty(diffvarUpdate[var])) 204 | 205 | out.dec() 206 | out(""" 207 | end""" % template) 208 | 209 | out = utility.Indenter(open(targetName+"_trace.m","w")) 210 | printer = MatlabPrintVisitor(out, model.ssa, params) 211 | out(""" 212 | function U_trace = %(target)s_trace(%(timename)s,U_diffvars,varargin) 213 | """ % template) 214 | out.inc() 215 | out("% make copies of the differential vars") 216 | for var in order(diffvars): 217 | out("%s = U_diffvars(:,%d);", pretty(var), diffvarNumbering[var]) 218 | out(""" 219 | narginchk(2+%(arglower)d,3); 220 | if (nargin >= 3) 221 | U_params = varargin{1}; 222 | else 223 | U_params = struct(); 224 | end 225 | """ % template) 226 | if inputs: 227 | out("% define all inputs") 228 | good |= inputs 229 | for symbol in order(inputs): 230 | out("%s = U_params.%s(%s);",pretty(symbol),pretty(symbol),timename) 231 | 232 | tracevars = model.varsWithAttribute("trace") 233 | out("%calculate the tracing vars we need") 234 | model.printTarget(good,tracevars-good,printer) 235 | 236 | out("%save the tracing vars") 237 | out("U_trace = struct();") 238 | for var in order(tracevars): 239 | out('U_trace.%s = %s;', var, var) 240 | out.dec() 241 | out(""" 242 | end""" % template) 243 | 244 | generators = { 245 | frozenset(["matlab"]): generateMatlab, 246 | } 247 | -------------------------------------------------------------------------------- /melodee/mechCardioidGenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | from melodee.parser import MelodeeParser,Differentiator 27 | from melodee import utility 28 | from melodee.utility import order,itemsOrderedByKey 29 | 30 | from melodee.cardioidGenerator import CPrintVisitor 31 | 32 | def generateCardioidMech(model, targetName): 33 | template = {} 34 | template["target"] = targetName 35 | 36 | diffvars = model.diffvars() 37 | diffvarUpdate = {var : model.diffvarUpdate(var) for var in diffvars} 38 | flagvars = model.varsWithAttribute("flag") 39 | paramvars = model.varsWithAttribute("param") 40 | tracevars = model.varsWithAttribute("trace") 41 | simvars = set() 42 | 43 | stretch = model.input("stretch") 44 | tension = model.output("tension") 45 | if "stretchVel" not in model._inputs: 46 | stretchVel = model.addSymbol("stretchVel") 47 | else: 48 | stretchVel = model.input("stretchVel") 49 | inputvars = set([stretch,stretchVel])|model.inputs() 50 | 51 | partialFromDiff = {} 52 | diffPartialFromDiff = {} 53 | 54 | differ = Differentiator(model, inputvars-set([stretch])) 55 | partialvars = set() 56 | for diffvar in diffvars: 57 | partial = model.addSymbol("_partial_"+str(diffvar)) 58 | partialvars.add(partial) 59 | differ.cacheResult(diffvar, stretchVel, partial, None) 60 | partialFromDiff[diffvar] = partial 61 | partialStretch = model.addSymbol("_partial_stretch") 62 | differ.cacheResult(stretch, stretchVel, partialStretch, None) 63 | 64 | for diffvar in diffvars: 65 | (diffvarUpdate[partialFromDiff[diffvar]],dontcare) = differ.diff(diffvarUpdate[diffvar],stretchVel) 66 | (dtension_temp,dontcare) = differ.diff(tension, stretchVel) 67 | differ.augmentInstructions() 68 | dtension_dstretchVel = model.addInstruction("dtension_dstretchVel",dtension_temp) 69 | 70 | outputvars = set([tension,dtension_dstretchVel]) 71 | 72 | out = utility.Indenter(open(targetName+".hh","w")) 73 | out(r''' 74 | #include "ExcitationContraction.hh" 75 | #include 76 | #include 77 | 78 | namespace %(target)s 79 | { 80 | 81 | struct State 82 | {''',template) 83 | out.inc() 84 | for var in order(diffvars|partialvars): 85 | out("double %s;", var) 86 | out.dec() 87 | out(''' 88 | }; 89 | 90 | class ThisModel : public ExcitationContraction 91 | { 92 | public: 93 | ThisModel(const int numPoints); 94 | virtual std::string name() const; 95 | virtual int getHandle(const std::string& varName) const; 96 | virtual std::string getUnit(const int varHandle) const; 97 | 98 | virtual std::vector getVarGroup(const std::string type) const; 99 | 100 | virtual double get(const int varHandle) const; 101 | virtual void set(const int varHandle, const double value); 102 | 103 | virtual double get(const int varHandle, const int iCell) const; 104 | virtual void set(const int varHandle, const int iCell, const double value); 105 | 106 | virtual double get(const int varHandle, const int iCell, const double* inputs[]) const; 107 | 108 | virtual void resetDefaultParameters(); 109 | virtual void initialize(const double *const inputs[]); 110 | virtual void tryTimestep(const double dt, const double *const inputs[]); 111 | virtual void outputForNextTimestep(const double dt, const double* const inputs[], double* const outputs[]); 112 | virtual void commitTimestep(); 113 | 114 | private: 115 | int _numPoints; 116 | //double _dt; 117 | 118 | //FLAGS 119 | ''', template) 120 | out.inc() 121 | for var in order(flagvars): 122 | out("double %s;", var) 123 | out.dec() 124 | out(r''' 125 | //PARAMETERS 126 | ''', template) 127 | out.inc() 128 | for var in order(paramvars): 129 | out("double %s;", var) 130 | out.dec() 131 | out(r''' 132 | 133 | //STATE 134 | std::vector _state[2]; 135 | std::vector _partial; 136 | int _oldIdx; 137 | 138 | inline int _old() const { return _oldIdx; } 139 | inline int _new() const { return 1 ^ _oldIdx; } 140 | inline void swapOldAndNew() { _oldIdx = _new(); } 141 | 142 | }; 143 | 144 | } 145 | 146 | ''', template) 147 | 148 | out = utility.Indenter(open(targetName+".cpp","w")) 149 | out(r''' 150 | #include "%(target)s.hh" 151 | #include 152 | #include 153 | 154 | using namespace std; 155 | 156 | namespace %(target)s 157 | { 158 | 159 | string ThisModel::name() const 160 | { 161 | return "%(target)s"; 162 | } 163 | 164 | enum varHandles 165 | { 166 | ''', template) 167 | handlevars = diffvars|inputvars|outputvars|flagvars|paramvars 168 | out.inc() 169 | for var in order(handlevars): 170 | out('_handle_%s,',var) 171 | out.dec() 172 | out(r''' 173 | NUM_HANDLES 174 | }; 175 | 176 | const string varNames[] = { 177 | ''', template) 178 | out.inc() 179 | for var in order(handlevars): 180 | out('"%s",',var) 181 | out.dec() 182 | out(r''' 183 | "" 184 | }; 185 | 186 | const string varUnits[] = { 187 | ''', template) 188 | out.inc() 189 | for var in order(handlevars): 190 | out('"not_implemented",') 191 | out.dec() 192 | out(r''' 193 | "" 194 | }; 195 | 196 | enum inputOrder 197 | { 198 | ''', template) 199 | out.inc() 200 | for var in order(inputvars): 201 | out('_inIdx_%s,',var) 202 | out.dec() 203 | out(r''' 204 | NUM_INPUTS 205 | }; 206 | 207 | enum outputOrder 208 | { 209 | ''', template) 210 | out.inc() 211 | for var in order(outputvars): 212 | out('_outIdx_%s,',var) 213 | out.dec() 214 | out(r''' 215 | NUM_OUTPUTS 216 | }; 217 | 218 | int ThisModel::getHandle(const string& varName) const 219 | { 220 | for (int ii=0; ii 0 && varHandle < NUM_HANDLES); 233 | return varUnits[varHandle]; 234 | } 235 | 236 | vector ThisModel::getVarGroup(const std::string type) const 237 | { 238 | vector names; 239 | if (0) {} 240 | ''', template) 241 | out.inc() 242 | varGroups = { 243 | "input" : inputvars, 244 | "output" : outputvars, 245 | "checkpoint" : diffvars, 246 | "flag" : flagvars, 247 | "param" : paramvars, 248 | } 249 | for (group,groupvars) in itemsOrderedByKey(varGroups): 250 | out(r'else if (type == "%s")' % group) 251 | out(r'{') 252 | out.inc() 253 | out(r'names.reserve(%d);', len(groupvars)) 254 | for var in order(groupvars): 255 | out(r'names.push_back("%s");', var) 256 | out.dec() 257 | out(r'}') 258 | out.dec() 259 | out(r''' 260 | return names; 261 | } 262 | 263 | 264 | double ThisModel::get(const int varHandle) const 265 | { 266 | if (0) {} 267 | ''', template) 268 | out.inc() 269 | for var in order(flagvars|paramvars): 270 | out('else if (varHandle == _handle_%s)',var) 271 | out('{') 272 | out(' return %s;',var) 273 | out('}') 274 | out.dec() 275 | out(r''' 276 | return NAN; 277 | } 278 | void ThisModel::set(const int varHandle, const double value) 279 | { 280 | if (0) {} 281 | ''', template) 282 | out.inc() 283 | for var in order(flagvars|paramvars): 284 | out('else if (varHandle == _handle_%s)',var) 285 | out('{') 286 | out(' %s = value;',var) 287 | out('}') 288 | out.dec() 289 | out(r''' 290 | assert(0 && "Can't set a value for parameter that doesn't exist"); 291 | } 292 | 293 | double ThisModel::get(const int varHandle, const int iCell) const 294 | { 295 | if (0) {} 296 | ''', template) 297 | out.inc() 298 | for var in order(diffvars): 299 | out('else if (varHandle == _handle_%s)',var) 300 | out('{') 301 | out(' return _state[_old()][iCell].%s;',var) 302 | out('}') 303 | out.dec() 304 | out(r''' 305 | return get(varHandle); 306 | } 307 | 308 | void ThisModel::set(const int varHandle, const int iCell, const double value) 309 | { 310 | if (0) {} 311 | ''', template) 312 | out.inc() 313 | for var in order(diffvars): 314 | out('else if (varHandle == _handle_%s)',var) 315 | out('{') 316 | out(' _state[_old()][iCell].%s = value;',var) 317 | out('}') 318 | out.dec() 319 | out(r''' 320 | set(varHandle, value); 321 | } 322 | 323 | double ThisModel::get(const int varHandle, const int iCell, const double* inputs[]) const 324 | { 325 | ''', template) 326 | out.inc() 327 | out('if (0) {}') 328 | for var in order(tracevars): 329 | out('else if (varHandle == _handle_%s)',var) 330 | out('{') 331 | out('}') 332 | out.dec() 333 | out(r''' 334 | return get(varHandle, iCell); 335 | } 336 | 337 | ThisModel::ThisModel(const int numPoints) 338 | { 339 | _numPoints = numPoints; 340 | _oldIdx = 0; 341 | _state[0].resize(numPoints); 342 | _state[1].resize(numPoints); 343 | 344 | //set the flags 345 | ''',template) 346 | out.inc() 347 | good = set(simvars) 348 | cprinter = CPrintVisitor(out, model.ssa, paramvars|flagvars|simvars) 349 | model.printTarget(good,flagvars,cprinter) 350 | good |= flagvars 351 | out.dec() 352 | out(r''' 353 | //set the default parameters 354 | resetDefaultParameters(); 355 | } 356 | 357 | void ThisModel::resetDefaultParameters() 358 | { 359 | ''', template) 360 | out.inc() 361 | cprinter = CPrintVisitor(out, model.ssa, paramvars|flagvars|simvars) 362 | model.printTarget(flagvars|simvars,paramvars,cprinter) 363 | good |= paramvars 364 | out.dec() 365 | out(r''' 366 | } 367 | 368 | void ThisModel::initialize(const double* const _inputs[]) 369 | { 370 | for (int _icell=0; _icell < _numPoints; _icell++) 371 | {''', template) 372 | out.inc(2) 373 | for var in order(inputvars): 374 | out("const double %s = _inputs[_inIdx_%s][_icell];", var, var) 375 | good |= inputvars 376 | cprinter = CPrintVisitor(out, model.ssa, paramvars|flagvars) 377 | model.printTarget(flagvars,diffvars,cprinter) 378 | for var in order(diffvars): 379 | out("_state[_old()][_icell].%s = %s;",var,var) 380 | good |= diffvars 381 | out.dec(2) 382 | out(r''' 383 | } 384 | } 385 | 386 | const int internalTimestep = 20; 387 | 388 | void ThisModel::tryTimestep(const double dt, const double* const _inputs[]) 389 | { 390 | for (int _icell=0; _icell < _numPoints; _icell++) 391 | {''', template) 392 | out.inc(2) 393 | for var in order(inputvars-set([stretch])): 394 | out("const double %s = _inputs[_inIdx_%s][_icell];", var, var) 395 | out("double %s = _inputs[_inIdx_%s][_icell];",stretch,stretch) 396 | good |= inputvars 397 | for var in order(partialvars): 398 | out("double %s = 0;",var) 399 | good |= partialvars 400 | for var in order(diffvars): 401 | out("double %s = _state[_old()][_icell].%s;", var, var) 402 | out("for (int itime=0; itime #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | import math 27 | 28 | class Unit: 29 | def __init__(self, unitSystem, bases, scale): 30 | self.system = unitSystem 31 | self.bases = bases 32 | self.scale = scale 33 | 34 | def isCompatibleWith(self, other): 35 | if other == None: 36 | return False 37 | if self.system != other.system: 38 | return False 39 | for (base,power) in self.bases.items(): 40 | if power != 0: 41 | if base not in other.bases: 42 | return False 43 | elif other.bases[base] != power: 44 | return False 45 | for (base,power) in other.bases.items(): 46 | if power != 0: 47 | if base not in self.bases: 48 | return False 49 | return True 50 | def __eq__(self, other): 51 | return self.isCompatibleWith(other) and self.scale == other.scale 52 | def __ne__(self, other): 53 | return not self==other 54 | def copy(self): 55 | basesCopy = dict(self.bases) 56 | return Unit(self.system, basesCopy, self.scale) 57 | def __mul__(self, other): 58 | assert(self.system == other.system) 59 | ret = self.copy() 60 | for (base,power) in other.bases.items(): 61 | ret.bases[base] = ret.bases.get(base, 0) + power 62 | ret.scale += other.scale 63 | return ret 64 | def __div__(self, other): 65 | return self.__truediv__(other) 66 | def __truediv__(self, other): 67 | assert(self.system == other.system) 68 | ret = self.copy() 69 | for (base,power) in other.bases.items(): 70 | ret.bases[base] = ret.bases.get(base, 0) - power 71 | ret.scale -= other.scale 72 | return ret 73 | def __pow__(self, number): 74 | ret = self.copy() 75 | for base in self.bases.keys(): 76 | ret.bases[base] *= number 77 | ret.scale = ret.scale*number 78 | return ret 79 | def __str__(self): 80 | return self.system.strify(self) 81 | def __repr__(self): 82 | return 'Unit(si,'+repr(self.bases)+','+repr(self.scale)+')' 83 | def convertTo(self, other): 84 | ''' 85 | Gives factor so that self * factor = providedUnit 86 | Test mentally with millimeters and meters 87 | ''' 88 | assert self.isCompatibleWith(other) 89 | return 10**(self.scale-other.scale) 90 | 91 | class UnitSystem: 92 | def __init__(self, possibleBases): 93 | self.knownUnits = {} 94 | self.possibleBases = set() 95 | for base in possibleBases: 96 | self.addBase(base) 97 | def addBase(self, base): 98 | if base not in self.possibleBases: 99 | self.possibleBases.add(base) 100 | self.register(base, Unit(self, {base : 1}, 0)) 101 | def register(self, name, unit): 102 | self.knownUnits[name] = unit 103 | def scaleToUnit(self,scale): 104 | return Unit(self, {}, math.log10(scale)) 105 | def get(self, unitName): 106 | return self.knownUnits[unitName] 107 | def strify(self, unit): 108 | '''find the smallest unit expr by greedy gradient descent''' 109 | def unitDot(xxx,yyy): 110 | allBases = set(xxx.bases.keys()) | set(yyy.bases.keys()) 111 | dotp = xxx.scale*yyy.scale 112 | for base in allBases: 113 | dotp += xxx.bases.get(base, 0)*yyy.bases.get(base, 0) 114 | return dotp 115 | numerator = [] 116 | denominator = [] 117 | remainder = unit 118 | while unitDot(remainder,remainder) > 0: 119 | maxUnitName = None 120 | maxUnitDot = 0 121 | for (thisName,thisUnit) in self.knownUnits.items(): 122 | thisSize = math.sqrt(unitDot(thisUnit,thisUnit)) 123 | if thisSize==0: 124 | continue 125 | thisUnitDot = unitDot(remainder,thisUnit)/thisSize 126 | if (maxUnitName == None or 127 | abs(thisUnitDot) > abs(maxUnitDot) or 128 | (abs(thisUnitDot) == abs(maxUnitDot) and 129 | len(thisName) < len(maxUnitName) 130 | )): 131 | maxUnitDot = thisUnitDot 132 | maxUnitName = thisName 133 | assert(maxUnitName != None) 134 | if maxUnitDot > 0: 135 | numerator.append(maxUnitName) 136 | remainder = remainder / self.get(maxUnitName) 137 | else: 138 | denominator.append(maxUnitName) 139 | remainder = remainder * self.get(maxUnitName) 140 | if not numerator and not denominator: 141 | return "1" 142 | elif numerator and not denominator: 143 | return "*".join(numerator) 144 | elif not numerator and denominator: 145 | return "1/"+"/".join(denominator) 146 | else: 147 | return "*".join(numerator)+"/"+"/".join(denominator) 148 | 149 | def __getattr__(self, name): 150 | try: 151 | return self.get(name) 152 | except KeyError: 153 | raise AttributeError(name) 154 | 155 | class Si(UnitSystem): 156 | def __init__(self): 157 | baseSi = ['mol', 'm', 's', 'A', 'g', 'cd', 'K', 'bool'] 158 | UnitSystem.__init__(self, baseSi) 159 | 160 | s = list(baseSi) 161 | l = [] 162 | 163 | x='unitless'; self.register(x, self.scaleToUnit(1)) 164 | x='dimensionless'; self.register(x, self.unitless) 165 | x='1'; self.register(x, self.unitless) 166 | 167 | x='L'; s.append(x); self.register(x, self.m**3 * self.scaleToUnit(1e-3)) 168 | x='liter'; l.append(x); self.register(x, self.L) 169 | x='litre'; l.append(x); self.register(x, self.L) 170 | x='M'; s.append(x); self.register(x, self.mol / self.L) 171 | x='molar'; l.append(x); self.register(x, self.M) 172 | x='C'; s.append(x); self.register(x, self.A*self.s) 173 | x="coulumb"; l.append(x); self.register(x, self.C) 174 | x='V'; s.append(x); self.register(x, self.scaleToUnit(1e3)*self.m**2*self.g/(self.s**3*self.A)) 175 | x='volt'; l.append(x); self.register(x, self.V) 176 | x='ohm'; l.append(x); self.register(x, self.V/self.A) 177 | x='S'; s.append(x); self.register(x, self.unitless/self.ohm) 178 | x='siemen'; l.append(x); self.register(x, self.S) 179 | x='F'; s.append(x); self.register(x, self.C/self.V) 180 | x='farad'; l.append(x); self.register(x, self.F) 181 | x='N'; s.append(x); self.register(x, self.scaleToUnit(1e3)*self.m*self.g/self.s**2) 182 | x='newton'; l.append(x); self.register(x, self.N) 183 | x='J'; s.append(x); self.register(x, self.N*self.m) 184 | x='joule'; l.append(x); self.register(x,self.J) 185 | x='Pa'; s.append(x); self.register(x, self.N/self.m**2) 186 | x='pascal'; l.append(x); self.register(x,self.Pa) 187 | x='W'; s.append(x); self.register(x, self.J/self.s) 188 | x='watt'; l.append(x); self.register(x, self.W) 189 | x='Hz'; s.append(x); self.register(x, self.unitless/self.s) 190 | x='hertz'; s.append(x); self.register(x, self.Hz) 191 | 192 | x='meter'; l.append(x); self.register(x, self.m) 193 | x='metre'; l.append(x); self.register(x, self.m) 194 | x='second'; l.append(x); self.register(x, self.s) 195 | x='ampere'; l.append(x); self.register(x, self.A) 196 | x='amp'; l.append(x); self.register(x, self.A) 197 | x='gram'; l.append(x); self.register(x, self.g) 198 | x='candela'; l.append(x); self.register(x, self.cd) 199 | x='kelvin'; l.append(x); self.register(x, self.K) 200 | 201 | x='eV'; s.append(x); self.register(x, self.J*self.scaleToUnit(6.241509e-18)) 202 | x='electron_volt'; l.append(x); self.register(x, self.eV) 203 | x='cal'; s.append(x); self.register(x,self.J*self.scaleToUnit(0.239006)) 204 | x='calorie'; l.append(x); self.register(x,self.cal) 205 | x='Ang'; s.append(x); self.register(x, self.m*self.scaleToUnit(1e-10)) 206 | x='angstrom'; l.append(x); self.register(x, self.Ang) 207 | 208 | shortNames = s 209 | longNames = l 210 | 211 | shortPrefixes = { 212 | 'y': 1e-24, 213 | 'z' : 1e-21, 214 | 'a' : 1e-18, 215 | 'f' : 1e-15, 216 | 'p' : 1e-12, 217 | 'n' : 1e-9, 218 | 'u' : 1e-6, 219 | 'm' : 1e-3, 220 | 'c' : 1e-2, 221 | 'd' : 1e-1, 222 | 'da' : 1e1, 223 | 'h' : 1e2, 224 | 'k' : 1e3, 225 | 'M' : 1e6, 226 | 'G' : 1e9, 227 | 'T' : 1e12, 228 | 'P' : 1e15, 229 | 'E' : 1e18, 230 | 'Z' : 1e21, 231 | 'Y' : 1e24, 232 | } 233 | for shortName in shortNames: 234 | for (prefix,scale) in shortPrefixes.items(): 235 | self.register(prefix+shortName, self.get(shortName)*self.scaleToUnit(scale)) 236 | 237 | longPrefixes = { 238 | 'yotto': 1e-24, 239 | 'zepto' : 1e-21, 240 | 'atto' : 1e-18, 241 | 'femto' : 1e-15, 242 | 'pico' : 1e-12, 243 | 'nano' : 1e-9, 244 | 'micro' : 1e-6, 245 | 'milli' : 1e-3, 246 | 'centi' : 1e-2, 247 | 'deci' : 1e-1, 248 | 'deca' : 1e1, 249 | 'hecto' : 1e2, 250 | 'kilo' : 1e3, 251 | 'mega' : 1e6, 252 | 'giga' : 1e9, 253 | 'tera' : 1e12, 254 | 'peta' : 1e15, 255 | 'exa' : 1e18, 256 | 'zetta' : 1e21, 257 | 'yotta' : 1e24, 258 | } 259 | for longName in longNames: 260 | for (prefix, scale) in longPrefixes.items(): 261 | self.register(prefix+longName, self.get(longName)*self.scaleToUnit(scale)) 262 | 263 | self.register('cc', self.cm**3) 264 | 265 | if __name__=='__main__': 266 | si = Si() 267 | assert (si.mV/si.ms).isCompatibleWith(si.uA/si.uF) 268 | print((si.mV/si.ms).convertTo(si.uA/si.uF)-1) 269 | assert (si.mV/si.ms).convertTo(si.uA/si.uF) == 1 270 | 271 | -------------------------------------------------------------------------------- /melodee/utility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #### #### 3 | # Copyright (c) 2016-2017, Lawrence Livermore National Security, 4 | # LLC. Produced at the Lawrence Livermore National Laboratory. Written 5 | # by Robert Blake . 6 | # 7 | # LLNL-CODE-720003. 8 | # All rights reserved. 9 | # 10 | # This file is part of MELODEE. For details, see 11 | # http://github.com/llnl/melodee. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "Licensee"); you 14 | # may not use this file except in compliance with the License. You may 15 | # obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 22 | # implied. See the License for the specific language governing 23 | # permissions and limitations under the license. 24 | #### #### 25 | 26 | from __future__ import print_function 27 | import sys 28 | import re 29 | import sympy 30 | 31 | 32 | class Indenter: 33 | def __init__(self, fff=sys.stdout, indentString=" "): 34 | self.indent = indentString 35 | self.indentAmount = 0 36 | self.outfile = fff 37 | 38 | def __call__(self, string, *args, **kwargs): 39 | initialstrip = string.lstrip('\n') 40 | if not initialstrip: 41 | print(string, end='', file=self.outfile) 42 | return 43 | indentString = self.indent*self.indentAmount 44 | for line in initialstrip.split('\n'): 45 | outline = indentString+line 46 | if line == "": 47 | print("\n", end='', file=self.outfile) 48 | elif kwargs: 49 | print((outline % kwargs), file=self.outfile) 50 | elif len(args) == 1 and type(args[0]) == dict: 51 | print((outline % args[0]), file=self.outfile) 52 | elif len(args) == 1: 53 | print((outline % args[0]), file=self.outfile) 54 | elif len(args) == 0: 55 | print(outline, file=self.outfile) 56 | else: 57 | print((outline % args), file=self.outfile) 58 | 59 | def inc(self, indentAmount=1): 60 | self.indentAmount += indentAmount 61 | 62 | def dec(self, indentAmount=1): 63 | self.indentAmount -= indentAmount 64 | 65 | def order(iterable): 66 | ret = [item for item in iterable] 67 | if ret and isinstance(ret[0], sympy.Symbol): 68 | ret.sort(key=str) 69 | else: 70 | ret.sort() 71 | return ret 72 | 73 | def unzip(lll): 74 | """Does the opposite of zip""" 75 | return list(zip(*lll)) 76 | 77 | def itemsOrderedByValue(myDict): 78 | return sorted(list(myDict.items()), key=lambda x: x[1]) 79 | def itemsOrderedByKey(myDict): 80 | return sorted(list(myDict.items()), key=lambda x: x[0]) 81 | 82 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [wheel] 2 | universal = true 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | def readme(): 4 | with open('README.md') as f: 5 | return f.read() 6 | 7 | setup( 8 | name='melodee', 9 | version='0.1', 10 | description='Differential Equation Compiler for HPC', 11 | classifiers=[ 12 | 'Development Status :: 3 - Alpha', 13 | 'Intended Audience :: Developers', 14 | 'Operating System :: OS Independent', 15 | 'Programming Language :: Python', 16 | 'Programming Language :: Python 2', 17 | 'Programming Language :: Python 3', 18 | ], 19 | url='https://github.com/llnl/melodee', 20 | author='Robert Blake', 21 | author_email='blake14@llnl.gov', 22 | license='Apache-2.0', 23 | packages=['melodee'], 24 | install_requires=[ 25 | 'sympy>=1.9', 26 | 'ply', 27 | #'xml', 28 | ], 29 | zip_safe=False, 30 | entry_points = { 31 | 'console_scripts' : ['melodee=melodee.main:main', 32 | 'cellml2melodee=melodee.cellmlConverter:main', 33 | ] 34 | }, 35 | ) 36 | --------------------------------------------------------------------------------