Search in sources :

Example 1 with RationalExp

use of cbit.vcell.matrix.RationalExp in project vcell by virtualcell.

the class StructureSizeSolver method updateAbsoluteStructureSizes.

public static void updateAbsoluteStructureSizes(SimulationContext simContext, Structure struct, double structSize, VCUnitDefinition structSizeUnit) throws Exception {
    StructureMapping[] structMappings = simContext.getGeometryContext().getStructureMappings();
    try {
        StructureTopology structTopology = simContext.getModel().getStructureTopology();
        SolverParameterCollection solverParameters = new SolverParameterCollection();
        ArrayList<String> unknownVars = new ArrayList<String>();
        for (StructureMapping sm : structMappings) {
            if (sm.getStructure() instanceof Membrane) {
                MembraneMapping mm = (MembraneMapping) sm;
                StructureMappingParameter svRatioParam = mm.getSurfaceToVolumeParameter();
                StructureMappingParameter volFractParam = mm.getVolumeFractionParameter();
                StructureMappingParameter sizeParam = mm.getSizeParameter();
                solverParameters.add(new SolverParameter(svRatioParam, TokenMangler.mangleToSName("sv_" + mm.getMembrane().getName()), svRatioParam.getExpression().evaluateConstant()));
                solverParameters.add(new SolverParameter(volFractParam, TokenMangler.mangleToSName("vf_" + mm.getMembrane().getName()), volFractParam.getExpression().evaluateConstant()));
            }
            StructureMappingParameter sizeParam = sm.getSizeParameter();
            Double priorKnownValue = null;
            String varName = TokenMangler.mangleToSName("size_" + sm.getStructure().getName());
            if (sizeParam.getExpression() != null) {
                priorKnownValue = sizeParam.getExpression().evaluateConstant();
            } else if (sm.getStructure() == struct) {
                priorKnownValue = structSize;
            } else {
                unknownVars.add(varName);
            }
            solverParameters.add(new SolverParameter(sizeParam, varName, priorKnownValue));
        }
        ArrayList<Expression> expressions = new ArrayList<Expression>();
        for (int i = 0; i < structMappings.length; i++) {
            if (structMappings[i] instanceof MembraneMapping) {
                MembraneMapping membraneMapping = (MembraneMapping) structMappings[i];
                Feature insideFeature = structTopology.getInsideFeature(membraneMapping.getMembrane());
                Feature outsideFeature = structTopology.getOutsideFeature(membraneMapping.getMembrane());
                StructureMappingParameter sizeParameter = membraneMapping.getSizeParameter();
                StructureMappingParameter volFractParameter = membraneMapping.getVolumeFractionParameter();
                StructureMappingParameter surfToVolParameter = membraneMapping.getSurfaceToVolumeParameter();
                // 
                // EC eclosing cyt, which contains er and golgi
                // "(cyt_size+ er_size + golgi_size) * cyt_svRatio - PM_size"  ... implicit equation, exp == 0 is implied
                // 
                Expression sumOfInsideVolumeExp = new Expression(0.0);
                for (int j = 0; j < structMappings.length; j++) {
                    if (structMappings[j] instanceof FeatureMapping && structTopology.enclosedBy(structMappings[j].getStructure(), insideFeature)) {
                        FeatureMapping childFeatureMappingOfInside = ((FeatureMapping) structMappings[j]);
                        sumOfInsideVolumeExp = Expression.add(sumOfInsideVolumeExp, new Expression(solverParameters.getName(childFeatureMappingOfInside.getSizeParameter())));
                    }
                }
                Expression tempExpr = Expression.mult(sumOfInsideVolumeExp, new Expression(solverParameters.getName(surfToVolParameter)));
                tempExpr = Expression.add(tempExpr, new Expression("-" + solverParameters.getName(sizeParameter)));
                expressions.add(tempExpr);
                // 
                // EC eclosing cyt, which contains er and golgi
                // (EC_size + cyt_size + er_size + golgi_size) * cyt_vfRatio - (cyt_size + er_size + golgi_size)  ... implicit equation, exp == 0 is implied
                // 
                Expression sumOfParentVolumeExp = new Expression(0.0);
                for (int j = 0; j < structMappings.length; j++) {
                    if (structMappings[j] instanceof FeatureMapping && structTopology.enclosedBy(structMappings[j].getStructure(), outsideFeature)) {
                        FeatureMapping childFeatureMappingOfParent = ((FeatureMapping) structMappings[j]);
                        sumOfParentVolumeExp = Expression.add(sumOfParentVolumeExp, new Expression(TokenMangler.mangleToSName(solverParameters.getName(childFeatureMappingOfParent.getSizeParameter()))));
                    }
                }
                Expression exp = Expression.mult(sumOfParentVolumeExp, new Expression(solverParameters.getName(volFractParameter)));
                exp = Expression.add(exp, Expression.negate(sumOfInsideVolumeExp));
                expressions.add(exp);
            }
        }
        if (expressions.size() != unknownVars.size()) {
            throw new RuntimeException("number of unknowns is " + unknownVars.size() + ", number of equations is " + expressions.size());
        }
        if (unknownVars.size() == 0 && expressions.size() == 0) {
            StructureMappingParameter sizeParam = simContext.getGeometryContext().getStructureMapping(struct).getSizeParameter();
            sizeParam.setExpression(new Expression(structSize));
            return;
        }
        RationalExp[][] rowColData = new RationalExp[unknownVars.size()][unknownVars.size() + 1];
        for (int row = 0; row < unknownVars.size(); row++) {
            // 
            // verify that there is no "constant" term (without an unknown)
            // 
            // System.out.println("equation("+row+"): "+expressions.get(row).infix());
            Expression constantTerm = new Expression(expressions.get(row));
            for (String var : unknownVars) {
                constantTerm.substituteInPlace(new Expression(var), new Expression(0.0));
            }
            constantTerm = constantTerm.flatten();
            // 
            for (int col = 0; col < unknownVars.size(); col++) {
                Expression equation = new Expression(expressions.get(row));
                String colVariable = unknownVars.get(col);
                Expression deriv = equation.differentiate(colVariable).flatten();
                String[] symbols = deriv.getSymbols();
                if (symbols != null) {
                    for (String symbol : symbols) {
                        if (unknownVars.contains(symbol)) {
                            throw new RuntimeException("equation is not linear in the unknowns");
                        }
                    }
                }
                rowColData[row][col] = RationalExpUtils.getRationalExp(deriv);
            }
            rowColData[row][unknownVars.size()] = RationalExpUtils.getRationalExp(constantTerm).minus();
        }
        RationalExpMatrix rationalExpMatrix = new RationalExpMatrix(rowColData);
        // rationalExpMatrix.show();
        RationalExp[] solutions = rationalExpMatrix.solveLinearExpressions();
        double[] solutionValues = new double[solutions.length];
        for (int i = 0; i < unknownVars.size(); i++) {
            Expression vcSolution = new Expression(solutions[i].infixString());
            String[] symbols = vcSolution.getSymbols();
            if (symbols != null) {
                for (String symbol : symbols) {
                    SolverParameter p = solverParameters.get(symbol);
                    if (p.knownValue == null) {
                        throw new RuntimeException("solution for var " + unknownVars.get(i) + " is a function of unknown var " + p.name);
                    }
                    vcSolution.substituteInPlace(new Expression(symbol), new Expression(p.knownValue.doubleValue()));
                }
            }
            double value = vcSolution.flatten().evaluateConstant();
            // System.out.println(unknownVars.get(i)+" = "+value+" = "+solutions[i].infixString());
            solutionValues[i] = value;
        }
        for (int i = 0; i < unknownVars.size(); i++) {
            SolverParameter p = solverParameters.get(unknownVars.get(i));
            p.parameter.setExpression(new Expression(solutionValues[i]));
        }
        // 
        // set the one known value (if not set already by the gui).
        // 
        StructureMappingParameter sizeParam = simContext.getGeometryContext().getStructureMapping(struct).getSizeParameter();
        sizeParam.setExpression(new Expression(structSize));
        System.out.println("done");
    } catch (ExpressionException e) {
        e.printStackTrace(System.out);
        throw new Exception(e.getMessage());
    }
}
Also used : MembraneMapping(cbit.vcell.mapping.MembraneMapping) ArrayList(java.util.ArrayList) StructureMappingParameter(cbit.vcell.mapping.StructureMapping.StructureMappingParameter) StructureMapping(cbit.vcell.mapping.StructureMapping) Feature(cbit.vcell.model.Feature) ExpressionException(cbit.vcell.parser.ExpressionException) FeatureMapping(cbit.vcell.mapping.FeatureMapping) RationalExpMatrix(cbit.vcell.matrix.RationalExpMatrix) Membrane(cbit.vcell.model.Membrane) StructureTopology(cbit.vcell.model.Model.StructureTopology) RationalExp(cbit.vcell.matrix.RationalExp) AbstractConstraint(cbit.vcell.constraints.AbstractConstraint) GeneralConstraint(cbit.vcell.constraints.GeneralConstraint) ExpressionException(cbit.vcell.parser.ExpressionException) Expression(cbit.vcell.parser.Expression)

