public bool Check(string sourceCode) { var status = parser.TryParseProgram(sourceCode, out var prog, out var internalerror, out var position); if (!status) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage(internalerror, SolverStatus.Error)); } else { if (prog.ClassDefinitions.Count == 1) { var translator = new ModelTranslatorV1(); var printer = new ModelicaTreePrinter(); var pretty = new ModelicaPrettyPrinter(); var instancePrinter = new InstancePrinter(); var flattening = new Flattening(); var astText = printer.Transform(prog); var prettyTest = pretty.Transform(prog); DAEProblem model = null; string prettyflat = ""; try { var flatModel = flattening.Transform(prog.ClassDefinitions.First()); prettyflat = instancePrinter.Transform(flatModel); //model = translator.Translate(flatModel); } catch (Exception e) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"{e.Message}", SolverStatus.Error)); return(false); } _eventAggregator.PublishOnUIThreadAsync(new UpdateModelAnalysisMessage() { SyntaxTree = astText, FlattenedModel = prettyflat, CalculationModel = model }); _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage("Model OK", SolverStatus.OK)); } else { throw new InvalidOperationException("Multiple class definitions detected. Flattening can only resolve one class."); } } return(status); }
public DAEProblem Translate(ClassDefinition model) { var problem = new DAEProblem(); problem.Name = model.ID; foreach (var element in model.Elements) { Handle(problem, element); } return(problem); }
static void LoktaVolterraHardoded() { var logger = new NoLogger(); var model = new DAEProblem(); var integrator = new ExplicitEuler(); integrator.StepSize = 0.1; integrator.EndTime = 200; var N1 = new Variable("N1", 5); var N2 = new Variable("N2", 10); var dN1 = new Variable("dN1dt", 0); var dN2 = new Variable("dN2dt", 0); var e1 = new Variable("e1", 0.09); var g1 = new Variable("g1", 0.01); var e2 = new Variable("e2", 0.04); var g2 = new Variable("g2", 0.01); var eq1 = new Equation(N1 * (e1 - g1 * N2) - dN1); var eq2 = new Equation(-N2 * (e2 - g2 * N1) - dN2); model.AlgebraicVariables.Add(N1); model.AlgebraicVariables.Add(N2); model.DifferentialVariables.Add(dN1); model.DifferentialVariables.Add(dN2); model.Equations.Add(eq1); model.Equations.Add(eq2); model.Mapping.Add(dN1, N1); model.Mapping.Add(dN2, N2); model.Initialize(new NoLogger()); var results = integrator.Integrate(model, logger); using (var sw = new StreamWriter(Environment.CurrentDirectory + "\\results.csv")) { sw.WriteLine("time;" + string.Join("; ", model.AlgebraicVariables.Select(v => v.Name))); foreach (var result in results) { sw.WriteLine(result.ToString()); } } }
public DAEProblem Translate(Instance model) { var problem = new DAEProblem(); problem.Name = model.ID; problem.Parameters.Add(new Variable("pi", Math.PI)); foreach (var element in model.Parts) { Handle(problem, element); } foreach (var element in model.Equations) { Handle(problem, element); } return(problem); }
void Handle(DAEProblem problem, object value) { switch (value) { case Instance i: { var vari = new Variable(i.ID, 0.0); var compClause = i.Source as ComponentClause; bool isParameter = false; if (compClause != null) { if (compClause.Variability == VariabilityPrefix.Parameter) { isParameter = true; } } if (i.Value != null) { //problem.Equations.Add(new Equation(vari - i.Value.Evaluate())); vari.SetValue(i.Value.Evaluate()); isParameter = true; } var initial = i.Parts.FirstOrDefault(p => p.ID == "start"); if (initial != null && initial.Value != null) { vari.SetValue(initial.Value.Evaluate()); } if (isParameter) { problem.Parameters.Add(vari); } else { problem.AlgebraicVariables.Add(vari); } } break; case ComponentClause c: foreach (var decl in c.Declarations) { decl.Clause = c; Handle(problem, decl); } break; case ComponentDeclaration e: { var vari = new Variable(e.ID, 0.0); if (e.Modification != null) { foreach (var mod in e.Modification.Modifications) { if (mod.Reference.ToString().ToLower() == "start") { vari.SetValue(mod.Modification.Value.Evaluate()); } } } if (e.Modification != null && e.Modification.Value != null) { vari.SetValue(e.Modification.Value.Evaluate()); e.Clause.Variability = VariabilityPrefix.Parameter; } if (e.Clause.Variability == VariabilityPrefix.Parameter) { problem.Parameters.Add(vari); } else { problem.AlgebraicVariables.Add(vari); } } break; case EquationSection e: foreach (var eq in e.Equations) { Handle(problem, eq); } break; case SimpleEquation e: var left = HandleExpression(problem, e.Left); var right = HandleExpression(problem, e.Right); var residual = right - left; problem.Equations.Add(new Equation(residual)); break; } }
Expression HandleExpression(DAEProblem problem, ModelicaExpression expr) { switch (expr) { case BinaryExpression b: { switch (b.Operator) { case BinaryOperator.Add: return(HandleExpression(problem, b.Left) + HandleExpression(problem, b.Right)); case BinaryOperator.Subtract: return(HandleExpression(problem, b.Left) - HandleExpression(problem, b.Right)); case BinaryOperator.Multiply: return(HandleExpression(problem, b.Left) * HandleExpression(problem, b.Right)); case BinaryOperator.Divide: return(HandleExpression(problem, b.Left) / HandleExpression(problem, b.Right)); case BinaryOperator.Power: return(Sym.Pow(HandleExpression(problem, b.Left), HandleExpression(problem, b.Right))); } } break; case UnaryExpression u: { switch (u.Operator) { case UnaryOperator.Negate: return(-HandleExpression(problem, u.Child)); case UnaryOperator.Parentheses: return(Sym.Par(HandleExpression(problem, u.Child))); case UnaryOperator.TimeDerivative: var y = HandleExpression(problem, u.Child) as Variable; if (y == null) { throw new InvalidOperationException("Cannot handle expressions inside der operator yet."); } var dery = new Variable("der(" + y.Name + ")", 0); var existingVar = problem.DifferentialVariables.FirstOrDefault(v => v.Name == dery.Name); if (existingVar == null) { problem.DifferentialVariables.Add(dery); problem.Mapping.Add(dery, y); return(dery); } else { return(existingVar); } default: throw new InvalidOperationException("Unknown unary operator " + u.Operator.ToString()); } } case BuiltinFunction u: { switch (u.Type) { case BuiltinFunctionType.Sin: return(Sym.Sin(HandleExpression(problem, u.Child))); case BuiltinFunctionType.Cos: return(Sym.Cos(HandleExpression(problem, u.Child))); case BuiltinFunctionType.Tan: return(Sym.Tan(HandleExpression(problem, u.Child))); case BuiltinFunctionType.Log: return(Sym.Ln(HandleExpression(problem, u.Child))); case BuiltinFunctionType.Exp: return(Sym.Exp(HandleExpression(problem, u.Child))); case BuiltinFunctionType.Sqrt: return(Sym.Sqrt(HandleExpression(problem, u.Child))); default: throw new InvalidOperationException("Unknown built-in fucntion " + u.Type.ToString()); } } case DoubleLiteral l: return(new Variable(l.Value.ToString(), l.Value)); case Reference r: { var vari = problem.ResolveReference(r.ToString()); if (vari != null) { return(vari); } else { throw new NullReferenceException("Variable " + r.ToString() + " not defined."); } } default: throw new InvalidOperationException("Unknown expression " + expr.ToString()); } return(null); }
public bool Simulate(string sourceCode) { var status = parser.TryParseProgram(sourceCode, out var prog, out var error, out var position); if (status) { var translator = new ModelTranslatorV1(); var flattening = new Flattening(); var ast = prog.ClassDefinitions.Last(); var instance = flattening.Transform(ast); DAEProblem model = null; try { model = translator.Translate(instance); } catch (Exception e) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"{e.Message}", SolverStatus.Error)); } var integrator = createIntegratorFromAnnotation(ast); integrator.StepSize = 0.1; integrator.EndTime = 1; integrator.OnIteration += (i) => OnIteration(integrator, i); updateIntegratorSettings(ast, integrator); var logger = new NoLogger(); try { integrator.Discretize(model); model.Initialize(logger); } catch (Exception e) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"{e.Message}", SolverStatus.Error)); return(false); } if (model.SystemToSolve.NumberOfEquations != model.SystemToSolve.NumberOfVariables) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"System not square! V={model.SystemToSolve.NumberOfVariables}, E={model.SystemToSolve.NumberOfEquations}", SolverStatus.Error)); return(false); } Stopwatch w = new Stopwatch(); _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage("Integration started", SolverStatus.Busy)); try { w.Start(); var results = integrator.Integrate(model, logger); w.Stop(); Console.WriteLine("Integration took " + w.ElapsedMilliseconds + "ms"); _eventAggregator.PublishOnUIThreadAsync(new UpdateModelResultMessage() { ModelName = model.Name, AlgebraicStates = model.AlgebraicVariables, DifferentialStates = model.DifferentialVariables, TimeSteps = results }); _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"Integration finished ({w.ElapsedMilliseconds} ms)", SolverStatus.OK)); } catch (Exception e) { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage($"{e.Message}", SolverStatus.Error)); return(false); } } else { _eventAggregator.PublishOnUIThreadAsync(new UpdateSolverStatusMessage(error, SolverStatus.Error)); } return(true); }