module Modelling::CPPModel

Public Instance Methods

_eqn_matlab_to_pow(eqstr) click to toggle source

Convert matlab notation for powers (a^b) to c++ notation (pow(a,b))

# File lib/modelling/cpp.rb, line 118
def _eqn_matlab_to_pow(eqstr)
    eqstr = eqstr.clone
    if not @exprparser
        @exprparser = Modelling::MATLABExprParser.new
    end
    qs = @exprparser.transform_pows(eqstr)
    qs
end
to_cpp(basepath) click to toggle source

Write CPP file which gives the model equations

# File lib/modelling/cpp.rb, line 8
        def to_cpp(basepath)
            File.open("#{basepath}.cpp", "w") do |f|
                mname = basepath.gsub(%r((.*[\/])?([^/\]+)$), "\\2")

                f.puts <<-END
/**
 * @file #{mname}.cpp
 * 
 * Model implementation for Model '#{mname}'
 *
 */

#include <cmath>

struct Model_#{mname} {
    Model_#{mname}() {
        reset_parameters();
    }

    void reset_parameters() {
END
                @parameters.each do |n, p|
                    f.puts("\t\t#{n} = #{p.value};\n")
                end
                f.puts <<-END
    }

    void initial_state(double * y) {
END

                mno = 1
                @species = (@species.sort {|x,y| x[1].matlab_no <=> y[1].matlab_no })
                @species.each do |n, sp|
                    f.puts("\t\ty[#{sp.matlab_no}] = #{sp.initial};\n")
                    # redo matlab numbers
                    sp.matlab_no=(mno)
                    mno = mno + 1
                end
                f.puts <<-END
    }
END
                @rules.each do |rule|
                    if rule.type == 'rate' and rule.output.kind_of?(Parameter)
                        raise "Parameters cannot have rate rules"
                    end
                end
                f.puts <<-END

    // #{@notes.gsub("%%%%-cb-%%%%", "\n// ")}
    double * operator() (double t, const double * y, double * dydt) {
END
                species_eqns = []
                orig_species_eqns = []
                species_comments = []
                ((@rules.reject { |e| e.output.kind_of? Parameter})                      .sort {|x,y| x.output.matlab_no <=> y.output.matlab_no})                      .each do |rule|
                        eq = rule.equation.clone
                        @species.each do |n,s|
                            eq.replace_ident(s.name, "y[#{s.matlab_no-1}]")
                        end
                        species_comments[rule.output.matlab_no] = eq.comments.gsub("%%%%-cb-%%%%", " ")
                        orig_species_eqns[rule.output.matlab_no] = eq.to_s
                        species_eqns[rule.output.matlab_no] = _eqn_matlab_to_pow(eq.to_s)
                    end

                (@rules.reject { |e| e.output.kind_of? Species})                      .each do |rule|
                        eq = rule.equation.clone
                        @species.each do |n,s|
                            eq.replace_ident(s.name, "y(#{s.matlab_no})")
                        end

                        orig_eq = eq.to_s
                        translated_eq =  _eqn_matlab_to_pow(orig_eq)
                        f.puts ("\t\t// " + eq.comments.gsub("%%%%-cb-%%%%", " ") + "\n"                              + "\t\t// Original: #{orig_eq}"                               + "#{rule.output.name} = #{translated_eq};\n")
                    end

                f.puts("\n")

                @species.each do |n,s|
                    if species_comments[s.matlab_no]
                        f.puts("\t\t// #{species_comments[s.matlab_no]}\n")
                    end
                    f.puts("\t\t// Original: dydt[#{s.matlab_no-1}] = #{orig_species_eqns[s.matlab_no]}\n")
                    if species_eqns[s.matlab_no]
                        f.puts("\t\tdydt[#{s.matlab_no-1}] = #{species_eqns[s.matlab_no]} ;\n")
                    else
                        puts("[W] Species #{s.name} has no rate rule, setting to zero.")
                        f.puts("\t\tdydt[#{s.matlab_no-1}] = 0;\n")
                    end
                end
                f.puts <<-END
        return dydt;
    }

END
                f.puts("\tenum { NSPECIES = #{mno} };\n\n")
                @parameters.each do |n, p|
                    f.puts("\tdouble #{n};\n")
                end
                f.puts <<-END
};
END
            end
        end