Example 2 with RationalExp

use of cbit.vcell.matrix.RationalExp in project vcell by virtualcell.

the class RationalExpUtils method getRationalExp.

private static RationalExp getRationalExp(SimpleNode node, boolean bAllowFunctions) throws ExpressionException {
    if (node == null) {
        return null;
    }
    if (node instanceof ASTAndNode || node instanceof ASTOrNode || node instanceof ASTNotNode || node instanceof ASTRelationalNode || node instanceof DerivativeNode || node instanceof ASTLaplacianNode) {
        throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression");
    } else if (node instanceof ASTFuncNode) {
        if (((ASTFuncNode) node).getFunction() == FunctionType.POW) {
            try {
                double constantExponent = node.jjtGetChild(1).evaluateConstant();
                if (constantExponent != Math.floor(constantExponent)) {
                    throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression, exponent is not an integer");
                }
                int intExponent = (int) constantExponent;
                if (intExponent == 0) {
                    return RationalExp.ONE;
                }
                RationalExp base = getRationalExp((SimpleNode) node.jjtGetChild(0), bAllowFunctions);
                if (intExponent < 0) {
                    base = base.inverse();
                    intExponent = -intExponent;
                }
                RationalExp baseUnit = new RationalExp(base);
                for (int i = 1; i < intExponent; i++) {
                    base = base.mult(baseUnit);
                }
                return base;
            } catch (ExpressionException e) {
                throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression, exponent is not constant");
            }
        } else {
            if (bAllowFunctions) {
                return new RationalExp(((ASTFuncNode) node).infixString(SimpleNode.LANGUAGE_DEFAULT));
            } else {
                throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression");
            }
        }
    } else if (node instanceof ASTPowerNode) {
        try {
            double constantExponent = node.jjtGetChild(1).evaluateConstant();
            if (constantExponent != Math.floor(constantExponent)) {
                throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression, exponent is not an integer");
            }
            int intExponent = (int) constantExponent;
            if (intExponent == 0) {
                return RationalExp.ONE;
            }
            RationalExp base = getRationalExp((SimpleNode) node.jjtGetChild(0), bAllowFunctions);
            if (intExponent < 0) {
                base = base.inverse();
                intExponent = -intExponent;
            }
            RationalExp baseUnit = new RationalExp(base);
            for (int i = 1; i < intExponent; i++) {
                base = base.mult(baseUnit);
            }
            return base;
        } catch (ExpressionException e) {
            throw new ExpressionException("sub-expression " + node.infixString(SimpleNode.LANGUAGE_DEFAULT) + " cannot be translated to a Rational Expression, exponent is not constant");
        }
    } else if (node instanceof ASTAddNode) {
        RationalExp exp = RationalExp.ZERO;
        for (int i = 0; i < node.jjtGetNumChildren(); i++) {
            exp = exp.add(getRationalExp((SimpleNode) node.jjtGetChild(i), bAllowFunctions));
        }
        return exp;
    } else if (node instanceof ASTMinusTermNode) {
        return getRationalExp((SimpleNode) node.jjtGetChild(0), bAllowFunctions).minus();
    } else if (node instanceof ASTMultNode) {
        if (node.jjtGetNumChildren() == 1) {
            return getRationalExp((SimpleNode) node.jjtGetChild(0), bAllowFunctions);
        }
        RationalExp exp = RationalExp.ONE;
        for (int i = 0; i < node.jjtGetNumChildren(); i++) {
            exp = exp.mult(getRationalExp((SimpleNode) node.jjtGetChild(i), bAllowFunctions));
        }
        return exp;
    } else if (node instanceof ASTInvertTermNode) {
        SimpleNode child = (SimpleNode) node.jjtGetChild(0);
        return getRationalExp(child, bAllowFunctions).inverse();
    } else if (node instanceof ASTFloatNode) {
        // return TBD instead of dimensionless.
        RationalNumber r = RationalNumber.getApproximateFraction(((ASTFloatNode) node).value.doubleValue());
        return new RationalExp(r);
    // } else if (node instanceof ASTFuncNode) {
    // String functionName = ((ASTFuncNode)node).getName();
    // if (functionName.equalsIgnoreCase("pow")) {
    // SimpleNode child0 =  (SimpleNode)node.jjtGetChild(0);
    // SimpleNode child1 =  (SimpleNode)node.jjtGetChild(1);
    // VCUnitDefinition unit0 = getRationalExp(child0);
    // VCUnitDefinition unit1 = getRationalExp(child1);
    // if (!unit1.compareEqual(VCUnitDefinition.UNIT_DIMENSIONLESS) && !unit1.compareEqual(VCUnitDefinition.UNIT_TBD)){
    // throw new VCUnitException("exponent of '"+node.infixString(SimpleNode.LANGUAGE_DEFAULT,SimpleNode.NAMESCOPE_DEFAULT)+"' has units of "+unit0);
    // }
    // if (unit0.compareEqual(VCUnitDefinition.UNIT_DIMENSIONLESS) || unit0.isTBD()){
    // return unit0;
    // }
    // try {
    // double d = ((SimpleNode)node.jjtGetChild(1)).evaluateConstant();
    // RationalNumber rn = RationalNumber.getApproximateFraction(d);
    // return unit0.raiseTo(rn);
    // }catch(ExpressionException e){
    // return VCUnitDefinition.UNIT_TBD;  // ????? don't know the unit now
    // }
    // }
    // } else if (node instanceof ASTPowerNode) {
    // SimpleNode child0 =  (SimpleNode)node.jjtGetChild(0);
    // SimpleNode child1 =  (SimpleNode)node.jjtGetChild(1);
    // VCUnitDefinition unit0 = getRationalExp(child0);
    // VCUnitDefinition unit1 = getRationalExp(child1);
    // if (!unit1.compareEqual(VCUnitDefinition.UNIT_DIMENSIONLESS) && !unit1.compareEqual(VCUnitDefinition.UNIT_TBD)){
    // throw new VCUnitException("exponent of '"+node.infixString(SimpleNode.LANGUAGE_DEFAULT,SimpleNode.NAMESCOPE_DEFAULT)+"' has units of "+unit0);
    // }
    // if (unit0.compareEqual(VCUnitDefinition.UNIT_DIMENSIONLESS)){
    // return VCUnitDefinition.UNIT_DIMENSIONLESS;
    // }
    // boolean bConstantExponent = false;
    // double exponentValue = 1;
    // try {
    // exponentValue = child1.evaluateConstant();
    // bConstantExponent = true;
    // }catch(ExpressionException e){
    // bConstantExponent = false;
    // }
    // if (bConstantExponent){ //
    // if (unit0.isTBD()){
    // return VCUnitDefinition.UNIT_TBD;
    // }else{
    // RationalNumber rn = RationalNumber.getApproximateFraction(exponentValue);
    // return unit0.raiseTo(rn);
    // }
    // }else{
    // return VCUnitDefinition.UNIT_TBD;
    // }
    } else if (node instanceof ASTIdNode) {
        return new RationalExp(((ASTIdNode) node).name);
    } else {
        throw new ExpressionException("node type " + node.getClass().toString() + " not supported yet");
    }
}
Also used : RationalExp(cbit.vcell.matrix.RationalExp) RationalNumber(cbit.vcell.matrix.RationalNumber)

