private NonlinearEquationDescription CompileEquations(RootNode root) { List <RPNExpression> rpnEquations = new List <RPNExpression>(); List <Expression.Expression> equations = new List <Expression.Expression>(); foreach (var constant in root.constants) { Expression.Expression right = ExpressionSimplifier.Simplify(ConvertToExpression(constant.Right)); //ExpressionNode right = simplify(constant.Right); if (right is Float) { constants.Add(constant.Identifier, ((Float)right).Value); } else { constants.Add(constant.Identifier, float.NaN); compilerErrors.Add(new ErrorMessage("Определение константы " + constant.Identifier + " не является константным выражением")); } } foreach (var equation in root.equations) { SubtractionNode subtraction = new SubtractionNode { Left = equation.Left, Right = equation.Right, Line = equation.Line, Position = equation.Position }; Expression.Expression expression = ExpressionSimplifier.Simplify(ConvertToExpression(subtraction)); equations.Add(expression); } //initialValues aren't important foreach (var initialValue in root.initialValues) { if (variables.ContainsKey(initialValue.Identifier)) { Expression.Expression right = ExpressionSimplifier.Simplify(ConvertToExpression(initialValue.Right)); //Expression expression = ConvertToExpression(right) if (right is Float) { initialValues[variables[initialValue.Identifier]] = ((Float)right).Value; } else { //add error message compilerErrors.Add(new ErrorMessage("Определение начального приближения переменной" + initialValue.Identifier + " не является константным выражением")); } } else { //add error message compilerErrors.Add(new ErrorMessage("Определение начального приближения несуществующей переменной")); } } //check that number of variables = number of equations if (variableNames.Count != equations.Count) { compilerErrors.Add(new ErrorMessage($"Количество переменных не совпадает с количеством уравнений: {variableNames.Count} переменных, {equations.Count} уравнений")); } if (equations.Count == 0) { compilerErrors.Add(new ErrorMessage("Пустая система уравнений")); } if (compilerErrors.Count > 0) { throw new CompilerException(compilerErrors); //fall back; } Expression.Compiler expCompiler = new Expression.Compiler(variables); for (int i = 0; i < equations.Count; i++) { rpnEquations.Add(expCompiler.Compile(equations[i])); } RPNExpression [,] jacobiMatrix = new RPNExpression[equations.Count, equations.Count]; Expression.DifferentiationVisitor difVisitor = new Expression.DifferentiationVisitor(); int j = 0; foreach (var equation in equations) { int i = 0; foreach (var variable in variableNames) { //find derivative for variable Expression.Expression derivative = ExpressionSimplifier.Simplify(difVisitor.Differentiate(equation, variable)); //simplify derivative expression RPNExpression exp = expCompiler.Compile(derivative); jacobiMatrix[i, j] = exp; i++; } j++; } NonlinearEquationDescription ned = new NonlinearEquationDescription(initialValues.ToArray(), variableNames.ToArray(), rpnEquations, jacobiMatrix); return(ned); }
private Implicit.DAEIDescription CompileDAEImplicit(RootNode root) { List <Expression.Expression> equations = new List <Expression.Expression>(); constants["time"] = 1.0; constants["t0"] = 0.0; foreach (var constant in root.constants) { //Convert to expression Expression.Expression right = ExpressionSimplifier.Simplify(ConvertToExpression(constant.Right)); if (right is Float) { constants[constant.Identifier] = ((Float)right).Value; } else { constants.Add(constant.Identifier, float.NaN); compilerErrors.Add(new ErrorMessage("Определение константы " + constant.Identifier + " не является константным выражением")); } } foreach (var parameter in root.parameters) { //Convert to expression Expression.Expression right = ExpressionSimplifier.Simplify(ConvertToExpression(parameter.Right)); if (right is Float) { //parameters.Add(parameter.Identifier, ((Float)right).Value); parameters[parameter.Identifier] = ((Float)right).Value; } else { parameters.Add(parameter.Identifier, float.NaN); compilerErrors.Add(new ErrorMessage("Определение параметра " + parameter.Identifier + " не является константным выражением")); } } foreach (var equation in root.equations) { //Convert to expression SubtractionNode exp = new SubtractionNode { Left = equation.Left, Right = equation.Right, Line = equation.Line, Position = equation.Position }; Expression.Expression expression = ExpressionSimplifier.Simplify(ConvertToExpression(exp)); equations.Add(expression); } foreach (var initialValue in root.initialValues) { if (variables.ContainsKey(initialValue.Identifier)) { //Convert to expression Expression.Expression right = ExpressionSimplifier.Simplify(ConvertToExpression(initialValue.Right)); if (right is Float) { Variable var = variables[initialValue.Identifier]; var.InitialValue = ((Float)right).Value; var.Initialized = true; } else { //add error message compilerErrors.Add(new ErrorMessage("Определение начального условия переменной " + initialValue.Identifier + " не является константным выражением")); } } else { //add error message compilerErrors.Add(new ErrorMessage("Определение начального условия несуществующей переменной")); } } //!!!!!!!!!!!!!!!!!!!!!!!!! //check that number of variables = number of equations if (variables.Count != equations.Count) { compilerErrors.Add(new ErrorMessage("Количество переменных не совпадает с количеством уравнений")); } if (equations.Count == 0) { compilerErrors.Add(new ErrorMessage("Пустая система уравнений")); } foreach (var variable in variables) { if (variable.Value.Initialized == false) { variable.Value.InitialValue = 0.0; //compilerErrors.Add(new ErrorMessage("Не объявлены начальные условия для переменной " + variable.Key)); } } if (compilerErrors.Count > 0) { throw new CompilerException(compilerErrors); //fall back; } List <RPNExpression> equationsRPN = new List <RPNExpression>(); List <string> variableNames = new List <string>(); List <string> symbolNames = new List <string>(); List <double> initialValues = new List <double>(); Dictionary <string, int> symbolIndicies = new Dictionary <string, int>(); List <Variable> variableList = new List <Variable>(); foreach (var variable in variables) { variableList.Add(variable.Value); } variableList.Sort(delegate(Variable x, Variable y) { return(x.Name.CompareTo(y.Name)); }); //time variable symbolIndicies.Add("t", 0); symbolNames.Add("t"); //variables foreach (var variable in variableList) { variableNames.Add(variable.Name); symbolNames.Add(variable.Name); initialValues.Add(variable.InitialValue); symbolIndicies.Add(variable.Name, symbolIndicies.Count); } //derivatives foreach (var variable in variableList) { symbolNames.Add(variable.Name + "'"); symbolIndicies.Add(variable.Name + "'", symbolIndicies.Count); } string[] parameterNames = new string[parameters.Count]; double[] parameterValues = new double[parameters.Count]; { int i = 0; foreach (var parameter in parameters) { parameterNames[i] = parameter.Key; parameterValues[i] = parameter.Value; i++; } } foreach (var parameter in parameterNames) { symbolNames.Add(parameter); symbolIndicies.Add(parameter, symbolIndicies.Count); } Expression.Compiler expCompiler = new Expression.Compiler(symbolIndicies); for (int i = 0; i < equations.Count; i++) { equationsRPN.Add(expCompiler.Compile(equations[i])); } MathUtils.SparseMatrix <RPNExpression> dfdx = MathUtils.SparseMatrix <RPNExpression> .Build(equations.Count, equations.Count); MathUtils.SparseMatrix <RPNExpression> dfddx = MathUtils.SparseMatrix <RPNExpression> .Build(equations.Count, equations.Count); Expression.DifferentiationVisitor difVisitor = new Expression.DifferentiationVisitor(); for (int j = 0; j < equations.Count; j++) { for (int i = 0; i < equations.Count; i++) { Expression.Expression derivative = ExpressionSimplifier.Simplify(difVisitor.Differentiate(equations[i], variableNames[j])); if (derivative.Type == ExpressionType.Float) { if ((derivative as Expression.Float).IsZero()) { continue; } } RPNExpression exp = expCompiler.Compile(derivative); //dfdx[i, j] = exp; dfdx.Add(i, j, exp); } } for (int j = 0; j < equations.Count; j++) { for (int i = 0; i < equations.Count; i++) { Expression.Expression derivative = ExpressionSimplifier.Simplify(difVisitor.Differentiate(equations[i], variableNames[j] + "'")); if (derivative.Type == ExpressionType.Float) { if ((derivative as Expression.Float).IsZero()) { continue; } } RPNExpression exp = expCompiler.Compile(derivative); //dfddx[i, j] = exp; dfddx.Add(i, j, exp); } } Implicit.DAEIDescription definition = new Implicit.DAEIDescription(variableNames.ToArray(), parameterNames, parameterValues, initialValues.ToArray(), equationsRPN, dfdx, dfddx, constants["t0"], constants["time"]); return(definition); }