Example 3 with RationalExp

use of cbit.vcell.matrix.RationalExp in project vcell by virtualcell.

the class PotentialMapping method determineLumpedEquations.

/**
 * Insert the method's description here.
 * Creation date: (2/20/2002 9:02:42 AM)
 * @return cbit.vcell.mathmodel.MathModel
 * @param circuitGraph cbit.vcell.mapping.potential.Graph
 */
private void determineLumpedEquations(Graph graph, double temperatureKelvin) throws ExpressionException, MatrixException, MappingException, MathException {
    // 
    // traverses graph and calculates RHS expressions for all capacitive devices (dV/dt)
    // 
    // calculate dependent voltages as functions of independent voltages.
    // 
    // 
    Graph[] spanningTrees = graph.getSpanningForest();
    if (!bSilent) {
        System.out.println("spanning tree(s):");
        for (int i = 0; i < spanningTrees.length; i++) {
            System.out.println(i + ") " + spanningTrees[i]);
        }
    }
    Path[] fundamentalCycles = graph.getFundamentalCycles();
    if (!bSilent) {
        System.out.println("fundamental cycles:");
        for (int i = 0; i < fundamentalCycles.length; i++) {
            System.out.println("   " + fundamentalCycles[i]);
        }
    }
    // 
    // print out basic device information
    // 
    fieldEdges = graph.getEdges();
    // 
    if (!bSilent) {
        System.out.println("\n\n applying KVL to <<ALL>> fundamental cycles\n");
    }
    Path[] graphCycles = graph.getFundamentalCycles();
    RationalExpMatrix voltageMatrix = new RationalExpMatrix(graphCycles.length, graph.getNumEdges());
    for (int i = 0; i < graphCycles.length; i++) {
        Edge[] cycleEdges = graphCycles[i].getEdges();
        Node[] nodesTraversed = graphCycles[i].getNodesTraversed();
        Expression exp = new Expression(0.0);
        // 
        for (int j = 0; j < cycleEdges.length; j++) {
            int edgeIndex = graph.getIndex(cycleEdges[j]);
            Expression voltage = new Expression(((ElectricalDevice) cycleEdges[j].getData()).getVoltageSymbol(), fieldMathMapping.getNameScope());
            if (cycleEdges[j].getNode1().equals(nodesTraversed[j])) {
                // going same direction
                exp = Expression.add(exp, voltage);
                voltageMatrix.set_elem(i, edgeIndex, 1);
            } else {
                // going opposite direction
                exp = Expression.add(exp, Expression.negate(voltage));
                voltageMatrix.set_elem(i, edgeIndex, -1);
            }
        }
        if (!bSilent) {
            System.out.println(exp.flatten().infix() + " = 0.0");
        }
    }
    if (!bSilent) {
        voltageMatrix.show();
    }
    if (voltageMatrix.getNumRows() > 0) {
        RationalExpMatrix vPermutationMatrix = new RationalExpMatrix(voltageMatrix.getNumRows(), voltageMatrix.getNumRows());
        voltageMatrix.gaussianElimination(vPermutationMatrix);
        if (!bSilent) {
            System.out.println("reduced matrix");
            voltageMatrix.show();
        }
    } else {
        voltageMatrix = null;
    }
    // 
    // declare dependent voltages as functions of independent voltages
    // 
    // 1) Always use Voltage-Clamps as independent voltages
    // 2) Try to use Capacitive devices as independent voltages
    // 
    // solve for current-clamp voltages and redundant/constrained capacitive voltages as function of (1) and (2).
    // 
    Expression[] dependentVoltageExpressions = new Expression[fieldEdges.length];
    // 
    // make sure assumptions hold regarding edge ordering, otherwise wrong dependent voltages will be selected
    // 
    verifyEdgeOrdering();
    for (int i = 0; voltageMatrix != null && i < voltageMatrix.getNumRows(); i++) {
        // 
        // find first '1.0' element, this column is the next 'dependent' voltage
        // 
        int column = -1;
        for (int j = i; j < voltageMatrix.getNumCols(); j++) {
            RationalExp elem = voltageMatrix.get(i, j);
            if (elem.isConstant() && elem.getConstant().doubleValue() == 1.0) {
                column = j;
                break;
            }
        }
        if (column != -1) {
            // 
            // get electrical device of dependent voltage
            // 
            ElectricalDevice device = (ElectricalDevice) fieldEdges[column].getData();
            // 
            // form dependency expression
            // 
            StringBuffer buffer = new StringBuffer();
            for (int j = column + 1; j < graph.getNumEdges(); j++) {
                if (!voltageMatrix.get_elem(i, j).isZero()) {
                    ElectricalDevice colDevice = (ElectricalDevice) fieldEdges[j].getData();
                    Expression voltage = new Expression(colDevice.getVoltageSymbol(), fieldMathMapping.getNameScope());
                    buffer.append(" + " + voltageMatrix.get(i, j).minus().infixString() + '*' + voltage.infix());
                }
            }
            dependentVoltageExpressions[column] = (new Expression(buffer.toString())).flatten();
            dependentVoltageExpressions[column].bindExpression(device);
            device.setDependentVoltageExpression(dependentVoltageExpressions[column]);
        }
    }
    if (!bSilent) {
        for (int i = 0; i < dependentVoltageExpressions.length; i++) {
            System.out.println("dependentVoltageExpressions[" + i + "] = " + dependentVoltageExpressions[i]);
        }
    }
    // 
    if (!bSilent) {
        System.out.println("\n\nSOLVE FOR TOTAL CURRENTS IN TERMS OF APPLIED CURRENTS");
        System.out.println("\n\n  1)  applying KVL to all fundamental \"capacitive\" and Voltage-clamp cycles (after current-clamp edges are removed)\n");
    }
    Graph capacitorGraph = new Graph();
    for (int i = 0; i < fieldEdges.length; i++) {
        ElectricalDevice device = (ElectricalDevice) fieldEdges[i].getData();
        if (device.hasCapacitance() || device.isVoltageSource()) {
            capacitorGraph.addEdge(fieldEdges[i]);
        }
    }
    Path[] capacitorGraphCycles = capacitorGraph.getFundamentalCycles();
    RationalExpMatrix capacitorGraphVoltageMatrix = new RationalExpMatrix(capacitorGraphCycles.length, graph.getNumEdges());
    for (int i = 0; i < capacitorGraphCycles.length; i++) {
        Edge[] cycleEdges = capacitorGraphCycles[i].getEdges();
        Node[] nodesTraversed = capacitorGraphCycles[i].getNodesTraversed();
        Expression exp = new Expression(0.0);
        // 
        for (int j = 0; j < cycleEdges.length; j++) {
            int edgeIndex = graph.getIndex(cycleEdges[j]);
            Expression voltage = new Expression(((ElectricalDevice) cycleEdges[j].getData()).getVoltageSymbol(), fieldMathMapping.getNameScope());
            if (cycleEdges[j].getNode1().equals(nodesTraversed[j])) {
                // going same direction
                exp = Expression.add(exp, voltage);
                capacitorGraphVoltageMatrix.set_elem(i, edgeIndex, 1);
            } else {
                // going opposite direction
                exp = Expression.add(exp, Expression.negate(voltage));
                capacitorGraphVoltageMatrix.set_elem(i, edgeIndex, -1);
            }
        }
        if (!bSilent) {
            System.out.println(exp.flatten().infix() + " = 0.0");
        }
    }
    if (!bSilent) {
        capacitorGraphVoltageMatrix.show();
    }
    // 
    if (!bSilent) {
        System.out.println("\n\n  2)  applying KCL to all nodes (except one) .. n-1 nodes of full graph  --- CONSERVATION OF TOTAL CURRENT\n");
    }
    Node[] nodes = graph.getNodes();
    RationalExpMatrix kclMatrix = new RationalExpMatrix(graph.getNumNodes() - 1, graph.getNumEdges());
    for (int i = 0; i < nodes.length - 1; i++) {
        if (graph.getDegree(nodes[i]) > 0) {
            Edge[] adjacentEdges = graph.getAdjacentEdges(nodes[i]);
            Expression exp = new Expression(0.0);
            // 
            for (int j = 0; j < adjacentEdges.length; j++) {
                int edgeIndex = graph.getIndex(adjacentEdges[j]);
                Expression totalCurrent = new Expression(((ElectricalDevice) adjacentEdges[j].getData()).getTotalCurrentSymbol(), fieldMathMapping.getNameScope());
                if (adjacentEdges[j].getNode1().equals(nodes[i])) {
                    exp = Expression.add(exp, Expression.negate(totalCurrent));
                    kclMatrix.set_elem(i, edgeIndex, -1);
                } else {
                    exp = Expression.add(exp, totalCurrent);
                    kclMatrix.set_elem(i, edgeIndex, 1);
                }
            }
            if (!bSilent) {
                System.out.println(exp.flatten().infix() + " = 0.0");
            }
        } else {
            throw new MappingException("compartment '" + nodes[i].getName() + "' is electrically isolated, cannot generate ciruit equations for application '" + fieldSimContext.getName() + "'.  \n\nPlease specify electrical properties for all membranes (see Structures tab in Physiology).");
        }
    }
    if (!bSilent) {
        kclMatrix.show();
    }
    // 
    if (!bSilent) {
        System.out.println("\n\n  3)  form total 'current' matrix\n");
    }
    int numNonCapacitiveEdges = 0;
    for (int i = 0; i < fieldEdges.length; i++) {
        ElectricalDevice device = (ElectricalDevice) fieldEdges[i].getData();
        if (!device.hasCapacitance()) {
            numNonCapacitiveEdges++;
        }
    }
    int cmat_rows = kclMatrix.getNumRows() + capacitorGraphVoltageMatrix.getNumRows() + numNonCapacitiveEdges;
    RationalExpMatrix currentMatrix = new RationalExpMatrix(cmat_rows, 3 * graph.getNumEdges());
    // 
    // order edges for current elimination (unknown voltage-clamp currents as well as all total currents).
    // 
    int[] cIndex = new int[fieldEdges.length];
    int ci = 0;
    for (int i = 0; i < fieldEdges.length; i++) {
        if (((ElectricalDevice) fieldEdges[i].getData()).isVoltageSource()) {
            cIndex[ci++] = i;
        }
    }
    for (int i = 0; i < fieldEdges.length; i++) {
        if (!((ElectricalDevice) fieldEdges[i].getData()).isVoltageSource()) {
            cIndex[ci++] = i;
        }
    }
    if (ci != fieldEdges.length) {
        throw new RuntimeException("error computing current indexes");
    }
    if (!bSilent) {
        System.out.println("reordered devices for current matrix elimination");
        for (int i = 0; i < cIndex.length; i++) {
            Expression voltage = new Expression(((ElectricalDevice) fieldEdges[cIndex[i]].getData()).getVoltageSymbol(), fieldMathMapping.getNameScope());
            System.out.println(i + ") = device[" + cIndex[i] + "] = " + voltage.infix());
        }
    }
    int row = 0;
    // 
    for (int i = 0; i < kclMatrix.getNumRows(); i++) {
        for (int j = 0; j < kclMatrix.getNumCols(); j++) {
            // entry for i's
            currentMatrix.set_elem(row, j, kclMatrix.get(i, cIndex[j]));
        }
        row++;
    }
    // 
    for (int i = 0; i < fieldEdges.length; i++) {
        ElectricalDevice device = (ElectricalDevice) fieldEdges[cIndex[i]].getData();
        if (!device.hasCapacitance()) {
            currentMatrix.set_elem(row, i, 1);
            currentMatrix.set_elem(row, i + graph.getNumEdges(), -1);
            row++;
        }
    }
    // 
    // add current terms of (i - F)*1000/C form using KVL relationships from "capacitor graph"
    // 
    ModelUnitSystem modelUnitSystem = fieldMathMapping.getSimulationContext().getModel().getUnitSystem();
    VCUnitDefinition potentialUnit = modelUnitSystem.getVoltageUnit();
    VCUnitDefinition timeUnit = modelUnitSystem.getTimeUnit();
    for (int i = 0; i < capacitorGraphVoltageMatrix.getNumRows(); i++) {
        for (int j = 0; j < capacitorGraphVoltageMatrix.getNumCols(); j++) {
            ElectricalDevice device = (ElectricalDevice) fieldEdges[cIndex[j]].getData();
            RationalExp coefficient = capacitorGraphVoltageMatrix.get(i, cIndex[j]);
            if (device.hasCapacitance()) {
                // 
                // replace dVi/dt  with   1000/Ci * Ii  +  1000/Ci * Fi
                // 
                SymbolTableEntry capacitanceParameter = ((MembraneElectricalDevice) device).getCapacitanceParameter();
                Expression capacitance = new Expression(capacitanceParameter, fieldMathMapping.getNameScope());
                String Cname = capacitance.infix();
                VCUnitDefinition unitFactor = potentialUnit.divideBy(timeUnit).multiplyBy(capacitanceParameter.getUnitDefinition()).divideBy(device.getTotalCurrentSymbol().getUnitDefinition());
                RationalExp unitFactorExp = fieldMathMapping.getUnitFactorAsRationalExp(unitFactor);
                // entry for i's
                currentMatrix.set_elem(row, j, coefficient.mult(unitFactorExp.div(new RationalExp(Cname))));
                // entry for F's
                currentMatrix.set_elem(row, j + graph.getNumEdges(), coefficient.minus().mult(unitFactorExp).div(new RationalExp(Cname)));
            } else if (device.isVoltageSource()) {
                // 
                // directly insert "symbolic" dVi/dt into the new matrix
                // 
                currentMatrix.set_elem(row, j + 2 * graph.getNumEdges(), coefficient);
            }
        }
        row++;
    }
    if (!bSilent) {
        currentMatrix.show();
    }
    if (currentMatrix.getNumRows() > 0) {
        RationalExpMatrix cPermutationMatrix = new RationalExpMatrix(currentMatrix.getNumRows(), currentMatrix.getNumRows());
        currentMatrix.gaussianElimination(cPermutationMatrix);
        if (!bSilent) {
            System.out.println("reduced matrix");
            currentMatrix.show();
        }
    }
    // 
    if (!bSilent) {
        System.out.println("\n\n total currents for each device\n");
    }
    Expression[] totalCurrents = new Expression[fieldEdges.length];
    for (int i = 0; i < fieldEdges.length; i++) {
        ElectricalDevice device = (ElectricalDevice) fieldEdges[cIndex[i]].getData();
        StringBuffer buffer = new StringBuffer("0.0");
        // 
        for (int j = 0; j < graph.getNumEdges(); j++) {
            RationalExp coefficient = currentMatrix.get(i, j + graph.getNumEdges());
            if (!coefficient.isZero()) {
                ElectricalDevice colDevice = (ElectricalDevice) fieldEdges[cIndex[j]].getData();
                Expression source = new Expression(colDevice.getSourceSymbol(), fieldMathMapping.getNameScope());
                buffer.append(" + " + coefficient.minus() + "*" + source.infix());
            }
        }
        // 
        for (int j = 0; j < graph.getNumEdges(); j++) {
            RationalExp coefficient = currentMatrix.get(i, j + 2 * graph.getNumEdges());
            if (!coefficient.isZero()) {
                VoltageClampElectricalDevice colDevice = (VoltageClampElectricalDevice) fieldEdges[cIndex[j]].getData();
                Expression timeDeriv = colDevice.getVoltageClampStimulus().getVoltageParameter().getExpression().differentiate("t");
                timeDeriv = timeDeriv.flatten();
                timeDeriv.bindExpression(colDevice);
                timeDeriv.renameBoundSymbols(colDevice.getNameScope().getParent());
                buffer.append(" + " + coefficient.minus() + "*" + timeDeriv.infix());
            }
        }
        totalCurrents[cIndex[i]] = (new Expression(buffer.toString())).flatten();
        totalCurrents[cIndex[i]].bindExpression(device.getNameScope().getParent().getScopedSymbolTable());
        device.getParameterFromRole(ElectricalDevice.ROLE_TotalCurrent).setExpression(totalCurrents[cIndex[i]]);
    }
    if (!bSilent) {
        for (int i = 0; i < totalCurrents.length; i++) {
            System.out.println("totalCurrents[" + i + "] = " + totalCurrents[cIndex[i]].toString());
        }
    }
    // 
    if (!bSilent) {
        System.out.println("\n\n capacitive currents for each device\n");
    }
    Expression[] capacitiveCurrents = new Expression[fieldEdges.length];
    for (int i = 0; i < fieldEdges.length; i++) {
        ElectricalDevice device = (ElectricalDevice) fieldEdges[i].getData();
        if (device instanceof MembraneElectricalDevice) {
            MembraneElectricalDevice membraneElectricalDevice = (MembraneElectricalDevice) device;
            Expression source = new Expression(membraneElectricalDevice.getSourceSymbol(), fieldMathMapping.getNameScope());
            capacitiveCurrents[i] = Expression.add(totalCurrents[i], Expression.negate(source));
            capacitiveCurrents[i].bindExpression(membraneElectricalDevice);
        // membraneElectricalDevice.setCapacitiveCurrentExpression(capacitiveCurrents[i]);
        } else {
        // device.setCapacitiveCurrentExpression(new Expression(0.0));
        }
    }
    if (!bSilent) {
        for (int i = 0; i < capacitiveCurrents.length; i++) {
            System.out.println("capacitiveCurrents[" + i + "] = " + ((capacitiveCurrents[cIndex[i]] == null) ? "0.0" : capacitiveCurrents[cIndex[i]].infix()));
        }
    }
// 
// display equations for independent voltages.
// 
// if (!bSilent){
// for (int i = 0; i < graph.getNumEdges(); i++){
// ElectricalDevice device = (ElectricalDevice)graph.getEdges()[i].getData();
// //
// // membrane ode
// //
// if (device.hasCapacitance() && dependentVoltageExpressions[i]==null){
// Expression initExp = new Expression(0.0);
// System.out.println(device.getInitialVoltageFunction().getVCML());
// System.out.println((new cbit.vcell.math.OdeEquation(new cbit.vcell.math.VolVariable(device.getVName()),new Expression(device.getInitialVoltageFunction().getName()),new Expression(fieldCapacitiveCurrent[i].flatten().toString()+"*"+cbit.vcell.model.ReservedSymbol.KMILLIVOLTS.getName()+"/"+device.getCapName()))).getVCML());
// }
// //
// // membrane forced potential
// //
// if (device.hasCapacitance() && dependentVoltageExpressions[i]!=null){
// System.out.println((new Function(device.getVName(),dependentVoltageExpressions[i])).getVCML());
// System.out.println((new Function(device.getSourceName(),device.getCurrentSourceExpression()).getVCML()));
// }
// //
// // current clamp
// //
// if (!device.hasCapacitance() && !device.isVoltageSource()){
// System.out.println((new Function(device.getSourceName(),device.getCurrentSourceExpression()).getVCML()));
// System.out.println((new Function(device.getVName(),dependentVoltageExpressions[i])).getVCML());
// }
// //
// // voltage clamp
// //
// if (!device.hasCapacitance() && device.isVoltageSource()){
// System.out.println((new Function(device.getIName(),totalCurrents[i])).getVCML());
// System.out.println((new Function(device.getVName(),device.getInitialVoltageFunction().getExpression())).getVCML());
// }
// }
// }
}
Also used : Path(cbit.util.graph.Path) Node(cbit.util.graph.Node) RationalExp(cbit.vcell.matrix.RationalExp) MappingException(cbit.vcell.mapping.MappingException) VCUnitDefinition(cbit.vcell.units.VCUnitDefinition) SymbolTableEntry(cbit.vcell.parser.SymbolTableEntry) Graph(cbit.util.graph.Graph) RationalExpMatrix(cbit.vcell.matrix.RationalExpMatrix) Expression(cbit.vcell.parser.Expression) Edge(cbit.util.graph.Edge) ModelUnitSystem(cbit.vcell.model.ModelUnitSystem)

Example 4 with RationalExp

use of cbit.vcell.matrix.RationalExp in project vcell by virtualcell.

the class AbstractMathMapping method getUnitFactorAsRationalExp.

/**
 * This method was created in VisualAge.
 * @return Expression
 */
public RationalExp getUnitFactorAsRationalExp(VCUnitDefinition unitFactor) {
    if (unitFactor.isEquivalent(getSimulationContext().getModel().getUnitSystem().getInstance_DIMENSIONLESS())) {
        return RationalExp.ONE;
    }
    for (MathMappingParameter p : fieldMathMappingParameters) {
        if (p instanceof UnitFactorParameter && p.getUnitDefinition().isEquivalent(unitFactor)) {
            return new RationalExp(p.getName());
        }
    }
    RationalNumber factor = unitFactor.getDimensionlessScale();
    String name = PARAMETER_K_UNITFACTOR_PREFIX + TokenMangler.fixTokenStrict(unitFactor.getSymbol().replace("-", "_neg_"));
    UnitFactorParameter unitFactorParameter = new UnitFactorParameter(name, new Expression(factor), unitFactor);
    MathMappingParameter[] newMathMappingParameters = (MathMappingParameter[]) BeanUtils.addElement(this.fieldMathMappingParameters, unitFactorParameter);
    try {
        setMathMapppingParameters(newMathMappingParameters);
    } catch (java.beans.PropertyVetoException e) {
        e.printStackTrace(System.out);
        throw new RuntimeException(e.getMessage());
    }
    return new RationalExp(factor);
}
Also used : PropertyVetoException(java.beans.PropertyVetoException) Expression(cbit.vcell.parser.Expression) RationalExp(cbit.vcell.matrix.RationalExp) RationalNumber(cbit.vcell.matrix.RationalNumber)

Example 5 with RationalExp

use of cbit.vcell.matrix.RationalExp in project vcell by virtualcell.

the class MassActionSolver method solveMassAction.

public static MassActionFunction solveMassAction(Parameter optionalForwardRateParameter, Parameter optionalReverseRateParameter, Expression orgExp, ReactionStep rs) throws ExpressionException, ModelException, DivideByZeroException {
    MassActionFunction maFunc = new MassActionFunction();
    // get reactants, products, overlaps, non-overlap reactants and non-overlap products
    ArrayList<ReactionParticipant> reactants = new ArrayList<ReactionParticipant>();
    ArrayList<ReactionParticipant> products = new ArrayList<ReactionParticipant>();
    ReactionParticipant[] rp = rs.getReactionParticipants();
    // should use this one to compare functional equavalent since this duplicatedExp has all params substituted.
    Expression duplicatedExp = substituteParameters(orgExp, false);
    // separate the reactants and products, fluxes, catalysts
    String rxnName = rs.getName();
    // reaction with membrane current can not be transformed to mass action
    if (rs.getPhysicsOptions() == ReactionStep.PHYSICS_MOLECULAR_AND_ELECTRICAL || rs.getPhysicsOptions() == ReactionStep.PHYSICS_ELECTRICAL_ONLY) {
        throw new ModelException("Kinetics of reaction " + rxnName + " has membrane current. It can not be automatically transformed to Mass Action kinetics.");
    }
    for (int i = 0; i < rp.length; i++) {
        if (rp[i] instanceof Reactant) {
            reactants.add(rp[i]);
        } else if (rp[i] instanceof Product) {
            products.add(rp[i]);
        } else if (rp[i] instanceof Catalyst) {
            String catalystName = rp[i].getSpeciesContext().getName();
            // only if duplictedExp is not a non-linear function of catalystName.
            if (duplicatedExp.hasSymbol(catalystName)) {
                // Only when catalyst appears in ReactionRate, we add catalyst to both reactant and product
                // the stoichiometry should be set to 1.
                ReactionParticipant catalystRP = new ReactionParticipant(null, rs, rp[i].getSpeciesContext(), 1) {

                    public boolean compareEqual(Matchable obj) {
                        ReactionParticipant rp = (ReactionParticipant) obj;
                        if (rp == null) {
                            return false;
                        }
                        if (!Compare.isEqual(getSpecies(), rp.getSpecies())) {
                            return false;
                        }
                        if (!Compare.isEqual(getStructure(), rp.getStructure())) {
                            return false;
                        }
                        if (getStoichiometry() != rp.getStoichiometry()) {
                            return false;
                        }
                        return true;
                    }

                    @Override
                    public void writeTokens(PrintWriter pw) {
                    }

                    @Override
                    public void fromTokens(CommentStringTokenizer tokens, Model model) throws Exception {
                    }
                };
                products.add(catalystRP);
                reactants.add(catalystRP);
            }
        }
    }
    /**
     * The code below is going to solve reaction with kinetics that are NOT Massaction. Or Massaction with catalysts involved.
     */
    // 
    // 2x2 rational matrix
    // 
    // lets define
    // J() is the substituted total rate expression
    // P() as the theoretical "product" term with Kf = 1
    // R() as the theoretical "reactant" term with Kr = 1
    // 
    // Kf * R([1 1 1])  - Kr * P([1 1 1])  = J([1 1 1])
    // Kf * R([2 3 4])  - Kr * P([2 3 4])  = J([2 3 4])
    // 
    // in matrix form,
    // 
    // |                                        |
    // | R([1 1 1])   -P([1 1 1])    J([1 1 1]) |
    // | R([2 3 4])   -P([2 3 4])    J([2 3 4]) |
    // |                                        |
    // 
    // 
    // example: Kf*A*B^2*C - Kr*C*A
    // J() = forwardRate*43/Kabc*A*B^2*C - (myC*5-2)*C*A
    // P() = C*A
    // R() = A*B^2*C
    // 
    // |                                              |
    // | R([1 1 1])  -P([1 1 1])    J([1 1 1])        |
    // | R([2 3 4])  -P([2 3 4])    J([2 3 4])        |
    // |                                              |
    // 
    // |                                                                              |
    // | R([1 1 1])*R([2 3 4])    -P([1 1 1])*R([2 3 4])     J([1 1 1])*R([2 3 4])    |
    // | R([2 3 4])*R([1 1 1])    -P([2 3 4])*R([1 1 1])     J([2 3 4])*R([1 1 1])    |
    // |                                                                              |
    // 
    // 
    // |                                                                                                                    |
    // | R([1 1 1])*R([2 3 4])  -P([1 1 1])*R([2 3 4])                         J([1 1 1])*R([2 3 4])                        |
    // | 0                      -P([2 3 4])*R([1 1 1])+P([1 1 1])*R([2 3 4])   J([2 3 4])*R([1 1 1])-J([1 1 1])*R([2 3 4])  |
    // |                                                                                                                    |
    // 
    // 
    // 
    // 
    Expression forwardExp = null;
    Expression reverseExp = null;
    Expression R_exp = new Expression(1);
    if (reactants.size() > 0) {
        R_exp = new Expression(1.0);
        for (ReactionParticipant reactant : reactants) {
            R_exp = Expression.mult(R_exp, Expression.power(new Expression(reactant.getName()), new Expression(reactant.getStoichiometry())));
        }
    }
    Expression P_exp = new Expression(1);
    if (products.size() > 0) {
        P_exp = new Expression(1.0);
        for (ReactionParticipant product : products) {
            P_exp = Expression.mult(P_exp, Expression.power(new Expression(product.getName()), new Expression(product.getStoichiometry())));
        }
    }
    HashSet<String> reactionParticipantNames = new HashSet<String>();
    for (ReactionParticipant reactionParticipant : rs.getReactionParticipants()) {
        reactionParticipantNames.add(reactionParticipant.getName());
    }
    Expression R_1 = new Expression(R_exp);
    Expression R_2 = new Expression(R_exp);
    Expression P_1 = new Expression(P_exp);
    Expression P_2 = new Expression(P_exp);
    Expression J_1 = new Expression(duplicatedExp);
    Expression J_2 = new Expression(duplicatedExp);
    int index = 0;
    for (String rpName : reactionParticipantNames) {
        R_1.substituteInPlace(new Expression(rpName), new Expression(1.0));
        R_2.substituteInPlace(new Expression(rpName), new Expression(primeIntNumbers[index]));
        P_1.substituteInPlace(new Expression(rpName), new Expression(1.0));
        P_2.substituteInPlace(new Expression(rpName), new Expression(primeIntNumbers[index]));
        J_1.substituteInPlace(new Expression(rpName), new Expression(1.0));
        J_2.substituteInPlace(new Expression(rpName), new Expression(primeIntNumbers[index]));
        index++;
    }
    R_1 = R_1.flatten();
    R_2 = R_2.flatten();
    P_1 = P_1.flatten();
    P_2 = P_2.flatten();
    J_1 = J_1.flatten();
    J_2 = J_2.flatten();
    // e.g. A+B <-> A+B, A+2B <-> A+2B
    if (ExpressionUtils.functionallyEquivalent(R_exp, P_exp, false, 1e-8, 1e-8)) {
        throw new ModelException(VCellErrorMessages.getMassActionSolverMessage(rs.getName(), "Identical reactants and products not supported for stochastic models."));
    }
    if (R_exp.compareEqual(new Expression(1)) && P_exp.compareEqual(new Expression(1))) {
        // no reactants, no products ... nothing to do
        forwardExp = null;
        reverseExp = null;
    } else {
        // both reactants and products
        RationalExpMatrix matrix = new RationalExpMatrix(2, 3);
        matrix.set_elem(0, 0, RationalExpUtils.getRationalExp(R_1, true));
        matrix.set_elem(0, 1, RationalExpUtils.getRationalExp(Expression.negate(P_1), true));
        matrix.set_elem(0, 2, RationalExpUtils.getRationalExp(J_1, true));
        matrix.set_elem(1, 0, RationalExpUtils.getRationalExp(R_2, true));
        matrix.set_elem(1, 1, RationalExpUtils.getRationalExp(Expression.negate(P_2), true));
        matrix.set_elem(1, 2, RationalExpUtils.getRationalExp(J_2, true));
        RationalExp[] solution;
        try {
            // matrix.show();
            solution = matrix.solveLinearExpressions();
            // solution[0] is forward rate.
            solution[0] = solution[0].simplify();
            // solution[1] is reverse rate.
            solution[1] = solution[1].simplify();
        } catch (MatrixException e) {
            e.printStackTrace();
            throw new ModelException(VCellErrorMessages.getMassActionSolverMessage(rs.getName(), "MatrixException: " + e.getMessage()));
        }
        forwardExp = new Expression(solution[0].infixString());
        reverseExp = new Expression(solution[1].infixString());
        // for massAction, if there is no reactant in the forward rate, the forwardExp should be set to null to avoid writing jump process for the forward reaction.
        if (R_exp.compareEqual(new Expression(1)) && rs.getKinetics().getKineticsDescription().equals(KineticsDescription.MassAction)) {
            forwardExp = null;
        }
        // for massAction, if there is no product in the reverse rate, the reverseExp should be set to null to avoid writing jump process for the reverse reaction.
        if (P_exp.compareEqual(new Expression(1)) && rs.getKinetics().getKineticsDescription().equals(KineticsDescription.MassAction)) {
            reverseExp = null;
        }
    }
    if (forwardExp != null) {
        forwardExp.bindExpression(rs);
    }
    if (reverseExp != null) {
        reverseExp.bindExpression(rs);
    }
    // Reconstruct the rate based on the extracted forward rate and reverse rate. If the reconstructed rate is not equivalent to the original rate,
    // it means the original rate is not in the form of Kf*r1^n1*r2^n2-Kr*p1^m1*p2^m2.
    Expression constructedExp = reconstructedRate(forwardExp, reverseExp, reactants, products, rs.getNameScope());
    Expression orgExp_withoutCatalyst = removeCatalystFromExp(duplicatedExp, rs);
    Expression constructedExp_withoutCatalyst = removeCatalystFromExp(constructedExp, rs);
    if (!ExpressionUtils.functionallyEquivalent(orgExp_withoutCatalyst, constructedExp_withoutCatalyst, false, 1e-8, 1e-8)) {
        throw new ModelException(VCellErrorMessages.getMassActionSolverMessage(rs.getName(), "Mathmatical form incompatible with mass action."));
    }
    // check if forward rate constant and reverse rate constant both can be evaluated to constants(numbers) after substituting all parameters.
    if (forwardExp != null) {
        Expression forwardExpCopy = new Expression(forwardExp);
        try {
            substituteParameters(forwardExpCopy, true).evaluateConstant();
        } catch (ExpressionException e) {
            throw new ModelException(VCellErrorMessages.getMassActionSolverMessage(rs.getName(), "Problem in forward rate '" + forwardExp.infix() + "', " + e.getMessage()));
        }
        // 
        if (optionalForwardRateParameter != null) {
            Expression forwardRateParameterCopy = new Expression(optionalForwardRateParameter, optionalForwardRateParameter.getNameScope());
            try {
                substituteParameters(forwardRateParameterCopy, true).evaluateConstant();
                if (forwardExpCopy.compareEqual(forwardRateParameterCopy)) {
                    forwardExp = new Expression(optionalForwardRateParameter, optionalForwardRateParameter.getNameScope());
                }
            } catch (ExpressionException e) {
                // not expecting a problem because forwardExpCopy didn't have a problem, but in any case it is ok to swallow this exception
                e.printStackTrace(System.out);
            }
        }
    }
    if (reverseExp != null) {
        Expression reverseExpCopy = new Expression(reverseExp);
        try {
            substituteParameters(reverseExpCopy, true).evaluateConstant();
        } catch (ExpressionException e) {
            throw new ModelException(VCellErrorMessages.getMassActionSolverMessage(rs.getName(), "Problem in reverse rate '" + reverseExp.infix() + "', " + e.getMessage()));
        }
        // 
        if (optionalReverseRateParameter != null) {
            Expression reverseRateParameterCopy = new Expression(optionalReverseRateParameter, optionalReverseRateParameter.getNameScope());
            try {
                substituteParameters(reverseRateParameterCopy, true).evaluateConstant();
                if (reverseExpCopy.compareEqual(reverseRateParameterCopy)) {
                    reverseExp = new Expression(optionalReverseRateParameter, optionalReverseRateParameter.getNameScope());
                }
            } catch (ExpressionException e) {
                // not expecting a problem because reverseExpCopy didn't have a problem, but in any case it is ok to swallow this exception
                e.printStackTrace(System.out);
            }
        }
    }
    maFunc.setForwardRate(forwardExp);
    maFunc.setReverseRate(reverseExp);
    maFunc.setReactants(reactants);
    maFunc.setProducts(products);
    return maFunc;
}
Also used : ArrayList(java.util.ArrayList) RationalExp(cbit.vcell.matrix.RationalExp) Matchable(org.vcell.util.Matchable) ExpressionException(cbit.vcell.parser.ExpressionException) MatrixException(cbit.vcell.matrix.MatrixException) Expression(cbit.vcell.parser.Expression) RationalExpMatrix(cbit.vcell.matrix.RationalExpMatrix) CommentStringTokenizer(org.vcell.util.CommentStringTokenizer) PrintWriter(java.io.PrintWriter) HashSet(java.util.HashSet)

Aggregations

RationalExp (cbit.vcell.matrix.RationalExp)16 Expression (cbit.vcell.parser.Expression)12 RationalExpMatrix (cbit.vcell.matrix.RationalExpMatrix)6 FastInvariant (cbit.vcell.math.FastInvariant)5 Variable (cbit.vcell.math.Variable)5 ExpressionException (cbit.vcell.parser.ExpressionException)5 MemVariable (cbit.vcell.math.MemVariable)4 ReservedVariable (cbit.vcell.math.ReservedVariable)4 VolVariable (cbit.vcell.math.VolVariable)4 MatrixException (cbit.vcell.matrix.MatrixException)4 FastRate (cbit.vcell.math.FastRate)3 MathException (cbit.vcell.math.MathException)3 RationalNumber (cbit.vcell.matrix.RationalNumber)3 MappingException (cbit.vcell.mapping.MappingException)2 StructureMapping (cbit.vcell.mapping.StructureMapping)2 PseudoConstant (cbit.vcell.math.PseudoConstant)2 Kinetics (cbit.vcell.model.Kinetics)2 KineticsParameter (cbit.vcell.model.Kinetics.KineticsParameter)2 LumpedKinetics (cbit.vcell.model.LumpedKinetics)2 Membrane (cbit.vcell.model.Membrane)2